This commit is contained in:
whale 2026-10-05 09:36:51 +00:00 • committed by GitHub
commit e91a1c5282
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 137 additions and 0 deletions

View file

@ -17,6 +17,7 @@ if the desired service isn't supported yet, feel free to create an appropriate i
| service | video + audio | only audio | only video | metadata | rich file names |
| :-------- | :-----------: | :--------: | :--------: | :------: | :-------------: |
| alipay | ✅ | ❌ | ✅ | ✅ | ➖ |
| bilibili | ✅ | ✅ | ✅ | ➖ | ➖ |
| bluesky | ✅ | ✅ | ✅ | ➖ | ➖ |
| dailymotion | ✅ | ✅ | ✅ | ✅ | ✅ |

View file

@ -25,6 +25,7 @@ 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 alipay from "./services/alipay.js";
import loom from "./services/loom.js";
import facebook from "./services/facebook.js";
import bluesky from "./services/bluesky.js";
@ -237,6 +238,10 @@ export default async function({ host, patternMatch, params, authType }) {
});
break;
case "alipay":
r = await alipay(patternMatch);
break;
case "loom":
r = await loom({
id: patternMatch.id,

View file

@ -4,6 +4,13 @@ export const audioIgnore = new Set(["vk", "ok", "loom"]);
export const hlsExceptions = new Set(["dailymotion", "vimeo", "rutube", "bsky", "youtube"]);
export const services = {
alipay: {
patterns: [
"video/:contentId",
"_shortLink/:shortLink"
],
subdomains: ["render", "ur"],
},
bilibili: {
patterns: [
"video/:comId",

View file

@ -22,6 +22,10 @@ export const testers = {
pattern.shareId?.length <= 16 ||
(pattern.username?.length <= 30 && pattern.storyId?.length <= 24),
"alipay": pattern =>
pattern.contentId?.length <= 40 ||
pattern.shortLink?.length <= 40,
"loom": pattern =>
pattern.id?.length <= 32,

View file

@ -0,0 +1,72 @@
import { genericUserAgent } from "../../config.js";
import { getRedirectingURL } from "../../misc/utils.js";
const gateway = "https://webgw-internet.alipay.com/contentservice/com.alipay.sofa.function.SOFAFunction/apply/myjf.yuyan.contentservice.default.ContentWebGWController.list";
const contentIdRegex = /contentId(?:%253D|%3D|=)([A-Za-z0-9]+)/;
const clarities = ["1080P_h265_EH", "1080P_h265", "720P_h265", "720P_h264", "540P_h264"];
const headers = {
"user-agent": genericUserAgent,
"content-type": "application/json",
"x-webgw-appid": "180020010001266490",
"x-webgw-version": "2.0"
};
async function getContent(contentId) {
const json = await fetch(gateway, {
method: "POST",
headers,
body: JSON.stringify({ contentId })
}).then(r => r.json()).catch(() => {});
if (!json?.success) return;
return json.resultObj?.data?.[0];
}
async function pickStream(vid) {
const [base, token] = vid.split("?t=");
if (!token) return vid;
const prefix = base.slice(0, base.lastIndexOf("/"));
for (const clarity of clarities) {
const url = `${prefix}/${clarity}?t=${token}`;
const status = await fetch(url, {
headers: { "user-agent": genericUserAgent, range: "bytes=0-1" }
}).then(r => r.status).catch(() => 0);
if (status === 200 || status === 206) return url;
}
return vid;
}
export default async function({ contentId, shortLink }) {
let id = contentId;
if (!id && shortLink) {
const location = await getRedirectingURL(`https://ur.lepudding.com/${shortLink}`);
id = location?.match(contentIdRegex)?.[1];
}
if (!id) return { error: "fetch.short_link" };
const content = await getContent(id);
if (!content) return { error: "fetch.fail" };
if (!content.video?.vid) return { error: "fetch.empty" };
const url = await pickStream(content.video.vid);
const fileMetadata = {
title: content.title,
artist: content.author?.nickName
};
return {
urls: url,
filename: `alipay_${id}.mp4`,
audioFilename: `alipay_${id}_audio`,
fileMetadata
};
}

View file

@ -97,6 +97,23 @@ function aliasURL(url) {
}
break;
case "lepudding":
if (url.hostname === 'ur.lepudding.com' && parts.length === 2) {
url = new URL(`https://alipay.com/_shortLink/${
encodeURIComponent(parts[1])
}`);
}
break;
case "alipay":
if (url.pathname.endsWith('/video-share.html')) {
const contentId = url.search.match(/contentId(?:%253D|%3D|=)([A-Za-z0-9]+)/)?.[1];
if (contentId) {
url = new URL(`https://alipay.com/video/${contentId}`);
}
}
break;
case "loom":
const idPart = parts[parts.length - 1];
if (idPart.length > 32) {

View file

@ -0,0 +1,31 @@
[
{
"name": "short link video",
"url": "https://ur.lepudding.com/_3Je3KhPExzQMlHZRvuBgcd",
"params": {},
"expected": {
"code": 200,
"status": "tunnel"
}
},
{
"name": "short link video (muted)",
"url": "https://ur.lepudding.com/_3Je3KhPExzQMlHZRvuBgcd",
"params": {
"downloadMode": "mute"
},
"expected": {
"code": 200,
"status": "tunnel"
}
},
{
"name": "content id link",
"url": "https://alipay.com/video/20260913OB020010038324417829",
"params": {},
"expected": {
"code": 200,
"status": "tunnel"
}
}
]