add support for ok videos & clean up

This commit is contained in:
wukko 2024-01-17 13:02:52 +06:00
parent a63a35c74d
commit 5b1e9f1fa6
5 changed files with 94 additions and 22 deletions

View file

@ -13,6 +13,7 @@ import reddit from "./services/reddit.js";
import twitter from "./services/twitter.js"; import twitter from "./services/twitter.js";
import youtube from "./services/youtube.js"; import youtube from "./services/youtube.js";
import vk from "./services/vk.js"; import vk from "./services/vk.js";
import ok from "./services/ok.js";
import tiktok from "./services/tiktok.js"; import tiktok from "./services/tiktok.js";
import tumblr from "./services/tumblr.js"; import tumblr from "./services/tumblr.js";
import vimeo from "./services/vimeo.js"; import vimeo from "./services/vimeo.js";
@ -43,19 +44,25 @@ export default async function(host, patternMatch, url, lang, obj) {
break; break;
case "vk": case "vk":
r = await vk({ r = await vk({
userId: patternMatch["userId"], userId: patternMatch.userId,
videoId: patternMatch["videoId"], videoId: patternMatch.videoId,
quality: obj.vQuality
});
break;
case "ok":
r = await ok({
id: patternMatch.id,
quality: obj.vQuality quality: obj.vQuality
}); });
break; break;
case "bilibili": case "bilibili":
r = await bilibili({ r = await bilibili({
id: patternMatch["id"].slice(0, 12) id: patternMatch.id.slice(0, 12)
}); });
break; break;
case "youtube": case "youtube":
let fetchInfo = { let fetchInfo = {
id: patternMatch["id"].slice(0, 11), id: patternMatch.id.slice(0, 11),
quality: obj.vQuality, quality: obj.vQuality,
format: obj.vCodec, format: obj.vCodec,
isAudioOnly: isAudioOnly, isAudioOnly: isAudioOnly,
@ -73,16 +80,16 @@ export default async function(host, patternMatch, url, lang, obj) {
break; break;
case "reddit": case "reddit":
r = await reddit({ r = await reddit({
sub: patternMatch["sub"], sub: patternMatch.sub,
id: patternMatch["id"] id: patternMatch.id
}); });
break; break;
case "douyin": case "douyin":
case "tiktok": case "tiktok":
r = await tiktok({ r = await tiktok({
host: host, host: host,
postId: patternMatch["postId"], postId: patternMatch.postId,
id: patternMatch["id"], id: patternMatch.id,
noWatermark: obj.isNoTTWatermark, noWatermark: obj.isNoTTWatermark,
fullAudio: obj.isTTFullAudio, fullAudio: obj.isTTFullAudio,
isAudioOnly: isAudioOnly isAudioOnly: isAudioOnly
@ -97,7 +104,7 @@ export default async function(host, patternMatch, url, lang, obj) {
break; break;
case "vimeo": case "vimeo":
r = await vimeo({ r = await vimeo({
id: patternMatch["id"].slice(0, 11), id: patternMatch.id.slice(0, 11),
quality: obj.vQuality, quality: obj.vQuality,
isAudioOnly: isAudioOnly, isAudioOnly: isAudioOnly,
forceDash: isAudioOnly ? true : obj.vimeoDash forceDash: isAudioOnly ? true : obj.vimeoDash
@ -107,10 +114,10 @@ export default async function(host, patternMatch, url, lang, obj) {
isAudioOnly = true; isAudioOnly = true;
r = await soundcloud({ r = await soundcloud({
url, url,
author: patternMatch["author"], author: patternMatch.author,
song: patternMatch["song"], song: patternMatch.song,
shortLink: patternMatch["shortLink"] || false, shortLink: patternMatch.shortLink || false,
accessKey: patternMatch["accessKey"] || false accessKey: patternMatch.accessKey || false
}); });
break; break;
case "instagram": case "instagram":
@ -121,31 +128,31 @@ export default async function(host, patternMatch, url, lang, obj) {
break; break;
case "vine": case "vine":
r = await vine({ r = await vine({
id: patternMatch["id"] id: patternMatch.id
}); });
break; break;
case "pinterest": case "pinterest":
r = await pinterest({ r = await pinterest({
id: patternMatch["id"] id: patternMatch.id
}); });
break; break;
case "streamable": case "streamable":
r = await streamable({ r = await streamable({
id: patternMatch["id"], id: patternMatch.id,
quality: obj.vQuality, quality: obj.vQuality,
isAudioOnly: isAudioOnly, isAudioOnly: isAudioOnly,
}); });
break; break;
case "twitch": case "twitch":
r = await twitch({ r = await twitch({
clipId: patternMatch["clip"] || false, clipId: patternMatch.clip || false,
quality: obj.vQuality, quality: obj.vQuality,
isAudioOnly: obj.isAudioOnly isAudioOnly: obj.isAudioOnly
}); });
break; break;
case "rutube": case "rutube":
r = await rutube({ r = await rutube({
id: patternMatch["id"], id: patternMatch.id,
quality: obj.vQuality, quality: obj.vQuality,
isAudioOnly: isAudioOnly isAudioOnly: isAudioOnly
}); });

View file

@ -0,0 +1,56 @@
import { genericUserAgent, maxVideoDuration } from "../../config.js";
import { cleanString } from "../../sub/utils.js";
const resolutions = {
"ultra": "2160",
"quad": "1440",
"full": "1080",
"hd": "720",
"sd": "480",
"low": "360",
"lowest": "240",
"mobile": "144"
}
export default async function(o) {
let quality = o.quality === "max" ? "2160" : o.quality;
let html = await fetch(`https://ok.ru/video/${o.id}`, {
headers: { "user-agent": genericUserAgent }
}).then((r) => { return r.text() }).catch(() => { return false });
if (!html) return { error: 'ErrorCouldntFetch' };
if (!html.includes(`<div data-module="OKVideo" data-options="{`)) {
return { error: 'ErrorEmptyDownload' };
}
let videoData = html.split(`<div data-module="OKVideo" data-options="`)[1].split('" data-')[0].replaceAll("&quot;", '"');
videoData = JSON.parse(JSON.parse(videoData).flashvars.metadata);
if (videoData.provider !== "UPLOADED_ODKL") return { error: 'ErrorUnsupported' };
if (videoData.movie.is_live) return { error: 'ErrorLiveVideo' };
if (videoData.movie.duration > maxVideoDuration / 1000) return { error: ['ErrorLengthLimit', maxVideoDuration / 60000] };
let videos = videoData.videos.filter(v => !v.disallowed);
let bestVideo = videos.find(v => resolutions[v.name] === quality) || videos[videos.length - 1];
let fileMetadata = {
title: cleanString(videoData.movie.title.trim()),
author: cleanString(videoData.author.name.trim()),
}
if (bestVideo) return {
urls: bestVideo.url,
filenameAttributes: {
service: "ok",
id: o.id,
title: fileMetadata.title,
author: fileMetadata.author,
resolution: `${resolutions[bestVideo.name]}p`,
qualityLabel: `${resolutions[bestVideo.name]}p`,
extension: "mp4"
}
}
return { error: 'ErrorEmptyDownload' }
}

View file

@ -12,7 +12,7 @@ export default async function(o) {
if (!html) return { error: 'ErrorCouldntFetch' }; if (!html) return { error: 'ErrorCouldntFetch' };
// decode cyrillic from windows-1251 because vk still uses apis from prehistoring times // decode cyrillic from windows-1251 because vk still uses apis from prehistoric times
let decoder = new TextDecoder('windows-1251'); let decoder = new TextDecoder('windows-1251');
html = decoder.decode(html); html = decoder.decode(html);
@ -35,7 +35,7 @@ export default async function(o) {
let fileMetadata = { let fileMetadata = {
title: cleanString(js.player.params[0].md_title.trim()), title: cleanString(js.player.params[0].md_title.trim()),
artist: cleanString(js.player.params[0].md_author.trim()), author: cleanString(js.player.params[0].md_author.trim()),
} }
if (url) return { if (url) return {
@ -44,7 +44,7 @@ export default async function(o) {
service: "vk", service: "vk",
id: `${o.userId}_${o.videoId}`, id: `${o.userId}_${o.videoId}`,
title: fileMetadata.title, title: fileMetadata.title,
author: fileMetadata.artist, author: fileMetadata.author,
resolution: `${quality}p`, resolution: `${quality}p`,
qualityLabel: `${quality}p`, qualityLabel: `${quality}p`,
extension: "mp4" extension: "mp4"

View file

@ -1,5 +1,5 @@
{ {
"audioIgnore": ["vk"], "audioIgnore": ["vk", "ok"],
"config": { "config": {
"bilibili": { "bilibili": {
"alias": "bilibili.com videos", "alias": "bilibili.com videos",
@ -28,6 +28,12 @@
"patterns": ["video:userId_:videoId", "clip:userId_:videoId", "clips:duplicate?z=clip:userId_:videoId"], "patterns": ["video:userId_:videoId", "clip:userId_:videoId", "clips:duplicate?z=clip:userId_:videoId"],
"enabled": true "enabled": true
}, },
"ok": {
"alias": "ok video",
"tld": "ru",
"patterns": ["video/:id"],
"enabled": true
},
"youtube": { "youtube": {
"alias": "youtube videos, shorts & music", "alias": "youtube videos, shorts & music",
"patterns": ["watch?v=:id", "embed/:id", "watch/:id"], "patterns": ["watch?v=:id", "embed/:id", "watch/:id"],

View file

@ -6,6 +6,9 @@ export const testers = {
patternMatch.postId?.length <= 12 patternMatch.postId?.length <= 12
|| (patternMatch.username?.length <= 30 && patternMatch.storyId?.length <= 24), || (patternMatch.username?.length <= 30 && patternMatch.storyId?.length <= 24),
"ok": (patternMatch) =>
patternMatch.id?.length <= 16,
"pinterest": (patternMatch) => "pinterest": (patternMatch) =>
patternMatch.id?.length <= 128, patternMatch.id?.length <= 128,