mirror of
https://github.com/imputnet/cobalt.git
synced 2025-06-28 17:38:31 +00:00
Merge branch 'main' into main
This commit is contained in:
commit
ffe05adf2a
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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: "*",
|
||||||
},
|
},
|
||||||
|
@ -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) ||
|
||||||
|
@ -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
|
||||||
|
@ -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)) {
|
||||||
|
@ -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));
|
||||||
|
@ -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,
|
||||||
|
@ -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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
Loading…
Reference in New Issue
Block a user