From cd1d699886d5cff3c8a23ba220c0e2fd2d0ce290 Mon Sep 17 00:00:00 2001 From: Blobadoodle Date: Sat, 19 Aug 2023 17:42:10 +0100 Subject: [PATCH] feat: streamable support --- src/modules/processing/match.js | 8 ++++ src/modules/processing/matchActionDecider.js | 1 + src/modules/processing/services/streamable.js | 21 +++++++++++ src/modules/processing/servicesConfig.json | 5 +++ .../processing/servicesPatternTesters.js | 4 +- src/test/tests.json | 37 +++++++++++++++++++ 6 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 src/modules/processing/services/streamable.js diff --git a/src/modules/processing/match.js b/src/modules/processing/match.js index 70a31a21..0552f2da 100644 --- a/src/modules/processing/match.js +++ b/src/modules/processing/match.js @@ -18,6 +18,7 @@ import soundcloud from "./services/soundcloud.js"; import instagram from "./services/instagram.js"; import vine from "./services/vine.js"; import pinterest from "./services/pinterest.js"; +import streamable from "./services/streamable.js"; export default async function (host, patternMatch, url, lang, obj) { try { @@ -114,6 +115,13 @@ export default async function (host, patternMatch, url, lang, obj) { case "pinterest": r = await pinterest({ id: patternMatch["id"] }); break; + case "streamable": + r = await streamable({ + id: patternMatch["id"], + quality: obj.vQuality, + isAudioOnly: isAudioOnly, + }); + break; default: return apiJSON(0, { t: errorUnsupported(lang) }); } diff --git a/src/modules/processing/matchActionDecider.js b/src/modules/processing/matchActionDecider.js index 6d1b46b5..e46991fa 100644 --- a/src/modules/processing/matchActionDecider.js +++ b/src/modules/processing/matchActionDecider.js @@ -56,6 +56,7 @@ export default function(r, host, audioFormat, isAudioOnly, lang, isAudioMuted) { case "tumblr": case "twitter": case "pinterest": + case "streamable": responseType = 1; break; } diff --git a/src/modules/processing/services/streamable.js b/src/modules/processing/services/streamable.js new file mode 100644 index 00000000..9e5da11a --- /dev/null +++ b/src/modules/processing/services/streamable.js @@ -0,0 +1,21 @@ +export default async function(obj) { + const video = await fetch(`https://api.streamable.com/videos/${obj.id}`) + .then((r) => { + if (r.status === 404) + return undefined; + else + return r.json(); + }).catch(() => { return false }); + + if (video === undefined) return { error: 'ErrorEmptyDownload' } ; + else if (!video) return { error: 'ErrorCouldntFetch' }; // not sure if this is the correct error here, should it be this or ErrorCantConnectToServiceAPI + + let best; + if (obj.isAudioOnly || obj.quality === "max" || obj.quality >= "720") // audio seems to be compressed on the mp4-mobile version so isAudiOnly only usese the higest quality + best = video.files.mp4 ?? video.files['mp4-mobile']; + else + best = video.files['mp4-mobile'] ?? video.files.mp4; + + if (best) return { urls: best.url, filename: `streamable_${obj.id}_${best.width}x${best.height}.mp4`, audioFilename: `streamable_${obj.id}_audio` }; // video filename isnt actually used since its redirected but who cares + else return { error: 'ErrorEmptyDownload' } +} diff --git a/src/modules/processing/servicesConfig.json b/src/modules/processing/servicesConfig.json index a9219354..69dad6ab 100644 --- a/src/modules/processing/servicesConfig.json +++ b/src/modules/processing/servicesConfig.json @@ -67,6 +67,11 @@ "alias": "pinterest videos & stories", "patterns": ["pin/:id"], "enabled": true + }, + "streamable": { + "alias": "streamable videos", + "patterns": [":id", "o/:id"], + "enabled": true } } } diff --git a/src/modules/processing/servicesPatternTesters.js b/src/modules/processing/servicesPatternTesters.js index c336afcc..5c759acf 100644 --- a/src/modules/processing/servicesPatternTesters.js +++ b/src/modules/processing/servicesPatternTesters.js @@ -30,5 +30,7 @@ export const testers = { "vine": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length <= 12), - "pinterest": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length <= 128) + "pinterest": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length <= 128), + + "streamable": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length == 6) } diff --git a/src/test/tests.json b/src/test/tests.json index bfac3bec..c777f9e4 100644 --- a/src/test/tests.json +++ b/src/test/tests.json @@ -983,5 +983,42 @@ "code": 200, "status": "redirect" } + }], + "streamable": [{ + "name": "regular video", + "url": "https://streamable.com/03r3c2", + "params": {}, + "expected": { + "code": 200, + "status": "redirect" + } + }, { + "name": "regular video (isAudioOnly)", + "url": "https://streamable.com/03r3c2", + "params": { + "isAudioOnly": true + }, + "expected": { + "code": 200, + "status": "stream" + } + }, { + "name": "regular video (isAudioMuted)", + "url": "https://streamable.com/03r3c2", + "params": { + "isAudioMuted": true + }, + "expected": { + "code": 200, + "status": "stream" + } + }, { + "name": "inexistent video", + "url": "https://streamable.com/XXXXXX", + "params": {}, + "expected": { + "code": 400, + "status": "error" + } }] } \ No newline at end of file