mirror of
https://git.luna-app.eu/50n50/sources
synced 2025-12-28 10:15:18 +01:00
Upload
This commit is contained in:
commit
09c423e95a
276 changed files with 54396 additions and 0 deletions
BIN
filmpalast/filmpalast.ico
Normal file
BIN
filmpalast/filmpalast.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
287
filmpalast/filmpalast.js
Normal file
287
filmpalast/filmpalast.js
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
/**
|
||||
* filmpalast.js
|
||||
* A module for Sora that provides watch functionality for filmpalast.to.
|
||||
* @module filmpalast
|
||||
* @author JMcrafte26
|
||||
* @license MIT
|
||||
* @version 1.1.3
|
||||
* @mirror https://api.jm26.net/sora-modules/filmpalast/filmpalast.json
|
||||
*/
|
||||
|
||||
/**
|
||||
* Searches for films on filmpalast.to based on a keyword.
|
||||
* @param {string} keyword - The search keyword.
|
||||
* @returns {Promise<string>} - A JSON string of search results.
|
||||
*/
|
||||
async function searchResults(keyword) {
|
||||
try {
|
||||
const encodedKeyword = encodeURIComponent(keyword);
|
||||
const html = await fetch(
|
||||
`https://filmpalast.to/search/title/${encodedKeyword}`
|
||||
);
|
||||
const filmListRegex =
|
||||
/<article class="liste glowliste rb"[\s\S]*?<\/article>/g;
|
||||
const items = html.match(filmListRegex) || [];
|
||||
|
||||
const results = [];
|
||||
|
||||
items.forEach((itemHtml, index) => {
|
||||
const titleMatch = itemHtml.match(
|
||||
/<a href="([^"]+)" class="rb" title="([^"]+)"[^>]*>([^<]+)<\/a>/
|
||||
);
|
||||
let title = titleMatch ? titleMatch[3] : "";
|
||||
const hrefMatch = itemHtml.match(
|
||||
/<a href="\/\/filmpalast.to\/stream\/([^"]+)"[^>]*>/
|
||||
);
|
||||
const href = hrefMatch
|
||||
? `https://filmpalast.to/stream/${hrefMatch[1]}`
|
||||
: "";
|
||||
const imageMatch = itemHtml.match(
|
||||
/<img[^>]+src="([^"]+)"[^>]+class="cover-opacity"[^>]*>/
|
||||
);
|
||||
const image = "https://filmpalast.to" + (imageMatch ? imageMatch[1] : "");
|
||||
title = cleanTitle(title);
|
||||
|
||||
if (title && href) {
|
||||
results.push({
|
||||
title,
|
||||
image,
|
||||
href,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return JSON.stringify(results);
|
||||
} catch (error) {
|
||||
console.log("Fetch error:", error);
|
||||
return JSON.stringify([{ title: "Error", image: "", href: "" }]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans the title by replacing HTML entities with their corresponding characters.
|
||||
* @param {string} title - The title to clean.
|
||||
* @returns {string} - The cleaned title.
|
||||
*/
|
||||
function cleanTitle(title) {
|
||||
return title
|
||||
.replace(/&/g, "&")
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, "'")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">");
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts details from a film's page.
|
||||
* @param {string} url - The URL of the film's page.
|
||||
* @returns {Promise<string>} - A JSON string of the film's details.
|
||||
*/
|
||||
async function extractDetails(url) {
|
||||
try {
|
||||
const html = await fetch(url);
|
||||
const descriptionMatch = html.match(
|
||||
/<span itemprop="description">([^<]+)<\/span>/
|
||||
);
|
||||
const description = descriptionMatch
|
||||
? descriptionMatch[1]
|
||||
: "Error loading description";
|
||||
|
||||
const durationMatch = html.match(/<br \/>Spielzeit: <em>([^<]+)<\/em>/);
|
||||
const duration = durationMatch ? durationMatch[1] : "Unknown";
|
||||
|
||||
const airedMatch = html.match(/<br \/>Veröffentlicht: (\d{4})/);
|
||||
const aired = airedMatch ? airedMatch[1] : "Unknown";
|
||||
|
||||
const transformedResults = [
|
||||
{
|
||||
description,
|
||||
aliases: `Duration: ${duration}`,
|
||||
airdate: `Aired: ${aired}`,
|
||||
},
|
||||
];
|
||||
return JSON.stringify(transformedResults);
|
||||
} catch (error) {
|
||||
console.log("Details error:", error);
|
||||
return JSON.stringify([
|
||||
{
|
||||
description: "Error loading description",
|
||||
aliases: "Duration: Unknown",
|
||||
airdate: "Aired: Unknown",
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts episodes from a film's page.
|
||||
* @param {string} url - The URL of the film's page.
|
||||
* @returns {Promise<string>} - A JSON string of the episodes.
|
||||
*/
|
||||
async function extractEpisodes(url) {
|
||||
try {
|
||||
const match = url.match(/https:\/\/filmpalast\.to\/stream\/(.+)$/);
|
||||
if (!match) {
|
||||
return JSON.stringify([{ number: "0", href: "" }]);
|
||||
}
|
||||
|
||||
return JSON.stringify([{ number: "1", href: url }]);
|
||||
} catch (error) {
|
||||
console.log("Fetch error:", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the stream URL from a film's page.
|
||||
* @param {string} url - The URL of the film's page.
|
||||
* @returns {Promise<string|null>} - The stream URL or null if not found.
|
||||
*
|
||||
*/
|
||||
async function extractStreamUrl(url) {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
const html = await response.text ? response.text() : response;
|
||||
|
||||
let streamUrl = null;
|
||||
try {
|
||||
streamUrl = await voeExtract(html);
|
||||
} catch (error) {
|
||||
console.log('VOE HD extraction error:', error);
|
||||
}
|
||||
|
||||
console.log('Voe Stream URL: ' + streamUrl);
|
||||
if (streamUrl && streamUrl !== false && streamUrl !== null) {
|
||||
return streamUrl;
|
||||
}
|
||||
|
||||
|
||||
console.log('using alternative extraction method');
|
||||
try {
|
||||
streamUrl = await bigWarpExtract(html);
|
||||
} catch (error) {
|
||||
console.log('BigWarp HD extraction error:', error);
|
||||
}
|
||||
|
||||
console.log('BigWarp Stream URL: ' + streamUrl);
|
||||
if (streamUrl && streamUrl !== false && streamUrl !== null) {
|
||||
return streamUrl;
|
||||
}
|
||||
|
||||
console.log('No stream URL found');
|
||||
|
||||
return null;
|
||||
|
||||
} catch (error) {
|
||||
console.log("Fetch error:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the stream URL from a film's page.
|
||||
* @param {string} url - The URL of the film's page.
|
||||
* @returns {Promise<string|null>} - The stream URL or null if not found.
|
||||
* Thanks to @Hamzo for the Voe extraction code.
|
||||
*/
|
||||
|
||||
async function voeExtract(html) {
|
||||
console.log('VOE HD extraction method');
|
||||
const voeRegex = /<ul class="currentStreamLinks"[\s\S]*?<p class="hostName">VOE HD<\/p>[\s\S]*?<a[^>]+class="button rb iconPlay"[^>]+href="([^"]+)"[^>]*>/;
|
||||
const voeMatch = voeRegex.exec(html);
|
||||
|
||||
if (!voeMatch || !voeMatch[1]) {
|
||||
console.log('VOE HD stream URL not found');
|
||||
return false;
|
||||
}
|
||||
const voeUrl = voeMatch[1];
|
||||
|
||||
|
||||
console.log('VOE URL:', voeUrl);
|
||||
|
||||
const videoPage = await fetch(voeUrl);
|
||||
if (!videoPage) {
|
||||
console.log('VOE HD video page not found');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const scriptRegex = /window\.location\.href\s*=\s*['"]([^'"]+)['"]/;
|
||||
const scriptMatch = scriptRegex.exec(videoPage);
|
||||
const winLocUrl = scriptMatch ? scriptMatch[1] : '';
|
||||
|
||||
if (!winLocUrl) {
|
||||
console.log('VOE HD window location URL not found');
|
||||
return false;
|
||||
}
|
||||
|
||||
const hlsSourceUrl = await fetch(winLocUrl);
|
||||
|
||||
const sourcesRegex = /var\s+sources\s*=\s*({[^}]+})/;
|
||||
const sourcesMatch = sourcesRegex.exec(hlsSourceUrl);
|
||||
let sourcesString = sourcesMatch ? sourcesMatch[1].replace(/'/g, '"') : null;
|
||||
|
||||
sourcesString = sourcesString ? sourcesString.replace(/,\s*}/g, '}').replace(/,\s*]/g, ']') : null;
|
||||
|
||||
const sources = sourcesString ? JSON.parse(sourcesString) : null;
|
||||
if (sources && sources.hls) {
|
||||
const hlsBase64 = sources.hls;
|
||||
const hlsDecoded = base64Decode(hlsBase64);
|
||||
console.log('HLS Decoded:' + hlsDecoded);
|
||||
return hlsDecoded;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the stream URL from a film's page.
|
||||
* @param {string} url - The URL of the film's page.
|
||||
* @returns {Promise<string|null>} - The stream URL or null if not found.
|
||||
*/
|
||||
|
||||
async function bigWarpExtract(html) {
|
||||
console.log('BigWarp HD extraction method');
|
||||
const bwRegex = /<ul class="currentStreamLinks"[\s\S]*?<p class="hostName">BigWarp HD<\/p>[\s\S]*?<a[^>]+class="button rb iconPlay"[^>]+href="([^"]+)"[^>]*>/;
|
||||
const bwMatch = bwRegex.exec(html);
|
||||
|
||||
if (!bwMatch || !bwMatch[1]) {
|
||||
console.log('BigWarp HD stream URL not found');
|
||||
return false;
|
||||
}
|
||||
|
||||
let bwUrl = bwMatch[1];
|
||||
|
||||
console.log('BigWarp URL:', bwUrl);
|
||||
|
||||
const videoPage = await fetch(bwUrl);
|
||||
|
||||
const scriptRegex = /jwplayer\("vplayer"\)\.setup\(\{[\s\S]*?sources:\s*\[\{file:"([^"]+)",label:"[^"]+"\}\]/;
|
||||
const scriptMatch = scriptRegex.exec(videoPage);
|
||||
const bwDecoded = scriptMatch ? scriptMatch[1] : false;
|
||||
console.log('BigWarp HD Decoded:', bwDecoded);
|
||||
return bwDecoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a base64 encoded string.
|
||||
* @param {string} str - The base64 encoded string.
|
||||
* @returns {string} - The decoded string.
|
||||
*/
|
||||
function base64Decode(str) {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
let output = '';
|
||||
|
||||
str = String(str).replace(/=+$/, '');
|
||||
|
||||
if (str.length % 4 === 1) {
|
||||
throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");
|
||||
}
|
||||
|
||||
for (let bc = 0, bs, buffer, idx = 0; (buffer = str.charAt(idx++)); ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0) {
|
||||
buffer = chars.indexOf(buffer);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
// Check out the Sora WebUI at https://api.jm26.net/sora-modules/
|
||||
19
filmpalast/filmpalast.json
Normal file
19
filmpalast/filmpalast.json
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"sourceName": "Filmpalast",
|
||||
"iconUrl": "https://api.jm26.net/sora-modules/filmpalast/filmpalast.ico",
|
||||
"author": {
|
||||
"name": "Cufiy",
|
||||
"icon": "https://cdn.discordapp.com/avatars/606801871189049344/d5aba1f20de41a14540e66f357d0707b.webp",
|
||||
"url": "https://github.com/JMcrafter26"
|
||||
},
|
||||
"version": "1.1.3",
|
||||
"language": "German (DUB)",
|
||||
"streamType": "HLS",
|
||||
"quality": "720p",
|
||||
"baseUrl": "https://filmpalast.to",
|
||||
"searchBaseUrl": "https://filmpalast.to/search/title/%s",
|
||||
"scriptUrl": "https://api.jm26.net/sora-modules/filmpalast/filmpalast.js",
|
||||
"asyncJS": true,
|
||||
"streamAsyncJS": false,
|
||||
"type": "movies/shows"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue