@vot.js/node
Advanced tools
Comparing version 2.1.3 to 2.1.4
@@ -140,4 +140,5 @@ import { VideoService as CoreVideoService } from "@vot.js/core/types/service"; | ||
host: CoreVideoService.yandexdisk, | ||
url: "https://yadi.sk/i/", | ||
match: /^disk.yandex.ru|yadi.sk$/, | ||
url: "https://yadi.sk/", | ||
match: /^disk.yandex.(ru|kz|com(\.(am|ge|tr))?|by|az|co\.il|ee|lt|lv|md|net|tj|tm|uz)|yadi.sk$/, | ||
needExtraData: true, | ||
}, | ||
@@ -144,0 +145,0 @@ { |
@@ -10,3 +10,3 @@ import { parseFromString } from "dom-parser"; | ||
const content = await res.text(); | ||
const doc = parseFromString(content.replace("<!DOCTYPE html>", "")); | ||
const doc = parseFromString(content.replace(/<!DOCTYPE html>/i, "")); | ||
const videoEl = doc.getElementById("incflix-stream"); | ||
@@ -13,0 +13,0 @@ if (!videoEl) { |
@@ -11,3 +11,3 @@ import { parseFromString } from "dom-parser"; | ||
const content = await res.text(); | ||
const doc = parseFromString(content.replace("<!DOCTYPE html>", "")); | ||
const doc = parseFromString(content.replace(/<!DOCTYPE html>/i, "")); | ||
const videoEl = doc.getElementsByClassName("video-js")?.[0]; | ||
@@ -14,0 +14,0 @@ if (!videoEl) { |
@@ -10,3 +10,3 @@ import { parseFromString } from "dom-parser"; | ||
const content = await res.text(); | ||
const doc = parseFromString(content.replace("<!DOCTYPE html>", "")); | ||
const doc = parseFromString(content.replace(/<!DOCTYPE html>/i, "")); | ||
const varDelimiter = /var flashvars\s=\s/; | ||
@@ -13,0 +13,0 @@ const dataScript = doc |
@@ -66,3 +66,3 @@ import { parseFromString } from "dom-parser"; | ||
const [, kalturaDomain, partnerId] = sapData; | ||
const doc = parseFromString(content.replace("<!DOCTYPE html>", "")); | ||
const doc = parseFromString(content.replace(/<!DOCTYPE html>/i, "")); | ||
let entryId = doc | ||
@@ -69,0 +69,0 @@ .getElementById("shadow") |
@@ -101,3 +101,3 @@ import { parseFromString } from "dom-parser"; | ||
const content = await res.text(); | ||
const doc = parseFromString(content.replace("<!DOCTYPE html>", "")); | ||
const doc = parseFromString(content.replace(/<!DOCTYPE html>/i, "")); | ||
const playerConfigScript = doc | ||
@@ -104,0 +104,0 @@ .getElementsByTagName("script") |
import { BaseHelper } from "./base.js"; | ||
import * as YandexDisk from "@vot.js/shared/types/helpers/yandexdisk"; | ||
export default class YandexDiskHelper extends BaseHelper { | ||
API_ORIGIN: string; | ||
INLINE_PREFIX: string; | ||
DISK_PREFIX: string; | ||
clearTitle(title: string): string; | ||
getBodyHash(fileHash: string, sk: string): string; | ||
fetchList(dirHash: string, sk: string): Promise<(YandexDisk.ResourceFullVideoData | YandexDisk.ResourceFullDirData)[]>; | ||
getDownloadUrl(fileHash: string, sk: string): Promise<string>; | ||
getDiskVideoData(videoId: string): Promise<{ | ||
url: string; | ||
duration: number; | ||
title: string; | ||
} | undefined>; | ||
getVideoData(videoId: string): Promise<{ | ||
url: string; | ||
duration: number; | ||
title: string; | ||
} | { | ||
url: string; | ||
} | undefined>; | ||
getVideoId(url: URL): Promise<string | undefined>; | ||
} | ||
//# sourceMappingURL=yandexdisk.d.ts.map |
@@ -1,6 +0,120 @@ | ||
import { BaseHelper } from "./base.js"; | ||
import { parseFromString } from "dom-parser"; | ||
import { BaseHelper, VideoHelperError } from "./base.js"; | ||
import Logger from "@vot.js/shared/utils/logger"; | ||
import { proxyMedia } from "@vot.js/shared/utils/utils"; | ||
export default class YandexDiskHelper extends BaseHelper { | ||
API_ORIGIN = this.origin ?? "https://disk.yandex.ru"; | ||
INLINE_PREFIX = "/i/"; | ||
DISK_PREFIX = "/d/"; | ||
clearTitle(title) { | ||
return title.replace(/(\.[^.]+)$/, ""); | ||
} | ||
getBodyHash(fileHash, sk) { | ||
const data = JSON.stringify({ | ||
hash: fileHash, | ||
sk, | ||
}); | ||
return encodeURIComponent(data); | ||
} | ||
async fetchList(dirHash, sk) { | ||
const body = this.getBodyHash(dirHash, sk); | ||
const res = await this.fetch(this.API_ORIGIN + "/public/api/fetch-list", { | ||
method: "POST", | ||
body, | ||
}); | ||
const data = (await res.json()); | ||
if (Object.hasOwn(data, "error")) { | ||
throw new VideoHelperError("Failed to fetch folder list"); | ||
} | ||
return data.resources; | ||
} | ||
async getDownloadUrl(fileHash, sk) { | ||
const body = this.getBodyHash(fileHash, sk); | ||
const res = await this.fetch(this.API_ORIGIN + "/public/api/download-url", { | ||
method: "POST", | ||
body, | ||
}); | ||
const data = (await res.json()); | ||
if (data.error) { | ||
throw new VideoHelperError("Failed to get download url"); | ||
} | ||
return data.data.url; | ||
} | ||
async getDiskVideoData(videoId) { | ||
try { | ||
const res = await this.fetch(this.API_ORIGIN + videoId); | ||
if (res.status !== 200) { | ||
throw new VideoHelperError("Failed to fetch document"); | ||
} | ||
const content = await res.text(); | ||
const doc = parseFromString(content.replace(/<!DOCTYPE html>/i, "")); | ||
const prefetchEl = doc.getElementById("store-prefetch"); | ||
if (!prefetchEl) { | ||
throw new VideoHelperError("Failed to get prefetch data"); | ||
} | ||
const resourcePaths = videoId.split("/").slice(3); | ||
if (!resourcePaths.length) { | ||
throw new VideoHelperError("Failed to find video file path"); | ||
} | ||
const data = JSON.parse(prefetchEl.textContent); | ||
const { resources, rootResourceId, environment: { sk }, } = data; | ||
const rootResource = resources[rootResourceId]; | ||
const resourcePathsLastIdx = resourcePaths.length - 1; | ||
const resourcePath = resourcePaths | ||
.filter((_, idx) => idx !== resourcePathsLastIdx) | ||
.join("/"); | ||
let resourcesList = Object.values(resources); | ||
if (resourcePath.includes("/")) { | ||
resourcesList = await this.fetchList(`${rootResource.hash}:/${resourcePath}`, sk); | ||
} | ||
const resource = resourcesList.find((resource) => resource.name === resourcePaths[resourcePathsLastIdx]); | ||
if (!resource) { | ||
throw new VideoHelperError("Failed to find resource"); | ||
} | ||
if (resource && resource.type === "dir") { | ||
throw new VideoHelperError("Path is dir, but expected file"); | ||
} | ||
const { meta: { short_url, mediatype, videoDuration }, path, name, } = resource; | ||
if (mediatype !== "video") { | ||
throw new VideoHelperError("Resource isn't a video"); | ||
} | ||
const title = this.clearTitle(name); | ||
const duration = Math.round(videoDuration / 1000); | ||
if (short_url) { | ||
return { | ||
url: short_url, | ||
duration, | ||
title, | ||
}; | ||
} | ||
const downloadUrl = await this.getDownloadUrl(path, sk); | ||
return { | ||
url: proxyMedia(new URL(downloadUrl)), | ||
duration, | ||
title, | ||
}; | ||
} | ||
catch (err) { | ||
Logger.error(`Failed to get yandex disk video data by disk video ID: ${videoId}`, err.message); | ||
return undefined; | ||
} | ||
} | ||
async getVideoData(videoId) { | ||
if (videoId.startsWith(this.INLINE_PREFIX)) { | ||
return { | ||
url: this.service.url + videoId.slice(1), | ||
}; | ||
} | ||
videoId = decodeURIComponent(videoId); | ||
return await this.getDiskVideoData(videoId); | ||
} | ||
async getVideoId(url) { | ||
return /\/i\/([^/]+)/.exec(url.pathname)?.[1]; | ||
const fileId = /\/i\/([^/]+)/.exec(url.pathname)?.[0]; | ||
if (fileId) { | ||
return fileId; | ||
} | ||
return /\/d\/([^/]+)\/([^/]+)/.exec(url.pathname) | ||
? url.pathname | ||
: undefined; | ||
} | ||
} |
{ | ||
"name": "@vot.js/node", | ||
"description": "package for runtimes", | ||
"version": "2.1.3", | ||
"version": "2.1.4", | ||
"author": "Toil", | ||
@@ -85,4 +85,4 @@ "license": "MIT", | ||
"dependencies": { | ||
"@vot.js/shared": "^2.1.3", | ||
"@vot.js/core": "^2.1.3", | ||
"@vot.js/shared": "^2.1.4", | ||
"@vot.js/core": "^2.1.4", | ||
"dom-parser": "^1.1.5" | ||
@@ -89,0 +89,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
127148
2654
Updated@vot.js/core@^2.1.4
Updated@vot.js/shared@^2.1.4