updated readme and fixed some things
This commit is contained in:
parent
7f1ba6b36b
commit
13c2884a41
9 changed files with 34 additions and 31 deletions
|
@ -27,6 +27,9 @@ It preserves original media quality so you get best downloads possible (unless y
|
||||||
| Vimeo | ✅ | ❌️ | |
|
| Vimeo | ✅ | ❌️ | |
|
||||||
| VK Videos & Clips | ✅ | ❌️ | |
|
| VK Videos & Clips | ✅ | ❌️ | |
|
||||||
|
|
||||||
|
## cobalt API
|
||||||
|
cobalt has an open API that you can use for free. It's pretty straightforward in use, [check out the docs](https://github.com/wukko/cobalt/blob/current/docs/API.md) and see for yourself.
|
||||||
|
|
||||||
## How to contribute translations
|
## How to contribute translations
|
||||||
You can translate cobalt to any language you want on [cobalt's crowdin](https://crowdin-co.wukko.me/). Feel free to ignore QA errors if you think you know better. If you don't see a language you want to translate cobalt to, open an issue, and I'll add it to crowdin.
|
You can translate cobalt to any language you want on [cobalt's crowdin](https://crowdin-co.wukko.me/). Feel free to ignore QA errors if you think you know better. If you don't see a language you want to translate cobalt to, open an issue, and I'll add it to crowdin.
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ export default async function(obj) {
|
||||||
try {
|
try {
|
||||||
let html = await fetch(`https://bilibili.com/video/${obj.id}`, {
|
let html = await fetch(`https://bilibili.com/video/${obj.id}`, {
|
||||||
headers: {"user-agent": genericUserAgent}
|
headers: {"user-agent": genericUserAgent}
|
||||||
}).then(async (r) => {return r.text()}).catch(() => {return false});
|
}).then((r) => {return r.text()}).catch(() => {return false});
|
||||||
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"')) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { maxVideoDuration } from "../config.js";
|
||||||
|
|
||||||
export default async function(obj) {
|
export default async function(obj) {
|
||||||
try {
|
try {
|
||||||
let data = await fetch(`https://www.reddit.com/r/${obj.sub}/comments/${obj.id}/${obj.name}.json`).then(async (r) => {return r.json()}).catch(() => {return false});
|
let data = await fetch(`https://www.reddit.com/r/${obj.sub}/comments/${obj.id}/${obj.name}.json`).then((r) => {return r.json()}).catch(() => {return false});
|
||||||
if (!data) return { error: 'ErrorCouldntFetch' };
|
if (!data) return { error: 'ErrorCouldntFetch' };
|
||||||
data = data[0]["data"]["children"][0]["data"];
|
data = data[0]["data"]["children"][0]["data"];
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ let cachedID = {}
|
||||||
|
|
||||||
async function findClientID() {
|
async function findClientID() {
|
||||||
try {
|
try {
|
||||||
let sc = await fetch('https://soundcloud.com/').then(async (r) => {return r.text()}).catch(() => {return false});
|
let sc = await fetch('https://soundcloud.com/').then((r) => {return r.text()}).catch(() => {return false});
|
||||||
let sc_version = String(sc.match(/<script>window\.__sc_version="[0-9]{10}"<\/script>/)[0].match(/[0-9]{10}/));
|
let sc_version = String(sc.match(/<script>window\.__sc_version="[0-9]{10}"<\/script>/)[0].match(/[0-9]{10}/));
|
||||||
|
|
||||||
if (cachedID.version == sc_version) {
|
if (cachedID.version == sc_version) {
|
||||||
|
@ -17,7 +17,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(async (r) => {return r.text()}).catch(() => {return false});
|
let scrf = await fetch(url).then((r) => {return r.text()}).catch(() => {return false});
|
||||||
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,12 +41,12 @@ export default async function(obj) {
|
||||||
if (!obj.author && !obj.song && obj.shortLink) {
|
if (!obj.author && !obj.song && obj.shortLink) {
|
||||||
html = await fetch(`https://soundcloud.app.goo.gl/${obj.shortLink}/`, {
|
html = await fetch(`https://soundcloud.app.goo.gl/${obj.shortLink}/`, {
|
||||||
headers: {"user-agent": genericUserAgent}
|
headers: {"user-agent": genericUserAgent}
|
||||||
}).then(async (r) => {return r.text()}).catch(() => {return false});
|
}).then((r) => {return r.text()}).catch(() => {return false});
|
||||||
}
|
}
|
||||||
if (obj.author && obj.song) {
|
if (obj.author && obj.song) {
|
||||||
html = await fetch(`https://soundcloud.com/${obj.author}/${obj.song}`, {
|
html = await fetch(`https://soundcloud.com/${obj.author}/${obj.song}`, {
|
||||||
headers: {"user-agent": genericUserAgent}
|
headers: {"user-agent": genericUserAgent}
|
||||||
}).then(async (r) => {return r.text()}).catch(() => {return false});
|
}).then((r) => {return r.text()}).catch(() => {return false});
|
||||||
}
|
}
|
||||||
if (!html) return { error: 'ErrorCouldntFetch'};
|
if (!html) return { error: 'ErrorCouldntFetch'};
|
||||||
if (html.includes('<script>window.__sc_hydration = ') && html.includes('"format":{"protocol":"progressive","mime_type":"audio/mpeg"},') && html.includes('{"hydratable":"sound","data":')) {
|
if (html.includes('<script>window.__sc_hydration = ') && html.includes('"format":{"protocol":"progressive","mime_type":"audio/mpeg"},') && html.includes('{"hydratable":"sound","data":')) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ export default async function(obj) {
|
||||||
let html = await fetch(`${config[obj.host]["short"]}${obj.id}`, {
|
let html = await fetch(`${config[obj.host]["short"]}${obj.id}`, {
|
||||||
redirect: "manual",
|
redirect: "manual",
|
||||||
headers: { "user-agent": userAgent }
|
headers: { "user-agent": userAgent }
|
||||||
}).then(async (r) => {return r.text()}).catch(() => {return false});
|
}).then((r) => {return r.text()}).catch(() => {return false});
|
||||||
if (!html) return { error: 'ErrorCouldntFetch' };
|
if (!html) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
if (html.slice(0, 17) === '<a href="https://' && html.includes('/video/')) {
|
if (html.slice(0, 17) === '<a href="https://' && html.includes('/video/')) {
|
||||||
|
@ -46,7 +46,7 @@ export default async function(obj) {
|
||||||
let detail;
|
let detail;
|
||||||
detail = await fetch(config[obj.host]["api"].replace("{postId}", obj.postId), {
|
detail = await fetch(config[obj.host]["api"].replace("{postId}", obj.postId), {
|
||||||
headers: {"user-agent": "TikTok 26.2.0 rv:262018 (iPhone; iOS 14.4.2; en_US) Cronet"}
|
headers: {"user-agent": "TikTok 26.2.0 rv:262018 (iPhone; iOS 14.4.2; en_US) Cronet"}
|
||||||
}).then(async (r) => {return r.json()}).catch(() => {return false});
|
}).then((r) => {return r.json()}).catch(() => {return false});
|
||||||
|
|
||||||
detail = selector(detail, obj.host, obj.postId);
|
detail = selector(detail, obj.host, obj.postId);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ export default async function(obj) {
|
||||||
let user = obj.user ? obj.user : obj.url.split('.')[0].replace('https://', '');
|
let user = obj.user ? obj.user : obj.url.split('.')[0].replace('https://', '');
|
||||||
let html = await fetch(`https://${user}.tumblr.com/post/${obj.id}`, {
|
let html = await fetch(`https://${user}.tumblr.com/post/${obj.id}`, {
|
||||||
headers: {"user-agent": genericUserAgent}
|
headers: {"user-agent": genericUserAgent}
|
||||||
}).then(async (r) => {return r.text()}).catch(() => {return false});
|
}).then((r) => {return r.text()}).catch(() => {return false});
|
||||||
if (!html) return { error: 'ErrorCouldntFetch' };
|
if (!html) return { error: 'ErrorCouldntFetch' };
|
||||||
if (html.includes('property="og:video" content="https://va.media.tumblr.com/')) {
|
if (html.includes('property="og:video" content="https://va.media.tumblr.com/')) {
|
||||||
return { urls: `https://va.media.tumblr.com/${html.split('property="og:video" content="https://va.media.tumblr.com/')[1].split('"/>')[0]}`, audioFilename: `tumblr_${obj.id}_audio` }
|
return { urls: `https://va.media.tumblr.com/${html.split('property="og:video" content="https://va.media.tumblr.com/')[1].split('"/>')[0]}`, audioFilename: `tumblr_${obj.id}_audio` }
|
||||||
|
|
|
@ -15,13 +15,13 @@ export default async function(obj) {
|
||||||
let req_act = await fetch(`${apiURL}/guest/activate.json`, {
|
let req_act = await fetch(`${apiURL}/guest/activate.json`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: _headers
|
headers: _headers
|
||||||
}).then(async (r) => { return r.status == 200 ? r.json() : false;}).catch(() => {return false});
|
}).then((r) => { return r.status == 200 ? r.json() : false;}).catch(() => {return false});
|
||||||
|
|
||||||
if (!req_act) return { error: 'ErrorCouldntFetch' };
|
if (!req_act) return { error: 'ErrorCouldntFetch' };
|
||||||
_headers["x-guest-token"] = req_act["guest_token"];
|
_headers["x-guest-token"] = req_act["guest_token"];
|
||||||
let showURL = `${apiURL}/statuses/show/${obj.id}.json?tweet_mode=extended&include_user_entities=0&trim_user=1&include_entities=0&cards_platform=Web-12&include_cards=1`
|
let showURL = `${apiURL}/statuses/show/${obj.id}.json?tweet_mode=extended&include_user_entities=0&trim_user=1&include_entities=0&cards_platform=Web-12&include_cards=1`
|
||||||
if (!obj.spaceId) {
|
if (!obj.spaceId) {
|
||||||
let req_status = await fetch(showURL, { headers: _headers }).then(async (r) => { return r.status == 200 ? r.json() : false;}).catch((e) => { return false});
|
let req_status = await fetch(showURL, { headers: _headers }).then((r) => { return r.status == 200 ? r.json() : false;}).catch((e) => { return false});
|
||||||
if (!req_status) {
|
if (!req_status) {
|
||||||
_headers.authorization = "Bearer AAAAAAAAAAAAAAAAAAAAAPYXBAAAAAAACLXUNDekMxqa8h%2F40K4moUkGsoc%3DTYfbDKbT3jJPCEVnMYqilB28NHfOPqkca3qaAxGfsyKCs0wRbw";
|
_headers.authorization = "Bearer AAAAAAAAAAAAAAAAAAAAAPYXBAAAAAAACLXUNDekMxqa8h%2F40K4moUkGsoc%3DTYfbDKbT3jJPCEVnMYqilB28NHfOPqkca3qaAxGfsyKCs0wRbw";
|
||||||
delete _headers["x-guest-token"]
|
delete _headers["x-guest-token"]
|
||||||
|
@ -29,11 +29,11 @@ export default async function(obj) {
|
||||||
req_act = await fetch(`${apiURL}/guest/activate.json`, {
|
req_act = await fetch(`${apiURL}/guest/activate.json`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: _headers
|
headers: _headers
|
||||||
}).then(async (r) => { return r.status == 200 ? r.json() : false;}).catch(() => {return false});
|
}).then((r) => { return r.status == 200 ? r.json() : false;}).catch(() => {return false});
|
||||||
if (!req_act) return { error: 'ErrorCouldntFetch' };
|
if (!req_act) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
_headers["x-guest-token"] = req_act["guest_token"];
|
_headers["x-guest-token"] = req_act["guest_token"];
|
||||||
req_status = await fetch(showURL, { headers: _headers }).then(async (r) => { return r.status == 200 ? r.json() : false;}).catch(() => {return false});
|
req_status = await fetch(showURL, { headers: _headers }).then((r) => { return r.status == 200 ? r.json() : false;}).catch(() => {return false});
|
||||||
}
|
}
|
||||||
if (!req_status) return { error: 'ErrorCouldntFetch' }
|
if (!req_status) return { error: 'ErrorCouldntFetch' }
|
||||||
if (req_status["extended_entities"] && req_status["extended_entities"]["media"]) {
|
if (req_status["extended_entities"] && req_status["extended_entities"]["media"]) {
|
||||||
|
@ -63,13 +63,13 @@ export default async function(obj) {
|
||||||
variables: {"id": obj.spaceId,"isMetatagsQuery":true,"withSuperFollowsUserFields":true,"withDownvotePerspective":false,"withReactionsMetadata":false,"withReactionsPerspective":false,"withSuperFollowsTweetFields":true,"withReplays":true}, features: {"spaces_2022_h2_clipping":true,"spaces_2022_h2_spaces_communities":true,"verified_phone_label_enabled":false,"tweetypie_unmention_optimization_enabled":true,"responsive_web_uc_gql_enabled":true,"vibe_api_enabled":true,"responsive_web_edit_tweet_api_enabled":true,"graphql_is_translatable_rweb_tweet_is_translatable_enabled":true,"standardized_nudges_misinfo":true,"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled":false,"responsive_web_graphql_timeline_navigation_enabled":false,"interactive_text_enabled":true,"responsive_web_text_conversations_enabled":false,"responsive_web_enhance_cards_enabled":true}
|
variables: {"id": obj.spaceId,"isMetatagsQuery":true,"withSuperFollowsUserFields":true,"withDownvotePerspective":false,"withReactionsMetadata":false,"withReactionsPerspective":false,"withSuperFollowsTweetFields":true,"withReplays":true}, features: {"spaces_2022_h2_clipping":true,"spaces_2022_h2_spaces_communities":true,"verified_phone_label_enabled":false,"tweetypie_unmention_optimization_enabled":true,"responsive_web_uc_gql_enabled":true,"vibe_api_enabled":true,"responsive_web_edit_tweet_api_enabled":true,"graphql_is_translatable_rweb_tweet_is_translatable_enabled":true,"standardized_nudges_misinfo":true,"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled":false,"responsive_web_graphql_timeline_navigation_enabled":false,"interactive_text_enabled":true,"responsive_web_text_conversations_enabled":false,"responsive_web_enhance_cards_enabled":true}
|
||||||
}
|
}
|
||||||
|
|
||||||
let AudioSpaceById = await fetch(`https://twitter.com/i/api/graphql/wJ5g4zf7v8qPHSQbaozYuw/AudioSpaceById?variables=${new URLSearchParams(JSON.stringify(query.variables)).toString().slice(0, -1)}&features=${new URLSearchParams(JSON.stringify(query.features)).toString().slice(0, -1)}`, { headers: _headers }).then(async (r) => {
|
let AudioSpaceById = await fetch(`https://twitter.com/i/api/graphql/wJ5g4zf7v8qPHSQbaozYuw/AudioSpaceById?variables=${new URLSearchParams(JSON.stringify(query.variables)).toString().slice(0, -1)}&features=${new URLSearchParams(JSON.stringify(query.features)).toString().slice(0, -1)}`, { headers: _headers }).then((r) => {
|
||||||
return r.status == 200 ? r.json() : false;
|
return r.status == 200 ? r.json() : false;
|
||||||
}).catch((e) => {return false});
|
}).catch((e) => {return false});
|
||||||
|
|
||||||
if (AudioSpaceById) {
|
if (AudioSpaceById) {
|
||||||
if (AudioSpaceById.data.audioSpace.metadata.is_space_available_for_replay === true) {
|
if (AudioSpaceById.data.audioSpace.metadata.is_space_available_for_replay === true) {
|
||||||
let streamStatus = await fetch(`https://twitter.com/i/api/1.1/live_video_stream/status/${AudioSpaceById.data.audioSpace.metadata.media_key}`, { headers: _headers }).then(async (r) => {return r.status == 200 ? r.json() : false;}).catch(() => {return false;});
|
let streamStatus = await fetch(`https://twitter.com/i/api/1.1/live_video_stream/status/${AudioSpaceById.data.audioSpace.metadata.media_key}`, { headers: _headers }).then((r) => {return r.status == 200 ? r.json() : false;}).catch(() => {return false;});
|
||||||
if (!streamStatus) return { error: 'ErrorCouldntFetch' };
|
if (!streamStatus) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
let participants = AudioSpaceById.data.audioSpace.participants.speakers
|
let participants = AudioSpaceById.data.audioSpace.participants.speakers
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { quality, services } from "../config.js";
|
||||||
|
|
||||||
export default async function(obj) {
|
export default async function(obj) {
|
||||||
try {
|
try {
|
||||||
let api = await fetch(`https://player.vimeo.com/video/${obj.id}/config`).then(async (r) => {return r.json()}).catch(() => {return false});
|
let api = await fetch(`https://player.vimeo.com/video/${obj.id}/config`).then((r) => {return r.json()}).catch(() => {return false});
|
||||||
if (!api) return { error: 'ErrorCouldntFetch' };
|
if (!api) return { error: 'ErrorCouldntFetch' };
|
||||||
|
|
||||||
let downloadType = "";
|
let downloadType = "";
|
||||||
|
@ -32,7 +32,7 @@ export default async function(obj) {
|
||||||
return { urls: best["url"], filename: `tumblr_${obj.id}.mp4` };
|
return { urls: best["url"], filename: `tumblr_${obj.id}.mp4` };
|
||||||
case "dash":
|
case "dash":
|
||||||
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(async (r) => {return r.json()}).catch(() => {return false});
|
let masterJSON = await fetch(masterJSONURL).then((r) => {return r.json()}).catch(() => {return false});
|
||||||
if (!masterJSON) return { error: 'ErrorCouldntFetch' };
|
if (!masterJSON) return { error: 'ErrorCouldntFetch' };
|
||||||
if (masterJSON.video) {
|
if (masterJSON.video) {
|
||||||
let type = "";
|
let type = "";
|
||||||
|
|
|
@ -7,7 +7,7 @@ export default async function(obj) {
|
||||||
let html;
|
let html;
|
||||||
html = await fetch(`https://vk.com/video-${obj.userId}_${obj.videoId}`, {
|
html = await fetch(`https://vk.com/video-${obj.userId}_${obj.videoId}`, {
|
||||||
headers: {"user-agent": genericUserAgent}
|
headers: {"user-agent": genericUserAgent}
|
||||||
}).then(async (r) => {return r.text()}).catch(() => {return false});
|
}).then((r) => {return r.text()}).catch(() => {return false});
|
||||||
if (!html) return { error: 'ErrorCouldntFetch' };
|
if (!html) return { error: 'ErrorCouldntFetch' };
|
||||||
if (html.includes(`{"lang":`)) {
|
if (html.includes(`{"lang":`)) {
|
||||||
let js = JSON.parse('{"lang":' + html.split(`{"lang":`)[1].split(']);')[0]);
|
let js = JSON.parse('{"lang":' + html.split(`{"lang":`)[1].split(']);')[0]);
|
||||||
|
|
Loading…
Reference in a new issue