首頁 > 軟體

撤回我也能看到!教你用Python製作微信防撤回指令碼

2021-06-11 19:01:48

一、之前解決方案

大概是這樣:短時間內同一位好友傳送了多條訊息,當他隨便撤回一條訊息時,我們不能確定他到底撤回的到底是哪一條訊息。只能猜他可能是撤回了最近的一條訊息,然後將其他訊息貼出來作為備選。程式碼如下:

target_msg_pattern = '"{}" 撤回了一條訊息'.format(sender_name)
if content == target_msg_pattern:
    return_msg = '【{}】撤回了一條訊息:n'.format(sender_name)
    if len(log[sender_name].items()) == 0:
        return_msg = '快取資訊列表為空!'
    else:
        return_msg += log[sender_name].items()[-1][-1] + 'n'
        if len(log[sender_name].items()) > 1:
            msgs = [msg for timestamp, msg in log[sender_name].items()[:-1]]
            return_msg += '也有可能是下列資訊中的某一條:n' + 'n'.join(msgs)

實際效果是這樣:


 

我這個強迫症簡直受不了這麼不確定的說法。

二、分析msg資訊

要想確定撤回了哪一條資訊,就必須先熟悉普通msg和撤回的msg裡面都有哪些資訊,他們的相同點和不同點。下面就來看看這兩種情況下msg都是怎麼樣的,不需要仔細的看每一行,後面會作具體分析。

先是用機器人「小幫幫」傳送過來的資訊得到的msg資訊:

{
	'MsgId': '2018511155698964390',
	'FromUserName': '@**********f511363f8200853d724137bb31236a7ea81e5183cc06cb4ec978e3',
	'ToUserName': '@**********c2e61fdb47b5c241553a2f',
	'MsgType': 1,
	'Content': 'msg裡面到底有什麼?',
	'Status': 3,
	'ImgStatus': 1,
	'CreateTime': 1578069291,
	'VoiceLength': 0,
	'PlayLength': 0,
	'FileName': '',
	'FileSize': '',
	'MediaId': '',
	'Url': '',
	'AppMsgType': 0,
	'StatusNotifyCode': 0,
	'StatusNotifyUserName': '',
	'RecommendInfo': {
		'UserName': '',
		'NickName': '',
		'QQNum': 0,
		'Province': '',
		'City': '',
		'Content': '',
		'Signature': '',
		'Alias': '',
		'Scene': 0,
		'VerifyFlag': 0,
		'AttrStatus': 0,
		'Sex': 0,
		'Ticket': '',
		'OpCode': 0
	},
	'ForwardFlag': 0,
	'AppInfo': {
		'AppID': '',
		'Type': 0
	},
	'HasProductId': 0,
	'Ticket': '',
	'ImgHeight': 0,
	'ImgWidth': 0,
	'SubMsgType': 0,
	'NewMsgId': 2018511155698964390,
	'OriContent': '',
	'EncryFileName': '',
	'User': < User: {
		'MemberList': < ContactList: [] > ,
		'Uin': 0,
		'UserName': '@**********f511363f8200853d724137bb31236a7ea81e5183cc06cb4ec978e3',
		'NickName': '小幫幫',
		'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=699837854&[email protected]**********f511363f8200853d724137bb31236a7ea81e5183cc06cb4ec978e3&[email protected]_****c00c_92668c8ba7d285c221a85e**********',
		'ContactFlag': 2049,
		'MemberCount': 0,
		'RemarkName': '小幫幫',
		'HideInputBarFlag': 0,
		'Sex': 2,
		'Signature': '',
		'VerifyFlag': 0,
		'OwnerUin': 0,
		'PYInitial': 'XBB',
		'PYQuanPin': 'xiaobangbang',
		'RemarkPYInitial': 'XBB',
		'RemarkPYQuanPin': 'xiaobangbang',
		'StarFriend': 0,
		'AppAccountFlag': 0,
		'Statues': 0,
		'AttrStatus': 33658937,
		'Province': '浙江',
		'City': '台州',
		'Alias': '',
		'SnsFlag': 17,
		'UniFriend': 0,
		'DisplayName': '',
		'ChatRoomId': 0,
		'KeyWord': '',
		'EncryChatRoomId': '',
		'IsOwner': 0
	} > ,
	'Type': 'Text',
	'Text': 'msg裡面到底有什麼?'
}

下面是機器人撤回剛才的資訊得到的msg資訊:

{
	'MsgId': '4056955577161654067',
	'FromUserName': '@**********f511363f8200853d724137bb31236a7ea81e5183cc06cb4ec978e3',
	'ToUserName': '@**********c2e61fdb47b5c241553a2f',
	'MsgType': 10002,
	'Content': '<sysmsg type="revokemsg"><revokemsg><session>wxid_4gngrr04aqjn21</session><oldmsgid>1123721956</oldmsgid><msgid>2018511155698964390</msgid><replacemsg><![CDATA["小幫幫" 撤回了一條訊息]]></replacemsg></revokemsg></sysmsg>',
	'Status': 4,
	'ImgStatus': 1,
	'CreateTime': 1578069381,
	'VoiceLength': 0,
	'PlayLength': 0,
	'FileName': '',
	'FileSize': '',
	'MediaId': '',
	'Url': '',
	'AppMsgType': 0,
	'StatusNotifyCode': 0,
	'StatusNotifyUserName': '',
	'RecommendInfo': {
		'UserName': '',
		'NickName': '',
		'QQNum': 0,
		'Province': '',
		'City': '',
		'Content': '',
		'Signature': '',
		'Alias': '',
		'Scene': 0,
		'VerifyFlag': 0,
		'AttrStatus': 0,
		'Sex': 0,
		'Ticket': '',
		'OpCode': 0
	},
	'ForwardFlag': 0,
	'AppInfo': {
		'AppID': '',
		'Type': 0
	},
	'HasProductId': 0,
	'Ticket': '',
	'ImgHeight': 0,
	'ImgWidth': 0,
	'SubMsgType': 0,
	'NewMsgId': 4056955577161654067,
	'OriContent': '',
	'EncryFileName': '',
	'User': < User: {
		'MemberList': < ContactList: [] > ,
		'Uin': 0,
		'UserName': '@**********f511363f8200853d724137bb31236a7ea81e5183cc06cb4ec978e3',
		'NickName': '小幫幫',
		'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=699837854&[email protected]**********f511363f8200853d724137bb31236a7ea81e5183cc06cb4ec978e3&[email protected]_****c00c_92668c8ba7d285c221a85e**********',
		'ContactFlag': 2049,
		'MemberCount': 0,
		'RemarkName': '小幫幫',
		'HideInputBarFlag': 0,
		'Sex': 2,
		'Signature': '',
		'VerifyFlag': 0,
		'OwnerUin': 0,
		'PYInitial': 'XBB',
		'PYQuanPin': 'xiaobangbang',
		'RemarkPYInitial': 'XBB',
		'RemarkPYQuanPin': 'xiaobangbang',
		'StarFriend': 0,
		'AppAccountFlag': 0,
		'Statues': 0,
		'AttrStatus': 33658937,
		'Province': '浙江',
		'City': '台州',
		'Alias': '',
		'SnsFlag': 17,
		'UniFriend': 0,
		'DisplayName': '',
		'ChatRoomId': 0,
		'KeyWord': '',
		'EncryChatRoomId': '',
		'IsOwner': 0
	} > ,
	'Type': 'Note',
	'Text': '"小幫幫" 撤回了一條訊息'
}

得到了兩種型別的msg,下面是對比(高亮的部分是不同處,省略了部分相同內容。可以點選放大檢視大圖

現在來分析幾條關鍵資訊:

  • MsgId(與下面的NewMsgId同)
  • 訊息編號。這個很好理解,每條訊息都是通過一個獨一無二的編號來與其他訊息區分,所以這兩條訊息的編號不同很正常。如果我們能拿到好友撤回訊息的編號,也就能鎖定這條訊息了。
  • MsgType(與下面的Type同)
  • 訊息型別。如下圖,左邊是普通的對話訊息,右邊類似於系統提示訊息。是不是可以根據這條資訊來判斷是不是有好友撤回了訊息?

Content

訊息內容,注意與下面的Text區分,這兩種訊息型別在內容上最大的區別可能就在這裡了。

來看一下撤回訊息的Content是怎麼樣的(為了便於檢視,已經經過格式化)

<sysmsg type="revokemsg">
    <revokemsg>
        <session>wxid_4gngrr04aqjn21</session>
        <oldmsgid>1123721956</oldmsgid>
        <msgid>2018511155698964390</msgid>
        <replacemsg><![CDATA["小幫幫" 撤回了一條訊息]]></replacemsg>
    </revokemsg>
</sysmsg>

一眼就能發現關鍵點:撤回的那條訊息屬於系統訊息(sysmsg),型別是撤回訊息(revokemsg),對應的訊息編號是2018511155698964390

細心的讀者已經發現,這個訊息編號正好就是左邊那條訊息的編號。

通過這個推理,猜測Content欄位是系統內部傳輸的內容,而Text欄位則是使用者看到的內容。

三、確定訊息型別

根據上述分析,有三個地方幫助確定收到的某條資訊是否是撤回的訊息:

1.MsgType

1就是普通訊息,是10002則可能為撤回訊息。

2.Content

如果Content裡有包含type="revokemsg"則可能為撤回訊息,否則不是撤回訊息。

3.Type

是Text就是普通訊息,是Note則可能為撤回訊息。

精確起見,訊息還要同時滿足上面三種情況才可認定為撤回訊息。

四、鎖定撤回的訊息

由於要鎖定撤回訊息必須要MsgId才能確定,所以在儲存臨時訊息時需要加上這一欄位。

log[sender_name][cur_timestamp] = msg['MsgId'] + '|||' + content

為了簡化資料複雜度,我通過分隔符|||直接把MsgId加在前面。

於是,鎖定並行送撤回訊息的程式碼就時這樣:

content = str(msg['Text'])
revoke_info = msg['Content']
print('{}, {} 發來訊息: {}'.format(formatted_timestamp, sender_name, content))
target_msg_pattern = '"{}" 撤回了一條訊息'.format(sender_name)
if target_msg_pattern == content and msg['Type'] == 'Note' and str(msg['MsgType']) == '10002' and 'type="revokemsg"' in revoke_info:
    return_msg = ''
    return_msg_head = '{},【{}】撤回了一條訊息:n'.format(formatted_timestamp, sender_name)
    revoke_msg_id = revoke_info.split('<msgid>')[-1].split('</msgid>')[0]
    for _, value in log[sender_name].items():
        if value.split('|||')[0] == revoke_msg_id:
            return_msg = value.split('|||')[1]
    if return_msg == '':
        return_msg = '快取資訊列表為空!'
    return_msg = return_msg_head + return_msg
    print(return_msg)
    itchat.send_msg(return_msg, 'filehelper')

測試一下,為便於檢視,將撤回提醒直接發給機器人「小幫幫」

 

一個完美的微信防撤回指令碼大功告成!

五、結語

Python有很多好用好玩的庫,可以慢慢發掘。本期我們利用ItChat庫編寫了一個微信防撤回指令碼。其實ItChat功能遠遠不止這些,它還可以處理微信群訊息以及各種其他型別的訊息,我們講到的只是九牛一毛,更多的還要大家自己去探索。

到此這篇關於撤回我也能看到!教你用Python製作微信防撤回指令碼的文章就介紹到這了,更多相關Python微信防撤回指令碼內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com