mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Add /:id/mp3 router to redirect request to speech MP3 URL
This commit is contained in:
parent
c74f2bc3fd
commit
301746d494
3 changed files with 60 additions and 10 deletions
|
|
@ -3,15 +3,20 @@
|
|||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import express from 'express'
|
||||
import { CreateArticleErrorCode } from './../generated/graphql'
|
||||
import { isSiteBlockedForParse } from './../utils/blocked'
|
||||
import { CreateArticleErrorCode } from '../generated/graphql'
|
||||
import { isSiteBlockedForParse } from '../utils/blocked'
|
||||
import cors from 'cors'
|
||||
import { buildLogger } from './../utils/logger'
|
||||
import { buildLogger } from '../utils/logger'
|
||||
import { corsConfig } from '../utils/corsConfig'
|
||||
import { createPageSaveRequest } from '../services/create_page_save_request'
|
||||
import { initModels } from '../server'
|
||||
import { kx } from '../datalayer/knex_config'
|
||||
import { getClaimsByToken } from '../utils/auth'
|
||||
import * as jwt from 'jsonwebtoken'
|
||||
import { env } from '../env'
|
||||
import { Claims } from '../resolvers/types'
|
||||
import { getRepository } from '../entity/utils'
|
||||
import { Speech } from '../entity/speech'
|
||||
|
||||
const logger = buildLogger('app.dispatch')
|
||||
|
||||
|
|
@ -61,5 +66,40 @@ export function articleRouter() {
|
|||
articleSavingRequestId: result.id,
|
||||
})
|
||||
})
|
||||
|
||||
router.get(
|
||||
'/:id/mp3',
|
||||
cors<express.Request>(corsConfig),
|
||||
async (req, res) => {
|
||||
const id = req.params.id
|
||||
const token = req.cookies?.auth || req.headers?.authorization
|
||||
if (!token || !jwt.verify(token, env.server.jwtSecret)) {
|
||||
return res.status(401).send({ errorCode: 'UNAUTHORIZED' })
|
||||
}
|
||||
const { uid } = jwt.decode(token) as Claims
|
||||
|
||||
logger.info('Get article speech in mp3 format', {
|
||||
params: req.params,
|
||||
labels: {
|
||||
userId: uid,
|
||||
source: 'GetArticleSpeechMp3',
|
||||
articleId: id,
|
||||
},
|
||||
})
|
||||
|
||||
const speech = await getRepository(Speech).findOneBy({
|
||||
elasticPageId: id,
|
||||
user: { id: uid },
|
||||
})
|
||||
|
||||
if (!speech) {
|
||||
return res.status(404).send({ errorCode: 'NOT_FOUND' })
|
||||
}
|
||||
|
||||
logger.info('Found speech mp3', { audioUrl: speech.audioUrl })
|
||||
res.redirect(speech.audioUrl)
|
||||
}
|
||||
)
|
||||
|
||||
return router
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,19 +6,20 @@ import { User } from '../../entity/user'
|
|||
import { getPageById } from '../../elastic/pages'
|
||||
import { synthesizeTextToSpeech } from '../../utils/textToSpeech'
|
||||
import { Speech } from '../../entity/speech'
|
||||
import { parseHTML } from 'linkedom'
|
||||
|
||||
export function textToSpeechServiceRouter() {
|
||||
export function speechServiceRouter() {
|
||||
const router = express.Router()
|
||||
|
||||
router.options('/', cors<express.Request>({ ...corsConfig, maxAge: 600 }))
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
router.post('/', async (req, res) => {
|
||||
const { userId, pageId, text } = req.body as {
|
||||
const { userId, pageId } = req.body as {
|
||||
userId: string
|
||||
pageId: string
|
||||
text: string
|
||||
}
|
||||
|
||||
if (!userId || !pageId || !text) {
|
||||
if (!userId || !pageId) {
|
||||
return res.status(200).send('Invalid data')
|
||||
}
|
||||
|
||||
|
|
@ -35,7 +36,12 @@ export function textToSpeechServiceRouter() {
|
|||
return res.status(200).send('Page not found')
|
||||
}
|
||||
|
||||
const audioAndSpeechMarks = await synthesizeTextToSpeech({
|
||||
const text = parseHTML(page.content).document.textContent
|
||||
if (!text) {
|
||||
return res.status(200).send('Page has no text')
|
||||
}
|
||||
|
||||
const speech = await synthesizeTextToSpeech({
|
||||
id: pageId,
|
||||
text,
|
||||
languageCode: page.language,
|
||||
|
|
@ -44,11 +50,13 @@ export function textToSpeechServiceRouter() {
|
|||
|
||||
await getRepository(Speech).save({
|
||||
elasticPageId: pageId,
|
||||
audioUrl: audioAndSpeechMarks.audioUrl,
|
||||
speechMarks: JSON.stringify(audioAndSpeechMarks.speechMarks),
|
||||
audioUrl: speech.audioUrl,
|
||||
speechMarks: JSON.stringify(speech.speechMarks),
|
||||
user,
|
||||
})
|
||||
|
||||
res.status(200).send('OK')
|
||||
})
|
||||
|
||||
return router
|
||||
}
|
||||
|
|
@ -45,6 +45,7 @@ import { uploadServiceRouter } from './routers/svc/upload'
|
|||
import rateLimit from 'express-rate-limit'
|
||||
import { webhooksServiceRouter } from './routers/svc/webhooks'
|
||||
import { integrationsServiceRouter } from './routers/svc/integrations'
|
||||
import { speechServiceRouter } from './routers/svc/speech'
|
||||
|
||||
const PORT = process.env.PORT || 4000
|
||||
|
||||
|
|
@ -119,6 +120,7 @@ export const createApp = (): {
|
|||
app.use('/svc/pubsub/integrations', integrationsServiceRouter())
|
||||
app.use('/svc/reminders', remindersServiceRouter())
|
||||
app.use('/svc/pdf-attachments', pdfAttachmentsRouter())
|
||||
app.use('/svc/speech', speechServiceRouter())
|
||||
|
||||
if (env.dev.isLocal) {
|
||||
app.use('/local/debug', localDebugRouter())
|
||||
|
|
|
|||
Loading…
Reference in a new issue