Tự động lưu và khôi phục lịch sử xem phim khi AnimeHay đổi tên miền mới
// ==UserScript==
// @name AnimeHay
// @namespace https://greasyfork.org/en/scripts/492147-animehay
// @match *://animehay.*/thong-tin-phim/*
// @match *://animehay.*/xem-phim/*
// @match *://hhtq3d*.*/*/
// @match *://hhtq3d*.*/watch/*/
// @grant GM_getValue
// @grant GM_setValue
// @version 1.7
// @author HVD
// @icon https://i.imgur.com/EiOLZtO.png
// @description Tự động lưu và khôi phục lịch sử xem phim khi AnimeHay đổi tên miền mới
// @license MIT
// ==/UserScript==
function waitForElements(selector, observeElement) {
return new Promise((resolve, reject) => {
const elements = document.querySelectorAll(selector);
if (elements.length > 0) return resolve(elements);
observeElement = document.querySelector(observeElement) || document.body;
const observer = new MutationObserver(() => {
const elements = observeElement.querySelectorAll(selector);
if (elements.length > 0) {
observer.disconnect();
resolve(elements);
}
});
observer.observe(observeElement, {
childList: true,
subtree: true,
});
setTimeout(() => {
observer.disconnect();
reject(new Error(`Elements not found: ${selector}`));
}, 10000); // Timeout after 10 seconds
});
}
const getValue = (key) => JSON.parse(GM_getValue(key, '{}'));
const setValue = (key, value) => GM_setValue(key, JSON.stringify(value));
class AnimeHay {
constructor() {
this.keyName = 'AnimeHay';
this.maxHistory = 20;
this.pathName = location.pathname;
this.watchedMovies = getValue(this.keyName);
}
save(watchedMovies) {
setValue(this.keyName, watchedMovies);
}
markViewed(watchedEps, name) {
if (watchedEps.size === 0) return;
if (watchedEps.size > this.maxHistory) watchedEps.delete([...watchedEps][0]);
const epList = document.querySelectorAll('.list-item-episode a');
for (const ep of watchedEps) {
for (const item of epList) {
const href = item.getAttribute('href');
if (href.includes(ep)) {
item.style.backgroundColor = 'rgb(25 81 75)';
break;
}
}
}
}
handleMovieInfoPage() {
const name = this.pathName.replace(/\/thong-tin-phim\/|\-(\d+).html/g, '');
const watchedEps = new Set(this.watchedMovies[name] ?? []);
this.markViewed(watchedEps, name);
}
handleWatchMoviePage() {
const [name, episode] = this.pathName.replace(/\/xem-phim\/|\.html/g, '').split('-tap-');
const watchedEps = new Set(this.watchedMovies[name] ?? []);
this.markViewed(watchedEps, name);
if (watchedEps.has(episode)) return;
watchedEps.add(episode);
this.watchedMovies[name] = [...watchedEps];
setValue(this.keyName, this.watchedMovies);
}
init() {
if (this.pathName.includes('/thong-tin-phim/')) {
this.handleMovieInfoPage();
} else if (this.pathName.includes('/xem-phim/')) {
this.handleWatchMoviePage();
}
}
}
class HHTQ {
constructor() {
this.keyName = 'HHTQ';
this.maxHistory = 20;
this.pathName = location.pathname;
this.watchedMovies = getValue(this.keyName);
}
markViewed(watchedEps, name) {
if (watchedEps.size === 0) return;
if (watchedEps.size > this.maxHistory) watchedEps.delete([...watchedEps][0]);
waitForElements('.halim-list-eps > li span', '#halim-list-server').then(epList => {
for (const ep of watchedEps) {
for (const item of epList) {
if (item.innerText == ep) {
item.style.backgroundColor = 'rgb(25 81 75)';
break;
}
}
}
document.querySelector('#halim-list-server ul li span.active').style.backgroundColor = '';
});
}
handleMovieInfoPage() {
const name = this.pathName.replace(/^\/|\/$/g, '');
const watchedEps = new Set(this.watchedMovies[name] ?? []);
this.markViewed(watchedEps, name);
}
handleWatchMoviePage() {
const [, name, episode] = this.pathName.match(/\/watch\/([^/]+)-eps-(\d+)-server-\d+\//);
const watchedEps = new Set(this.watchedMovies[name] ?? []);
this.markViewed(watchedEps, name);
if (watchedEps.has(episode)) return;
watchedEps.add(episode);
this.watchedMovies[name] = [...watchedEps];
setValue(this.keyName, this.watchedMovies);
}
init() {
if (/^\/[^/]+\/$/.test(this.pathName)) {
this.handleMovieInfoPage();
} else if (this.pathName.includes('/watch/')) {
if (!window._jwplayer) {
const self = this;
window._jwplayer = unsafeWindow.jwplayer;
unsafeWindow.jwplayer = function(id) {
if (self.pathName != location.pathname) {
self.pathName = location.pathname;
self.handleWatchMoviePage();
}
return window._jwplayer(id);
};
}
this.handleWatchMoviePage();
}
}
}
if (location.hostname.includes('animehay')) (new AnimeHay()).init();
else (new HHTQ()).init();