forked from FreakU/watch-party
ids are cool
This commit is contained in:
parent
7801ac0dc0
commit
56a78a4731
|
@ -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",
|
||||||
|
|
32
Cargo.toml
32
Cargo.toml
|
@ -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"
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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") {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
|
@ -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";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -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();
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
58
src/main.rs
58
src/main.rs
|
@ -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"));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue