初学python–微信防撤回功能改进(一个用处不大的功能)

真真是遇到一个好玩的python库,可以玩好几天。

上上篇文章中使用itchat对消息进行实时备份和自动回复,同时兼顾防撤回功能,但是有个知友说了:你这防撤回功能代价太大了,要把所有的消息都备份一遍。确实,我也觉得这么做太傻*。想了想看能不能有什么好一点的办法,最起码别这么笨重。

为什么说这是个用处不大的功能,文末再说。

这个功能实现也很简单(实话.mp3->我就不会写难的),120行代码就可以实现。大家可以拿来练练手。

老规矩,使用的库itchat、re、time、shutil、os

实现思路,将接收到的消息都存进一个字典(msg_dict),接收到撤回通知时,提取撤回消息的id,从字典中进行比对,然后发送、保存。那么字典能放得下那么多消息吗?当接收到新消息时,执行函数对字典中超过两分钟的消息进行清理(两分钟内消息不会很多)。

对于四种消息:图片、语音、附件、视频 这些不像文字一样、没法直观看见消息内容。于是收到消息后,将这些消息内容下载缓存,超过两分钟进行删除。同时,如果撤回这些消息的话,便将相应的消息内容保存到另一文件夹中,并发送消息到文件助手进行通知。

文件助手的通知

初学python--微信防撤回功能改进(一个用处不大的功能)PC保存的文件(图片、视频、附件、语音):

初学python--微信防撤回功能改进(一个用处不大的功能)

这个过程中踩到的坑:

1. 对于字典:在使用for item in msg_dict.keys() 进行遍历时,不能进行增删操作,否则报错
2. 注意做好异常处理和细节处理
3.

if item['msg_type'] == "Picture" /
                        or item['msg_type'] == "Recording" /
                        or item['msg_type'] == "Video" /
                        or item['msg_type'] == "Attachment":

上面的消息,如果写在一行中,错误不容易找出来。

对于发送的比较大的附件或视频,大家可以判断一下大小再决定要不要保存。

代码里写的注释写的比较详细,大家看代码:

# -*-encoding:utf-8-*-
import os
import re
import shutil
import time
import itchat
from itchat.content import *

# {msg_id:(msg_from,msg_to,msg_time,msg_time_touser,msg_type,msg_content,msg_url)}
msg_dict = {}

#ClearTimeOutMsg用于清理消息字典,把超时消息清理掉
#为减少资源占用,此函数只在有新消息动态时调用
def ClearTimeOutMsg():
    if msg_dict.__len__() > 0:
        for msgid in list(msg_dict): #由于字典在遍历过程中不能删除元素,故使用此方法
            if time.time() - msg_dict.get(msgid, None)["msg_time"] > 130.0: #超时两分钟
                item = msg_dict.pop(msgid)
                #print("超时的消息:", item['msg_content'])
                #可下载类消息,并删除相关文件
                if item['msg_type'] == "Picture" /
                        or item['msg_type'] == "Recording" /
                        or item['msg_type'] == "Video" /
                        or item['msg_type'] == "Attachment":
                    print("要删除的文件:", item['msg_content'])
                    os.remove(item['msg_content'])

#将接收到的消息存放在字典中,当接收到新消息时对字典中超时的消息进行清理
#没有注册note(通知类)消息,通知类消息一般为:红包 转账 消息撤回提醒等,不具有撤回功能
@itchat.msg_register([TEXT, PICTURE, MAP, CARD, SHARING, RECORDING, ATTACHMENT, VIDEO, FRIENDS])
def Revocation(msg):
    mytime = time.localtime()  # 这儿获取的是本地时间
    #获取用于展示给用户看的时间 2017/03/03 13:23:53
    msg_time_touser = mytime.tm_year.__str__() /
                      + "/" + mytime.tm_mon.__str__() /
                      + "/" + mytime.tm_mday.__str__() /
                      + " " + mytime.tm_hour.__str__() /
                      + ":" + mytime.tm_min.__str__() /
                      + ":" + mytime.tm_sec.__str__()

    msg_id = msg['MsgId'] #消息ID
    msg_time = msg['CreateTime'] #消息时间
    msg_from = itchat.search_friends(userName=msg['FromUserName'])['NickName'] #消息发送人昵称
    msg_type = msg['Type'] #消息类型
    msg_content = None #根据消息类型不同,消息内容不同
    msg_url = None #分享类消息有url
    #图片 语音 附件 视频,可下载消息将内容下载暂存到当前目录
    if msg['Type'] == 'Text':
        msg_content = msg['Text']
    elif msg['Type'] == 'Picture':
        msg_content = msg['FileName']
        msg['Text'](msg['FileName'])
    elif msg['Type'] == 'Card':
        msg_content = msg['RecommendInfo']['NickName'] + r" 的名片"
    elif msg['Type'] == 'Map':
        x, y, location = re.search("<location x=/"(.*?)/" y=/"(.*?)/".*label=/"(.*?)/".*", msg['OriContent']).group(1,
                                                                                                                    2,
                                                                                                                    3)
        if location is None:
            msg_content = r"纬度->" + x.__str__() + " 经度->" + y.__str__()
        else:
            msg_content = r"" + location
    elif msg['Type'] == 'Sharing':
        msg_content = msg['Text']
        msg_url = msg['Url']
    elif msg['Type'] == 'Recording':
        msg_content = msg['FileName']
        msg['Text'](msg['FileName'])
    elif msg['Type'] == 'Attachment':
        msg_content = r"" + msg['FileName']
        msg['Text'](msg['FileName'])
    elif msg['Type'] == 'Video':
        msg_content = msg['FileName']
        msg['Text'](msg['FileName'])
    elif msg['Type'] == 'Friends':
        msg_content = msg['Text']

    #更新字典
    # {msg_id:(msg_from,msg_time,msg_time_touser,msg_type,msg_content,msg_url)}
    msg_dict.update(
        {msg_id: {"msg_from": msg_from, "msg_time": msg_time, "msg_time_touser": msg_time_touser, "msg_type": msg_type,
                  "msg_content": msg_content, "msg_url": msg_url}})
    #清理字典
    ClearTimeOutMsg()

#收到note类消息,判断是不是撤回并进行相应操作
@itchat.msg_register([NOTE])
def SaveMsg(msg):
    # print(msg)
    #创建可下载消息内容的存放文件夹,并将暂存在当前目录的文件移动到该文件中
    if not os.path.exists(".//Revocation//"):
        os.mkdir(".//Revocation//")

    if re.search(r"/<replacemsg/>/</!/[CDATA/[.*撤回了一条消息/]/]/>/<//replacemsg/>", msg['Content']) != None:
        old_msg_id = re.search("/<msgid/>(.*?)/<//msgid/>", msg['Content']).group(1)
        old_msg = msg_dict.get(old_msg_id, {})
        #print(old_msg_id, old_msg)
        msg_send = r"您的好友:" /
                   + old_msg.get('msg_from', None) /
                   + r"  在 [" + old_msg.get('msg_time_touser', None) /
                   + r"], 撤回了一条 ["+old_msg['msg_type']+"] 消息, 内容如下:" /
                   + old_msg.get('msg_content', None)
        if old_msg['msg_type'] == "Sharing":
            msg_send += r", 链接: " /
                        + old_msg.get('msg_url', None)
        elif old_msg['msg_type'] == 'Picture' /
                or old_msg['msg_type'] == 'Recording' /
                or old_msg['msg_type'] == 'Video' /
                or old_msg['msg_type'] == 'Attachment':
            msg_send += r", 存储在当前目录下Revocation文件夹中"
            shutil.move(old_msg['msg_content'], r".//Revocation//")
        itchat.send(msg_send, toUserName='filehelper') #将撤回消息的通知以及细节发送到文件助手

        msg_dict.pop(old_msg_id)
        ClearTimeOutMsg()

if __name__ == '__main__':
    itchat.auto_login(hotReload=True)
    itchat.run()

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/aiops/55129.html

(0)
上一篇 2021年8月7日 06:47
下一篇 2021年8月7日 06:47

相关推荐

发表回复

登录后才能评论