diff --git a/config.yaml.template b/config.yaml.template new file mode 100644 index 0000000..1b703ad --- /dev/null +++ b/config.yaml.template @@ -0,0 +1,39 @@ +logging: + version: 1 + disable_existing_loggers: True + + formatters: + simple: + format: "%(asctime)s %(message)s" + datefmt: "%Y-%m-%d %H:%M:%S" + error: + format: "%(asctime)s %(name)s %(levelname)s %(filename)s::%(funcName)s[%(lineno)d]:%(message)s" + + handlers: + console: + class: logging.StreamHandler + level: INFO + formatter: simple + stream: ext://sys.stdout + + info_file_handler: + class: logging.handlers.RotatingFileHandler + level: INFO + formatter: simple + filename: wcai.log + maxBytes: 10485760 # 10MB + backupCount: 20 + encoding: utf8 + + error_file_handler: + class: logging.handlers.RotatingFileHandler + level: ERROR + formatter: error + filename: errors.log + maxBytes: 10485760 # 10MB + backupCount: 20 + encoding: utf8 + + root: + level: INFO + handlers: [console, info_file_handler, error_file_handler] diff --git a/main.py b/main.py index 38d80cf..21a361e 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,34 @@ #! /usr/bin/env python3 # -*- coding: utf-8 -*- -import sdk.wcferry as WxSDK +import time + +import robot.sdk.wcferry as WxSDK +from robot.base_robot import BaseRobot +from robot.configuration import Config + + +class Robot(BaseRobot): + def __init__(self, sdk: WxSDK, config: Config) -> None: + super().__init__(sdk, config) + + def processMsg(self, msg) -> None: + # 如果不实现本方法,则默认打印原始消息 + + if self.isGroupChat(msg): # 是群消息 + if self.isAt(msg): # 被@ + if msg.roomId in self.config.GROUPS: # 在配置的响应的群列表里 + self.sendTextMsg(msg.roomId, "收到你的消息了!", msg.wxId) def main(): - print(dir(WxSDK)) + robot = Robot(WxSDK, Config()) + robot.initSDK() + robot.enableRecvMsg() + + while True: + time.sleep(1) + # 不让进程退出,否则机器人就退出了 if __name__ == "__main__": diff --git a/robot/base_robot.py b/robot/base_robot.py new file mode 100644 index 0000000..0548fbc --- /dev/null +++ b/robot/base_robot.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- + +import re +import logging + + +class BaseRobot(object): + def __init__(self, sdk, config) -> None: + self.sdk = sdk + self.config = config + self.LOG = logging.getLogger("Robot") + + def onMsg(self, msg) -> int: + try: + self.processMsg(msg) + except Exception as e: + self.LOG.error(e) + self.printRawMsg(msg) + + return 0 + + def initSDK(self): + if self.sdk.WxInitSDK() != 0: + self.LOG.error("初始化失败") + exit(-1) + self.LOG.info("初始化成功") + self.wxid = self.sdk.WxGetSelfWxid() + + def enableRecvMsg(self): + self.sdk.WxEnableRecvMsg(self.onMsg) + + def sendTextMsg(self, receiver, msg, at_list=""): + # msg 中需要有 @ 名单中一样数量的 @ + ats = "" + if at_list: + # 这里只简单补全数量,后续可以补充群昵称(通过 SQL 获取) + ats = " @" * len(at_list.split(",")) + self.sdk.WxSendTextMsg(receiver, f"{msg}{ats}", at_list) + + def isGroupChat(self, msg): + return msg.source == 1 + + def isAt(self, msg, exclude_at_all=True): + atall = [] + atuserlist = re.findall(f".*({self.wxid}).*", msg.xml) + if exclude_at_all: + atall = re.findall(f"@所有人", msg.content) # 排除@所有人 + + return (len(atuserlist) > 0) and (len(atall) == 0) + + def printRawMsg(self, msg) -> None: + rmsg = {} + rmsg["id"] = msg.id + rmsg["self"] = msg.self + rmsg["wxId"] = msg.wxId + rmsg["roomId"] = msg.roomId + rmsg["type"] = msg.type + rmsg["source"] = msg.source + rmsg["xml"] = msg.xml + rmsg["content"] = msg.content + + self.LOG.info(rmsg) + + def processMsg(self, msg) -> None: + raise NotImplementedError("Method [processMsg] should be implemented.") diff --git a/robot/configuration.py b/robot/configuration.py new file mode 100644 index 0000000..5af1314 --- /dev/null +++ b/robot/configuration.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import os +import yaml +import logging.config + + +class Config(object): + def __init__(self) -> None: + self.reload() + + def _load_config(self) -> dict: + pwd = os.path.dirname(os.path.abspath(__file__)) + try: + with open(f"{pwd}/config.yaml", "rb") as fp: + yconfig = yaml.safe_load(fp) + except FileNotFoundError: + with open(f"{pwd}/../config.yaml.template", "rb") as fp: + yconfig = yaml.safe_load(fp) + with open(f"{pwd}/config.yaml", "w+") as yf: + yaml.dump(yconfig, yf, default_flow_style=False) + + return yconfig + + def reload(self): + yconfig = self._load_config() + logging.config.dictConfig(yconfig["logging"]) + self.GROUPS = yconfig["groups"]["enable"] diff --git a/robot/sdk/App.exe b/robot/sdk/App.exe new file mode 100644 index 0000000..81bfb38 Binary files /dev/null and b/robot/sdk/App.exe differ diff --git a/sdk/App.py b/robot/sdk/App.py old mode 100755 new mode 100644 similarity index 100% rename from sdk/App.py rename to robot/sdk/App.py diff --git a/robot/sdk/SDK.dll b/robot/sdk/SDK.dll new file mode 100644 index 0000000..ce0362d Binary files /dev/null and b/robot/sdk/SDK.dll differ diff --git a/robot/sdk/Spy.dll b/robot/sdk/Spy.dll new file mode 100644 index 0000000..a826a32 Binary files /dev/null and b/robot/sdk/Spy.dll differ diff --git a/sdk/test.jpg b/robot/sdk/test.jpg old mode 100755 new mode 100644 similarity index 100% rename from sdk/test.jpg rename to robot/sdk/test.jpg diff --git a/robot/sdk/wcferry.pyd b/robot/sdk/wcferry.pyd new file mode 100644 index 0000000..cd7e4c0 Binary files /dev/null and b/robot/sdk/wcferry.pyd differ diff --git a/sdk/App.exe b/sdk/App.exe deleted file mode 100755 index 612c3a9..0000000 Binary files a/sdk/App.exe and /dev/null differ diff --git a/sdk/SDK.dll b/sdk/SDK.dll deleted file mode 100755 index 5bc4987..0000000 Binary files a/sdk/SDK.dll and /dev/null differ diff --git a/sdk/Spy.dll b/sdk/Spy.dll deleted file mode 100755 index aabdb14..0000000 Binary files a/sdk/Spy.dll and /dev/null differ diff --git a/sdk/wcferry.pyd b/sdk/wcferry.pyd deleted file mode 100755 index fc4254b..0000000 Binary files a/sdk/wcferry.pyd and /dev/null differ