diff --git a/plugins/talk-plugin-toxic-comments/server/config.js b/plugins/talk-plugin-toxic-comments/server/config.js index 67155cd45..bc7ddf138 100644 --- a/plugins/talk-plugin-toxic-comments/server/config.js +++ b/plugins/talk-plugin-toxic-comments/server/config.js @@ -1,5 +1,12 @@ -module.exports = { - API_ENDPOINT: 'https://commentanalyzer.googleapis.com/v1alpha1', - API_KEY: process.env.NODE_ENV !== 'test' ? process.env.TALK_PERSPECTIVE_API_KEY : '', - TOXICITY_THRESHOLD: process.env.TALK_TOXICITY_THRESHOLD || 0.8, +const config = { + API_ENDPOINT: process.env.TALK_PERSPECTIVE_API_ENDPOINT || 'https://commentanalyzer.googleapis.com/v1alpha1', + API_KEY: process.env.TALK_PERSPECTIVE_API_KEY, + THRESHOLD: process.env.TALK_TOXICITY_THRESHOLD || 0.8, + API_TIMEOUT: process.env.TALK_PERSPECTIVE_TIMEOUT || 300, }; + +if (process.env.NODE_ENV !== 'test' && !config.API_KEY) { + throw new Error('Please set the TALK_PERSPECTIVE_API_KEY environment variable to use the toxic-comments plugin. Visit https://www.perspectiveapi.com/ to request API access.'); +} + +module.exports = config; diff --git a/plugins/talk-plugin-toxic-comments/server/hooks.js b/plugins/talk-plugin-toxic-comments/server/hooks.js index 32f61b905..7fd138641 100644 --- a/plugins/talk-plugin-toxic-comments/server/hooks.js +++ b/plugins/talk-plugin-toxic-comments/server/hooks.js @@ -12,8 +12,19 @@ module.exports = { createComment: { async pre(_, {input}, _context, _info) { - // TODO: handle timeouts. - const scores = await getScores(input.body); + let scores; + + // Try getting scores. + try { + scores = await getScores(input.body); + } + catch(err) { + + // Warn and let mutation pass. + console.trace(err); + return; + } + const commentIsToxic = isToxic(scores); if (input.checkToxicity && commentIsToxic) { @@ -32,7 +43,8 @@ module.exports = { } }, async post(_, _input, _context, _info, result) { - if (isToxic(result.comment.metadata.perspective)) { + const metadata = result.comment.metadata; + if (metadata.perspective && isToxic(metadata.perspective)) { // TODO: this is kind of fragile, we should refactor this to resolve // all these const's that we're using like 'COMMENTS', 'FLAG' to be diff --git a/plugins/talk-plugin-toxic-comments/server/perspective.js b/plugins/talk-plugin-toxic-comments/server/perspective.js index 0b5cd6b05..fba81b3d2 100644 --- a/plugins/talk-plugin-toxic-comments/server/perspective.js +++ b/plugins/talk-plugin-toxic-comments/server/perspective.js @@ -1,5 +1,5 @@ const fetch = require('node-fetch'); -const {API_ENDPOINT, API_KEY, TOXICITY_THRESHOLD} = require ('./config'); +const {API_ENDPOINT, API_KEY, THRESHOLD, API_TIMEOUT} = require('./config'); /** * Get scores from the perspective api @@ -12,6 +12,7 @@ async function getScores(text) { headers: { 'Content-Type': 'application/json', }, + timeout: API_TIMEOUT, body: JSON.stringify({ comment: { text, @@ -54,11 +55,31 @@ function isToxic(scoresOrProbability) { const probability = typeof scoresOrProbability === 'object' ? getProbability(scoresOrProbability) : scoresOrProbability; - return probability > TOXICITY_THRESHOLD; + return probability > THRESHOLD; +} + +/** + * maskKeyInError is a decorator that calls fn and masks the + * API_KEY in errors before throwing. + * @param {function} fn Function that returns a Promise + * @return {function} decorated function + */ +function maskKeyInError(fn) { + return async (...args) => { + try { + return await fn(...args); + } + catch(err) { + if (err.message) { + err.message = err.message.replace(API_KEY, '***'); + } + throw err; + } + }; } module.exports = { - getScores, + getScores: maskKeyInError(getScores), getProbability, isToxic, };