Skip to content

Commit

Permalink
feat: several changes
Browse files Browse the repository at this point in the history
  • Loading branch information
z7pz committed Feb 15, 2024
1 parent 1350f2f commit e23333b
Show file tree
Hide file tree
Showing 5 changed files with 350 additions and 27 deletions.
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@
8. [x] Create real Authentication system (JWT maybe)
9. [x] join a party
10. [x] listen to party events (seek/pause/resume, etc...)
11. [ ] craete rooms for each party
11. [x] craete rooms for each party
12. [ ] implement the fully prototype
69 changes: 53 additions & 16 deletions src/gateway/mod.rs
Original file line number Diff line number Diff line change
@@ -1,53 +1,90 @@
use std::{any::Any, sync::Arc};

use serde::Deserialize;
use serde_json::Value;
use socketioxide::extract::{Data, SocketRef, State as IoState};

use crate::{
middlewares::{self},
middlewares,
structures::{AppState, Snowflake},
Message, Party,
};

#[derive(Deserialize)]
#[derive(Deserialize, Clone)]
struct JoinParty {
id: String,
pub id: String,
}

#[derive(Deserialize, Clone)]
struct SendMessage {
pub id: String,
pub content: String,
}

pub async fn on_connect(socket: SocketRef, IoState(state): IoState<AppState>) {
if let Ok(user) = middlewares::auth_parts(socket.req_parts(), state.clone()).await {
println!("creating listners for {}/{}", user.username, socket.id);

socket.on(
"message",
|socket: SocketRef, Data::<SendMessage>(data), IoState(state): IoState<AppState>| {
let mut parties = state.parties.lock().unwrap();
if let Some(party) = parties.get_mut(&Snowflake::try_from(data.clone().id).unwrap())
{
let message = Arc::new(Message::new(data.clone().content.into(), user));
let messages = [party.messages.clone(), vec![message.clone()]].concat();
let party = Arc::new(Party {
messages,
..Party::clone(party)
});
parties.insert(Snowflake::try_from(data.clone().id).unwrap(), party.clone());
socket.to(data.id).emit("message", message).ok();
println!("{:#?}", party.messages);
} else {
println!("party not found")
// FIXME: return something somehow
}
},
);
socket.on(
"join",
|socket: SocketRef, Data::<JoinParty>(data), IoState(state): IoState<AppState>| {
println!("join request party: {:?}", data.id);
let parties = state.parties.lock().unwrap();
if let Some(party) = parties.get(&Snowflake::try_from(data.id).unwrap()) {
if let Some(party) = parties.get(&Snowflake::try_from(data.clone().id).unwrap()) {
println!("sending joined {}", socket.id);
socket.emit("joined", party).unwrap();
socket.leave_all().ok();
println!("{:#?}", state.socket.sockets().unwrap());
socket.join(data.id).ok();
socket.emit("joined", party).ok();
} else {
println!("party not found")
// FIXME: return something somehow
}
},
);
// event reciver is getting data and transfer it into everyone
// event reciver is getting data and transfer it into everyone
//
// for example:
// for example:
//
// <socket-client>.emit("event", { type: "seek", data: { /* some data about seeking */ } })
// <socket-client>.emit("event", { type: "pause", data: { None } })
// <socket-client>.emit("event", { type: "resume", data: { None } })

#[derive(Deserialize, Clone)]
struct Event {
id: String,
data: Value
}
socket.on(
"event",
|socket: SocketRef,
IoState(state): IoState<AppState>,
Data::<Value>(data): Data<Value>| {
// emit event into everyone except the user that sent the event
for s in state.socket.sockets().unwrap() {
if s.id == socket.id {
continue;
}
s.emit("event", data.clone()).ok();
Data::<Event>(data): Data<Event>| {
let parties = state.parties.lock().unwrap();
if parties.get(&Snowflake::try_from(data.clone().id).unwrap()).is_some() {
socket.to(data.id).emit("event", data.data.clone()).ok();
} else {
println!("party not found")
// FIXME: return something somehow
}
},
);
Expand Down
11 changes: 10 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,16 @@ async fn main() -> Result<()> {
parties.insert(
Snowflake::try_from("7156070048988135428".to_string()).unwrap(),
Arc::new(Party {
name: "this is name".to_string(),
name: "1".to_string(),
owner: user.clone(),
messages: <_>::default(),
video: <_>::default(),
}),
);
parties.insert(
Snowflake::try_from("7156070048988135430".to_string()).unwrap(),
Arc::new(Party {
name: "2".to_string(),
owner: user.clone(),
messages: <_>::default(),
video: <_>::default(),
Expand Down
236 changes: 236 additions & 0 deletions src/party1.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<video onseeked="" onseeking="" width="320" height="240" controls>
<source src="BigBuckBunny.mp4" type="video/mp4" />
<source src="movie.ogg" type="video/ogg" />
Your browser does not support the video tag.
</video>

<input type="text" /> <button>send</button>
<div id="messages"></div>
<script
src="https://cdn.socket.io/4.7.4/socket.io.min.js"
integrity="sha384-Gr6Lu2Ajx28mzwyVR8CFkULdCU7kMlZ9UthllibdOSo6qAiN+yXNHqtgdTvFXMT4"
crossorigin="anonymous"
></script>
<script>
async function get_token() {
let myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");

let raw = JSON.stringify({
username: "super user",
password: "super password",
});

let requestOptions = {
method: "POST",
headers: myHeaders,
body: raw,
};

let token = await fetch(
"http://localhost:3000/auth/login",
requestOptions
)
.then((response) => response.text())
.catch((error) => console.error(error));

return token;
}

async function get_parties(token) {
let headers = new Headers();
headers.append("Authorization", token);
const requestOptions = {
method: "GET",
headers: headers,
redirect: "follow",
};
let parties = await fetch(
"http://localhost:3000/party/all",
requestOptions
)
.then((response) => response.json())
.catch((error) => console.error(error));
return parties;
}

(async () => {
const videoElement = document.getElementsByTagName("video")[0];
const messageInput = document.getElementsByTagName("input")[0];
const sendBtn = document.getElementsByTagName("button")[0];
const messagesContainer =
document.getElementsByTagName("div")[0];
videoElement.addEventListener("seeked", emitSeek);
videoElement.addEventListener("pause", emitPause);
videoElement.addEventListener("play", emitPlay);

sendBtn.addEventListener("click", () => {
if (!messageInput.value) return;
emitMessage();
});

const token = await get_token();
const parties = await get_parties(token);

const socket = io("ws://localhost:3000", {
extraHeaders: {
Authorization: token,
},
});
socket.on("connect", () => {
console.log("connected to the websocket!");
});
socket.emit("join", {
id: "7156070048988135430",
});
socket.on("message", (message) => {
const div = document.createElement("div");
div.innerText = message.content;
messagesContainer.appendChild(div);
});

socket.on("event", (data) => {
switch (data.type) {
case "seek": {
console.log("seeking received");

// remove Listener temporary
videoElement.removeEventListener(
"seeked",
emitSeek
);
// after we recieved the event of seeking from the socket we get back the old Listener (emitSeek)
function reset() {
videoElement.removeEventListener(
"seeked",
reset
);
videoElement.addEventListener(
"seeked",
emitSeek
);
}
// this is magic :)
videoElement.addEventListener("seeked", reset);
// update the seek time
videoElement.currentTime = data.data.time;
// get back the Listener

break;
}
case "pause": {
console.log("pause received");

// remove Listener temporary
videoElement.removeEventListener(
"pause",
emitPause
);
// after we recieved the event of seeking from the socket we get back the old Listener (emitSeek)
function reset() {
videoElement.removeEventListener(
"pause",
reset
);
videoElement.addEventListener(
"pause",
emitPause
);
}
// this is magic :)
videoElement.addEventListener("pause", reset);
// update the seek time
videoElement.pause();
// get back the Listener

break;
}
case "resume": {
console.log("resume received");

// remove Listener temporary
videoElement.removeEventListener("pause", emitPlay);
// after we recieved the event of seeking from the socket we get back the old Listener (emitSeek)
function reset() {
videoElement.removeEventListener("play", reset);
videoElement.addEventListener("play", emitPlay);
}
// this is magic :)
videoElement.addEventListener("play", reset);
// update the seek time
videoElement.play();
// get back the Listener
break;
}
default: {
console.log(data);
break;
}
}
});
socket.once("joined", (party) => {
console.log("event received");
console.log(party.messages.length);
for (let message of party.messages) {
console.log('i');
const div = document.createElement("div");
div.innerText = message.content;
messagesContainer.appendChild(div);
}
});
socket.emit("join", {
id: "7156070048988135430",
});

function emitSeek() {
console.log("seeking");
socket.emit("event", {
id: "7156070048988135430",
data: {
type: "seek",
data: {
time: videoElement.currentTime,
},
},
});
}
function emitMessage() {
console.log("sending message");
socket.emit("message", {
id: "7156070048988135430",
content: messageInput.value,
});
const div = document.createElement("div");
div.innerText = messageInput.value;
messagesContainer.appendChild(div);
}
function emitPlay() {
console.log("playing");
socket.emit("event", {
id: "7156070048988135430",
data: {
type: "resume",
},
});
}
function emitPause() {
console.log("pausing");
socket.emit("event", {
id: "7156070048988135430",
data: {
type: "pause",
},
});
}
})();
</script>
</body>
</html>
Loading

0 comments on commit e23333b

Please sign in to comment.