// ==UserScript== // @name 盘链批量发帖 // @namespace https://pinglian.lol/ // @version 2.2.0 // @description 批量搜索片源并自动添加网盘链接。读取CSV/TSV数据(格式:剧名,链接名称,链接地址),自动逐条完成搜索→详情→填写→提交全流程。 // @author Marvis // @match https://pinglian.lol/* // @match *://www.guangyapan.com/* // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_xmlhttpRequest // @grant GM_addStyle // @connect supabase.co // @connect * // @run-at document-end // ==/UserScript== /* global GM_setValue, GM_getValue, GM_deleteValue, GM_xmlhttpRequest, GM_addStyle */ // ============================================================ // 样式注入 // ============================================================ GM_addStyle(` #pl-batch-panel { position: fixed; top: 60px; right: 10px; z-index: 99999; width: 380px; max-height: calc(100vh - 80px); background: #1e1e2e; border: 1px solid #45475a; border-radius: 10px; box-shadow: 0 8px 32px rgba(0,0,0,0.5); color: #cdd6f4; font-family: "Microsoft YaHei", "PingFang SC", sans-serif; font-size: 13px; display: flex; flex-direction: column; overflow: hidden; } #pl-batch-panel.minimized .pl-panel-body { display: none; } #pl-batch-panel.minimized .pl-panel-footer { display: none; } .pl-panel-header { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; background: #313244; cursor: move; user-select: none; flex-shrink: 0; } .pl-panel-header h3 { margin: 0; font-size: 14px; color: #f5c2e7; } .pl-panel-header .pl-btns { display: flex; gap: 6px; } .pl-panel-header button { background: #45475a; border: none; color: #cdd6f4; width: 26px; height: 26px; border-radius: 4px; cursor: pointer; font-size: 14px; line-height: 26px; text-align: center; padding: 0; } .pl-panel-header button:hover { background: #585b70; } .pl-panel-body { padding: 10px 14px; overflow-y: auto; flex: 1; display: flex; flex-direction: column; gap: 8px; } .pl-panel-body label { font-size: 12px; color: #a6adc8; margin-bottom: -4px; } .pl-panel-body textarea { width: 100%; height: 120px; background: #11111b; border: 1px solid #45475a; border-radius: 6px; color: #cdd6f4; font-size: 12px; padding: 8px; resize: vertical; box-sizing: border-box; } .pl-panel-body textarea:focus { outline: none; border-color: #cba6f7; } .pl-panel-body select, .pl-panel-body input[type=file] { width: 100%; background: #11111b; border: 1px solid #45475a; border-radius: 6px; color: #cdd6f4; font-size: 12px; padding: 6px 8px; box-sizing: border-box; } .pl-panel-body select:focus { outline: none; border-color: #cba6f7; } .pl-row { display: flex; gap: 8px; align-items: center; } .pl-row > * { flex: 1; } .pl-btn { padding: 8px 16px; border: none; border-radius: 6px; cursor: pointer; font-size: 13px; font-weight: bold; } .pl-btn-start { background: #a6e3a1; color: #1e1e2e; } .pl-btn-start:hover { background: #94e2d5; } .pl-btn-start:disabled { background: #585b70; color: #6c7086; cursor: not-allowed; } .pl-btn-pause { background: #f9e2af; color: #1e1e2e; } .pl-btn-pause:hover { background: #fab387; } .pl-btn-reset { background: #f38ba8; color: #1e1e2e; } .pl-btn-reset:hover { background: #eba0ac; } .pl-panel-footer { padding: 8px 14px; background: #181825; flex-shrink: 0; display: flex; gap: 6px; } .pl-progress { background: #313244; border-radius: 4px; height: 8px; overflow: hidden; margin-top: 4px; } .pl-progress-bar { height: 100%; background: linear-gradient(90deg, #cba6f7, #89b4fa); width: 0%; transition: width 0.3s; } .pl-stats { font-size: 11px; color: #a6adc8; display: flex; gap: 10px; } .pl-stats span.ok { color: #a6e3a1; } .pl-stats span.fail { color: #f38ba8; } .pl-stats span.warn { color: #f9e2af; } .pl-import-hint { font-size: 11px; color: #6c7086; margin-top: -4px; } .pl-status { padding: 6px 10px; background: #313244; border-radius: 6px; font-size: 12px; color: #f5c2e7; text-align: center; flex-shrink: 0; } .pl-log-area { background: #11111b; border: 1px solid #313244; border-radius: 6px; max-height: 80px; overflow-y: auto; padding: 5px 8px; flex-shrink: 0; } .pl-candidate-area { max-height: 160px; overflow-y: auto; font-size: 11px; background: #1e1e2e; border: 1px solid #cba6f7; border-radius: 4px; padding: 6px 8px; margin-bottom: 4px; } .pl-candidate-title { color: #cba6f7; font-weight: bold; margin-bottom: 4px; } .pl-candidate-item { display: block; width: 100%; text-align: left; padding: 3px 6px; margin: 2px 0; border: 1px solid #45475a; border-radius: 3px; background: #313244; color: #cdd6f4; cursor: pointer; font-size: 11px; } .pl-candidate-item:hover { background: #45475a; border-color: #cba6f7; } .pl-candidate-skip { display: inline-block; padding: 3px 10px; margin-top: 4px; background: #f38ba8; color: #1e1e2e; border: none; border-radius: 3px; cursor: pointer; font-size: 11px; font-weight: bold; } .pl-candidate-skip:hover { background: #f5c2e7; } .pl-log-entry { font-size: 10px; color: #6c7086; line-height: 1.5; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } `); // ============================================================ // 常量 // ============================================================ const GM_KEY_TASKS = "pl_tasks"; const GM_KEY_INDEX = "pl_index"; const GM_KEY_PAN_TYPE = "pl_pan_type"; const GM_KEY_STATUS = "pl_status"; const GM_KEY_STATS = "pl_stats"; const GM_KEY_CANDIDATES = "pl_candidates"; // 人工决策候选列表 const STATUS_IDLE = "idle"; const STATUS_RUNNING = "running"; const STATUS_PAUSED = "paused"; const INTERVAL_MIN = 2000; const INTERVAL_MAX = 3500; const SEARCH_TIMEOUT = 20000; const MAX_CONSECUTIVE_TIMEOUTS = 3; let consecutiveTimeouts = 0; let logBuffer = []; function addLog(msg) { console.log("[PL]", msg); logBuffer.push(new Date().toLocaleTimeString() + " " + msg); if (logBuffer.length > 5) logBuffer.shift(); updateLogDisplay(); } function updateLogDisplay() { const el = document.getElementById("pl-log-area"); if (!el) return; el.innerHTML = logBuffer.map(function(s) { return '
支持 .csv / .tsv / .txt,逗号或Tab分隔,三列:剧名,链接名称,链接地址