mirror of
https://github.com/smallevilbeast/ntchat.git
synced 2025-12-14 04:17:44 +08:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da155c82e3 | ||
|
|
92364c1e65 | ||
|
|
90c824d0b0 | ||
|
|
330f0724f3 | ||
|
|
38506a0e7b | ||
|
|
f7fb727257 | ||
|
|
ae450372b1 | ||
|
|
734eab020e | ||
|
|
89ea755606 | ||
|
|
cdaacf186b | ||
|
|
cd51f463bc | ||
|
|
99ac6bf007 | ||
|
|
476e8428cb |
12
README.md
12
README.md
|
|
@ -1,6 +1,6 @@
|
||||||
<h1 align="center">NtChat</h1>
|
<h1 align="center">NtChat</h1>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/smallevilbeast/ntchat/releases"><img src="https://img.shields.io/badge/release-0.1.13-blue.svg?" alt="release"></a>
|
<a href="https://github.com/smallevilbeast/ntchat/releases"><img src="https://img.shields.io/badge/release-0.1.17-blue.svg?" alt="release"></a>
|
||||||
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-brightgreen.svg?" alt="License"></a>
|
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-brightgreen.svg?" alt="License"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
@ -20,7 +20,6 @@
|
||||||
- 查看 [常见问题](docs/FAQ.md)
|
- 查看 [常见问题](docs/FAQ.md)
|
||||||
- 查看 [常用示例](examples)
|
- 查看 [常用示例](examples)
|
||||||
- 查看 [NtChatHttp接口示例](fastapi_example)
|
- 查看 [NtChatHttp接口示例](fastapi_example)
|
||||||
- 加入群聊 [PyXCGUI&NtChat交流群](https://jq.qq.com/?_wv=1027&k=oIXzbTbI)
|
|
||||||
- 查看 [PyXCGUI项目](https://github.com/smallevilbeast/pyxcgui)
|
- 查看 [PyXCGUI项目](https://github.com/smallevilbeast/pyxcgui)
|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
@ -146,7 +145,7 @@ except KeyboardInterrupt:
|
||||||
# -*- coding: utf8 -*-
|
# -*- coding: utf8 -*-
|
||||||
import xcgui
|
import xcgui
|
||||||
import ntchat
|
import ntchat
|
||||||
from xcgui import XApp, XWindow
|
from xcgui import XApp, XWindow, RunUiThread
|
||||||
|
|
||||||
|
|
||||||
class NtChatWindow(XWindow):
|
class NtChatWindow(XWindow):
|
||||||
|
|
@ -171,6 +170,8 @@ class NtChatWindow(XWindow):
|
||||||
def on_btn_open_clicked(self, sender, _):
|
def on_btn_open_clicked(self, sender, _):
|
||||||
self.wechat_instance = ntchat.WeChat()
|
self.wechat_instance = ntchat.WeChat()
|
||||||
self.wechat_instance.open(smart=True)
|
self.wechat_instance.open(smart=True)
|
||||||
|
|
||||||
|
# 监听所有通知消息
|
||||||
self.wechat_instance.on(ntchat.MT_ALL, self.on_recv_message)
|
self.wechat_instance.on(ntchat.MT_ALL, self.on_recv_message)
|
||||||
|
|
||||||
def on_btn_send_clicked(self, sender, _):
|
def on_btn_send_clicked(self, sender, _):
|
||||||
|
|
@ -182,6 +183,7 @@ class NtChatWindow(XWindow):
|
||||||
else:
|
else:
|
||||||
self.wechat_instance.send_text(self.edit_wxid.getText(), self.edit_content.getText())
|
self.wechat_instance.send_text(self.edit_wxid.getText(), self.edit_content.getText())
|
||||||
|
|
||||||
|
@RunUiThread()
|
||||||
def on_recv_message(self, wechat, message):
|
def on_recv_message(self, wechat, message):
|
||||||
text = self.edit_log.getText()
|
text = self.edit_log.getText()
|
||||||
text += "\n"
|
text += "\n"
|
||||||
|
|
@ -199,7 +201,3 @@ if __name__ == '__main__':
|
||||||
app.exit()
|
app.exit()
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
帮助&支持
|
|
||||||
-------------------------
|
|
||||||
点击链接加入群聊 [PyXCGUI&NtChat交流群](https://jq.qq.com/?_wv=1027&k=oIXzbTbI)
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import xcgui
|
import xcgui
|
||||||
import ntchat
|
import ntchat
|
||||||
from xcgui import XApp, XWindow
|
from xcgui import XApp, XWindow, RunUiThread
|
||||||
|
|
||||||
|
|
||||||
class NtChatWindow(XWindow):
|
class NtChatWindow(XWindow):
|
||||||
|
|
@ -38,6 +38,7 @@ class NtChatWindow(XWindow):
|
||||||
else:
|
else:
|
||||||
self.wechat_instance.send_text(self.edit_wxid.getText(), self.edit_content.getText())
|
self.wechat_instance.send_text(self.edit_wxid.getText(), self.edit_content.getText())
|
||||||
|
|
||||||
|
@RunUiThread()
|
||||||
def on_recv_message(self, wechat, message):
|
def on_recv_message(self, wechat, message):
|
||||||
text = self.edit_log.getText()
|
text = self.edit_log.getText()
|
||||||
text += "\n"
|
text += "\n"
|
||||||
|
|
|
||||||
18
examples/show_login_qrcode.py
Normal file
18
examples/show_login_qrcode.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import ntchat
|
||||||
|
|
||||||
|
|
||||||
|
def version_tuple(v):
|
||||||
|
return tuple(map(int, (v.split("."))))
|
||||||
|
|
||||||
|
|
||||||
|
if version_tuple(ntchat.__version__) < version_tuple('0.1.15'):
|
||||||
|
print("error: ntchat version required 0.1.15, use `pip install -U ntchat` to upgrade")
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
wechat = ntchat.WeChat()
|
||||||
|
|
||||||
|
# 打开一个新的微信,并显示二维码界面
|
||||||
|
wechat.open(smart=False, show_login_qrcode=True)
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import ntchat
|
|
||||||
|
|
||||||
wechat = ntchat.WeChat()
|
|
||||||
|
|
||||||
# 打开pc微信, smart: 是否管理已经登录的微信
|
|
||||||
wechat.open(smart=True)
|
|
||||||
|
|
||||||
# 等待登录
|
|
||||||
wechat.wait_login()
|
|
||||||
|
|
||||||
# 获取群列表并输出
|
|
||||||
room_wxid = wechat.get_rooms()[0]["wxid"]
|
|
||||||
|
|
||||||
|
|
||||||
def get_room_name(wechat: ntchat.WeChat, room_wxid: str):
|
|
||||||
sql = f"select nickname from contact where username='{room_wxid}'"
|
|
||||||
result = wechat.sql_query(sql, 1)["result"]
|
|
||||||
if result:
|
|
||||||
return result[0][0]
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
print("群名是: ", get_room_name(wechat, room_wxid))
|
|
||||||
|
|
||||||
# 以下是为了让程序不结束,如果有用于PyQt等有主循环消息的框架,可以去除下面代码
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
time.sleep(0.5)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
ntchat.exit_()
|
|
||||||
sys.exit()
|
|
||||||
119
examples/transmit.py
Normal file
119
examples/transmit.py
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from email import message
|
||||||
|
from email.mime import image
|
||||||
|
import sys
|
||||||
|
import os.path
|
||||||
|
import time
|
||||||
|
import ntchat
|
||||||
|
import re
|
||||||
|
|
||||||
|
# 聊天记录通知
|
||||||
|
MT_RECV_CHAT_RECORDS_MSG = 11061
|
||||||
|
|
||||||
|
wechat = ntchat.WeChat()
|
||||||
|
|
||||||
|
# 要监听的wxids,可以通过获取contact接口获取wxid,也可以开启后从debug信息中看出来
|
||||||
|
from_wxids = ["xxxxx", "xxxxxx"]
|
||||||
|
# 要转发的目标群
|
||||||
|
target_wxids = ["xxxxxxxx@chatroom"]
|
||||||
|
# 检查文件等待时长,单位s
|
||||||
|
wait_limit = 10
|
||||||
|
|
||||||
|
# 打开pc微信, smart: 是否管理已经登录的微信
|
||||||
|
wechat.open(smart=True)
|
||||||
|
|
||||||
|
|
||||||
|
@wechat.msg_register(ntchat.MT_RECV_TEXT_MSG)
|
||||||
|
def on_recv_text_msg(wechat_instance: ntchat.WeChat, message):
|
||||||
|
data = message["data"]
|
||||||
|
from_wxid = data["from_wxid"]
|
||||||
|
self_wxid = wechat_instance.get_login_info()["wxid"]
|
||||||
|
|
||||||
|
# 判断消息不是自己发的,且来自于想要转发的用户列表,并发给target用户
|
||||||
|
if from_wxid != self_wxid and from_wxid in from_wxids:
|
||||||
|
for target_wxid in target_wxids:
|
||||||
|
wechat_instance.send_text(to_wxid=target_wxid,
|
||||||
|
content=f"{data['msg']}")
|
||||||
|
|
||||||
|
|
||||||
|
# 等待file_path的文件被下载,超过等待次数后返回true
|
||||||
|
def wait_for_file(file_path) -> bool:
|
||||||
|
cnt = 0
|
||||||
|
while not os.path.exists(file_path):
|
||||||
|
time.sleep(1)
|
||||||
|
cnt = cnt + 1
|
||||||
|
if cnt > wait_limit:
|
||||||
|
print(
|
||||||
|
f"wait for {wait_limit} second, but file cannot be downloaded, forgive."
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@wechat.msg_register(ntchat.MT_RECV_IMAGE_MSG)
|
||||||
|
def on_recv_img_msg(wechat_instance: ntchat.WeChat, message):
|
||||||
|
data = message["data"]
|
||||||
|
from_wxid = data["from_wxid"]
|
||||||
|
img_path = data["image"]
|
||||||
|
# img_path = "D:\\a.png"
|
||||||
|
self_wxid = wechat_instance.get_login_info()["wxid"]
|
||||||
|
|
||||||
|
# 判断消息不是自己发的,且来自于想要转发的用户列表,并发给target用户
|
||||||
|
if from_wxid != self_wxid and from_wxid in from_wxids:
|
||||||
|
if wait_for_file(file_path=img_path):
|
||||||
|
for target_wxid in target_wxids:
|
||||||
|
wechat_instance.send_image(to_wxid=target_wxid, file_path=img_path)
|
||||||
|
|
||||||
|
|
||||||
|
@wechat.msg_register(ntchat.MT_RECV_FILE_MSG)
|
||||||
|
def on_recv_img_msg(wechat_instance: ntchat.WeChat, message):
|
||||||
|
data = message["data"]
|
||||||
|
from_wxid = data["from_wxid"]
|
||||||
|
file_path = data["file"]
|
||||||
|
self_wxid = wechat_instance.get_login_info()["wxid"]
|
||||||
|
|
||||||
|
# 判断消息不是自己发的,且来自于想要转发的用户列表,并发给target用户
|
||||||
|
if from_wxid != self_wxid and from_wxid in from_wxids:
|
||||||
|
if wait_for_file(file_path=file_path):
|
||||||
|
for target_wxid in target_wxids:
|
||||||
|
wechat_instance.send_file(to_wxid=target_wxid, file_path=file_path)
|
||||||
|
|
||||||
|
|
||||||
|
def update_wxid_in_xml(xml, from_wxid, target_wxid):
|
||||||
|
patten = re.compile(from_wxid)
|
||||||
|
return patten.sub(target_wxid, xml)
|
||||||
|
|
||||||
|
|
||||||
|
@wechat.msg_register(MT_RECV_CHAT_RECORDS_MSG)
|
||||||
|
def on_recv_chat_record_msg(wechat_instance: ntchat.WeChat, message):
|
||||||
|
data = message["data"]
|
||||||
|
from_wxid = data["from_wxid"]
|
||||||
|
raw_msg = data["raw_msg"]
|
||||||
|
self_wxid = wechat_instance.get_login_info()["wxid"]
|
||||||
|
xml = update_wxid_in_xml(raw_msg, from_wxid, self_wxid)
|
||||||
|
# 判断消息不是自己发的,且来自于想要转发的用户列表,并发给target用户
|
||||||
|
if from_wxid != self_wxid and from_wxid in from_wxids:
|
||||||
|
for target_wxid in target_wxids:
|
||||||
|
wechat_instance.send_xml(to_wxid=target_wxid, xml=xml)
|
||||||
|
|
||||||
|
|
||||||
|
@wechat.msg_register(ntchat.MT_RECV_LINK_MSG)
|
||||||
|
def on_recv_link_msg(wechat_instance: ntchat.WeChat, message):
|
||||||
|
data = message["data"]
|
||||||
|
from_wxid = data["from_wxid"]
|
||||||
|
raw_msg = data["raw_msg"]
|
||||||
|
# xml中的fromusername改成自己的wxid 再发
|
||||||
|
self_wxid = wechat_instance.get_login_info()["wxid"]
|
||||||
|
xml = update_wxid_in_xml(raw_msg, from_wxid, self_wxid)
|
||||||
|
# 判断消息不是自己发的,且来自于想要转发的用户列表,并发给target用户
|
||||||
|
if from_wxid != self_wxid and from_wxid in from_wxids:
|
||||||
|
for target_wxid in target_wxids:
|
||||||
|
wechat_instance.send_xml(to_wxid=target_wxid, xml=xml)
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
pass
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
ntchat.exit_()
|
||||||
|
sys.exit()
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import uvicorn
|
import uvicorn
|
||||||
|
import threading
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from mgr import ClientManager
|
from mgr import ClientManager
|
||||||
|
|
@ -56,8 +57,14 @@ async def client_create():
|
||||||
response_model=models.ResponseModel)
|
response_model=models.ResponseModel)
|
||||||
@catch_exception()
|
@catch_exception()
|
||||||
async def client_open(model: models.ClientOpenReqModel):
|
async def client_open(model: models.ClientOpenReqModel):
|
||||||
ret = client_mgr.get_client(model.guid).open(model.smart)
|
client = client_mgr.get_client(model.guid)
|
||||||
return response_json(1 if ret else 0)
|
ret = client.open(model.smart, model.show_login_qrcode)
|
||||||
|
|
||||||
|
# 当show_login_qrcode=True时, 打开微信时会显示二维码界面
|
||||||
|
if model.show_login_qrcode:
|
||||||
|
client.qrcode_event = threading.Event()
|
||||||
|
client.qrcode_event.wait(timeout=10)
|
||||||
|
return response_json(1 if ret else 0, {'qrcode': client.qrcode})
|
||||||
|
|
||||||
|
|
||||||
@app.post("/global/set_callback_url", summary="设置接收通知地址", tags=["Global"],
|
@app.post("/global/set_callback_url", summary="设置接收通知地址", tags=["Global"],
|
||||||
|
|
@ -92,6 +99,13 @@ async def get_contact_detail(model: models.ContactDetailReqModel):
|
||||||
return response_json(1, data)
|
return response_json(1, data)
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/contact/modify_remark", summary="修改联系人备注", tags=["Contact"], response_model=models.ResponseModel)
|
||||||
|
@catch_exception()
|
||||||
|
async def send_gif(model: models.ModifyFriendRemarkReqModel):
|
||||||
|
data = client_mgr.get_client(model.guid).modify_friend_remark(model.wxid, model.remark)
|
||||||
|
return response_json(1, data)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/room/get_rooms", summary="获取群列表", tags=["Room"],
|
@app.post("/room/get_rooms", summary="获取群列表", tags=["Room"],
|
||||||
response_model=models.ResponseModel)
|
response_model=models.ResponseModel)
|
||||||
@catch_exception()
|
@catch_exception()
|
||||||
|
|
@ -100,6 +114,17 @@ async def get_rooms(model: models.ClientReqModel):
|
||||||
return response_json(1, data)
|
return response_json(1, data)
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/room/get_name_name", summary="获取群名称", tags=["Room"],
|
||||||
|
response_model=models.ResponseModel)
|
||||||
|
@catch_exception()
|
||||||
|
async def get_rooms(model: models.GetRoomNameReqModel):
|
||||||
|
name = client_mgr.get_client(model.guid).get_room_name(model.room_wxid)
|
||||||
|
data = {
|
||||||
|
"name": name
|
||||||
|
}
|
||||||
|
return response_json(1, data)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/room/get_room_members", summary="获取群成员列表", tags=["Room"],
|
@app.post("/room/get_room_members", summary="获取群成员列表", tags=["Room"],
|
||||||
response_model=models.ResponseModel)
|
response_model=models.ResponseModel)
|
||||||
@catch_exception()
|
@catch_exception()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import ntchat
|
import ntchat
|
||||||
|
import threading
|
||||||
import requests
|
import requests
|
||||||
from typing import Dict, Union
|
from typing import Dict, Union
|
||||||
from ntchat.utils.singleton import Singleton
|
from ntchat.utils.singleton import Singleton
|
||||||
|
|
@ -9,6 +10,8 @@ from exception import ClientNotExists
|
||||||
|
|
||||||
class ClientWeChat(ntchat.WeChat):
|
class ClientWeChat(ntchat.WeChat):
|
||||||
guid: str = ""
|
guid: str = ""
|
||||||
|
qrcode_event: threading.Event = None
|
||||||
|
qrcode: str = ""
|
||||||
|
|
||||||
|
|
||||||
class ClientManager(metaclass=Singleton):
|
class ClientManager(metaclass=Singleton):
|
||||||
|
|
@ -35,7 +38,7 @@ class ClientManager(metaclass=Singleton):
|
||||||
wechat.on(ntchat.MT_RECV_WECHAT_QUIT_MSG, self.__on_quit_callback)
|
wechat.on(ntchat.MT_RECV_WECHAT_QUIT_MSG, self.__on_quit_callback)
|
||||||
return guid
|
return guid
|
||||||
|
|
||||||
def get_client(self, guid: str) -> Union[None, ntchat.WeChat]:
|
def get_client(self, guid: str) -> ClientWeChat:
|
||||||
client = self.__client_map.get(guid, None)
|
client = self.__client_map.get(guid, None)
|
||||||
if client is None:
|
if client is None:
|
||||||
raise ClientNotExists(guid)
|
raise ClientNotExists(guid)
|
||||||
|
|
@ -45,7 +48,14 @@ class ClientManager(metaclass=Singleton):
|
||||||
if guid in self.__client_map:
|
if guid in self.__client_map:
|
||||||
del self.__client_map[guid]
|
del self.__client_map[guid]
|
||||||
|
|
||||||
def __on_callback(self, wechat, message):
|
def __on_callback(self, wechat: ClientWeChat, message: dict):
|
||||||
|
|
||||||
|
# 通知二维码显示
|
||||||
|
msg_type = message['type']
|
||||||
|
if msg_type == ntchat.MT_RECV_LOGIN_QRCODE_MSG and wechat.qrcode_event:
|
||||||
|
wechat.qrcode = message["data"]["code"]
|
||||||
|
wechat.qrcode_event.set()
|
||||||
|
|
||||||
if not self.callback_url:
|
if not self.callback_url:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,10 @@ class GetRoomMembersReqModel(ClientReqModel):
|
||||||
room_wxid: str
|
room_wxid: str
|
||||||
|
|
||||||
|
|
||||||
|
class GetRoomNameReqModel(ClientReqModel):
|
||||||
|
room_wxid: str
|
||||||
|
|
||||||
|
|
||||||
class CreateRoomReqModel(ClientReqModel):
|
class CreateRoomReqModel(ClientReqModel):
|
||||||
member_list: List[str]
|
member_list: List[str]
|
||||||
|
|
||||||
|
|
@ -145,3 +149,9 @@ class SendPatReqModel(ClientReqModel):
|
||||||
room_wxid: str
|
room_wxid: str
|
||||||
patted_wxid: str
|
patted_wxid: str
|
||||||
|
|
||||||
|
|
||||||
|
class ModifyFriendRemarkReqModel(ClientReqModel):
|
||||||
|
wxid: str
|
||||||
|
remark: str
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
VERSION = '0.1.13'
|
VERSION = '0.1.17'
|
||||||
|
|
||||||
LOG_LEVEL = "DEBUG"
|
LOG_LEVEL = "DEBUG"
|
||||||
LOG_KEY = 'NTCHAT_LOG'
|
LOG_KEY = 'NTCHAT_LOG'
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import json
|
import json
|
||||||
import os.path
|
import os.path
|
||||||
from ntchat.wc import wcprobe
|
from ntchat.wc import wcprobe, SUPPORT_VERSIONS
|
||||||
from ntchat.utils.xdg import get_helper_file
|
from ntchat.utils.xdg import get_helper_file, is_support_version, has_helper_file
|
||||||
from ntchat.exception import WeChatVersionNotMatchError, WeChatBindError
|
from ntchat.exception import WeChatVersionNotMatchError, WeChatBindError, WeChatRuntimeError
|
||||||
from ntchat.utils.singleton import Singleton
|
from ntchat.utils.singleton import Singleton
|
||||||
from ntchat.const import notify_type
|
from ntchat.const import notify_type
|
||||||
from ntchat.utils.logger import get_logger
|
from ntchat.utils.logger import get_logger
|
||||||
|
|
@ -31,9 +31,16 @@ class WeChatMgr(metaclass=Singleton):
|
||||||
else:
|
else:
|
||||||
version = wechat_version
|
version = wechat_version
|
||||||
|
|
||||||
|
if not is_support_version(version):
|
||||||
|
raise WeChatVersionNotMatchError(f"ntchat support wechat versions: {','.join(SUPPORT_VERSIONS)}")
|
||||||
|
|
||||||
|
if not has_helper_file():
|
||||||
|
raise WeChatRuntimeError('When using pyinstaller to package exe, you need to add the '
|
||||||
|
'`--collect-data=ntchat` parameter')
|
||||||
|
|
||||||
helper_file = get_helper_file(version)
|
helper_file = get_helper_file(version)
|
||||||
if not os.path.exists(helper_file):
|
if not os.path.exists(helper_file):
|
||||||
raise WeChatVersionNotMatchError()
|
raise WeChatRuntimeError("missing core files")
|
||||||
|
|
||||||
log.info("initialize wechat, version: %s", version)
|
log.info("initialize wechat, version: %s", version)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,34 +62,32 @@ class WeChat:
|
||||||
WeChatMgr().append_instance(self)
|
WeChatMgr().append_instance(self)
|
||||||
self.__wait_login_event = Event()
|
self.__wait_login_event = Event()
|
||||||
self.__req_data_cache = {}
|
self.__req_data_cache = {}
|
||||||
self.__msg_event_emitter = pyee.EventEmitter()
|
self.event_emitter = pyee.EventEmitter()
|
||||||
self.__login_info = {}
|
self.__login_info = {}
|
||||||
|
|
||||||
def on(self, msg_type, f):
|
def on(self, msg_type, f):
|
||||||
return self.__msg_event_emitter.on(str(msg_type), RaiseExceptionFunc(f))
|
|
||||||
|
|
||||||
def msg_register(self, msg_type: Union[int, List[int], Tuple[int]]):
|
|
||||||
if not (isinstance(msg_type, list) or isinstance(msg_type, tuple)):
|
if not (isinstance(msg_type, list) or isinstance(msg_type, tuple)):
|
||||||
msg_type = [msg_type]
|
msg_type = [msg_type]
|
||||||
|
for event in msg_type:
|
||||||
|
self.event_emitter.on(str(event), RaiseExceptionFunc(f))
|
||||||
|
|
||||||
|
def msg_register(self, msg_type: Union[int, List[int], Tuple[int]]):
|
||||||
def wrapper(f):
|
def wrapper(f):
|
||||||
wraps(f)
|
wraps(f)
|
||||||
for event in msg_type:
|
self.on(msg_type, f)
|
||||||
self.on(event, RaiseExceptionFunc(f))
|
|
||||||
return f
|
return f
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
def on_close(self):
|
def on_close(self):
|
||||||
self.login_status = False
|
self.login_status = False
|
||||||
self.status = False
|
self.status = False
|
||||||
self.__msg_event_emitter.emit(str(notify_type.MT_RECV_WECHAT_QUIT_MSG), self)
|
self.event_emitter.emit(str(notify_type.MT_RECV_WECHAT_QUIT_MSG), self)
|
||||||
|
|
||||||
message = {
|
message = {
|
||||||
"type": notify_type.MT_RECV_WECHAT_QUIT_MSG,
|
"type": notify_type.MT_RECV_WECHAT_QUIT_MSG,
|
||||||
"data": {}
|
"data": {}
|
||||||
}
|
}
|
||||||
self.__msg_event_emitter.emit(str(notify_type.MT_ALL), self, message)
|
self.event_emitter.emit(str(notify_type.MT_ALL), self, message)
|
||||||
|
|
||||||
def bind_client_id(self, client_id):
|
def bind_client_id(self, client_id):
|
||||||
self.status = True
|
self.status = True
|
||||||
|
|
@ -113,14 +111,17 @@ class WeChat:
|
||||||
req_data.on_response(message)
|
req_data.on_response(message)
|
||||||
del self.__req_data_cache[extend]
|
del self.__req_data_cache[extend]
|
||||||
else:
|
else:
|
||||||
self.__msg_event_emitter.emit(str(msg_type), self, message)
|
self.event_emitter.emit(str(msg_type), self, message)
|
||||||
self.__msg_event_emitter.emit(str(notify_type.MT_ALL), self, message)
|
self.event_emitter.emit(str(notify_type.MT_ALL), self, message)
|
||||||
|
|
||||||
def wait_login(self, timeout=None):
|
def wait_login(self, timeout=None):
|
||||||
log.info("wait login...")
|
log.info("wait login...")
|
||||||
self.__wait_login_event.wait(timeout)
|
self.__wait_login_event.wait(timeout)
|
||||||
|
|
||||||
def open(self, smart=False):
|
def open(self, smart=False, show_login_qrcode=False):
|
||||||
|
if show_login_qrcode:
|
||||||
|
wcprobe.show_login_qrcode()
|
||||||
|
|
||||||
self.pid = wcprobe.open(smart)
|
self.pid = wcprobe.open(smart)
|
||||||
log.info("open wechat pid: %d", self.pid)
|
log.info("open wechat pid: %d", self.pid)
|
||||||
return self.pid != 0
|
return self.pid != 0
|
||||||
|
|
@ -478,3 +479,13 @@ class WeChat:
|
||||||
"remark": remark
|
"remark": remark
|
||||||
}
|
}
|
||||||
return self.__send_sync(send_type.MT_MODIFY_FRIEND_REMARK, data)
|
return self.__send_sync(send_type.MT_MODIFY_FRIEND_REMARK, data)
|
||||||
|
|
||||||
|
def get_room_name(self, room_wxid: str) -> str:
|
||||||
|
"""
|
||||||
|
获取群名
|
||||||
|
"""
|
||||||
|
sql = f"select nickname from contact where username='{room_wxid}'"
|
||||||
|
result = self.sql_query(sql, 1)["result"]
|
||||||
|
if result:
|
||||||
|
return result[0][0]
|
||||||
|
return ''
|
||||||
|
|
|
||||||
|
|
@ -8,3 +8,7 @@ class WeChatBindError(Exception):
|
||||||
|
|
||||||
class WeChatNotLoginError(Exception):
|
class WeChatNotLoginError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class WeChatRuntimeError(Exception):
|
||||||
|
pass
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
|
from ntchat.wc import SUPPORT_VERSIONS
|
||||||
|
|
||||||
|
|
||||||
def get_exec_dir():
|
def get_exec_dir():
|
||||||
|
|
@ -26,9 +27,13 @@ def get_helper_file(version):
|
||||||
return os.path.join(get_wc_dir(), f"helper_{version}.dat")
|
return os.path.join(get_wc_dir(), f"helper_{version}.dat")
|
||||||
|
|
||||||
|
|
||||||
def get_support_download_url():
|
def has_helper_file():
|
||||||
return 'https://webcdn.m.qq.com/spcmgr/download/WeChat3.6.0.18.exe'
|
for name in os.listdir(get_wc_dir()):
|
||||||
|
if name.startswith("helper_"):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
def is_support_version(version):
|
||||||
print(get_helper_file('3.6.0.18'))
|
return version in SUPPORT_VERSIONS
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
SUPPORT_VERSIONS = [
|
||||||
|
'3.6.0.18'
|
||||||
|
]
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.8.0-win32\python.exe -m pip install --upgrade pip setuptools wheel
|
%UserProfile%\.pyenv\pyenv-win\versions\3.8.0-win32\python.exe -m pip install --upgrade pip setuptools wheel
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.9.0-win32\python.exe -m pip install --upgrade pip setuptools wheel
|
%UserProfile%\.pyenv\pyenv-win\versions\3.9.0-win32\python.exe -m pip install --upgrade pip setuptools wheel
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.10.0-win32\python.exe -m pip install --upgrade pip setuptools wheel
|
%UserProfile%\.pyenv\pyenv-win\versions\3.10.0-win32\python.exe -m pip install --upgrade pip setuptools wheel
|
||||||
|
%UserProfile%\.pyenv\pyenv-win\versions\3.11.0-win32\python.exe -m pip install --upgrade pip setuptools wheel
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat"
|
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat"
|
||||||
pushd ..
|
pushd ..
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.6.0-win32\python.exe setup.py bdist_wheel -d wheelhouse
|
%UserProfile%\.pyenv\pyenv-win\versions\3.6.0-win32\python.exe setup.py bdist_wheel -d wheelhouse
|
||||||
|
|
@ -10,4 +11,5 @@ pushd ..
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.8.0-win32\python.exe setup.py bdist_wheel -d wheelhouse
|
%UserProfile%\.pyenv\pyenv-win\versions\3.8.0-win32\python.exe setup.py bdist_wheel -d wheelhouse
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.9.0-win32\python.exe setup.py bdist_wheel -d wheelhouse
|
%UserProfile%\.pyenv\pyenv-win\versions\3.9.0-win32\python.exe setup.py bdist_wheel -d wheelhouse
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.10.0-win32\python.exe setup.py bdist_wheel -d wheelhouse
|
%UserProfile%\.pyenv\pyenv-win\versions\3.10.0-win32\python.exe setup.py bdist_wheel -d wheelhouse
|
||||||
|
%UserProfile%\.pyenv\pyenv-win\versions\3.11.0-win32\python.exe setup.py bdist_wheel -d wheelhouse
|
||||||
popd
|
popd
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.8.0\python.exe -m pip install --upgrade pip setuptools wheel
|
%UserProfile%\.pyenv\pyenv-win\versions\3.8.0\python.exe -m pip install --upgrade pip setuptools wheel
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.9.0\python.exe -m pip install --upgrade pip setuptools wheel
|
%UserProfile%\.pyenv\pyenv-win\versions\3.9.0\python.exe -m pip install --upgrade pip setuptools wheel
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.10.0\python.exe -m pip install --upgrade pip setuptools wheel
|
%UserProfile%\.pyenv\pyenv-win\versions\3.10.0\python.exe -m pip install --upgrade pip setuptools wheel
|
||||||
|
%UserProfile%\.pyenv\pyenv-win\versions\3.11.0\python.exe -m pip install --upgrade pip setuptools wheel
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
|
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||||
pushd ..
|
pushd ..
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.6.0\python.exe setup.py bdist_wheel -d wheelhouse
|
%UserProfile%\.pyenv\pyenv-win\versions\3.6.0\python.exe setup.py bdist_wheel -d wheelhouse
|
||||||
|
|
@ -10,4 +11,5 @@ pushd ..
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.8.0\python.exe setup.py bdist_wheel -d wheelhouse
|
%UserProfile%\.pyenv\pyenv-win\versions\3.8.0\python.exe setup.py bdist_wheel -d wheelhouse
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.9.0\python.exe setup.py bdist_wheel -d wheelhouse
|
%UserProfile%\.pyenv\pyenv-win\versions\3.9.0\python.exe setup.py bdist_wheel -d wheelhouse
|
||||||
%UserProfile%\.pyenv\pyenv-win\versions\3.10.0\python.exe setup.py bdist_wheel -d wheelhouse
|
%UserProfile%\.pyenv\pyenv-win\versions\3.10.0\python.exe setup.py bdist_wheel -d wheelhouse
|
||||||
|
%UserProfile%\.pyenv\pyenv-win\versions\3.11.0\python.exe setup.py bdist_wheel -d wheelhouse
|
||||||
popd
|
popd
|
||||||
|
|
|
||||||
5
setup.py
5
setup.py
|
|
@ -194,7 +194,7 @@ extension.extra_compile_cpp_args = extra_compile_cpp_args[target_os]
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='ntchat',
|
name='ntchat',
|
||||||
version='0.1.13',
|
version='0.1.17',
|
||||||
description='About Conversational RPA SDK for Chatbot Makers',
|
description='About Conversational RPA SDK for Chatbot Makers',
|
||||||
long_description="",
|
long_description="",
|
||||||
long_description_content_type='text/markdown',
|
long_description_content_type='text/markdown',
|
||||||
|
|
@ -209,7 +209,8 @@ setup(
|
||||||
'Programming Language :: Python :: 3.7',
|
'Programming Language :: Python :: 3.7',
|
||||||
'Programming Language :: Python :: 3.8',
|
'Programming Language :: Python :: 3.8',
|
||||||
'Programming Language :: Python :: 3.9',
|
'Programming Language :: Python :: 3.9',
|
||||||
'Programming Language :: Python :: 3.10'
|
'Programming Language :: Python :: 3.10',
|
||||||
|
'Programming Language :: Python :: 3.11'
|
||||||
],
|
],
|
||||||
package_data={"": ["py.typed", "*.pyi", "helper*.dat"]},
|
package_data={"": ["py.typed", "*.pyi", "helper*.dat"]},
|
||||||
include_package_data=False,
|
include_package_data=False,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user