diff --git a/src/modules/processing/match.js b/src/modules/processing/match.js index 7f9714b7..c3091709 100644 --- a/src/modules/processing/match.js +++ b/src/modules/processing/match.js @@ -179,6 +179,7 @@ export default async function(host, patternMatch, lang, obj) { r = await rutube({ id: patternMatch.id, yappyId: patternMatch.yappyId, + key: patternMatch.key, quality: obj.vQuality, isAudioOnly: isAudioOnly }); diff --git a/src/modules/processing/services/rutube.js b/src/modules/processing/services/rutube.js index dd984c57..a8d0abbe 100644 --- a/src/modules/processing/services/rutube.js +++ b/src/modules/processing/services/rutube.js @@ -12,10 +12,10 @@ async function requestJSON(url) { export default async function(obj) { if (obj.yappyId) { - let yappy = await requestJSON( + const yappy = await requestJSON( `https://rutube.ru/pangolin/api/web/yappy/yappypage/?client=wdp&videoId=${obj.yappyId}&page=1&page_size=15` ) - let yappyURL = yappy?.results?.find(r => r.id === obj.yappyId)?.link; + const yappyURL = yappy?.results?.find(r => r.id === obj.yappyId)?.link; if (!yappyURL) return { error: 'ErrorEmptyDownload' }; return { @@ -25,11 +25,12 @@ export default async function(obj) { } } - let quality = obj.quality === "max" ? "9000" : obj.quality; + const quality = obj.quality === "max" ? "9000" : obj.quality; - let play = await requestJSON( - `https://rutube.ru/api/play/options/${obj.id}/?no_404=true&referer&pver=v2` - ) + const requestURL = new URL(`https://rutube.ru/api/play/options/${obj.id}/?no_404=true&referer&pver=v2`); + if (obj.key) requestURL.searchParams.set('p', obj.key); + + const play = await requestJSON(requestURL); if (!play) return { error: 'ErrorCouldntFetch' }; if (play.detail || !play.video_balancer) return { error: 'ErrorEmptyDownload' }; @@ -51,7 +52,7 @@ export default async function(obj) { bestQuality = m3u8.find((i) => (Number(quality) === i.resolution.height)); } - let fileMetadata = { + const fileMetadata = { title: cleanString(play.title.trim()), artist: cleanString(play.author.name.trim()), } diff --git a/src/modules/processing/servicesConfig.json b/src/modules/processing/servicesConfig.json index 2daa7b63..c0a11817 100644 --- a/src/modules/processing/servicesConfig.json +++ b/src/modules/processing/servicesConfig.json @@ -105,7 +105,7 @@ "rutube": { "alias": "rutube videos", "tld": "ru", - "patterns": ["video/:id", "play/embed/:id", "shorts/:id", "yappy/:yappyId"], + "patterns": ["video/:id", "play/embed/:id", "shorts/:id", "yappy/:yappyId", "video/private/:id?p=:key", "video/private/:id"], "enabled": true }, "dailymotion": { diff --git a/src/modules/processing/servicesPatternTesters.js b/src/modules/processing/servicesPatternTesters.js index 25b8943a..a4770c17 100644 --- a/src/modules/processing/servicesPatternTesters.js +++ b/src/modules/processing/servicesPatternTesters.js @@ -20,6 +20,7 @@ export const testers = { || (patternMatch.user?.length <= 22 && patternMatch.id?.length <= 10), "rutube": (patternMatch) => + (patternMatch.id?.length === 32 && patternMatch.key?.length <= 32) || patternMatch.id?.length === 32 || patternMatch.yappyId?.length === 32, "soundcloud": (patternMatch) => diff --git a/src/modules/processing/url.js b/src/modules/processing/url.js index 1a8bb927..111f1f6f 100644 --- a/src/modules/processing/url.js +++ b/src/modules/processing/url.js @@ -100,6 +100,11 @@ function cleanURL(url) { limitQuery('v') } break; + case "rutube": + if (url.searchParams.get('p')) { + limitQuery('p') + } + break; } if (stripQuery) { diff --git a/src/test/tests.json b/src/test/tests.json index 565fa5a4..36044cde 100644 --- a/src/test/tests.json +++ b/src/test/tests.json @@ -1089,6 +1089,14 @@ "code": 200, "status": "stream" } + }, { + "name": "private video", + "url": "https://rutube.ru/video/private/1161415be0e686214bb2a498165cab3e/?p=_IL1G8RSnKutunnTYwhZ5A", + "params": {}, + "expected": { + "code": 200, + "status": "stream" + } }], "ok": [{ "name": "regular video",