moving website to fastapi as well
|
|
@ -9,3 +9,4 @@ spectre/
|
||||||
velconnect_backup.sql
|
velconnect_backup.sql
|
||||||
discord_bot/graph.png
|
discord_bot/graph.png
|
||||||
discord_bot/config.py
|
discord_bot/config.py
|
||||||
|
env_win/
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
export FLASK_APP="velconnect"
|
|
||||||
export FLASK_ENV=development
|
|
||||||
source env/bin/activate
|
|
||||||
flask run
|
|
||||||
|
|
@ -1,210 +0,0 @@
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png">
|
|
||||||
<link rel="manifest" href="/favicons/site.webmanifest">
|
|
||||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#5bbad5">
|
|
||||||
<meta name="msapplication-TileColor" content="#b91d47">
|
|
||||||
<meta name="theme-color" content="#ffffff">
|
|
||||||
|
|
||||||
<title>VEL Connect</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="/css/spectre.min.css">
|
|
||||||
<script src="/js/util.js"></script>
|
|
||||||
<style>
|
|
||||||
.container {
|
|
||||||
max-width: 30em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
margin: 1em;
|
|
||||||
box-shadow: 0 0 2em #0003;
|
|
||||||
}
|
|
||||||
|
|
||||||
input.btn {
|
|
||||||
cursor: auto;
|
|
||||||
user-select: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.centered {
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
|
|
||||||
<div id="loading" class="loading loading-lg"></div>
|
|
||||||
<div id="failure" style="display: none;">☹️</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="headset_details" style="display: none;">
|
|
||||||
<div class="panel card">
|
|
||||||
<div class="panel-header text-center">
|
|
||||||
<figure class="avatar avatar-lg"><img src="/favicons/android-chrome-192x192.png"
|
|
||||||
alt="Avatar"></figure>
|
|
||||||
<div class="panel-title h5 mt-10">Headset Info</div>
|
|
||||||
<div class="panel-subtitle hw_id">---</div>
|
|
||||||
</div>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="tile tile-centered">
|
|
||||||
<div class="tile-content">
|
|
||||||
<div class="tile-title text-bold">Current Room</div>
|
|
||||||
<input class="btn current_room" type="text" id="current_room" placeholder="----">
|
|
||||||
</div>
|
|
||||||
<div class="tile-action">
|
|
||||||
<button class="btn btn-primary btn-lg tooltip tooltip-left" id="set_room_id"
|
|
||||||
data-tooltip="Set Room ID">Set</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div class="tile tile-centered">
|
|
||||||
<div class="tile-content">
|
|
||||||
<div class="tile-title text-bold">First Added</div>
|
|
||||||
<div class="tile-subtitle date_created">---</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div class="tile tile-centered">
|
|
||||||
<div class="tile-content">
|
|
||||||
<div class="tile-title text-bold">Last Used</div>
|
|
||||||
<div class="tile-subtitle last_used">---</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div class="tile tile-centered">
|
|
||||||
<div class="tile-content">
|
|
||||||
<div class="tile-title text-bold">User Name</div>
|
|
||||||
<input class="btn user_name" type="text" id="user_name" placeholder="----">
|
|
||||||
</div>
|
|
||||||
<div class="tile-action">
|
|
||||||
<button class="btn btn-primary btn-lg tooltip tooltip-left" id="set_user_name"
|
|
||||||
data-tooltip="">Set</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div class="tile tile-centered">
|
|
||||||
<div class="tile-content">
|
|
||||||
<div class="tile-title text-bold">TV URL</div>
|
|
||||||
<input class="btn tv_url" type="text" id="tv_url" placeholder="----">
|
|
||||||
</div>
|
|
||||||
<div class="tile-action">
|
|
||||||
<button class="btn btn-primary btn-lg tooltip tooltip-left" id="set_tv_url"
|
|
||||||
data-tooltip="">Set</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div class="tile tile-centered">
|
|
||||||
<div class="tile-content">
|
|
||||||
<div class="tile-title text-bold">User Color</div>
|
|
||||||
<input class="btn user_color" type="color" id="user_color" placeholder="#ffffff">
|
|
||||||
</div>
|
|
||||||
<div class="tile-action">
|
|
||||||
<button class="btn btn-primary btn-lg tooltip tooltip-left" id="set_user_color"
|
|
||||||
data-tooltip="Set User Color">Set</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<div class="tile tile-centered">
|
|
||||||
<div class="tile-content">
|
|
||||||
<div class="tile-title text-bold">Carpet Color</div>
|
|
||||||
<input class="btn carpet_color" type="color" id="carpet_color" placeholder="#ffffff">
|
|
||||||
</div>
|
|
||||||
<div class="tile-action">
|
|
||||||
<button class="btn btn-primary btn-lg tooltip tooltip-left" id="set_carpet_color"
|
|
||||||
data-tooltip="Set Carpet Color">Set</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
let submit_button = document.getElementById('submit_pairing_code');
|
|
||||||
let pair_code_input = document.getElementById('pair_code');
|
|
||||||
let loading = document.getElementById('loading');
|
|
||||||
let enter_pairing_id = document.getElementById('enter_pairing_id');
|
|
||||||
let headset_details = document.getElementById('headset_details');
|
|
||||||
let hw_id_field = document.getElementById('hw_id');
|
|
||||||
let failure = document.getElementById('failure');
|
|
||||||
let set_room_id = document.getElementById('set_room_id');
|
|
||||||
let current_room = document.getElementById('current_room');
|
|
||||||
|
|
||||||
|
|
||||||
// check cookie
|
|
||||||
let hw_id = getCookie('hw_id');
|
|
||||||
loading.style.display = "none";
|
|
||||||
if (hw_id != "") {
|
|
||||||
|
|
||||||
httpGetAsync('https://connect.vel.workers.dev/api/get_state/' + hw_id, (resp) => {
|
|
||||||
console.log(resp);
|
|
||||||
let respData = JSON.parse(resp);
|
|
||||||
|
|
||||||
writeClass('hw_id', respData['user']['hw_id']);
|
|
||||||
writeValue('current_room', respData['user']['current_room']);
|
|
||||||
writeClass('date_created', respData['user']['date_created']);
|
|
||||||
writeClass('last_used', respData['user']['last_used']);
|
|
||||||
writeValue('user_color', respData['user']['user_color']);
|
|
||||||
writeValue('user_name', respData['user']['user_name']);
|
|
||||||
if (respData['room']) {
|
|
||||||
writeValue('tv_url', respData['room']['tv_url']);
|
|
||||||
writeValue('carpet_color', respData['room']['carpet_color']);
|
|
||||||
}
|
|
||||||
|
|
||||||
headset_details.style.display = "block";
|
|
||||||
}, (status) => {
|
|
||||||
failure.style.display = "block";
|
|
||||||
});
|
|
||||||
|
|
||||||
function setUserData(endpoint, data) {
|
|
||||||
httpPostAsync('https://connect.vel.workers.dev/api/set_headset_details/' + hw_id + '/' + endpoint,
|
|
||||||
data,
|
|
||||||
(resp) => {console.log('success');},
|
|
||||||
(status) => {console.log('fail');}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
function setRoomData(endpoint, data) {
|
|
||||||
httpPostAsync('https://connect.vel.workers.dev/api/set_room_details/' + current_room.value + '/' + endpoint,
|
|
||||||
data,
|
|
||||||
(resp) => {console.log('success');},
|
|
||||||
(status) => {console.log('fail');}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
set_room_id.addEventListener('click', () => {
|
|
||||||
setUserData('current_room', {"current_room": current_room.value});
|
|
||||||
});
|
|
||||||
document.getElementById('set_user_color').addEventListener('click', () => {
|
|
||||||
setUserData('user_color', {"user_color": document.getElementById('user_color').value});
|
|
||||||
});
|
|
||||||
document.getElementById('set_user_name').addEventListener('click', () => {
|
|
||||||
setUserData('user_name', {"user_name": document.getElementById('user_name').value});
|
|
||||||
});
|
|
||||||
document.getElementById('set_tv_url').addEventListener('click', () => {
|
|
||||||
setRoomData('tv_url', {"tv_url": document.getElementById('tv_url').value});
|
|
||||||
});
|
|
||||||
document.getElementById('set_carpet_color').addEventListener('click', () => {
|
|
||||||
setRoomData('carpet_color', {"carpet_color": document.getElementById('carpet_color').value});
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
window.location.href = "/pair";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
|
|
@ -34,6 +34,8 @@ CREATE TABLE `Headset` (
|
||||||
`avatar_url` VARCHAR(128),
|
`avatar_url` VARCHAR(128),
|
||||||
-- Stuff like player color, nickname, whiteboard state
|
-- Stuff like player color, nickname, whiteboard state
|
||||||
`user_details` JSON,
|
`user_details` JSON,
|
||||||
|
`streamer_stream_id` VARCHAR(64),
|
||||||
|
`streamer_control_id` VARCHAR(64),
|
||||||
CHECK (JSON_VALID(`user_details`))
|
CHECK (JSON_VALID(`user_details`))
|
||||||
);
|
);
|
||||||
DROP TABLE IF EXISTS `APIKey`;
|
DROP TABLE IF EXISTS `APIKey`;
|
||||||
|
|
@ -8,6 +8,8 @@ from fastapi.security import OAuth2PasswordBearer
|
||||||
from db import query, insert
|
from db import query, insert
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
from pyppeteer import launch
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
# APIRouter creates path operations for user module
|
# APIRouter creates path operations for user module
|
||||||
|
|
@ -219,3 +221,43 @@ def get_user_count(hours: float = 24):
|
||||||
WHERE TIMESTAMP > DATE_SUB(NOW(), INTERVAL """ + str(hours) + """ HOUR);
|
WHERE TIMESTAMP > DATE_SUB(NOW(), INTERVAL """ + str(hours) + """ HOUR);
|
||||||
""")
|
""")
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
|
||||||
|
class QuestRift(str, Enum):
|
||||||
|
quest = "quest"
|
||||||
|
rift = "rift"
|
||||||
|
|
||||||
|
|
||||||
|
@router.get('/get_store_details/{quest_rift}/{app_id}', tags=["Oculus API"])
|
||||||
|
async def get_version_nums(quest_rift: QuestRift, app_id: int):
|
||||||
|
browser = await launch(headless=True, options={'args': ['--no-sandbox']})
|
||||||
|
page = await browser.newPage()
|
||||||
|
await page.goto(f'https://www.oculus.com/experiences/{quest_rift}/{app_id}')
|
||||||
|
|
||||||
|
ret = {}
|
||||||
|
|
||||||
|
# title
|
||||||
|
title = await page.querySelector(".app-description__title")
|
||||||
|
ret["title"] = await page.evaluate("e => e.textContent", title)
|
||||||
|
|
||||||
|
# description
|
||||||
|
desc = await page.querySelector(".clamped-description__content")
|
||||||
|
ret["description"] = await page.evaluate("e => e.textContent", desc)
|
||||||
|
|
||||||
|
# versions
|
||||||
|
await page.evaluate("document.querySelector('.app-details-version-info-row__version').nextElementSibling.firstChild.click();")
|
||||||
|
elements = await page.querySelectorAll('.sky-dropdown__link.link.link--clickable')
|
||||||
|
|
||||||
|
versions = []
|
||||||
|
for e in elements:
|
||||||
|
v = await page.evaluate('(element) => element.textContent', e)
|
||||||
|
versions.append({
|
||||||
|
'channel': v.split(':')[0],
|
||||||
|
'version': v.split(':')[1]
|
||||||
|
})
|
||||||
|
|
||||||
|
ret["versions"] = versions
|
||||||
|
|
||||||
|
await browser.close()
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ import uvicorn
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from api import router as api_router
|
from api import router as api_router
|
||||||
|
from website import router as website_router
|
||||||
|
from fastapi.staticfiles import StaticFiles
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
@ -21,7 +23,10 @@ app.add_middleware(
|
||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||||
|
|
||||||
app.include_router(api_router)
|
app.include_router(api_router)
|
||||||
|
app.include_router(website_router)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
uvicorn.run("main:app", host='127.0.0.1', port=8005,
|
uvicorn.run("main:app", host='127.0.0.1', port=8005,
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,5 @@ fastapi
|
||||||
autopep8
|
autopep8
|
||||||
uvicorn
|
uvicorn
|
||||||
pymysql
|
pymysql
|
||||||
|
pyppeteer
|
||||||
|
jinja2
|
||||||
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 815 B After Width: | Height: | Size: 815 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 977 B After Width: | Height: | Size: 977 B |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
|
@ -96,3 +96,60 @@ function writeSrc(className, data) {
|
||||||
e.src = data;
|
e.src = data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function timeSince(date) {
|
||||||
|
|
||||||
|
let seconds = Math.floor((new Date() - date) / 1000);
|
||||||
|
|
||||||
|
let interval = seconds / 31536000;
|
||||||
|
|
||||||
|
if (interval > 1) {
|
||||||
|
return Math.floor(interval) + " years";
|
||||||
|
}
|
||||||
|
interval = seconds / 2592000;
|
||||||
|
if (interval > 1) {
|
||||||
|
return Math.floor(interval) + " months";
|
||||||
|
}
|
||||||
|
interval = seconds / 86400;
|
||||||
|
if (interval > 1) {
|
||||||
|
return Math.floor(interval) + " days";
|
||||||
|
}
|
||||||
|
interval = seconds / 3600;
|
||||||
|
if (interval > 1) {
|
||||||
|
return Math.floor(interval) + " hours";
|
||||||
|
}
|
||||||
|
interval = seconds / 60;
|
||||||
|
if (interval > 1) {
|
||||||
|
return Math.floor(interval) + " minutes";
|
||||||
|
}
|
||||||
|
return Math.floor(seconds) + " seconds";
|
||||||
|
}
|
||||||
|
|
||||||
|
function timeSinceString(date) {
|
||||||
|
|
||||||
|
date = Date.parse(date);
|
||||||
|
let seconds = Math.floor((new Date() - date) / 1000);
|
||||||
|
|
||||||
|
let interval = seconds / 31536000;
|
||||||
|
|
||||||
|
if (interval > 1) {
|
||||||
|
return Math.floor(interval) + " years";
|
||||||
|
}
|
||||||
|
interval = seconds / 2592000;
|
||||||
|
if (interval > 1) {
|
||||||
|
return Math.floor(interval) + " months";
|
||||||
|
}
|
||||||
|
interval = seconds / 86400;
|
||||||
|
if (interval > 1) {
|
||||||
|
return Math.floor(interval) + " days";
|
||||||
|
}
|
||||||
|
interval = seconds / 3600;
|
||||||
|
if (interval > 1) {
|
||||||
|
return Math.floor(interval) + " hours";
|
||||||
|
}
|
||||||
|
interval = seconds / 60;
|
||||||
|
if (interval > 1) {
|
||||||
|
return Math.floor(interval) + " minutes";
|
||||||
|
}
|
||||||
|
return Math.floor(seconds) + " seconds";
|
||||||
|
}
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
|
|
||||||
<div slot="nav-logo" style="display: flex; align-items: center; justify-content: center;">
|
<div slot="nav-logo" style="display: flex; align-items: center; justify-content: center;">
|
||||||
<img src = "/favicons/android-chrome-256x256.png" style="width:10em; margin: auto;" />
|
<img src = "/static/favicons/android-chrome-256x256.png" style="width:10em; margin: auto;" />
|
||||||
</div>
|
</div>
|
||||||
</rapi-doc>
|
</rapi-doc>
|
||||||
</body>
|
</body>
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="/static/favicons/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicons/favicon-32x32.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicons/favicon-16x16.png">
|
||||||
<link rel="manifest" href="/favicons/site.webmanifest">
|
<link rel="manifest" href="/static/favicons/site.webmanifest">
|
||||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#5bbad5">
|
<link rel="mask-icon" href="/static/favicons/safari-pinned-tab.svg" color="#5bbad5">
|
||||||
<meta name="msapplication-TileColor" content="#b91d47">
|
<meta name="msapplication-TileColor" content="#b91d47">
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
|
|
@ -0,0 +1,225 @@
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/static/favicons/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicons/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicons/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="/static/favicons/site.webmanifest">
|
||||||
|
<link rel="mask-icon" href="/static/favicons/safari-pinned-tab.svg" color="#5bbad5">
|
||||||
|
<meta name="msapplication-TileColor" content="#b91d47">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
|
<title>VEL Connect</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/static/css/spectre.min.css">
|
||||||
|
<script src="/static/js/util.js"></script>
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
max-width: 30em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
margin: 1em;
|
||||||
|
box-shadow: 0 0 2em #0003;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.btn {
|
||||||
|
cursor: auto;
|
||||||
|
user-select: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centered {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div id="loading"><br><br><div class="loading loading-lg"></div></div>
|
||||||
|
<div id="failure" style="display: none;"><br><br><br>☹️</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="headset_details" style="display: none;">
|
||||||
|
<div class="panel card">
|
||||||
|
<div class="panel-header text-center">
|
||||||
|
<figure class="avatar avatar-lg"><img src="/static/favicons/android-chrome-192x192.png" alt="Avatar"></figure>
|
||||||
|
<div class="panel-title h5 mt-10">Headset Info</div>
|
||||||
|
<div class="panel-subtitle hw_id">---</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="tile tile-centered">
|
||||||
|
<div class="tile-content">
|
||||||
|
<div class="tile-title text-bold">Current Room</div>
|
||||||
|
<input class="btn current_room" type="text" id="current_room" placeholder="----">
|
||||||
|
</div>
|
||||||
|
<div class="tile-action">
|
||||||
|
<button class="btn btn-primary btn-lg tooltip tooltip-left" id="set_room_id"
|
||||||
|
data-tooltip="Set Room ID">Set</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="tile tile-centered">
|
||||||
|
<div class="tile-content">
|
||||||
|
<div class="tile-title text-bold">First Seen</div>
|
||||||
|
<div class="tile-subtitle date_created">---</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="tile tile-centered">
|
||||||
|
<div class="tile-content">
|
||||||
|
<div class="tile-title text-bold">Last Login</div>
|
||||||
|
<div class="tile-subtitle last_used">---</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="tile tile-centered">
|
||||||
|
<div class="tile-content">
|
||||||
|
<div class="tile-title text-bold">User Name</div>
|
||||||
|
<input class="btn user_name" type="text" id="user_name" placeholder="----">
|
||||||
|
<button class="btn btn-primary btn-lg tooltip tooltip-left" id="set_user_name" data-tooltip="">Set</button>
|
||||||
|
</div>
|
||||||
|
<div class="tile-action">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="tile tile-centered">
|
||||||
|
<div class="tile-content">
|
||||||
|
<div class="tile-title text-bold">TV URL</div>
|
||||||
|
<input class="btn tv_url" type="text" id="tv_url" placeholder="----">
|
||||||
|
<button class="btn btn-primary btn-lg tooltip tooltip-left" id="set_tv_url" data-tooltip="">Set</button>
|
||||||
|
</div>
|
||||||
|
<div class="tile-action">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="tile tile-centered">
|
||||||
|
<div class="tile-content">
|
||||||
|
<div class="tile-title text-bold">User Color</div>
|
||||||
|
<input class="btn user_color coloris" type="text" id="user_color" placeholder="#ffffff">
|
||||||
|
<button class="btn btn-primary btn-lg tooltip tooltip-left" id="set_user_color" data-tooltip="Set User Color">Set</button>
|
||||||
|
</div>
|
||||||
|
<div class="tile-action">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div class="tile tile-centered">
|
||||||
|
<div class="tile-content">
|
||||||
|
<div class="tile-title text-bold">Carpet Color</div>
|
||||||
|
<input class="btn carpet_color coloris" type="text" id="carpet_color" placeholder="#ffffff">
|
||||||
|
<button class="btn btn-primary btn-lg tooltip tooltip-left" id="set_carpet_color" data-tooltip="Set Carpet Color">Set</button>
|
||||||
|
</div>
|
||||||
|
<div class="tile-action">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/static/js/coloris.min.js"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
let submit_button = document.getElementById('submit_pairing_code');
|
||||||
|
let pair_code_input = document.getElementById('pair_code');
|
||||||
|
let loading = document.getElementById('loading');
|
||||||
|
let enter_pairing_id = document.getElementById('enter_pairing_id');
|
||||||
|
let headset_details = document.getElementById('headset_details');
|
||||||
|
let hw_id_field = document.getElementById('hw_id');
|
||||||
|
let failure = document.getElementById('failure');
|
||||||
|
let set_room_id = document.getElementById('set_room_id');
|
||||||
|
let current_room = document.getElementById('current_room');
|
||||||
|
|
||||||
|
|
||||||
|
// check cookie
|
||||||
|
let hw_id = getCookie('hw_id');
|
||||||
|
if (hw_id != "") {
|
||||||
|
|
||||||
|
httpGetAsync('/api/get_state/' + hw_id, (resp) => {
|
||||||
|
console.log(resp);
|
||||||
|
let respData = JSON.parse(resp);
|
||||||
|
|
||||||
|
writeClass('hw_id', respData['user']['hw_id']);
|
||||||
|
writeValue('current_room', respData['user']['current_room']);
|
||||||
|
writeClass('date_created', respData['user']['date_created'] + "<br>" + timeSinceString(respData['user']['date_created']) + " ago");
|
||||||
|
writeClass('last_used', respData['user']['last_used'] + "<br>" + timeSinceString(respData['user']['last_used']) + " ago");
|
||||||
|
writeValue('user_color', respData['user']['user_color']);
|
||||||
|
writeValue('user_name', respData['user']['user_name']);
|
||||||
|
if (respData['room']) {
|
||||||
|
writeValue('tv_url', respData['room']['tv_url']);
|
||||||
|
writeValue('carpet_color', respData['room']['carpet_color']);
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.style.display = "none";
|
||||||
|
headset_details.style.display = "block";
|
||||||
|
}, (status) => {
|
||||||
|
loading.style.display = "none";
|
||||||
|
failure.style.display = "block";
|
||||||
|
});
|
||||||
|
|
||||||
|
function setUserData(endpoint, data) {
|
||||||
|
httpPostAsync('/api/set_headset_details/' + hw_id + '/' + endpoint,
|
||||||
|
data,
|
||||||
|
(resp) => { console.log('success'); },
|
||||||
|
(status) => { console.log('fail'); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function setRoomData(endpoint, data) {
|
||||||
|
httpPostAsync('/api/set_room_details/' + current_room.value + '/' + endpoint,
|
||||||
|
data,
|
||||||
|
(resp) => { console.log('success'); },
|
||||||
|
(status) => { console.log('fail'); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_room_id.addEventListener('click', () => {
|
||||||
|
setUserData('current_room', { "current_room": current_room.value });
|
||||||
|
});
|
||||||
|
document.getElementById('set_user_color').addEventListener('click', () => {
|
||||||
|
setUserData('user_color', { "user_color": document.getElementById('user_color').value });
|
||||||
|
});
|
||||||
|
document.getElementById('set_user_name').addEventListener('click', () => {
|
||||||
|
setUserData('user_name', { "user_name": document.getElementById('user_name').value });
|
||||||
|
});
|
||||||
|
document.getElementById('set_tv_url').addEventListener('click', () => {
|
||||||
|
setRoomData('tv_url', { "tv_url": document.getElementById('tv_url').value });
|
||||||
|
});
|
||||||
|
document.getElementById('set_carpet_color').addEventListener('click', () => {
|
||||||
|
setRoomData('carpet_color', { "carpet_color": document.getElementById('carpet_color').value });
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
window.location.href = "/pair";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Coloris({
|
||||||
|
el: '.coloris',
|
||||||
|
swatches: [
|
||||||
|
'#264653',
|
||||||
|
'#2a9d8f',
|
||||||
|
'#e9c46a',
|
||||||
|
'#f4a261',
|
||||||
|
'#e76f51',
|
||||||
|
'#d62828',
|
||||||
|
'#023e8a',
|
||||||
|
'#0077b6',
|
||||||
|
'#0096c7',
|
||||||
|
'#00b4d8',
|
||||||
|
'#48cae4',
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
@ -2,19 +2,19 @@
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="/static/favicons/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicons/favicon-32x32.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicons/favicon-16x16.png">
|
||||||
<link rel="manifest" href="/favicons/site.webmanifest">
|
<link rel="manifest" href="/static/favicons/site.webmanifest">
|
||||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#5bbad5">
|
<link rel="mask-icon" href="/static/favicons/safari-pinned-tab.svg" color="#5bbad5">
|
||||||
<meta name="msapplication-TileColor" content="#b91d47">
|
<meta name="msapplication-TileColor" content="#b91d47">
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
<title>VEL Connect | Pair</title>
|
<title>VEL Connect | Pair</title>
|
||||||
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="/css/spectre.min.css">
|
<link rel="stylesheet" href="/static/css/spectre.min.css">
|
||||||
<script src="/js/util.js"></script>
|
<script src="/static/js/util.js"></script>
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--primary-color: #bc1f2d;
|
--primary-color: #bc1f2d;
|
||||||
|
|
@ -54,7 +54,7 @@
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-image">
|
<div class="card-image">
|
||||||
<img src="/img/pair_code_screenshot.png" class="img-responsive">
|
<img src="/static/img/pair_code_screenshot.png" class="img-responsive">
|
||||||
</div>
|
</div>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="card-title h5">Enter Pairing Code</div>
|
<div class="card-title h5">Enter Pairing Code</div>
|
||||||
|
|
@ -75,7 +75,7 @@
|
||||||
let submit_button = document.getElementById('submit_pairing_code');
|
let submit_button = document.getElementById('submit_pairing_code');
|
||||||
let pair_code_input = document.getElementById('pair_code');
|
let pair_code_input = document.getElementById('pair_code');
|
||||||
submit_button.addEventListener('click', () => {
|
submit_button.addEventListener('click', () => {
|
||||||
httpGetAsync('https://connect.vel.workers.dev/api/pair_headset/' + pair_code_input.value, (resp) => {
|
httpGetAsync('/api/pair_headset/' + pair_code_input.value, (resp) => {
|
||||||
console.log(resp);
|
console.log(resp);
|
||||||
let respData = JSON.parse(resp);
|
let respData = JSON.parse(resp);
|
||||||
if (respData['hw_id'] != '') {
|
if (respData['hw_id'] != '') {
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
from fastapi import APIRouter
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
|
|
||||||
|
|
||||||
|
# APIRouter creates path operations for user module
|
||||||
|
router = APIRouter(
|
||||||
|
prefix="",
|
||||||
|
tags=["Website"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get('/')
|
||||||
|
def index():
|
||||||
|
return FileResponse("templates/index.html")
|
||||||
|
|
||||||
|
|
||||||
|
@router.get('/pair')
|
||||||
|
def pair():
|
||||||
|
return FileResponse("templates/pair.html")
|
||||||
|
|
||||||
|
|
||||||
|
@router.get('/success')
|
||||||
|
def success():
|
||||||
|
return FileResponse("templates/success.html")
|
||||||
|
|
||||||
|
|
||||||
|
@router.get('/failure')
|
||||||
|
def failure():
|
||||||
|
return FileResponse("templates/failure.html")
|
||||||