websocket stuff
This commit is contained in:
parent
013e6c5b01
commit
cad2d85ce4
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
|
|
@ -5,8 +5,19 @@
|
|||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="8a64704d-5500-41a6-aa4c-e275933fc58c" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/components/Player.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/components/Player.tsx" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Caddyfile" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/docker-compose.yml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/internal/ws/handlers.go" beforeDir="false" afterPath="$PROJECT_DIR$/internal/ws/handlers.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/.env.example" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/.env.example" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/package.json" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/interfaces/IMessage.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/interfaces/IMessage.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/interfaces/Identity.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/interfaces/Identity.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/pages/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/pages/index.tsx" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/pages/player.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/pages/player.tsx" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/util/Message.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/util/Message.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/types/environment.d.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/types/environment.d.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/yarn.lock" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/yarn.lock" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
localhost:3001
|
||||
|
||||
file_server
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version: "3.9"
|
||||
services:
|
||||
caddy:
|
||||
|
|
@ -3,12 +3,15 @@ package ws
|
|||
//todo better data deserialization
|
||||
|
||||
type IdentityData struct {
|
||||
ClientID string `json:"clientId"`
|
||||
ClientID string `json:"clientID"`
|
||||
User User `json:"user"`
|
||||
}
|
||||
|
||||
func handleIdentifyEvent(message *Message) {
|
||||
d := message.Data.(map[string]interface{})
|
||||
if id, ok := d["clientID"]; ok {
|
||||
log.Infof("Client %s has sent identify event", id.(string))
|
||||
}
|
||||
m := Message{
|
||||
MessageData: MessageData{
|
||||
Type: Identify,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
DISCORD_ID=
|
||||
DISCORD_SECRET=
|
||||
SECRET=
|
||||
CLIENT_ID=
|
||||
NEXTAUTH_URL=
|
||||
NEXT_PUBLIC_CLIENT_ID=
|
||||
NEXTAUTH_URL=
|
||||
NEXT_PUBLIC_WS_URI=
|
||||
|
|
@ -22,7 +22,8 @@
|
|||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-player": "^2.9.0",
|
||||
"uuid": "^8.3.2"
|
||||
"uuid": "^8.3.2",
|
||||
"ws": "^8.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "^12.0.8",
|
||||
|
|
@ -31,6 +32,7 @@
|
|||
"@types/react-dom": "^17.0.3",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@types/websocket": "^1.0.4",
|
||||
"@types/ws": "^8.2.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"typescript": "4.3.2"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
import { User } from "next-auth";
|
||||
import { useEffect, useState } from "react";
|
||||
import PlayerSocket from "../ws/websocket";
|
||||
|
||||
interface useWSProps {
|
||||
user: User;
|
||||
}
|
||||
|
||||
// todo write websocket reconnector
|
||||
const useWS = ({ user }: useWSProps) => {
|
||||
// todo checkout usecallback
|
||||
const [socket, setSocket] = useState<PlayerSocket>();
|
||||
useEffect(() => {
|
||||
let socket = new PlayerSocket(user);
|
||||
setSocket(socket);
|
||||
return () => {
|
||||
return socket.close();
|
||||
};
|
||||
}, []);
|
||||
return socket;
|
||||
};
|
||||
|
||||
export default useWS;
|
||||
|
|
@ -8,7 +8,7 @@ export enum MessageTypes {
|
|||
|
||||
interface IMessage {
|
||||
type: MessageTypes;
|
||||
data?: Record<string, unknown>;
|
||||
data?: unknown;
|
||||
}
|
||||
|
||||
export default IMessage;
|
||||
|
|
|
|||
|
|
@ -6,3 +6,5 @@ interface IdentityData {
|
|||
playHead?: number;
|
||||
user: IUser;
|
||||
}
|
||||
|
||||
export default IdentityData;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Button, Link as ChakraLink, Text } from "@chakra-ui/react";
|
||||
import { GetServerSideProps, NextPage } from "next";
|
||||
import { getSession, signIn } from "next-auth/react";
|
||||
import Head from "next/head";
|
||||
import Link from "next/link";
|
||||
import React from "react";
|
||||
import { Container } from "../components/Container";
|
||||
|
|
@ -10,26 +11,30 @@ import { Main } from "../components/Main";
|
|||
|
||||
const Index: NextPage = () => {
|
||||
return (
|
||||
<Container height="100vh">
|
||||
<Hero />
|
||||
<Main>
|
||||
<Button
|
||||
maxWidth="200"
|
||||
alignSelf="center"
|
||||
onClick={() => signIn("discord")}
|
||||
disabled
|
||||
>
|
||||
Login With Discord
|
||||
</Button>
|
||||
</Main>
|
||||
<Footer>
|
||||
<ChakraLink>
|
||||
<Link href="https://velvox.dev">
|
||||
<Text>©2022 Velvox</Text>
|
||||
</Link>
|
||||
</ChakraLink>
|
||||
</Footer>
|
||||
</Container>
|
||||
<>
|
||||
<Head>
|
||||
<title>Watch Together</title>
|
||||
</Head>
|
||||
<Container height="100vh">
|
||||
<Hero />
|
||||
<Main>
|
||||
<Button
|
||||
maxWidth="200"
|
||||
alignSelf="center"
|
||||
onClick={() => signIn("discord")}
|
||||
>
|
||||
Login With Discord
|
||||
</Button>
|
||||
</Main>
|
||||
<Footer>
|
||||
<ChakraLink>
|
||||
<Link href="https://velvox.dev">
|
||||
<Text>©2022 Velvox</Text>
|
||||
</Link>
|
||||
</ChakraLink>
|
||||
</Footer>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
import consola from "consola";
|
||||
import { GetServerSideProps, NextPage } from "next";
|
||||
import { Session, User } from "next-auth";
|
||||
import { getSession, useSession } from "next-auth/react";
|
||||
import { User } from "next-auth";
|
||||
import { getSession } from "next-auth/react";
|
||||
import dynamic from "next/dynamic";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import Head from "next/head";
|
||||
import React, { useRef } from "react";
|
||||
import ReactPlayer from "react-player";
|
||||
import { Container } from "../components/Container";
|
||||
import { MessageTypes } from "../interfaces/IMessage";
|
||||
import Message from "../util/Message";
|
||||
import MessageUtil from "../util/MessageUtil";
|
||||
import useWS from "../hooks/useWS";
|
||||
|
||||
const Player = dynamic(() => import("../components/Player"), { ssr: false });
|
||||
|
||||
|
|
@ -17,58 +15,52 @@ interface PlayerPageProps {
|
|||
user: User;
|
||||
}
|
||||
|
||||
const pingEvent = (ws: WebSocket) => {
|
||||
let interval = setInterval(() => {
|
||||
if (ws.readyState === ws.CLOSED) {
|
||||
clearInterval(interval);
|
||||
return;
|
||||
}
|
||||
console.log("running ping event");
|
||||
ws.send(MessageUtil.encode(new Message(MessageTypes.Ping)));
|
||||
}, 20000);
|
||||
};
|
||||
|
||||
const PlayerPage: NextPage<PlayerPageProps> = ({ URI, user }) => {
|
||||
const playerRef = useRef<ReactPlayer>();
|
||||
consola.wrapAll();
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined") return;
|
||||
const ws = new WebSocket(URI);
|
||||
ws.onopen = () => {
|
||||
ws.send(
|
||||
MessageUtil.encode(
|
||||
new Message(MessageTypes.Identify, {
|
||||
clientID: process.env.CLIENT_ID,
|
||||
user: {
|
||||
ID: user.id,
|
||||
Name: user.name,
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
pingEvent(ws);
|
||||
};
|
||||
ws.onmessage = (event) => {
|
||||
console.log(event);
|
||||
console.log(JSON.parse(event.data));
|
||||
};
|
||||
ws.onclose = () => {
|
||||
ws.close();
|
||||
};
|
||||
ws.onerror = (err) => {
|
||||
console.log(err);
|
||||
return () => {
|
||||
ws.close();
|
||||
};
|
||||
};
|
||||
return () => {
|
||||
ws.close();
|
||||
};
|
||||
}, []);
|
||||
const socket = useWS({ user });
|
||||
// useEffect(() => {
|
||||
// if (typeof window === "undefined") return;
|
||||
// const ws = new WebSocket(URI);
|
||||
// ws.onopen = () => {
|
||||
// ws.send(
|
||||
// MessageUtil.encode(
|
||||
// new Message(MessageTypes.Identify, {
|
||||
// clientID: process.env.CLIENT_ID,
|
||||
// user: {
|
||||
// ID: user.id,
|
||||
// Name: user.name,
|
||||
// },
|
||||
// })
|
||||
// )
|
||||
// );
|
||||
// pingEvent(ws);
|
||||
// };
|
||||
// ws.onmessage = (event) => {
|
||||
// console.log(event);
|
||||
// console.log(JSON.parse(event.data));
|
||||
// };
|
||||
// ws.onclose = () => {
|
||||
// ws.close();
|
||||
// };
|
||||
// ws.onerror = (err) => {
|
||||
// console.log(err);
|
||||
// return () => {
|
||||
// ws.close();
|
||||
// };
|
||||
// };
|
||||
// return () => {
|
||||
// ws.close();
|
||||
// };
|
||||
// }, []);
|
||||
return (
|
||||
<Container height="100vh">
|
||||
<Player id="" ref={playerRef} />
|
||||
</Container>
|
||||
<>
|
||||
<Head>
|
||||
<title>Watch Together</title>
|
||||
</Head>
|
||||
<Container height="100vh">
|
||||
<Player id="" ref={playerRef} />
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
@ -84,7 +76,6 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
|
|||
}
|
||||
return {
|
||||
props: {
|
||||
URI: process.env.WS_URI,
|
||||
user: session.user,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
import IMessage, { MessageTypes } from "../interfaces/IMessage";
|
||||
|
||||
export default class Message implements IMessage {
|
||||
constructor(
|
||||
public type: MessageTypes,
|
||||
public data?: Record<string, unknown>
|
||||
) {}
|
||||
constructor(public type: MessageTypes, public data?: unknown) {}
|
||||
|
||||
toJSON(): Record<string, unknown> {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
// nice and easy way to get types for the
|
||||
|
||||
import { User } from "next-auth";
|
||||
import IdentityData from "../interfaces/Identity";
|
||||
import { MessageTypes } from "../interfaces/IMessage";
|
||||
import Message from "../util/Message";
|
||||
import MessageUtil from "../util/MessageUtil";
|
||||
|
||||
// browser socket
|
||||
let Websocket: typeof WebSocket;
|
||||
if (typeof window !== "undefined") {
|
||||
Websocket = window.WebSocket;
|
||||
} else {
|
||||
Websocket = require("ws");
|
||||
}
|
||||
|
||||
export default class PlayerSocket extends Websocket {
|
||||
constructor(private user: User) {
|
||||
super(process.env.NEXT_PUBLIC_WS_URI);
|
||||
this.onopen = this.onOpen;
|
||||
}
|
||||
onOpen() {
|
||||
this.send(
|
||||
MessageUtil.encode(
|
||||
new Message(MessageTypes.Identify, {
|
||||
clientID: process.env.NEXT_PUBLIC_CLIENT_ID,
|
||||
user: {
|
||||
id: this.user.id,
|
||||
name: this.user.name,
|
||||
},
|
||||
} as IdentityData)
|
||||
)
|
||||
);
|
||||
this.pingEvent();
|
||||
}
|
||||
pingEvent() {
|
||||
let interval = setInterval(() => {
|
||||
if (!this.open) {
|
||||
clearInterval(interval);
|
||||
return;
|
||||
}
|
||||
console.log("[WS] running ping event");
|
||||
this.send(MessageUtil.encode(new Message(MessageTypes.Ping)));
|
||||
}, 20000);
|
||||
}
|
||||
get open() {
|
||||
return this.readyState === this.OPEN;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ declare namespace NodeJS {
|
|||
DISCORD_ID: string;
|
||||
DISCORD_SECRET: string;
|
||||
SECRET: string;
|
||||
CLIENT_ID: string;
|
||||
WS_URI: string;
|
||||
NEXT_PUBLIC_CLIENT_ID: string;
|
||||
NEXT_PUBLIC_WS_URI: string;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1029,6 +1029,13 @@
|
|||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/ws@^8.2.2":
|
||||
version "8.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21"
|
||||
integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
acorn-walk@^8.0.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
|
||||
|
|
@ -3227,6 +3234,11 @@ ws@^7.3.1:
|
|||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b"
|
||||
integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==
|
||||
|
||||
ws@^8.4.2:
|
||||
version "8.4.2"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.2.tgz#18e749868d8439f2268368829042894b6907aa0b"
|
||||
integrity sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA==
|
||||
|
||||
xtend@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
|
|
|
|||
Loading…
Reference in New Issue