mirror of
https://github.com/wukko/cobalt.git
synced 2025-02-13 14:16:25 +01:00
merge: 10.7.3 from main
This commit is contained in:
commit
c31c484894
14 changed files with 63 additions and 31 deletions
3
.github/workflows/test-services.yml
vendored
3
.github/workflows/test-services.yml
vendored
|
@ -31,3 +31,6 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
- run: pnpm i --frozen-lockfile && node api/src/util/test run-tests-for ${{ matrix.service }}
|
- run: pnpm i --frozen-lockfile && node api/src/util/test run-tests-for ${{ matrix.service }}
|
||||||
|
env:
|
||||||
|
API_EXTERNAL_PROXY: ${{ secrets.API_EXTERNAL_PROXY }}
|
||||||
|
TEST_IGNORE_SERVICES: "none"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@imput/cobalt-api",
|
"name": "@imput/cobalt-api",
|
||||||
"description": "save what you love",
|
"description": "save what you love",
|
||||||
"version": "10.7.2",
|
"version": "10.7.3",
|
||||||
"author": "imput",
|
"author": "imput",
|
||||||
"exports": "./src/cobalt.js",
|
"exports": "./src/cobalt.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
@ -23,6 +23,10 @@ export async function runTest(url, params, expect) {
|
||||||
if (expect.status !== result.body.status) {
|
if (expect.status !== result.body.status) {
|
||||||
const detail = `${expect.status} (expected) != ${result.body.status} (actual)`;
|
const detail = `${expect.status} (expected) != ${result.body.status} (actual)`;
|
||||||
error.push(`status mismatch: ${detail}`);
|
error.push(`status mismatch: ${detail}`);
|
||||||
|
|
||||||
|
if (result.body.status === 'error') {
|
||||||
|
error.push(`error code: ${result.body?.error?.code}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expect.errorCode && expect.errorCode !== result.body?.error?.code) {
|
if (expect.errorCode && expect.errorCode !== result.body?.error?.code) {
|
||||||
|
|
|
@ -305,12 +305,12 @@ export default function instagram(obj) {
|
||||||
if (sidecar) {
|
if (sidecar) {
|
||||||
const picker = sidecar.edges.filter(e => e.node?.display_url)
|
const picker = sidecar.edges.filter(e => e.node?.display_url)
|
||||||
.map((e, i) => {
|
.map((e, i) => {
|
||||||
const type = e.node?.is_video ? "video" : "photo";
|
const type = e.node?.is_video && e.node?.video_url ? "video" : "photo";
|
||||||
|
|
||||||
let url;
|
let url;
|
||||||
if (type === 'video') {
|
if (type === "video") {
|
||||||
url = e.node?.video_url;
|
url = e.node?.video_url;
|
||||||
} else if (type === 'photo') {
|
} else if (type === "photo") {
|
||||||
url = e.node?.display_url;
|
url = e.node?.display_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ export default async function(o) {
|
||||||
|
|
||||||
let fileMetadata = {
|
let fileMetadata = {
|
||||||
title: videoData.movie.title.trim(),
|
title: videoData.movie.title.trim(),
|
||||||
author: (videoData.author?.name || videoData.compilationTitle).trim(),
|
author: (videoData.author?.name || videoData.compilationTitle)?.trim(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bestVideo) return {
|
if (bestVideo) return {
|
||||||
|
|
|
@ -98,6 +98,14 @@ function aliasURL(url) {
|
||||||
if (url.hostname === 'xhslink.com' && parts.length === 3) {
|
if (url.hostname === 'xhslink.com' && parts.length === 3) {
|
||||||
url = new URL(`https://www.xiaohongshu.com/a/${parts[2]}`);
|
url = new URL(`https://www.xiaohongshu.com/a/${parts[2]}`);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "loom":
|
||||||
|
const idPart = parts[parts.length - 1];
|
||||||
|
if (idPart.length > 32) {
|
||||||
|
url.pathname = `/share/${idPart.slice(-32)}`;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { env } from "../config.js";
|
||||||
import { runTest } from "../misc/run-test.js";
|
import { runTest } from "../misc/run-test.js";
|
||||||
import { loadJSON } from "../misc/load-from-fs.js";
|
import { loadJSON } from "../misc/load-from-fs.js";
|
||||||
import { Red, Bright } from "../misc/console-text.js";
|
import { Red, Bright } from "../misc/console-text.js";
|
||||||
|
import { setGlobalDispatcher, ProxyAgent } from "undici";
|
||||||
import { randomizeCiphers } from "../misc/randomize-ciphers.js";
|
import { randomizeCiphers } from "../misc/randomize-ciphers.js";
|
||||||
|
|
||||||
import { services } from "../processing/service-config.js";
|
import { services } from "../processing/service-config.js";
|
||||||
|
@ -13,7 +14,11 @@ const getTests = (service) => loadJSON(getTestPath(service));
|
||||||
|
|
||||||
// services that are known to frequently fail due to external
|
// services that are known to frequently fail due to external
|
||||||
// factors (e.g. rate limiting)
|
// factors (e.g. rate limiting)
|
||||||
const finnicky = new Set(['bilibili', 'instagram', 'facebook', 'youtube', 'vk', 'twitter', 'reddit']);
|
const finnicky = new Set(
|
||||||
|
typeof process.env.TEST_IGNORE_SERVICES === 'string'
|
||||||
|
? process.env.TEST_IGNORE_SERVICES.split(',')
|
||||||
|
: ['bilibili', 'instagram', 'facebook', 'youtube', 'vk', 'twitter', 'reddit']
|
||||||
|
);
|
||||||
|
|
||||||
const runTestsFor = async (service) => {
|
const runTestsFor = async (service) => {
|
||||||
const tests = getTests(service);
|
const tests = getTests(service);
|
||||||
|
@ -64,6 +69,14 @@ const printHeader = (service, padLen) => {
|
||||||
console.log(service + '='.repeat(50));
|
console.log(service + '='.repeat(50));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (env.externalProxy) {
|
||||||
|
setGlobalDispatcher(new ProxyAgent(env.externalProxy));
|
||||||
|
}
|
||||||
|
|
||||||
|
env.streamLifespan = 10000;
|
||||||
|
env.apiURL = 'http://x/';
|
||||||
|
randomizeCiphers();
|
||||||
|
|
||||||
const action = process.argv[2];
|
const action = process.argv[2];
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case "get-services":
|
case "get-services":
|
||||||
|
@ -86,9 +99,6 @@ switch (action) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "run-tests-for":
|
case "run-tests-for":
|
||||||
env.streamLifespan = 10000;
|
|
||||||
env.apiURL = 'http://x/';
|
|
||||||
randomizeCiphers();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { softFails } = await runTestsFor(process.argv[3]);
|
const { softFails } = await runTestsFor(process.argv[3]);
|
||||||
|
@ -104,10 +114,6 @@ switch (action) {
|
||||||
const maxHeaderLen = Object.keys(services).reduce((n, v) => v.length > n ? v.length : n, 0);
|
const maxHeaderLen = Object.keys(services).reduce((n, v) => v.length > n ? v.length : n, 0);
|
||||||
const failCounters = {};
|
const failCounters = {};
|
||||||
|
|
||||||
env.streamLifespan = 10000;
|
|
||||||
env.apiURL = 'http://x/';
|
|
||||||
randomizeCiphers();
|
|
||||||
|
|
||||||
for (const service in services) {
|
for (const service in services) {
|
||||||
printHeader(service, maxHeaderLen);
|
printHeader(service, maxHeaderLen);
|
||||||
const { fails, softFails } = await runTestsFor(service);
|
const { fails, softFails } = await runTestsFor(service);
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
{
|
{
|
||||||
"name": "shortlink video",
|
"name": "shortlink video",
|
||||||
"url": "https://fb.watch/r1K6XHMfGT/",
|
"url": "https://fb.watch/r1K6XHMfGT/",
|
||||||
"canFail": true,
|
|
||||||
"params": {},
|
"params": {},
|
||||||
"expected": {
|
"expected": {
|
||||||
"code": 200,
|
"code": 200,
|
||||||
|
@ -39,7 +38,6 @@
|
||||||
{
|
{
|
||||||
"name": "reel video",
|
"name": "reel video",
|
||||||
"url": "https://web.facebook.com/reel/730293269054758",
|
"url": "https://web.facebook.com/reel/730293269054758",
|
||||||
"canFail": true,
|
|
||||||
"params": {},
|
"params": {},
|
||||||
"expected": {
|
"expected": {
|
||||||
"code": 200,
|
"code": 200,
|
||||||
|
@ -64,4 +62,4 @@
|
||||||
"status": "redirect"
|
"status": "redirect"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -102,9 +102,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "retweeted video",
|
"name": "retweeted video",
|
||||||
"url": "https://twitter.com/uwukko/status/1696901469633421344",
|
"url": "https://twitter.com/schlizzawg/status/1869017025055793405",
|
||||||
"params": {},
|
"params": {},
|
||||||
"canFail": true,
|
|
||||||
"expected": {
|
"expected": {
|
||||||
"code": 200,
|
"code": 200,
|
||||||
"status": "redirect"
|
"status": "redirect"
|
||||||
|
@ -145,7 +144,7 @@
|
||||||
"params": {},
|
"params": {},
|
||||||
"expected": {
|
"expected": {
|
||||||
"code": 200,
|
"code": 200,
|
||||||
"status": "redirect"
|
"status": "tunnel"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -203,11 +202,11 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "bookmarked photo",
|
"name": "bookmarked photo",
|
||||||
"url": "https://twitter.com/i/bookmarks?post_id=1837430141179289876",
|
"url": "https://twitter.com/i/bookmarks?post_id=1887450602164396149",
|
||||||
"params": {},
|
"params": {},
|
||||||
"expected": {
|
"expected": {
|
||||||
"code": 200,
|
"code": 200,
|
||||||
"status": "redirect"
|
"status": "tunnel"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -48,7 +48,6 @@
|
||||||
{
|
{
|
||||||
"name": "short link, wrong id",
|
"name": "short link, wrong id",
|
||||||
"url": "https://xhslink.com/a/aaaaaa",
|
"url": "https://xhslink.com/a/aaaaaa",
|
||||||
"canFail": true,
|
|
||||||
"params": {},
|
"params": {},
|
||||||
"expected": {
|
"expected": {
|
||||||
"code": 400,
|
"code": 400,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@imput/cobalt-web",
|
"name": "@imput/cobalt-web",
|
||||||
"version": "10.6",
|
"version": "10.7.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -50,7 +50,9 @@
|
||||||
<div class="picker-body">
|
<div class="picker-body">
|
||||||
{#if items}
|
{#if items}
|
||||||
{#each items as item, i}
|
{#each items as item, i}
|
||||||
<PickerItem {item} number={i + 1} />
|
{#if item?.url}
|
||||||
|
<PickerItem {item} number={i + 1} />
|
||||||
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,18 +14,28 @@
|
||||||
export let number: number;
|
export let number: number;
|
||||||
|
|
||||||
let imageLoaded = false;
|
let imageLoaded = false;
|
||||||
const isTunnel = new URL(item.url).pathname === "/tunnel";
|
|
||||||
|
let validUrl = false;
|
||||||
|
try {
|
||||||
|
new URL(item.url);
|
||||||
|
validUrl = true;
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
const isTunnel = validUrl && new URL(item.url).pathname === "/tunnel";
|
||||||
|
|
||||||
$: itemType = item.type ?? "photo";
|
$: itemType = item.type ?? "photo";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="picker-item"
|
class="picker-item"
|
||||||
on:click={() =>
|
on:click={() => {
|
||||||
downloadFile({
|
if (validUrl) {
|
||||||
url: item.url,
|
downloadFile({
|
||||||
urlType: isTunnel ? "tunnel" : "redirect",
|
url: item.url,
|
||||||
})}
|
urlType: isTunnel ? "tunnel" : "redirect",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div class="picker-type">
|
<div class="picker-type">
|
||||||
{#if itemType === "video"}
|
{#if itemType === "video"}
|
||||||
|
|
|
@ -72,6 +72,9 @@ export const youtubeLanguages = [
|
||||||
"ur",
|
"ur",
|
||||||
"uz",
|
"uz",
|
||||||
"vi",
|
"vi",
|
||||||
|
"zh",
|
||||||
|
"zh-Hans",
|
||||||
|
"zh-Hant",
|
||||||
"zh-CN",
|
"zh-CN",
|
||||||
"zh-HK",
|
"zh-HK",
|
||||||
"zh-TW",
|
"zh-TW",
|
||||||
|
|
Loading…
Reference in a new issue