mirror of
https://github.com/imputnet/cobalt.git
synced 2025-07-16 18:28:29 +00:00
Merge branch 'current' into current
This commit is contained in:
commit
f282b16805
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "cobalt",
|
"name": "cobalt",
|
||||||
"description": "save what you love",
|
"description": "save what you love",
|
||||||
"version": "7.1.1",
|
"version": "7.1.2",
|
||||||
"author": "wukko",
|
"author": "wukko",
|
||||||
"exports": "./src/cobalt.js",
|
"exports": "./src/cobalt.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
@ -9,9 +9,7 @@ let com = getCommitInfo();
|
|||||||
|
|
||||||
let defaultApiURL = process.env.apiURL ? process.env.apiURL.slice(0, -1) : '';
|
let defaultApiURL = process.env.apiURL ? process.env.apiURL.slice(0, -1) : '';
|
||||||
|
|
||||||
let enabledServices = Object.keys(s).filter((p) => {
|
let enabledServices = Object.keys(s).filter(p => s[p].enabled).sort().map((p) => {
|
||||||
if (s[p].enabled) return true;
|
|
||||||
}).sort().map((p) => {
|
|
||||||
return `<br>• ${s[p].alias ? s[p].alias : p}`
|
return `<br>• ${s[p].alias ? s[p].alias : p}`
|
||||||
}).join('').substring(4)
|
}).join('').substring(4)
|
||||||
|
|
||||||
|
@ -9,12 +9,6 @@ export default function (inHost, inURL) {
|
|||||||
url = `https://youtube.com/watch?v=${url.replace("https://youtu.be/", "")}`;
|
url = `https://youtube.com/watch?v=${url.replace("https://youtu.be/", "")}`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "goo":
|
|
||||||
if (url.startsWith("https://soundcloud.app.goo.gl/")) {
|
|
||||||
host = "soundcloud";
|
|
||||||
url = `https://soundcloud.com/${url.replace("https://soundcloud.app.goo.gl/", "").split('/')[0]}`
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "vxtwitter":
|
case "vxtwitter":
|
||||||
case "x":
|
case "x":
|
||||||
if (url.startsWith("https://x.com/")) {
|
if (url.startsWith("https://x.com/")) {
|
||||||
@ -33,7 +27,6 @@ export default function (inHost, inURL) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
host: host,
|
host: host,
|
||||||
url: url
|
url: url
|
||||||
|
@ -11,13 +11,13 @@ export default async function(obj) {
|
|||||||
let streamData = JSON.parse(html.split('<script>window.__playinfo__=')[1].split('</script>')[0]);
|
let streamData = JSON.parse(html.split('<script>window.__playinfo__=')[1].split('</script>')[0]);
|
||||||
if (streamData.data.timelength > maxVideoDuration) return { error: ['ErrorLengthLimit', maxVideoDuration / 60000] };
|
if (streamData.data.timelength > maxVideoDuration) return { error: ['ErrorLengthLimit', maxVideoDuration / 60000] };
|
||||||
|
|
||||||
let video = streamData["data"]["dash"]["video"].filter((v) => {
|
let video = streamData["data"]["dash"]["video"].filter(v =>
|
||||||
if (!v["baseUrl"].includes("https://upos-sz-mirrorcosov.bilivideo.com/")) return true;
|
!v["baseUrl"].includes("https://upos-sz-mirrorcosov.bilivideo.com/")
|
||||||
}).sort((a, b) => Number(b.bandwidth) - Number(a.bandwidth));
|
).sort((a, b) => Number(b.bandwidth) - Number(a.bandwidth));
|
||||||
|
|
||||||
let audio = streamData["data"]["dash"]["audio"].filter((a) => {
|
let audio = streamData["data"]["dash"]["audio"].filter(a =>
|
||||||
if (!a["baseUrl"].includes("https://upos-sz-mirrorcosov.bilivideo.com/")) return true;
|
!a["baseUrl"].includes("https://upos-sz-mirrorcosov.bilivideo.com/")
|
||||||
}).sort((a, b) => Number(b.bandwidth) - Number(a.bandwidth));
|
).sort((a, b) => Number(b.bandwidth) - Number(a.bandwidth));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
urls: [video[0]["baseUrl"], audio[0]["baseUrl"]],
|
urls: [video[0]["baseUrl"], audio[0]["baseUrl"]],
|
||||||
|
@ -35,31 +35,31 @@ async function findClientID() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default async function(obj) {
|
export default async function(obj) {
|
||||||
let html;
|
|
||||||
if (!obj.author && !obj.song && obj.shortLink) {
|
|
||||||
html = await fetch(`https://on.soundcloud.com/${obj.shortLink}/`).then((r) => {
|
|
||||||
return r.status === 404 ? false : r.text()
|
|
||||||
}).catch(() => { return false });
|
|
||||||
}
|
|
||||||
if (obj.author && obj.song) {
|
|
||||||
html = await fetch(
|
|
||||||
`https://soundcloud.com/${obj.author}/${obj.song}${obj.accessKey ? `/s-${obj.accessKey}` : ''}`
|
|
||||||
).then((r) => {
|
|
||||||
return r.text()
|
|
||||||
}).catch(() => { return false });
|
|
||||||
}
|
|
||||||
if (!html) return { error: 'ErrorCouldntFetch' };
|
|
||||||
if (!(html.includes('<script>window.__sc_hydration = ') && html.includes('{"hydratable":"sound","data":'))) {
|
|
||||||
return { error: ['ErrorBrokenLink', 'soundcloud'] }
|
|
||||||
}
|
|
||||||
|
|
||||||
let json = JSON.parse(html.split('{"hydratable":"sound","data":')[1].split('}];</script>')[0]);
|
|
||||||
if (!json["media"]["transcodings"]) return { error: 'ErrorEmptyDownload' };
|
|
||||||
|
|
||||||
let clientId = await findClientID();
|
let clientId = await findClientID();
|
||||||
if (!clientId) return { error: 'ErrorSoundCloudNoClientId' };
|
if (!clientId) return { error: 'ErrorSoundCloudNoClientId' };
|
||||||
|
|
||||||
let fileUrlBase = json.media.transcodings.filter((v) => { if (v["format"]["mime_type"].startsWith("audio/ogg")) return true })[0]["url"],
|
let link;
|
||||||
|
if (obj.shortLink && !obj.author && !obj.song) {
|
||||||
|
link = await fetch(`https://on.soundcloud.com/${obj.shortLink}/`, { redirect: "manual" }).then((r) => {
|
||||||
|
if (r.status === 302 && r.headers.get("location").startsWith("https://soundcloud.com/")) {
|
||||||
|
return r.headers.get("location").split('?', 1)[0]
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}).catch(() => { return false });
|
||||||
|
}
|
||||||
|
if (!link && obj.author && obj.song) {
|
||||||
|
link = `https://soundcloud.com/${obj.author}/${obj.song}${obj.accessKey ? `/s-${obj.accessKey}` : ''}`
|
||||||
|
}
|
||||||
|
if (!link) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
|
let json = await fetch(`https://api-v2.soundcloud.com/resolve?url=${link}&client_id=${clientId}`).then((r) => {
|
||||||
|
return r.status === 200 ? r.json() : false
|
||||||
|
}).catch(() => { return false });
|
||||||
|
if (!json) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
|
if (!json["media"]["transcodings"]) return { error: 'ErrorEmptyDownload' };
|
||||||
|
|
||||||
|
let fileUrlBase = json.media.transcodings.filter(v => v.preset === "opus_0_0")[0]["url"],
|
||||||
fileUrl = `${fileUrlBase}${fileUrlBase.includes("?") ? "&" : "?"}client_id=${clientId}&track_authorization=${json.track_authorization}`;
|
fileUrl = `${fileUrlBase}${fileUrlBase.includes("?") ? "&" : "?"}client_id=${clientId}&track_authorization=${json.track_authorization}`;
|
||||||
|
|
||||||
if (fileUrl.substring(0, 54) !== "https://api-v2.soundcloud.com/media/soundcloud:tracks:") return { error: 'ErrorEmptyDownload' };
|
if (fileUrl.substring(0, 54) !== "https://api-v2.soundcloud.com/media/soundcloud:tracks:") return { error: 'ErrorEmptyDownload' };
|
||||||
|
@ -17,7 +17,7 @@ function selector(j, h, id) {
|
|||||||
let t;
|
let t;
|
||||||
switch (h) {
|
switch (h) {
|
||||||
case "tiktok":
|
case "tiktok":
|
||||||
t = j["aweme_list"].filter((v) => { if (v["aweme_id"] === id) return true })[0];
|
t = j["aweme_list"].filter(v => v["aweme_id"] === id)[0];
|
||||||
break;
|
break;
|
||||||
case "douyin":
|
case "douyin":
|
||||||
t = j['aweme_detail'];
|
t = j['aweme_detail'];
|
||||||
@ -92,7 +92,7 @@ export default async function(obj) {
|
|||||||
let imageLinks = [];
|
let imageLinks = [];
|
||||||
for (let i in images) {
|
for (let i in images) {
|
||||||
let sel = obj.host === "tiktok" ? images[i]["display_image"]["url_list"] : images[i]["url_list"];
|
let sel = obj.host === "tiktok" ? images[i]["display_image"]["url_list"] : images[i]["url_list"];
|
||||||
sel = sel.filter((p) => { if (p.includes(".jpeg?")) return true; })
|
sel = sel.filter(p => p.includes(".jpeg?"))
|
||||||
imageLinks.push({url: sel[0]})
|
imageLinks.push({url: sel[0]})
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { genericUserAgent } from "../../config.js";
|
import { genericUserAgent } from "../../config.js";
|
||||||
|
|
||||||
function bestQuality(arr) {
|
function bestQuality(arr) {
|
||||||
return arr.filter((v) => { if (v["content_type"] === "video/mp4") return true }).sort((a, b) => Number(b.bitrate) - Number(a.bitrate))[0]["url"]
|
return arr.filter(v => v["content_type"] === "video/mp4").sort((a, b) => Number(b.bitrate) - Number(a.bitrate))[0]["url"]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function(obj) {
|
export default async function(obj) {
|
||||||
|
@ -64,7 +64,7 @@ export default async function(obj) {
|
|||||||
let videoUrl, audioUrl, baseUrl = masterJSONURL.split("/sep/")[0];
|
let videoUrl, audioUrl, baseUrl = masterJSONURL.split("/sep/")[0];
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "parcel":
|
case "parcel":
|
||||||
let masterJSON_Audio = masterJSON.audio.sort((a, b) => Number(b.bitrate) - Number(a.bitrate)).filter((a) => { if (a['mime_type'] === "audio/mp4") return true }),
|
let masterJSON_Audio = masterJSON.audio.sort((a, b) => Number(b.bitrate) - Number(a.bitrate)).filter(a => a['mime_type'] === "audio/mp4"),
|
||||||
bestAudio = masterJSON_Audio[0];
|
bestAudio = masterJSON_Audio[0];
|
||||||
videoUrl = `${baseUrl}/parcel/video/${bestVideo.index_segment.split('?')[0]}`,
|
videoUrl = `${baseUrl}/parcel/video/${bestVideo.index_segment.split('?')[0]}`,
|
||||||
audioUrl = `${baseUrl}/parcel/audio/${bestAudio.index_segment.split('?')[0]}`;
|
audioUrl = `${baseUrl}/parcel/audio/${bestAudio.index_segment.split('?')[0]}`;
|
||||||
|
@ -39,9 +39,9 @@ export default async function(o) {
|
|||||||
if (info.playability_status.status !== 'OK') return { error: 'ErrorYTUnavailable' };
|
if (info.playability_status.status !== 'OK') return { error: 'ErrorYTUnavailable' };
|
||||||
if (info.basic_info.is_live) return { error: 'ErrorLiveVideo' };
|
if (info.basic_info.is_live) return { error: 'ErrorLiveVideo' };
|
||||||
|
|
||||||
let bestQuality, hasAudio, adaptive_formats = info.streaming_data.adaptive_formats.filter((e) => {
|
let bestQuality, hasAudio, adaptive_formats = info.streaming_data.adaptive_formats.filter(e =>
|
||||||
if (e["mime_type"].includes(c[o.format].codec) || e["mime_type"].includes(c[o.format].aCodec)) return true
|
e["mime_type"].includes(c[o.format].codec) || e["mime_type"].includes(c[o.format].aCodec)
|
||||||
}).sort((a, b) => Number(b.bitrate) - Number(a.bitrate));
|
).sort((a, b) => Number(b.bitrate) - Number(a.bitrate));
|
||||||
|
|
||||||
bestQuality = adaptive_formats.find(i => i["has_video"]);
|
bestQuality = adaptive_formats.find(i => i["has_video"]);
|
||||||
hasAudio = adaptive_formats.find(i => i["has_audio"]);
|
hasAudio = adaptive_formats.find(i => i["has_audio"]);
|
||||||
|
Loading…
Reference in New Issue
Block a user