Merge branch 'main' into main

This commit is contained in:
Syed Mufeth 2025-04-02 18:58:10 +05:30 committed by GitHub
commit ffe05adf2a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 63 additions and 19 deletions

View File

@ -1,17 +1,26 @@
import { request } from 'undici'; import { request } from 'undici';
const redirectStatuses = new Set([301, 302, 303, 307, 308]); const redirectStatuses = new Set([301, 302, 303, 307, 308]);
export async function getRedirectingURL(url, dispatcher, userAgent) { export async function getRedirectingURL(url, dispatcher, headers) {
const location = await request(url, { const params = {
dispatcher, dispatcher,
method: 'HEAD', method: 'HEAD',
headers: { 'user-agent': userAgent } headers,
}).then(r => { redirect: 'manual'
};
let location = await request(url, params).then(r => {
if (redirectStatuses.has(r.statusCode) && r.headers['location']) { if (redirectStatuses.has(r.statusCode) && r.headers['location']) {
return r.headers['location']; return r.headers['location'];
} }
}).catch(() => null); }).catch(() => null);
location ??= await fetch(url, params).then(r => {
if (redirectStatuses.has(r.status) && r.headers.has('location')) {
return r.headers.get('location');
}
}).catch(() => null);
return location; return location;
} }

View File

@ -90,7 +90,9 @@ export const services = {
"r/u_:user/comments/:id/:title", "r/u_:user/comments/:id/:title",
"r/u_:user/comments/:id/comment/:commentId", "r/u_:user/comments/:id/comment/:commentId",
"r/:sub/s/:shareId" "r/:sub/s/:shareId",
"video/:shortId",
], ],
subdomains: "*", subdomains: "*",
}, },

View File

@ -23,7 +23,8 @@ export const testers = {
pattern.id?.length <= 16 && !pattern.sub && !pattern.user pattern.id?.length <= 16 && !pattern.sub && !pattern.user
|| (pattern.sub?.length <= 22 && pattern.id?.length <= 16) || (pattern.sub?.length <= 22 && pattern.id?.length <= 16)
|| (pattern.user?.length <= 22 && pattern.id?.length <= 16) || (pattern.user?.length <= 22 && pattern.id?.length <= 16)
|| (pattern.sub?.length <= 22 && pattern.shareId?.length <= 16), || (pattern.sub?.length <= 22 && pattern.shareId?.length <= 16)
|| (pattern.shortId?.length <= 16),
"rutube": pattern => "rutube": pattern =>
(pattern.id?.length === 32 && pattern.key?.length <= 32) || (pattern.id?.length === 32 && pattern.key?.length <= 32) ||

View File

@ -527,7 +527,7 @@ export default function instagram(obj) {
// for some reason instagram decides to return HTML // for some reason instagram decides to return HTML
// instead of a redirect when requesting with a normal // instead of a redirect when requesting with a normal
// browser user-agent // browser user-agent
'curl/7.88.1' {'User-Agent': 'curl/7.88.1'}
).then(match => instagram({ ).then(match => instagram({
...obj, ...match, ...obj, ...match,
shareId: undefined shareId: undefined

View File

@ -50,12 +50,24 @@ async function getAccessToken() {
export default async function(obj) { export default async function(obj) {
let params = obj; let params = obj;
const accessToken = await getAccessToken();
const headers = {
'user-agent': genericUserAgent,
authorization: accessToken && `Bearer ${accessToken}`,
accept: 'application/json'
};
if (params.shortId) {
params = await resolveRedirectingURL(
`https://www.reddit.com/video/${params.shortId}`,
obj.dispatcher, headers
);
}
if (!params.id && params.shareId) { if (!params.id && params.shareId) {
params = await resolveRedirectingURL( params = await resolveRedirectingURL(
`https://www.reddit.com/r/${params.sub}/s/${params.shareId}`, `https://www.reddit.com/r/${params.sub}/s/${params.shareId}`,
obj.dispatcher, obj.dispatcher, headers
genericUserAgent
); );
} }
@ -63,17 +75,10 @@ export default async function(obj) {
const url = new URL(`https://www.reddit.com/comments/${params.id}.json`); const url = new URL(`https://www.reddit.com/comments/${params.id}.json`);
const accessToken = await getAccessToken();
if (accessToken) url.hostname = 'oauth.reddit.com'; if (accessToken) url.hostname = 'oauth.reddit.com';
let data = await fetch( let data = await fetch(
url, { url, { headers }
headers: {
'User-Agent': genericUserAgent,
accept: 'application/json',
authorization: accessToken && `Bearer ${accessToken}`
}
}
).then(r => r.json()).catch(() => {}); ).then(r => r.json()).catch(() => {});
if (!data || !Array.isArray(data)) { if (!data || !Array.isArray(data)) {

View File

@ -106,6 +106,14 @@ function aliasURL(url) {
url.pathname = `/share/${idPart.slice(-32)}`; url.pathname = `/share/${idPart.slice(-32)}`;
} }
break; break;
case "redd":
/* reddit short video links can be treated by changing https://v.redd.it/<id>
to https://reddit.com/video/<id>.*/
if (url.hostname === "v.redd.it" && parts.length === 2) {
url = new URL(`https://www.reddit.com/video/${parts[1]}`);
}
break;
} }
return url; return url;
@ -231,11 +239,11 @@ export function extract(url) {
return { host, patternMatch }; return { host, patternMatch };
} }
export async function resolveRedirectingURL(url, dispatcher, userAgent) { export async function resolveRedirectingURL(url, dispatcher, headers) {
const originalService = getHostIfValid(normalizeURL(url)); const originalService = getHostIfValid(normalizeURL(url));
if (!originalService) return; if (!originalService) return;
const canonicalURL = await getRedirectingURL(url, dispatcher, userAgent); const canonicalURL = await getRedirectingURL(url, dispatcher, headers);
if (!canonicalURL) return; if (!canonicalURL) return;
const { host, patternMatch } = extract(normalizeURL(canonicalURL)); const { host, patternMatch } = extract(normalizeURL(canonicalURL));

View File

@ -123,6 +123,7 @@
{ {
"name": "private instagram post", "name": "private instagram post",
"url": "https://www.instagram.com/p/C5_A1TQNPrYw4c2g9KAUTPUl8RVHqiAdAcOOSY0", "url": "https://www.instagram.com/p/C5_A1TQNPrYw4c2g9KAUTPUl8RVHqiAdAcOOSY0",
"canFail": true,
"params": {}, "params": {},
"expected": { "expected": {
"code": 400, "code": 400,

View File

@ -56,5 +56,23 @@
"code": 200, "code": 200,
"status": "tunnel" "status": "tunnel"
} }
},
{
"name": "shortened video link",
"url": "https://v.redd.it/ifg2emt5ck0e1",
"params": {},
"expected": {
"code": 200,
"status": "tunnel"
}
},
{
"name": "shortened video link (alternative)",
"url": "https://reddit.com/video/ifg2emt5ck0e1",
"params": {},
"expected": {
"code": 200,
"status": "tunnel"
}
} }
] ]