Skip to content

Commit

Permalink
Add fetch embed module & test
Browse files Browse the repository at this point in the history
  • Loading branch information
ndaidong committed Jun 25, 2024
1 parent a586347 commit bdbf539
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 0 deletions.
1 change: 1 addition & 0 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"license": "MIT",
"tasks": {
"build": "deno run -A ./scripts/build_npm.ts",
"eval": "deno run --allow-net scripts/eval.ts",
"sync": "deno run --allow-net --allow-write --allow-read scripts/sync.ts"
},
"imports": {
Expand Down
3 changes: 3 additions & 0 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// mod.ts

import extractWithDiscovery from './utils/auto_discovery.ts'
import fetchEmbed from './utils/fetch_embed.ts'

export {
find as findProvider,
has as hasProvider,
Expand Down
4 changes: 4 additions & 0 deletions scripts/eval.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env deno run --allow-net

const url = Deno.args[0];
console.log(url)
130 changes: 130 additions & 0 deletions tests/feed_embed_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// feed_embed_test.ts

import { assertEquals, assertRejects } from "https://deno.land/std/testing/asserts.ts";
import { mockFetch, resetFetch } from "jsr:@c4spar/mock-fetch";
import { isObject, hasProperty } from "jsr:@ndaidong/bellajs";

import { getEndpoint } from '../utils/provider.ts'

import fetchEmbed from '../utils/fetch_embed.ts'

const parseUrl = (url: string): any => {
const re = new URL(url)
return {
baseUrl: `${re.protocol}//${re.host}`,
path: re.pathname,
}
}

Deno.test("test if fetchEmbed() works correctly", async (t) => {
const cases = [
{
input: {
url: 'https://youtu.be/iQzwqZgr8Hc',
file: './tests/test_data/youtube.json',
},
expected: {
provider_name: 'YouTube',
type: 'video',
},
},
{
input: {
url: 'https://twitter.com/ndaidong/status/1173592062878314497',
file: './tests/test_data/twitter.json',
},
expected: {
provider_name: 'Twitter',
type: 'rich',
},
},
{
input: {
url: 'https://twitter.com/ndaidong/status/1173592062878314497?theme=dark',
file: './tests/test_data/twitter-dark.json',
},
expected: {
provider_name: 'Twitter',
type: 'rich',
},
},
{
input: {
url: 'https://www.facebook.com/facebook/videos/10153231379946729/',
params: {
access_token: '845078789498971|8ff3ab4ddd45b8f018b35c4fb7edac62',
},
file: './tests/test_data/facebook.json',
},
expected: {
provider_name: 'Facebook',
type: 'video',
},
},
{
input: {
url: 'http://farm4.static.flickr.com/3123/2341623661_7c99f48bbf_m.jpg',
file: './tests/test_data/flickr-default.json',
},
expected: {
provider_name: 'Flickr',
type: 'photo',
maxwidth: 1024,
maxheight: 683,
},
},
{
input: {
url: 'http://farm4.static.flickr.com/3123/2341623661_7c99f48bbf_m.jpg',
params: {
maxwidth: 800,
maxheight: 400,
},
file: './tests/test_data/flickr-sizelimit.json',
},
expected: {
provider_name: 'Flickr',
type: 'photo',
maxwidth: 800,
maxheight: 400,
},
},
];

for (const ucase of cases) {
const { input, expected } = ucase;
const { url, file: mockFile } = input;
const params: any = input.params || {}
await t.step(`check fetchEmbed("${url}")`, async () => {
const endpoint = getEndpoint(url) || ''
const { baseUrl, path } = parseUrl(endpoint)

const queries = new URLSearchParams({
url,
format: 'json',
...params,
})

const target = `${endpoint}?${queries.toString()}`;
console.log(target)

const fakeJson = await Deno.readTextFile(mockFile);
mockFetch(target, {
body: fakeJson,
headers: {
'Content-Type': 'application/json',
}
});

const maxwidth: number = Number(params.maxwidth || 0)
const maxheight: number = Number(params.maxheight || 0)

const result = await fetchEmbed(url, { maxwidth, maxheight }, endpoint);
assertEquals(isObject(result), true);
assertEquals(result.provider_name, expected.provider_name)
assertEquals(result.type, expected.type)

resetFetch();
});
}
});
52 changes: 52 additions & 0 deletions utils/fetch_embed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// fetch_embed.ts

import { getJson, FetchOptions } from './retrieve.ts';
import { getDomain } from './linker.ts';

const isFacebookGraphDependent = (url: string): boolean => {
return getDomain(url) === 'graph.facebook.com';
}

const getFacebookGraphToken = (): string => {
const env = Deno.env.toObject();
const appId = env.FACEBOOK_APP_ID;
const clientToken = env.FACEBOOK_CLIENT_TOKEN;
return `${appId}|${clientToken}`;
}

interface Params {
[key: string]: string | number | undefined;
}

export default async (
url: string,
params: Params = {},
endpoint: string = '',
options: FetchOptions = {}
): Promise<any> => {
const query: Params = {
url,
format: 'json',
...params,
};

const maxwidth: number = Number(query.maxwidth || 0)
const maxheight: number = Number(query.maxheight || 0)

if (maxwidth <= 0) {
delete query.maxwidth;
}
if (maxheight <= 0) {
delete query.maxheight;
}

if (isFacebookGraphDependent(endpoint)) {
query.access_token = getFacebookGraphToken();
}

const queryParams = new URLSearchParams(query as Record<string, string>).toString();
const link = `${endpoint}?${queryParams}`;
const body = await getJson(link, options);
body.method = 'provider-api';
return body;
}

0 comments on commit bdbf539

Please sign in to comment.