from pathlib import Path root = Path('C:/wechat_rpa') path = root / 'protocol_engine.py' text = path.read_text(encoding='utf-8') def replace(old,new,count=1): global text assert text.count(old)==count,(str(path),old[:90],text.count(old),count) text=text.replace(old,new) replace('def _restore_review_details(state):', '''def _send_protection(state): """Use either durable field; missing/old schema must not enable a replay.""" status=str(state.get('send_state') or '') stage=str(state.get('stage') or '') if status=='sending' or stage=='sending':return 'sending' if status in ('uncertain','unknown','sent_uncommitted') or stage in ('receipt_check','uncertain','unknown'): return 'uncertain' if status=='failed' or stage=='failed':return 'failed' return 'uncertain' if status else '' def _restore_review_details(state):''') replace(" if state.get('send_state')=='sending':state.update(send_state='uncertain',stage='receipt_check',last_error='上次发送结果待核对,禁止自动重发')", " if _send_protection(state) in ('sending','uncertain'):state.update(send_state='uncertain',stage='receipt_check',last_error=state.get('last_error') or '上次发送结果待核对,禁止自动重发')") replace("s.get('send_state')=='uncertain'", "_send_protection(s)=='uncertain'",2) replace("if old and old.get('send_state') in ('sending','uncertain','failed'):return", "if old and _send_protection(old):return") replace("if state.get('send_state') in ('sending','uncertain','failed') or state.get('stage')=='error':return", "if _send_protection(state) or state.get('stage')=='error':return") replace("if s.get('send_state') in ('sending','uncertain','failed'):result['protected'].append(key);continue", "if _send_protection(s):result['protected'].append(key);continue") replace("if self._pending.get(key) is state:state['send_state']='';self._save()", "if self._pending.get(key) is state:state.update(send_state='',stage='queued',stage_detail='发送前检查已取消,等待重新核对');self._save()") replace(' def handoff_pending_replies(self, keys):', ' def handoff_pending_replies(self, keys, *, confirm_uncertain=False):') replace(" result={'handed_off':[], 'deleted':[], 'missing':[], 'protected':[], 'scheduled':[]}", " result={'handed_off':[], 'deleted':[], 'missing':[], 'protected':[], 'scheduled':[], 'requires_confirmation':[]}") replace(" if state.get('account')!=self.account or state.get('send_state')=='sending':\n result['protected'].append(key);continue", """ protection=_send_protection(state) if state.get('account')!=self.account or protection=='sending': result['protected'].append(key);continue if protection=='uncertain' and not confirm_uncertain: result['protected'].append(key);result['requires_confirmation'].append(key);continue""") compile(text,str(path),'exec') path.write_text(text,encoding='utf-8') for root in (Path('C:/wechat_rpa'),Path('C:/kefu/wechat_rpa')): path=root/'gui_runtime.py' text=path.read_text(encoding='utf-8') replace('def delete_pending_reply_file(keys, path="", *, handoff=False):', 'def delete_pending_reply_file(keys, path="", *, handoff=False, confirm_uncertain=False):') replace(' result = {"deleted": [], "missing": sorted(requested), "protected": [], "scheduled": []}\n if not requested:', ' result = {"deleted": [], "missing": sorted(requested), "protected": [], "scheduled": []}\n if handoff:\n result["requires_confirmation"] = []\n if not requested:') replace(' if handoff and str(state.get("send_state") or "") == "sending":\n result["protected"].append(key)\n continue', ''' send_state = str(state.get("send_state") or "") stage = str(state.get("stage") or "") sending = send_state == "sending" or stage == "sending" uncertain = send_state in {"uncertain", "sent_uncommitted", "unknown"} or stage in {"receipt_check", "uncertain", "unknown"} if sending or (uncertain and not (handoff and confirm_uncertain)): result["protected"].append(key) if handoff and uncertain and not sending: result["requires_confirmation"].append(key) continue''') replace('def handoff_pending_reply_file(keys, path=""):', 'def handoff_pending_reply_file(keys, path="", *, confirm_uncertain=False):') replace(' result = delete_pending_reply_file(keys, path, handoff=True)', ' result = delete_pending_reply_file(keys, path, handoff=True, confirm_uncertain=confirm_uncertain)') replace(' self._queued_handoffs = set()', ' self._queued_handoffs = set()\n self._queued_handoff_confirmations = set()') replace(' def _handoff_bot_tasks(bot, keys):', ' def _handoff_bot_tasks(bot, keys, *, confirm_uncertain=False):') replace(' return handoff(keys)', ' return handoff(keys, confirm_uncertain=confirm_uncertain)') replace(' def handoff_pending_tasks(self, keys):', ' def handoff_pending_tasks(self, keys, *, confirm_uncertain=False):') replace(' self._queued_handoffs.update(requested)\n return', ' self._queued_handoffs.update(requested)\n if confirm_uncertain:\n self._queued_handoff_confirmations.update(requested)\n return') replace(' return self._handoff_bot_tasks(bot, requested)', ' return self._handoff_bot_tasks(bot, requested, confirm_uncertain=confirm_uncertain)') replace(' requested = set(self._queued_handoffs)\n self._queued_handoffs.clear()\n if requested:\n self._handoff_bot_tasks(bot, requested)', ''' requested = set(self._queued_handoffs) confirmed = requested & self._queued_handoff_confirmations self._queued_handoffs.clear() self._queued_handoff_confirmations.clear() if requested - confirmed: self._handoff_bot_tasks(bot, requested - confirmed, confirm_uncertain=False) if confirmed: self._handoff_bot_tasks(bot, confirmed, confirm_uncertain=True)''') compile(text,str(path),'exec') path.write_text(text,encoding='utf-8') print('Both runtimes and protocol engine now require explicit uncertainty confirmation and protect stage-only sends.')