diff --git a/README.md b/README.md index 9316e5a8..3ae31147 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ des vidéos et des musiques sur **Kodi** : My Cloud Player, Odysee, Overcast, PeerTube, Pippa, podCloud, Pokémon TV, Radio, Radioline, Steam, Streamable, TikTok, Ultimedia, Veoh, VideoPress, Viously ; - - Allemagne : Arte ; + - Allemagne : Arte, ZDF ; - Belgique : VRT NU, VTM GO ; - États-Unis : KCAA Radio ; - France : 20 Minutes, AlloCiné, Arte, Arte Radio, France Inter, Futura diff --git a/locales/en/amo_description.html b/locales/en/amo_description.html index 99176c52..c41efc47 100644 --- a/locales/en/amo_description.html +++ b/locales/en/amo_description.html @@ -6,16 +6,16 @@
null
.
+ */
+const action = async function (_url, content) {
+ const doc = await content.html();
+ const button = doc.querySelector("button.download-btn[data-dialog]");
+ if (null === button) {
+ return null;
+ }
+
+ const { contentUrl, apiToken } = JSON.parse(button.dataset.dialog);
+ const url = contentUrl.replace("{playerId}", "ngplayer_2_4");
+ const response = await fetch(url, {
+ headers: new Headers({ "Api-Auth": `Bearer ${apiToken}` }),
+ });
+ const json = await response.json();
+ return json.priorityList[0].formitaeten[0].qualities[0].audio.tracks[0].uri;
+};
+export const extract = matchPattern(action, "*://www.zdf.de/*");
diff --git a/src/core/scrapers.js b/src/core/scrapers.js
index a9f3c13f..3ef4a752 100644
--- a/src/core/scrapers.js
+++ b/src/core/scrapers.js
@@ -67,6 +67,7 @@ import * as viously from "./scraper/viously.js";
import * as vrtnu from "./scraper/vrtnu.js";
import * as vtmgo from "./scraper/vtmgo.js";
import * as youtube from "./scraper/youtube.js";
+import * as zdf from "./scraper/zdf.js";
/**
* La liste des extracteurs (retournant le fichier extrait ou
@@ -124,6 +125,7 @@ const SCRAPERS = [
vrtnu,
vtmgo,
youtube,
+ zdf,
// Utiliser les scrapers génériques en dernier recours.
video,
audio,
diff --git a/test/integration/scraper/zdf.js b/test/integration/scraper/zdf.js
new file mode 100644
index 00000000..3b967117
--- /dev/null
+++ b/test/integration/scraper/zdf.js
@@ -0,0 +1,23 @@
+import assert from "node:assert";
+import { extract } from "../../../src/core/scrapers.js";
+
+describe("Scraper: ZDF", function () {
+ it("should return URL when it's not a video", async function () {
+ const url = new URL("https://www.zdf.de/filme");
+ const options = { depth: false, incognito: false };
+
+ const file = await extract(url, options);
+ assert.strictEqual(file, url.href);
+ });
+
+ it("should return video URL", async function () {
+ const url = new URL("https://www.zdf.de/dokumentation/37-grad" +
+ "/37-im-schuldenstrudel-100.html");
+ const options = { depth: false, incognito: false };
+
+ const file = await extract(url, options);
+ assert.strictEqual(file,
+ "https://nrodlzdf-a.akamaihd.net/none/zdf/21/04" +
+ "/210427_sendung_37g/4/210427_sendung_37g_a1a2_2128k_p18v15.webm");
+ });
+});
diff --git a/test/unit/core/scraper/zdf.js b/test/unit/core/scraper/zdf.js
new file mode 100644
index 00000000..3a34622a
--- /dev/null
+++ b/test/unit/core/scraper/zdf.js
@@ -0,0 +1,70 @@
+import assert from "node:assert";
+import sinon from "sinon";
+import { extract } from "../../../../src/core/scraper/zdf.js";
+
+describe("core/scraper/zdf.js", function () {
+ describe("extract()", function () {
+ it("should return null when it's a unsupported URL", async function () {
+ const url = new URL("https://www.zdftext.de/");
+
+ const file = await extract(url);
+ assert.strictEqual(file, null);
+ });
+
+ it("should return null when it's not a video", async function () {
+ const url = new URL("https://www.zdf.de/foo");
+ const content = {
+ html: () => Promise.resolve(new DOMParser().parseFromString(`
+
+
+ `, "text/html")),
+ };
+
+ const file = await extract(url, content);
+ assert.strictEqual(file, null);
+ });
+
+ it("should return video URL", async function () {
+ const stub = sinon.stub(globalThis, "fetch").resolves(new Response(
+ JSON.stringify({
+ priorityList: [{
+ formitaeten: [{
+ qualities: [{
+ audio: {
+ tracks: [{
+ uri: "https://quux.de/corge.webm",
+ }],
+ },
+ }],
+ }],
+ }],
+ }),
+ ));
+
+ const url = new URL("https://www.zdf.de/foo");
+ const content = {
+ html: () => Promise.resolve(new DOMParser().parseFromString(`
+
+
+
+
+ `, "text/html")),
+ };
+
+ const file = await extract(url, content);
+ assert.strictEqual(file, "https://quux.de/corge.webm");
+
+ assert.strictEqual(stub.callCount, 1);
+ assert.deepStrictEqual(stub.firstCall.args, [
+ "http://bar.de/ngplayer_2_4/baz.json",
+ { headers: new Headers({ "Api-Auth": "Bearer qux" }) },
+ ]);
+
+ stub.restore();
+ });
+ });
+});