Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Video-Downloader/api/src/processing/match.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
316 lines (276 sloc)
9.59 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { strict as assert } from "node:assert"; | |
import { env } from "../config.js"; | |
import { createResponse } from "../processing/request.js"; | |
import { testers } from "./service-patterns.js"; | |
import matchAction from "./match-action.js"; | |
import { friendlyServiceName } from "./service-alias.js"; | |
import bilibili from "./services/bilibili.js"; | |
import reddit from "./services/reddit.js"; | |
import twitter from "./services/twitter.js"; | |
import youtube from "./services/youtube.js"; | |
import vk from "./services/vk.js"; | |
import ok from "./services/ok.js"; | |
import tiktok from "./services/tiktok.js"; | |
import tumblr from "./services/tumblr.js"; | |
import vimeo from "./services/vimeo.js"; | |
import soundcloud from "./services/soundcloud.js"; | |
import instagram from "./services/instagram.js"; | |
import pinterest from "./services/pinterest.js"; | |
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 snapchat from "./services/snapchat.js"; | |
import loom from "./services/loom.js"; | |
import facebook from "./services/facebook.js"; | |
import bluesky from "./services/bluesky.js"; | |
import xiaohongshu from "./services/xiaohongshu.js"; | |
let freebind; | |
export default async function({ host, patternMatch, params }) { | |
const { url } = params; | |
assert(url instanceof URL); | |
let dispatcher, requestIP; | |
if (env.freebindCIDR) { | |
if (!freebind) { | |
freebind = await import('freebind'); | |
} | |
requestIP = freebind.ip.random(env.freebindCIDR); | |
dispatcher = freebind.dispatcherFromIP(requestIP, { strict: false }); | |
} | |
try { | |
let r, | |
isAudioOnly = params.downloadMode === "audio", | |
isAudioMuted = params.downloadMode === "mute"; | |
if (!testers[host]) { | |
return createResponse("error", { | |
code: "error.api.service.unsupported" | |
}); | |
} | |
if (!(testers[host](patternMatch))) { | |
return createResponse("error", { | |
code: "error.api.link.unsupported", | |
context: { | |
service: friendlyServiceName(host), | |
} | |
}); | |
} | |
switch (host) { | |
case "twitter": | |
r = await twitter({ | |
id: patternMatch.id, | |
index: patternMatch.index - 1, | |
toGif: !!params.twitterGif, | |
alwaysProxy: params.alwaysProxy, | |
dispatcher | |
}); | |
break; | |
case "vk": | |
r = await vk({ | |
ownerId: patternMatch.ownerId, | |
videoId: patternMatch.videoId, | |
accessKey: patternMatch.accessKey, | |
quality: params.videoQuality | |
}); | |
break; | |
case "ok": | |
r = await ok({ | |
id: patternMatch.id, | |
quality: params.videoQuality | |
}); | |
break; | |
case "bilibili": | |
r = await bilibili(patternMatch); | |
break; | |
case "youtube": | |
let fetchInfo = { | |
dispatcher, | |
id: patternMatch.id.slice(0, 11), | |
quality: params.videoQuality, | |
format: params.youtubeVideoCodec, | |
isAudioOnly, | |
isAudioMuted, | |
dubLang: params.youtubeDubLang, | |
youtubeHLS: params.youtubeHLS, | |
} | |
if (url.hostname === "music.youtube.com" || isAudioOnly) { | |
fetchInfo.quality = "max"; | |
fetchInfo.format = "vp9"; | |
fetchInfo.isAudioOnly = true; | |
fetchInfo.isAudioMuted = false; | |
} | |
r = await youtube(fetchInfo); | |
break; | |
case "reddit": | |
r = await reddit({ | |
sub: patternMatch.sub, | |
id: patternMatch.id, | |
user: patternMatch.user | |
}); | |
break; | |
case "tiktok": | |
r = await tiktok({ | |
postId: patternMatch.postId, | |
shortLink: patternMatch.shortLink, | |
fullAudio: params.tiktokFullAudio, | |
isAudioOnly, | |
h265: params.tiktokH265, | |
alwaysProxy: params.alwaysProxy, | |
}); | |
break; | |
case "tumblr": | |
r = await tumblr({ | |
id: patternMatch.id, | |
user: patternMatch.user, | |
url | |
}); | |
break; | |
case "vimeo": | |
r = await vimeo({ | |
id: patternMatch.id.slice(0, 11), | |
password: patternMatch.password, | |
quality: params.videoQuality, | |
isAudioOnly, | |
}); | |
break; | |
case "soundcloud": | |
isAudioOnly = true; | |
isAudioMuted = false; | |
r = await soundcloud({ | |
url, | |
author: patternMatch.author, | |
song: patternMatch.song, | |
format: params.audioFormat, | |
shortLink: patternMatch.shortLink || false, | |
accessKey: patternMatch.accessKey || false | |
}); | |
break; | |
case "instagram": | |
r = await instagram({ | |
...patternMatch, | |
quality: params.videoQuality, | |
alwaysProxy: params.alwaysProxy, | |
dispatcher | |
}) | |
break; | |
case "pinterest": | |
r = await pinterest({ | |
id: patternMatch.id, | |
shortLink: patternMatch.shortLink || false | |
}); | |
break; | |
case "streamable": | |
r = await streamable({ | |
id: patternMatch.id, | |
quality: params.videoQuality, | |
isAudioOnly, | |
}); | |
break; | |
case "twitch": | |
r = await twitch({ | |
clipId: patternMatch.clip || false, | |
quality: params.videoQuality, | |
isAudioOnly, | |
}); | |
break; | |
case "rutube": | |
r = await rutube({ | |
id: patternMatch.id, | |
yappyId: patternMatch.yappyId, | |
key: patternMatch.key, | |
quality: params.videoQuality, | |
isAudioOnly, | |
}); | |
break; | |
case "dailymotion": | |
r = await dailymotion(patternMatch); | |
break; | |
case "snapchat": | |
r = await snapchat({ | |
...patternMatch, | |
alwaysProxy: params.alwaysProxy, | |
}); | |
break; | |
case "loom": | |
r = await loom({ | |
id: patternMatch.id | |
}); | |
break; | |
case "facebook": | |
r = await facebook({ | |
...patternMatch | |
}); | |
break; | |
case "bsky": | |
r = await bluesky({ | |
...patternMatch, | |
alwaysProxy: params.alwaysProxy, | |
dispatcher | |
}); | |
break; | |
case "xiaohongshu": | |
r = await xiaohongshu({ | |
...patternMatch, | |
h265: params.tiktokH265, | |
isAudioOnly, | |
dispatcher, | |
}); | |
break; | |
default: | |
return createResponse("error", { | |
code: "error.api.service.unsupported" | |
}); | |
} | |
if (r.isAudioOnly) { | |
isAudioOnly = true; | |
isAudioMuted = false; | |
} | |
if (r.error && r.critical) { | |
return createResponse("critical", { | |
code: `error.api.${r.error}`, | |
}) | |
} | |
if (r.error) { | |
let context; | |
switch(r.error) { | |
case "content.too_long": | |
context = { | |
limit: env.durationLimit / 60, | |
} | |
break; | |
case "fetch.fail": | |
case "fetch.rate": | |
case "fetch.critical": | |
case "link.unsupported": | |
case "content.video.unavailable": | |
context = { | |
service: friendlyServiceName(host), | |
} | |
break; | |
} | |
return createResponse("error", { | |
code: `error.api.${r.error}`, | |
context, | |
}) | |
} | |
return matchAction({ | |
r, | |
host, | |
audioFormat: params.audioFormat, | |
isAudioOnly, | |
isAudioMuted, | |
disableMetadata: params.disableMetadata, | |
filenameStyle: params.filenameStyle, | |
twitterGif: params.twitterGif, | |
requestIP, | |
audioBitrate: params.audioBitrate, | |
alwaysProxy: params.alwaysProxy, | |
}) | |
} catch { | |
return createResponse("error", { | |
code: "error.api.fetch.critical", | |
context: { | |
service: friendlyServiceName(host), | |
} | |
}) | |
} | |
} |