diff --git a/README.md b/README.md index 1b762df..e2ca055 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ Extract eEmbed content from given URL. - [Changes with Instagram](#changes-with-instagram) - ## Demo - [Give it a try!](https://ndaidong.github.io/oembed-parser-demo) @@ -77,6 +76,29 @@ console.log(data) Return boolean. True if the URL matches with any provider in the list. +#### .findProvider(String URL) + +Return provider which is relevant to given URL. + +For example: + +```js +import { + findProvider +} from 'oembed-parser' + +findProvider('https://www.facebook.com/video.php?v=999999999') + +// get something like below: + +// { +// fetchEndpoint: 'https://graph.facebook.com/v10.0/oembed_video', +// providerName: 'Facebook', +// providerUrl: 'https://www.facebook.com/' +// } +``` + + #### .setProviderList(Array of provider definitions) Sets the list of providers to use, overriding the defaults. @@ -93,17 +115,17 @@ For the expected format, see the List of resource providers is a clone of [oembed.com](http://oembed.com/providers.json) and available [here](https://raw.githubusercontent.com/ndaidong/oembed-parser/master/src/utils/providers.json). -## Changes with Instagram +## Facebook and Instagram -Since October 24 2020, Facebook have deprecated their legacy urls and applied a new Facebook oEmbed endpoints. Please update your `oembed-parser` version to v1.4.2 to be able to extract Instagram links. +Since October 24 2020, Facebook have deprecated their legacy urls and applied a new Facebook oEmbed endpoints. +Please update your `oembed-parser` version to v1.4.2 or later to be able to extract oembed data from Instagram and Facebook. -Technically, now we have to use Facebook Graph API, with the access token from a valid and live Facebook app. By default, `oembed-parser` build Graph API endpoint using a pre-existing access token. Althrough it should work in almost cases. However, we recommend to add your own ones. +Technically, now we have to use Facebook Graph API, with the access token from a valid and live Facebook app. -``` +```bash export FACEBOOK_APP_ID=your_app_id export FACEBOOK_CLIENT_TOKEN=your_client_token - ``` For more info, please refer: diff --git a/eval.js b/eval.js index 77dcbaf..688bfea 100644 --- a/eval.js +++ b/eval.js @@ -1,3 +1,6 @@ +// eval.js +// to quickly test with a single url or file + const { extract } = require('./src/main') const run = async (url) => { diff --git a/index.d.ts b/index.d.ts index c15dbe9..7306618 100644 --- a/index.d.ts +++ b/index.d.ts @@ -19,7 +19,7 @@ export interface Endpoint { } export interface Provider { - "provider_name": string; + "providerName": string; "provider_url": string; "endpoints": Endpoint[]; } diff --git a/package.json b/package.json index 26b81dd..f978ed1 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.5.2", + "version": "2.0.0rc1", "name": "oembed-parser", "description": "Get oEmbed data from given URL.", "homepage": "https://www.npmjs.com/package/oembed-parser", @@ -9,6 +9,7 @@ }, "author": "@ndaidong", "main": "./index.js", + "types": "./index.d.ts", "engines": { "node": ">= 10.14.2" }, @@ -22,9 +23,12 @@ "build": "tsc", "reset": "node reset" }, + "dependencies": { + "got": "^11.8.3" + }, "devDependencies": { - "jest": "^27.3.1", - "typescript": "^4.4.4" + "jest": "^27.4.3", + "nock": "^13.2.1" }, "keywords": [ "oembed", @@ -32,9 +36,5 @@ "parser", "util" ], - "license": "MIT", - "types": "./index.d.ts", - "dependencies": { - "got": "^11.8.2" - } + "license": "MIT" } diff --git a/src/config.js b/src/config.js new file mode 100644 index 0000000..dd358d0 --- /dev/null +++ b/src/config.js @@ -0,0 +1,15 @@ +// config + +const fetchOptions = { + headers: { + 'user-agent': 'Mozilla/5.0 (X11; Linux i686; rv:94.0) Gecko/20100101 Firefox/94.0', + accept: 'application/json; charset=utf-8' + }, + responseType: 'json', + timeout: 30 * 1e3, + redirect: 'follow' +} + +module.exports = { + fetchOptions +} diff --git a/src/main.js b/src/main.js index 02c4086..4a871b7 100644 --- a/src/main.js +++ b/src/main.js @@ -1,20 +1,18 @@ -// main +/** + * oembed parser + * @ndaidong + **/ -const { - isValidURL, - findProvider, - fetchEmbed, - providersFromList -} = require('./utils') +const isValidURL = require('./utils/isValidURL') +const fetchEmbed = require('./utils/fetchEmbed') -const defaultProviderList = require('./utils/providers.json') -let providers = providersFromList(defaultProviderList) +const provider = require('./utils/provider') const extract = async (url, params = {}) => { if (!isValidURL(url)) { throw new Error('Invalid input URL') } - const p = findProvider(url, providers) + const p = provider.find(url) if (!p) { throw new Error(`No provider found with given url "${url}"`) } @@ -22,16 +20,9 @@ const extract = async (url, params = {}) => { return data } -const hasProvider = (url) => { - return findProvider(url, providers) !== null -} - -const setProviderList = (list) => { - providers = providersFromList(list) -} - module.exports = { extract, - hasProvider, - setProviderList + hasProvider: provider.has, + findProvider: provider.find, + setProviderList: provider.set } diff --git a/src/main.test.js b/src/main.test.js index b02c677..ac8dd53 100644 --- a/src/main.test.js +++ b/src/main.test.js @@ -1,9 +1,12 @@ // main /* eslint-env jest */ +const nock = require('nock') + const { extract, hasProvider, + findProvider, setProviderList } = require('./main') @@ -40,6 +43,14 @@ const InstagramKeys = [ ...required ] +const parseUrl = (url) => { + const re = new URL(url) + return { + baseUrl: `${re.protocol}//${re.host}`, + path: re.pathname + } +} + const hasProperty = (obj, key) => { return Object.prototype.hasOwnProperty.call(obj, key) } @@ -60,9 +71,9 @@ const hasInstagramKeys = (o) => { return InstagramKeys.every((k) => { return hasProperty(o, k) }) -}; +} -(() => { +describe('test extract(bad url)', () => { const badSamples = [ '', { k: 9 }, @@ -76,7 +87,7 @@ const hasInstagramKeys = (o) => { 'https://soundcloud^(*%%$%^$$%$$*&(&)())' ] - const testBadOne = (url) => { + badSamples.forEach((url) => { test(`testing extract bad url "${url}"`, async () => { try { await extract(url) @@ -84,51 +95,116 @@ const hasInstagramKeys = (o) => { expect(err).toBeTruthy() } }) - } - - return badSamples.map(testBadOne) -})() + }) +}) test('test extract YouTube link', async () => { - try { - const url = 'https://www.youtube.com/watch?v=ciS8aCrX-9s' - const result = await extract(url) - expect(hasRichKeys(result)).toBe(true) - } catch (err) { - expect(err).toBe(null) - } + const url = 'https://www.youtube.com/watch?v=ciS8aCrX-9s' + const provider = findProvider(url) + const { baseUrl, path } = parseUrl(provider.fetchEndpoint) + const scope = nock(baseUrl, { encodedQueryParams: true }) + const params = new URLSearchParams({ + url, + format: 'json' + }) + scope.get(path) + .query(params) + .replyWithFile(200, './test-data/youtube_ciS8aCrX-9s.json', { + 'Content-Type': 'application/json' + }) + const result = await extract(url) + expect(hasRichKeys(result)).toBe(true) + expect(result.provider_name).toEqual('YouTube') + expect(result.type).toEqual('video') }) test('test extract Flickr link', async () => { - try { - const url = 'https://flic.kr/p/2iYctUr' - const result = await extract(url) - expect(hasPhotoKeys(result)).toBe(true) - } catch (err) { - expect(err).toBe(null) - } + const url = 'https://flic.kr/p/2iYctUr' + const provider = findProvider(url) + const { baseUrl, path } = parseUrl(provider.fetchEndpoint) + const scope = nock(baseUrl, { encodedQueryParams: true }) + const params = new URLSearchParams({ + url, + format: 'json' + }) + scope.get(path) + .query(params) + .replyWithFile(200, './test-data/flickr_2iYctUr.json', { + 'Content-Type': 'application/json' + }) + const result = await extract(url) + expect(hasPhotoKeys(result)).toBe(true) + expect(result.provider_name).toEqual('Flickr') + expect(result.type).toEqual('photo') + expect(result.width).toEqual(1024) + expect(result.height).toEqual(768) }) test('test extract Flickr link with params', async () => { - try { - const url = 'https://flic.kr/p/2iYctUr' - const result = await extract(url, { maxwidth: 640, maxheight: 480 }) - expect(hasPhotoKeys(result)).toBe(true) - } catch (err) { - expect(err).toBe(null) - } + const url = 'https://flic.kr/p/2iYctUr' + const provider = findProvider(url) + const { baseUrl, path } = parseUrl(provider.fetchEndpoint) + const scope = nock(baseUrl, { encodedQueryParams: true }) + const params = new URLSearchParams({ + url, + maxwidth: 640, + maxheight: 480, + format: 'json' + }) + scope.get(path) + .query(params) + .replyWithFile(200, './test-data/flickr_2iYctUr_640x480.json', { + 'Content-Type': 'application/json' + }) + const result = await extract(url, { maxwidth: 640, maxheight: 480 }) + expect(hasPhotoKeys(result)).toBe(true) + expect(result.provider_name).toEqual('Flickr') + expect(result.type).toEqual('photo') + expect(result.width).toBeLessThanOrEqual(640) + expect(result.height).toBeLessThanOrEqual(480) }) test('test extract Instagram link', async () => { - try { - const url = 'https://www.instagram.com/p/ic7kRDqOlt/' - const result = await extract(url) - expect(hasInstagramKeys(result)).toBe(true) - } catch (err) { - // could not wait for reviewing 'Oembed Read' feature - // https://developers.facebook.com/docs/apps/review - expect(err).toBeTruthy() - } + const url = 'https://www.instagram.com/p/ic7kRDqOlt/' + const provider = findProvider(url) + const { baseUrl, path } = parseUrl(provider.fetchEndpoint) + const scope = nock(baseUrl, { encodedQueryParams: true }) + const params = new URLSearchParams({ + url, + format: 'json', + access_token: '845078789498971|8ff3ab4ddd45b8f018b35c4fb7edac62' + }) + scope.get(path) + .query(params) + .replyWithFile(200, './test-data/instagram_ic7kRDqOlt.json', { + 'Content-Type': 'application/json' + }) + const result = await extract(url) + expect(hasInstagramKeys(result)).toBe(true) + expect(result.provider_name).toEqual('Instagram') + expect(result.type).toEqual('rich') +}) + +test('test extract Facebook video', async () => { + const url = 'https://www.facebook.com/facebook/videos/10153231379946729/' + const provider = findProvider(url) + const { baseUrl, path } = parseUrl(provider.fetchEndpoint) + const scope = nock(baseUrl, { encodedQueryParams: true }) + const params = new URLSearchParams({ + url, + format: 'json', + access_token: '845078789498971|8ff3ab4ddd45b8f018b35c4fb7edac62' + }) + scope.get(path) + .query(params) + .replyWithFile(200, './test-data/facebook.json', { + 'Content-Type': 'application/json' + }) + const result = await extract(url) + expect(hasRichKeys(result)).toBe(true) + expect(result).toBeTruthy() + expect(result.provider_name).toEqual('Facebook') + expect(result.type).toEqual('video') }) test('test .hasProvider() method', () => { diff --git a/src/utils/fetchEmbed.js b/src/utils/fetchEmbed.js index 7ce37cc..0779e6c 100644 --- a/src/utils/fetchEmbed.js +++ b/src/utils/fetchEmbed.js @@ -1,26 +1,15 @@ // utils -> fetchEmbed -const got = require('got') +const retrieve = require('./retrieve') -const { name, version } = require('../../package.json') - -const fetchOptions = { - headers: { - 'user-agent': `${name}/${version}`, - accept: 'application/json; charset=utf-8' - }, - timeout: 30 * 1e3, - redirect: 'follow' -} - -const isFacebookGraphDependent = (provider) => { - return provider.provider_name === 'Facebook' || provider.provider_name === 'Instagram' +const isFacebookGraphDependent = (url) => { + return url.includes('facebook.com') || url.includes('instagram.com') } const getFacebookGraphToken = () => { const env = process.env || {} const appId = env.FACEBOOK_APP_ID || '845078789498971' - const clientToken = env.FACEBOOK_CLIENT_TOKEN || '0d4b05bf3f7e201c636441912423a491' + const clientToken = env.FACEBOOK_CLIENT_TOKEN || '8ff3ab4ddd45b8f018b35c4fb7edac62' return `access_token=${appId}|${clientToken}` } @@ -30,11 +19,6 @@ const getRegularUrl = (query, basseUrl) => { } const fetchEmbed = async (url, provider, params = {}) => { - const { - provider_name, // eslint-disable-line camelcase - provider_url // eslint-disable-line camelcase - } = provider - const queries = [ 'format=json', `url=${encodeURIComponent(url)}` @@ -52,17 +36,14 @@ const fetchEmbed = async (url, provider, params = {}) => { queries.push(`maxheight=${maxheight}`) } - if (isFacebookGraphDependent(provider)) { + if (isFacebookGraphDependent(provider.providerUrl)) { queries.push(getFacebookGraphToken()) } const query = queries.join('&') - const link = getRegularUrl(query, provider.url) - const res = got(link, fetchOptions) - const body = await res.json() - body.provider_name = provider_name // eslint-disable-line camelcase - body.provider_url = provider_url // eslint-disable-line camelcase + const link = getRegularUrl(query, provider.fetchEndpoint) + const body = retrieve(link) return body } diff --git a/src/utils/fetchEmbed.test.js b/src/utils/fetchEmbed.test.js new file mode 100644 index 0000000..1989996 --- /dev/null +++ b/src/utils/fetchEmbed.test.js @@ -0,0 +1,132 @@ +// fetchEmbed.test +/* eslint-env jest */ + +const nock = require('nock') + +const fetchEmbed = require('./fetchEmbed') +const { find: findProvider } = require('./provider') + +const parseUrl = (url) => { + const re = new URL(url) + return { + baseUrl: `${re.protocol}//${re.host}`, + path: re.pathname + } +} + +test('test fetchEmbed(youtube video)', async () => { + const url = 'https://youtu.be/qQpb1oCernE' + const provider = findProvider(url) + const { baseUrl, path } = parseUrl(provider.fetchEndpoint) + + const scope = nock(baseUrl, { encodedQueryParams: true }) + const params = new URLSearchParams({ + url, + format: 'json' + }) + scope.get(path) + .query(params) + .replyWithFile(200, './test-data/youtube.json', { + 'Content-Type': 'application/json' + }) + + const result = await fetchEmbed(url, provider) + expect(result).toBeTruthy() + expect(result.provider_name).toEqual('YouTube') + expect(result.type).toEqual('video') +}) + +test('test fetchEmbed(twitter tweet)', async () => { + const url = 'https://twitter.com/ndaidong/status/1173592062878314497' + const provider = findProvider(url) + const { baseUrl, path } = parseUrl(provider.fetchEndpoint) + + const scope = nock(baseUrl, { encodedQueryParams: true }) + const params = new URLSearchParams({ + url, + format: 'json' + }) + scope.get(path) + .query(params) + .replyWithFile(200, './test-data/twitter.json', { + 'Content-Type': 'application/json' + }) + + const result = await fetchEmbed(url, provider) + expect(result).toBeTruthy() + expect(result.provider_name).toEqual('Twitter') + expect(result.type).toEqual('rich') +}) + +test('test fetchEmbed(facebook video)', async () => { + const url = 'https://www.facebook.com/facebook/videos/10153231379946729/' + const provider = findProvider(url) + const { baseUrl, path } = parseUrl(provider.fetchEndpoint) + + const scope = nock(baseUrl, { encodedQueryParams: true }) + const params = new URLSearchParams({ + url, + format: 'json', + access_token: '845078789498971|8ff3ab4ddd45b8f018b35c4fb7edac62' + }) + scope.get(path) + .query(params) + .replyWithFile(200, './test-data/facebook.json', { + 'Content-Type': 'application/json' + }) + + const result = await fetchEmbed(url, provider) + expect(result).toBeTruthy() + expect(result.provider_name).toEqual('Facebook') + expect(result.type).toEqual('video') +}) + +test('test fetchEmbed(flikr photo)', async () => { + const url = 'http://farm4.static.flickr.com/3123/2341623661_7c99f48bbf_m.jpg' + const provider = findProvider(url) + const { baseUrl, path } = parseUrl(provider.fetchEndpoint) + + const scope = nock(baseUrl, { encodedQueryParams: true }) + const params = new URLSearchParams({ + url, + format: 'json' + }) + scope.get(path) + .query(params) + .replyWithFile(200, './test-data/flickr-default.json', { + 'Content-Type': 'application/json' + }) + + const result = await fetchEmbed(url, provider) + expect(result).toBeTruthy() + expect(result.provider_name).toEqual('Flickr') + expect(result.type).toEqual('photo') + expect(result.width).toEqual(1024) + expect(result.height).toEqual(683) +}) + +test('test fetchEmbed(flikr photo) with size limit', async () => { + const url = 'http://farm4.static.flickr.com/3123/2341623661_7c99f48bbf_m.jpg' + const provider = findProvider(url) + const { baseUrl, path } = parseUrl(provider.fetchEndpoint) + + const scope = nock(baseUrl, { encodedQueryParams: true }) + const params = new URLSearchParams({ + url, + maxwidth: 800, + maxheight: 400, + format: 'json' + }) + scope.get(path) + .query(params) + .replyWithFile(200, './test-data/flickr-sizelimit.json', { + 'Content-Type': 'application/json' + }) + + const result = await fetchEmbed(url, provider, { maxwidth: 800, maxheight: 400 }) + expect(result).toBeTruthy() + expect(result.provider_name).toEqual('Flickr') + expect(result.type).toEqual('photo') + expect(result.width).toBeLessThan(1024) + expect(result.height).toBeLessThan(683) +}) diff --git a/src/utils/findProvider.js b/src/utils/findProvider.js deleted file mode 100644 index d8912f4..0000000 --- a/src/utils/findProvider.js +++ /dev/null @@ -1,21 +0,0 @@ -// utils -> findProvider - -const findProvider = (url, providers) => { - const candidates = providers.filter((provider) => { - const { - schemes, - domain - } = provider - if (!schemes.length) { - return url.includes(domain) - } - return schemes.some((scheme) => { - const reg = new RegExp(scheme.replace(/\*/g, '(.*)').replace(/\?/g, '\\?'), 'i') - return url.match(reg) - }) - }) - - return candidates.length > 0 ? candidates[0] : null -} - -module.exports = findProvider diff --git a/src/utils/getDomain.js b/src/utils/getDomain.js new file mode 100644 index 0000000..3721557 --- /dev/null +++ b/src/utils/getDomain.js @@ -0,0 +1,10 @@ +// utils -> getDomain + +module.exports = (url = '') => { + try { + const { host } = new URL(url) + return host + } catch (err) { + return '' + } +} diff --git a/src/utils/getDomain.test.js b/src/utils/getDomain.test.js new file mode 100644 index 0000000..bde05e7 --- /dev/null +++ b/src/utils/getDomain.test.js @@ -0,0 +1,43 @@ +// getDomain.test +/* eslint-env jest */ + +const getDomain = require('./getDomain') + +describe('test getDomain()', () => { + const cases = [ + { + url: 'https://www.23hq.com', + expected: 'www.23hq.com' + }, + { + url: 'https://secure.actblue.com', + expected: 'secure.actblue.com' + }, + { + url: 'https://docs.microsoft.com/en-us/azure/iot-edge/quickstart?view=iotedge-2018-06', + expected: 'docs.microsoft.com' + }, + { + url: 'http://192.168.1.199:8081/example/page', + expected: '192.168.1.199:8081' + }, + { + url: '', + expected: '' + }, + { + url: null, + expected: '' + }, + { + url: { a: 'x' }, + expected: '' + } + ] + cases.forEach(({ url, expected }) => { + test(` getDomain("${url}") must return "${expected}"`, () => { + const result = getDomain(url) + expect(result).toEqual(expected) + }) + }) +}) diff --git a/src/utils/index.js b/src/utils/index.js deleted file mode 100644 index f90594f..0000000 --- a/src/utils/index.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - isValidURL: require('./isValidURL'), - findProvider: require('./findProvider'), - fetchEmbed: require('./fetchEmbed'), - providersFromList: require('./providersFromList') -} diff --git a/src/utils/isValidURL.js b/src/utils/isValidURL.js index febdaf1..1d57b48 100644 --- a/src/utils/isValidURL.js +++ b/src/utils/isValidURL.js @@ -2,8 +2,9 @@ module.exports = (url = '') => { try { - return new URL(url) !== null + const ourl = new URL(url) + return ourl !== null && ourl.protocol.startsWith('http') } catch (err) { - return null + return false } } diff --git a/src/utils/isValidURL.test.js b/src/utils/isValidURL.test.js new file mode 100644 index 0000000..b4c23bf --- /dev/null +++ b/src/utils/isValidURL.test.js @@ -0,0 +1,47 @@ +// isValidURL.test +/* eslint-env jest */ + +const isValidURL = require('./isValidURL') + +describe('test isValidURL()', () => { + const cases = [ + { + url: 'https://www.23hq.com', + expected: true + }, + { + url: 'https://secure.actblue.com', + expected: true + }, + { + url: 'https://docs.microsoft.com/en-us/azure/iot-edge/quickstart?view=iotedge-2018-06', + expected: true + }, + { + url: 'http://192.168.1.199:8081/example/page', + expected: true + }, + { + url: 'ftp://192.168.1.199:8081/example/page', + expected: false + }, + { + url: '', + expected: false + }, + { + url: null, + expected: false + }, + { + url: { a: 'x' }, + expected: false + } + ] + cases.forEach(({ url, expected }) => { + test(` isValidURL("${url}") must return "${expected}"`, () => { + const result = isValidURL(url) + expect(result).toEqual(expected) + }) + }) +}) diff --git a/src/utils/provider.js b/src/utils/provider.js new file mode 100644 index 0000000..56a0467 --- /dev/null +++ b/src/utils/provider.js @@ -0,0 +1,90 @@ +// utils / provider + +const isValidURL = require('./isValidURL') +const getDomain = require('./getDomain') + +const defaultProviderList = require('./providers.json') + +const providersFromList = (providers = []) => { + return providers.map((provider) => { + const { provider_url: url } = provider + provider.domain = getDomain(url) + return provider + }).filter((provider) => { + return provider.domain !== '' + }) +} + +const store = { + providers: providersFromList(defaultProviderList) +} + +const get = () => { + return [...store.providers] +} + +const set = (providers = []) => { + store.providers = providersFromList(providers) + return store.providers.length +} + +const getEndpoint = (url, domain, endpoints) => { + for (let i = 0; i < endpoints.length; i++) { + const endpoint = endpoints[i] + const { schemes = [], url: endpointUrl } = endpoint + if (schemes.length === 0) { + const endpointDomain = getDomain(endpointUrl) + if (endpointDomain === domain) { + return endpoint + } + } + const isMatchedScheme = schemes.some((scheme) => { + const reg = new RegExp(scheme.replace(/\*/g, '(.*)').replace(/\?/g, '\\?').replace(/,$/g, ''), 'i') + return url.match(reg) + }) + if (isMatchedScheme) { + return endpoint + } + } + return null +} + +const find = (url = '') => { + if (!isValidURL(url)) { + return null + } + + const domain = getDomain(url) + + const providers = get() + + for (let i = 0; i < providers.length; i++) { + const prov = providers[i] + const { + endpoints, + provider_name: providerName, + provider_url: providerUrl + } = prov + const endpoint = getEndpoint(url, domain, endpoints) + if (endpoint) { + return { + fetchEndpoint: endpoint.url, + providerName, + providerUrl + } + } + } + + return null +} + +const has = (url = '') => { + return find(url) !== null +} + +module.exports = { + get, + set, + find, + has +} diff --git a/src/utils/provider.test.js b/src/utils/provider.test.js new file mode 100644 index 0000000..305c2a8 --- /dev/null +++ b/src/utils/provider.test.js @@ -0,0 +1,77 @@ +// provider.test +/* eslint-env jest */ + +const provider = require('./provider') + +describe('test if provider.find() works correctly', () => { + const cases = [ + { + url: 'https://www.facebook.com/video.php?v=999999999', + fetchEndpoint: 'https://graph.facebook.com/v10.0/oembed_video' + }, + { + url: 'https://www.facebook.com/someone/photos/somephoto', + fetchEndpoint: 'https://graph.facebook.com/v10.0/oembed_post' + }, + { + url: 'https://www.facebook.com/someone/page', + fetchEndpoint: 'https://graph.facebook.com/v10.0/oembed_page' + }, + { + url: 'http://instagram.com/someone/p/somepage', + fetchEndpoint: 'https://graph.facebook.com/v10.0/instagram_oembed' + }, + { + url: 'https://www.edumedia-sciences.com/en/media/558-heredity', + fetchEndpoint: 'https://www.edumedia-sciences.com/oembed.json' + }, + { + url: 'https://vimeo.com/999999', + fetchEndpoint: 'https://vimeo.com/api/oembed.{format}' + }, + { + url: 'https://www.youtube.com/watch?v=9999999', + fetchEndpoint: 'https://www.youtube.com/oembed' + } + ] + + cases.forEach(({ url, fetchEndpoint }) => { + test(` provider.find("${url}") must return "${fetchEndpoint}"`, () => { + const foundedProvider = provider.find(url) + expect(foundedProvider.fetchEndpoint).toEqual(fetchEndpoint) + }) + }) + + test(' provider.find("{}") must return null', () => { + expect(provider.find({})).toEqual(null) + }) + + test(' provider.find("abcdef") must return null', () => { + expect(provider.find('abcdef')).toEqual(null) + }) + + test(' provider.find("https://somethingdoesnotexist.com") must return null', () => { + expect(provider.find('https://somethingdoesnotexist.com')).toEqual(null) + }) +}) + +describe('test if provider set/get works correctly', () => { + const providerList = [ + { + provider_name: 'Alpha', + provider_url: 'https://alpha.com', + endpoints: [] + }, + { + provider_name: 'Beta', + provider_url: 'https://beta.com', + endpoints: [] + } + ] + test(' provider.set()', () => { + expect(provider.set(providerList)).toEqual(providerList.length) + }) + test(' provider.get()', () => { + expect(provider.get()).toEqual(providerList) + }) +}) diff --git a/src/utils/providers.backup.json b/src/utils/providers.backup.json index b7378d3..43423ad 100644 --- a/src/utils/providers.backup.json +++ b/src/utils/providers.backup.json @@ -64,6 +64,21 @@ } ] }, + { + "provider_name": "Altium LLC", + "provider_url": "https://altium.com", + "endpoints": [ + { + "schemes": [ + "https://altium.com/viewer/*" + ], + "url": "https://viewer.altium.com/shell/oembed", + "formats": [ + "json" + ] + } + ] + }, { "provider_name": "Altru", "provider_url": "https://www.altrulabs.com", @@ -217,6 +232,22 @@ } ] }, + { + "provider_name": "Audiomeans", + "provider_url": "https://audiomeans.fr", + "endpoints": [ + { + "schemes": [ + "https://podcasts.audiomeans.fr/*" + ], + "url": "https://podcasts.audiomeans.fr/services/oembed", + "discovery": false, + "formats": [ + "json" + ] + } + ] + }, { "provider_name": "Avocode", "provider_url": "https://www.avocode.com/", @@ -300,6 +331,19 @@ } ] }, + { + "provider_name": "Bopp", + "provider_url": "http://www.bopp.tk", + "endpoints": [ + { + "schemes": [ + "http://i.bopp.tk/*" + ], + "url": "http://api.bopp.tk/v1/oembed", + "discovery": true + } + ] + }, { "provider_name": "Box Office Buz", "provider_url": "http://boxofficebuz.com", @@ -376,6 +420,20 @@ } ] }, + { + "provider_name": "Catapult", + "provider_url": "https://www.catapult.app/", + "endpoints": [ + { + "schemes": [ + "https://www-catapult-app.sandbox.hs-sites.com/video-page*", + "https://www-catapult.app/video-page*" + ], + "url": "https://www.catapult.app/_hcms/api/video/oembed", + "discovery": true + } + ] + }, { "provider_name": "CatBoat", "provider_url": "http://img.catbo.at/", @@ -445,6 +503,20 @@ } ] }, + { + "provider_name": "CHROCO", + "provider_url": "https://chroco.ooo/", + "endpoints": [ + { + "schemes": [ + "https://chroco.ooo/mypage/*", + "https://chroco.ooo/story/*" + ], + "url": "https://chroco.ooo/embed", + "discovery": true + } + ] + }, { "provider_name": "CircuitLab", "provider_url": "https://www.circuitlab.com/", @@ -513,7 +585,7 @@ ] }, { - "provider_name": "Codepen", + "provider_name": "CodePen", "provider_url": "https://codepen.io", "endpoints": [ { @@ -616,6 +688,22 @@ } ] }, + { + "provider_name": "Curated", + "provider_url": "https://curated.co/", + "endpoints": [ + { + "schemes": [ + "https://*.curated.co/*" + ], + "url": "https://api.curated.co/oembed", + "formats": [ + "json" + ], + "discovery": true + } + ] + }, { "provider_name": "CustomerDB", "provider_url": "http://customerdb.com/", @@ -658,6 +746,19 @@ } ] }, + { + "provider_name": "DALEXNI", + "provider_url": "https://dalexni.com/", + "endpoints": [ + { + "schemes": [ + "https://dalexni.com/i/*" + ], + "url": "https://dalexni.com/oembed/", + "discovery": true + } + ] + }, { "provider_name": "Datawrapper", "provider_url": "http://www.datawrapper.de", @@ -710,7 +811,7 @@ "schemes": [ "https://*.didacte.com/a/course/*" ], - "url": "https://*.didacte.com/cards/oembed'", + "url": "https://*.didacte.com/cards/oembed", "discovery": true, "formats": [ "json" @@ -864,6 +965,23 @@ } ] }, + { + "provider_name": "Enystre Music", + "provider_url": "https://music.enystre.com", + "endpoints": [ + { + "schemes": [ + "https://music.enystre.com/lyrics/*" + ], + "url": "https://music.enystre.com/oembed", + "formats": [ + "json", + "xml" + ], + "discovery": true + } + ] + }, { "provider_name": "Ethfiddle", "provider_url": "https://www.ethfiddle.com/", @@ -877,6 +995,22 @@ } ] }, + { + "provider_name": "EventLive", + "provider_url": "https://eventlive.pro", + "endpoints": [ + { + "schemes": [ + "https://evt.live/*", + "https://evt.live/*/*", + "https://live.eventlive.pro/*", + "https://live.eventlive.pro/*/*" + ], + "url": "https://evt.live/api/oembed", + "discovery": true + } + ] + }, { "provider_name": "Ex.Co", "provider_url": "https://ex.co", @@ -913,6 +1047,7 @@ "schemes": [ "https://www.facebook.com/*/posts/*", "https://www.facebook.com/*/activity/*", + "https://www.facebook.com/*/photos/*", "https://www.facebook.com/photo.php?fbid=*", "https://www.facebook.com/photos/*", "https://www.facebook.com/permalink.php?story_fbid=*", @@ -920,7 +1055,7 @@ "https://www.facebook.com/questions/*", "https://www.facebook.com/notes/*/*/*" ], - "url": "https://graph.facebook.com/v9.0/oembed_post", + "url": "https://graph.facebook.com/v10.0/oembed_post", "discovery": false }, { @@ -929,14 +1064,14 @@ "https://www.facebook.com/video.php?id=*", "https://www.facebook.com/video.php?v=*" ], - "url": "https://graph.facebook.com/v9.0/oembed_video", + "url": "https://graph.facebook.com/v10.0/oembed_video", "discovery": false }, { "schemes": [ "https://www.facebook.com/*" ], - "url": "https://graph.facebook.com/v9.0/oembed_page", + "url": "https://graph.facebook.com/v10.0/oembed_page", "discovery": false } ] @@ -1071,6 +1206,20 @@ } ] }, + { + "provider_name": "Framer", + "provider_url": "https://www.framer.com", + "endpoints": [ + { + "schemes": [ + "https://framer.com/share/*", + "https://framer.com/embed/*" + ], + "url": "https://api.framer.com/web/oembed", + "discovery": true + } + ] + }, { "provider_name": "FunnyOrDie", "provider_url": "http://www.funnyordie.com/", @@ -1179,9 +1328,9 @@ { "schemes": [ "https://giphy.com/gifs/*", + "https://giphy.com/clips/*", "http://gph.is/*", - "https://media.giphy.com/media/*/giphy.gif", - "https://giphy.com/clips/*" + "https://media.giphy.com/media/*/giphy.gif" ], "url": "https://giphy.com/services/oembed", "discovery": true @@ -1204,7 +1353,6 @@ "endpoints": [ { "schemes": [ - "https://app.gong.io/call", "https://app.gong.io/call?id=*" ], "url": "https://app.gong.io/oembed", @@ -1276,7 +1424,7 @@ "schemes": [ "https://player.hihaho.com/*" ], - "url": "https://player.hihaho.com/services/oembed/*", + "url": "https://player.hihaho.com/services/oembed", "formats": [ "json", "xml" @@ -1284,6 +1432,20 @@ } ] }, + { + "provider_name": "HippoVideo", + "provider_url": "https://hippovideo.io", + "endpoints": [ + { + "schemes": [ + "http://*.hippovideo.io/*", + "https://*.hippovideo.io/*" + ], + "url": "https://www.hippovideo.io/services/oembed", + "discovery": true + } + ] + }, { "provider_name": "Homey", "provider_url": "https://homey.app", @@ -1337,6 +1499,21 @@ } ] }, + { + "provider_name": "Idomoo", + "provider_url": "https://idomoo.com/", + "endpoints": [ + { + "schemes": [ + "https://*.idomoo.com/*" + ], + "url": "https://oembed.idomoo.com/oembed", + "formats": [ + "json" + ] + } + ] + }, { "provider_name": "iFixit", "provider_url": "http://www.iFixit.com", @@ -1482,15 +1659,34 @@ "https://instagram.com/tv/*", "https://instagr.am/tv/*", "https://www.instagram.com/tv/*", - "https://www.instagr.am/tv/*" - ], - "url": "https://graph.facebook.com/v11.0/instagram_oembed", + "https://www.instagr.am/tv/*", + "http://www.instagram.com/reel/*", + "https://www.instagram.com/reel/*", + "http://instagram.com/reel/*", + "https://instagram.com/reel/*", + "http://instagr.am/reel/*", + "https://instagr.am/reel/*" + ], + "url": "https://graph.facebook.com/v10.0/instagram_oembed", "formats": [ "json" ] } ] }, + { + "provider_name": "Insticator Inc", + "provider_url": "https://www.insticator.com/", + "endpoints": [ + { + "schemes": [ + "https://ppa.insticator.com/embed-unit/*" + ], + "url": "https://www.insticator.com/oembed", + "discovery": true + } + ] + }, { "provider_name": "Issuu", "provider_url": "https://issuu.com/", @@ -1539,11 +1735,11 @@ { "schemes": [ "https://tv.kakao.com/channel/*/cliplink/*", + "https://tv.kakao.com/m/channel/*/cliplink/*", "https://tv.kakao.com/channel/v/*", "https://tv.kakao.com/channel/*/livelink/*", - "https://tv.kakao.com/channel/l/*", - "https://tv.kakao.com/m/channel/*/cliplink/*", - "https://tv.kakao.com/m/channel/*/livelink/*" + "https://tv.kakao.com/m/channel/*/livelink/*", + "https://tv.kakao.com/channel/l/*" ], "url": "https://tv.kakao.com/oembed", "discovery": true @@ -1657,6 +1853,20 @@ } ] }, + { + "provider_name": "Kooapp", + "provider_url": "https://kooapp.com", + "endpoints": [ + { + "schemes": [ + "https://*.kooapp.com/koo/", + "http://*.kooapp.com/koo/" + ], + "url": "https://embed-stage.kooapp.com/services/oembed", + "discovery": true + } + ] + }, { "provider_name": "LearningApps.org", "provider_url": "http://learningapps.org/", @@ -1714,6 +1924,23 @@ } ] }, + { + "provider_name": "LottieFiles", + "provider_url": "https://lottiefiles.com/", + "endpoints": [ + { + "schemes": [ + "https://lottiefiles.com/*", + "https://*.lottiefiles.com/*" + ], + "url": "https://embed.lottiefiles.com/oembed", + "discovery": true, + "formats": [ + "json" + ] + } + ] + }, { "provider_name": "Ludus", "provider_url": "https://ludus.one", @@ -1813,24 +2040,6 @@ } ] }, - { - "provider_name": "Meetup", - "provider_url": "http://www.meetup.com", - "endpoints": [ - { - "schemes": [ - "http://meetup.com/*", - "https://www.meetup.com/*", - "https://meetup.com/*", - "http://meetu.ps/*" - ], - "url": "https://api.meetup.com/oembed", - "formats": [ - "json" - ] - } - ] - }, { "provider_name": "Mermaid Ink", "provider_url": "https://mermaid.ink", @@ -1868,6 +2077,26 @@ } ] }, + { + "provider_name": "Minerva", + "provider_url": "https://www.minervaknows.com", + "endpoints": [ + { + "schemes": [ + "https://www.minervaknows.com/featured-recipes/*", + "https://www.minervaknows.com/themes/*", + "https://www.minervaknows.com/themes/*/recipes/*", + "https://app.minervaknows.com/recipes/*", + "https://app.minervaknows.com/recipes/*/follow" + ], + "url": "https://oembed.minervaknows.com", + "formats": [ + "json" + ], + "discovery": true + } + ] + }, { "provider_name": "MixCloud", "provider_url": "https://mixcloud.com/", @@ -2038,15 +2267,27 @@ ] }, { - "provider_name": "NoPaste", - "provider_url": "https://nopaste.ml", + "provider_name": "NFTNDX.IO", + "provider_url": "https://www.nftndx.io/", "endpoints": [ { - "schemes": [ - "https://nopaste.ml/*" - ], - "url": "https://oembed.nopaste.ml", - "discovery": false + "url": "https://www.nftndx.io/oembed", + "formats": [ + "json" + ] + } + ] + }, + { + "provider_name": "NoPaste", + "provider_url": "https://nopaste.ml", + "endpoints": [ + { + "schemes": [ + "https://nopaste.ml/*" + ], + "url": "https://oembed.nopaste.ml", + "discovery": false } ] }, @@ -2130,6 +2371,21 @@ } ] }, + { + "provider_name": "Omny Studio", + "provider_url": "https://omnystudio.com", + "endpoints": [ + { + "schemes": [ + "https://omny.fm/shows/*" + ], + "url": "https://omny.fm/oembed", + "formats": [ + "json" + ] + } + ] + }, { "provider_name": "On Aol", "provider_url": "http://on.aol.com/", @@ -2142,6 +2398,19 @@ } ] }, + { + "provider_name": "Opsomai", + "provider_url": "http://www.opsomai.com", + "endpoints": [ + { + "schemes": [ + "https://*.opsismedia.com/*" + ], + "url": "https://test-bysa.opsismedia.com/oembed.php", + "discovery": true + } + ] + }, { "provider_name": "Ora TV", "provider_url": "http://www.ora.tv/", @@ -2286,6 +2555,32 @@ } ] }, + { + "provider_name": "Pinterest", + "provider_url": "https://www.pinterest.com", + "endpoints": [ + { + "schemes": [ + "https://www.pinterest.com/*" + ], + "url": "https://www.pinterest.com/oembed.json", + "discovery": true + } + ] + }, + { + "provider_name": "PitchHub", + "provider_url": "https://www.pitchhub.com/", + "endpoints": [ + { + "schemes": [ + "https://*.pitchhub.com/en/public/player/*" + ], + "url": "https://*.pitchhub.com.com/en/public/oembed", + "discovery": true + } + ] + }, { "provider_name": "Pixdor", "provider_url": "http://www.pixdor.com/", @@ -2381,6 +2676,36 @@ } ] }, + { + "provider_name": "Present", + "provider_url": "https://present.do", + "endpoints": [ + { + "schemes": [ + "https://present.do/decks/*" + ], + "url": "https://gateway.cobalt.run/present/decks/oembed", + "discovery": true, + "formats": [ + "json" + ] + } + ] + }, + { + "provider_name": "Prezi Video", + "provider_url": "https://prezi.com/", + "endpoints": [ + { + "schemes": [ + "https://prezi.com/v/*", + "https://*.prezi.com/v/*" + ], + "url": "https://prezi.com/v/oembed", + "discovery": true + } + ] + }, { "provider_name": "Qualifio", "provider_url": "https://qualifio.com/", @@ -2436,6 +2761,25 @@ } ] }, + { + "provider_name": "Raindrop", + "provider_url": "https://raindrop.io", + "endpoints": [ + { + "schemes": [ + "https://raindrop.io/*", + "https://raindrop.io/*/*", + "https://raindrop.io/*/*/*", + "https://raindrop.io/*/*/*/*" + ], + "url": "https://pub.raindrop.io/api/oembed", + "discovery": true, + "formats": [ + "json" + ] + } + ] + }, { "provider_name": "rcvis", "provider_url": "https://www.rcvis.com/", @@ -2480,13 +2824,14 @@ }, { "provider_name": "Replit", - "provider_url": "https://repl.it/", + "provider_url": "https://replit.com/", "endpoints": [ { "schemes": [ - "https://repl.it/@*/*" + "https://repl.it/@*/*", + "https://replit.com/@*/*" ], - "url": "https://repl.it/data/oembed", + "url": "https://replit.com/data/oembed", "discovery": true } ] @@ -2504,6 +2849,19 @@ } ] }, + { + "provider_name": "Resso", + "provider_url": "https://www.resso.app/", + "endpoints": [ + { + "schemes": [ + "https://h5.resso.com/*" + ], + "url": "https://h5.resso.com/oembed/", + "discovery": true + } + ] + }, { "provider_name": "ReverbNation", "provider_url": "https://www.reverbnation.com/", @@ -2824,6 +3182,21 @@ } ] }, + { + "provider_name": "Smrthi", + "provider_url": "https://www.smrthi.com", + "endpoints": [ + { + "schemes": [ + "https://www.smrthi.com/book/*" + ], + "url": "https://www.smrthi.com/api/oembed", + "formats": [ + "json" + ] + } + ] + }, { "provider_name": "SmugMug", "provider_url": "https://www.smugmug.com/", @@ -2904,10 +3277,11 @@ "endpoints": [ { "schemes": [ - "https://*.spotify.com/*", + "https://open.spotify.com/*", "spotify:*" ], - "url": "https://embed.spotify.com/oembed/" + "url": "https://open.spotify.com/oembed/", + "discovery": true } ] }, @@ -2925,6 +3299,24 @@ } ] }, + { + "provider_name": "SproutVideo", + "provider_url": "https://sproutvideo.com", + "endpoints": [ + { + "schemes": [ + "https://sproutvideo.com/videos/*", + "https://*.vids.io/videos/*" + ], + "url": "http://sproutvideo.com/oembed.{format}", + "formats": [ + "json", + "xml" + ], + "discovery": true + } + ] + }, { "provider_name": "Stanford Digital Repository", "provider_url": "https://purl.stanford.edu/", @@ -2952,6 +3344,20 @@ } ] }, + { + "provider_name": "Streamio", + "provider_url": "https://www.streamio.com", + "endpoints": [ + { + "schemes": [ + "https://s3m.io/*", + "https://23m.io/*" + ], + "url": "https://streamio.com/api/v1/oembed", + "discovery": true + } + ] + }, { "provider_name": "StreamOneCloud", "provider_url": "https://www.streamone.nl", @@ -3132,6 +3538,19 @@ } ] }, + { + "provider_name": "Totango", + "provider_url": "https://totango.com", + "endpoints": [ + { + "schemes": [ + "https://app-test.totango.com/*" + ], + "url": "https://app-test.totango.com/oembed", + "discovery": true + } + ] + }, { "provider_name": "TourHero", "provider_url": "http://www.tourhero.com", @@ -3148,6 +3567,20 @@ } ] }, + { + "provider_name": "Trinity Audio", + "provider_url": "https://trinityaudio.ai", + "endpoints": [ + { + "schemes": [ + "https://trinitymedia.ai/player/*", + "http://trinitymedia.ai/player/*" + ], + "url": "https://trinitymedia.ai/player/trinity-oembed", + "discovery": true + } + ] + }, { "provider_name": "Tumblr", "provider_url": "https://www.tumblr.com", @@ -3193,9 +3626,7 @@ { "schemes": [ "https://twitter.com/*/status/*", - "https://*.twitter.com/*/status/*", - "https://twitter.com/*/moments/*", - "https://*.twitter.com/*/moments/*" + "https://*.twitter.com/*/status/*" ], "url": "https://publish.twitter.com/oembed" } @@ -3225,6 +3656,19 @@ } ] }, + { + "provider_name": "UAPod", + "provider_url": "https://uapod.univ-antilles.fr/", + "endpoints": [ + { + "schemes": [ + "https://uapod.univ-antilles.fr/video/*" + ], + "url": "https://uapod.univ-antilles.fr/oembed", + "discovery": true + } + ] + }, { "provider_name": "Ubideo", "provider_url": "https://player.ubideo.com/", @@ -3279,6 +3723,19 @@ } ] }, + { + "provider_name": "Upec.Pod", + "provider_url": "https://pod.u-pec.fr/", + "endpoints": [ + { + "schemes": [ + "https://pod.u-pec.fr/video/*" + ], + "url": "https://pod.u-pec.fr/oembed", + "discovery": true + } + ] + }, { "provider_name": "uppy", "provider_url": "https://uppy.jp", @@ -3572,6 +4029,19 @@ } ] }, + { + "provider_name": "Waltrack", + "provider_url": "https://waltrack/net", + "endpoints": [ + { + "schemes": [ + "https://waltrack.net/product/*" + ], + "url": "https://waltrack.net/oembed", + "discovery": true + } + ] + }, { "provider_name": "Wave.video", "provider_url": "https://wave.video", @@ -3811,458 +4281,5 @@ "discovery": true } ] - }, - { - "provider_name": "Altium LLC", - "provider_url": "https://altium.com", - "endpoints": [ - { - "schemes": [ - "https://altium.com/viewer/*" - ], - "url": "https://viewer.altium.com/shell/oembed", - "formats": [ - "json" - ] - } - ] - }, - { - "provider_name": "Bopp", - "provider_url": "http://www.bopp.tk", - "endpoints": [ - { - "schemes": [ - "http://i.bopp.tk/*" - ], - "url": "http://api.bopp.tk/v1/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "Curated", - "provider_url": "https://curated.co/", - "endpoints": [ - { - "schemes": [ - "https://*.curated.co/*" - ], - "url": "https://api.curated.co/oembed", - "formats": [ - "json" - ], - "discovery": true - } - ] - }, - { - "provider_name": "HippoVideo", - "provider_url": "https://hippovideo.io", - "endpoints": [ - { - "schemes": [ - "http://*.hippovideo.io/*", - "https://*.hippovideo.io/*" - ], - "url": "https://www.hippovideo.io/services/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "Idomoo", - "provider_url": "https://idomoo.com/", - "endpoints": [ - { - "schemes": [ - "https://*.idomoo.com/*" - ], - "url": "https://oembed.idomoo.com/oembed", - "formats": [ - "json" - ] - } - ] - }, - { - "provider_name": "Insticator Inc", - "provider_url": "https://www.insticator.com/", - "endpoints": [ - { - "schemes": [ - "https://ppa.insticator.com/embed-unit/*" - ], - "url": "https://www.insticator.com/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "LottieFiles", - "provider_url": "https://lottiefiles.com/", - "endpoints": [ - { - "schemes": [ - "https://lottiefiles.com/*", - "https://*.lottiefiles.com/*" - ], - "url": "https://embed.lottiefiles.com/oembed", - "discovery": true, - "formats": [ - "json" - ] - } - ] - }, - { - "provider_name": "Minerva", - "provider_url": "https://www.minervaknows.com", - "endpoints": [ - { - "schemes": [ - "https://www.minervaknows.com/featured-recipes/*", - "https://www.minervaknows.com/themes/*", - "https://www.minervaknows.com/themes/*/recipes/*", - "https://app.minervaknows.com/recipes/*", - "https://app.minervaknows.com/recipes/*/follow" - ], - "url": "https://oembed.minervaknows.com", - "formats": [ - "json" - ], - "discovery": true - } - ] - }, - { - "provider_name": "Omny Studio", - "provider_url": "https://omnystudio.com", - "endpoints": [ - { - "schemes": [ - "https://omny.fm/shows/*" - ], - "url": "https://omny.fm/oembed", - "formats": [ - "json" - ] - } - ] - }, - { - "provider_name": "Prezi Video", - "provider_url": "https://prezi.com/", - "endpoints": [ - { - "schemes": [ - "https://prezi.com/v/*", - "https://*.prezi.com/v/*" - ], - "url": "https://prezi.com/v/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "SproutVideo", - "provider_url": "https://sproutvideo.com", - "endpoints": [ - { - "schemes": [ - "https://sproutvideo.com/videos/*", - "https://*.vids.io/videos/*" - ], - "url": "http://sproutvideo.com/oembed.{format}", - "formats": [ - "json", - "xml" - ], - "discovery": true - } - ] - }, - { - "provider_name": "Upec.Pod", - "provider_url": "https://pod.u-pec.fr/", - "endpoints": [ - { - "schemes": [ - "https://pod.u-pec.fr/video/*" - ], - "url": "https://pod.u-pec.fr/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "Audiomeans", - "provider_url": "https://audiomeans.fr", - "endpoints": [ - { - "schemes": [ - "https://podcasts.audiomeans.fr/*" - ], - "url": "https://podcasts.audiomeans.fr/services/oembed", - "discovery": false, - "formats": [ - "json" - ] - } - ] - }, - { - "provider_name": "CHROCO", - "provider_url": "https://chroco.ooo/", - "endpoints": [ - { - "schemes": [ - "https://chroco.ooo/mypage/*", - "https://chroco.ooo/story/*" - ], - "url": "https://chroco.ooo/embed", - "discovery": true - } - ] - }, - { - "provider_name": "CodePen", - "provider_url": "https://codepen.io", - "endpoints": [ - { - "schemes": [ - "http://codepen.io/*", - "https://codepen.io/*" - ], - "url": "https://codepen.io/api/oembed" - } - ] - }, - { - "provider_name": "Enystre Music", - "provider_url": "https://music.enystre.com", - "endpoints": [ - { - "schemes": [ - "https://music.enystre.com/lyrics/*" - ], - "url": "https://music.enystre.com/oembed", - "formats": [ - "json", - "xml" - ], - "discovery": true - } - ] - }, - { - "provider_name": "Framer", - "provider_url": "https://www.framer.com", - "endpoints": [ - { - "schemes": [ - "https://framer.com/share/*", - "https://framer.com/embed/*" - ], - "url": "https://api.framer.com/web/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "NFTNDX.IO", - "provider_url": "https://www.nftndx.io/", - "endpoints": [ - { - "url": "https://www.nftndx.io/oembed", - "formats": [ - "json" - ] - } - ] - }, - { - "provider_name": "Opsomai", - "provider_url": "http://www.opsomai.com", - "endpoints": [ - { - "schemes": [ - "https://*.opsismedia.com/*" - ], - "url": "https://test-bysa.opsismedia.com/oembed.php", - "discovery": true - } - ] - }, - { - "provider_name": "Pinterest", - "provider_url": "https://www.pinterest.com", - "endpoints": [ - { - "schemes": [ - "https://www.pinterest.com/*" - ], - "url": "https://www.pinterest.com/oembed.json", - "discovery": true - } - ] - }, - { - "provider_name": "PitchHub", - "provider_url": "https://www.pitchhub.com/", - "endpoints": [ - { - "schemes": [ - "https://*.pitchhub.com/en/public/player/*" - ], - "url": "https://*.pitchhub.com.com/en/public/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "Present", - "provider_url": "https://present.do", - "endpoints": [ - { - "schemes": [ - "https://present.do/decks/*" - ], - "url": "https://gateway.cobalt.run/present/decks/oembed", - "discovery": true, - "formats": [ - "json" - ] - } - ] - }, - { - "provider_name": "Raindrop", - "provider_url": "https://raindrop.io", - "endpoints": [ - { - "schemes": [ - "https://raindrop.io/*", - "https://raindrop.io/*/*", - "https://raindrop.io/*/*/*", - "https://raindrop.io/*/*/*/*" - ], - "url": "https://pub.raindrop.io/api/oembed", - "discovery": true, - "formats": [ - "json" - ] - } - ] - }, - { - "provider_name": "UAPod", - "provider_url": "https://uapod.univ-antilles.fr/", - "endpoints": [ - { - "schemes": [ - "https://uapod.univ-antilles.fr/video/*" - ], - "url": "https://uapod.univ-antilles.fr/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "Waltrack", - "provider_url": "https://waltrack/net", - "endpoints": [ - { - "schemes": [ - "https://waltrack.net/product/*" - ], - "url": "https://waltrack.net/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "Catapult", - "provider_url": "https://www.catapult.app/", - "endpoints": [ - { - "schemes": [ - "https://www-catapult-app.sandbox.hs-sites.com/video-page*", - "https://www-catapult.app/video-page*" - ], - "url": "https://www.catapult.app/_hcms/api/video/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "EventLive", - "provider_url": "https://eventlive.pro", - "endpoints": [ - { - "schemes": [ - "https://evt.live/*", - "https://evt.live/*/*", - "https://live.eventlive.pro/*", - "https://live.eventlive.pro/*/*" - ], - "url": "https://evt.live/api/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "Resso", - "provider_url": "https://www.resso.app/", - "endpoints": [ - { - "schemes": [ - "https://h5.resso.com/*" - ], - "url": "https://h5.resso.com/oembed/", - "discovery": true - } - ] - }, - { - "provider_name": "Streamio", - "provider_url": "https://www.streamio.com", - "endpoints": [ - { - "schemes": [ - "https://s3m.io/*", - "https://23m.io/*" - ], - "url": "https://streamio.com/api/v1/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "Totango", - "provider_url": "https://totango.com", - "endpoints": [ - { - "schemes": [ - "https://app-test.totango.com/*" - ], - "url": "https://app-test.totango.com/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "Trinity Audio", - "provider_url": "https://trinityaudio.ai", - "endpoints": [ - { - "schemes": [ - "https://trinitymedia.ai/player/*", - "http://trinitymedia.ai/player/*" - ], - "url": "https://trinitymedia.ai/player/trinity-oembed", - "discovery": true - } - ] } -] +] \ No newline at end of file diff --git a/src/utils/providers.json b/src/utils/providers.json index 3bf3dac..f4c6c1f 100644 --- a/src/utils/providers.json +++ b/src/utils/providers.json @@ -49,18 +49,17 @@ ] }, { - "provider_name": "Alpha App Net", - "provider_url": "https://alpha.app.net/browse/posts/", + "provider_name": "afreecaTV", + "provider_url": "https://www.afreecatv.com", "endpoints": [ { "schemes": [ - "https://alpha.app.net/*/post/*", - "https://photos.app.net/*/*" + "https://v.afree.ca/ST/", + "https://vod.afreecatv.com/ST/", + "https://vod.afreecatv.com/PLAYER/STATION/" ], - "url": "https://alpha-api.app.net/oembed", - "formats": [ - "json" - ] + "url": "https://openapi.afreecatv.com/vod/embedinfo", + "discovery": true } ] }, @@ -263,19 +262,6 @@ } ] }, - { - "provider_name": "AxiomNinja", - "provider_url": "http://axiom.ninja", - "endpoints": [ - { - "schemes": [ - "http://axiom.ninja/*" - ], - "url": "http://axiom.ninja/oembed/", - "discovery": true - } - ] - }, { "provider_name": "Backtracks", "provider_url": "https://backtracks.fm", @@ -331,19 +317,6 @@ } ] }, - { - "provider_name": "Bopp", - "provider_url": "http://www.bopp.tk", - "endpoints": [ - { - "schemes": [ - "http://i.bopp.tk/*" - ], - "url": "http://api.bopp.tk/v1/oembed", - "discovery": true - } - ] - }, { "provider_name": "Box Office Buz", "provider_url": "http://boxofficebuz.com", @@ -407,19 +380,6 @@ } ] }, - { - "provider_name": "Carbon Health", - "provider_url": "https://carbonhealth.com", - "endpoints": [ - { - "schemes": [ - "https://carbonhealth.com/practice/*" - ], - "url": "http://carbonhealth.com/oembed", - "discovery": true - } - ] - }, { "provider_name": "Catapult", "provider_url": "https://www.catapult.app/", @@ -462,22 +422,6 @@ } ] }, - { - "provider_name": "Chainflix", - "provider_url": "https://chainflix.net", - "endpoints": [ - { - "schemes": [ - "https://chainflix.net/video/*", - "https://chainflix.net/video/embed/*", - "https://*.chainflix.net/video/*", - "https://*.chainflix.net/video/embed/*" - ], - "url": "https://www.chainflix.net/video/oembed", - "discovery": true - } - ] - }, { "provider_name": "ChartBlocks", "provider_url": "http://www.chartblocks.com/", @@ -716,23 +660,6 @@ } ] }, - { - "provider_name": "Cyrano Systems", - "provider_url": "http://www.cyranosystems.com/", - "endpoints": [ - { - "schemes": [ - "https://staging.cyranosystems.com/msg/*", - "https://app.cyranosystems.com/msg/*" - ], - "url": "https://staging.cyranosystems.com/oembed", - "formats": [ - "json" - ], - "discovery": true - } - ] - }, { "provider_name": "Dailymotion", "provider_url": "https://www.dailymotion.com", @@ -834,18 +761,6 @@ } ] }, - { - "provider_name": "Dipity", - "provider_url": "http://www.dipity.com", - "endpoints": [ - { - "schemes": [ - "http://www.dipity.com/*/*/" - ], - "url": "http://www.dipity.com/oembed/timeline/" - } - ] - }, { "provider_name": "DocDroid", "provider_url": "https://www.docdroid.net/", @@ -892,18 +807,6 @@ } ] }, - { - "provider_name": "edocr", - "provider_url": "http://www.edocr.com", - "endpoints": [ - { - "schemes": [ - "http://edocr.com/docs/*" - ], - "url": "http://edocr.com/api/oembed" - } - ] - }, { "provider_name": "eduMedia", "provider_url": "https://www.edumedia-sciences.com/", @@ -931,18 +834,6 @@ } ] }, - { - "provider_name": "Embed Articles", - "provider_url": "http://embedarticles.com/", - "endpoints": [ - { - "schemes": [ - "http://embedarticles.com/*" - ], - "url": "http://embedarticles.com/oembed/" - } - ] - }, { "provider_name": "Embedery", "provider_url": "https://embedery.com/", @@ -1158,6 +1049,8 @@ "http://*.flickr.com/photos/*", "http://flic.kr/p/*", "https://*.flickr.com/photos/*", + "https://*.*.flickr.com/*/*", + "http://*.*.flickr.com/*/*", "https://flic.kr/p/*" ], "url": "https://www.flickr.com/services/oembed/", @@ -1220,18 +1113,6 @@ } ] }, - { - "provider_name": "FunnyOrDie", - "provider_url": "http://www.funnyordie.com/", - "endpoints": [ - { - "schemes": [ - "http://www.funnyordie.com/videos/*" - ], - "url": "http://www.funnyordie.com/oembed.{format}" - } - ] - }, { "provider_name": "Geograph Britain and Ireland", "provider_url": "https://www.geograph.org.uk/", @@ -1460,21 +1341,6 @@ } ] }, - { - "provider_name": "Hosted by You", - "provider_url": "https://hostedbyyou.com", - "endpoints": [ - { - "schemes": [ - "https://hostedbyyou.com/event/*" - ], - "url": "https://hostedbyyou.com/api/oembed", - "formats": [ - "json" - ] - } - ] - }, { "provider_name": "HuffDuffer", "provider_url": "http://huffduffer.com", @@ -1700,16 +1566,6 @@ } ] }, - { - "provider_name": "ivlismusic", - "provider_url": "https://music.ivlis.kr/", - "endpoints": [ - { - "url": "https://music.ivlis.kr/oembed", - "discovery": true - } - ] - }, { "provider_name": "Jovian", "provider_url": "https://jovian.ai/", @@ -2054,15 +1910,6 @@ } ] }, - { - "provider_name": "Microlink", - "provider_url": "http://api.microlink.io", - "endpoints": [ - { - "url": "https://api.microlink.io" - } - ] - }, { "provider_name": "Microsoft Stream", "provider_url": "https://stream.microsoft.com", @@ -2123,35 +1970,6 @@ } ] }, - { - "provider_name": "Modelo", - "provider_url": "http://modelo.io/", - "endpoints": [ - { - "schemes": [ - "https://beta.modelo.io/embedded/*" - ], - "url": "https://portal.modelo.io/oembed", - "discovery": false - } - ] - }, - { - "provider_name": "MorphCast", - "provider_url": "https://www.morphcast.com", - "endpoints": [ - { - "schemes": [ - "https://m-roll.morphcast.com/mroll/*" - ], - "url": "https://m-roll.morphcast.com/service/oembed", - "discovery": true, - "formats": [ - "json" - ] - } - ] - }, { "provider_name": "Music Box Maniacs", "provider_url": "https://musicboxmaniacs.com/", @@ -2343,6 +2161,20 @@ } ] }, + { + "provider_name": "Odysee", + "provider_url": "https://odysee.com", + "endpoints": [ + { + "schemes": [ + "https://odysee.com/*/*", + "https://odysee.com/*" + ], + "url": "https://odysee.com/$/oembed", + "discovery": true + } + ] + }, { "provider_name": "Official FM", "provider_url": "http://official.fm", @@ -2386,31 +2218,6 @@ } ] }, - { - "provider_name": "On Aol", - "provider_url": "http://on.aol.com/", - "endpoints": [ - { - "schemes": [ - "http://on.aol.com/video/*" - ], - "url": "http://on.aol.com/api" - } - ] - }, - { - "provider_name": "Opsomai", - "provider_url": "http://www.opsomai.com", - "endpoints": [ - { - "schemes": [ - "https://*.opsismedia.com/*" - ], - "url": "https://test-bysa.opsismedia.com/oembed.php", - "discovery": true - } - ] - }, { "provider_name": "Ora TV", "provider_url": "http://www.ora.tv/", @@ -2443,19 +2250,6 @@ } ] }, - { - "provider_name": "Oumy", - "provider_url": "https://www.oumy.com/", - "endpoints": [ - { - "schemes": [ - "https://www.oumy.com/v/*" - ], - "url": "https://www.oumy.com/oembed", - "discovery": true - } - ] - }, { "provider_name": "Outplayed.tv", "provider_url": "https://outplayed.tv/", @@ -2612,19 +2406,6 @@ } ] }, - { - "provider_name": "Polaris Share", - "provider_url": "https://www.polarishare.com/", - "endpoints": [ - { - "schemes": [ - "https://www.polarishare.com/*/*" - ], - "url": "https://api.polarishare.com/rest/api/oembed", - "discovery": true - } - ] - }, { "provider_name": "Poll Daddy", "provider_url": "http://polldaddy.com", @@ -2639,18 +2420,6 @@ } ] }, - { - "provider_name": "Port", - "provider_url": "http://www.sellwithport.com/", - "endpoints": [ - { - "schemes": [ - "https://app.sellwithport.com/#/buyer/*" - ], - "url": "https://api.sellwithport.com/v1.0/buyer/oembed" - } - ] - }, { "provider_name": "Portfolium", "provider_url": "https://portfolium.com", @@ -2663,19 +2432,6 @@ } ] }, - { - "provider_name": "posiXion", - "provider_url": "https://posixion.com/", - "endpoints": [ - { - "schemes": [ - "https://posixion.com/question/*", - "https://posixion.com/*/question/*" - ], - "url": "http://posixion.com/services/oembed/" - } - ] - }, { "provider_name": "Present", "provider_url": "https://present.do", @@ -2706,16 +2462,6 @@ } ] }, - { - "provider_name": "Qualifio", - "provider_url": "https://qualifio.com/", - "endpoints": [ - { - "url": "https://oembed.qualifio.com/", - "discovery": true - } - ] - }, { "provider_name": "Quiz.biz", "provider_url": "http://www.quiz.biz/", @@ -2836,32 +2582,6 @@ } ] }, - { - "provider_name": "RepubHub", - "provider_url": "http://repubhub.icopyright.net/", - "endpoints": [ - { - "schemes": [ - "http://repubhub.icopyright.net/freePost.act?*" - ], - "url": "http://repubhub.icopyright.net/oembed.act", - "discovery": true - } - ] - }, - { - "provider_name": "Resso", - "provider_url": "https://www.resso.app/", - "endpoints": [ - { - "schemes": [ - "https://h5.resso.com/*" - ], - "url": "https://h5.resso.com/oembed/", - "discovery": true - } - ] - }, { "provider_name": "ReverbNation", "provider_url": "https://www.reverbnation.com/", @@ -2876,16 +2596,6 @@ } ] }, - { - "provider_name": "RiffReporter", - "provider_url": "https://www.riffreporter.de/", - "endpoints": [ - { - "url": "https://www.riffreporter.de/service/oembed", - "discovery": true - } - ] - }, { "provider_name": "Roomshare", "provider_url": "http://roomshare.jp", @@ -3258,19 +2968,6 @@ } ] }, - { - "provider_name": "Spotful", - "provider_url": "https://bespotful.com", - "endpoints": [ - { - "schemes": [ - "http://play.bespotful.com/*" - ], - "url": "https://api.bespotful.com/oembed", - "discovery": true - } - ] - }, { "provider_name": "Spotify", "provider_url": "https://spotify.com/", @@ -3358,19 +3055,6 @@ } ] }, - { - "provider_name": "StreamOneCloud", - "provider_url": "https://www.streamone.nl", - "endpoints": [ - { - "schemes": [ - "https://content.streamonecloud.net/embed/*" - ], - "url": "https://content.streamonecloud.net/oembed", - "discovery": true - } - ] - }, { "provider_name": "Subscribi", "provider_url": "https://subscribi.io/", @@ -3551,22 +3235,6 @@ } ] }, - { - "provider_name": "TourHero", - "provider_url": "http://www.tourhero.com", - "endpoints": [ - { - "schemes": [ - "https://www.tourhero.com/*" - ], - "url": "https://oembed.tourhero.com/", - "discovery": true, - "formats": [ - "json" - ] - } - ] - }, { "provider_name": "Trinity Audio", "provider_url": "https://trinityaudio.ai", @@ -3669,21 +3337,6 @@ } ] }, - { - "provider_name": "Ubideo", - "provider_url": "https://player.ubideo.com/", - "endpoints": [ - { - "schemes": [ - "https://player.ubideo.com/*" - ], - "url": "https://player.ubideo.com/api/oembed.json", - "formats": [ - "json" - ] - } - ] - }, { "provider_name": "University of Cambridge Map", "provider_url": "https://map.cam.ac.uk", @@ -3709,20 +3362,6 @@ } ] }, - { - "provider_name": "UOL", - "provider_url": "https://mais.uol.com.br/", - "endpoints": [ - { - "schemes": [ - "https://*.uol.com.br/view/*", - "https://*.uol.com.br/video/*" - ], - "url": "https://mais.uol.com.br/apiuol/v3/oembed/view", - "discovery": true - } - ] - }, { "provider_name": "Upec.Pod", "provider_url": "https://pod.u-pec.fr/", @@ -3736,19 +3375,6 @@ } ] }, - { - "provider_name": "uppy", - "provider_url": "https://uppy.jp", - "endpoints": [ - { - "schemes": [ - "https://app.uppy.jp/_shares/video/*" - ], - "url": "https://api.uppy.jp/v1/oembed", - "discovery": true - } - ] - }, { "provider_name": "Ustream", "provider_url": "http://www.ustream.tv", @@ -3782,37 +3408,6 @@ } ] }, - { - "provider_name": "Utposts", - "provider_url": "https://www.utposts.com/", - "endpoints": [ - { - "schemes": [ - "https://www.utposts.com/products/*", - "http://www.utposts.com/products/*", - "https://utposts.com/products/*", - "http://utposts.com/products/*" - ], - "url": "https://www.utposts.com/api/oembed", - "formats": [ - "json" - ] - } - ] - }, - { - "provider_name": "Uttles", - "provider_url": "http://uttles.com", - "endpoints": [ - { - "schemes": [ - "http://uttles.com/uttle/*" - ], - "url": "http://uttles.com/api/reply/oembed", - "discovery": true - } - ] - }, { "provider_name": "VeeR VR", "provider_url": "http://veer.tv/", @@ -3857,41 +3452,15 @@ ] }, { - "provider_name": "VideoJug", - "provider_url": "http://www.videojug.com", - "endpoints": [ - { - "schemes": [ - "http://www.videojug.com/film/*", - "http://www.videojug.com/interview/*" - ], - "url": "http://www.videojug.com/oembed.{format}" - } - ] - }, - { - "provider_name": "Vidlit", - "provider_url": "https://vidl.it/", + "provider_name": "Videfit", + "provider_url": "https://videfit.com/", "endpoints": [ { "schemes": [ - "https://vidl.it/*" + "https://videfit.com/videos/*" ], - "url": "https://api.vidl.it/oembed", - "discovery": true - } - ] - }, - { - "provider_name": "Vidmizer", - "provider_url": "https://www.vidmizer.com/", - "endpoints": [ - { - "schemes": [ - "https://players-cdn-v2.vidmizer.com/*" - ], - "url": "https://app-v2.vidmizer.com/api/oembed", - "discovery": true + "url": "https://videfit.com/oembed", + "discovery": false } ] }, @@ -3946,19 +3515,6 @@ } ] }, - { - "provider_name": "Viziosphere", - "provider_url": "http://www.viziosphere.com", - "endpoints": [ - { - "schemes": [ - "http://viziosphere.com/3dphoto*" - ], - "url": "http://viziosphere.com/services/oembed/", - "discovery": true - } - ] - }, { "provider_name": "Vizydrop", "provider_url": "https://vizydrop.com", @@ -3999,20 +3555,6 @@ } ] }, - { - "provider_name": "Vlurb", - "provider_url": "https://www.vlurb.co/", - "endpoints": [ - { - "schemes": [ - "http://vlurb.co/video/*", - "https://vlurb.co/video/*" - ], - "url": "https://vlurb.co/oembed.json", - "discovery": true - } - ] - }, { "provider_name": "VoxSnap", "provider_url": "https://voxsnap.com/", @@ -4058,10 +3600,10 @@ }, { "provider_name": "wecandeo", - "provider_url": "http://www.wecandeo.com/", + "provider_url": "https://www.wecandeo.com/", "endpoints": [ { - "url": "http://play.wecandeo.com/oembed", + "url": "https://play.wecandeo.com/oembed", "discovery": true } ] @@ -4099,16 +3641,14 @@ }, { "provider_name": "wizer.me", - "provider_url": "http://www.wizer.me/", + "provider_url": "https://www.wizer.me/", "endpoints": [ { "schemes": [ - "http://*.wizer.me/learn/*", "https://*.wizer.me/learn/*", - "http://*.wizer.me/preview/*", "https://*.wizer.me/preview/*" ], - "url": "http://app.wizer.me/api/oembed.{format}", + "url": "https://app.wizer.me/api/oembed.{format}", "discovery": true } ] @@ -4142,74 +3682,26 @@ } ] }, - { - "provider_name": "Wootled", - "provider_url": "http://www.wootled.com/", - "endpoints": [ - { - "url": "http://www.wootled.com/oembed" - } - ] - }, { "provider_name": "WordPress.com", "provider_url": "http://wordpress.com/", - "endpoints": [ - { - "url": "http://public-api.wordpress.com/oembed/", - "discovery": true - } - ] - }, - { - "provider_name": "Xpression", - "provider_url": "https://web.xpression.jp", "endpoints": [ { "schemes": [ - "https://web.xpression.jp/video/*" - ], - "url": "https://web.xpression.jp/api/oembed", - "formats": [ - "json", - "xml" - ] - } - ] - }, - { - "provider_name": "Yes, I Know IT!", - "provider_url": "http://yesik.it", - "endpoints": [ - { - "schemes": [ - "http://yesik.it/*", - "http://www.yesik.it/*" - ], - "url": "http://yesik.it/s/oembed", - "formats": [ - "json" + "https://wordpress.com/*", + "http://wordpress.com/*", + "https://*.wordpress.com/*", + "http://*.wordpress.com/*", + "https://*.*.wordpress.com/*", + "http://*.*.wordpress.com/*", + "https://wp.me/*", + "http://wp.me/*" ], + "url": "http://public-api.wordpress.com/oembed/", "discovery": true } ] }, - { - "provider_name": "YFrog", - "provider_url": "http://yfrog.com/", - "endpoints": [ - { - "schemes": [ - "http://*.yfrog.com/*", - "http://yfrog.us/*" - ], - "url": "http://www.yfrog.com/api/oembed", - "formats": [ - "json" - ] - } - ] - }, { "provider_name": "YouTube", "provider_url": "https://www.youtube.com/", @@ -4219,7 +3711,8 @@ "https://*.youtube.com/watch*", "https://*.youtube.com/v/*", "https://youtu.be/*", - "https://*.youtube.com/playlist?list=*" + "https://*.youtube.com/playlist?list=*", + "https://youtube.com/playlist?list=*" ], "url": "https://www.youtube.com/oembed", "discovery": true diff --git a/src/utils/providersFromList.js b/src/utils/providersFromList.js deleted file mode 100644 index a4bb85d..0000000 --- a/src/utils/providersFromList.js +++ /dev/null @@ -1,40 +0,0 @@ -// utils -> providersFromList - -const getHostname = (url) => { - const match = url.match(/:\/\/(www[0-9]?\.)?(.[^/:]+)/i) - if (match && match.length > 2 && typeof match[2] === 'string' && match[2].length > 0) { - return match[2] - } - return null -} - -const providersFromList = (list) => { - return list.map((item) => { - const { - provider_name, // eslint-disable-line camelcase - provider_url, // eslint-disable-line camelcase - endpoints - } = item - - const endpoint = endpoints[0] - const { - schemes = [], - url - } = endpoint - - const hostname = getHostname(url) - const domain = hostname ? hostname.replace('www.', '') : '' - - return { - provider_name, // eslint-disable-line camelcase - provider_url, // eslint-disable-line camelcase - schemes, - domain, - url - } - }).filter((item) => { - return item.domain !== '' - }) -} - -module.exports = providersFromList diff --git a/src/utils/providersFromList.test.js b/src/utils/providersFromList.test.js deleted file mode 100644 index dd8fa79..0000000 --- a/src/utils/providersFromList.test.js +++ /dev/null @@ -1,24 +0,0 @@ -// providersFromList -/* eslint-env jest */ - -const providersFromList = require('./providersFromList') - -test('test providersFromList bad URI format', () => { - const customProviderOnly = [ - { - provider_name: 'Example', - provider_url: 'http.org', - endpoints: [ - { - schemes: [ - 'example.org/media/*' - ], - url: 'org/oembed' - } - ] - } - ] - const result = providersFromList(customProviderOnly) - expect(Array.isArray(result)).toBe(true) - expect(result.length).toEqual(0) -}) diff --git a/src/utils/retrieve.js b/src/utils/retrieve.js new file mode 100644 index 0000000..e5f5ed2 --- /dev/null +++ b/src/utils/retrieve.js @@ -0,0 +1,20 @@ +// utils -> retrieve + +const got = require('got') + +const { fetchOptions } = require('../config') + +module.exports = async (url) => { + try { + const { headers, body } = await got(url, fetchOptions) + + const contentType = headers['content-type'] || '' + if (!contentType || !contentType.includes('application/json')) { + return null + } + + return body + } catch (err) { + return null + } +} diff --git a/src/utils/retrieve.test.js b/src/utils/retrieve.test.js new file mode 100644 index 0000000..d2fcc56 --- /dev/null +++ b/src/utils/retrieve.test.js @@ -0,0 +1,47 @@ +// retrieve.test +/* eslint-env jest */ + +const nock = require('nock') + +const retrieve = require('./retrieve') + +const parseUrl = (url) => { + const re = new URL(url) + return { + baseUrl: `${re.protocol}//${re.host}`, + path: re.pathname + } +} + +test('test retrieve() from good source', async () => { + const url = 'https://some.where/good/page' + const { baseUrl, path } = parseUrl(url) + const scope = nock(baseUrl) + scope.get(path).reply(200, { data: { name: 'oembed-parser' } }, { + 'Content-Type': 'application/json' + }) + const result = await retrieve(url) + expect(result.data.name).toEqual('oembed-parser') +}) + +test('test retrieve() from bad source', async () => { + const url = 'https://some.where/good/page' + const { baseUrl, path } = parseUrl(url) + const scope = nock(baseUrl) + scope.get(path).reply(500, { data: { name: 'oembed-parser' } }, { + 'Content-Type': 'application/json' + }) + const result = await retrieve(url) + expect(result).toEqual(null) +}) + +test('test retrieve() with unsupported content type', async () => { + const url = 'https://some.where/good/page' + const { baseUrl, path } = parseUrl(url) + const scope = nock(baseUrl) + scope.get(path).reply(200, { data: { name: 'oembed-parser' } }, { + 'Content-Type': 'text/json' + }) + const result = await retrieve(url) + expect(result).toEqual(null) +}) diff --git a/sync.js b/sync.js index 43fe56a..807a574 100644 --- a/sync.js +++ b/sync.js @@ -5,7 +5,11 @@ const { writeFileSync } = require('fs') -const fetch = require('cross-fetch') +const got = require('got') + +const { + fetchOptions +} = require('./src/config') const source = 'https://oembed.com/providers.json' const target = './src/utils/providers.json' @@ -13,7 +17,7 @@ const backup = './src/utils/providers.backup.json' const providerList = require(target) -const merge = (data) => { +const merge = async () => { // backup previous version writeFileSync( backup, @@ -21,6 +25,9 @@ const merge = (data) => { 'utf8' ) + const res = got(source, fetchOptions) + const data = await res.json() + // merging unlinkSync(target) writeFileSync( @@ -31,7 +38,4 @@ const merge = (data) => { console.log('Providers list has been updated') } -fetch(source) - .then((res) => res.json()) - .then(merge) - .catch(console.trace) +merge() diff --git a/test-data/facebook.json b/test-data/facebook.json new file mode 100644 index 0000000..78bd08b --- /dev/null +++ b/test-data/facebook.json @@ -0,0 +1,13 @@ +{ + "author_name": "Facebook", + "author_url": "https://www.facebook.com/facebook/", + "provider_url": "https://www.facebook.com", + "provider_name": "Facebook", + "success": true, + "height": null, + "html": "
\nHow to Share With Just FriendsHow to share with just friends.
Posted by Facebook on Friday, December 5, 2014
\n\n", + "width": 550, + "height": null, + "type": "rich", + "cache_age": "3153600000", + "provider_name": "Twitter", + "provider_url": "https://twitter.com", + "version": "1.0" +} \ No newline at end of file diff --git a/test-data/youtube.json b/test-data/youtube.json new file mode 100644 index 0000000..0d67cc5 --- /dev/null +++ b/test-data/youtube.json @@ -0,0 +1,15 @@ +{ + "title": "My dog trio", + "author_name": "Dong Nguyen", + "author_url": "https://www.youtube.com/c/DongNguyenbellajs", + "type": "video", + "height": 113, + "width": 200, + "version": "1.0", + "provider_name": "YouTube", + "provider_url": "https://www.youtube.com/", + "thumbnail_height": 360, + "thumbnail_width": 480, + "thumbnail_url": "https://i.ytimg.com/vi/qQpb1oCernE/hqdefault.jpg", + "html": "" +} \ No newline at end of file diff --git a/test-data/youtube_ciS8aCrX-9s.json b/test-data/youtube_ciS8aCrX-9s.json new file mode 100644 index 0000000..f3aa6da --- /dev/null +++ b/test-data/youtube_ciS8aCrX-9s.json @@ -0,0 +1,15 @@ +{ + "title": "prOfile", + "author_name": "Ora Walters", + "author_url": "https://www.youtube.com/c/OwenWalters", + "type": "video", + "height": 150, + "width": 200, + "version": "1.0", + "provider_name": "YouTube", + "provider_url": "https://www.youtube.com/", + "thumbnail_height": 360, + "thumbnail_width": 480, + "thumbnail_url": "https://i.ytimg.com/vi/ciS8aCrX-9s/hqdefault.jpg", + "html": "" +} \ No newline at end of fileLive event: Release Lotus - New social network in Vietnamhttps://t.co/BWGejBZRWh#lotus #SocialNetwork
— Dong Nguyen (@ndaidong) September 16, 2019