// ==UserScript== // @name 新闻工作台 · 本地连接 // @namespace local.dww11.auto-news // @version 0.1.1 // @match https://www.dww11.com/* // @match https://dww11.com/* // @match https://house.dww11.com/* // @grant GM_xmlhttpRequest // @grant GM_getValue // @grant GM_setValue // @grant GM_addValueChangeListener // @connect 127.0.0.1 // @run-at document-start // @noframes // ==/UserScript== (() => { 'use strict'; const allowed = new Set(['heartbeat','next','package','event','accept','switch-begin','takeover','stop','current','skip']); let token = GM_getValue('pairToken',''), port = GM_getValue('pairPort',8770); let stopRevision = 0; const signalStop = () => { stopRevision++; document.dispatchEvent(new CustomEvent('dww11:auto-stop')); }; GM_addValueChangeListener('halted', (_key, _old, value) => { if (value) signalStop(); }); function request(route, body) { return new Promise((resolve, reject) => { if (!token) return reject(new Error('请在左下角填入本地工作台的连接码')); GM_xmlhttpRequest({method:'POST',url:`http://127.0.0.1:${port}/bridge/${route}`, headers:{'Content-Type':'application/json','X-Session-Token':token},data:JSON.stringify(body),timeout:60000, onload(response) { try { const value=JSON.parse(response.responseText); if(response.status!==200) throw new Error(value.error || '本地连接失败'); resolve(value); } catch(error) { reject(error); } }, onerror:()=>reject(new Error('本地服务未连接,请检查服务与脚本权限')), ontimeout:()=>reject(new Error('本地服务超时,任务已暂停'))}); }); } document.addEventListener('dww11:local-request', async event => { let message; try {message=JSON.parse(event.detail);} catch {return;} if (!allowed.has(message.route) || typeof message.id !== 'string') return; try { if (message.route==='stop') { GM_setValue('halted',true); signalStop(); } const revision = stopRevision; let value=await request(message.route,message.body || {}); if (message.route==='heartbeat') { if (revision !== stopRevision) value = {...value, running:false, reason:'终止后忽略旧连接响应'}; GM_setValue('halted',!value.running); if (!value.running) signalStop(); } document.dispatchEvent(new CustomEvent('dww11:local-response',{detail:JSON.stringify({id:message.id,value})})); } catch(error) { if (message.route==='heartbeat') {GM_setValue('halted',true); signalStop();} document.dispatchEvent(new CustomEvent('dww11:local-response',{detail:JSON.stringify({id:message.id,error:error.message})})); } }); function mount() { if (!document.body || document.getElementById('auto-news-connection')) return; const host=document.createElement('div');host.id='auto-news-connection'; host.style.cssText='position:fixed;left:16px;bottom:16px;z-index:2147483647'; const shadow=host.attachShadow({mode:'closed'}); shadow.innerHTML='
新闻工作台 · 本地连接
连接设置
请启动本地工作台并配对
'; const $=id=>shadow.getElementById(id);$('port').value=port; const skip=document.createElement('button');skip.id='skip';skip.type='button';skip.textContent='跳过本文章'; $('halt').before(skip); skip.onclick=()=>document.dispatchEvent(new CustomEvent('dww11:skip-article')); document.addEventListener('dww11:skip-busy',event=>{skip.disabled=Boolean(event.detail);}); $('save').onclick=()=>{ const value=Number($('port').value);if(!Number.isInteger(value)||value<1||value>65535){$('status').textContent='端口无效';return;} if($('token').value.trim()) token=$('token').value.trim();port=value; GM_setValue('pairToken',token);GM_setValue('pairPort',port);$('token').value='';$('status').textContent='已保存;服务重启后需要更新连接码'; }; $('halt').onclick=async()=>{ GM_setValue('halted',true);signalStop();$('status').textContent='已终止;在途请求仍可能完成'; try {await request('stop',{});} catch(error) {$('status').textContent+='。'+error.message;} }; document.addEventListener('dww11:connection-status',event=>{$('status').textContent=String(event.detail).slice(0,250);}); document.body.append(host); if(GM_getValue('halted',true)) signalStop(); } if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',mount,{once:true}); else mount(); })();