### Виправлення зроблені за допомогою Claude AI
Фікс пошуку:
uaserials.js:
function setupSearchPage(page, query) {
setPageHeader(page, DEFAULT_PAGE_TYPE, PLUGIN.id)
const itemsPerPage = 18; // відповідає до createPageLoader
var searchUrl = BASE_URL + "/index.php?do=search&story=" + encodeURIComponent(query);
function generateSearchURL(nextPageNumber) {
const searchStart = (nextPageNumber - 1) * itemsPerPage;
return searchUrl + "&search_start=" + searchStart;
}
var loader = createPageLoader(page, generateSearchURL, 1);
loader();
page.paginator = loader;
}
Фікс відео:
uaserials.js
new page.Route(PLUGIN.id + ':play:(.*)', function(page, data) {
data = JSON.parse(data);
setPageHeader(page, "video", PLUGIN.id + " - " + data.title)
const videoUrl = parseVideoURL(data.href);
if (!videoUrl) {
page.error("Не вдалося отримати URL відео");
return;
}
page.type = 'video';
page.source = 'videoparams:' + JSON.stringify({
title: data.title + (data.season ? ": " + data.season + " " + data.episode : ""),
sources: [{
url: videoUrl, // ✅ без префіксу "hls:"
mimetype: 'application/x-mpegURL' // ✅ явно вказуємо mimetype для HLS
}],
canonicalUrl: data.href, // ✅ додаємо canonical URL
year: data.year ? data.year : 0,
no_subtitle_scan: false,
no_fs_scan: false,
});
page.loading = false;
});
movie-parser.js
function base64Decode(input) {
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
var str = input.replace(/=+$/, '');
var output = '';
if (str.length % 4 == 1) {
throw new Error('Invalid base64 string');
}
for (var bc = 0, bs = 0, buffer, i = 0; (buffer = str.charAt(i++));) {
buffer = chars.indexOf(buffer);
if (buffer === -1) continue;
bs = bc % 4 ? bs * 64 + buffer : buffer;
if (bc++ % 4) {
output += String.fromCharCode(255 & bs >> (-2 * bc & 6));
}
}
return output;
}
function parseVideoURL(href) {
console.log("parseVideoURL: input href = " + href);
const allowedCDNs = ["://tortuga.wtf/", "://tortuga.tw/"]
var isValidSource = false;
for (var i in allowedCDNs) {
const cdnSubstring = allowedCDNs[i];
if (href.match(cdnSubstring)) {
isValidSource = true;
break;
}
}
if (!isValidSource) {
console.error("Unknown CDN url '" + href + "' - url must include one of " + allowedCDNs.join(" or "))
return null;
}
try {
// Передаємо Referer для обходу 403
const HTML = fetchHTML(href, 'https://uaserials.com/');
console.log("parseVideoURL: Got HTML, length = " + HTML.length);
// Перевіряємо чи це USP тип (прямий URL)
const uspPattern = /file:\s*"(https?:\/\/[^"]+)"/;
const uspMatch = HTML.match(uspPattern);
if (uspMatch) {
console.log("parseVideoURL: USP type, direct URL = " + uspMatch[1]);
return uspMatch[1];
}
// VOD тип - base64 reversed
const vodPattern = /file:\s*"([A-Za-z0-9+/=]+)"/;
const vodMatch = HTML.match(vodPattern);
if (!vodMatch) {
console.error("Not found video url in either USP or VOD format");
console.log("HTML snippet: " + HTML.substring(0, 500));
return null;
}
const encodedUrl = vodMatch[1];
console.log("parseVideoURL: VOD type, decoding...");
const decoded = base64Decode(encodedUrl);
const videoUrl = decoded.split('').reverse().join('');
console.log("parseVideoURL: Final URL = " + videoUrl);
return videoUrl;
} catch (e) {
console.error("parseVideoURL: Exception = " + e);
return null;
}
}
api.js
const http = require('movian/http');
const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36';
function fetchHTML(href, referer) {
/* returns html code as string */
var headers = {
'user-agent': USER_AGENT,
};
// Додаємо Referer якщо передано
if (referer) {
headers['referer'] = referer;
}
var response = http.request(href, {
'headers': headers,
});
logDebug("fetch '" + href + "': status code is " + response.statuscode);
response = response.toString();
return response;
}
function fetchDOM(href, referer) {
var response = fetchHTML(href, referer);
return html.parse(response);
}
function fetchDoc(href, referer) {
/* returns document, methods:
- getElementById -> object
- getElementByClassName -> array
- getElementByTagName -> array
*/
var dom = fetchDOM(href, referer);
return dom.root;
}
Відео з плеєра Tortuga тепер відтворюється і https://tortuga.tw/usp/{video_id} і https://tortuga.tw/vod/{video_id}.
### Виправлення зроблені за допомогою Claude AI
Фікс пошуку:
uaserials.js:
Фікс відео:
uaserials.js
movie-parser.js
api.js
Відео з плеєра Tortuga тепер відтворюється і https://tortuga.tw/usp/{video_id} і https://tortuga.tw/vod/{video_id}.