Mac 微信是有一个消息通知的,这一点就挺好的,有时候根本不用点开开看就能看到消息内容。而 Windows 电脑版是没有这个消息通知的,只有右下角图标闪烁。
于是我想了不少的办法去实现这么一个功能,已经另辟蹊径实现了这个功能,其实也有一定的局限性,但是能满足办公期间的小需求。
效果如下:
接收通知
首先是 Windows 的通知弹出的实现就是 Windows 自带的通知栏,我们可以通过 Python 去调用 Windows API 去发送 Windows 通知,让消息弹出来。
发送通知
相比于接收通知,那么发送通知就比较困难,因为 Windows 微信电脑版的窗口属于非 Windows 窗口标准,我们无法通过常规的方式去读取每个控件的内容,更无法监听到通知内容,所以我这边另辟蹊径,通过安卓手机去监听微信消息。
所以这里用到了 SmsForwarder 这款开源软件,安装在你的安卓手机上,然后设置转发规则,监听微信 APP 的通知,然后发送通道选择 WebHook ,将监听到的消息 POST 到 Python 开启的 HTTP 服务器,触发 Windows 通知就行了!
from flask import Flask, request
from winotify import Notification
import urllib.parse
import win32gui
import win32con
app = Flask(__name__)
@app.route('/') # 获取 url 信息
def getUrlInfo():
# 完整 url
url = request.url
# 主机部分
hostUrl = request.host_url
# 访问路径
fullPath = request.full_path
# 输出
print('收到推送任务,推送内容是:'+str(urllib.parse.unquote(fullPath.split("/?")[1])).replace('+', ' ', 1))
# 接收到的内容
content = str(urllib.parse.unquote(fullPath.split("/?")[1])).replace('+', ' ', 1);
# 错误处理
# 因为监听软件那边监听到的首条消息是没有带上微信用户昵称的
# 所以需要判断当前接收到的消息是不是首条消息
# 如果不做这一步就会出错
pdmh = ":" in content
if pdmh == True:
# 截取:前面的内容
qianmian = content.split(":")[0]
weixinMsg = content.split(":")[1]
# 还要将[]这一块也去掉,这就提取到了微信昵称
nickname = qianmian.split("]")[1]
else:
nickname = '微信消息通知'
weixinMsg = content
# 开发 Push 通知
# toaster = ToastNotifier()
# toaster.show_toast(title=nickname, msg=weixinMsg,icon_path="logo.ico", duration=5)
toast = Notification(app_id="通知中心",title=nickname,msg=weixinMsg,icon=r"D:\Python\demo\wechat.png")
toast.show()
return "ok"
def notify(hwnd, msg, wparam, lparam):
print("notify", msg)
if lparam == win32con.WM_LBUTTONDBLCLK: # 双击左键
print("双击左键", msg)
pass
elif lparam == win32con.WM_RBUTTONUP: # 右键弹起
print("右键弹起", msg)
pass
elif lparam == win32con.WM_LBUTTONUP: # 左键弹起
print("左键弹起", msg)
pass
return True
wc = win32gui.WNDCLASS()
wc.hInstance = win32gui.GetModuleHandle(None)
wc.lpszClassName = "Windows 通知中心"
wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW;
wc.lpfnWndProc = notify
classAtom = win32gui.RegisterClass(wc)
hwnd =win32gui.CreateWindow(classAtom,"tst2",win32con.WS_OVERLAPPEDWINDOW,win32con.CW_USEDEFAULT,win32con.CW_USEDEFAULT,win32con.CW_USEDEFAULT,win32con.CW_USEDEFAULT,None,None,None,None)
notify_id = (hwnd,0,win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP,win32con.WM_USER + 20,win32gui.LoadIcon(0, win32con.IDI_APPLICATION),"Windows 通知中心")
win32gui.Shell_NotifyIcon(0,notify_id)
# 在指定 IP 和端口开启 HTTP 服务
if __name__ == '__main__':
app.run(debug=False,host='192.168.1.100', port=8080)
192.168.1.100 是我电脑的内网 ip ,8080 是端口号,你需要获取你电脑的内网 ip 换上去,不然后续配置安卓那边的监听转发端就无法正常转发通知。
执行代码后,会在你电脑开启一个 HTTP 服务,这时候你可以在浏览器进行本地测试,在浏览器按照以下格式粘贴:
http://内网 ip:端口号 /?通知内容
安装 SmsForwarder 这款软件。
下载地址: https://gitee.com/pp/SmsForwarder/releases/tag/v3.0.8
设置发送通道,选择 Webhook ,Webserver 按照以下格式填写:
http://内网 ip:端口号 /
WebParams 直接填写 [msg] ,请求方式是 GET
设置转发规则,添加规则,选择匹配 “APP 包名”,匹配模式选择 “是”,匹配值是 com.tencent.mm ,选择刚才配置的发送通道,自定义模板直接点击通知内容。
简单进行配置后,SmsForwarder 进行一些必要的设置后,就可以正常使用了。
目前还在想办法在电脑本地监听微信消息,毕竟通过安卓手机监听消息也不是办法,一方面是依赖本地的服务器,通过局域网才可以发送通知给电脑。另一方面就是安卓监听消息也不具备稳定性,而且也不是人人都用安卓,对于苹果手机的用户,也是难以实现这个。
内网 ip 可能会变化,如果你发现后面无法正常接收到通知,可以检查下内网 ip ,更换一下 ip 重启服务。
因为这是使用内网 ip 实现的 HTTP 服务,所以你安卓手机需要连接的 wifi 与电脑的一致,如果电脑是有线网络,那么你手机需要与电脑有线网络同一个网络环境,即 ip 相同。
如果不想通过局域网实现,可以自己配置内网穿透服务去实现外网请求服务。
自写 Hook 微信,读取内存去监听微信消息
使用现成的方案,市面上也有一些 Hook 微信的框架,例如可爱猫,这个框架提供了非常便利的 SDK 去调用 API 来监听微信聊天消息,甚至还可以做到发送消息。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.