diff --git a/README.md b/README.md index b2505d8c..5509665a 100644 --- a/README.md +++ b/README.md @@ -20,9 +20,9 @@ et Firefox. Elle permet de diffuser des vidéos et des musiques sur **Kodi** : - YouTube, Twitch, Vimeo, SoundCloud ainsi que Acast, Ace Stream, Apple Podcasts, Ausha, Bigo Live, BitChute, Blog Talk Radio, Castbox, Dailymotion, DevTube, Facebook, Flickr, Instagram, ItemFix, Jamendo, Mastodon, Megaphone, - Mixcloud, Odysee, Overcast, PeerTube, Pippa, Podcast Addict, podCloud, - Pokémon TV, Radio, Radioline, Reddit, Steam, Streamable, TikTok, Ultimedia, - Veoh, VideoPress, VideosHub, Vidyard, Viously ; + Mixcloud, Odysee, Overcast, PeerTube, Podcast Addict, podCloud, Pokémon TV, + Radio, Radioline, Reddit, Steam, Streamable, TikTok, Ultimedia, Veoh, + VideoPress, VideosHub, Vidyard, Viously ; - 🇩🇪 Allemagne : ARD Mediathek, Arte, DMAX, ZDF ; - 🇧🇪 Belgique : GoPlay, VRT NU, VTM GO ; - 🇺🇸 États-Unis : KCAA Radio ; diff --git a/locales/en/description.tpl b/locales/en/description.tpl index 20a4c7c0..6c09339b 100644 --- a/locales/en/description.tpl +++ b/locales/en/description.tpl @@ -8,7 +8,7 @@ Cast Kodi, as the name suggests, adds the ability to cast videos and music direct links: avi, mkv, mp3, flac, … and torrent / magnet;
undefined
.
*/
-const action = function ({ pathname }) {
- const [, s, e] = pathname.split("/");
- return Promise.resolve(`https://sphinx.acast.com/p/open/s/${s}/e/${e}` +
- "/media.mp3");
+const action = async function ({ pathname }) {
+ const result = REGEXP.exec(pathname);
+ const response = await fetch(`${API_URL}/shows/${result.groups.show}` +
+ `/episodes/${result.groups.episode}`);
+ const json = await response.json();
+ return json.url;
};
-export const extract = matchPattern(action, "*://embed.acast.com/*/*");
+export const extract = matchPattern(action,
+ "*://play.acast.com/s/*/*",
+ "*://embed.acast.com/*/*");
diff --git a/test/integration/scraper/acast.js b/test/integration/scraper/acast.js
index f7a50c3a..c18319c4 100644
--- a/test/integration/scraper/acast.js
+++ b/test/integration/scraper/acast.js
@@ -3,20 +3,32 @@ import { extract } from "../../../src/core/scrapers.js";
describe("Scraper: Acast", function () {
it("should return audio URL [opengraph]", async function () {
- const url = new URL("https://shows.acast.com/cdanslair/episodes" +
- "/chine-le-virus-qui-inquiete-le-monde-22-01-2020");
+ const url = new URL("https://play.acast.com/s/c-dans-lair" +
+ "/8caa8723-c9fd-4104-97f9-5da3d44f2d0b");
const options = { depth: false, incognito: false };
const file = await extract(url, options);
assert.strictEqual(file,
- "https://open.acast.com/public/streams" +
- "/5bb36892b799143c5a063e7f/episodes" +
- "/5e288874bd860fd53f96625f.mp3");
+ "https://francetv.proxycast.org/2969354392962084864" +
+ "/8caa8723-c9fd-4104-97f9-5da3d44f2d0b.mp3" +
+ "?u=VePZcdrLSG&_=1661879526");
+ });
+
+ it("should return audio URL from share [opengraph]", async function () {
+ const url = new URL("https://play.acast.com/s" +
+ "/5d84d37cf721f89940031fb4" +
+ "/63282b9b00922400136f2602");
+ const options = { depth: false, incognito: false };
+
+ const file = await extract(url, options);
+ assert.strictEqual(file,
+ "https://sphinx.acast.com/p/open/s/5d84d37cf721f89940031fb4/e" +
+ "/63282b9b00922400136f2602/media.mp3");
});
it("should return audio URL from embed", async function () {
const url = new URL("https://embed.acast.com/5b7ac427c6a58e726f576cff" +
- "/626c0242162abf00141b401b?logo=false");
+ "/626c0242162abf00141b401b?seek=42");
const options = { depth: false, incognito: false };
const file = await extract(url, options);
diff --git a/test/integration/scraper/pippa.js b/test/integration/scraper/pippa.js
deleted file mode 100644
index c6a3d256..00000000
--- a/test/integration/scraper/pippa.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import assert from "node:assert";
-import { extract } from "../../../src/core/scrapers.js";
-
-describe("Scraper: Pippa", function () {
- it("should return audio URL [opengraph]", async function () {
- const url = new URL("https://shows.pippa.io/cdanslair/episodes" +
- "/5-decembre-la-greve-qui-fait-peur-22-11-2019");
- const options = { depth: false, incognito: false };
-
- const file = await extract(url, options);
- assert.strictEqual(file,
- "https://open.acast.com/public/streams" +
- "/5bb36892b799143c5a063e7f/episodes" +
- "/5dd81469bd860fd53f965cf7.mp3");
- });
-
- it("should return audio URL when protocol is HTTP [opengraph]",
- async function () {
- const url = new URL("http://shows.pippa.io/cdanslair/episodes" +
- "/hongkong-la-colere-monte-pekin-menace-19-11-2019");
- const options = { depth: false, incognito: false };
-
- const file = await extract(url, options);
- assert.strictEqual(file,
- "https://open.acast.com/public/streams" +
- "/5bb36892b799143c5a063e7f/episodes" +
- "/5dd4250950a8cbb62f4b21ad.mp3");
- });
-});
diff --git a/test/unit/core/scraper/acast.js b/test/unit/core/scraper/acast.js
index cf963ef0..32316973 100644
--- a/test/unit/core/scraper/acast.js
+++ b/test/unit/core/scraper/acast.js
@@ -1,22 +1,63 @@
import assert from "node:assert";
+import sinon from "sinon";
import * as scraper from "../../../../src/core/scraper/acast.js";
describe("core/scraper/acast.js", function () {
describe("extract()", function () {
it("should return undefined when it's a unsupported URL",
async function () {
- const url = new URL("https://embed.acast.com/foo");
+ const url = new URL("https://play.acast.com/foo/bar");
const file = await scraper.extract(url);
assert.strictEqual(file, undefined);
});
+ it("should return undefined when id is invalid", async function () {
+ const stub = sinon.stub(globalThis, "fetch").resolves(new Response(
+ JSON.stringify({}),
+ ));
+
+ const url = new URL("https://play.acast.com/s/foo/bar");
+
+ const file = await scraper.extract(url);
+ assert.strictEqual(file, undefined);
+
+ assert.strictEqual(stub.callCount, 1);
+ assert.deepStrictEqual(stub.firstCall.args, [
+ "https://feeder.acast.com/api/v1/shows/foo/episodes/bar",
+ ]);
+ });
+
it("should return audio URL", async function () {
- const url = new URL("https://embed.acast.com/foo/bar?baz=qux");
+ const stub = sinon.stub(globalThis, "fetch").resolves(new Response(
+ JSON.stringify({ url: "https://foo.com/bar.mp3" }),
+ ));
+
+ const url = new URL("https://play.acast.com/s/baz/qux?quux=corge");
const file = await scraper.extract(url);
- assert.strictEqual(file,
- "https://sphinx.acast.com/p/open/s/foo/e/bar/media.mp3");
+ assert.strictEqual(file, "https://foo.com/bar.mp3");
+
+ assert.strictEqual(stub.callCount, 1);
+ assert.deepStrictEqual(stub.firstCall.args, [
+ "https://feeder.acast.com/api/v1/shows/baz/episodes/qux",
+ ]);
+ });
+
+ it("should return audio URL embed", async function () {
+ const stub = sinon.stub(globalThis, "fetch").resolves(new Response(
+ JSON.stringify({ url: "https://foo.com/bar.mp3" }),
+ ));
+
+ const url = new URL("https://embed.acast.com/baz/qux?quux=corge");
+
+ const file = await scraper.extract(url);
+ assert.strictEqual(file, "https://foo.com/bar.mp3");
+
+ assert.strictEqual(stub.callCount, 1);
+ assert.deepStrictEqual(stub.firstCall.args, [
+ "https://feeder.acast.com/api/v1/shows/baz/episodes/qux",
+ ]);
});
});
});