更新审核提示流程与工作台版本
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
12 files changed
+296
-268
No files matched your search
+79
-51
@@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name 新闻工作台 · 导入排版与流程
|
||||
// @namespace local.dww11.auto-news
|
||||
// @version 0.2.0
|
||||
// @version 0.2.1
|
||||
// @match https://www.dww11.com/*
|
||||
// @match https://dww11.com/*
|
||||
// @match https://house.dww11.com/*
|
||||
@@ -741,41 +741,52 @@ window.DWW11Formatter = Object.freeze({
|
||||
function parameter(href,key,base){try{return new URL(href,base).searchParams.get(key);}catch{return null;}}
|
||||
function aid(image){return String(image.getAttribute('aid')||image.id||'').match(/(?:attachimg_|aimg_)?(\d+)$/)?.[1]||null;}
|
||||
function inspect(doc,url,snapshot={}) {
|
||||
const titleNode=doc.querySelector('#thread_subject');
|
||||
if(!titleNode) {
|
||||
const prompt=doc.querySelector('#messagetext, .messagetext');
|
||||
const text=clean(prompt?.textContent);
|
||||
if(/^(?:抱歉[,,]\s*)?(?:您填写的)?(?:帖子)?标题.{0,40}(?:超过|超出).{0,40}(?:字符|长度|限制)/.test(text))return {kind:'rejected',error:text};
|
||||
return {kind:'waiting',prompt:text,candidate:prompt?.querySelector('a[href]')?.href||''};
|
||||
}
|
||||
const region=titleNode.closest('td')||titleNode.closest('h1')?.parentElement;
|
||||
if(!region)return {kind:'incomplete',error:'缺少标题状态区域'};
|
||||
const ids=new Set([...region.querySelectorAll('a[href]')].filter(a=>parameter(a.href,'mod',url)==='viewthread').map(a=>parameter(a.href,'tid',url)).filter(x=>/^\d+$/.test(x)));
|
||||
if(ids.size!==1)return {kind:'incomplete',error:'详情页真实主题编号缺失或冲突'};
|
||||
const thread_id=[...ids][0],body=doc.querySelector('[id^="postmessage_"]');
|
||||
const pid=body?.id.match(/^postmessage_(\d+)$/)?.[1];
|
||||
const post=pid&&doc.querySelector('#post_'+pid);
|
||||
if(!post||clean(post.querySelector('#postnum'+pid)?.textContent)!=='楼主')return {kind:'incomplete',error:'无法确认当前正文属于首帖'};
|
||||
const authors=post?[...post.querySelectorAll('.plc .pti .authi a[href], .pls .authi a[href]')]:[];
|
||||
const uids=new Set(authors.map(a=>parameter(a.href,'uid',url)).filter(x=>/^\d+$/.test(x)));
|
||||
const fids=new Set([...doc.querySelectorAll('#pt a[href], .mumucms_pt a[href]')].filter(a=>parameter(a.href,'mod',url)==='forumdisplay').map(a=>parameter(a.href,'fid',url)).filter(x=>/^\d+$/.test(x)));
|
||||
if(!body||!pid||uids.size!==1||fids.size!==1)return {kind:'incomplete',error:'首帖作者、正文或版块证据不足'};
|
||||
const moderation=[...region.querySelectorAll('span.xg1')].some(n=>/\(\s*审核中\s*\)|(\s*审核中\s*)/.test(n.textContent));
|
||||
// A public-page sample is not available yet. Absence of moderation is not proof of publication.
|
||||
if(!moderation)return {kind:'incomplete',error:'尚无可验证的公开或审核中状态'};
|
||||
const allImages=[...body.querySelectorAll('img')];
|
||||
const images=allImages.filter(img=>aid(img)).map(img=>({aid:aid(img),src:img.getAttribute('src'),loaded:img.complete&&img.naturalWidth>0&&!/\/none\.gif(?:[?#]|$)/.test(img.src||img.getAttribute('src')||''),file:img.getAttribute('file')||img.getAttribute('zoomfile')}));
|
||||
const expected=(snapshot.images||[]).map(img=>String(img.aid||img.id||'').match(/(?:attachimg_|aimg_)?(\d+)$/)?.[1]).filter(Boolean);
|
||||
const issues=[];
|
||||
if(allImages.some(img=>!aid(img)))issues.push('正文存在无法关联附件的图片');
|
||||
if(expected.length!==(snapshot.images||[]).length)issues.push('提交快照存在无法识别附件编号的图片');
|
||||
if(JSON.stringify(expected)!==JSON.stringify(images.map(img=>img.aid)))issues.push('首帖正文图片引用或顺序与提交快照不一致');
|
||||
if(images.some(img=>!img.loaded))issues.push('结果页正文图片尚未加载或加载失败');
|
||||
if(snapshot.text&&clean(body.innerText||body.textContent)!==clean(snapshot.text))issues.push('结果正文与最终提交快照存在文字差异');
|
||||
const attachments=post?[...post.querySelectorAll('.pattl img, .attm img')].map(img=>({aid:aid(img),src:img.getAttribute('src')})):[];
|
||||
if(attachments.length)issues.push('结果页存在附件区图片,请核对正文位置');
|
||||
return {kind:'accepted',thread_id,first_post_pid:pid,post_url:url,title:clean(titleNode.textContent),author_uid:[...uids][0],fid:Number([...fids][0]),state:'accepted_pending_moderation',
|
||||
evidence:{adapter:1,thread_id,first_post_pid:pid,title:clean(titleNode.textContent),author_uid:[...uids][0],fid:Number([...fids][0]),moderation:true,images,attachments,integrity_issues:issues}};
|
||||
const prompt=doc.querySelector('#messagetext, .messagetext');
|
||||
const text=clean(prompt?.textContent);
|
||||
const message='新主题需要审核,您的帖子通过审核后才能显示';
|
||||
if(text.includes(message))return {
|
||||
kind:'accepted_prompt',state:'accepted_pending_moderation',
|
||||
evidence:{adapter:'moderation_prompt',message,observed_text:text,observed_url:url}
|
||||
};
|
||||
if(/^(?:抱歉[,,]\s*)?(?:您填写的)?(?:帖子)?标题.{0,40}(?:超过|超出).{0,40}(?:字符|长度|限制)/.test(text))return {kind:'rejected',error:text};
|
||||
return {kind:'waiting',prompt:text};
|
||||
|
||||
// 暂停详情页核对:按用户要求注释保留,待恢复时启用。
|
||||
// const titleNode=doc.querySelector('#thread_subject');
|
||||
// if(!titleNode) {
|
||||
// const prompt=doc.querySelector('#messagetext, .messagetext');
|
||||
// const text=clean(prompt?.textContent);
|
||||
// if(/^(?:抱歉[,,]\s*)?(?:您填写的)?(?:帖子)?标题.{0,40}(?:超过|超出).{0,40}(?:字符|长度|限制)/.test(text))return {kind:'rejected',error:text};
|
||||
// return {kind:'waiting',prompt:text,candidate:prompt?.querySelector('a[href]')?.href||''};
|
||||
// }
|
||||
// const region=titleNode.closest('td')||titleNode.closest('h1')?.parentElement;
|
||||
// if(!region)return {kind:'incomplete',error:'缺少标题状态区域'};
|
||||
// const ids=new Set([...region.querySelectorAll('a[href]')].filter(a=>parameter(a.href,'mod',url)==='viewthread').map(a=>parameter(a.href,'tid',url)).filter(x=>/^\d+$/.test(x)));
|
||||
// if(ids.size!==1)return {kind:'incomplete',error:'详情页真实主题编号缺失或冲突'};
|
||||
// const thread_id=[...ids][0],body=doc.querySelector('[id^="postmessage_"]');
|
||||
// const pid=body?.id.match(/^postmessage_(\d+)$/)?.[1];
|
||||
// const post=pid&&doc.querySelector('#post_'+pid);
|
||||
// if(!post||clean(post.querySelector('#postnum'+pid)?.textContent)!=='楼主')return {kind:'incomplete',error:'无法确认当前正文属于首帖'};
|
||||
// const authors=post?[...post.querySelectorAll('.plc .pti .authi a[href], .pls .authi a[href]')]:[];
|
||||
// const uids=new Set(authors.map(a=>parameter(a.href,'uid',url)).filter(x=>/^\d+$/.test(x)));
|
||||
// const fids=new Set([...doc.querySelectorAll('#pt a[href], .mumucms_pt a[href]')].filter(a=>parameter(a.href,'mod',url)==='forumdisplay').map(a=>parameter(a.href,'fid',url)).filter(x=>/^\d+$/.test(x)));
|
||||
// if(!body||!pid||uids.size!==1||fids.size!==1)return {kind:'incomplete',error:'首帖作者、正文或版块证据不足'};
|
||||
// const moderation=[...region.querySelectorAll('span.xg1')].some(n=>/\(\s*审核中\s*\)|(\s*审核中\s*)/.test(n.textContent));
|
||||
// // A public-page sample is not available yet. Absence of moderation is not proof of publication.
|
||||
// if(!moderation)return {kind:'incomplete',error:'尚无可验证的公开或审核中状态'};
|
||||
// const allImages=[...body.querySelectorAll('img')];
|
||||
// const images=allImages.filter(img=>aid(img)).map(img=>({aid:aid(img),src:img.getAttribute('src'),loaded:img.complete&&img.naturalWidth>0&&!/\/none\.gif(?:[?#]|$)/.test(img.src||img.getAttribute('src')||''),file:img.getAttribute('file')||img.getAttribute('zoomfile')}));
|
||||
// const expected=(snapshot.images||[]).map(img=>String(img.aid||img.id||'').match(/(?:attachimg_|aimg_)?(\d+)$/)?.[1]).filter(Boolean);
|
||||
// const issues=[];
|
||||
// if(allImages.some(img=>!aid(img)))issues.push('正文存在无法关联附件的图片');
|
||||
// if(expected.length!==(snapshot.images||[]).length)issues.push('提交快照存在无法识别附件编号的图片');
|
||||
// if(JSON.stringify(expected)!==JSON.stringify(images.map(img=>img.aid)))issues.push('首帖正文图片引用或顺序与提交快照不一致');
|
||||
// if(images.some(img=>!img.loaded))issues.push('结果页正文图片尚未加载或加载失败');
|
||||
// if(snapshot.text&&clean(body.innerText||body.textContent)!==clean(snapshot.text))issues.push('结果正文与最终提交快照存在文字差异');
|
||||
// const attachments=post?[...post.querySelectorAll('.pattl img, .attm img')].map(img=>({aid:aid(img),src:img.getAttribute('src')})):[];
|
||||
// if(attachments.length)issues.push('结果页存在附件区图片,请核对正文位置');
|
||||
// return {kind:'accepted',thread_id,first_post_pid:pid,post_url:url,title:clean(titleNode.textContent),author_uid:[...uids][0],fid:Number([...fids][0]),state:'accepted_pending_moderation',
|
||||
// evidence:{adapter:1,thread_id,first_post_pid:pid,title:clean(titleNode.textContent),author_uid:[...uids][0],fid:Number([...fids][0]),moderation:true,images,attachments,integrity_issues:issues}};
|
||||
}
|
||||
return {inspect,clean};
|
||||
});
|
||||
@@ -789,7 +800,7 @@ window.DWW11Formatter = Object.freeze({
|
||||
const owner=sessionStorage.getItem('auto-news-owner') || crypto.randomUUID();
|
||||
sessionStorage.setItem('auto-news-owner',owner);
|
||||
let run=null, working=false, halted=true, aborter=null, active=null, tickBusy=false;
|
||||
let skipBusy=false, preparation=null, stopRevision=0, resultSeenAt=0;
|
||||
let skipBusy=false, preparation=null, stopRevision=0 /*, resultSeenAt=0 */;
|
||||
const pending=new Map();
|
||||
function rpc(route,body={}) {
|
||||
return new Promise((resolve,reject)=>{
|
||||
@@ -886,7 +897,7 @@ window.DWW11Formatter = Object.freeze({
|
||||
const snapshot=editorSnapshot();
|
||||
const local={id:active.id,snapshot,clickedAt:Date.now(),observed:false};saveLocal(local);
|
||||
rpc('event',{id:active.id,state:'user_submitting',epoch:run?.epoch,snapshot})
|
||||
.then(()=>{const latest=loadLocal();if(latest?.clickedAt===local.clickedAt)saveLocal({...local,observed:true});})
|
||||
.then(()=>{const latest=loadLocal();if(latest?.clickedAt===local.clickedAt)saveLocal({...latest,observed:true});})
|
||||
.catch(error=>status('提交记录待恢复:'+error.message));
|
||||
active.state='user_submitting';status('已观察到人工点击,等待结果页核对。');
|
||||
}catch(error){status('提交快照记录失败:'+error.message);}
|
||||
@@ -928,22 +939,24 @@ window.DWW11Formatter = Object.freeze({
|
||||
}
|
||||
if(!['user_submitting','submit_unknown'].includes(job.state))return;
|
||||
const snapshot=job.snapshot||local?.snapshot||{};
|
||||
const result=window.DWW11Results?.inspect(document,location.href,snapshot);
|
||||
const result=(local?.id===job.id&&local.promptResult)||window.DWW11Results?.inspect(document,location.href,snapshot);
|
||||
if(result?.kind==='rejected'&&job.state==='user_submitting') {
|
||||
await rpc('event',{id:job.id,state:'rejected',error:result.error});
|
||||
status('网站明确拒绝本次提交,已暂停;核对并处理稿件后仍需亲手发表');return;
|
||||
}
|
||||
if(result?.kind==='accepted') {
|
||||
if(result.author_uid!==job.account.uid||result.fid!==job.fid||result.title!==window.DWW11Results.clean(snapshot.title)) {
|
||||
if(job.state==='user_submitting')await rpc('event',{id:job.id,state:'submit_unknown',error:'结果页标题、首帖作者或版块与提交任务不符'});
|
||||
await rpc('stop');status('结果不匹配,已暂停,请人工核对');return;
|
||||
}
|
||||
resultSeenAt ||= Date.now();
|
||||
if(result.evidence.integrity_issues.some(x=>x.includes('尚未加载'))&&Date.now()-resultSeenAt<15000) {
|
||||
status('已看到审核中详情,等待正文图片加载后核对');return;
|
||||
}
|
||||
// 暂停详情页标题、作者、版块和图文核对;保留原代码。
|
||||
// if(result?.kind==='accepted') {
|
||||
// if(result.author_uid!==job.account.uid||result.fid!==job.fid||result.title!==window.DWW11Results.clean(snapshot.title)) {
|
||||
// if(job.state==='user_submitting')await rpc('event',{id:job.id,state:'submit_unknown',error:'结果页标题、首帖作者或版块与提交任务不符'});
|
||||
// await rpc('stop');status('结果不匹配,已暂停,请人工核对');return;
|
||||
// }
|
||||
// resultSeenAt ||= Date.now();
|
||||
// if(result.evidence.integrity_issues.some(x=>x.includes('尚未加载'))&&Date.now()-resultSeenAt<15000) {
|
||||
// status('已看到审核中详情,等待正文图片加载后核对');return;
|
||||
// }
|
||||
if(result?.kind==='accepted_prompt') {
|
||||
const revision=stopRevision,epoch=run.epoch;
|
||||
await rpc('accept',{id:job.id,...result});
|
||||
await rpc('accept',{id:job.id,attempt:job.attempt,...result});
|
||||
sessionStorage.removeItem(SLOT);active=null;
|
||||
// Re-read persistent control after accounting; Stop must suppress navigation and subsequent jobs.
|
||||
run=await rpc('heartbeat',{account:account(),url:location.href,extension:extension()});
|
||||
@@ -956,9 +969,9 @@ window.DWW11Formatter = Object.freeze({
|
||||
if(clickedAt&&Date.now()-clickedAt<45000) {
|
||||
status(result?.prompt||result?.error||'等待网站提交结果,不会重复发表');return;
|
||||
}
|
||||
if(job.state==='user_submitting')await rpc('event',{id:job.id,state:'submit_unknown',error:result?.error||'提交结果证据不足,请打开对应帖子详情后核对'});
|
||||
if(job.state==='user_submitting')await rpc('event',{id:job.id,state:'submit_unknown',error:result?.error||'未观察到网站新主题审核提示,请人工核对是否已受理'});
|
||||
if(run.running)await rpc('stop');
|
||||
status('发布结果待核对;打开对应详情页可继续核对,不会重发');
|
||||
status('未观察到网站审核提示,已暂停;请人工核对,不会重发');
|
||||
}
|
||||
async function switchAccount() {
|
||||
if(working||halted)return;
|
||||
@@ -1022,5 +1035,20 @@ window.DWW11Formatter = Object.freeze({
|
||||
takeover.style.cssText='position:fixed;left:16px;top:16px;z-index:2147483646;padding:8px;background:#fff;border:1px solid #aab;border-radius:6px';
|
||||
takeover.onclick=async()=>{try{await rpc('takeover');status('已接管;核对当前页面后在工作台继续');}catch(error){status(error.message);}};
|
||||
document.body.append(takeover);
|
||||
// 提示可能短暂出现后跳转;及时保存到本次任务,避免两秒轮询漏掉。
|
||||
function capturePrompt() {
|
||||
const local=loadLocal();
|
||||
if(!local?.id||!local.snapshot||!local.clickedAt||local.promptResult)return false;
|
||||
if(active&&(active.id!==local.id||!['user_submitting','submit_unknown'].includes(active.state)))return false;
|
||||
const result=window.DWW11Results?.inspect(document,location.href,local.snapshot);
|
||||
if(result?.kind!=='accepted_prompt')return false;
|
||||
saveLocal({...local,promptResult:result});
|
||||
return true;
|
||||
}
|
||||
if(typeof MutationObserver!=='undefined')new MutationObserver(()=>{
|
||||
if(capturePrompt())void tick();
|
||||
}).observe(document.body,{childList:true,subtree:true,characterData:true});
|
||||
// 跳转后的提示页可能已经渲染完成,首次轮询前也捕获一次。
|
||||
capturePrompt();
|
||||
setInterval(tick,2000);tick();
|
||||
})();
|
||||
+46
-35
@@ -9,41 +9,52 @@
|
||||
function parameter(href,key,base){try{return new URL(href,base).searchParams.get(key);}catch{return null;}}
|
||||
function aid(image){return String(image.getAttribute('aid')||image.id||'').match(/(?:attachimg_|aimg_)?(\d+)$/)?.[1]||null;}
|
||||
function inspect(doc,url,snapshot={}) {
|
||||
const titleNode=doc.querySelector('#thread_subject');
|
||||
if(!titleNode) {
|
||||
const prompt=doc.querySelector('#messagetext, .messagetext');
|
||||
const text=clean(prompt?.textContent);
|
||||
if(/^(?:抱歉[,,]\s*)?(?:您填写的)?(?:帖子)?标题.{0,40}(?:超过|超出).{0,40}(?:字符|长度|限制)/.test(text))return {kind:'rejected',error:text};
|
||||
return {kind:'waiting',prompt:text,candidate:prompt?.querySelector('a[href]')?.href||''};
|
||||
}
|
||||
const region=titleNode.closest('td')||titleNode.closest('h1')?.parentElement;
|
||||
if(!region)return {kind:'incomplete',error:'缺少标题状态区域'};
|
||||
const ids=new Set([...region.querySelectorAll('a[href]')].filter(a=>parameter(a.href,'mod',url)==='viewthread').map(a=>parameter(a.href,'tid',url)).filter(x=>/^\d+$/.test(x)));
|
||||
if(ids.size!==1)return {kind:'incomplete',error:'详情页真实主题编号缺失或冲突'};
|
||||
const thread_id=[...ids][0],body=doc.querySelector('[id^="postmessage_"]');
|
||||
const pid=body?.id.match(/^postmessage_(\d+)$/)?.[1];
|
||||
const post=pid&&doc.querySelector('#post_'+pid);
|
||||
if(!post||clean(post.querySelector('#postnum'+pid)?.textContent)!=='楼主')return {kind:'incomplete',error:'无法确认当前正文属于首帖'};
|
||||
const authors=post?[...post.querySelectorAll('.plc .pti .authi a[href], .pls .authi a[href]')]:[];
|
||||
const uids=new Set(authors.map(a=>parameter(a.href,'uid',url)).filter(x=>/^\d+$/.test(x)));
|
||||
const fids=new Set([...doc.querySelectorAll('#pt a[href], .mumucms_pt a[href]')].filter(a=>parameter(a.href,'mod',url)==='forumdisplay').map(a=>parameter(a.href,'fid',url)).filter(x=>/^\d+$/.test(x)));
|
||||
if(!body||!pid||uids.size!==1||fids.size!==1)return {kind:'incomplete',error:'首帖作者、正文或版块证据不足'};
|
||||
const moderation=[...region.querySelectorAll('span.xg1')].some(n=>/\(\s*审核中\s*\)|(\s*审核中\s*)/.test(n.textContent));
|
||||
// A public-page sample is not available yet. Absence of moderation is not proof of publication.
|
||||
if(!moderation)return {kind:'incomplete',error:'尚无可验证的公开或审核中状态'};
|
||||
const allImages=[...body.querySelectorAll('img')];
|
||||
const images=allImages.filter(img=>aid(img)).map(img=>({aid:aid(img),src:img.getAttribute('src'),loaded:img.complete&&img.naturalWidth>0&&!/\/none\.gif(?:[?#]|$)/.test(img.src||img.getAttribute('src')||''),file:img.getAttribute('file')||img.getAttribute('zoomfile')}));
|
||||
const expected=(snapshot.images||[]).map(img=>String(img.aid||img.id||'').match(/(?:attachimg_|aimg_)?(\d+)$/)?.[1]).filter(Boolean);
|
||||
const issues=[];
|
||||
if(allImages.some(img=>!aid(img)))issues.push('正文存在无法关联附件的图片');
|
||||
if(expected.length!==(snapshot.images||[]).length)issues.push('提交快照存在无法识别附件编号的图片');
|
||||
if(JSON.stringify(expected)!==JSON.stringify(images.map(img=>img.aid)))issues.push('首帖正文图片引用或顺序与提交快照不一致');
|
||||
if(images.some(img=>!img.loaded))issues.push('结果页正文图片尚未加载或加载失败');
|
||||
if(snapshot.text&&clean(body.innerText||body.textContent)!==clean(snapshot.text))issues.push('结果正文与最终提交快照存在文字差异');
|
||||
const attachments=post?[...post.querySelectorAll('.pattl img, .attm img')].map(img=>({aid:aid(img),src:img.getAttribute('src')})):[];
|
||||
if(attachments.length)issues.push('结果页存在附件区图片,请核对正文位置');
|
||||
return {kind:'accepted',thread_id,first_post_pid:pid,post_url:url,title:clean(titleNode.textContent),author_uid:[...uids][0],fid:Number([...fids][0]),state:'accepted_pending_moderation',
|
||||
evidence:{adapter:1,thread_id,first_post_pid:pid,title:clean(titleNode.textContent),author_uid:[...uids][0],fid:Number([...fids][0]),moderation:true,images,attachments,integrity_issues:issues}};
|
||||
const prompt=doc.querySelector('#messagetext, .messagetext');
|
||||
const text=clean(prompt?.textContent);
|
||||
const message='新主题需要审核,您的帖子通过审核后才能显示';
|
||||
if(text.includes(message))return {
|
||||
kind:'accepted_prompt',state:'accepted_pending_moderation',
|
||||
evidence:{adapter:'moderation_prompt',message,observed_text:text,observed_url:url}
|
||||
};
|
||||
if(/^(?:抱歉[,,]\s*)?(?:您填写的)?(?:帖子)?标题.{0,40}(?:超过|超出).{0,40}(?:字符|长度|限制)/.test(text))return {kind:'rejected',error:text};
|
||||
return {kind:'waiting',prompt:text};
|
||||
|
||||
// 暂停详情页核对:按用户要求注释保留,待恢复时启用。
|
||||
// const titleNode=doc.querySelector('#thread_subject');
|
||||
// if(!titleNode) {
|
||||
// const prompt=doc.querySelector('#messagetext, .messagetext');
|
||||
// const text=clean(prompt?.textContent);
|
||||
// if(/^(?:抱歉[,,]\s*)?(?:您填写的)?(?:帖子)?标题.{0,40}(?:超过|超出).{0,40}(?:字符|长度|限制)/.test(text))return {kind:'rejected',error:text};
|
||||
// return {kind:'waiting',prompt:text,candidate:prompt?.querySelector('a[href]')?.href||''};
|
||||
// }
|
||||
// const region=titleNode.closest('td')||titleNode.closest('h1')?.parentElement;
|
||||
// if(!region)return {kind:'incomplete',error:'缺少标题状态区域'};
|
||||
// const ids=new Set([...region.querySelectorAll('a[href]')].filter(a=>parameter(a.href,'mod',url)==='viewthread').map(a=>parameter(a.href,'tid',url)).filter(x=>/^\d+$/.test(x)));
|
||||
// if(ids.size!==1)return {kind:'incomplete',error:'详情页真实主题编号缺失或冲突'};
|
||||
// const thread_id=[...ids][0],body=doc.querySelector('[id^="postmessage_"]');
|
||||
// const pid=body?.id.match(/^postmessage_(\d+)$/)?.[1];
|
||||
// const post=pid&&doc.querySelector('#post_'+pid);
|
||||
// if(!post||clean(post.querySelector('#postnum'+pid)?.textContent)!=='楼主')return {kind:'incomplete',error:'无法确认当前正文属于首帖'};
|
||||
// const authors=post?[...post.querySelectorAll('.plc .pti .authi a[href], .pls .authi a[href]')]:[];
|
||||
// const uids=new Set(authors.map(a=>parameter(a.href,'uid',url)).filter(x=>/^\d+$/.test(x)));
|
||||
// const fids=new Set([...doc.querySelectorAll('#pt a[href], .mumucms_pt a[href]')].filter(a=>parameter(a.href,'mod',url)==='forumdisplay').map(a=>parameter(a.href,'fid',url)).filter(x=>/^\d+$/.test(x)));
|
||||
// if(!body||!pid||uids.size!==1||fids.size!==1)return {kind:'incomplete',error:'首帖作者、正文或版块证据不足'};
|
||||
// const moderation=[...region.querySelectorAll('span.xg1')].some(n=>/\(\s*审核中\s*\)|(\s*审核中\s*)/.test(n.textContent));
|
||||
// // A public-page sample is not available yet. Absence of moderation is not proof of publication.
|
||||
// if(!moderation)return {kind:'incomplete',error:'尚无可验证的公开或审核中状态'};
|
||||
// const allImages=[...body.querySelectorAll('img')];
|
||||
// const images=allImages.filter(img=>aid(img)).map(img=>({aid:aid(img),src:img.getAttribute('src'),loaded:img.complete&&img.naturalWidth>0&&!/\/none\.gif(?:[?#]|$)/.test(img.src||img.getAttribute('src')||''),file:img.getAttribute('file')||img.getAttribute('zoomfile')}));
|
||||
// const expected=(snapshot.images||[]).map(img=>String(img.aid||img.id||'').match(/(?:attachimg_|aimg_)?(\d+)$/)?.[1]).filter(Boolean);
|
||||
// const issues=[];
|
||||
// if(allImages.some(img=>!aid(img)))issues.push('正文存在无法关联附件的图片');
|
||||
// if(expected.length!==(snapshot.images||[]).length)issues.push('提交快照存在无法识别附件编号的图片');
|
||||
// if(JSON.stringify(expected)!==JSON.stringify(images.map(img=>img.aid)))issues.push('首帖正文图片引用或顺序与提交快照不一致');
|
||||
// if(images.some(img=>!img.loaded))issues.push('结果页正文图片尚未加载或加载失败');
|
||||
// if(snapshot.text&&clean(body.innerText||body.textContent)!==clean(snapshot.text))issues.push('结果正文与最终提交快照存在文字差异');
|
||||
// const attachments=post?[...post.querySelectorAll('.pattl img, .attm img')].map(img=>({aid:aid(img),src:img.getAttribute('src')})):[];
|
||||
// if(attachments.length)issues.push('结果页存在附件区图片,请核对正文位置');
|
||||
// return {kind:'accepted',thread_id,first_post_pid:pid,post_url:url,title:clean(titleNode.textContent),author_uid:[...uids][0],fid:Number([...fids][0]),state:'accepted_pending_moderation',
|
||||
// evidence:{adapter:1,thread_id,first_post_pid:pid,title:clean(titleNode.textContent),author_uid:[...uids][0],fid:Number([...fids][0]),moderation:true,images,attachments,integrity_issues:issues}};
|
||||
}
|
||||
return {inspect,clean};
|
||||
});
|
||||
+32
-15
@@ -7,7 +7,7 @@
|
||||
const owner=sessionStorage.getItem('auto-news-owner') || crypto.randomUUID();
|
||||
sessionStorage.setItem('auto-news-owner',owner);
|
||||
let run=null, working=false, halted=true, aborter=null, active=null, tickBusy=false;
|
||||
let skipBusy=false, preparation=null, stopRevision=0, resultSeenAt=0;
|
||||
let skipBusy=false, preparation=null, stopRevision=0 /*, resultSeenAt=0 */;
|
||||
const pending=new Map();
|
||||
function rpc(route,body={}) {
|
||||
return new Promise((resolve,reject)=>{
|
||||
@@ -104,7 +104,7 @@
|
||||
const snapshot=editorSnapshot();
|
||||
const local={id:active.id,snapshot,clickedAt:Date.now(),observed:false};saveLocal(local);
|
||||
rpc('event',{id:active.id,state:'user_submitting',epoch:run?.epoch,snapshot})
|
||||
.then(()=>{const latest=loadLocal();if(latest?.clickedAt===local.clickedAt)saveLocal({...local,observed:true});})
|
||||
.then(()=>{const latest=loadLocal();if(latest?.clickedAt===local.clickedAt)saveLocal({...latest,observed:true});})
|
||||
.catch(error=>status('提交记录待恢复:'+error.message));
|
||||
active.state='user_submitting';status('已观察到人工点击,等待结果页核对。');
|
||||
}catch(error){status('提交快照记录失败:'+error.message);}
|
||||
@@ -146,22 +146,24 @@
|
||||
}
|
||||
if(!['user_submitting','submit_unknown'].includes(job.state))return;
|
||||
const snapshot=job.snapshot||local?.snapshot||{};
|
||||
const result=window.DWW11Results?.inspect(document,location.href,snapshot);
|
||||
const result=(local?.id===job.id&&local.promptResult)||window.DWW11Results?.inspect(document,location.href,snapshot);
|
||||
if(result?.kind==='rejected'&&job.state==='user_submitting') {
|
||||
await rpc('event',{id:job.id,state:'rejected',error:result.error});
|
||||
status('网站明确拒绝本次提交,已暂停;核对并处理稿件后仍需亲手发表');return;
|
||||
}
|
||||
if(result?.kind==='accepted') {
|
||||
if(result.author_uid!==job.account.uid||result.fid!==job.fid||result.title!==window.DWW11Results.clean(snapshot.title)) {
|
||||
if(job.state==='user_submitting')await rpc('event',{id:job.id,state:'submit_unknown',error:'结果页标题、首帖作者或版块与提交任务不符'});
|
||||
await rpc('stop');status('结果不匹配,已暂停,请人工核对');return;
|
||||
}
|
||||
resultSeenAt ||= Date.now();
|
||||
if(result.evidence.integrity_issues.some(x=>x.includes('尚未加载'))&&Date.now()-resultSeenAt<15000) {
|
||||
status('已看到审核中详情,等待正文图片加载后核对');return;
|
||||
}
|
||||
// 暂停详情页标题、作者、版块和图文核对;保留原代码。
|
||||
// if(result?.kind==='accepted') {
|
||||
// if(result.author_uid!==job.account.uid||result.fid!==job.fid||result.title!==window.DWW11Results.clean(snapshot.title)) {
|
||||
// if(job.state==='user_submitting')await rpc('event',{id:job.id,state:'submit_unknown',error:'结果页标题、首帖作者或版块与提交任务不符'});
|
||||
// await rpc('stop');status('结果不匹配,已暂停,请人工核对');return;
|
||||
// }
|
||||
// resultSeenAt ||= Date.now();
|
||||
// if(result.evidence.integrity_issues.some(x=>x.includes('尚未加载'))&&Date.now()-resultSeenAt<15000) {
|
||||
// status('已看到审核中详情,等待正文图片加载后核对');return;
|
||||
// }
|
||||
if(result?.kind==='accepted_prompt') {
|
||||
const revision=stopRevision,epoch=run.epoch;
|
||||
await rpc('accept',{id:job.id,...result});
|
||||
await rpc('accept',{id:job.id,attempt:job.attempt,...result});
|
||||
sessionStorage.removeItem(SLOT);active=null;
|
||||
// Re-read persistent control after accounting; Stop must suppress navigation and subsequent jobs.
|
||||
run=await rpc('heartbeat',{account:account(),url:location.href,extension:extension()});
|
||||
@@ -174,9 +176,9 @@
|
||||
if(clickedAt&&Date.now()-clickedAt<45000) {
|
||||
status(result?.prompt||result?.error||'等待网站提交结果,不会重复发表');return;
|
||||
}
|
||||
if(job.state==='user_submitting')await rpc('event',{id:job.id,state:'submit_unknown',error:result?.error||'提交结果证据不足,请打开对应帖子详情后核对'});
|
||||
if(job.state==='user_submitting')await rpc('event',{id:job.id,state:'submit_unknown',error:result?.error||'未观察到网站新主题审核提示,请人工核对是否已受理'});
|
||||
if(run.running)await rpc('stop');
|
||||
status('发布结果待核对;打开对应详情页可继续核对,不会重发');
|
||||
status('未观察到网站审核提示,已暂停;请人工核对,不会重发');
|
||||
}
|
||||
async function switchAccount() {
|
||||
if(working||halted)return;
|
||||
@@ -240,5 +242,20 @@
|
||||
takeover.style.cssText='position:fixed;left:16px;top:16px;z-index:2147483646;padding:8px;background:#fff;border:1px solid #aab;border-radius:6px';
|
||||
takeover.onclick=async()=>{try{await rpc('takeover');status('已接管;核对当前页面后在工作台继续');}catch(error){status(error.message);}};
|
||||
document.body.append(takeover);
|
||||
// 提示可能短暂出现后跳转;及时保存到本次任务,避免两秒轮询漏掉。
|
||||
function capturePrompt() {
|
||||
const local=loadLocal();
|
||||
if(!local?.id||!local.snapshot||!local.clickedAt||local.promptResult)return false;
|
||||
if(active&&(active.id!==local.id||!['user_submitting','submit_unknown'].includes(active.state)))return false;
|
||||
const result=window.DWW11Results?.inspect(document,location.href,local.snapshot);
|
||||
if(result?.kind!=='accepted_prompt')return false;
|
||||
saveLocal({...local,promptResult:result});
|
||||
return true;
|
||||
}
|
||||
if(typeof MutationObserver!=='undefined')new MutationObserver(()=>{
|
||||
if(capturePrompt())void tick();
|
||||
}).observe(document.body,{childList:true,subtree:true,characterData:true});
|
||||
// 跳转后的提示页可能已经渲染完成,首次轮询前也捕获一次。
|
||||
capturePrompt();
|
||||
setInterval(tick,2000);tick();
|
||||
})();
|
||||
Reference in new issue
Block a user