Skip to content

Commit

Permalink
fix epic games helper
Browse files Browse the repository at this point in the history
  • Loading branch information
ilyhalight committed Dec 7, 2024
1 parent 6a7249b commit edc1afc
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 40 deletions.
10 changes: 10 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# 2.0.9

## Ext

- Fix EpicGames helper

## Node

- Fix EpicGames helper

# 2.0.8

## Ext
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vot.js",
"version": "2.0.8",
"version": "2.0.9",
"author": "Toil",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vot.js/core",
"description": "core package",
"version": "2.0.8",
"version": "2.0.9",
"author": "Toil",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/ext/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vot.js/ext",
"description": "package for web extensions",
"version": "2.0.8",
"version": "2.0.9",
"author": "Toil",
"license": "MIT",
"repository": {
Expand Down
90 changes: 77 additions & 13 deletions packages/ext/src/helpers/epicgames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,76 @@ export default class EpicGamesHelper extends BaseHelper {
}
}

getVideoBlock() {
const videoUrlRe = /videoUrl\s?=\s"([^"]+)"?/;
const script = Array.from(document.body.querySelectorAll("script")).find(
(s) => videoUrlRe.exec(s.innerHTML),
);
if (!script) {
return undefined;
}

const content = script.innerHTML.trim();
const playlistUrl = videoUrlRe
.exec(content)?.[1]
?.replace("qsep://", "https://");
if (!playlistUrl) {
return undefined;
}

let subtitlesString = /sources\s?=\s(\[([^\]]+)\])?/.exec(content)?.[1];
if (!subtitlesString) {
return {
playlistUrl,
subtitles: [],
};
}

try {
subtitlesString = (
subtitlesString
.replace(/src:(\s)+?(videoUrl)/g, 'src:"removed"')
.substring(0, subtitlesString.lastIndexOf("},")) + "]"
)
.split("\n")
.map((line) => line.replace(/([^\s]+):\s?(?!.*\1)/, '"$1":'))
.join("\n");
const subtitlesObj = JSON.parse(
subtitlesString,
) as EpicGames.VideoSources[];
const subtitles = subtitlesObj.filter((sub) => sub.type === "captions");

return {
playlistUrl,
subtitles,
};
} catch {
return {
playlistUrl,
subtitles: [],
};
}
}

async getVideoData(videoId: string): Promise<MinimalVideoData | undefined> {
const postInfo = await this.getPostInfo(videoId);
if (!postInfo) {
return undefined;
}

const videoBlock = postInfo.blocks.find((block) => block.type === "video");
const playlistUrl = videoBlock?.video_url?.replace("qsep://", "https://");
if (!playlistUrl) {
const videoBlock = this.getVideoBlock();
if (!videoBlock) {
return undefined;
}

const { playlistUrl, subtitles: videoSubtitles } = videoBlock;
const { title, description } = postInfo;
const subtitles: VideoDataSubtitle[] | undefined =
videoBlock?.video_captions?.map((caption) => ({
language: normalizeLang(caption.locale),
source: "epicgames",
format: "vtt",
url: caption.signed_url,
}));
const subtitles: VideoDataSubtitle[] = videoSubtitles.map((caption) => ({
language: normalizeLang(caption.srclang),
source: "epicgames",
format: "vtt",
url: caption.src,
}));

// url returns a json containing a dash playlist (in base64) in the playlist field
return {
Expand All @@ -55,8 +105,22 @@ export default class EpicGamesHelper extends BaseHelper {
};
}

// eslint-disable-next-line @typescript-eslint/require-await
async getVideoId(url: URL) {
return /\/(\w{3,5})\/[^/]+$/.exec(url.pathname)?.[1];
async getVideoId(url: URL): Promise<string | undefined> {
return new Promise((resolve) => {
const origin = "https://dev.epicgames.com";
window.addEventListener("message", (e) => {
if (e.origin !== origin) {
return undefined;
}

if (typeof e.data === "string" && e.data.startsWith("getVideoId:")) {
const videoId = e.data.replace("getVideoId:", "");
return resolve(videoId);
}

return undefined;
});
window.top!.postMessage("getVideoId", origin);
});
}
}
6 changes: 2 additions & 4 deletions packages/ext/src/helpers/nineanimetv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,8 @@ export default class NineAnimeTVHelper extends BaseHelper {
return undefined;
}

// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
if (e.data?.startsWith("getVideoId:")) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
const videoId = e.data.replace("getVideoId:", "") as string;
if (typeof e.data === "string" && e.data.startsWith("getVideoId:")) {
const videoId = e.data.replace("getVideoId:", "");
return resolve(videoId);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/node/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vot.js/node",
"description": "package for runtimes",
"version": "2.0.8",
"version": "2.0.9",
"author": "Toil",
"license": "MIT",
"repository": {
Expand Down
34 changes: 23 additions & 11 deletions packages/node/src/helpers/epicgames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,47 @@ export default class EpicGamesHelper extends BaseHelper {
}
}

async fetchPlaylistUrl(embedId: string) {
try {
const res = await this.fetch(
`https://dev.epicgames.com/community/api/cms/videos/${embedId}/embed.html`,
);
const content = await res.text();
const playlistUrl = /videoUrl\s?=\s"([^"]+)"?/.exec(content);
return playlistUrl?.[1]?.replace("qsep://", "https://");
} catch (err) {
Logger.error(
`Failed to get playlist url by embed Id ${embedId}, because: ${
(err as Error).message
}`,
);
return undefined;
}
}

async getVideoData(videoId: string): Promise<MinimalVideoData | undefined> {
const postInfo = await this.getPostInfo(videoId);
if (!postInfo) {
return undefined;
}

const videoBlock = postInfo.blocks.find((block) => block.type === "video");
const playlistUrl = videoBlock?.video_url?.replace("qsep://", "https://");
if (!videoBlock) {
return undefined;
}

const playlistUrl = await this.fetchPlaylistUrl(videoBlock.video_id);
if (!playlistUrl) {
return undefined;
}

const { title, description } = postInfo;
const subtitles = videoBlock?.video_captions?.map(
(caption) =>
({
language: normalizeLang(caption.locale),
source: "epicgames",
format: "vtt",
url: caption.signed_url,
}) as VideoDataSubtitle,
);

// url returns a json containing a dash playlist (in base64) in the playlist field
return {
url: playlistUrl,
title,
description,
subtitles,
};
}

Expand Down
2 changes: 1 addition & 1 deletion packages/shared/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vot.js/shared",
"description": "shared for all @vot.js package",
"version": "2.0.8",
"version": "2.0.9",
"author": "Toil",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/data/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ export default {
defaultDuration: 343,
minChunkSize: 5295308,
loggerLevel: 1,
version: "2.0.8",
version: "2.0.9",
} as ConfigSchema;
17 changes: 11 additions & 6 deletions packages/shared/src/types/helpers/epicgames.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
export type VideoCaption = {
signed_url: string;
locale: string; // en-us
srclang: string;
type: "captions";
src: string;
};

export type VideoSources =
| VideoCaption
| {
src: string;
type: "quicksilver";
};

export type VideoBlock = {
type: "video";
video_id: string;
provider: string;
caption: string;
autoplay: boolean;
video_url: string; // startswith qsep://
video_captions: VideoCaption[];
video_thumbnail_large_url: string;
};

export type Link = {
Expand All @@ -33,6 +38,6 @@ export type Post = {
title: string;
description: string;
locale: string; // en-us
blocks: [VideoBlock, LinkGroupBlock];
blocks: [VideoBlock, LinkGroupBlock]; // now useless
status: "published";
};

0 comments on commit edc1afc

Please sign in to comment.