dify-on-wechat中涉及企业微信几个函数解析

NtWork是基于PC企业微信的API接口,支持收发文本、群@、名片、图片、文件、视频、链接卡片等。

一.sigterm_handler_wrap()函数

代码位置:dify-on-wechat/app.py

这段代码的作用是在程序接收到特定信号时,保存用户数据,并根据原有的信号处理逻辑决定是否结束程序。

def sigterm_handler_wrap(_signo):
    old_handler = signal.getsignal(_signo)

    def func(_signo, _stack_frame):
        logger.info("signal {} received, exiting...".format(_signo))
        conf().save_user_datas()
        if callable(old_handler):  #  check old_handler
            return old_handler(_signo, _stack_frame)
        sys.exit(0)

    signal.signal(_signo, func)

这段代码定义了一个名为 sigterm_handler_wrap 的函数,它接受一个参数 _signo,这个参数代表一个信号的编号。这个函数的主要目的是为了处理程序接收到的特定信号。

首先,它获取当前已经设置的信号处理函数 old_handler,这是通过调用 signal.getsignal(_signo) 实现的。

然后,它定义了一个新的信号处理函数 func。这个函数在接收到信号时会被调用,它接受两个参数:信号编号 _signo 和栈帧对象 _stack_frame

func 函数内部,首先会记录一条日志,表示接收到了信号。然后,它会调用 conf().save_user_datas() 来保存用户数据。

接下来,它会检查 old_handler 是否是可调用的。如果是,那么就调用 old_handler,并将信号编号和栈帧对象作为参数传入。这样做的目的是为了保留原有的信号处理逻辑。

如果 old_handler 不是可调用的,那么就直接调用 sys.exit(0) 来结束程序。

最后,通过调用 signal.signal(_signo, func) 将新的信号处理函数 func 设置为 _signo 信号的处理函数。

二.signal.SIGINT和signal.SIGTERM

signal.SIGINTsignal.SIGTERM 是 Python 中的信号处理模块 signal 中的两个预定义信号。

1.signal.SIGINT

这个信号通常是由用户生成的,当用户在命令行中按下 Ctrl+C 时,就会发送 SIGINT 信号。这个信号的默认行为是终止进程,但是我们可以通过编程来改变这个行为。

2.signal.SIGTERM

这个信号通常是由 kill 命令发送的。它的默认行为也是终止进程,但是和 SIGINT 一样,我们也可以通过编程来改变这个行为。

在代码中,sigterm_handler_wrap(signal.SIGINT)sigterm_handler_wrap(signal.SIGTERM) 是为 SIGINTSIGTERM 信号设置了新的处理函数。当这两个信号被接收到时,会执行 sigterm_handler_wrap 函数中定义的 func 函数,这个函数会保存用户数据,然后根据原有的信号处理逻辑决定是否结束程序。

三.start_channel()函数

代码位置:dify-on-wechat/app.py

这个函数的作用是根据传入的通道名称创建一个通道对象,加载插件,可能会启动 linkai_client,并启动这个通道。

def start_channel(channel_name: str):
    channel = channel_factory.create_channel(channel_name)
    if channel_name in ["wx", "wxy", "terminal", "wechatmp", "wechatmp_service", "wechatcom_app", "wework", "wechatcom_service", const.FEISHU, const.DINGTALK]:
        PluginManager().load_plugins()

    if conf().get("use_linkai"):
        try:
            from common import linkai_client
            threading.Thread(target=linkai_client.start, args=(channel,)).start()
        except Exception as e:
            pass
    channel.startup()

这段代码定义了一个名为 start_channel 的函数,它接受一个参数 channel_name,这个参数代表一个通道的名称。

首先,它调用 channel_factory.create_channel(channel_name) 来创建一个通道对象,并将其赋值给变量 channelchannel_factory 是一个工厂对象,它的 create_channel 方法根据传入的通道名称创建对应的通道对象。

然后,它检查 channel_name 是否在一个特定的列表中。这个列表包含了 "wx", "wxy", "terminal", "wechatmp", "wechatmp_service", "wechatcom_app", "wework", "wechatcom_service", const.FEISHU, const.DINGTALK 等值。如果 channel_name 在这个列表中,那么就调用 PluginManager().load_plugins() 来加载插件。

接下来,它检查配置项 "use_linkai" 的值。如果这个配置项的值为真,那么就尝试从 common 模块导入 linkai_client,并在一个新的线程中启动 linkai_client。这个新线程的目标函数是 linkai_client.start,并将 channel 作为参数传入。如果在这个过程中发生任何异常,那么就忽略这个异常。

最后,它调用 channel.startup() 来启动这个通道。

四.企业微信中channel.startup()函数

代码位置:dify-on-wechat/channel/wework/wework_channel.py

这个方法的作用是启动企业微信的服务,获取并保存联系人和聊天室的信息,然后启动主循环。

def startup(self):
    smart = conf().get("wework_smart", True)
    wework.open(smart)
    logger.info("等待登录······")
    wework.wait_login()
    login_info = wework.get_login_info()
    self.user_id = login_info['user_id']
    self.name = login_info['nickname']
    logger.info(f"登录信息:>>>user_id:{self.user_id}>>>>>>>>name:{self.name}")
    logger.info("静默延迟60s,等待客户端刷新数据,请勿进行任何操作······")
    time.sleep(60)
    contacts = get_with_retry(wework.get_external_contacts)
    rooms = get_with_retry(wework.get_rooms)
    directory = os.path.join(os.getcwd(), "tmp")
    if not contacts or not rooms:
        logger.error("获取contacts或rooms失败,程序退出")
        ntwork.exit_()
        os.exit(0)
    if not os.path.exists(directory):
        os.makedirs(directory)
    # 将contacts保存到json文件中
    with open(os.path.join(directory, 'wework_contacts.json'), 'w', encoding='utf-8') as f:
        json.dump(contacts, f, ensure_ascii=False, indent=4)
    with open(os.path.join(directory, 'wework_rooms.json'), 'w', encoding='utf-8') as f:
        json.dump(rooms, f, ensure_ascii=False, indent=4)
    # 创建一个空字典来保存结果
    result = {}

    # 遍历列表中的每个字典
    for room in rooms['room_list']:
        # 获取聊天室ID
        room_wxid = room['conversation_id']

        # 获取聊天室成员
        room_members = wework.get_room_members(room_wxid)

        # 将聊天室成员保存到结果字典中
        result[room_wxid] = room_members

    # 将结果保存到json文件中
    with open(os.path.join(directory, 'wework_room_members.json'), 'w', encoding='utf-8') as f:
        json.dump(result, f, ensure_ascii=False, indent=4)
    logger.info("wework程序初始化完成········")
    run.forever()

这段代码是 WeworkChannel 类的 startup 方法,它的主要作用是启动企业微信(WeWork)的相关服务。首先,它从配置中获取 "wework_smart" 的值,如果没有这个配置项,则默认为 True。然后,它调用 wework.open(smart) 来打开企业微信的服务。

接着,它调用 wework.wait_login() 来等待用户登录。当用户登录后,它会获取登录信息,并将用户的 ID 和昵称保存到 self.user_idself.name 中。

然后,它会暂停 60 秒,等待客户端刷新数据。接下来,它会尝试获取企业微信的外部联系人(contacts)和聊天室(rooms)。如果获取失败,那么就会退出程序。

如果获取成功,那么就会将 contactsrooms 保存到本地的 JSON 文件中。同时,它还会遍历每个聊天室,获取聊天室的成员,并将结果保存到本地的 JSON 文件中。

最后,它会打印一条日志,表示企业微信的程序已经初始化完成,并调用 run.forever() 来启动主循环。

  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NLP工程化

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值