diff --git a/packages/api/src/routers/svc/text_to_speech.ts b/packages/api/src/routers/svc/text_to_speech.ts index 8f597c652..61098e86f 100644 --- a/packages/api/src/routers/svc/text_to_speech.ts +++ b/packages/api/src/routers/svc/text_to_speech.ts @@ -9,11 +9,7 @@ import { getPageById } from '../../elastic/pages' import { Speech, SpeechState } from '../../entity/speech' import { buildLogger } from '../../utils/logger' import { getClaimsByToken } from '../../utils/auth' -import { - setSpeechFailure, - shouldSynthesize, - synthesize, -} from '../../services/speech' +import { shouldSynthesize, synthesize } from '../../services/speech' import { readPushSubscription } from '../../datalayer/pubsub' const logger = buildLogger('app.dispatch') @@ -79,58 +75,41 @@ export function speechServiceRouter() { router.options('/', cors({ ...corsConfig, maxAge: 600 })) // eslint-disable-next-line @typescript-eslint/no-misused-promises router.post('/', async (req, res) => { - logger.info('Synthesize svc request', { + logger.info('Updating speech', { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment body: req.body, }) + let userId: string const token = req.query.token as string try { - if (!(await getClaimsByToken(token))) { + const claims = await getClaimsByToken(token) + if (!claims) { logger.info('Unauthorized request', { token }) - return res.status(200).send('UNAUTHORIZED') + return res.status(401).send('UNAUTHORIZED') } + userId = claims.uid } catch (error) { logger.error('Unauthorized request', { token, error }) - return res.status(200).send('UNAUTHORIZED') + return res.status(401).send('UNAUTHORIZED') } - const { userId, speechId } = req.body as { - userId: string + const { speechId, audioFileName, speechMarksFileName } = req.body as { speechId: string + audioFileName: string + speechMarksFileName: string } - if (!userId || !speechId) { - return res.status(200).send('Invalid data') + if (!speechId || !audioFileName || !speechMarksFileName) { + return res.status(400).send('Invalid data') } - logger.info(`Create article speech`, { - body: { - userId, - speechId, - }, - labels: { - source: 'CreateArticleSpeech', - }, + // set state to completed + await getRepository(Speech).update(speechId, { + audioFileName: audioFileName, + speechMarksFileName: speechMarksFileName, + state: SpeechState.COMPLETED, }) - const speech = await getRepository(Speech).findOneBy({ - id: speechId, - user: { id: userId }, - }) - if (!speech) { - return res.status(200).send('Speech not found') - } - const page = await getPageById(speech.elasticPageId) - if (!page) { - await setSpeechFailure(speech.id) - return res.status(200).send('Page not found') - } - - try { - await synthesize(page, speech) - } catch (error) { - logger.error(`Error synthesizing article`, { error }) - res.status(500).send('Error synthesizing article') - } + res.send('OK') }) return router diff --git a/packages/text-to-speech/package.json b/packages/text-to-speech/package.json index 14ccdd9e3..3e3901bc4 100644 --- a/packages/text-to-speech/package.json +++ b/packages/text-to-speech/package.json @@ -25,7 +25,6 @@ }, "dependencies": { "@google-cloud/functions-framework": "3.1.2", - "@google-cloud/pubsub": "^2.18.4", "@google-cloud/storage": "^6.4.1", "@sentry/serverless": "^6.16.1", "axios": "^0.27.2", diff --git a/packages/text-to-speech/src/index.ts b/packages/text-to-speech/src/index.ts index b10172f92..ec3f8403a 100644 --- a/packages/text-to-speech/src/index.ts +++ b/packages/text-to-speech/src/index.ts @@ -15,7 +15,8 @@ import { SpeechSynthesisResult, SpeechSynthesizer, } from 'microsoft-cognitiveservices-speech-sdk' -import { PubSub } from '@google-cloud/pubsub' +import axios from 'axios' +import * as jwt from 'jsonwebtoken' interface TextToSpeechInput { id: string @@ -43,8 +44,6 @@ interface SpeechMark { } const storage = new Storage() -const pubsub = new PubSub() -const SPEECH_UPDATE_TOPIC = 'speech-update' const uploadToBucket = async ( filePath: string, @@ -59,18 +58,25 @@ const createGCSFile = (bucket: string, filename: string): File => { return storage.bucket(bucket).file(filename) } -const updateSpeech = ( +const updateSpeech = async ( speechId: string, audioFileName: string, - speechMarksFileName: string -): Promise => { - return pubsub - .topic(SPEECH_UPDATE_TOPIC) - .publishMessage({ json: { speechId, audioFileName, speechMarksFileName } }) - .catch((err) => { - console.error('error publishing speech update:', err) - return undefined - }) + speechMarksFileName: string, + token: string +): Promise => { + if (!process.env.REST_BACKEND_ENDPOINT) { + throw new Error('backend rest api endpoint not exists') + } + const response = await axios.post( + `${process.env.REST_BACKEND_ENDPOINT}/svc/text-to-speech?token=${token}`, + { + speechId, + audioFileName, + speechMarksFileName, + } + ) + + return response.status === 200 } const synthesizeTextToSpeech = async ( @@ -375,17 +381,29 @@ const htmlElementToSsml = ({ export const textToSpeechHandler = Sentry.GCPFunction.wrapHttpFunction( async (req, res) => { console.debug('New text to speech request', req) + const token = req.query.token as string + if (!process.env.JWT_SECRET) { + console.error('JWT_SECRET not exists') + return res.status(500).send('JWT_SECRET not exists') + } + try { + jwt.verify(token, process.env.JWT_SECRET) + } catch (e) { + console.error(e) + return res.status(200).send('UNAUTHENTICATED') + } const input = req.body as TextToSpeechInput const { audioFileName, speechMarksFileName } = await synthesizeTextToSpeech( input ) - const result = await updateSpeech( + const updated = await updateSpeech( input.id, audioFileName, - speechMarksFileName + speechMarksFileName, + token ) - if (!result) { + if (!updated) { return res.status(500).send('Failed to update speech') } res.send('OK')