Hangjau 发表于 2021-9-16 13:03

微信bot推送库

本帖最后由 Hangjau 于 2021-9-16 13:09 编辑

### 背景
首先也是看了@Ysnv   大哥的https://www.52pojie.cn/thread-1338005-1-1.html 这篇帖子后的想法,就是写一个py的库,只支持微信能够接收的消息类型。
参考网上类似库,对自己本来写的做了库重构。然后打包上传到PYPI

### 原理

   通过企业微信可以创建应用与咱使用的微信进行通信。操作企业微信的APi达到推送到微信的目的

### 项目安装

                              pip install pywchat


### 项目实现

1. 已实现配置信息进行初始化.

2. 已实现对token的离线保存,以及token失效的自动获取.

3. 已实现对text、image、voice、video、file、textcard、graphic、upload_image、get_user_id 消息的发送封装.

4. 已实现对错误返回的处理.
5. 支持多个企业微信操作
6. 支持所有的OS

### 导入包
```
from pywchat import Sender
```

### 三种初始化方法

    第一种:直接传入,只会在当前路径生成一个.token文件
    app = Sender(corpid,corpsecret,agentid)
   
    第二种:传入配置文件路径.读取配置(格式参考配置介绍.chatkey)并在当前路径生成一个.token文件(理论上文件也可无后缀且能读取成text即可)
    app = Sender(path=r"G:\chat\conf.ini")
   
    第三种:不传任何参. 动态输入所需的corpid,corpsecret,agentid,并在当前路径生成一个.chatkey,.token两个文件
    app = Sender()



代码展示

代码分为2层,接口层,处理层。

接口层(对外使用的):

class Sender(WorkChatApi):
    def __init__(self, corpid=None, corpsecret=None, agentid=None, **kwargs):
      self._Handler = HandlerTool(corpid, corpsecret, agentid, **kwargs)

    def get_token(self):
      """
      获取token
      :return: token
      """
      return self._Handler.get_token()

    def send_text(self, message, **kwargs):
      """
      发送文本消息,支持换行、以及A标签,大小最长不超过2048字节
      :param message:消息内容
      :param kwargs:可选择发送对象,tousers(用户), todept(部门), totags(标签用户). 默认为发送全部人
      """

      text_msg = {"content": message}
      self._Handler.send_message("text", text_msg, **kwargs)

    def send_image(self, iamge_path, **kwargs):
      """
      发送图片消息,仅支持jpg,png格式,大小5B~2M
      :param iamge_path: 发送图片的本地路径
      :param kwargs: 可选择发送对象,tousers(用户), todept(部门), totags(标签用户).
      """

      image_msg = {"media_id": iamge_path}
      self._Handler.send_message("image", image_msg, **kwargs)

处理层:

class HandlerTool:
    """
    处理类,封装请求,处理请求以及请求闭环。为上层接口提供处理逻辑
    """

    def __init__(self, corpid=None, corpsecret=None, agentid=None, **kwargs):
      self.corpid = corpid
      self.corpsecret = corpsecret
      self.agentid = agentid
      self._op = None
      self.url = 'https://qyapi.weixin.qq.com'
      self.conf = configparser.ConfigParser()
      self.judgment_type(corpid, corpsecret, agentid, **kwargs)
      self.token = self.get_token()


    @staticmethod
    def is_image(file):

      if not (file.suffix in (".JPG", ".PNG", ".jpg", ".png") and (5 <= file.stat().st_size <= 2 * 1024 * 1024)):
            raise TypeError({"Code": "ERROR", "message": '图片文件不合法, 请检查文件类型(jpg, png, JPG, PNG)或文件大小(5B~2M)'})

    @staticmethod
    def is_voice(file):

      if not (file.suffix in (".AMR", ".amr") and (5 <= file.stat().st_size <= 2 * 1024 * 1024)):
            raise TypeError({"Code": "ERROR", "message": '语音文件不合法, 请检查文件类型(AMR, amr)或文件大小(5B~2M)'})

    @staticmethod
    def is_video(file):

      if not (file.suffix in (".MP4", ".mp4") and (5 <= file.stat().st_size <= 10 * 1024 * 1024)):
            raise TypeError({"Code": "ERROR", "message": '视频文件不合法, 请检查文件类型(MP4, mp4)或文件大小(5B~10M)'})      
    def send_message(self, message_type, message, touser=None, todept=None, totags=None):
      """
      发送消息的主要接口封装和发起请求
      :param message_type: 发送消息的类型
      :param message: 发送消息的内容
      :param touser: 发送到具体的用户,当此参数为@all时,忽略todept,totags 参数并发送到全部人,此参数默认为@all
      用户名用 | 拼接。最多支持100个
      :param todept: 发送到部门,当tousers为默认@all 此参数会被忽略.部门之间用 | 拼接。最多支持100个
      :param totags: 发送到标签的用用户,当tousers为默认@all 此参数会被忽略. 标签之间用 | 拼接.最多支持100个
      :return:
      """
      data = {
            "msgtype": message_type,
            "agentid": self.agentid,
            message_type: message
      }

      if not (touser or todept or totags):
            data["touser"] = "@all"

      else:
            if touser:
                data["touser"] = touser

            if todept:
                data["toparty"] = todept

            if totags:
                data["totag"] = totags

      # 判断是否需要上传
      if message_type in ("image", "voice", "video", "file"):
            filepath = message.get("media_id")

            media_id = self.upload_media(message_type, filepath)
            message["media_id"] = media_id

      self._post(chat_api.get('MESSAGE_SEND'), data=json.dumps(data))
      logging.info(f"发送 {message_type} 消息成功...")



只展示了部分,篇幅有点长,详细源码 可去项目地址查看:

      https://github.com/HangJau/pywchat.git


效果展示




结束语
      感谢各位大佬看官,若发现问题还请给小弟提出来。还请大佬朋友们多多支持

kkfgef 发表于 2021-9-16 14:07

请问是推送到关注 企业号 后的聊天窗口吗,这个 助理 是什么来的?

叫我小王叔叔 发表于 2022-4-4 17:56

Hangjau 发表于 2022-4-3 18:50
可以直接改掉 workhandler58行tokenp = Path.cwd().joinpath(".token")这个路径改成云函数/tmp 路径 ...

with open('/tmp/check.txt', 'r') as fp:
    check = fp.read()
if title != check:
    app.send_text("您投稿的论文现在处于:"+title+"状态,请耐心等待或者拨打010-68331164询问!", touser="wa")
    with open('/tmp/check.txt', 'w') as fp:
      fp.write(title)

大佬,我的云函数里有这么几行,代码,为啥运行的时候说找不到这个文件呢?我是手动新建的,我改了你的58后,你的就不报错了,请问这是什么情况呀?

ZuiShuai-Song 发表于 2021-9-16 13:25

不明觉厉,感觉好厉害

ynboyinkm 发表于 2021-9-16 13:27

可是只有企业版微信才有这功能

magicianly 发表于 2021-9-16 13:58

学习一下

csp3949160 发表于 2021-9-16 14:25

个人版能这样就厉害了

Hangjau 发表于 2021-9-16 14:33

kkfgef 发表于 2021-9-16 14:07
请问是推送到关注 企业号 后的聊天窗口吗,这个 助理 是什么来的?

是的, 这个名字就是创建的应用名称

Hangjau 发表于 2021-9-16 14:34

csp3949160 发表于 2021-9-16 14:25
个人版能这样就厉害了

个人版不行的,目前只能通过外部的进行通信。

Hangjau 发表于 2021-9-16 14:36

ynboyinkm 发表于 2021-9-16 13:27
可是只有企业版微信才有这功能

是的这里就是通过微信关注企业号 的方式接收到推送的信息。不过对于开发者想接收推送到微信已经够用了。真要很方便得 其实还得 TG

Hangjau 发表于 2021-9-16 14:38

kkfgef 发表于 2021-9-16 14:07
请问是推送到关注 企业号 后的聊天窗口吗,这个 助理 是什么来的?

是的, 这个名字就是创建应用的名字。可以任意改的
页: [1] 2 3 4 5 6 7
查看完整版本: 微信bot推送库