Skip to content
This repository has been archived by the owner on Jun 24, 2020. It is now read-only.

功能请求: Python SDK退出功能和手动绑定、解绑处理函数的功能 #8

Open
SuperMarioSF opened this issue May 3, 2018 · 2 comments

Comments

@SuperMarioSF
Copy link
Contributor

SuperMarioSF commented May 3, 2018

由于一些需求,我需要能够在Python SDK中手动通过CQHttp类的方法来绑定和解绑处理函数,并且无法使用装饰器。
此外,由于相同的需求,我需要能够正确停止掉Python SDK的全部线程。目前是一旦初始化CQHttp对象并调用了run()方法,Bottle总是会有一个线程在后面持续运行不退出,结果导致必须按Ctrl+C终止。

以下是一些方法命名与参数的建议,如果起名困难的话可以参考一下这里。
更新: 重新阅读源码之后发现给出的建议参数列表中有一些不妥之处,已修改。

from typing import Callable, Iterable

class CQHttp(...):
    # 停止本地SDK的线程,如需重新启动bot则需重新启动CQHttp.run()。
    def sdk_local_stop() -> None:
        pass

    # 通过方法注册处理函数
    def set_handler(post_type: str, handler: Callable, types: Iterable=None) -> None:
        pass

    # 通过方法解除已经注册的函数
    def unset_handler(post_type: str, types: Iterable=None) -> None:
        pass

感谢你对本功能请求的关注。

@SuperMarioSF
Copy link
Contributor Author

SuperMarioSF commented May 3, 2018

于是试着实现了一下关于手动注册与解除注册处理函数的功能,可供参考。

from functools import wraps
from cqhttp import CQHttp as _CQHttp
from typing import Callable, Iterable

class CQHttp(_CQHttp):
    def set_handler(self, post_type: str,  func: Callable, types: Iterable=None):
        """
        设置回调处理函数

        --------------

        通常可以用 **@self.on_message** 、 **@self.on_request** 、 **@self.on_event** 这几个装饰器来设定回调函数,但在不允许使用装饰器的情况下,可以使用本方法设定回调函数。
        每个上报类型的每个特定信息类型只能设置一个处理函数。

        --------------

        :param str post_type: 上报类型,以下三者其一:"message"、"request"、"event"
        :param Callable func: 指定处理函数
        :param Iterable | None types: 信息类型。详情参见API文档中的消息与事件类型。默认为空,为空时注册该函数处理全部类型。
        :return: None
        """
        @wraps(func)
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)

        if types:
            for t in types:
                self._handlers[post_type][t] = wrapper
        else:
            self._handlers[post_type]['*'] = wrapper

    def unset_handler(self, post_type: str, types: Iterable = None):
        """
        删除回调处理函数

        --------------

        解除注册指定上报类型的回调函数。
        如果指定了信息类型,则只会解除所请求的信息类型的回调函数的注册。

        **注意**: 如果要单独解除默认监听全部信息类型的回调函数的注册,请指定 **['*']** 。如果不指定事件类型,将会解除整个上报类型的全部回调函数的注册。

        --------------

        :param str post_type: 上报类型,以下三者其一:"message"、"request"、"event"
        :param Iterable | None types: 信息类型。详情参见API文档中的消息与事件类型。默认为空,为空时解除整个上报类型的全部回调函数的注册。
        :return: None
        """

        if types:
            for t in types:
                self._handlers[post_type].pop(t)
            if len(self._handlers[post_type]) == 0:
                self._handlers.pop(post_type)
        else:
            self._handlers.pop(post_type)

@stdrc
Copy link
Member

stdrc commented Jun 2, 2018

关于关闭服务器的问题,我在 SDK v1.2.1 给 CQHttp 的实例增加了 wsgi 属性用于获取内部 WSGI 兼容的 app 对象,然后可以用 WSGI 服务器来部署,例如 CherryPy:

# deploy.py

from cherrypy import wsgiserver
from .demo import bot

d = wsgiserver.WSGIPathInfoDispatcher({'/': bot.wsgi})
server = wsgiserver.CherryPyWSGIServer(('0.0.0.0', 8080), d)

if __name__ == '__main__':
   try:
      server.start()
   except KeyboardInterrupt:
      server.stop()

这里 CherryPy 是支持从其它地方来关闭服务器的。除此之外还可以用 Gunicorn 等。


手动注册处理函数这个我再考虑考虑。

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants