Fix Presences
This commit is contained in:
parent
ce60f51034
commit
106f61f881
@ -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;
|
||||
}
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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)}>
|
||||
|
@ -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());
|
||||
|
@ -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
4
types/entity.d.ts
vendored
@ -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
5
types/ws.d.ts
vendored
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user