-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathbot_core.py
209 lines (173 loc) · 7.22 KB
/
bot_core.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
import asyncio
import json
import os
import time
import tomllib
from pathlib import Path
from loguru import logger
import WechatAPI
from database.database import BotDatabase
from utils.decorators import scheduler
from utils.plugin_manager import plugin_manager
from utils.xybot import XYBot
async def bot_core():
# 设置工作目录
script_dir = Path(__file__).resolve().parent
# 读取主设置
config_path = script_dir / "main_config.toml"
with open(config_path, "rb") as f:
main_config = tomllib.load(f)
logger.success("读取主设置成功")
# 启动WechatAPI服务
server = WechatAPI.WechatAPIServer()
api_config = main_config.get("WechatAPIServer", {})
redis_host = api_config.get("redis-host", "127.0.0.1")
redis_port = api_config.get("redis-port", 6379)
logger.debug("Redis 主机地址: {}:{}", redis_host, redis_port)
server.start(port=api_config.get("port", 9000),
mode=api_config.get("mode", "release"),
redis_host=redis_host,
redis_port=redis_port,
redis_password=api_config.get("redis-password", ""),
redis_db=api_config.get("redis-db", 0))
# 实例化WechatAPI客户端
bot = WechatAPI.WechatAPIClient("127.0.0.1", api_config.get("port", 9000))
bot.ignore_protect = main_config.get("XYBot", {}).get("ignore-protection", False)
# 等待WechatAPI服务启动
time_out = 10
while not await bot.is_running() and time_out > 0:
logger.info("等待WechatAPI启动中")
await asyncio.sleep(2)
time_out -= 2
if time_out <= 0:
logger.error("WechatAPI服务启动超时")
return
if not await bot.check_database():
logger.error("Redis连接失败,请检查Redis是否在运行中,Redis的配置")
return
logger.success("WechatAPI服务已启动")
# ==========登陆==========
# 检查并创建robot_stat.json文件
robot_stat_path = script_dir / "resource" / "robot_stat.json"
if not os.path.exists(robot_stat_path):
default_config = {
"wxid": "",
"device_name": "",
"device_id": ""
}
os.makedirs(os.path.dirname(robot_stat_path), exist_ok=True)
with open(robot_stat_path, "w") as f:
json.dump(default_config, f)
robot_stat = default_config
else:
with open(robot_stat_path, "r") as f:
robot_stat = json.load(f)
wxid = robot_stat.get("wxid", None)
device_name = robot_stat.get("device_name", None)
device_id = robot_stat.get("device_id", None)
if not await bot.is_logged_in(wxid):
while not await bot.is_logged_in(wxid):
# 需要登录
try:
if await bot.get_cached_info(wxid):
# 尝试唤醒登录
uuid = await bot.awaken_login(wxid)
logger.success("获取到登录uuid: {}", uuid)
else:
# 二维码登录
if not device_name:
device_name = bot.create_device_name()
if not device_id:
device_id = bot.create_device_id()
uuid, url = await bot.get_qr_code(device_id=device_id, device_name=device_name, print_qr=True)
logger.success("获取到登录uuid: {}", uuid)
logger.success("获取到登录二维码: {}", url)
except:
# 二维码登录
if not device_name:
device_name = bot.create_device_name()
if not device_id:
device_id = bot.create_device_id()
uuid, url = await bot.get_qr_code(device_id=device_id, device_name=device_name, print_qr=True)
logger.success("获取到登录uuid: {}", uuid)
logger.success("获取到登录二维码: {}", url)
while True:
stat, data = await bot.check_login_uuid(uuid, device_id=device_id)
if stat:
break
logger.info("等待登录中,过期倒计时:{}", data)
await asyncio.sleep(5)
# 保存登录信息
robot_stat["wxid"] = bot.wxid
robot_stat["device_name"] = device_name
robot_stat["device_id"] = device_id
with open("resource/robot_stat.json", "w") as f:
json.dump(robot_stat, f)
# 获取登录账号信息
bot.wxid = data.get("acctSectResp").get("userName")
bot.nickname = data.get("acctSectResp").get("nickName")
bot.alias = data.get("acctSectResp").get("alias")
bot.phone = data.get("acctSectResp").get("bindMobile")
logger.info("登录账号信息: wxid: {} 昵称: {} 微信号: {} 手机号: {}", bot.wxid, bot.nickname, bot.alias,
bot.phone)
else: # 已登录
bot.wxid = wxid
profile = await bot.get_profile()
bot.nickname = profile.get("NickName").get("string")
bot.alias = profile.get("Alias")
bot.phone = profile.get("BindMobile").get("string")
logger.info("登录账号信息: wxid: {} 昵称: {} 微信号: {} 手机号: {}", bot.wxid, bot.nickname, bot.alias,
bot.phone)
logger.info("登录设备信息: device_name: {} device_id: {}", device_name, device_id)
logger.success("登录成功")
# ========== 登录完毕 开始初始化 ========== #
# 开启自动心跳
try:
success = await bot.start_auto_heartbeat()
if success:
logger.success("已开启自动心跳")
else:
logger.warning("开启自动心跳失败")
except ValueError:
logger.warning("自动心跳已在运行")
except Exception as e:
if "在运行" not in e:
logger.warning("自动心跳已在运行")
# 初始化机器人
xybot = XYBot(bot)
xybot.update_profile(bot.wxid, bot.nickname, bot.alias, bot.phone)
# 初始化数据库
BotDatabase()
# 启动调度器
scheduler.start()
logger.success("定时任务已启动")
# 加载插件目录下的所有插件
loaded_plugins = await plugin_manager.load_plugins_from_directory(bot, load_disabled_plugin=False)
logger.success(f"已加载插件: {loaded_plugins}")
# ========== 开始接受消息 ========== #
# 先接受10秒的消息,之前的消息有堆积
logger.info("处理堆积消息中")
now = time.time()
while time.time() - now < 10:
data = await bot.sync_message()
data = data.get("AddMsgs")
if not data:
break
logger.debug("接受到 {} 条消息", len(data))
await asyncio.sleep(1)
logger.success("处理堆积消息完毕")
logger.success("开始处理消息")
while True:
now = time.time()
try:
data = await bot.sync_message()
except Exception as e:
logger.warning("获取新消息失败 {}", e)
await asyncio.sleep(5)
continue
data = data.get("AddMsgs")
if data:
for message in data:
asyncio.create_task(xybot.process_message(message))
while time.time() - now < 1:
pass