From cc276486f0360eb3017e1d55f0d3dd9b2d3a2228 Mon Sep 17 00:00:00 2001 From: arsereg Date: Wed, 3 Aug 2022 09:11:55 -0400 Subject: [PATCH] Updated Tenor API to v2 (#2418) refs: https://github.com/TryGhost/Ghost/issues/14980 refs: https://github.com/TryGhost/Ghost/pull/15087 - The Tenor v1 API has been decommissioned https://developers.google.com/tenor/guides/migrate-from-v1 - Updated the API to v2, but there are some differences we have to account for - Swapped from using the old "trending" API to the new "featured" API, which at present seem to be the same thing - Added a new client_key, which identifies the integration using the google API key, as google API keys can be used for multiple APIs and projects - Fixed up the error handling to support Google's error format, and also caught and replaced the error that everyone with old keys will see to make it clearer. This includes adding an htmlError property so that we can output HTML safely in the frontend. There is still an active TODO with the naming of the config key, but we will resolve this after merging admin into the monorepo. Co-authored-by: Hannah Wolfe --- ghost/admin/app/services/tenor.js | 26 +++++++++++++------ .../koenig-card-image/selector-tenor.hbs | 4 ++- .../koenig-card-image/selector-tenor.js | 2 +- .../koenig-card-image/selector-tenor/gif.js | 2 +- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/ghost/admin/app/services/tenor.js b/ghost/admin/app/services/tenor.js index fb4405fbc2..c7bb25325f 100644 --- a/ghost/admin/app/services/tenor.js +++ b/ghost/admin/app/services/tenor.js @@ -6,8 +6,8 @@ import {isEmpty} from '@ember/utils'; import {task, taskGroup, timeout} from 'ember-concurrency'; import {tracked} from '@glimmer/tracking'; -const API_URL = 'https://g1.tenor.com'; -const API_VERSION = 'v1'; +const API_URL = 'https://tenor.googleapis.com'; +const API_VERSION = 'v2'; const DEBOUNCE_MS = 600; export default class TenorService extends Service { @@ -16,15 +16,17 @@ export default class TenorService extends Service { @tracked columnCount = 4; @tracked columns = null; @tracked error = null; + @tracked htmlError = null; @tracked gifs = new TrackedArray([]); @tracked searchTerm = ''; - @tracked loadedType = 'trending'; + @tracked loadedType = ''; _columnHeights = []; _nextPos = null; get apiKey() { - return this.config.get('tenor.publicReadOnlyApiKey'); + // @TODO confirm this! + return this.config.get('tenor.apiKey'); } get contentfilter() { @@ -94,9 +96,10 @@ export default class TenorService extends Service { @task({group: 'loadingTasks'}) *loadTrendingTask() { - this.loadedType = 'trending'; + this.loadedType = 'featured'; yield this._makeRequest(this.loadedType, {params: { + q: 'excited', media_filter: 'minimal' }}); } @@ -134,6 +137,7 @@ export default class TenorService extends Service { const params = new URLSearchParams(options.params); params.set('key', this.apiKey); + params.set('client_key', 'ghost-editor'); params.set('contentfilter', this.contentfilter); url.search = params.toString(); @@ -153,6 +157,12 @@ export default class TenorService extends Service { if (!options.ignoreErrors && !this.error) { this.error = 'Uh-oh! Trouble reaching the Tenor API, please check your connection'; } + + if (this.error && this.error.startsWith('API key not valid')) { + // Added an html error field, so that we don't pass raw API errors from tenor to triple-braces in the frontend + this.htmlError = `This version of the Tenor API is no longer supported. Please update your API key by following our + documentation here.
`; + } console.error(e); // eslint-disable-line }); } @@ -165,8 +175,8 @@ export default class TenorService extends Service { let responseText; - if (response.headers.map['content-type'] === 'application/json') { - responseText = await response.json().then(json => json.errors[0]); + if (response.headers.map['content-type'].startsWith('application/json')) { + responseText = await response.json().then(json => json.error.message || json.error); } else if (response.headers.map['content-type'] === 'text/xml') { responseText = await response.text(); } @@ -192,7 +202,7 @@ export default class TenorService extends Service { _addGif(gif) { // re-calculate ratio for later use - const [width, height] = gif.media[0].tinygif.dims; + const [width, height] = gif.media_formats.tinygif.dims; gif.ratio = height / width; // add to general gifs list diff --git a/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image/selector-tenor.hbs b/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image/selector-tenor.hbs index d63f2c8e4b..00a323d56b 100644 --- a/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image/selector-tenor.hbs +++ b/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image/selector-tenor.hbs @@ -53,7 +53,9 @@
Network error -

{{this.tenor.error}} (retry)

+ {{!-- template-lint-disable no-triple-curlies --}} +

{{#if this.tenor.htmlError}}{{{this.tenor.htmlError}}}{{else}}{{this.tenor.error}}{{/if}} (retry)

+ {{!-- template-lint-enable no-triple-curlies --}}
{{/if}} diff --git a/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image/selector-tenor.js b/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image/selector-tenor.js index 10e1ceae1b..220586d49b 100644 --- a/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image/selector-tenor.js +++ b/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image/selector-tenor.js @@ -58,7 +58,7 @@ export default class KoenigCardImageTenorSelector extends Component { event?.preventDefault(); event?.stopPropagation(); - const media = gif.media[0].gif; + const media = gif.media_formats.gif; const payload = { src: media.url, diff --git a/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image/selector-tenor/gif.js b/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image/selector-tenor/gif.js index 3947694a6d..328bee044c 100644 --- a/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image/selector-tenor/gif.js +++ b/ghost/admin/lib/koenig-editor/addon/components/koenig-card-image/selector-tenor/gif.js @@ -3,7 +3,7 @@ import {htmlSafe} from '@ember/template'; export default class GhTenorGifComponent extends Component { get media() { - return this.args.gif.media[0].tinygif; + return this.args.gif.media_formats.tinygif; } get imageUrl() {