You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
3.3 KiB
109 lines
3.3 KiB
"""微信消息监听 — 主入口"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import logging
|
|
import signal
|
|
import sys
|
|
import time
|
|
|
|
from .config import Config
|
|
from .monitor.event import MessageEvent
|
|
from .monitor.watcher import WeChatWatcher
|
|
from .storage.sqlite import SQLiteStorage
|
|
|
|
|
|
def setup_logging(config: Config) -> None:
|
|
fmt = "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
|
|
handlers: list[logging.Handler] = [logging.StreamHandler(sys.stdout)]
|
|
if config.log_file:
|
|
handlers.append(logging.FileHandler(config.log_file, encoding="utf-8"))
|
|
logging.basicConfig(
|
|
level=getattr(logging, config.log_level, logging.INFO),
|
|
format=fmt,
|
|
handlers=handlers,
|
|
)
|
|
|
|
|
|
def create_on_message_callback(storage: SQLiteStorage):
|
|
"""创建消息回调:打印 + 持久化"""
|
|
|
|
def _on_message(event: MessageEvent) -> None:
|
|
msg = event.message
|
|
# 控制台输出
|
|
prefix = "[自己]" if msg.is_self else f"[{msg.sender}]"
|
|
print(f" {msg.conversation} | {prefix} {msg.content[:120]}")
|
|
# 存储
|
|
storage.save_message(msg)
|
|
|
|
return _on_message
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description="微信聊天消息监听器")
|
|
parser.add_argument("-c", "--conversation", default="", help="指定监听的会话名称(为空则监听当前活跃会话)")
|
|
parser.add_argument("--db", default="wechat_messages.db", help="SQLite 数据库路径")
|
|
parser.add_argument("--interval", type=float, default=1.0, help="轮询间隔(秒)")
|
|
parser.add_argument("--log-level", default="INFO", help="日志级别")
|
|
args = parser.parse_args()
|
|
|
|
config = Config(
|
|
poll_interval=args.interval,
|
|
sqlite_path=args.db,
|
|
log_level=args.log_level,
|
|
)
|
|
setup_logging(config)
|
|
logger = logging.getLogger("main")
|
|
|
|
# 初始化存储
|
|
storage = SQLiteStorage(config.sqlite_path)
|
|
storage.connect()
|
|
|
|
# 初始化监听器
|
|
watcher = WeChatWatcher(config)
|
|
watcher.on_message(create_on_message_callback(storage))
|
|
|
|
logger.info("正在连接微信窗口...")
|
|
if not watcher.connect():
|
|
logger.error("连接微信失败,请确保微信已登录且窗口可见")
|
|
storage.close()
|
|
sys.exit(1)
|
|
|
|
# 优雅退出
|
|
def _signal_handler(sig, frame):
|
|
logger.info("收到退出信号,正在停止...")
|
|
watcher.stop()
|
|
storage.close()
|
|
sys.exit(0)
|
|
|
|
signal.signal(signal.SIGINT, _signal_handler)
|
|
signal.signal(signal.SIGTERM, _signal_handler)
|
|
|
|
# 启动监听
|
|
logger.info("开始监听会话: %s", args.conversation or "(当前活跃会话)")
|
|
watcher.start(conversation=args.conversation)
|
|
|
|
# 主线程保持运行
|
|
try:
|
|
while True:
|
|
time.sleep(1)
|
|
if not watcher._wechat.is_alive():
|
|
logger.warning("微信窗口已关闭,尝试重新连接...")
|
|
watcher.stop()
|
|
time.sleep(2)
|
|
if watcher.connect():
|
|
watcher.start(conversation=args.conversation)
|
|
else:
|
|
logger.error("重新连接失败,退出")
|
|
break
|
|
except KeyboardInterrupt:
|
|
pass
|
|
finally:
|
|
watcher.stop()
|
|
storage.close()
|
|
logger.info("监听器已退出")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|