Fix Presences

This commit is contained in:
ADAMJR 2021-10-04 18:15:43 +01:00
parent ce60f51034
commit 106f61f881
9 changed files with 73 additions and 40 deletions

View File

@ -1,7 +1,27 @@
export class VoiceService {
private connections = new Map<string, VoiceData[]>();
private connections = new Map<string, ChannelTypes.VoiceConnection[]>();
public add(channelId: string, data: VoiceData) {
public get(channelId: string) {
return this.getOrCreate(channelId);
}
public getForUser(channelId: string, userId: string) {
// check if user is already connected
const connections = this.getOrCreate(channelId);
const isConnected = connections.some(u => u.userId === userId);
if (!isConnected)
throw new TypeError('Scream!');
// we don't want to give user their own audio back
return connections.filter(c => c.userId !== userId);
}
private getOrCreate(channelId: string) {
return this.connections.get(channelId)
?? this.connections
.set(channelId, [])
.get(channelId)!;
}
public add(channelId: string, data: ChannelTypes.VoiceConnection) {
const channelConnections = this.getOrCreate(channelId);
channelConnections.push(data);
this.connections.set(channelId, channelConnections);
@ -14,16 +34,4 @@ export class VoiceService {
channelConnections.splice(index, 1);
this.connections.set(channelId, channelConnections);
}
private getOrCreate(channelId: string) {
return this.connections.get(channelId)
?? this.connections
.set(channelId, [])
.get(channelId)!;
}
}
export interface VoiceData {
userId: string;
stream: any;
}

View File

@ -20,14 +20,13 @@ export default class implements WSEvent<'disconnect'> {
const userId = ws.sessions.get(client.id);
const user = await this.users.getSelf(userId);
try {
await this.channelLeaveEvent.invoke(ws, client);
} catch {}
await this.handleUser(ws, user);
ws.sessions.delete(client.id);
client.rooms.clear();
await this.handleUser(ws, user);
}
public async handleUser(ws: WebSocket, user: SelfUserDocument) {

View File

@ -37,25 +37,26 @@ export default class implements WSEvent<'READY'> {
});
} catch {}
await Promise.all([
this.handleUser(user),
this.rooms.join(client, user),
]);
ws.io
.to(user.guildIds)
.emit('PRESENCE_UPDATE', {
userId,
status: user.status
} as WS.Args.PresenceUpdate);
await this.handleUser(ws, user);
await this.rooms.join(client, user);
ws.io
.to(client.id)
.emit('READY', { user } as WS.Args.Ready);
}
private async handleUser(user: SelfUserDocument) {
private async handleUser(ws: WebSocket, user: SelfUserDocument) {
if (user.status === 'ONLINE') return;
user.status = 'ONLINE';
return await user.save();
await user.save();
ws.io
.to(user.guildIds)
.emit('PRESENCE_UPDATE', {
userId: user.id,
status: user.status
} as WS.Args.PresenceUpdate);
}
}

View File

@ -1,9 +1,7 @@
import { Socket } from 'socket.io';
import Users from '../../data/users';
import { EmailFunctions } from '../../email/email-functions';
import { WS } from '../../types/ws';
import Deps from '../../utils/deps';
import { WSGuard } from '../modules/ws-guard';
import { VoiceService } from '../../voice/voice-service';
import { WebSocket } from '../websocket';
import { WSEvent, } from './ws-event';
@ -11,12 +9,19 @@ export default class implements WSEvent<'VOICE_DATA'> {
on = 'VOICE_DATA' as const;
constructor(
private users = Deps.get<Users>(Users),
private guard = Deps.get<WSGuard>(WSGuard),
private sendEmail = Deps.get<EmailFunctions>(EmailFunctions),
private voiceService = Deps.get<VoiceService>(VoiceService),
) {}
public async invoke(ws: WebSocket, client: Socket, {}: WS.Params.VoiceData) {
client.emit('VOICE_DATA', {} as WS.Args.VoiceData);
public async invoke(ws: WebSocket, client: Socket, { channelId }: WS.Params.VoiceData) {
const userId = ws.sessions.get(client.id);
// receive data
// channel id of voice channel?
// -> if specified in args it can be spoofed
// -> if we constantly get user voice state from db that's very inefficient
// send audio back to client
const connections = this.voiceService.getForUser(channelId, userId);
client.emit('VOICE_DATA', { connections } as WS.Args.VoiceData);
}
}

View File

@ -19,6 +19,7 @@ export type PageWrapperProps = React.DetailedHTMLProps<
const PageWrapper: React.FunctionComponent<PageWrapperProps> = (props) => {
const dispatch = useDispatch();
const dropdown = useSelector((s: Store.AppState) => s.ui.openDropdown);
const devMode = useSelector((s: Store.AppState) => s.config.devMode);
useEffect(() => {
document.title = props.pageTitle ?? 'accord.app';
@ -26,6 +27,14 @@ const PageWrapper: React.FunctionComponent<PageWrapperProps> = (props) => {
const onClick = () => dropdown && dispatch(ui.toggleDropdown({}));
if (!devMode) {
console.log(`%cAttention!`, `color: red; font-size: 32px; font-weight: 900;`);
console.log(
`%cIf someone told you to paste something in this console, it's probably against the TOS and could steal your account.`,
`color: darkred; font-size: 16px; font-weight: 700;`
);
}
return (
<div onClick={onClick}
{...filterProps(props)}>

View File

@ -143,12 +143,16 @@ const WSListener: React.FunctionComponent = () => {
dispatch(users.updated(args));
});
ws.on('VOICE_DATA', (args) => {
//
alert(args);
});
ws.on('VOICE_STATE_UPDATE', (args) => {
const data = { userId: args.userId, partialUser: { voice: args.voice } };
dispatch(auth.updatedUser(data));
dispatch(users.updated(data ));
if (!args.voice.channelId) return;
ws.emit('VOICE_DATA', { channelId: args.voice.channelId })
});
dispatch(meta.listenedToWS());

View File

@ -12,7 +12,7 @@ ws.io.on('open', () => console.log('Connected to WS Server'));
export default ws as WSClient;
interface WSClient {
emit: <K extends keyof WS.To>(event: K, callback: (args: WS.To[K]) => any) => any;
emit: <K extends keyof WS.To>(event: K, args: WS.To[K]) => any;
on: <K extends keyof WS.From>(event: K | 'error' | 'disconnect', callback: (args: WS.From[K]) => any) => any;
off: (event: string, callback?: any) => any;
disconnect: () => any;

4
types/entity.d.ts vendored
View File

@ -90,6 +90,10 @@ declare namespace ChannelTypes {
allow: number;
deny: number;
}
export interface VoiceConnection {
userId: string;
stream: any;
}
}
declare namespace GeneralTypes {

5
types/ws.d.ts vendored
View File

@ -226,6 +226,9 @@ declare namespace WS {
email?: string;
token: string;
}
export interface VoiceData {
channelId: string;
}
}
export namespace Args {
@ -361,7 +364,7 @@ declare namespace WS {
partialUser: Partial<UserTypes.Self>;
}
export interface VoiceData {
connections: VoiceConnection[];
}
export interface VoiceStateUpdate {
userId: string;