mirror of
https://github.com/wukko/cobalt.git
synced 2024-11-15 04:39:58 +00:00
services: clean up functions and improve readability
This commit is contained in:
parent
9eed3b5b67
commit
c6f1184e55
12 changed files with 78 additions and 46 deletions
|
@ -31,7 +31,7 @@ function extractBestQuality(dashData) {
|
||||||
async function com_download(id) {
|
async function com_download(id) {
|
||||||
let html = await fetch(`https://bilibili.com/video/${id}`, {
|
let html = await fetch(`https://bilibili.com/video/${id}`, {
|
||||||
headers: { "user-agent": genericUserAgent }
|
headers: { "user-agent": genericUserAgent }
|
||||||
}).then((r) => { return r.text() }).catch(() => { return false });
|
}).then(r => r.text()).catch(() => {});
|
||||||
if (!html) return { error: 'ErrorCouldntFetch' };
|
if (!html) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
if (!(html.includes('<script>window.__playinfo__=') && html.includes('"video_codecid"'))) {
|
if (!(html.includes('<script>window.__playinfo__=') && html.includes('"video_codecid"'))) {
|
||||||
|
|
|
@ -17,19 +17,27 @@ export default async function(o) {
|
||||||
|
|
||||||
let html = await fetch(`https://ok.ru/video/${o.id}`, {
|
let html = await fetch(`https://ok.ru/video/${o.id}`, {
|
||||||
headers: { "user-agent": genericUserAgent }
|
headers: { "user-agent": genericUserAgent }
|
||||||
}).then((r) => { return r.text() }).catch(() => { return false });
|
}).then(r => r.text()).catch(() => {});
|
||||||
|
|
||||||
if (!html) return { error: 'ErrorCouldntFetch' };
|
if (!html) return { error: 'ErrorCouldntFetch' };
|
||||||
if (!html.includes(`<div data-module="OKVideo" data-options="{`)) {
|
if (!html.includes(`<div data-module="OKVideo" data-options="{`)) {
|
||||||
return { error: 'ErrorEmptyDownload' };
|
return { error: 'ErrorEmptyDownload' };
|
||||||
}
|
}
|
||||||
|
|
||||||
let videoData = html.split(`<div data-module="OKVideo" data-options="`)[1].split('" data-')[0].replaceAll(""", '"');
|
let videoData = html.split(`<div data-module="OKVideo" data-options="`)[1]
|
||||||
|
.split('" data-')[0]
|
||||||
|
.replaceAll(""", '"');
|
||||||
|
|
||||||
videoData = JSON.parse(JSON.parse(videoData).flashvars.metadata);
|
videoData = JSON.parse(JSON.parse(videoData).flashvars.metadata);
|
||||||
|
|
||||||
if (videoData.provider !== "UPLOADED_ODKL") return { error: 'ErrorUnsupported' };
|
if (videoData.provider !== "UPLOADED_ODKL")
|
||||||
if (videoData.movie.is_live) return { error: 'ErrorLiveVideo' };
|
return { error: 'ErrorUnsupported' };
|
||||||
if (videoData.movie.duration > env.durationLimit) return { error: ['ErrorLengthLimit', env.durationLimit / 60] };
|
|
||||||
|
if (videoData.movie.is_live)
|
||||||
|
return { error: 'ErrorLiveVideo' };
|
||||||
|
|
||||||
|
if (videoData.movie.duration > env.durationLimit)
|
||||||
|
return { error: ['ErrorLengthLimit', env.durationLimit / 60] };
|
||||||
|
|
||||||
let videos = videoData.videos.filter(v => !v.disallowed);
|
let videos = videoData.videos.filter(v => !v.disallowed);
|
||||||
let bestVideo = videos.find(v => resolutions[v.name] === quality) || videos[videos.length - 1];
|
let bestVideo = videos.find(v => resolutions[v.name] === quality) || videos[videos.length - 1];
|
||||||
|
|
|
@ -7,16 +7,16 @@ export default async function(o) {
|
||||||
let id = o.id;
|
let id = o.id;
|
||||||
|
|
||||||
if (!o.id && o.shortLink) {
|
if (!o.id && o.shortLink) {
|
||||||
id = await fetch(`https://api.pinterest.com/url_shortener/${o.shortLink}/redirect/`, { redirect: "manual" }).then((r) => {
|
id = await fetch(`https://api.pinterest.com/url_shortener/${o.shortLink}/redirect/`, { redirect: "manual" })
|
||||||
return r.headers.get("location").split('pin/')[1].split('/')[0]
|
.then(r => r.headers.get("location").split('pin/')[1].split('/')[0])
|
||||||
}).catch(() => {});
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
if (id.includes("--")) id = id.split("--")[1];
|
if (id.includes("--")) id = id.split("--")[1];
|
||||||
if (!id) return { error: 'ErrorCouldntFetch' };
|
if (!id) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
let html = await fetch(`https://www.pinterest.com/pin/${id}/`, {
|
let html = await fetch(`https://www.pinterest.com/pin/${id}/`, {
|
||||||
headers: { "user-agent": genericUserAgent }
|
headers: { "user-agent": genericUserAgent }
|
||||||
}).then((r) => { return r.text() }).catch(() => { return false });
|
}).then(r => r.text()).catch(() => {});
|
||||||
|
|
||||||
if (!html) return { error: 'ErrorCouldntFetch' };
|
if (!html) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ async function getAccessToken() {
|
||||||
'accept': 'application/json'
|
'accept': 'application/json'
|
||||||
},
|
},
|
||||||
body: `grant_type=refresh_token&refresh_token=${encodeURIComponent(values.refresh_token)}`
|
body: `grant_type=refresh_token&refresh_token=${encodeURIComponent(values.refresh_token)}`
|
||||||
}).then(r => r.json()).catch(_ => {});
|
}).then(r => r.json()).catch(() => {});
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
const { access_token, refresh_token, expires_in } = data;
|
const { access_token, refresh_token, expires_in } = data;
|
||||||
|
@ -91,7 +91,7 @@ export default async function(obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// test the existence of audio
|
// test the existence of audio
|
||||||
await fetch(audioFileLink, { method: "HEAD" }).then((r) => {
|
await fetch(audioFileLink, { method: "HEAD" }).then(r => {
|
||||||
if (Number(r.status) === 200) {
|
if (Number(r.status) === 200) {
|
||||||
audio = true
|
audio = true
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ export default async function(obj) {
|
||||||
// fallback for videos with variable audio quality
|
// fallback for videos with variable audio quality
|
||||||
if (!audio) {
|
if (!audio) {
|
||||||
audioFileLink = `${video.split('_')[0]}_AUDIO_128.mp4`
|
audioFileLink = `${video.split('_')[0]}_AUDIO_128.mp4`
|
||||||
await fetch(audioFileLink, { method: "HEAD" }).then((r) => {
|
await fetch(audioFileLink, { method: "HEAD" }).then(r => {
|
||||||
if (Number(r.status) === 200) {
|
if (Number(r.status) === 200) {
|
||||||
audio = true
|
audio = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ export default async function(obj) {
|
||||||
|
|
||||||
let bestQuality = m3u8[0];
|
let bestQuality = m3u8[0];
|
||||||
if (Number(quality) < bestQuality.resolution.height) {
|
if (Number(quality) < bestQuality.resolution.height) {
|
||||||
bestQuality = m3u8.find((i) => (Number(quality) === i["resolution"].height));
|
bestQuality = m3u8.find((i) => (Number(quality) === i.resolution.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
let fileMetadata = {
|
let fileMetadata = {
|
||||||
|
|
|
@ -8,7 +8,7 @@ const cachedID = {
|
||||||
|
|
||||||
async function findClientID() {
|
async function findClientID() {
|
||||||
try {
|
try {
|
||||||
let sc = await fetch('https://soundcloud.com/').then((r) => { return r.text() }).catch(() => { return false });
|
let sc = await fetch('https://soundcloud.com/').then(r => r.text()).catch(() => {});
|
||||||
let scVersion = String(sc.match(/<script>window\.__sc_version="[0-9]{10}"<\/script>/)[0].match(/[0-9]{10}/));
|
let scVersion = String(sc.match(/<script>window\.__sc_version="[0-9]{10}"<\/script>/)[0].match(/[0-9]{10}/));
|
||||||
|
|
||||||
if (cachedID.version === scVersion) return cachedID.id;
|
if (cachedID.version === scVersion) return cachedID.id;
|
||||||
|
@ -20,7 +20,7 @@ async function findClientID() {
|
||||||
|
|
||||||
if (url && !url.startsWith('https://a-v2.sndcdn.com')) return;
|
if (url && !url.startsWith('https://a-v2.sndcdn.com')) return;
|
||||||
|
|
||||||
let scrf = await fetch(url).then((r) => {return r.text()}).catch(() => { return false });
|
let scrf = await fetch(url).then(r => r.text()).catch(() => {});
|
||||||
let id = scrf.match(/\("client_id=[A-Za-z0-9]{32}"\)/);
|
let id = scrf.match(/\("client_id=[A-Za-z0-9]{32}"\)/);
|
||||||
|
|
||||||
if (id && typeof id[0] === 'string') {
|
if (id && typeof id[0] === 'string') {
|
||||||
|
@ -41,7 +41,7 @@ export default async function(obj) {
|
||||||
|
|
||||||
let link;
|
let link;
|
||||||
if (obj.url.hostname === 'on.soundcloud.com' && obj.shortLink) {
|
if (obj.url.hostname === 'on.soundcloud.com' && obj.shortLink) {
|
||||||
link = await fetch(`https://on.soundcloud.com/${obj.shortLink}/`, { redirect: "manual" }).then((r) => {
|
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/")) {
|
if (r.status === 302 && r.headers.get("location").startsWith("https://soundcloud.com/")) {
|
||||||
return r.headers.get("location").split('?', 1)[0]
|
return r.headers.get("location").split('?', 1)[0]
|
||||||
}
|
}
|
||||||
|
@ -54,13 +54,13 @@ export default async function(obj) {
|
||||||
|
|
||||||
if (!link) return { error: 'ErrorCouldntFetch' };
|
if (!link) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
let json = await fetch(`https://api-v2.soundcloud.com/resolve?url=${link}&client_id=${clientId}`).then((r) => {
|
let json = await fetch(`https://api-v2.soundcloud.com/resolve?url=${link}&client_id=${clientId}`)
|
||||||
return r.status === 200 ? r.json() : false
|
.then(r => r.status === 200 ? r.json() : false)
|
||||||
}).catch(() => {});
|
.catch(() => {});
|
||||||
|
|
||||||
if (!json) return { error: 'ErrorCouldntFetch' };
|
if (!json) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
if (!json["media"]["transcodings"]) return { error: 'ErrorEmptyDownload' };
|
if (!json.media.transcodings) return { error: 'ErrorEmptyDownload' };
|
||||||
|
|
||||||
let bestAudio = "opus",
|
let bestAudio = "opus",
|
||||||
selectedStream = json.media.transcodings.find(v => v.preset === "opus_0_0"),
|
selectedStream = json.media.transcodings.find(v => v.preset === "opus_0_0"),
|
||||||
|
@ -75,12 +75,15 @@ export default async function(obj) {
|
||||||
let fileUrlBase = selectedStream.url;
|
let fileUrlBase = selectedStream.url;
|
||||||
let fileUrl = `${fileUrlBase}${fileUrlBase.includes("?") ? "&" : "?"}client_id=${clientId}&track_authorization=${json.track_authorization}`;
|
let 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' };
|
||||||
|
|
||||||
if (json.duration > env.durationLimit * 1000)
|
if (json.duration > env.durationLimit * 1000)
|
||||||
return { error: ['ErrorLengthAudioConvert', env.durationLimit / 60] };
|
return { error: ['ErrorLengthAudioConvert', env.durationLimit / 60] };
|
||||||
|
|
||||||
let file = await fetch(fileUrl).then(async (r) => { return (await r.json()).url }).catch(() => {});
|
let file = await fetch(fileUrl)
|
||||||
|
.then(async r => (await r.json()).url)
|
||||||
|
.catch(() => {});
|
||||||
if (!file) return { error: 'ErrorCouldntFetch' };
|
if (!file) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
let fileMetadata = {
|
let fileMetadata = {
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
export default async function(obj) {
|
export default async function(obj) {
|
||||||
let video = await fetch(`https://api.streamable.com/videos/${obj.id}`).then((r) => { return r.status === 200 ? r.json() : false }).catch(() => { return false });
|
let video = await fetch(`https://api.streamable.com/videos/${obj.id}`)
|
||||||
|
.then(r => r.status === 200 ? r.json() : false)
|
||||||
|
.catch(() => {});
|
||||||
|
|
||||||
if (!video) return { error: 'ErrorEmptyDownload' };
|
if (!video) return { error: 'ErrorEmptyDownload' };
|
||||||
|
|
||||||
let best = video.files['mp4-mobile'];
|
let best = video.files['mp4-mobile'];
|
||||||
|
|
|
@ -29,13 +29,15 @@ export default async function (obj) {
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
})
|
})
|
||||||
}).then((r) => { return r.status === 200 ? r.json() : false; }).catch(() => { return false });
|
}).then(r => r.status === 200 ? r.json() : false).catch(() => {});
|
||||||
if (!req_metadata) return { error: 'ErrorCouldntFetch' };
|
if (!req_metadata) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
let clipMetadata = req_metadata.data.clip;
|
let clipMetadata = req_metadata.data.clip;
|
||||||
|
|
||||||
if (clipMetadata.durationSeconds > env.durationLimit) return { error: ['ErrorLengthLimit', env.durationLimit / 60] };
|
if (clipMetadata.durationSeconds > env.durationLimit)
|
||||||
if (!clipMetadata.videoQualities || !clipMetadata.broadcaster) return { error: 'ErrorEmptyDownload' };
|
return { error: ['ErrorLengthLimit', env.durationLimit / 60] };
|
||||||
|
if (!clipMetadata.videoQualities || !clipMetadata.broadcaster)
|
||||||
|
return { error: 'ErrorEmptyDownload' };
|
||||||
|
|
||||||
let req_token = await fetch(gqlURL, {
|
let req_token = await fetch(gqlURL, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
@ -54,7 +56,7 @@ export default async function (obj) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
}).then((r) => { return r.status === 200 ? r.json() : false; }).catch(() => { return false });
|
}).then(r => r.status === 200 ? r.json() : false).catch(() => {});
|
||||||
|
|
||||||
if (!req_token) return { error: 'ErrorCouldntFetch' };
|
if (!req_token) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,9 @@ export default async function(obj) {
|
||||||
if (!api) return { error: 'ErrorCouldntFetch' };
|
if (!api) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
let downloadType = "dash";
|
let downloadType = "dash";
|
||||||
if (!obj.isAudioOnly && JSON.stringify(api).includes('"progressive":[{')) downloadType = "progressive";
|
|
||||||
|
if (!obj.isAudioOnly && JSON.stringify(api).includes('"progressive":[{'))
|
||||||
|
downloadType = "progressive";
|
||||||
|
|
||||||
let fileMetadata = {
|
let fileMetadata = {
|
||||||
title: cleanString(api.video.title.trim()),
|
title: cleanString(api.video.title.trim()),
|
||||||
|
@ -48,33 +50,43 @@ export default async function(obj) {
|
||||||
|
|
||||||
if (downloadType !== "dash") {
|
if (downloadType !== "dash") {
|
||||||
if (qualityMatch[quality]) quality = qualityMatch[quality];
|
if (qualityMatch[quality]) quality = qualityMatch[quality];
|
||||||
let all = api["request"]["files"]["progressive"].sort((a, b) => Number(b.width) - Number(a.width));
|
let all = api.request.files.progressive.sort((a, b) => Number(b.width) - Number(a.width));
|
||||||
let best = all[0];
|
let best = all[0];
|
||||||
|
|
||||||
let bestQuality = all[0]["quality"].split('p')[0];
|
let bestQuality = all[0].quality.split('p')[0];
|
||||||
bestQuality = qualityMatch[bestQuality] ? qualityMatch[bestQuality] : bestQuality;
|
if (qualityMatch[bestQuality]) {
|
||||||
if (Number(quality) < Number(bestQuality)) best = all.find(i => i["quality"].split('p')[0] === quality);
|
bestQuality = qualityMatch[bestQuality]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Number(quality) < Number(bestQuality)) {
|
||||||
|
best = all.find(i => i.quality.split('p')[0] === quality);
|
||||||
|
}
|
||||||
|
|
||||||
if (!best) return { error: 'ErrorEmptyDownload' };
|
if (!best) return { error: 'ErrorEmptyDownload' };
|
||||||
|
|
||||||
return {
|
return {
|
||||||
urls: best["url"],
|
urls: best.url,
|
||||||
audioFilename: `vimeo_${obj.id}_audio`,
|
audioFilename: `vimeo_${obj.id}_audio`,
|
||||||
filename: `vimeo_${obj.id}_${best["width"]}x${best["height"]}.mp4`
|
filename: `vimeo_${obj.id}_${best.width}x${best.height}.mp4`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (api.video.duration > env.durationLimit) return { error: ['ErrorLengthLimit', env.durationLimit / 60] };
|
if (api.video.duration > env.durationLimit)
|
||||||
|
return { error: ['ErrorLengthLimit', env.durationLimit / 60] };
|
||||||
|
|
||||||
let masterJSONURL = api["request"]["files"]["dash"]["cdns"]["akfire_interconnect_quic"]["url"];
|
let masterJSONURL = api.request.files.dash.cdns.akfire_interconnect_quic.url;
|
||||||
let masterJSON = await fetch(masterJSONURL).then((r) => { return r.json() }).catch(() => { return false });
|
let masterJSON = await fetch(masterJSONURL).then(r => r.json()).catch(() => {});
|
||||||
|
|
||||||
if (!masterJSON) return { error: 'ErrorCouldntFetch' };
|
if (!masterJSON) return { error: 'ErrorCouldntFetch' };
|
||||||
if (!masterJSON.video) return { error: 'ErrorEmptyDownload' };
|
if (!masterJSON.video) return { error: 'ErrorEmptyDownload' };
|
||||||
|
|
||||||
let masterJSON_Video = masterJSON.video.sort((a, b) => Number(b.width) - Number(a.width)).filter(a => ["dash", "mp42"].includes(a['format'])),
|
let masterJSON_Video = masterJSON.video
|
||||||
bestVideo = masterJSON_Video[0];
|
.sort((a, b) => Number(b.width) - Number(a.width))
|
||||||
if (Number(quality) < Number(resolutionMatch[bestVideo["width"]])) {
|
.filter(a => ["dash", "mp42"].includes(a.format));
|
||||||
bestVideo = masterJSON_Video.find(i => resolutionMatch[i["width"]] === quality)
|
|
||||||
|
let bestVideo = masterJSON_Video[0];
|
||||||
|
if (Number(quality) < Number(resolutionMatch[bestVideo.width])) {
|
||||||
|
bestVideo = masterJSON_Video.find(i => resolutionMatch[i.width] === quality)
|
||||||
}
|
}
|
||||||
|
|
||||||
let masterM3U8 = `${masterJSONURL.split("/sep/")[0]}/sep/video/${bestVideo.id}/master.m3u8`;
|
let masterM3U8 = `${masterJSONURL.split("/sep/")[0]}/sep/video/${bestVideo.id}/master.m3u8`;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
export default async function(obj) {
|
export default async function(obj) {
|
||||||
let post = await fetch(`https://archive.vine.co/posts/${obj.id}.json`).then((r) => { return r.json() }).catch(() => { return false });
|
let post = await fetch(`https://archive.vine.co/posts/${obj.id}.json`)
|
||||||
|
.then(r => r.json())
|
||||||
|
.catch(() => {});
|
||||||
|
|
||||||
if (!post) return { error: 'ErrorEmptyDownload' };
|
if (!post) return { error: 'ErrorEmptyDownload' };
|
||||||
|
|
||||||
if (post.videoUrl) return {
|
if (post.videoUrl) return {
|
||||||
|
|
|
@ -8,7 +8,7 @@ export default async function(o) {
|
||||||
|
|
||||||
html = await fetch(`https://vk.com/video${o.userId}_${o.videoId}`, {
|
html = await fetch(`https://vk.com/video${o.userId}_${o.videoId}`, {
|
||||||
headers: { "user-agent": genericUserAgent }
|
headers: { "user-agent": genericUserAgent }
|
||||||
}).then((r) => { return r.arrayBuffer() }).catch(() => { return false });
|
}).then(r => r.arrayBuffer()).catch(() => {});
|
||||||
|
|
||||||
if (!html) return { error: 'ErrorCouldntFetch' };
|
if (!html) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ export default async function(o) {
|
||||||
let js = JSON.parse('{"lang":' + html.split(`{"lang":`)[1].split(']);')[0]);
|
let js = JSON.parse('{"lang":' + html.split(`{"lang":`)[1].split(']);')[0]);
|
||||||
|
|
||||||
if (Number(js.mvData.is_active_live) !== 0) return { error: 'ErrorLiveVideo' };
|
if (Number(js.mvData.is_active_live) !== 0) return { error: 'ErrorLiveVideo' };
|
||||||
if (js.mvData.duration > env.durationLimit) return { error: ['ErrorLengthLimit', env.durationLimit / 60] };
|
if (js.mvData.duration > env.durationLimit)
|
||||||
|
return { error: ['ErrorLengthLimit', env.durationLimit / 60] };
|
||||||
|
|
||||||
for (let i in resolutions) {
|
for (let i in resolutions) {
|
||||||
if (js.player.params[0][`url${resolutions[i]}`]) {
|
if (js.player.params[0][`url${resolutions[i]}`]) {
|
||||||
|
|
|
@ -57,7 +57,7 @@ export default async function(o) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
info = await yt.getBasicInfo(o.id, 'WEB');
|
info = await yt.getBasicInfo(o.id, 'WEB');
|
||||||
} catch (e) {
|
} catch {
|
||||||
return { error: 'ErrorCantConnectToServiceAPI' };
|
return { error: 'ErrorCantConnectToServiceAPI' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue