Implementing a WeChat Message Anti‑Recall Feature Using Python and itchat
This tutorial demonstrates how to use Python's built‑in modules together with the third‑party itchat library to monitor, capture, and resend WeChat messages that have been withdrawn, providing step‑by‑step code and explanations for installing dependencies, handling different message types, and running the script on various operating systems.
The article explains how to create a WeChat anti‑recall tool by leveraging Python's standard libraries (os, re, time, platform) and the third‑party itchat module to intercept messages from the web version of WeChat, cache them, and forward any withdrawn content to the user's own filehelper.
First, install the required library:
pip install itchatImport the necessary modules:
import re
import os
import time
import itchat
import platform
from itchat.content import *Define a handler to process incoming messages of various types (text, picture, video, location, sharing, etc.) and store their details in a dictionary:
msg_info = {}
face_package = None
@itchat.msg_register([TEXT, PICTURE, FRIENDS, CARD, MAP, SHARING, RECORDING, ATTACHMENT, VIDEO], isFriendChat=True, isMpChat=True)
def handle_rsg(msg):
global face_package
msg_time_receive = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
try:
msg_from = itchat.search_friends(userName=msg['FromUserName'])['NickName']
except:
msg_from = 'WeChat Official Accounts'
msg_time_send = msg['CreateTime']
msg_id = msg['MsgId']
msg_content = None
msg_link = None
if msg['Type'] in ('Text', 'Friends'):
msg_content = msg['Text']
elif msg['Type'] in ('Attachment', 'Video', 'Picture', 'Recording'):
msg_content = msg['FileName']
elif msg['Type'] == 'Map':
x, y, location = re.search("<location x=\"(.*?)\" y=\"(.*?)\".*label=\"(.*?)\".*", msg['OriContent']).group(1,2,3)
msg_content = f"纬度:{x} 经度:{y}" if location is None else f"{location}"
elif msg['Type'] == 'Sharing':
msg_content = msg['Text']
msg_link = msg['Url']
msg_info.update({msg_id:{"msg_from":msg_from,"msg_time_send":msg_time_send,"msg_time_receive":msg_time_receive,"msg_type":msg['Type'],"msg_content":msg_content,"msg_link":msg_link}})
face_package = msg_contentSet up a monitor to detect recall notifications, retrieve the original message from the cache, and send it back via the filehelper account, handling both text and media types appropriately:
@itchat.msg_register(NOTE, isFriendChat=True, isGroupChat=True, isMpChat=True)
def monitor(msg):
if '撤回了一条消息' in msg['Content']:
recall_msg_id = re.search("<msgid>(.*?)</msgid>", msg['Content']).group(1)
recall_msg = msg_info.get(recall_msg_id)
if len(recall_msg_id) < 11:
itchat.send_file(face_package, toUserName='filehelper')
else:
msg_prime = f"---{recall_msg.get('msg_from')} 撤回了一条消息---\n"
msg_prime += f"消息类型:{recall_msg.get('msg_type')}\n"
msg_prime += f"时间:{recall_msg.get('msg_time_receive')}\n"
msg_prime += f"内容:{recall_msg.get('msg_content')}\n"
if recall_msg['msg_type'] == 'Sharing':
msg_prime += f"链接:{recall_msg.get('msg_link')}\n"
itchat.send_msg(msg_prime, toUserName='filehelper')
if recall_msg['msg_type'] in ('Attachment','Video','Picture','Recording'):
file = f"@fil@{recall_msg['msg_content']}"
itchat.send(msg=file, toUserName='filehelper')
os.remove(recall_msg['msg_content'])
msg_info.pop(recall_msg_id, None)Finally, run the script with platform‑specific login options and start the itchat event loop:
if __name__ == '__main__':
if platform.platform()[:7] == 'Windows':
itchat.auto_login(enableCmdQR=False, hotReload=True)
else:
itchat.auto_login(enableCmdQR=True, hotReload=True)
itchat.run()Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.