-
⚠️ IMPORTANT
-
Any app meeting the following criteria is free to use my modules:
-
-- No paywall, subscription, or payment required for my modules
- (you may charge for other parts of your app).
-- No advertisements during the usage of my modules.
-- Open source: your app’s source code must be publicly available.
-
-
All the above terms are mandatory unless given permission by me.
-In short: no commercial use and transparency is required.
-
-
-
-
🚫 CAUTION
-
Do not pay to use these modules — if someone is charging you, it's a scam!
-
Neither should you bear watching ads to use these modules. Please report apps that do this forcibly!
-
-
-
-
-[](https://discord.com/users/1072985316916469870)
-
-
-
-[](https://ko-fi.com/50n50)
-
-
-
-
diff --git a/.tmp.driveupload/3462 b/.tmp.driveupload/3462
deleted file mode 100644
index 41bffab..0000000
--- a/.tmp.driveupload/3462
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "sourceName": "Ashi (あし) - Literally Everything",
- "iconUrl": "https://files.catbox.moe/y8v199.png",
- "author": {
- "name": "50/50",
- "icon": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3122kQwublLkZ6rf1fEpUP79BxZOFmH9BSA&s"
- },
- "version": "1.1.1",
- "language": "English",
- "streamType": "HLS",
- "quality": "1080p",
- "baseUrl": "https://animekai.to/",
- "searchBaseUrl": "https://animekai.to/",
- "scriptUrl": "https://git.luna-app.eu/50n50/sources/raw/branch/main/ashi/ashi.js",
- "type": "anime/movies/shows",
- "asyncJS": true,
- "softsub": true,
- "downloadSupport": true
-}
diff --git a/.tmp.driveupload/3464 b/.tmp.driveupload/3464
deleted file mode 100644
index 69436d5..0000000
--- a/.tmp.driveupload/3464
+++ /dev/null
@@ -1,761 +0,0 @@
-//
-//
-// Main functions
-//
-//
-
-async function searchResults(query) {
- const encodeQuery = keyword => encodeURIComponent(keyword);
-
- const decodeHtmlEntities = (str) => {
- if (!str) return str;
- return str.replace(/(\d+);/g, (match, dec) => String.fromCharCode(dec))
- .replace(/"/g, '"')
- .replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>');
- };
-
- const fuzzyMatch = (query, title) => {
- const q = query.toLowerCase().trim();
- const t = title.toLowerCase().trim();
-
- if (t === q) return 1000;
-
- if (t.startsWith(q + ' ') || t.startsWith(q + ':') || t.startsWith(q + '-')) return 950;
-
- const wordBoundaryRegex = new RegExp(`\\b${q.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`);
- if (wordBoundaryRegex.test(t)) return 900;
-
- const qTokens = q.split(/\s+/).filter(token => token.length > 0);
- const tTokens = t.split(/[\s\-:]+/).filter(token => token.length > 0);
-
- const stopwords = new Set(['the', 'a', 'an', 'and', 'or', 'of', 'in', 'on', 'at', 'to', 'for', 'with']);
-
- let score = 0;
- let exactMatches = 0;
- let partialMatches = 0;
- let significantMatches = 0;
-
- qTokens.forEach(qToken => {
- const isStopword = stopwords.has(qToken);
- let bestMatch = 0;
- let hasExactMatch = false;
-
- tTokens.forEach(tToken => {
- let matchScore = 0;
-
- if (tToken === qToken) {
- matchScore = isStopword ? 25 : 120;
- hasExactMatch = true;
- if (!isStopword) significantMatches++;
- }
- else if (qToken.includes(tToken) && tToken.length >= 3 && qToken.length <= tToken.length + 2) {
- matchScore = isStopword ? 8 : 40;
- if (!isStopword) significantMatches++;
- }
- else if (tToken.startsWith(qToken) && qToken.length >= 3) {
- matchScore = isStopword ? 12 : 70;
- if (!isStopword) significantMatches++;
- }
- else if (qToken.length >= 4 && tToken.length >= 4) {
- const dist = levenshteinDistance(qToken, tToken);
- const maxLen = Math.max(qToken.length, tToken.length);
- const similarity = 1 - (dist / maxLen);
-
- if (similarity > 0.8) {
- matchScore = Math.floor(similarity * 60);
- if (!isStopword) significantMatches++;
- }
- }
-
- bestMatch = Math.max(bestMatch, matchScore);
- });
-
- if (bestMatch > 0) {
- score += bestMatch;
- if (hasExactMatch) exactMatches++;
- else partialMatches++;
- }
- });
-
- const significantTokens = qTokens.filter(t => !stopwords.has(t)).length;
-
- const requiredMatches = Math.max(1, Math.ceil(significantTokens * 0.8));
- if (significantMatches < requiredMatches) {
- return 0;
- }
-
- if (exactMatches + partialMatches >= qTokens.length) {
- score += 80;
- }
-
- score += exactMatches * 20;
-
- const extraWords = tTokens.length - qTokens.length;
- if (extraWords > 2) {
- score -= (extraWords - 2) * 25;
- }
-
- let orderBonus = 0;
- for (let i = 0; i < qTokens.length - 1; i++) {
- const currentTokenIndex = tTokens.findIndex(t => t.includes(qTokens[i]));
- const nextTokenIndex = tTokens.findIndex(t => t.includes(qTokens[i + 1]));
-
- if (currentTokenIndex !== -1 && nextTokenIndex !== -1 && currentTokenIndex < nextTokenIndex) {
- orderBonus += 15;
- }
- }
- score += orderBonus;
-
- return Math.max(0, score);
- };
-
- const levenshteinDistance = (a, b) => {
- const matrix = [];
-
- for (let i = 0; i <= b.length; i++) {
- matrix[i] = [i];
- }
-
- for (let j = 0; j <= a.length; j++) {
- matrix[0][j] = j;
- }
-
- for (let i = 1; i <= b.length; i++) {
- for (let j = 1; j <= a.length; j++) {
- if (b.charAt(i - 1) === a.charAt(j - 1)) {
- matrix[i][j] = matrix[i - 1][j - 1];
- } else {
- matrix[i][j] = Math.min(
- matrix[i - 1][j - 1] + 1,
- matrix[i][j - 1] + 1,
- matrix[i - 1][j] + 1
- );
- }
- }
- }
-
- return matrix[b.length][a.length];
- };
-
- const animekaiSearch = async () => {
- const searchBaseUrl = "https://animekai.to/browser?keyword=";
- const baseUrl = "https://animekai.to";
-
- const posterHrefRegex = /href="[^"]*" class="poster"/g;
- const titleRegex = /class="title"[^>]*title="[^"]*"/g;
- const imageRegex = /data-src="[^"]*"/g;
- const extractHrefRegex = /href="([^"]*)"/;
- const extractImageRegex = /data-src="([^"]*)"/;
- const extractTitleRegex = /title="([^"]*)"/;
-
- const extractResultsFromHTML = (htmlText) => {
- const results = [];
- const posterMatches = htmlText.match(posterHrefRegex) || [];
- const titleMatches = htmlText.match(titleRegex) || [];
- const imageMatches = htmlText.match(imageRegex) || [];
- const minLength = Math.min(posterMatches.length, titleMatches.length, imageMatches.length);
-
- for (let i = 0; i < minLength; i++) {
- const hrefMatch = posterMatches[i].match(extractHrefRegex);
- const fullHref = hrefMatch ? (hrefMatch[1].startsWith("http") ? hrefMatch[1] : baseUrl + hrefMatch[1]) : null;
-
- const imageMatch = imageMatches[i].match(extractImageRegex);
- const imageSrc = imageMatch ? imageMatch[1] : null;
-
- const titleMatch = titleMatches[i].match(extractTitleRegex);
- const cleanTitle = titleMatch ? decodeHtmlEntities(titleMatch[1]) : null;
-
- if (fullHref && imageSrc && cleanTitle) {
- results.push({
- href: `Animekai:${fullHref}`,
- image: imageSrc,
- title: cleanTitle
- });
- }
- }
-
- return results;
- };
-
- try {
- const encodedQuery = encodeQuery(query);
- const urls = [
- `${searchBaseUrl}${encodedQuery}`,
- `${searchBaseUrl}${encodedQuery}&page=2`,
- `${searchBaseUrl}${encodedQuery}&page=3`
- ];
-
- const responses = await Promise.all(urls.map(url => fetchv2(url)));
- const htmlTexts = await Promise.all(responses.map(res => res.text()));
-
- const allResults = [];
- htmlTexts.forEach(html => allResults.push(...extractResultsFromHTML(html)));
- return allResults;
- } catch (error) {
- console.error("Animekai search error:" + error);
- return [];
- }
- };
-
- const oneMoviesSearch = async () => {
- const searchBaseUrl = "https://1movies.bz/browser?keyword=";
- const baseUrl = "https://1movies.bz";
-
- const posterHrefRegex = /href="([^"]*)" class="poster"/g;
- const titleRegex = /class="title" href="[^"]*">([^<]*) {
- const results = [];
- const posterMatches = [...htmlText.matchAll(posterHrefRegex)];
- const titleMatches = [...htmlText.matchAll(titleRegex)];
- const imageMatches = [...htmlText.matchAll(imageRegex)];
- const minLength = Math.min(posterMatches.length, titleMatches.length, imageMatches.length);
-
- for (let i = 0; i < minLength; i++) {
- const href = posterMatches[i][1];
- const fullHref = href.startsWith("http") ? href : baseUrl + href;
-
- const imageSrc = imageMatches[i][1];
- const title = decodeHtmlEntities(titleMatches[i][1]);
-
- results.push({ href: fullHref, image: imageSrc, title });
- }
- return results;
- };
-
- try {
- const encodedQuery = encodeQuery(query);
- const urls = [
- `${searchBaseUrl}${encodedQuery}`,
- `${searchBaseUrl}${encodedQuery}&page=2`,
- `${searchBaseUrl}${encodedQuery}&page=3`
- ];
-
- const responses = await Promise.all(urls.map(url => fetchv2(url)));
- const htmlTexts = await Promise.all(responses.map(res => res.text()));
-
- const allResults = [];
- htmlTexts.forEach(html => allResults.push(...extractResultsFromHTML(html)));
- return allResults;
- } catch (error) {
- console.error("1Movies search error:" + error);
- return [];
- }
- };
-
- try {
- const [animekaiResults, oneMoviesResults] = await Promise.all([
- animekaiSearch(),
- oneMoviesSearch()
- ]);
-
- const mergedResults = [...animekaiResults, ...oneMoviesResults];
-
- const scoredResults = mergedResults.map(r => ({
- ...r,
- score: fuzzyMatch(query, r.title)
- }));
-
- const filteredResults = scoredResults
- .filter(r => r.score > 50)
- .sort((a, b) => b.score - a.score)
- .map(({ score, ...rest }) => rest);
-
- return JSON.stringify(filteredResults.length > 0 ? filteredResults : [{
- href: "",
- image: "",
- title: "No results found, please refine query."
- }]);
- } catch (error) {
- return JSON.stringify([{
- href: "",
- image: "",
- title: "Search failed: " + error.message
- }]);
- }
-}
-
-async function extractDetails(url) {
-
- if (url.startsWith("Animekai:")) {
- const actualUrl = url.replace("Animekai:", "").trim();
-
- try {
- const response = await fetchv2(actualUrl);
- const htmlText = await response.text();
-
- const descriptionMatch = (/