Skip to content

插件 Plugin 的写法

更新于:几秒前
字数统计:830 字
阅读时长:3 分钟

关于路径

插件应该写在 plugins 文件夹下,可以是一个包或者是一个文件,但文件名、文件夹名中不能包含_字符

关于类

  1. 除了要使用ConversationHandler 的插件外,都要继承 core.plugin.Plugin

    python
    from core.plugin import Plugin
    
    
    class TestPlugin(Plugin):
        pass
    from core.plugin import Plugin
    
    
    class TestPlugin(Plugin):
        pass
  2. 针对要用 ConversationHandler 的插件,要继承 core.plugin.Plugin.Conversation

    python
    from core.plugin import Plugin
    
    
    class TestConversationPlugin(Plugin.Conversation):
        pass
    from core.plugin import Plugin
    
    
    class TestConversationPlugin(Plugin.Conversation):
        pass
  3. 关于初始化方法以及依赖注入

    初始化类, 可写在 __init____async_init__ 中, 其中 __async_init__ 应该是异步方法, 用于执行初始化时需要的异步操作. 这两个方法的执行顺序是 __init__ 在前, __async_init__ 在后

    若需要注入依赖, 直接在插件类的__init__方法中,提供相应的参数以及标注标注即可, 例如我需要注入一个 MySQL

    python
    from service.mysql import MySQL
    from core.plugin import Plugin
    
    class TestPlugin(Plugin):
       def __init__(self, mysql: MySQL):
           self.mysql = mysql
    
       async def __async_init__(self):
          """do something"""
    from service.mysql import MySQL
    from core.plugin import Plugin
    
    class TestPlugin(Plugin):
       def __init__(self, mysql: MySQL):
           self.mysql = mysql
    
       async def __async_init__(self):
          """do something"""

关于 handler

给函数加上 core.plugin.handler 这一装饰器即可将这个函数注册为handler

ConversationHandlerhandler

  1. 直接使用 core.plugin.handler 装饰器

    第一个参数是 handler 的种类,后续参数为该 handlercallback 参数外的其余参数

    python
    from core.plugin import Plugin, handler
    from telegram import Update
    from telegram.ext import CommandHandler, CallbackContext
    
    
    class TestPlugin(Plugin):
        @handler(CommandHandler, command='start', block=False)
        async def start(self, update: Update, context: CallbackContext):
            await update.effective_chat.send_message('hello world!')
    from core.plugin import Plugin, handler
    from telegram import Update
    from telegram.ext import CommandHandler, CallbackContext
    
    
    class TestPlugin(Plugin):
        @handler(CommandHandler, command='start', block=False)
        async def start(self, update: Update, context: CallbackContext):
            await update.effective_chat.send_message('hello world!')

    比如上面代码中的 command='start', block=False 就是 CommandHandler 的参数

  2. 使用 core.plugin.handler 的子装饰器

    这种方式比第一种简单, 不需要声明 handler 的类型

    python
    from core.plugin import Plugin, handler
    from telegram import Update
    from telegram.ext import CallbackContext
    
    
    class TestPlugin(Plugin):
        @handler.command(command='start', block=False)
        async def start(self, update: Update, context: CallbackContext):
            await update.effective_chat.send_message('hello world!')
    from core.plugin import Plugin, handler
    from telegram import Update
    from telegram.ext import CallbackContext
    
    
    class TestPlugin(Plugin):
        @handler.command(command='start', block=False)
        async def start(self, update: Update, context: CallbackContext):
            await update.effective_chat.send_message('hello world!')
Telegram
User 用户
/start
GrambBot 机器人
hello world!

对于 ConversationHandler

由于 ConversationHandler 比较特殊,所以一个 Plugin 类中只能存在一个 ConversationHandler

conversation.entry_pointconversation.stateconversation.fallback 装饰器分别对应 ConversationHandlerentry_pointsstatsfallbacks 参数

python
from telegram import Update
from telegram.ext import CallbackContext, filters

from core.plugin import Plugin, conversation, handler

STATE_A, STATE_B, STATE_C = range(3)


class TestConversation(Plugin.Conversation, allow_reentry=True, block=False):

    @conversation.entry_point  # 标注这个handler是ConversationHandler的一个entry_point
    @handler.command(command='entry')
    async def entry_point(self, update: Update, context: CallbackContext):
        """do something"""
        await update.effective_chat.send_message('hello')
        return STATE_A

    @conversation.state(state=STATE_A)
    @handler.message(filters=filters.TEXT)
    async def state(self, update: Update, context: CallbackContext):
        """do something"""
        await update.effective_chat.send_message('world!')

    @conversation.fallback
    @handler.message(filters=filters.TEXT)
    async def fallback(self, update: Update, context: CallbackContext):
        """do something"""

    @handler.inline_query()  # 你可以在此 Plugin 下定义其它类型的 handler
    async def inline_query(self, update: Update, context: CallbackContext):
        """do something"""
from telegram import Update
from telegram.ext import CallbackContext, filters

from core.plugin import Plugin, conversation, handler

STATE_A, STATE_B, STATE_C = range(3)


class TestConversation(Plugin.Conversation, allow_reentry=True, block=False):

    @conversation.entry_point  # 标注这个handler是ConversationHandler的一个entry_point
    @handler.command(command='entry')
    async def entry_point(self, update: Update, context: CallbackContext):
        """do something"""
        await update.effective_chat.send_message('hello')
        return STATE_A

    @conversation.state(state=STATE_A)
    @handler.message(filters=filters.TEXT)
    async def state(self, update: Update, context: CallbackContext):
        """do something"""
        await update.effective_chat.send_message('world!')

    @conversation.fallback
    @handler.message(filters=filters.TEXT)
    async def fallback(self, update: Update, context: CallbackContext):
        """do something"""

    @handler.inline_query()  # 你可以在此 Plugin 下定义其它类型的 handler
    async def inline_query(self, update: Update, context: CallbackContext):
        """do something"""
Telegram
User 用户
/entry
GrambBot 机器人
hello
User 用户
ok
GrambBot 机器人
world!

对于 Job

  1. 依然需要继承 core.plugin.Plugin
  2. 直接使用 core.plugin.job 装饰器 参数都与官方 JobQueue 类对应
python
from core.plugin import Plugin, job
   
class TestJob(Plugin):
   
   @job.run_repeating(interval=datetime.timedelta(hours=2), name="TestJob")
   async def refresh(self, _: CallbackContext):
   logger.info("TestJob")
from core.plugin import Plugin, job
   
class TestJob(Plugin):
   
   @job.run_repeating(interval=datetime.timedelta(hours=2), name="TestJob")
   async def refresh(self, _: CallbackContext):
   logger.info("TestJob")

注意

被注册到 handler 的函数需要添加 error_callable 修饰器作为错误统一处理

被注册到 handler 的函数必须使用 @restricts() 修饰器 预防洪水攻击ConversationHandler 外只需要注册入口函数使用

如果引用服务,参数需要声明需要引用服务的类型并设置默认传入为 None

必要的函数必须捕获异常后通知用户或者直接抛出异常

部分修饰器为带参修饰器,必须带括号,否则会出现调用错误

Contributors

luoshuijs
zhxycn

Telegram robot, query the official game information.