2048-预览

为2048核基地论坛帖子添加图片、链接预览

// ==UserScript==
// @name         2048-预览
// @version      1.2.5
// @namespace    https://sleazyfork.org/zh-CN/users/1461640-%E6%98%9F%E5%AE%BF%E8%80%81%E9%AD%94
// @author       星宿老魔
// @description  为2048核基地论坛帖子添加图片、链接预览
// @match        https://hjd2048.com/2048/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=hjd2048.com
// @license      MIT
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-start
// ==/UserScript==

(function(){"use strict";class Storage{static get(e,t=null){try{const n=GM_getValue(e);if(null==n)return t;try{return JSON.parse(n)}catch{return n}
}catch(n){return void 0,t}}static set(e,t){try{const n=JSON.stringify(t);return GM_setValue(e,n),!0}catch(n){return void 0,!1}}static delete(e){try{
return GM_deleteValue(e),!0}catch(t){return void 0,!1}}static listKeys(){try{return GM_listValues()}catch(e){return void 0,[]}}
static migrateFromLocalStorage(e,t=!0){try{const n=localStorage.getItem(e);if(null!==n){try{const t=JSON.parse(n);this.set(e,t)}catch{GM_setValue(e,n)
}return t&&localStorage.removeItem(e),!0}return!1}catch(n){return void 0,!1}}}const CONFIG={PREVIEW_IMAGE_HEIGHT:300,PREVIEW_COUNT:4,
getPreviewCount(){return this.PREVIEW_COUNT},getExcludedForums(){try{return Storage.get("EXCLUDED_FORUMS",[])??[]}catch(e){return[]}},
setExcludedForums(e){try{Storage.set("EXCLUDED_FORUMS",e)}catch(t){void 0}},selectors:{threadRows:"tr.tr3.t_one",
threadLinks:'a[target="_self"], a[target="_blank"]',contentSelectors:["#read_tpc",".tpc_content",".f14.cc",'div[id="read_tpc"]',".t_f"],
searchLink:'#nav-pc a[href="/search.php"]',navSearch:"#nav-s",searchResultTable:".t table",searchResultRows:'tr[id^="search_"]',
searchResultHeader:".t table .h",previewRows:"tr.imagePreviewTr",
imgSelectors:["#read_tpc img",".tpc_content img",".f14.cc img",'div[id="read_tpc"] img'],magnetTextarea:"textarea[readonly], textarea#copytext",
magnetLink:'a[href^="magnet:?xt=urn:btih:"]',ed2kLink:'a[href^="ed2k://"]',
btLink:'a[href*="bt.ivcbt.com/list.php?name="], a[href*="bt.bxmho.cn/list.php?name="]'},regex:{threadUrl:/read\.php\?tid=/,searchUrl:/search\.php/,
searchRowId:/^search_(\d+)_(\d+)$/,magnetHash:/([A-F0-9]{40})/i,thunder:/thunder:\/\/[A-Za-z0-9+\/=]+/i,
ed2k:/ed2k:\/\/\|file\|[^|]+\|\d+\|[A-F0-9]{32}\|\//i,magnetLink:/magnet:\?xt=urn:btih:[a-zA-Z0-9]+/,copyText:/magnet:\?xt=urn:btih:/},btSites:[{
name:"bxmho",pattern:/(?:\/\/bt\.bxmho\.cn\/list\.php\?name=|userscript\.html\?name=)([0-9a-z]+)/i,url:"https://bt.bxmho.cn/list.php",method:"GET",
getHash:e=>{const t=e.match(/([0-9a-z]+)$/i);return t?t[1]:""}},{name:"82bt",pattern:/\/\/www\.82bt\.com\/(?:cao\.php|dlink\.php)\?hash=([0-9a-z]+)/i,
url:"https://www.82bt.com/downt-m.php",method:"POST",paramName:"code",referer:"https://www.82bt.com",getHash:e=>{const t=e.match(/hash=([0-9a-z]+)/i)
;return t?t[1]:""}}]};function e(e,t,n){const a=document.createElement(e);return a.className=t,a}const t={copyToClipboard(e,t){
navigator.clipboard.writeText(e).then(()=>{this.showClickTip("已复制",t)}).catch(()=>{this.fallbackCopyTextToClipboard(e,t)})},
fallbackCopyTextToClipboard(e,t){const n=document.createElement("textarea");n.value=e,n.style.position="fixed",n.style.top="-1000px",
n.style.left="-1000px",document.body.appendChild(n),n.focus(),n.select();try{document.execCommand("copy"),this.showClickTip("已复制",t)}catch(a){void 0,
this.showClickTip("复制失败",t)}document.body.removeChild(n)},showClickTip(e,t){const n=t;let a=document.querySelector(".click-tip");a&&a.remove(),
a=document.createElement("div"),a.className="click-tip",a.textContent=e,document.body.appendChild(a),a.style.left=`${n.clientX}px`,
a.style.top=`${n.clientY}px`,setTimeout(()=>{a.style.opacity="1"},10),setTimeout(()=>{a.style.opacity="0",setTimeout(()=>{a.parentElement&&a.remove()
},200)},1e3)},removeRules(){try{const e=document.querySelector(".collapse-header");if(e){
const t=e.closest("div, section, .rule-container, .collapse-container");t&&t.remove()}}catch(e){void 0}},isContentPage(){
return CONFIG.regex.threadUrl.test(window.location.href)},safeQuerySelector(e,t=document){try{return t.querySelector(e)}catch(n){return null}},
safeQuerySelectorAll(e,t=document){try{return Array.from(t.querySelectorAll(e))}catch(n){return[]}}},n=class{static getForumById(e){
return this.FORUM_SECTIONS.find(t=>t.id===e)}static getChildForums(e){return this.FORUM_SECTIONS.filter(t=>t.parent===e)}static getMainCategories(){
return this.FORUM_SECTIONS.filter(e=>2===e.level&&"1"===e.parent)}static getDisplayName(e){return`${" ".repeat(Math.max(0,e.level-2))}${e.name}`}
static getForumTree(){const e=[];return this.getMainCategories().forEach(t=>{e.push(t),this.getChildForums(t.id).forEach(t=>{e.push(t),
this.getChildForums(t.id).forEach(t=>{e.push(t);const n=this.getChildForums(t.id);e.push(...n)})})}),e}};n.FORUM_SECTIONS=[{id:"all",name:"全部版块分类",
level:0},{id:"1",name:"总板块",level:1},{id:"2",name:"新片速递",level:2,parent:"1"},{id:"3",name:"最新合集",level:3,parent:"2"},{id:"4",name:"亞洲無碼",level:3,
parent:"2"},{id:"5",name:"日本騎兵",level:3,parent:"2"},{id:"13",name:"歐美新片",level:3,parent:"2"},{id:"15",name:"國內原創",level:3,parent:"2"},{id:"16",
name:"中字原創",level:3,parent:"2"},{id:"18",name:"三級寫真",level:3,parent:"2"},{id:"343",name:"实时BT",level:3,parent:"2"},{id:"326",name:"本站高清影院",level:3,
parent:"2"},{id:"7",name:"图片专区",level:2,parent:"1"},{id:"23",name:"網友自拍",level:3,parent:"7"},{id:"24",name:"亞洲激情",level:3,parent:"7"},{id:"25",
name:"歐美激情",level:3,parent:"7"},{id:"26",name:"熟女专图",level:3,parent:"7"},{id:"27",name:"高跟絲襪",level:3,parent:"7"},{id:"28",name:"卡通漫畫",level:3,
parent:"7"},{id:"345",name:"图你所图",level:3,parent:"7"},{id:"135",name:"原創达人",level:3,parent:"7"},{id:"273",name:"美图秀秀",level:2,parent:"1"},{id:"21",
name:"唯美清純",level:3,parent:"273"},{id:"275",name:"亞洲正妹",level:3,parent:"273"},{id:"276",name:"素人正妹",level:3,parent:"273"},{id:"277",name:"角色扮演",
level:3,parent:"273"},{id:"278",name:"A I 智能",level:3,parent:"273"},{id:"320",name:"优质图片",level:3,parent:"273"},{id:"333",name:"明星合成",level:3,
parent:"273"},{id:"29",name:"动态图片",level:3,parent:"273"},{id:"92",name:"精品收录",level:2,parent:"1"},{id:"295",name:"原创首发",level:3,parent:"92"},{id:"94",
name:"稀有首發",level:3,parent:"92"},{id:"329",name:"藏精阁 — 2017-2024",level:4,parent:"94"},{id:"283",name:"网络见闻",level:3,parent:"92"},{id:"111",
name:"主播實錄",level:3,parent:"92"},{id:"99",name:"國產主播",level:4,parent:"111"},{id:"324",name:"自购主播区",level:4,parent:"111"},{id:"323",name:"国产主播2区",
level:4,parent:"111"},{id:"322",name:"国产主播3区",level:4,parent:"111"},{id:"131",name:"名站同步",level:3,parent:"92"},{id:"314",name:"真实街拍",level:3,
parent:"92"},{id:"341",name:"原档115",level:3,parent:"92"},{id:"213",name:"国产主播同步",level:4,parent:"341"},{id:"342",name:"VR視頻2023-2025",level:4,
parent:"341"},{id:"290",name:"日本4K超清",level:4,parent:"341"},{id:"303",name:"高清有碼",level:4,parent:"341"},{id:"302",name:"AI視界",level:4,parent:"341"},{
id:"304",name:"外掛字幕",level:4,parent:"341"},{id:"306",name:"FC2視頻",level:4,parent:"341"},{id:"307",name:"S-cute / Mywife",level:4,parent:"341"},{
id:"305",name:"亞洲SM",level:4,parent:"341"},{id:"321",name:"补档申请",level:3,parent:"92"},{id:"75",name:"免空網盤",level:2,parent:"1"},{id:"72",name:"网盘二区",
level:3,parent:"75"},{id:"272",name:"网盘三区",level:3,parent:"75"},{id:"195",name:"优质 B T",level:3,parent:"75"},{id:"280",name:"国产精选",level:3,parent:"75"
},{id:"76",name:"多挂原创",level:3,parent:"75"},{id:"55",name:"有声小说",level:3,parent:"75"},{id:"180",name:"实用漫画",level:3,parent:"75"},{id:"113",
name:"原档收藏",level:3,parent:"75"},{id:"116",name:"有碼.HD",level:4,parent:"113"},{id:"114",name:"亞洲SM.HD",level:4,parent:"113"},{id:"96",name:"日韓VR/3D",
level:4,parent:"113"},{id:"119",name:"S-cute / Mywife / G-area",level:4,parent:"113"},{id:"41",name:"綜合資源",level:2,parent:"1"},{id:"43",
name:"E D 2 K",level:3,parent:"41"},{id:"315",name:"原档字幕",level:3,parent:"41"},{id:"318",name:"磁链迅雷",level:3,parent:"41"},{id:"316",name:"包罗万象",
level:3,parent:"41"},{id:"271",name:"聚合1区",level:4,parent:"316"},{id:"281",name:"聚合2区",level:4,parent:"316"},{id:"284",name:"聚合3区",level:4,
parent:"316"},{id:"313",name:"远古资源",level:4,parent:"316"},{id:"319",name:"聚合5区",level:4,parent:"316"},{id:"325",name:"聚合6区 WK",level:4,parent:"316"},{
id:"327",name:"聚合7区",level:4,parent:"316"},{id:"332",name:"司机社",level:4,parent:"316"},{id:"335",name:"套图学院",level:4,parent:"316"},{id:"334",
name:"游戏下载",level:4,parent:"316"},{id:"340",name:"韩国主播",level:4,parent:"316"},{id:"344",name:"美足踩踏",level:4,parent:"316"},{id:"346",name:"套图百晓生",
level:4,parent:"316"},{id:"348",name:"街拍精品",level:4,parent:"316"},{id:"67",name:"正片大片",level:3,parent:"41"},{id:"66",name:"H-GAME",level:3,parent:"41"
},{id:"291",name:"快播影院",level:3,parent:"41"},{id:"293",name:"快播1号",level:4,parent:"291"},{id:"294",name:"快播2号",level:4,parent:"291"},{id:"296",
name:"快播3号",level:4,parent:"291"},{id:"299",name:"快播4号",level:4,parent:"291"},{id:"300",name:"快播5号",level:4,parent:"291"},{id:"301",name:"快播6号",
level:4,parent:"291"},{id:"308",name:"快播7号",level:4,parent:"291"},{id:"309",name:"快播频道",level:4,parent:"291"},{id:"311",name:"快播10号",level:4,
parent:"291"},{id:"312",name:"快播11号",level:4,parent:"291"},{id:"331",name:"本站破解资源",level:3,parent:"41"},{id:"102",name:"文学欣赏",level:2,parent:"1"},{
id:"328",name:"在线速听",level:3,parent:"102"},{id:"48",name:"综合小说",level:3,parent:"102"},{id:"49",name:"激情都市",level:4,parent:"48"},{id:"51",name:"青春校园",
level:4,parent:"48"},{id:"52",name:"武侠虚幻",level:4,parent:"48"},{id:"105",name:"另类其他",level:4,parent:"48"},{id:"103",name:"人妻意淫",level:3,parent:"102"
},{id:"50",name:"乱伦迷情",level:3,parent:"102"},{id:"54",name:"长篇连载",level:3,parent:"102"},{id:"100",name:"文学作者",level:3,parent:"102"},{id:"109",
name:"TXT小说打包",level:3,parent:"102"},{id:"297",name:"2008-2024大集合",level:4,parent:"109"},{id:"110",name:"TXT小说綜合一区",level:4,parent:"109"},{id:"189",
name:"TXT小说綜合二区",level:4,parent:"109"},{id:"193",name:"同人小说",level:4,parent:"109"},{id:"336",name:"耽美小说",level:4,parent:"109"},{id:"192",name:"言情小说",
level:4,parent:"109"},{id:"338",name:"常规小说",level:4,parent:"109"},{id:"190",name:"都市校园",level:4,parent:"109"},{id:"191",name:"武侠小说",level:4,
parent:"109"},{id:"93",name:"TXT小说網盤區",level:4,parent:"109"},{id:"56",name:"网友互动",level:2,parent:"1"},{id:"57",name:"聚友客栈",level:3,parent:"56"},{
id:"61",name:"求片专版",level:3,parent:"56"},{id:"206",name:"重金求片区(米粒悬赏)限侠客以上",level:4,parent:"61"},{id:"218",name:"成人信息",level:3,parent:"56"},{id:"220",
name:"北京性息",level:4,parent:"218"},{id:"237",name:"上海性息",level:4,parent:"218"},{id:"238",name:"广州性息",level:4,parent:"218"},{id:"239",name:"深圳性息",
level:4,parent:"218"},{id:"287",name:"赚米专区",level:3,parent:"56"},{id:"136",name:"坛友自售",level:3,parent:"56"},{id:"289",name:"破解软件",level:3,parent:"56"
},{id:"339",name:"包养情报",level:3,parent:"56"},{id:"128",name:"问题建议/举报申诉",level:3,parent:"56"},{id:"292",name:"解禁忏悔区/丢失找回",level:4,parent:"128"}]
;let a=n;const r=class{static init(){this.initialized||(this.removeSearchButton(),this.addSimpleButtons(),this.initialized=!0)}
static removeSearchButton(){try{const e=document.getElementById("td_ID141");if(e){const t=e.closest("li");if(t)return t.remove(),void 0}
document.querySelectorAll('a[href="/search.php"]').forEach(e=>{const t=e.closest("li");t&&t.remove()})}catch(e){void 0}}static addSimpleButtons(){
const e=document.getElementById("nav-pc");if(e){const t=document.createElement("li"),n=document.createElement("a");n.href="javascript:;",
n.textContent="搜索过滤",n.onclick=()=>!1,t.appendChild(n),e.appendChild(t);const a=this.createSearchFilterPanel();n.addEventListener("click",e=>{
e.preventDefault(),a.show()})}}static createSearchFilterPanel(){
const e='\n      <dialog id="search-filter-panel" class="clean-search-panel script-container">\n        <header>\n          <span>搜索过滤设置</span>\n          <button id="search-close-settings-btn" class="close-x">×</button>\n        </header>\n        <main id="search-forum-list" class="clean-forum-tree"></main>\n        <footer>\n          <div class="filter-controls">\n            <button id="search-clear-all-filters" class="secondary">清除全部</button>\n            <button id="search-select-all-forums" class="secondary">全选</button>\n          </div>\n          <button id="search-save-settings-btn">保存设置</button>\n        </footer>\n      </dialog>\n      <div id="search-filter-overlay" style="display:none; position:fixed; inset:0; background:rgba(0,0,0,0.5); z-index:10000;"></div>\n    '
;document.body.insertAdjacentHTML("beforeend",e)
;const t=document.getElementById("search-filter-panel"),n=document.getElementById("search-filter-overlay");return this.generateCleanSearchForumList(),
this.loadSearchFilterSettings(),setTimeout(()=>{n&&this.setupSearchFilterEventListeners(t,n)},50),{show:()=>{t.style.display="block",
n.style.display="block"}}}static generateCleanSearchForumList(){const e=document.getElementById("search-forum-list");if(!e)return
;const t=a.getForumTree();t.filter(e=>2===e.level).forEach(n=>{const a=document.createElement("div");a.className="clean-forum-card"
;const r=document.createElement("div");r.className="clean-card-header";const i=document.createElement("input");i.type="checkbox",
i.id=`search-forum-${n.id}`,i.value=n.id,i.className="main-forum-checkbox";const l=document.createElement("span");l.className="main-forum-title",
l.textContent=n.name,r.appendChild(i),r.appendChild(l),a.appendChild(r);const s=document.createElement("div");s.className="clean-card-content",
this.addCleanSubForums(t,n.id,s,n.id),a.appendChild(s),e.appendChild(a),i.addEventListener("change",()=>{
this.handleSearchFilterParentToggle(n.id,i.checked)})})}static addCleanSubForums(e,t,n,a){const r=e.filter(e=>e.parent===t&&3===e.level)
;if(0!==r.length)if(r.some(t=>e.some(e=>4===e.level&&e.parent===t.id)))r.forEach(t=>{const r=document.createElement("div")
;r.className="clean-sub-section";const i=document.createElement("div");i.className="clean-sub-header";const l=document.createElement("input")
;l.type="checkbox",l.id=`search-forum-${t.id}`,l.value=t.id,l.className="sub-forum-checkbox",l.dataset.parent=a;const s=document.createElement("span")
;s.className="sub-forum-title",s.textContent=t.name,i.appendChild(l),i.appendChild(s),r.appendChild(i),l.addEventListener("change",()=>{
this.handleLevel3Toggle(t.id,l.checked)});const o=e.filter(e=>4===e.level&&e.parent===t.id);if(o.length>0){const e=document.createElement("div")
;e.className="clean-level4-grid",o.forEach(n=>{const r=document.createElement("label");r.className="clean-level4-item"
;const i=document.createElement("input");i.type="checkbox",i.id=`search-forum-${n.id}`,i.value=n.id,i.className="level4-forum-checkbox",
i.dataset.parent=a,i.dataset.level3Parent=t.id;const l=document.createElement("span");l.textContent=n.name,r.appendChild(i),r.appendChild(l),
e.appendChild(r)}),r.appendChild(e)}n.appendChild(r)});else{const e=document.createElement("div");e.className="clean-compact-grid",r.forEach(t=>{
const n=document.createElement("label");n.className="clean-compact-item";const r=document.createElement("input");r.type="checkbox",
r.id=`search-forum-${t.id}`,r.value=t.id,r.className="compact-forum-checkbox",r.dataset.parent=a;const i=document.createElement("span")
;i.textContent=t.name,n.appendChild(r),n.appendChild(i),e.appendChild(n)}),n.appendChild(e)}}static loadSearchFilterSettings(){
CONFIG.getExcludedForums().forEach(e=>{const t=document.getElementById(`search-forum-${e}`);t&&(t.checked=!0)})}
static setupSearchFilterEventListeners(e,t){const n=document.getElementById("search-save-settings-btn")
;n&&n.addEventListener("click",()=>this.saveSearchFilterSettings());const a=()=>{e.style.display="none",t.style.display="none"
},r=document.getElementById("search-close-settings-btn");r&&r.addEventListener("click",a),t.addEventListener("click",a)
;const i=document.getElementById("search-clear-all-filters"),l=document.getElementById("search-select-all-forums")
;i&&i.addEventListener("click",()=>this.clearAllSearchFilters()),l&&l.addEventListener("click",()=>this.selectAllSearchForums())}
static saveSearchFilterSettings(){
const e=document.querySelectorAll('.clean-search-panel input[type="checkbox"]:checked'),t=Array.from(e).map(e=>e.value);CONFIG.setExcludedForums(t),
window.location.reload()}static handleSearchFilterParentToggle(e,t){document.querySelectorAll(`[data-parent="${e}"]`).forEach(e=>{e.checked=t})}
static handleLevel3Toggle(e,t){document.querySelectorAll(`[data-level3-parent="${e}"]`).forEach(e=>{e.checked=t})}static clearAllSearchFilters(){
document.querySelectorAll('.clean-search-panel input[type="checkbox"]').forEach(e=>e.checked=!1)}static selectAllSearchForums(){
document.querySelectorAll('.clean-search-panel input[type="checkbox"]').forEach(e=>e.checked=!0)}};r.initialized=!1;let i=r;const l=class{
static injectStyles(){const e=document.getElementById(this.styleElementId);e&&e.remove();const t=document.createElement("style")
;t.id=this.styleElementId,
t.textContent=".click-tip{position:fixed;background:rgba(0,0,0,0.8);color:#fff;padding:6px 12px;border-radius:4px;font-size:13px;z-index:10000}.thread-title-highlighted{background:#e8f4fd!important;border-radius:4px 4px 0 0}.preview-container{margin:0 0 10px 0;border:1px solid #dee2e6;border-top:none;border-radius:0 0 4px 4px;padding:16px;background:#f8f9fa}.preview-images{display:flex;gap:12px;margin-bottom:16px}.preview-image-wrapper{height:300px;flex:0 0 auto;border-radius:4px;cursor:pointer;overflow:hidden}.preview-image{width:100%;height:100%;object-fit:cover}.preview-magnet{font-size:13px;word-break:break-all;cursor:pointer;padding:10px 12px;background:#f0f9ff;border:1px solid #e0f2fe;border-radius:4px;margin-bottom:10px}.lightbox{position:fixed;inset:0;background:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:9999;opacity:0;visibility:hidden}.lightbox.active{opacity:1;visibility:visible}.lightbox-image{border-radius:8px;display:block;object-fit:contain}.lightbox-prev,.lightbox-next,.lightbox-close{position:absolute;color:#fff;cursor:pointer;background:rgba(0,0,0,0.5);border-radius:50%;display:flex;align-items:center;justify-content:center}.lightbox-prev,.lightbox-next{top:50%;transform:translateY(-50%);font-size:36px;width:60px;height:60px}.lightbox-close{top:20px;right:20px;font-size:24px;width:40px;height:40px}.lightbox-prev{left:20px}.lightbox-next{right:20px}.simple-toggle-btn{color:#007bff;text-decoration:none;font-size:13px;cursor:pointer}.simple-toggle-btn:hover{color:#0056b3;text-decoration:underline}.clean-search-panel{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10001;background:#fff;border:1px solid #ddd;border-radius:8px;font-family:system-ui,sans-serif;width:750px;max-height:80vh;overflow:hidden;box-shadow:0 4px 16px rgba(0,0,0,0.2)}.clean-search-panel header{position:relative;padding:16px 20px;border-bottom:1px solid #e5e7eb;background:#f8f9fa;border-radius:8px 8px 0 0;font-size:15px;font-weight:600;color:#374151}.clean-forum-tree{padding:20px;max-height:500px;overflow-y:auto}.clean-forum-card{margin-bottom:20px;border:1px solid #e5e7eb;border-radius:8px;overflow:hidden;background:#fff}.clean-forum-card:last-child{margin-bottom:0}.clean-card-header{padding:12px 16px;background:#f1f5f9;border-bottom:1px solid #e5e7eb;display:flex;align-items:center;gap:10px}.main-forum-title{font-weight:600;font-size:14px;color:#1f2937;cursor:pointer}.main-forum-checkbox{margin:0;transform:scale(1.1)}.clean-card-content{padding:16px}.clean-sub-section{margin-bottom:16px;border-left:3px solid #e5e7eb;padding-left:12px}.clean-sub-section:last-child{margin-bottom:0}.clean-sub-header{display:flex;align-items:center;gap:8px;margin-bottom:12px}.sub-forum-title{font-weight:500;font-size:13px;color:#4b5563;cursor:pointer}.sub-forum-checkbox{margin:0}.clean-level4-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:8px;margin-left:20px}.clean-level4-item{display:flex;align-items:center;gap:6px;padding:8px 12px;background:#f9fafb;border:1px solid #f3f4f6;border-radius:6px;cursor:pointer;font-size:12px;color:#6b7280}.clean-level4-item:hover{background:#f3f4f6}.level4-forum-checkbox{margin:0;transform:scale(0.9)}.clean-compact-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px;padding:12px}.clean-compact-item{display:flex;align-items:center;gap:6px;padding:10px 12px;background:#fff;border:1px solid #e5e7eb;border-radius:6px;cursor:pointer;font-size:13px;color:#4b5563}.clean-compact-item:hover{background:#f9fafb}.compact-forum-checkbox{margin:0;transform:scale(1.05)}.filter-controls{display:flex;gap:10px}.clean-search-panel footer{padding:16px 20px;background:#f8f9fa;border-top:1px solid #e5e7eb;border-radius:0 0 8px 8px;display:flex;justify-content:space-between;align-items:center}.clean-search-panel button{padding:8px 16px;border:1px solid #d1d5db;border-radius:6px;background:#fff;color:#374151;cursor:pointer;font-size:13px;font-weight:500}.clean-search-panel button.secondary{background:#f9fafb}.clean-search-panel #search-save-settings-btn{background:#3b82f6;border-color:#3b82f6;color:#fff}.flex{display:flex}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:0.5rem}.mb-3{margin-bottom:0.75rem}.p-3{padding:0.75rem}.text-center{text-align:center}.cursor-pointer{cursor:pointer}.close-x{position:absolute;top:12px;right:16px;width:24px;height:24px;border:none;background:none;color:#999;font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;line-height:1}.close-x:hover{color:#666}",
document.head.appendChild(t)}static setImageGridWidth(e,t){let n;n=1===t?"50%":`calc((100% - ${12*(t-1)}px) / ${t})`,
Array.from(e.children).forEach(e=>{e.style.width=n,e.style.flex="0 0 auto"})}};l.styleElementId="ultra-minimal-styles";let s=l;class AdRemover{
static removeAds(){this.removeStickyPosts(),this.removeAdButtons()}static removeGlobalAds(){this.removeAdButtons()}static removeStickyPosts(){
document.querySelectorAll(CONFIG.selectors.threadRows).forEach(e=>{const t=e.querySelector("td.tal")
;t&&t.innerHTML.includes("headtopic_3.gif")&&e.remove()})}static removeAdButtons(){["td_ID144","td_ID86","td_ID139"].forEach(e=>{
const t=document.getElementById(e);if(t){const e=t.closest("li");e?e.remove():t.remove()}})}}class DataExtractor{static extractImages(e){
const t=CONFIG.getPreviewCount();let n=[];for(const r of CONFIG.selectors.imgSelectors)if(n=Array.from(e.querySelectorAll(r)),n.length>0)break
;let a=n.filter(e=>{const t=e.getAttribute("style")||"";return!t.includes("display: none")&&!t.includes("display:none")}).map(e=>({
src:e.getAttribute("data-original")||e.getAttribute("src")||"",img:e})).filter(e=>!(!e.src||e.src.length<4));return a.sort((e,t)=>{
const n=/\.(jpg|jpeg|png)$/i.test(e.src),a=/\.(jpg|jpeg|png)$/i.test(t.src);return n&&!a?-1:!n&&a?1:0}),a.map(e=>e.src).slice(0,t)}
static extractMagnet(e){let t="",n=e.querySelector(CONFIG.selectors.magnetTextarea);if(n)t=n.value.trim();else{
let n=e.querySelector(CONFIG.selectors.magnetLink);if(n)t=n.getAttribute("href")||"";else{const n=e.body.innerHTML.match(CONFIG.regex.magnetHash)
;n&&n[1]&&(t=`magnet:?xt=urn:btih:${n[1]}`)}}return t}static extractEd2k(e){let t="";const n=e.querySelector(CONFIG.selectors.ed2kLink)
;if(n)t=n.getAttribute("href")||"";else{const n=e.body.innerHTML.match(CONFIG.regex.ed2k);n&&n[0]&&(t=n[0])}return t}static extractThunder(e){let t=""
;const n=e.body.innerHTML.match(CONFIG.regex.thunder);return n&&n[0]&&(t=n[0]),t}}class ExternalMagnetExtractor{static async extractFromPage(e){try{
for(const t of CONFIG.btSites){const n=e.match(t.pattern);if(n){const e=t.getHash(n[0]),a=await this.fetchFromBtSite(t,e)
;if(a)return this.cleanMagnetLink(a)}}return null}catch(t){return void 0,null}}static cleanMagnetLink(e){
const t=e.match(/magnet:\?xt=urn:btih:([a-f0-9]{40})/i);return t?`magnet:?xt=urn:btih:${t[1]}`:e}static async fetchFromBtSite(e,t){try{
return new Promise(n=>{const a={method:e.method,url:"GET"===e.method?`${e.url}?name=${t}`:e.url,headers:{
Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept-Language":"zh-CN,zh;q=0.9,en;q=0.8",DNT:"1",Connection:"keep-alive","Upgrade-Insecure-Requests":"1"},onload:e=>{
if(e.status>=200&&e.status<300)try{const t=(new DOMParser).parseFromString(e.responseText,"text/html"),a=t.querySelector("#magnetInput");if(a){
const e=a.value||a.getAttribute("value");if(e){const t=e.replace(/&amp;/g,"&");return n(t),void 0}}const r=t.querySelector(".magnet-box input");if(r){
const e=r.getAttribute("value")||r.value;if(e){const t=e.replace(/&amp;/g,"&");return n(t),void 0}}
const i=e.responseText.match(/magnet:\?xt=urn:btih:[a-f0-9]{40}[^"'\s]*/i);if(i){const e=i[0].replace(/&amp;/g,"&");return n(e),void 0}n(null)
}catch(t){void 0,n(null)}else n(null)},onerror:()=>n(null),ontimeout:()=>n(null)};if("POST"===e.method){
a.headers["Content-Type"]="application/x-www-form-urlencoded",a.headers.Referer=e.referer,a.headers.Origin=e.referer;const n={};n[e.paramName]=t,
a.data=new URLSearchParams(n).toString()}GM_xmlhttpRequest(a)})}catch(n){return void 0,null}}}const o=class{static init(){
this.overlay||(this.overlay=document.createElement("div"),
this.overlay.style.cssText="\n      position: fixed;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      background: rgba(0, 0, 0, 0.95);\n      z-index: 999999;\n      display: none;\n      align-items: center;\n      justify-content: center;\n    ",
this.img=document.createElement("img"),
this.img.style.cssText="\n      max-width: 85%;\n      max-height: 85%;\n      object-fit: contain;\n      border-radius: 4px;\n    ",
this.counter=document.createElement("div"),
this.counter.style.cssText="\n      position: absolute;\n      top: 20px;\n      left: 50%;\n      transform: translateX(-50%);\n      color: white;\n      background: rgba(0, 0, 0, 0.6);\n      padding: 8px 16px;\n      border-radius: 20px;\n      font-size: 14px;\n    ",
this.prevBtn=this.createNavButton("‹","left"),this.nextBtn=this.createNavButton("›","right"),this.overlay.appendChild(this.img),
this.overlay.appendChild(this.counter),this.overlay.appendChild(this.prevBtn),this.overlay.appendChild(this.nextBtn),
document.body.appendChild(this.overlay),this.setupEvents())}static createNavButton(e,t){const n=document.createElement("button")
;return n.innerHTML="‹"===e?'<svg viewBox="0 0 24 24" fill="white" width="30" height="30"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></svg>':'<svg viewBox="0 0 24 24" fill="white" width="30" height="30"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>',
n.style.cssText=`\n      position: fixed;\n      ${t}: 16px;\n      top: 50%;\n      transform: translateY(-50%);\n      width: 40px;\n      height: 40px;\n      background: rgba(255, 255, 255, 0.2);\n      border-radius: 50%;\n      border: none;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      color: white;\n      cursor: pointer;\n      user-select: none;\n      z-index: 10002;\n    `,
n}static setupEvents(){this.overlay.onclick=e=>{e.target===this.overlay&&this.close()},this.prevBtn.onclick=e=>{e.stopPropagation(),this.prev()},
this.nextBtn.onclick=e=>{e.stopPropagation(),this.next()},document.addEventListener("keydown",e=>{
"flex"===this.overlay?.style.display&&("Escape"===e.key?this.close():"ArrowLeft"===e.key?this.prev():"ArrowRight"===e.key&&this.next())})}
static show(e,t=0){this.init(),this.images=e,this.currentIndex=t,this.updateImage(),this.overlay.style.display="flex"}static close(){
this.overlay&&(this.overlay.style.display="none")}static prev(){this.currentIndex=(this.currentIndex-1+this.images.length)%this.images.length,
this.updateImage()}static next(){this.currentIndex=(this.currentIndex+1)%this.images.length,this.updateImage()}static updateImage(){
const e=this.images[this.currentIndex];this.img.style.display="none",this.img.src="",
this.counter.textContent=`${this.currentIndex+1} / ${this.images.length}`,this.images.length<=1?(this.prevBtn.style.display="none",
this.nextBtn.style.display="none",this.counter.style.display="none"):(this.prevBtn.style.display="flex",this.nextBtn.style.display="flex",
this.counter.style.display="block"),this.img.onload=()=>{this.img.style.display="block"},this.img.onerror=()=>{this.img.alt="图片加载失败"},this.img.src=e}}
;o.overlay=null,o.img=null,o.counter=null,o.prevBtn=null,o.nextBtn=null,o.images=[],o.currentIndex=0;let c=o;const d=class{
static injectStyles(options={}){if(this.injected)return;const e={...this.defaultOptions,...options},t=document.createElement("style")
;t.textContent=`\n      .shared-img-grid {\n        display: flex;\n        flex-wrap: nowrap;\n        align-items: flex-start;\n        gap: ${e.gap}px;\n        width: 100%;\n      }\n      \n      .shared-img-item {\n        overflow: hidden;\n        border-radius: ${e.borderRadius}px;\n        position: relative;\n        cursor: ${e.cursor};\n        min-height: ${e.minHeight}px;\n        max-height: ${e.maxHeight}px;\n        height: auto;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        background: ${e.backgroundColor};\n      }\n      \n      .shared-img-item-single {\n        overflow: hidden;\n        border-radius: ${e.borderRadius}px;\n        position: relative;\n        cursor: ${e.cursor};\n        min-height: ${e.minHeight}px;\n        max-height: ${e.maxHeight}px;\n        height: auto;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        background: ${e.backgroundColor};\n      }\n      \n      .shared-img {\n        max-width: 100%;\n        max-height: ${e.maxHeight}px;\n        width: auto;\n        height: auto;\n        object-fit: contain;\n      }\n    `,
document.head.appendChild(t),this.injected=!0}static createGrid(){const e=document.createElement("div");return e.className="shared-img-grid",e}
static createImageItem(e,t=!1,n){const a=document.createElement("div");a.className=t?"shared-img-item-single":"shared-img-item"
;const r=document.createElement("img");return r.className="shared-img",r.src=e,r.loading="lazy",n&&a.addEventListener("click",t=>{t.preventDefault(),
t.stopPropagation(),n(e)}),a.appendChild(r),a}static setGridWidth(e,t,n=8){const a=`calc((100% - ${(t-1)*n}px) / ${t})`
;Array.from(e.children).forEach(e=>{e.style.width=a,e.style.flex="0 0 auto"})}static create(e,t,options={}){this.injectStyles(options)
;const n=this.createGrid(),a=1===e.length;e.forEach((e,r)=>{const i=this.createImageItem(e,a,e=>{t&&t(e,r)});n.appendChild(i)})
;const r=options.gap||this.defaultOptions.gap;return this.setGridWidth(n,e.length,r),n}};d.injected=!1,d.defaultOptions={minHeight:200,maxHeight:400,
gap:8,backgroundColor:"#f5f5f5",borderRadius:4,cursor:"pointer"};let p=d;class UIComponents{static buildPreviewUI(t,n){
const{imgSrcs:a,magnet:r,ed2k:i,thunder:l}=n;if(t.nextElementSibling&&t.nextElementSibling.classList.contains("imagePreviewTr"))return
;t.classList.add("thread-title-highlighted");const s=document.createElement("tr");s.className="imagePreviewTr";const o=document.createElement("td")
;o.colSpan=t.children.length;const c=e("div","preview-container");c.style.borderTop="none",a.length&&c.appendChild(this.createImageSection(a)),
r&&c.appendChild(this.createInfoSection(r)),i&&c.appendChild(this.createEd2kSection(i)),l&&c.appendChild(this.createThunderSection(l)),
o.appendChild(c),s.appendChild(o),t.parentNode.insertBefore(s,t.nextSibling)}static createImageSection(e){const t=e.filter(e=>e&&e.startsWith("http"))
;if(0===t.length)return document.createElement("div");const n=p.create(t,(e,n)=>c.show(t,n),{minHeight:200,maxHeight:400,gap:12,
backgroundColor:"#f5f5f5",borderRadius:4});return n.style.marginBottom="16px",n}static createInfoSection(e){const n=document.createElement("div")
;return n.className="preview-magnet",n.textContent=e,n.title="点击链接可复制",n.onclick=function(n){t.copyToClipboard(e,n)},n}static createEd2kSection(e){
const n=document.createElement("div");return n.className="preview-magnet",n.textContent=e,n.title="点击ed2k链接可复制",n.onclick=function(n){
t.copyToClipboard(e,n)},n}static createThunderSection(e){const n=document.createElement("div");return n.className="preview-magnet",n.textContent=e,
n.title="点击迅雷链接可复制",n.onclick=function(n){t.copyToClipboard(e,n)},n}}const m=class{static init(){
this.initialized||this.isSearchResultPage()&&(this.filterSearchResults(),this.updateResultStats(),this.initialized=!0)}static isSearchResultPage(){
if(!window.location.href.includes("search.php"))return!1;const e=document.querySelector(".t table"),t=document.querySelectorAll('tr[id^="search_"]')
;return!!(e&&t.length>0)}static extractForumId(e){const t=e.getAttribute("id");if(t&&t.startsWith("search_")){const e=t.split("_")
;if(e.length>=2)return e[1]}return null}static getExcludedForums(){return CONFIG.getExcludedForums()}static filterSearchResults(){
const e=this.getExcludedForums();if(0===e.length)return;const t=document.querySelectorAll('tr[id^="search_"]');this.totalCount=t.length;let n=0
;t.forEach(t=>{const a=this.extractForumId(t);if(a&&e.includes(a)){t.style.display="none";const e=t.nextElementSibling
;e&&e.classList.contains("imagePreviewTr")&&(e.style.display="none"),n++}}),this.filteredCount=n,n>0}static updateResultStats(){
if(0===this.filteredCount)return;const e=document.querySelector(".t table .h");if(e){
const t=e.textContent||"主题列表",n=this.totalCount-this.filteredCount;e.textContent=`${t} (显示 ${n}/${this.totalCount} 条结果,已过滤 ${this.filteredCount} 条)`,
e.setAttribute("title",`已根据设置隐藏${this.filteredCount}条不相关结果`)}}static reapplyFilter(){
this.isSearchResultPage()&&(document.querySelectorAll('tr[id^="search_"], tr.imagePreviewTr').forEach(e=>{e.style.display=""}),this.filteredCount=0,
this.filterSearchResults(),this.updateResultStats())}static getFilterStats(){return{total:this.totalCount,filtered:this.filteredCount,
visible:this.totalCount-this.filteredCount}}static clearAllFilters(){CONFIG.setExcludedForums([]),this.reapplyFilter()}static addExcludedForum(e){
const t=this.getExcludedForums();t.includes(e)||(t.push(e),CONFIG.setExcludedForums(t),this.reapplyFilter())}static removeExcludedForum(e){
const t=this.getExcludedForums().filter(t=>t!==e);CONFIG.setExcludedForums(t),this.reapplyFilter()}static toggleForumExclusion(e){
this.getExcludedForums().includes(e)?this.removeExcludedForum(e):this.addExcludedForum(e)}static shouldFilterRow(e){
const t=this.extractForumId(e),n=this.getExcludedForums();return!!t&&n.includes(t)}};m.initialized=!1,m.filteredCount=0,m.totalCount=0;let h=m
;class PreviewProcessor{static async processThreadLink(e){const t=e.href;if(!t||!CONFIG.regex.threadUrl.test(t))return;const n=e.closest("tr")
;if(n&&!n.querySelector('img[src*="headtopic"]')&&!h.shouldFilterRow(n))try{
const e=await fetch(t),a=await e.text(),r=(new DOMParser).parseFromString(a,"text/html");let i=DataExtractor.extractMagnet(r)
;i||(i=await ExternalMagnetExtractor.extractFromPage(a)||"");const l={imgSrcs:DataExtractor.extractImages(r),magnet:i||"",
ed2k:DataExtractor.extractEd2k(r),thunder:DataExtractor.extractThunder(r)};if(!(l.imgSrcs.length||l.magnet||l.ed2k||l.thunder))return
;UIComponents.buildPreviewUI(n,l)}catch(a){void 0}}}class App2048{static async displayThreadImages(){if(t.isContentPage())return;t.removeRules()
;const e=t.safeQuerySelectorAll(CONFIG.selectors.threadLinks);e.length&&await Promise.all(e.map(e=>PreviewProcessor.processThreadLink(e)))}
static isSearchPage(){return CONFIG.regex.searchUrl.test(window.location.href)&&null!==document.querySelector(CONFIG.selectors.searchResultTable)}
static async main(){try{if(i.init(),s.injectStyles(),t.isContentPage())return;this.isSearchPage()?(h.init(),
await this.displayThreadImages()):(AdRemover.removeAds(),await this.displayThreadImages())}catch(e){void 0}}}AdRemover.removeGlobalAds(),
"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>{AdRemover.removeGlobalAds(),App2048.main()
}):(AdRemover.removeGlobalAds(),App2048.main()),window.addEventListener("load",()=>{AdRemover.removeGlobalAds()})})();