mirror of
https://git.luna-app.eu/50n50/sources
synced 2025-12-21 21:26:19 +01:00
215 lines
6.8 KiB
JavaScript
215 lines
6.8 KiB
JavaScript
async function searchResults(keyword) {
|
|
const results = [];
|
|
let pageNumber = 1;
|
|
let hasMore = true;
|
|
|
|
try {
|
|
while (hasMore) {
|
|
const headers = {
|
|
"next-action": await extractNextActionIdentifier(),
|
|
"Content-Type": "text/plain"
|
|
};
|
|
console.log(JSON.stringify(headers));
|
|
const postData = `[${pageNumber},"${keyword}",""]`;
|
|
const response = await fetchv2("https://mapple.site/audiobooks?search=" + encodeURIComponent(keyword), headers, "POST", postData);
|
|
const text = await response.text();
|
|
console.log("Page " + pageNumber + " response:", text);
|
|
|
|
const lines = text.split('\n').filter(line => line.trim());
|
|
let foundBooks = false;
|
|
|
|
for (const line of lines) {
|
|
try {
|
|
const data = JSON.parse(line.substring(line.indexOf('{')));
|
|
|
|
if (data.books && Array.isArray(data.books)) {
|
|
foundBooks = true;
|
|
for (const book of data.books) {
|
|
results.push({
|
|
title: book.title || "Untitled",
|
|
image: book.image || "",
|
|
href: "https://mapple.site/listen/" + (book.$id || "") + "/" + encodeURIComponent(book.title || "untitled")
|
|
});
|
|
}
|
|
hasMore = data.hasMore === true;
|
|
console.log("hasMore: " + hasMore);
|
|
}
|
|
} catch (e) {
|
|
}
|
|
}
|
|
|
|
if (!foundBooks) {
|
|
hasMore = false;
|
|
}
|
|
|
|
pageNumber++;
|
|
}
|
|
|
|
return JSON.stringify(results);
|
|
} catch (err) {
|
|
console.log("Search error:", err);
|
|
return JSON.stringify([{
|
|
title: "Error",
|
|
image: "Error",
|
|
href: "Error"
|
|
}]);
|
|
}
|
|
}
|
|
|
|
async function extractDetails(url) {
|
|
try {
|
|
return JSON.stringify([{
|
|
description: "",
|
|
aliases: "",
|
|
airdate: ""
|
|
}]);
|
|
} catch (err) {
|
|
return JSON.stringify([{
|
|
description: "Error",
|
|
aliases: "Error",
|
|
airdate: "Error"
|
|
}]);
|
|
}
|
|
}
|
|
|
|
async function extractEpisodes(url) {
|
|
const results = [];
|
|
try {
|
|
const fetchResponse = await fetchv2(url, {
|
|
"rsc": "1"
|
|
});
|
|
const fetchText = await fetchResponse.text();
|
|
|
|
const audioItemsMatch = fetchText.match(/"audio_items":\[([^\]]+)\]/);
|
|
|
|
if (audioItemsMatch && audioItemsMatch[1]) {
|
|
const audioItemsStr = audioItemsMatch[1];
|
|
const urlMatches = audioItemsStr.match(/"(https?:\/\/[^"]+)"/g);
|
|
|
|
if (urlMatches) {
|
|
for (let i = 0; i < urlMatches.length; i++) {
|
|
const audioUrl = urlMatches[i].replace(/"/g, '');
|
|
results.push({
|
|
href: audioUrl,
|
|
number: i + 1,
|
|
title: `Chapter ${i + 1}`
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
return JSON.stringify(results);
|
|
} catch (err) {
|
|
console.log("Episodes error:", err);
|
|
return JSON.stringify([{
|
|
href: "Error",
|
|
number: "Error",
|
|
title: "Error"
|
|
}]);
|
|
}
|
|
}
|
|
|
|
async function extractStreamUrl(url) {
|
|
try {
|
|
const headers = {
|
|
"Host": "ipaudio.club",
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:146.0) Gecko/20100101 Firefox/146.0",
|
|
"Accept": "*/*",
|
|
"Accept-Language": "en-US,en;q=0.5",
|
|
"Accept-Encoding": "gzip, deflate, br, zstd",
|
|
"Connection": "keep-alive",
|
|
"Sec-Fetch-Dest": "empty",
|
|
"Sec-Fetch-Mode": "no-cors",
|
|
"Sec-Fetch-Site": "cross-site",
|
|
"Priority": "u=4",
|
|
"Pragma": "no-cache",
|
|
"Cache-Control": "no-cache"
|
|
};
|
|
|
|
const streams = [{
|
|
title: `Audio Stream 1`,
|
|
streamUrl: url,
|
|
headers: headers
|
|
}];
|
|
|
|
return JSON.stringify({
|
|
streams: streams,
|
|
subtitle: ""
|
|
});
|
|
|
|
} catch (err) {
|
|
console.log("Stream error:", err);
|
|
return JSON.stringify({
|
|
streams: [{
|
|
title: "Error",
|
|
streamUrl: "",
|
|
headers: {}
|
|
}],
|
|
subtitle: ""
|
|
});
|
|
}
|
|
}
|
|
|
|
async function soraFetch(url, options = { headers: {}, method: 'GET', body: null, encoding: 'utf-8' }) {
|
|
try {
|
|
return await fetchv2(
|
|
url,
|
|
options.headers ?? {},
|
|
options.method ?? 'GET',
|
|
options.body ?? null,
|
|
true,
|
|
options.encoding ?? 'utf-8'
|
|
);
|
|
} catch(e) {
|
|
try {
|
|
return await fetch(url, options);
|
|
} catch(error) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function extractNextActionIdentifier() {
|
|
const htmlResponse = await soraFetch(atob("aHR0cHM6Ly9tYXBwbGUuc2l0ZS9hdWRpb2Jvb2tz"));
|
|
const htmlText = await htmlResponse.text();
|
|
|
|
const pageMatch = htmlText.match(/<script[^>]*src="([^"]*app\/audiobooks\/page-[^"]*\.js)"[^>]*><\/script>/);
|
|
|
|
if (!pageMatch || !pageMatch[1]) {
|
|
throw new Error("error 1");
|
|
}
|
|
|
|
const beforePageMatch = htmlText.match(/<script[^>]*src="([^"]*\.js)"[^>]*><\/script><script[^>]*src="[^"]*app\/audiobooks\/page-[^"]*\.js"/);
|
|
|
|
if (!beforePageMatch || !beforePageMatch[1]) {
|
|
throw new Error("error 2");
|
|
}
|
|
|
|
let targetUrl = beforePageMatch[1];
|
|
if (targetUrl.startsWith('/_next/')) {
|
|
targetUrl = 'https://mapple.site' + targetUrl;
|
|
} else if (!targetUrl.startsWith('http')) {
|
|
targetUrl = 'https://mapple.site/' + targetUrl;
|
|
}
|
|
|
|
try {
|
|
const response = await soraFetch(targetUrl);
|
|
const text = await response.text();
|
|
|
|
let actionMatch = text.match(/createServerReference\)\("([a-f0-9]{40,})"[^"]*"getStreamUrl/);
|
|
if (!actionMatch) {
|
|
actionMatch = text.match(/createServerReference\)\("([a-f0-9]{40,})"/);
|
|
}
|
|
if (!actionMatch) {
|
|
actionMatch = text.match(/"([a-f0-9]{40,})"[^"]*"getStreamUrl/);
|
|
}
|
|
|
|
if (actionMatch && actionMatch[1]) {
|
|
return actionMatch[1];
|
|
}
|
|
} catch (e) {
|
|
throw new Error("error 3: " + e);
|
|
}
|
|
|
|
throw new Error("error 4");
|
|
}
|