Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
sogehige committed May 31, 2024
1 parent 5b490a7 commit 22a10d5
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 76 deletions.
4 changes: 0 additions & 4 deletions d.ts/src/helpers/socket.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,6 @@ export type ClientToServerEventsWithNamespace = {
'stop.import': () => void,
'next': () => void,
},
'/core/tts': GenericEvents & {
'speak': (opts: { service: TTSService, text: string, key: string, voice: string; volume: number; rate: number; pitch: number; triggerTTSByHighlightedMessage?: boolean; } |
{ service: TTSService.ELEVENLABS, text: string, key: string, voice: string; volume: number; clarity: number; stability: number; exaggeration: number; triggerTTSByHighlightedMessage?: boolean; }, cb: (error: Error | string | null | unknown, b64mp3?: string) => void) => void,
},
'/core/ui': GenericEvents & {
'configuration': (cb: (error: Error | string | null | unknown, data?: Configuration) => void) => void,
},
Expand Down
13 changes: 9 additions & 4 deletions src/decorators/endpoint.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ZodError, ZodObject } from 'zod';
import { ZodError, ZodTypeAny } from 'zod';

import { getNameAndTypeFromStackTrace } from '~/decorators.js';
import { isBotStarted } from '~/helpers/database.js';
Expand All @@ -11,13 +11,15 @@ const registeredEndpoint: {
[endpoint: string]: {
[action: string]: {
fnc?: (req?: any) => Promise<any>,
zodValidator: ZodObject<any> | undefined,
zodValidator: ZodTypeAny | undefined,
},
}
} = {};

export function Post<T extends string>(endpoint: T, params: {
customEndpoint?: string, zodValidator?: ZodObject<any>, action?: string, isSensitive?: boolean
/** public or manage (you cannot mismatch different scope, if it is public, you need to handle auth yourself) */
scope?: 'public' | 'manage',
customEndpoint?: string, zodValidator?: ZodTypeAny, action?: string, isSensitive?: boolean
} = {}) {
const { name, type } = getNameAndTypeFromStackTrace();

Expand Down Expand Up @@ -61,7 +63,10 @@ export function Post<T extends string>(endpoint: T, params: {
}

// change scopes to sensitive if we are handling logins or sensitive data endpoints
const scopes = params.isSensitive ? [self.scope('sensitive')] : [self.scope('manage')];
const scopes
= params.scope === 'public'
? []
: params.isSensitive ? [self.scope('sensitive')] : [self.scope('manage')];
if (params.isSensitive) {
// add sensitive scope
if (type === 'integrations' || type === 'services') {
Expand Down
12 changes: 6 additions & 6 deletions src/helpers/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,10 @@ const initEndpoints = (socket: Socket, privileges: Unpacked<ReturnType<typeof ge
}
};

function endpoint<K0 extends keyof O, K1 extends keyof O[K0], O extends Record<PropertyKey, Record<PropertyKey, Fn>> = ClientToServerEventsWithNamespace>(allowedScopes: string[], nsp: K0, on: K1, callback: (...args: NestedFnParams<O, K0, K1>) => void): void {
if (!newEndpoints.find(o => isEqual(o.scopes, allowedScopes) && o.nsp === nsp && o.on === on)) {
function endpoint<K0 extends keyof O, K1 extends keyof O[K0], O extends Record<PropertyKey, Record<PropertyKey, Fn>> = ClientToServerEventsWithNamespace>(requiredScopes: string[], nsp: K0, on: K1, callback: (...args: NestedFnParams<O, K0, K1>) => void): void {
if (!newEndpoints.find(o => isEqual(o.scopes, requiredScopes) && o.nsp === nsp && o.on === on)) {
newEndpoints.push({
scopes: allowedScopes, nsp, on, callback,
scopes: requiredScopes, nsp, on, callback,
});
}
}
Expand All @@ -137,15 +137,15 @@ const viewerEndpoint = (nsp: string, on: string, callback: (opts: any, cb: (erro
}
};

const withScope = (allowedScopes: string[], isPublic: boolean = false) => {
const withScope = (requiredScopes: string[], isPublic: boolean = false) => {
return async (req: { headers: { [x: string]: any; }; }, res: { sendStatus: (arg0: number) => any; }, next: () => void) => {
const authHeader = req.headers.authorization;
const authToken = authHeader && authHeader.split(' ')[1];
try {

const socket = (await import('../socket.js')).default;

if (authToken === socket.socketToken || isPublic) {
if (authToken === socket.socketToken || isPublic || requiredScopes.length === 0) {
return next();
}

Expand All @@ -162,7 +162,7 @@ const withScope = (allowedScopes: string[], isPublic: boolean = false) => {
req.headers.scopes = token.privileges.scopes.sort();
req.headers.authUser = { userId: token.userId, userName: token.userName };

for (const allowed of allowedScopes) {
for (const allowed of requiredScopes) {
// allow manage also if read is allowed
if (allowed.includes(':read')) {
if (token.privileges.scopes.includes(allowed.replace(':read', ':manage'))) {
Expand Down
4 changes: 2 additions & 2 deletions src/registries/randomizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ class Randomizer extends Registry {
return RandomizerEntity.find();
}

@Get('/visible')
@Get('/visible', { scope: 'public' })
async getVisible () {
return RandomizerEntity.findOneBy({ isShown: true });
}

@Get('/:id')
@Get('/:id', { scope: 'public' })
async getOne (req: Request) {
return RandomizerEntity.findOneBy({ id: req.params.id });
}
Expand Down
108 changes: 49 additions & 59 deletions src/tts.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { randomUUID } from 'crypto';

import axios from 'axios';
import { Request } from 'express';
import { JWT } from 'google-auth-library';
import { google } from 'googleapis';
import { z } from 'zod';

import { TTSService } from './database/entity/overlay.js';
import { Post } from './decorators/endpoint.js';
import { MINUTE } from './helpers/constants.js';

import Core from '~/_interface.js';
Expand All @@ -17,7 +20,6 @@ import {
} from '~/decorators/on.js';
import { settings } from '~/decorators.js';
import { error, info, warning } from '~/helpers/log.js';
import { adminEndpoint, endpoint } from '~/helpers/socket.js';

/* secureKeys are used to authenticate use of public overlay endpoint */
const secureKeys = new Set<string>();
Expand Down Expand Up @@ -54,67 +56,55 @@ class TTS extends Core {
this.initializeTTSServices(); // reset settings
}

sockets() {
adminEndpoint('/core/tts', 'settings.refresh', async () => {
this.initializeTTSServices(); // reset settings
});

endpoint([], '/core/tts', 'speak', async (opts, cb) => {
if (secureKeys.has(opts.key)) {
secureKeys.delete(opts.key);
if (opts.service === TTSService.ELEVENLABS) {
const audioContent = await this.elevenlabsSpeak(opts as any);

if (!audioContent) {
throw new Error('Something went wrong');
}
if (cb) {
cb(null, audioContent);
}
} else if (opts.service === TTSService.GOOGLE) {
const audioContent = await this.googleSpeak(opts);

if (!audioContent) {
throw new Error('Something went wrong');
}
if (cb) {
cb(null, audioContent);
}
} else {
throw new Error('Invalid service.');
}
} else {
cb(new Error('Invalid auth.'));
@Post('/speak', {
scope: 'public',
zodValidator: z.union([
z.object({
key: z.string(),
service: z.literal(TTSService.ELEVENLABS),
voice: z.string(),
text: z.string(),
clarity: z.number(),
stability: z.number(),
exaggeration: z.number(),
triggerTTSByHighlightedMessage: z.boolean().optional(),
}),
z.object({
key: z.string(),
service: z.nativeEnum(TTSService),
voice: z.string(),
text: z.string(),
volume: z.number(),
pitch: z.number(),
rate: z.number(),
triggerTTSByHighlightedMessage: z.boolean().optional(),
}),
]),
})
async speak(req: Request) {
// public endpoint
const { key, service, ...opts } = req.body;
if (secureKeys.has(key) || req.headers.authUser) {
if (!req.headers.authUser) {
secureKeys.delete(key);
}
});

adminEndpoint('/core/tts', 'speak', async (opts, cb) => {
try {
if (opts.service === TTSService.ELEVENLABS) {
const audioContent = await this.elevenlabsSpeak(opts as any);

if (!audioContent) {
throw new Error('Something went wrong');
}
if (cb) {
cb(null, audioContent);
}
} else if (opts.service === TTSService.GOOGLE) {
const audioContent = await this.googleSpeak(opts);

if (!audioContent) {
throw new Error('Something went wrong');
}
if (cb) {
cb(null, audioContent);
}
} else {
throw new Error('Invalid service.');
const speakFunctions = {
[TTSService.ELEVENLABS]: this.elevenlabsSpeak,
[TTSService.GOOGLE]: this.googleSpeak,
};

if (Object.keys(speakFunctions).includes(service)) {
const audioContent = await speakFunctions[service as keyof typeof speakFunctions](opts as any);
if (!audioContent) {
new Error('Something went wrong');
}
} catch (e) {
cb(e);
return audioContent;
} else {
new Error('Invalid service.');
}
});
} else {
new Error('Invalid auth.');
}
}

initializedGoogleTTSHash: string | null = null;
Expand Down
2 changes: 1 addition & 1 deletion src/widgets/eventlist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class EventList extends Widget {

@Post('/:id', { action: 'resend' })
async resend(req: Request) {
const id = req.body.id;
const id = req.params.id;
const event = await AppDataSource.getRepository(EventListDB).findOneBy({ id: String(id) });
if (event) {
const values = JSON.parse(event.values_json);
Expand Down

0 comments on commit 22a10d5

Please sign in to comment.