ids are cool

This commit is contained in:
PeachyDelight 2022-06-11 04:57:36 +02:00
parent 7801ac0dc0
commit 56a78a4731
13 changed files with 5812 additions and 60 deletions

24
Cargo.lock generated
View File

@ -483,7 +483,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8"
dependencies = [ dependencies = [
"rand 0.8.4", "rand 0.8.5",
] ]
[[package]] [[package]]
@ -632,19 +632,18 @@ dependencies = [
"libc", "libc",
"rand_chacha 0.2.2", "rand_chacha 0.2.2",
"rand_core 0.5.1", "rand_core 0.5.1",
"rand_hc 0.2.0", "rand_hc",
] ]
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.8.4" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [ dependencies = [
"libc", "libc",
"rand_chacha 0.3.1", "rand_chacha 0.3.1",
"rand_core 0.6.3", "rand_core 0.6.3",
"rand_hc 0.3.1",
] ]
[[package]] [[package]]
@ -694,15 +693,6 @@ dependencies = [
"rand_core 0.5.1", "rand_core 0.5.1",
] ]
[[package]]
name = "rand_hc"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core 0.6.3",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.10" version = "0.2.10"
@ -851,7 +841,7 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"rand 0.8.4", "rand 0.8.5",
"redox_syscall", "redox_syscall",
"remove_dir_all", "remove_dir_all",
"winapi", "winapi",
@ -987,7 +977,7 @@ dependencies = [
"httparse", "httparse",
"input_buffer", "input_buffer",
"log", "log",
"rand 0.8.4", "rand 0.8.5",
"sha-1", "sha-1",
"url", "url",
"utf-8", "utf-8",
@ -1119,8 +1109,10 @@ version = "0.1.0"
dependencies = [ dependencies = [
"futures", "futures",
"futures-util", "futures-util",
"lazy_static",
"nanoid", "nanoid",
"once_cell", "once_cell",
"rand 0.8.5",
"serde", "serde",
"serde_json", "serde_json",
"tokio", "tokio",

View File

@ -1,15 +1,17 @@
[package] [package]
name = "watch-party" name = "watch-party"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
futures = "0.3.17" futures = "0.3.17"
futures-util = "0.3.17" futures-util = "0.3.17"
once_cell = "1.8.0" once_cell = "1.8.0"
serde = { version = "1.0.130", features = ["derive"] } serde = { version = "1.0.130", features = ["derive"] }
serde_json = "1.0.68" serde_json = "1.0.68"
tokio = { version = "1.12.0", features = ["full"] } tokio = { version = "1.12.0", features = ["full"] }
tokio-stream = { version = "0.1.7", features = ["fs"] } tokio-stream = { version = "0.1.7", features = ["fs"] }
warp = "0.3.1" warp = "0.3.1"
nanoid = "0.4.0" nanoid = "0.4.0"
lazy_static = "1.4.0"
rand = "0.8.5"

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>watch party :D</title> <title>watch party :D</title>
<link rel="stylesheet" href="/styles.css?v=bfdcf2" /> <link rel="stylesheet" href="/styles.css?v=bfdcf21" />
</head> </head>
<body> <body>
@ -38,6 +38,14 @@
id="create-session-subs-name" id="create-session-subs-name"
placeholder="English" placeholder="English"
/> />
<label for="create-session-id">Session ID:</label>
<input
type="text"
id="create-session-id"
placeholder="session-id"
/>
<button>Create</button> <button>Create</button>
<p> <p>
@ -47,6 +55,6 @@
</form> </form>
</div> </div>
<script type="module" src="/create.mjs?v=bfdcf2"></script> <script type="module" src="/create.mjs?v=bfdcf21"></script>
</body> </body>
</html> </html>

View File

@ -1,7 +1,7 @@
import { setupCreateSessionForm } from "./lib/create-session.mjs?v=bfdcf2"; import { setupCreateSessionForm } from "./lib/create-session.mjs?v=bfdcf21";
const main = () => { const main = async () => {
setupCreateSessionForm(); await setupCreateSessionForm();
}; };
if (document.readyState === "complete") { if (document.readyState === "complete") {

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>watch party :D</title> <title>watch party :D</title>
<link rel="stylesheet" href="/styles.css?v=bfdcf2" /> <link rel="stylesheet" href="/styles.css?v=bfdcf21" />
</head> </head>
<body> <body>
@ -66,7 +66,7 @@
</form> </form>
</div> </div>
<script type="module" src="/main.mjs?v=bfdcf2"></script> <script type="module" src="/main.mjs?v=bfdcf21"></script>
<script> <script>
const updateColourLabel = () => { const updateColourLabel = () => {
const colour = document.querySelector("#join-session-colour").value; const colour = document.querySelector("#join-session-colour").value;

View File

@ -2,11 +2,11 @@ import {
setDebounce, setDebounce,
setVideoTime, setVideoTime,
setPlaying, setPlaying,
} from "./watch-session.mjs?v=bfdcf2"; } from "./watch-session.mjs?v=bfdcf21";
import { emojify, findEmojis } from "./emojis.mjs?v=bfdcf2"; import { emojify, findEmojis } from "./emojis.mjs?v=bfdcf21";
import { linkify } from "./links.mjs?v=bfdcf2"; import { linkify } from "./links.mjs?v=bfdcf21";
import { joinSession } from "./watch-session.mjs?v=bfdcf2"; import { joinSession } from "./watch-session.mjs?v=bfdcf21";
import { pling } from "./pling.mjs?v=bfdcf2"; import { pling } from "./pling.mjs?v=bfdcf21";
import { state } from "./state.mjs"; import { state } from "./state.mjs";
function setCaretPosition(elem, caretPos) { function setCaretPosition(elem, caretPos) {

View File

@ -1,18 +1,48 @@
import { createSession } from "./watch-session.mjs?v=bfdcf2"; import { createSession } from "./watch-session.mjs?v=bfdcf21";
export const setupCreateSessionForm = () => { const getFreeSessionId = async () => {
// fetch /random_unused_session
const response = await fetch("/random_unused_session");
const json = await response.json();
return json.id;
}
const checkIfSessionExists = async (sessionId) => {
// fetch /check_if_session_exists/:sessionId
const response = await fetch(`/check_if_session_exists/${sessionId}`);
const json = await response.json();
return json.exists;
}
export const setupCreateSessionForm = async () => {
const form = document.querySelector("#create-session-form"); const form = document.querySelector("#create-session-form");
const videoUrl = form.querySelector("#create-session-video"); const videoUrl = form.querySelector("#create-session-video");
const subsUrl = form.querySelector("#create-session-subs"); const subsUrl = form.querySelector("#create-session-subs");
const subsName = form.querySelector("#create-session-subs-name"); const subsName = form.querySelector("#create-session-subs-name");
const sessionId = form.querySelector("#create-session-id");
form.addEventListener("submit", (event) => { // get free session id
const freeSessionId = await getFreeSessionId();
// set session id to free session id
sessionId.placeholder = freeSessionId;
// sessionId.value = freeSessionId;
form.addEventListener("submit", async (event) => {
event.preventDefault(); event.preventDefault();
const realSessionId = sessionId.value || sessionId.placeholder;
// check if session exists
const exists = await checkIfSessionExists(realSessionId);
if (exists) {
alert("Session already exists");
return;
}
let subs = []; let subs = [];
if (subsUrl.value) { if (subsUrl.value) {
subs.push({ url: subsUrl.value, name: subsName.value || "default" }); subs.push({ url: subsUrl.value, name: subsName.value || "default" });
} }
createSession(videoUrl.value, subs); createSession(realSessionId, videoUrl.value, subs);
}); });
}; }

View File

@ -1,4 +1,4 @@
import { joinSession } from "./watch-session.mjs?v=bfdcf2"; import { joinSession } from "./watch-session.mjs?v=bfdcf21";
import { state } from "./state.mjs"; import { state } from "./state.mjs";
/** /**

View File

@ -1,4 +1,4 @@
import { joinSession } from "./watch-session.mjs?v=bfdcf2"; import { joinSession } from "./watch-session.mjs?v=bfdcf21";
import { state } from "./state.mjs"; import { state } from "./state.mjs";
export async function linkify( export async function linkify(

View File

@ -1,10 +1,10 @@
import { setupVideo } from "./video.mjs?v=bfdcf2"; import { setupVideo } from "./video.mjs?v=bfdcf21";
import { import {
setupChat, setupChat,
logEventToChat, logEventToChat,
updateViewerList, updateViewerList,
printChatMessage, printChatMessage,
} from "./chat.mjs?v=bfdcf2"; } from "./chat.mjs?v=bfdcf21";
import ReconnectingWebSocket from "./reconnecting-web-socket.mjs"; import ReconnectingWebSocket from "./reconnecting-web-socket.mjs";
import { state } from "./state.mjs"; import { state } from "./state.mjs";
@ -259,14 +259,16 @@ export const joinSession = async () => {
}; };
/** /**
* @param {string} sessionId
* @param {string} videoUrl * @param {string} videoUrl
* @param {Array} subtitleTracks * @param {Array} subtitleTracks
*/ */
export const createSession = async (videoUrl, subtitleTracks) => { export const createSession = async (sessionId, videoUrl, subtitleTracks) => {
const { id } = await fetch("/start_session", { const { id } = await fetch("/start_session", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ body: JSON.stringify({
session_id: sessionId,
video_url: videoUrl, video_url: videoUrl,
subtitle_tracks: subtitleTracks, subtitle_tracks: subtitleTracks,
}), }),

View File

@ -1,4 +1,4 @@
import { setupJoinSessionForm } from "./lib/join-session.mjs?v=bfdcf2"; import { setupJoinSessionForm } from "./lib/join-session.mjs?v=bfdcf21";
const main = () => { const main = () => {
setupJoinSessionForm(); setupJoinSessionForm();

5672
src/id_generation.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,29 @@
#[macro_use]
extern crate lazy_static;
use serde_json::json; use serde_json::json;
use std::net::IpAddr; use std::net::IpAddr;
use warb::{hyper::StatusCode, Filter, Reply}; use warb::{hyper::StatusCode, Filter, Reply};
use warp as warb; // i think it's funny use warp as warb; // i think it's funny
use nanoid::nanoid;
mod events; mod events;
mod utils; mod utils;
mod viewer_connection; mod viewer_connection;
mod watch_session; mod watch_session;
mod id_generation;
use serde::Deserialize; use serde::Deserialize;
use crate::{ use crate::{
viewer_connection::ws_subscribe, viewer_connection::ws_subscribe,
watch_session::{get_session, SubtitleTrack, WatchSession, SESSIONS}, watch_session::{get_session, SubtitleTrack, WatchSession, SESSIONS},
id_generation::generate_id,
}; };
#[derive(Deserialize)] #[derive(Deserialize)]
struct StartSessionBody { struct StartSessionBody {
session_id: String,
video_url: String, video_url: String,
#[serde(default = "Vec::new")] #[serde(default = "Vec::new")]
subtitle_tracks: Vec<SubtitleTrack>, subtitle_tracks: Vec<SubtitleTrack>,
@ -54,16 +58,22 @@ async fn main() {
.and(warb::post()) .and(warb::post())
.and(warb::body::json()) .and(warb::body::json())
.map(|body: StartSessionBody| { .map(|body: StartSessionBody| {
// get session id from body
let session_id = body.session_id;
// check if session exists already
if get_session(&session_id).is_some() {
// if it does, return error
return StatusCode::CONFLICT.into_response();
}
let mut sessions = SESSIONS.lock().unwrap(); let mut sessions = SESSIONS.lock().unwrap();
let session_id = nanoid!(12);
let session = WatchSession::new(body.video_url, body.subtitle_tracks); let session = WatchSession::new(body.video_url, body.subtitle_tracks);
let session_view = session.view(); let session_view = session.view();
sessions.insert(session_id.clone(), session); sessions.insert(session_id.clone(), session);
warb::reply::json(&json!({ "id": session_id.to_string(), "session": session_view })) warb::reply::json(&json!({ "id": session_id.to_string(), "session": session_view })).into_response()
}); });
let get_emoji_route = warb::path!("emojos").and_then(get_emoji_list); let get_emoji_route = warb::path!("emojos").and(warb::path::end()).and_then(get_emoji_list);
enum RequestedSession { enum RequestedSession {
Session(String, WatchSession), Session(String, WatchSession),
@ -96,19 +106,55 @@ async fn main() {
.and(warb::path!("subscribe")) .and(warb::path!("subscribe"))
.and(warb::query()) .and(warb::query())
.and(warb::ws()) .and(warb::ws())
.and(warb::path::end())
.map( .map(
|requested_session, query: SubscribeQuery, ws: warb::ws::Ws| match requested_session { |requested_session, query: SubscribeQuery, ws: warb::ws::Ws| match requested_session {
RequestedSession::Session(session_id, _) => ws RequestedSession::Session(session_id, _) => ws
.on_upgrade(move |ws| ws_subscribe(session_id, query.nickname, query.colour, ws)) .on_upgrade(move |ws| {
ws_subscribe(session_id, query.nickname, query.colour, ws)
})
.into_response(), .into_response(),
RequestedSession::Error(error_response) => error_response.into_response(), RequestedSession::Error(error_response) => error_response.into_response(),
}, },
); );
let get_random_unused_session_route = warb::path("random_unused_session")
.and(warb::path::end())
.map(|| {
loop {
// generate a random session id
// if it's free, return it
let session_id = generate_id();
if get_session(&session_id).is_none() {
return warb::reply::json(&json!({ "id": session_id.to_string() }));
}
}
});
let check_if_session_exists_route = warb::path("check_if_session_exists")
.and(warb::path::param::<String>())
.and(warb::path::end())
.map(|session_id: String| {
if get_session(&session_id).is_some() {
warb::reply::with_status(
warb::reply::json(&json!({ "exists": true })),
StatusCode::OK,
)
} else {
warb::reply::with_status(
warb::reply::json(&json!({ "exists": false })),
StatusCode::OK,
)
}
});
let routes = start_session_route let routes = start_session_route
.or(get_status_route) .or(get_status_route)
.or(ws_subscribe_route) .or(ws_subscribe_route)
.or(get_emoji_route) .or(get_emoji_route)
.or(get_random_unused_session_route)
.or(check_if_session_exists_route)
.or(warb::path::end().and(warb::fs::file("frontend/index.html"))) .or(warb::path::end().and(warb::fs::file("frontend/index.html")))
.or(warb::fs::dir("frontend")); .or(warb::fs::dir("frontend"));