From 1bae1ad5a6064ae1a8655e84b1fd07623bf5b292 Mon Sep 17 00:00:00 2001 From: wukko Date: Wed, 29 May 2024 11:36:42 +0600 Subject: [PATCH] processing: add support for loom --- src/modules/processing/match.js | 6 +++ src/modules/processing/matchActionDecider.js | 1 + src/modules/processing/services/loom.js | 39 +++++++++++++++++++ src/modules/processing/servicesConfig.json | 7 +++- .../processing/servicesPatternTesters.js | 7 +++- 5 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/modules/processing/services/loom.js diff --git a/src/modules/processing/match.js b/src/modules/processing/match.js index 7f9714b7..baaf1623 100644 --- a/src/modules/processing/match.js +++ b/src/modules/processing/match.js @@ -24,6 +24,7 @@ import streamable from "./services/streamable.js"; import twitch from "./services/twitch.js"; import rutube from "./services/rutube.js"; import dailymotion from "./services/dailymotion.js"; +import loom from "./services/loom.js"; let freebind; @@ -186,6 +187,11 @@ export default async function(host, patternMatch, lang, obj) { case "dailymotion": r = await dailymotion(patternMatch); break; + case "loom": + r = await loom({ + id: patternMatch.id + }); + break; default: return createResponse("error", { t: loc(lang, 'ErrorUnsupported') diff --git a/src/modules/processing/matchActionDecider.js b/src/modules/processing/matchActionDecider.js index 42a35f1a..f7ed3da9 100644 --- a/src/modules/processing/matchActionDecider.js +++ b/src/modules/processing/matchActionDecider.js @@ -129,6 +129,7 @@ export default function(r, host, userFormat, isAudioOnly, lang, isAudioMuted, di case "tumblr": case "pinterest": case "streamable": + case "loom": responseType = "redirect"; break; } diff --git a/src/modules/processing/services/loom.js b/src/modules/processing/services/loom.js new file mode 100644 index 00000000..18c5a282 --- /dev/null +++ b/src/modules/processing/services/loom.js @@ -0,0 +1,39 @@ +import { genericUserAgent } from "../../config.js"; + +export default async function({ id }) { + const gql = await fetch(`https://www.loom.com/api/campaigns/sessions/${id}/transcoded-url`, { + method: "POST", + headers: { + "user-agent": genericUserAgent, + origin: "https://www.loom.com", + referer: `https://www.loom.com/share/${id}`, + cookie: `loom_referral_video=${id};`, + + "apollographql-client-name": "web", + "apollographql-client-version": "14c0b42", + "x-loom-request-source": "loom_web_14c0b42", + }, + body: { + force_original: false, + password: null, + anonID: null, + deviceID: null + } + }) + .then(r => r.status === 200 ? r.json() : false) + .catch(() => {}); + + if (!gql) return { error: 'ErrorEmptyDownload' }; + + const videoUrl = gql?.url; + + if (videoUrl?.includes('.mp4?')) { + return { + urls: videoUrl, + filename: `loom_${id}.mp4`, + audioFilename: `loom_${id}_audio` + } + } + + return { error: 'ErrorEmptyDownload' } +} diff --git a/src/modules/processing/servicesConfig.json b/src/modules/processing/servicesConfig.json index 2daa7b63..c362cb73 100644 --- a/src/modules/processing/servicesConfig.json +++ b/src/modules/processing/servicesConfig.json @@ -1,5 +1,5 @@ { - "audioIgnore": ["vk", "ok"], + "audioIgnore": ["vk", "ok", "loom"], "hlsExceptions": ["dailymotion", "vimeo", "rutube"], "config": { "bilibili": { @@ -112,6 +112,11 @@ "alias": "dailymotion videos", "patterns": ["video/:id"], "enabled": true + }, + "loom": { + "alias": "loom videos", + "patterns": ["share/:id"], + "enabled": true } } } diff --git a/src/modules/processing/servicesPatternTesters.js b/src/modules/processing/servicesPatternTesters.js index 25b8943a..b855cba4 100644 --- a/src/modules/processing/servicesPatternTesters.js +++ b/src/modules/processing/servicesPatternTesters.js @@ -8,7 +8,10 @@ export const testers = { "instagram": (patternMatch) => patternMatch.postId?.length <= 12 || (patternMatch.username?.length <= 30 && patternMatch.storyId?.length <= 24), - + + "loom": (patternMatch) => + patternMatch.id?.length <= 32, + "ok": (patternMatch) => patternMatch.id?.length <= 16, @@ -28,7 +31,7 @@ export const testers = { "streamable": (patternMatch) => patternMatch.id?.length === 6, - + "tiktok": (patternMatch) => patternMatch.postId?.length <= 21 || patternMatch.id?.length <= 13,