Sleazy Fork is available in English.

98T Picture Preview

[NOW]Click/Copy all magnet/torrent links that have not been viewed.

// ==UserScript==
// @name         98T Picture Preview
// @description  [NOW]Click/Copy all magnet/torrent links that have not been viewed.
// @version     1.9.0
// @icon data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABMLAAATCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtLvcALW92gawt9w0u73lZb2+62vKzu8ryNDpC87S9gDI1dgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArLPYAKuy1g6ts92Esbbj5rq66/u3tuv5x8jy4r3A56e7wOIhur/jAAAAAAAAAAAAAAAAAK6z3QCxt90FqKvbQ52f1XybotWZp67g+Ker5v+ipej/pKbr/7K17/+3uun/vcPpi////wDP1egAAAAAAAAAAAC4uucWuLjvfqmp6O2Xl97/kZfa/4uR3P96gNX/gYnb/46W5v+SmOv/o6js/7i97srDxvUiyc30CMOf/wDH19YAsrDpjraw8/ynovL/jY3l/3l/3P9eYtD/bXTT/5Sc5f+krO7/r7X0/5qg8P+ssvT5w8X818PF+LG0s+9cp6bnF6Ga3t6mnej/lZDo/3Z42/9vd9f/iI3g/6Op7/+ZoPX/k5z3/6mu+v+8wvr/tbz6/7i9+f+1tfL/sa7s+7y676qZktn/l4/h/4mI4P99gd7/q7Dt/5ed8P9weOz/S0/s/zg96/8+R+r/p6/8/7rC+P+nq/X/qafy/7Gu7v+0s+v3pJ/j/5eV4/+doOv/oKXx/6Op+P9OVub/T1nv/1Ra8P9ASOz/W2jz/4+Z/f+wtvj/oafv/6Cj8v+oqO7/ra7q/ael5MmjpOj/qq7x/6Cn9/+Yovv/dID3/1ll9/9kavj/XWj0/36L+P+NmP3/p6v8/7e69v+tr/T/sLPz/73C8r7AwPFBsrXr2auv7/+Ynfj/nqj8/4uW/f9sefz/XGT9/2Jp/f91gP3/eYX//6Om/P/BxPr+wcT45MXJ+Z7V3Psn////ALm+7Ty6u/Xnq6z9/6eu/P+ZoP7/bHb+/3yH/v+Sm/7/kZf+/6Wr/v+vs/v/ur7648rQ+z70/P8F2+L+AM7R+QDO0PgQy8v7w7+//f+ytv3/srf9/6Km/v+ipf//q6z//7a4//+1uv7/srL+/726/dTX2fob1df6AAAAAADCv/gAwLv4CNPQ/bfJyvv/wcP8/77C/f+5vPz/urr8/72//f+7vv7/sLD+/7Cr+//Bvfju1tf4NdTV+QAAAAAAxsj2AMfL9QnZ1fy30cz8/7689v+qpvb/tbT9/8DC/v+6u/7/t7b8/7Sx+P+3sPX/xMD2vNnc9xDV1vcAAAAAANDX9gDt4v8A3Nz8SczK98+wq+3fmZLwq6uo+47Fx/q/vb33+r279v/IxPn/xsH49MfF9Va3r/IA19z3AAAAAAAAAAAAwMz0AMbY/gG2vOsfr7PsKqus+gawtPAAzNHzF8PH8XDR0vi129v9qtPT+3DT1PgW09T4AAAAAAAAAAAA+B8AAPAPAACABwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAACAAwAAgAMAAIADAADABwAAwgcAAA==
// @author       UnforgetMemory
// @namespace    https://www.sehuatang.net/*
// @namespace    https://www.sehuatang.org/*
// @match        https://www.sehuatang.net/forum*
// @match        https://www.sehuatang.org/forum*
// @match        https://www.sehuatang.net/forum.php?mod=forumdisplay&fid=103&page=*
// @match        https://www.sehuatang.org/forum.php?mod=forumdisplay&fid=103&page=*
// @require      https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js
// @require      https://cdn.jsdelivr.net/npm/sweetalert2@11
// @require		 https://cdn.jsdelivr.net/npm/i18next@23.10.1/i18next.min.js
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_setClipboard
// @license 	 GNU GPLv3
// ==/UserScript==

(function () {
	'use strict';
	// Default Config >> Start
	const REFERER = document.location.href;
	const USER_AGENT = window.navigator.userAgent;
	const ACCEPT =
		'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7';
	const COOKIE = document.cookie;
	const JAVDB_COM = 'javdb.com';
	const VIEWED_AVIDS_LOCAL_STORAGE_KEY = '68905cf391b2428572e6446042ab1029';
	const VIEWED_US_TITLES_LOCAL_STORAGE_KEY = 'abba24c58fc69bf0955bddc7a0eadee1';
	const HIDE_VIEWED_MODE_KEY = '780fbed5c332f7f96ca73e19e94a9749';
	const VIEWED_COLOR = 'gray';
	const JIANGUOYUN_KEY_MD5 = '97f6483755d45ad927caf3108b61be91';
	const JIANGUOYUN_DAV_URL_EL_ID = `${JIANGUOYUN_KEY_MD5}_dav_url`;
	const JIANGUOYUN_ACCOUNT_EL_ID = `${JIANGUOYUN_KEY_MD5}_account`;
	const JIANGUOYUN_PASSWORD_EL_ID = `${JIANGUOYUN_KEY_MD5}_password`;
	const AVIDS_CLOUD_FILE_NAME = '95551967d3da7c5af36b141f630683c4';
	const US_CLOUD_FILE_NAME = '53648e7622cfa657f1f6de856efd67c9';
	const LOCALE_KEY = 'ee2757153264e82a1c8f64db8ddcb3e2';
	const LOCALE_LIST = {
		enUS: 'en-US',
		zhCN: 'zh-CN',
		zhHK: 'zh-HK',
		zhTW: 'zh-TW',
	};
	// Default Config >> End

	// REGEX >> Start
	const AVID_REGEX = /[a-zA-Z]{2,6}[-\s]?\d{2,5}/gi;
	// REGEX >> End

	// Gobal Var >> Start
	var elArrayLength = 0;
	// Gobal Var >> End

	// i18nnext

	i18next.init({
		lng: currentLocale(),
		fallbackLng: LOCALE_LIST.enUS,
		resources: {
			'en-US': {
				translation: {
					Language: '🕮 Language',
					'Hide Viewed': 'Hide Viewed',
					Jianguoyun: '☁️ Jianguoyun',
					'Jianguoyun Config': '☁️ Jianguoyun Config',
					'Upload To Jianguoyun': '↑ Upload To ☁️ Jianguoyun',
					'Download from Jianguoyun': '↓ Download from ☁️ Jianguoyun',
					'Local and Jianguoyun merge': '🔄 Local and ☁️ Jianguoyun merge',
					'DAV URL': '☁️  DAV URL',
					Account: '👤 Account',
					Password: '🔑 Password',
					'Show Password': 'Show Password',
					Save: 'Save',
					'Save Successful!': 'Save Successful!',
					'Update Successful!': 'Update Successful!',
					'Update Bad': 'Update Bad',
					'Upload successful!': 'Upload successful!',
					'Sync successful!': 'Sync successful!',
					'Download successful!': 'Download successful!',
					'Hidden Password': 'Hidden Password',
					'Status ERROR': 'Webdav Status Error',
					'Check Config!': 'Check Config!',
					'No Data': 'Cloud No historical data exists!',
					'Bad Download': 'Bad Download Data',
					'Page to Refresh':
						'The page is about to refresh due to new data updates. Please wait...',
					'Viewed Total': 'Viewed Total',
					click_all_magnet: 'Click All Magnet',
					click_all_torrent: 'Click All Torrent',
				},
			},
			'zh-CN': {
				translation: {
					Language: '🕮 语言(简体)',
					'Hide Viewed': '隐藏已阅',
					Jianguoyun: '☁️ 坚果云',
					'Jianguoyun Config': '☁️ 坚果云配置',
					'Upload To Jianguoyun': '↑ 上传至 ☁️ 坚果云',
					'Download from Jianguoyun': '从 ☁️ 坚果云 ↓ 下载',
					'Local and Jianguoyun merge': '🔄 双端同步 ☁️ 坚果云 ',
					'DAV URL': '☁️  DAV URL',
					Account: '👤 账号',
					Password: '🔑 密码',
					'Show Password': '显示密码',
					Save: '保存',
					'Save Successful!': '保存成功!',
					'Update Successful!': '更新成功!',
					'Update Bad': '更新失败',
					'Upload successful!': '上传成功!',
					'Sync successful!': '同步成功!',
					'Download successful!': '下载完成!',
					'Hidden Password': '隐藏密码',
					'Status ERROR': 'Webdav 状态异常',
					'Check Config!': '检查配置!',
					'No Data': '云端没有历史数据!',
					'Bad Download': '下载数据出错',
					'Page to Refresh': '数据更新,页面即将刷新,请稍候...',
					'Viewed Total': '浏览量',
					click_all_magnet: '点击所有磁力链接',
					click_all_torrent: '点击所有种子链接',
				},
			},
			'zh-TW': {
				translation: {
					Language: '🕮 語言(台)',
					'Hide Viewed': '隱藏已讀',
					Jianguoyun: '☁️ 堅果雲',
					'Jianguoyun Config': '☁️ 堅果雲配置',
					'Upload To Jianguoyun': '⬆️ 上傳至 ☁️ 堅果雲',
					'Download from Jianguoyun': '從 ☁️ 堅果雲 ⬇️ 下載',
					'Local and Jianguoyun merge': '本地與 ☁️ 堅果雲同步',
					'DAV URL': '☁️ DAV 網址',
					Account: ' 帳戶',
					Password: ' 密碼',
					'Show Password': '顯示密碼',
					Save: '儲存',
					'Save Successful!': '儲存成功!',
					'Hidden Password': '隱藏密碼',
					'Update Bad': '更新失敗',
					'Upload successful!': '上傳成功!',
					'Sync successful!': '同步成功!',
					'Download successful!': '下載成功!',
					'Status ERROR': 'Webdav 狀態錯誤',
					'Check Config!': '檢查設定!',
					'No Data': '雲端沒有歷史資料!',
					'Bad Download': '下載數據錯誤',
					'Page to Refresh': '頁面即將重新整理,以更新資料。請稍候...',
					'Viewed Total': '瀏覽量',
					click_all_magnet: '點擊所有磁力連結',
					click_all_torrent: '點擊所有種子連結',
				},
			},
			'zh-HK': {
				translation: {
					Language: '🕮 語言(港)',
					'Hide Viewed': '收埋睇過',
					'Jianguoyun Config': '☁️ 堅果雲',
					'Jianguoyun Config': '☁️ 堅果雲設定',
					'Upload To Jianguoyun': '⬆️ 上載到 ☁️ 堅果雲',
					'Download from Jianguoyun': '由 ☁️ 堅果雲 ⬇️ 下載',
					'Local and Jianguoyun merge': '本地同 ☁️ 堅果雲同步',
					'DAV URL': '☁️ DAV 網址',
					Account: '帳戶',
					Password: '密碼',
					'Show Password': '睇密碼',
					Save: '儲存',
					'Save Successful!': '儲存成功喇!',
					'Hidden Password': '收埋密碼',
					'Update Bad': '更新搞唔掂',
					'Upload successful!': '上傳成功喇!',
					'Sync successful!': '同步成功喇!',
					'Download successful!': '下載掂咗喇!',
					'Status ERROR': 'Webdav 狀態搞唔掂',
					'Check Config!': '睇吓設定啱唔啱!',
					'No Data': '雲端咩資料都冇呀!',
					'Bad Download': '下載嘅資料壞咗',
					'Page to Refresh': '资料更新紧系,页面要更新喇!等阵先!',
					'Viewed Total': '瀏覽量',
					click_all_magnet: '點擊所有磁力連結',
					click_all_torrent: '點擊所有種子連結',
				},
			},
		},
	});

	// i18nnext

	// Style >> Start
	GM_addStyle(`
        .nep_um_main{
            display: flex;
            flex-flow: wrap;
            width: 2501px;
        }

        .nep_um_title {
            width: 100%;
            max-width: 100%;
            margin: 1rem;
            font-size: 1.7rem;
            font-weight: bold;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            flex-basis: 100%;
        }

		.nep_um_release_date {
            width: 100%;
            max-width: 100%;
            margin: 1rem;
            flex-basis: 100%;
        }

        .nep_um_cover {
            height: auto;
            margin: 1rem;
            flex-basis: 100%;
			aspect-ratio: 3 / 2;
        }

        .nep_um_cover > img {
            width: 100%;
            height: auto;
            max-width: 938.667px;
        }

        .nep_um_magent {
            flex-basis: 100%;
            width: 100%;
            margin: 1rem;
        }

       .nep_um_torrent {
            flex-basis: 100%;
            width: 100%;
            margin: 1rem;
            font-size: 1.2rem;
        }

        .nep_um_divider {
            flex-basis: 100%;
            width: 100%;
            margin: 1rem;
            font-size: 1.2rem;
            height: 0.4rem;
            background-color: black;
			filter: grayscale(0.5);
        }
    `);
	// Style >> End

	// Custom Config >> Start
	GM_registerMenuCommand(`${i18next.t('Language')}`, languageConfigDialog);
	GM_registerMenuCommand(hideViewedTitle(), viewedModeSwitch);
	GM_registerMenuCommand(
		`${i18next.t('Jianguoyun Config')}`,
		jianguoyunConfigDialog
	);
	GM_registerMenuCommand(
		`${i18next.t('Upload To Jianguoyun')}`,
		uploadToJianguoyun
	);
	GM_registerMenuCommand(
		`${i18next.t('Download from Jianguoyun')}`,
		downloadFromJianguoyun
	);
	GM_registerMenuCommand(
		`${i18next.t('Local and Jianguoyun merge')}`,
		mergeWithJianguoyun
	);
	GM_registerMenuCommand(
		`${i18next.t('Viewed Total')} ${getCurrentViewedAVIDList().length}`
	);
	GM_registerMenuCommand(`${i18next.t('click_all_magnet')}`, clickAllMagent);
	GM_registerMenuCommand(`${i18next.t('click_all_torrent')}`, clickAllTorrent);
	// Custom Config >> End
	function currentLocale() {
		let locale = GM_getValue(LOCALE_KEY);
		if (typeof locale == 'string') {
			return locale;
		}
		return LOCALE_LIST.enUS;
	}

	function languageConfigDialog() {
		Swal.fire({
			title: '🕮 Language',
			input: 'select',
			inputOptions: {
				'en-US': '🕮 Language',
				'zh-CN': '🕮 语言(简体)',
				'zh-HK': '🕮 語言(港)',
				'zh-TW': '🕮 語言(台)',
			},
			inputValue: currentLocale(),
			showCancelButton: true,
			confirmButtonText: `${i18next.t('Save')}`,
		}).then((result) => {
			if (result.isConfirmed) {
				console.log(result);
				GM_setValue(LOCALE_KEY, result.value);
				i18next.changeLanguage(result.value);
				Swal.fire({
					icon: 'success',
					title: `${i18next.t('Save Successful!')}`,
					text: `${i18next.t('Page to Refresh')}`,
				});
				setTimeout(() => {
					document.location.reload();
				}, 300);
			}
		});
	}
	function hideViewedTitle() {
		let enabled = GM_getValue(HIDE_VIEWED_MODE_KEY) ? '✅' : '❌';
		return `${enabled} ${i18next.t('Hide Viewed')}`;
	}
	function viewedModeSwitch() {
		var enabled = GM_getValue(HIDE_VIEWED_MODE_KEY);
		enabled = !enabled;
		GM_setValue(HIDE_VIEWED_MODE_KEY, enabled);
		location.reload();
	}

	class JianguoyunClient {
		generateConfig(davURL, account, password) {
			if (
				account == null ||
				typeof account != 'string' ||
				account.trim().length < 1
			) {
				return null;
			}
			if (
				password == null ||
				typeof password != 'string' ||
				password.trim().length < 1
			) {
				return null;
			}
			if (
				davURL == null ||
				typeof davURL != 'string' ||
				account.trim().length < 1
			) {
				return null;
			}
			return {
				auth: `Basic ${btoa(`${account}:${password}`)}`,
				davURL: davURL,
			};
		}

		getConfig() {
			let jianguoyunConfig = getJianguoyunConfig();
			if (jianguoyunConfig == null) {
				return null;
			}
			let account = jianguoyunConfig.account;
			let password = jianguoyunConfig.password;
			let davURL = jianguoyunConfig.url;
			return this.generateConfig(davURL, account, password);
		}

		download(fileName) {
			let config = this.getConfig();
			if (config == null) {
				return Promise.reject('Bad Config!');
			}
			let url = `${config.davURL}/${fileName}.json`.replace(/\/+/g, '/');
			return new Promise((res, error) => {
				GM_xmlhttpRequest({
					method: 'GET',
					timeout: 3000,
					headers: { Authorization: config.auth },
					url: url,
					onload: res,
					onerror: error,
					ontimeout: error,
				});
			});
		}

		upload(fileName, data) {
			let config = this.getConfig();
			if (config == null) {
				return Promise.reject('Bad Config!');
			}
			let url = `${config.davURL}/${fileName}.json`.replace(/\/+/g, '/');
			return new Promise((res, error) => {
				GM_xmlhttpRequest({
					method: 'PUT',
					timeout: 3000,
					data: data,
					headers: { Authorization: config.auth },
					url: url,
					dataType: 'json',
					onload: res,
					onerror: error,
					ontimeout: error,
				});
			});
		}
	}
	function saveJianguoyunConfig(url, account, password) {
		GM_setValue(
			JIANGUOYUN_KEY_MD5,
			JSON.stringify({ url: url, account: account, password: password })
		);
	}
	function getJianguoyunConfig() {
		let jsonStr = GM_getValue(JIANGUOYUN_KEY_MD5);
		if (jsonStr == null) {
			return null;
		}
		try {
			return JSON.parse(jsonStr);
		} catch (_) {
			return null;
		}
	}
	function jianguoyunConfigDialog() {
		let oldData = getJianguoyunConfig();
		let formHTML = `
           <label for="${JIANGUOYUN_DAV_URL_EL_ID}">${i18next.t(
			'DAV URL'
		)}</label>
           <input type="text" id="${JIANGUOYUN_DAV_URL_EL_ID}" name="${JIANGUOYUN_DAV_URL_EL_ID}" class="swal2-input"/>
           <br />
           <label for="${JIANGUOYUN_ACCOUNT_EL_ID}">${i18next.t(
			'Account'
		)}</label>
           <input type="text" id="${JIANGUOYUN_ACCOUNT_EL_ID}" name="${JIANGUOYUN_ACCOUNT_EL_ID}" class="swal2-input"/>
           <br />
           <label for="${JIANGUOYUN_PASSWORD_EL_ID}">${i18next.t(
			'Password'
		)}</label>
           <input type="password" id="${JIANGUOYUN_PASSWORD_EL_ID}" name="${JIANGUOYUN_PASSWORD_EL_ID}" class="swal2-input"/>
           <button id="${JIANGUOYUN_PASSWORD_EL_ID}_button" class="swal2-cancel">${i18next.t(
			'Show Password'
		)}</button>
           <br />
         `;
		Swal.fire({
			title: `${i18next.t('Jianguoyun Config')}`,
			html: formHTML,
			showCancelButton: true,
			confirmButtonText: `${i18next.t('Save')}`,
			preConfirm: () => {
				let url = document.getElementById(JIANGUOYUN_DAV_URL_EL_ID).value;
				let account = document.getElementById(JIANGUOYUN_ACCOUNT_EL_ID).value;
				let password = document.getElementById(JIANGUOYUN_PASSWORD_EL_ID).value;
				saveJianguoyunConfig(url, account, password);
			},
		}).then((result) => {
			if (result.isConfirmed) {
				Swal.fire({
					icon: 'success',
					title: `${i18next.t('Save Successful!')}`,
				});
			}
		});
		document.getElementById(JIANGUOYUN_DAV_URL_EL_ID).value = oldData.url;
		document.getElementById(JIANGUOYUN_ACCOUNT_EL_ID).value = oldData.account;
		document.getElementById(JIANGUOYUN_PASSWORD_EL_ID).value = oldData.password;
		const passwordInput = document.getElementById(JIANGUOYUN_PASSWORD_EL_ID);
		const togglePasswordButton = document.getElementById(
			`${JIANGUOYUN_PASSWORD_EL_ID}_button`
		);
		togglePasswordButton.addEventListener('click', () => {
			if (passwordInput.type === 'password') {
				passwordInput.type = 'text';
				togglePasswordButton.innerText = `${i18next.t('Hidden Password')}`;
			} else {
				passwordInput.type = 'password';
				togglePasswordButton.innerText = `${i18next.t('Show Password')}`;
			}
		});
	}
	function uploadToJianguoyun() {
		let avIds = getCurrentViewedAVIDList();
		let usTitles = getCurrentViewedUSTitleList();
		let jianguoyunClient = new JianguoyunClient();
		jianguoyunClient
			.upload(US_CLOUD_FILE_NAME, JSON.stringify(usTitles))
			.then(() => {})
			.catch(() => {});
		jianguoyunClient
			.upload(AVIDS_CLOUD_FILE_NAME, JSON.stringify(avIds))
			.then((res) => {
				if (res.status >= 200 && res.status < 300) {
					Swal.fire({
						icon: 'success',
						title: `${i18next.t('Upload successful!')}`,
					});
				} else {
					Swal.fire({
						icon: 'error',
						title: `${i18next.t('Jianguoyun')}`,
						text: `${i18next.t('Status Error')} >> ${res.status} >> ${i18next.t(
							'Check Config!'
						)}`,
					});
				}
			})
			.catch((error) => {
				Swal.fire({
					icon: 'error',
					title: `${i18next.t('Update Bad')}`,
					text: JSON.stringify(error),
				});
			});
	}
	function downloadFromJianguoyun() {
		let jianguoyunClient = new JianguoyunClient();
		jianguoyunClient
			.download(US_CLOUD_FILE_NAME)
			.then((res) => {
				if (res === 200) {
					if (res.responseText != null && res.responseText.length > 2) {
						let cloudUSTitles = JSON.parse(res.responseText);
						addListToViewedUSTitle(cloudUSTitles);
					}
				}
			})
			.catch(() => {});
		jianguoyunClient
			.download(AVIDS_CLOUD_FILE_NAME)
			.then((res) => {
				if (res.status === 200) {
					if (res.responseText != null && res.responseText.length > 2) {
						let cloudAvIds = JSON.parse(res.responseText);
						addListToViewedAVID(cloudAvIds);
					}
					Swal.fire({
						icon: 'success',
						title: `${i18next.t('Download successful!')}`,
					});
				} else if (res.status == 404) {
					Swal.fire({
						icon: 'error',
						title: `${i18next.t('Jianguoyun')} >> ${i18next.t('No Data')}`,
					});
				} else {
					Swal.fire({
						icon: 'error',
						title: `${i18next.t('Jianguoyun')}`,
						text: `${i18next.t('Status Error')} >> ${res.status} >> ${i18next.t(
							'Check Config!'
						)}`,
					});
				}
			})
			.catch((error) => {
				Swal.fire({
					icon: 'error',
					title: `${i18next.t('Upload Bad')}`,
					text: JSON.stringify(error),
				});
			});
	}
	async function mergeWithJianguoyunUSTitle() {
		let jianguoyunClient = new JianguoyunClient();
		let cloudUSTitles = [];
		let usBreakFnc = false;
		await jianguoyunClient
			.download(US_CLOUD_FILE_NAME)
			.then((res) => {
				if (res.status >= 200 && res.status < 300) {
					if (res.responseText != null && res.responseText.length > 2) {
						cloudUSTitles = JSON.parse(res.responseText);
					}
				} else if (res.status == 404) {
				} else {
					usBreakFnc = true;
				}
			})
			.catch(() => {
				usBreakFnc = false;
			});
		if (usBreakFnc) {
			return;
		}
		let localUSTitles = getCurrentViewedUSTitleList();
		let mergeUSTitles = _.union(cloudUSTitles, localUSTitles);
		resetViewedUSTitle(mergeUSTitles);
		jianguoyunClient
			.upload(US_CLOUD_FILE_NAME, JSON.stringify(mergeUSTitles))
			.then(() => {})
			.catch(() => {});
	}
	async function mergeWithJianguoyun() {
		mergeWithJianguoyunUSTitle();
		let jianguoyunClient = new JianguoyunClient();
		let cloudAvIds = [];
		let breakFnc = false;
		await jianguoyunClient
			.download(AVIDS_CLOUD_FILE_NAME)
			.then((res) => {
				if (res.status >= 200 && res.status < 300) {
					if (res.responseText != null && res.responseText.length > 2) {
						cloudAvIds = JSON.parse(res.responseText);
					}
				} else if (res.status == 404) {
				} else {
					Swal.fire({
						icon: 'error',
						title: `${i18next.t('Jianguoyun')} >> ${i18next.t(
							'Status Error'
						)} >> ${res.status} >> ${i18next.t('Check Config!')}`,
					});
					breakFnc = true;
				}
			})
			.catch(() => {
				breakFnc = false;
			});
		if (breakFnc) {
			Swal.fire({
				icon: 'error',
				title: `${i18next.t('Jianguoyun')} >> ${i18next.t('Bad Download')}`,
			});
			return;
		}
		let localAvIds = getCurrentViewedAVIDList();
		let mergeAvIds = _.union(cloudAvIds, localAvIds);
		resetViewedAVID(mergeAvIds);
		jianguoyunClient
			.upload(AVIDS_CLOUD_FILE_NAME, JSON.stringify(mergeAvIds))
			.then((res) => {
				if (res.status >= 200 && res.status < 300) {
					Swal.fire({
						icon: 'success',
						title: `${i18next.t('Sync successful!')}`,
					});
				} else {
					Swal.fire({
						icon: 'error',
						title: `${i18next.t('Jianguoyun')} >> ${i18next.t(
							'Status Error'
						)} >> ${res.status} >> ${i18next.t('Check Config!')}`,
					});
				}
			})
			.catch((error) => {
				Swal.fire({
					icon: 'error',
					title: `${i18next.t('Upload Bad')}`,
					text: JSON.stringify(error),
				});
			});
	}

	function getCurrentViewedAVIDList() {
		let localList = GM_getValue(VIEWED_AVIDS_LOCAL_STORAGE_KEY) || '[]';
		return JSON.parse(localList);
	}

	function getCurrentViewedUSTitleList() {
		let localList = GM_getValue(VIEWED_US_TITLES_LOCAL_STORAGE_KEY) || '[]';
		return JSON.parse(localList);
	}

	function exitsViewedAVID(avId) {
		return getCurrentViewedAVIDList().includes(avId);
	}

	function exitsViewedUSTitle(title) {
		return getCurrentViewedUSTitleList().includes(title);
	}

	function addToViewedAVID(avId) {
		let oldIdList = getCurrentViewedAVIDList();
		if (oldIdList.includes(avId)) {
			return;
		}
		oldIdList.push(avId);
		let newValue = JSON.stringify(oldIdList);
		GM_setValue(VIEWED_AVIDS_LOCAL_STORAGE_KEY, newValue);
	}

	function addToViewedUSTitle(title) {
		let oldIdList = getCurrentViewedUSTitleList();
		if (oldIdList.includes(title)) {
			return;
		}
		oldIdList.push(title);
		let newValue = JSON.stringify(oldIdList);
		GM_setValue(VIEWED_US_TITLES_LOCAL_STORAGE_KEY, newValue);
	}

	function addListToViewedAVID(avIds) {
		let oldList = getCurrentViewedAVIDList();
		let newList = _.union(oldList, avIds);
		let newValue = JSON.stringify(newList);
		GM_setValue(VIEWED_AVIDS_LOCAL_STORAGE_KEY, newValue);
	}

	function addListToViewedUSTitle(titles) {
		let oldList = getCurrentViewedUSTitleList();
		let newList = _.union(oldList, titles);
		let newValue = JSON.stringify(newList);
		GM_setValue(VIEWED_US_TITLES_LOCAL_STORAGE_KEY, newValue);
	}

	function resetViewedAVID(avIds) {
		if (avIds == null || avIds.length < 1) {
			return;
		}
		let newValue = JSON.stringify(avIds);
		GM_setValue(VIEWED_AVIDS_LOCAL_STORAGE_KEY, newValue);
	}

	function resetViewedUSTitle(titles) {
		if (titles == null || titles.length < 1) {
			return;
		}
		let newValue = JSON.stringify(titles);
		GM_setValue(VIEWED_US_TITLES_LOCAL_STORAGE_KEY, newValue);
	}

	function elOpenUrl(elBody) {
		let elUrl = null;
		if (elBody) {
			let subUrl = null;
			let subUrlEl = elBody.querySelector('td > td.icon > a');
			if (!subUrlEl) {
				subUrlEl = elBody.querySelector('tr > th.common > a.s.xst');
			}
			if (!subUrlEl) {
				subUrlEl = elBody.querySelector('tr > th.new > a.s.xst');
			}
			if (subUrlEl) {
				subUrl = subUrlEl.href;
			}
			if (subUrl) {
				elUrl = subUrl;
			}
		}
		return elUrl;
	}
	function elAllArray() {
		return Array.from(
			document.querySelectorAll('[id^="normalthread_"]')
		).filter(function (element) {
			if (/^normalthread_\d+$/.test(element.id)) {
				return element;
			}
		});
	}
	function elCutLastArray() {
		let allArray = elAllArray();
		let lastArray = null;
		if (allArray && allArray.length > 0) {
			let nowArrayLength = allArray.length;
			if (elArrayLength <= 0) {
				lastArray = allArray;
			} else {
				lastArray = allArray.slice(elArrayLength);
			}
			elArrayLength = nowArrayLength;
		}
		return lastArray;
	}
	function elSubPageImageEl(subPageHTML) {
		if (subPageHTML) {
			let _el = subPageHTML.querySelector('ignore_js_op > img');
			if (_el) {
				return `<img src="${_el.getAttribute(
					'zoomFile'
				)}" style="width:100%; max-with:300px; height: auto;"/>`;
			}
		}
		return null;
	}

	function elSubPageMagentEl(subPageHTML) {
		if (subPageHTML) {
			let magentEl = subPageHTML.querySelector('.blockcode > div > ol > li');
			if (magentEl) {
				return `<a href="${magentEl.innerText}" style="text-decoration:underline;">${magentEl.innerText}</a>`;
			}
		}
		return null;
	}

	function elSubPageTorrentEl(subPageHTML) {
		if (subPageHTML) {
			return subPageHTML.querySelector(
				'div.pattl > ignore_js_op > dl > dd > p.attnm '
			);
		}
		return null;
	}

	function elPostReleaseDate(elBody) {
		let releaseDate = 'Unknown';
		if (elBody) {
			let _el = elBody.querySelector('tr > td:nth-child(3) > em > span > span');
			if (_el) {
				releaseDate = _el.innerText;
			}
			if (_el == null || _el.innerText == '') {
				_el = elBody.querySelector('tr > td:nth-child(3) > em > span');
				releaseDate = _el.innerText;
			}
		}
		return releaseDate;
	}

	function generateJAVDBURLEl(avId, title) {
		return `<a href='https://${JAVDB_COM}/search?q=${avId}&f=all' target='_blank' referrerpolicy='same-origin'>${avId} ${title}</a>`;
	}
	function elTitleDiv(elBody) {
		let title = 'Unknown';
		if (elBody) {
			let titleEl = elBody.querySelector('tr > th.common > a.s.xst');
			if (!titleEl) {
				titleEl = elBody.querySelector('tr > th.new > a.s.xst');
			}
			if (titleEl) {
				title = titleEl.innerText.replace(/<savdiv[^>]*>.*?<\/savdiv>/g, '');
			}
		}
		let avIdArray = title.match(AVID_REGEX);
		let avId = null;
		if (avIdArray && avIdArray.length > 0) {
			avId = avIdArray[0];
			let _title = title.replace(AVID_REGEX, '');
			title = generateJAVDBURLEl(avId, _title);
		}
		let titleDiv = document.createElement('div');
		titleDiv.classList.add('nep_um_title');
		titleDiv.innerHTML = title;
		let isUS = false;
		let isUSViewed = false;
		if (avId) {
			if (exitsViewedAVID(avId)) {
				titleDiv.querySelector('a').style.color = VIEWED_COLOR;
				if (GM_getValue(HIDE_VIEWED_MODE_KEY)) {
					return avId;
				}
			} else {
				titleDiv.addEventListener('click', function () {
					addToViewedAVID(avId);
					titleDiv.querySelector('a').style.color = VIEWED_COLOR;
				});
			}
		} else {
			isUS = true;
			titleDiv.innerHTML = `<a>${title}</a> `;
			if (exitsViewedUSTitle(title)) {
				isUSViewed = true;
				titleDiv.querySelector('a').style.color = VIEWED_COLOR;
				if (GM_getValue(HIDE_VIEWED_MODE_KEY)) {
					titleDiv.innerHTML = `<a>${title} >> ${i18next.t(
						'Hide Viewed'
					)}</a> `;
				}
			}
		}

		return {
			div: titleDiv,
			id: avId,
			isUS: isUS,
			isUSViewed: isUSViewed,
			title: title,
		};
	}

	function elTranTitleDivStyle(div, avId) {
		if (avId) {
			addToViewedAVID(avId);
			div.querySelector('a').style.color = VIEWED_COLOR;
		}
	}
	function elTranTitleDivStyleForUSTitle(div, title) {
		if (title) {
			addToViewedUSTitle(title);
			div.querySelector('a').style.color = VIEWED_COLOR;
		}
	}

	/* toRequestSubURL */
	function elConvertElBody(elBody) {
		let openPageUrl = elOpenUrl(elBody);

		if (!openPageUrl) {
			return null;
		}

		// main
		let mainDiv = document.createElement('div');
		mainDiv.classList.add('nep_um_main');
		mainDiv.id = 'nep_um_main';

		// title
		let titleDivAndId = elTitleDiv(elBody);
		if (typeof titleDivAndId === 'string') {
			let hiddenDiv = createHiddenDiv(
				titleDivAndId,
				`>> ${i18next.t('Hide Viewed')}`
			);
			mainDiv.append(hiddenDiv);
			elBody.innerHTML = '';
			elBody.appendChild(mainDiv);
			return;
		}

		let isUS = titleDivAndId.isUS;
		let titleDiv = titleDivAndId.div;
		let avId = titleDivAndId.id;
		let title = titleDivAndId.title;
		let isUSViewed = titleDivAndId.isUSViewed;

		if (isUS && isUSViewed) {
			let hiddenDiv = createHiddenDiv(
				openPageUrl,
				title,
				`>> ${i18next.t('Hide Viewed')}`
			);
			mainDiv.append(hiddenDiv);
			elBody.innerHTML = '';
			elBody.appendChild(mainDiv);
			return;
		}

		if (isUS) {
			titleDiv.onclick = function () {
				elTranTitleDivStyleForUSTitle(titleDiv, title);
				window.open(openPageUrl, '_blank');
			};
		}

		mainDiv.appendChild(titleDiv);

		// releaseDate
		let releaseDate = elPostReleaseDate(elBody);
		let releaseDateDiv = document.createElement('div');
		releaseDateDiv.classList.add('nep_um_release_date');
		releaseDateDiv.innerText = releaseDate;
		mainDiv.appendChild(releaseDateDiv);

		GM_xmlhttpRequest({
			method: 'GET',
			url: openPageUrl,
			headers: {
				'User-agent': USER_AGENT,
				Accept: ACCEPT,
				cookie: COOKIE,
				referer: REFERER,
			},
			onerror: function (error) {
				console.error('Error fetching data:', error);
				elBody.innerHTML = '';
				elBody.appendChild(mainDiv);
			},
			onload: function (res) {
				let parser = new DOMParser();
				let subPageHTML = parser.parseFromString(res.responseText, 'text/html');
				let imgEl = elSubPageImageEl(subPageHTML);
				let magentEl = elSubPageMagentEl(subPageHTML);
				let torrentEl = elSubPageTorrentEl(subPageHTML);
				if (imgEl && (magentEl || torrentEl)) {
					// cover
					let imgDiv = document.createElement('div');
					imgDiv.onclick = function () {
						window.open(openPageUrl, '_blank');
						if (isUS) {
							elTranTitleDivStyleForUSTitle(titleDiv, title);
						} else {
							elTranTitleDivStyle(titleDiv, avId);
						}
					};
					imgDiv.classList.add('nep_um_cover');
					imgDiv.innerHTML = imgEl;
					mainDiv.appendChild(imgDiv);

					// magent
					let magentDiv = document.createElement('div');
					magentDiv.onclick = function () {
						if (isUS) {
							elTranTitleDivStyleForUSTitle(titleDiv, title);
						} else {
							elTranTitleDivStyle(titleDiv, avId);
						}
					};
					magentDiv.classList.add('nep_um_magent');
					if (magentEl != null) {
						magentDiv.innerHTML = magentEl;
						mainDiv.appendChild(magentDiv);
					}

					// torrent
					let torrentDiv = document.createElement('div');
					torrentDiv.onclick = function () {
						if (isUS) {
							elTranTitleDivStyleForUSTitle(titleDiv, title);
						} else {
							elTranTitleDivStyle(titleDiv, avId);
						}
					};
					torrentDiv.classList.add('nep_um_torrent');
					if (torrentEl?.outerHTML != null) {
						torrentDiv.innerHTML = torrentEl.outerHTML;
						mainDiv.appendChild(torrentDiv);
					}

					// divider
					let dividerDiv = document.createElement('div');
					dividerDiv.classList.add('nep_um_divider');
					mainDiv.appendChild(dividerDiv);

					elBody.innerHTML = '';
					elBody.appendChild(mainDiv);
				}
			},
		});
	}

	function createHiddenDiv(url, innerText, additionalText = '') {
		let hiddenDiv = document.createElement('div');
		hiddenDiv.innerHTML = `<a href='${url}'>${innerText} ${additionalText}</a>`;
		hiddenDiv.style.color = VIEWED_COLOR;
		hiddenDiv.style.fontSize = '0.5rem';
		hiddenDiv.style.textAlign = 'center';
		hiddenDiv.style.width = '100%';
		hiddenDiv.style.paddingBottom = '0.5rem';
		return hiddenDiv;
	}

	function clickAllMagent() {
		let allMagentDiv = document.querySelectorAll('.nep_um_magent');
		let allMagentText = '';
		for (let i = 0; i < allMagentDiv.length; i++) {
			allMagentText += `\r\n${allMagentDiv[i].innerText}`;
			allMagentDiv[i].click();
		}
		GM_setClipboard(allMagentText);
	}

	function clickAllTorrent() {
		let allTorrentDiv = document.querySelectorAll('.nep_um_torrent');
		let allTorrentText = '';
		for (let i = 0; i < allTorrentDiv.length; i++) {
			allTorrentText += `\r\n${allTorrentDiv[i].innerText}`;
			allTorrentDiv[i].click();
		}
		GM_setClipboard(allTorrentText);
	}

	function run() {
		let modifyElArray = elCutLastArray();
		if (modifyElArray && modifyElArray.length > 0) {
			modifyElArray.forEach((_el) => {
				try {
					elConvertElBody(_el);
				} catch (error) {
					console.error('Error in elConvertElBody:', error);
				}
			});
		}
	}

	const runDebounce = _.debounce(run, 3000, { maxWait: 8000 });

	const observer_list = new MutationObserver((mutations) => {
		mutations.forEach((mutation) => {
			if (mutation.type === 'childList') {
				runDebounce();
			}
		});
	});

	const observerConfig_list = { childList: true, subtree: true };
	observer_list.observe(document.body, observerConfig_list);

	const wpDiv = document.querySelector('#wp');

	const observer_width = new ResizeObserver((entries) => {
		entries.forEach((entry) => {
			if (entry.target === wpDiv) {
				const newWidth = wpDiv.clientWidth;
				const childDivs = wpDiv.querySelectorAll('#nep_um_main');
				childDivs.forEach((childDiv) => {
					childDiv.style.width = `${newWidth}px`;
				});
			}
		});
	});
	observer_width.observe(wpDiv);

	// init
	run();
	document.querySelector('#threadlisttableid').style.width = '100%';
})();