diff --git a/command/CommandController.js b/command/CommandController.js index 754f602..5cbf466 100644 --- a/command/CommandController.js +++ b/command/CommandController.js @@ -286,6 +286,140 @@ router.post('/articleservice', VerifyToken, async function(req, res) { res.status(404).send(JSON.stringify({ speech: errSpeech })); } }); +router.post('/webpage', VerifyToken, async function(req, res) { + logger.info(`POST /webpage: ${req.body.url} `); + logMetric('webpage', req.body.url, req.get('User-Agent')); + res.setHeader('Content-Type', 'application/json'); + + try { + let version = req.body.v ? req.body.v : 1; + logger.debug('/webpage version is: ' + version); + + logger.debug(req.body); + //Use the Pocket service to get the resolved id. + logger.debug('URL is: ' + req.body.url); + let article = await getPocketArticleTextFromUrl(req.body.url); + // Make sure it's an article + if (article && article.isArticle && article.isArticle == 1) { + let mData = await getArticleMetadata(article, 1); + console.log('METADATA FUNCTION IS: ' + mData); + console.log('METADATA FUNCTION IS: ' + JSON.stringify(mData)); + + let mobileMetadata = await audioHelper.getMobileFileMetadata( + article.resolved_id, + req.body.locale + ); + // Do we have the article cached? + if (mobileMetadata && mobileMetadata.length > 0) { + // We have already processed this article + logger.debug( + `Found file(s) in the database for ${article.resolved_id}` + ); + let response = await buildPocketResponseFromMetadata( + mobileMetadata, + version + ); + mData.audio_url = response.url; + res.status(200).send(JSON.stringify(mData)); + } else { + let voice = vc.findVoice(article.lang, req.body.locale); + if (voice.main && voice.meta) { + let articleFile = await createAudioFileFromText( + `${article.article}`, + voice.main + ); + + // Extract the publisher's name if available. + let publisher = + article.domainMetadata && article.domainMetadata.name + ? article.domainMetadata.name + : article.host; + + let introFile = await createAudioFileFromText( + await buildIntro( + article.resolvedUrl, + article.title, + article.lang, + article.timePublished, + publisher + ), + voice.meta + ); + let audioMetadata = await buildPocketAudio( + introFile, + articleFile, + article.resolved_id, + req.body.locale + ); + // Add the correct voice: + audioMetadata['voice'] = voice.main; + + logger.debug('Calling StoreMobileLocation: ' + audioMetadata.url); + await audioHelper.storeMobileLocation( + article.resolved_id, + article.lang, + voice.main, + audioMetadata, + voice.localeSynthesis + ); + + // Re-query the metadata for new file info + mobileMetadata = await audioHelper.getMobileMetadataForLocale( + article.resolved_id, + voice.localeSynthesis + ); + logger.debug('mobilemetadata is: ' + mobileMetadata); + let response = await buildPocketResponseFromMetadata( + mobileMetadata, + version + ); + mData.audio_url = response.url; + + // Send it back to the mobile as quick as possible. + res.status(200).send(JSON.stringify(mData)); + + // Upload the individual parts for use by Alexa later & cleanup. + let introUrl = await polly_tts.postProcessPart(introFile); + let articleUrl = await polly_tts.postProcessPart(articleFile); + await audioHelper.storeIntroLocation( + article.resolved_id, + introUrl, + voice.meta, + false, + article.lang, + voice.localeSynthesis + ); + await audioHelper.storeAudioFileLocation( + article.resolved_id, + false, + voice.main, + articleUrl, + article.lang, + voice.localeSynthesis + ); + } else { + logger.error('No language found for article:' + req.body.url); + res.status(404).send( + JSON.stringify({ + speech: `There was an error processing the article. No language` + }) + ); + } + } + } else { + logger.error('Not an article: ' + req.body.url); + res.status(404).send( + JSON.stringify({ + speech: `There was an error processing the article. Not an article` + }) + ); + } + } catch (reason) { + logger.error('Error in /webpage ' + reason); + const errSpeech = `There was an error processing the article. ${reason}`; + res.status(404).send(JSON.stringify({ speech: errSpeech })); + } +}); // Request body parameters: // url: article url @@ -333,7 +467,7 @@ router.get('/search', VerifyToken, async function(req, res) { function logMetric(cmd, userid, agent) { if (process.env.GA_PROPERTY_ID) { - logger.info('User-Agent is: ' + agent); + logger.info('User-Agent is : ' + agent); var visitor = ua(process.env.GA_PROPERTY_ID, userid); var ga_params = { ec: cmd, @@ -599,7 +733,9 @@ async function scoutTitles(userid, res, extendedData) { async function getArticleMetadata(pocketArticle, extendedData) { const wordsPerMinute = 155; let lengthMinutes; - const wordCount = pocketArticle.word_count; + const wordCount = pocketArticle.word_count + ? pocketArticle.word_count + : pocketArticle.wordCount; if (wordCount) { lengthMinutes = Math.floor(parseInt(wordCount, 10) / wordsPerMinute); } @@ -614,18 +750,26 @@ async function getArticleMetadata(pocketArticle, extendedData) { item_id: pocketArticle.item_id, sort_id: pocketArticle.sort_id, resolved_url: pocketArticle.resolved_url, - title: pocketArticle.resolved_title, + title: pocketArticle.resolved_title + ? pocketArticle.resolved_title + : pocketArticle.title, author, lengthMinutes, length_minutes: lengthMinutes, - imageURL: pocketArticle.top_image_url, + imageURL: pocketArticle.top_image_url + ? pocketArticle.top_image_url + : pocketArticle.topImageUrl, image_url: pocketArticle.top_image_url + ? pocketArticle.top_image_url + : pocketArticle.topImageUrl }; if (extendedData) { try { const faviconData = await hostnameHelper.getHostnameData( pocketArticle.resolved_url + ? pocketArticle.resolved_url + : pocketArticle.resolvedUrl ); result.publisher = faviconData.publisher_name; result.icon_url = faviconData.favicon_url;