mirror of
https://git.luna-app.eu/50n50/sources
synced 2025-12-21 13:16:21 +01:00
Update checkmate/checkmate.js
This commit is contained in:
parent
ac2ff67c14
commit
b3d8ebbfb3
1 changed files with 145 additions and 12 deletions
|
|
@ -1,6 +1,6 @@
|
|||
//Thanks ibro for the TMDB search!
|
||||
// Credits for Search, Details, and Episodes functions to ibro, with impromements made by me
|
||||
|
||||
async function searchResults(keyword) {
|
||||
async function searchResults(query) {
|
||||
try {
|
||||
let transformedResults = [];
|
||||
|
||||
|
|
@ -14,29 +14,152 @@ async function searchResults(keyword) {
|
|||
|
||||
const skipTitleFilter = Object.values(keywordGroups).flat();
|
||||
|
||||
const shouldFilter = !matchesKeyword(keyword, skipTitleFilter);
|
||||
const shouldFilter = !matchesKeyword(query, skipTitleFilter);
|
||||
|
||||
const encodedKeyword = encodeURIComponent(keyword);
|
||||
const encodedQuery = encodeURIComponent(query);
|
||||
let baseUrl = null;
|
||||
|
||||
if (matchesKeyword(keyword, keywordGroups.trending)) {
|
||||
if (matchesKeyword(query, keywordGroups.trending)) {
|
||||
baseUrl = `https://api.themoviedb.org/3/trending/all/week?api_key=9801b6b0548ad57581d111ea690c85c8&include_adult=false&page=`;
|
||||
} else if (matchesKeyword(keyword, keywordGroups.topRatedMovie)) {
|
||||
} else if (matchesKeyword(query, keywordGroups.topRatedMovie)) {
|
||||
baseUrl = `https://api.themoviedb.org/3/movie/top_rated?api_key=9801b6b0548ad57581d111ea690c85c8&include_adult=false&page=`;
|
||||
} else if (matchesKeyword(keyword, keywordGroups.topRatedTV)) {
|
||||
} else if (matchesKeyword(query, keywordGroups.topRatedTV)) {
|
||||
baseUrl = `https://api.themoviedb.org/3/tv/top_rated?api_key=9801b6b0548ad57581d111ea690c85c8&include_adult=false&page=`;
|
||||
} else if (matchesKeyword(keyword, keywordGroups.popularMovie)) {
|
||||
} else if (matchesKeyword(query, keywordGroups.popularMovie)) {
|
||||
baseUrl = `https://api.themoviedb.org/3/movie/popular?api_key=9801b6b0548ad57581d111ea690c85c8&include_adult=false&page=`;
|
||||
} else if (matchesKeyword(keyword, keywordGroups.popularTV)) {
|
||||
} else if (matchesKeyword(query, keywordGroups.popularTV)) {
|
||||
baseUrl = `https://api.themoviedb.org/3/tv/popular?api_key=9801b6b0548ad57581d111ea690c85c8&include_adult=false&page=`;
|
||||
} else {
|
||||
baseUrl = `https://api.themoviedb.org/3/search/multi?api_key=9801b6b0548ad57581d111ea690c85c8&query=${encodedKeyword}&include_adult=false&page=`;
|
||||
baseUrl = `https://api.themoviedb.org/3/search/multi?api_key=9801b6b0548ad57581d111ea690c85c8&query=${encodedQuery}&include_adult=false&page=`;
|
||||
}
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
let dataResults = [];
|
||||
|
||||
if (baseUrl) {
|
||||
const pagePromises = Array.from({ length: 5 }, (_, i) =>
|
||||
const pagePromises = Array.from({ length: 10 }, (_, i) =>
|
||||
soraFetch(baseUrl + (i + 1)).then(r => r.json())
|
||||
);
|
||||
const pages = await Promise.all(pagePromises);
|
||||
|
|
@ -64,10 +187,20 @@ async function searchResults(keyword) {
|
|||
.filter(Boolean)
|
||||
.filter(result => result.title !== "Overflow")
|
||||
.filter(result => result.title !== "My Marriage Partner Is My Student, a Cocky Troublemaker")
|
||||
.filter(r => !shouldFilter || r.title.toLowerCase().includes(keyword.toLowerCase()))
|
||||
);
|
||||
}
|
||||
|
||||
if (shouldFilter) {
|
||||
const scoredResults = transformedResults.map(r => ({
|
||||
...r,
|
||||
score: fuzzyMatch(query, r.title)
|
||||
}));
|
||||
transformedResults = scoredResults
|
||||
.filter(r => r.score > 50)
|
||||
.sort((a, b) => b.score - a.score)
|
||||
.map(({ score, ...rest }) => rest);
|
||||
}
|
||||
|
||||
console.log("Transformed Results: " + JSON.stringify(transformedResults));
|
||||
return JSON.stringify(transformedResults);
|
||||
} catch (error) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue