Pyrogram Telegram Bot小纸条(二)

运用Pyrogram的Smart Plugins

·

2 min read

在我写的所有的Telegram Bot项目中,都希望它是一个灵活的部分。在以前的python-telegram-bot的项目里,我都会使用一个文件,将所有的command处理放在不同的文件里,然后一一import进去,后来也有一些朋友把它再写成配置文件什么,为的就是能够简单配置一个Bot能有不同的功能。在pyrogram里,特别提供了一套Smart Plugins以达成这样的效果。由于我非常喜欢使用这套预制的plugins机制,所以第二个文章就用来说明这个Smart Plugins。

普通的Bot

我们先写一个普通的bot,如果你没有特别的需要,一个文件的bot非常适合你。以下是一个简单的代码:

from pyrogram import Client, filters
from pyrogram.types import Message

app = Client("hdcola")


@app.on_message(filters.command("help"))
async def help(client: Client, message: Message):
    await message.reply(f"have to help {message.text}")


@app.on_message(filters.regex("你好"))
async def hello(client: Client, message: Message):
    await message.reply("我很好")


@app.on_message(filters.text & filters.private)
async def echo(client: Client, message: Message):
    await message.reply(message.text)

app.run()

这个Bot实现了三个功能:

  • 收到一个/help命令,回复have to help 后面跟着你发出来的命令的全部内容。
  • 收到一个"你好",回复"我很好"
  • 收到别的任何信息,都echo一个相同的信息

image.png

运用Smart Plugins

在普通的Bot里,如果我们想将三个功能放到一个单独的文件里去,你就需要写单独的import,而且每增加一个文件,就需要多一个import。所以我们完全可以使用smart plugins来简化这个行为。我们只需要做以下几件事:

  • 建立一个目录,名为"plugins"
  • 将相关功能的代码移入这个目录,将@app更换为@Client
  • 在你的启动文件里声明plugins的目录名,并在初始化Client里传入参数

比如,我们将echo功能放入plugins,我们只需要在目录中建立一个echo.py,内容如下:

from pyrogram import Client, filters
from pyrogram.types import Message


@Client.on_message(filters.text & filters.private)
async def echo(client: Client, message: Message):
    await message.reply(message.text)

在启动文件中加入plugins:

from pyrogram import Client, filters
from pyrogram.types import Message

plugins = dict(root="plugins")
app = Client("hdcola", plugins=plugins)
app.run()

Smart Plugins还可以指定加载、指定不加载以及在运行时Load和Unload plugins,高级话题,我用pyrogram一年多还没用过这功能,所以大家可以去这里自行查阅

附注

启动目录

在所有文档里没有提到的是,在启动程序时,你的当前目录必须是你的plugins的父目录,否则无法找到相应的目录。你会得到一个类似这样的提示:[hdcola] No plugin loaded from "plugins"

Session存储

缺省使用的 File Storage

使用了smart plugins后,你的session文件存储目录就出了问题,这时怎么办更为优雅呢?Pyrogram 给出了一个叫做Memory Storage的存储方案,目的就是把session中的存储信息都放在内存里。普通模式下,Pyrogram的存储使用的是File Storage,它实质上就是一个SQLite的文件,当你登录认证成功后,这个文件即生成,以后你每次登录时都会打开这个DB文件,这是数据中的结构:

image.png

使用Memory Storage

我们都知道,SQLite还提供一个内存模式,所以你就可以使用内存模式来存储session信息,只需要在init Client时加入in_memory=True参数即可:

from pyrogram import Client

async with Client("my_account", in_memory=True) as app:
    print(await app.get_me())

但是这样做有一个问题,每次启动都需要进行一编重新认证的过程。

使用Session Strings

为了不让你使用in_memory模式时重复进行认证,pyrogram还提供了一个session strings的方式,使用起来的代码如下:

from pyrogram import Client

session_string = "...ZnUIFD8jsjXTb8g_vpxx48k1zkov9sapD-tzjz-S4WZv70M..."

async with Client("my_account", session_string=session_string) as app:
    print(await app.get_me())

通过给出session_string参数,你就可以使用in_memory模式,但不用每次都进行登录验证了。但是如何得到这个session_string呢?官方给出的代码如下:

from pyrogram import Client

async with Client("my_account", in_memory=True) as app:
    print(await app.export_session_string())

不过,这段代码并不能很好的运行,所以有一位兄弟在replit上提供了一个getStringName的代码你可以直接运行。其实它的代码只是让你使用起来更为友好一些,你也可以自己将这段代码放在你自己的机器上生成session strings:

from pyrogram import Client
print("""
Go to my.telegram.org
Login using your Telegram account
Click on API Development Tools
Create a new application, by entering the required details
Check your Telegram saved messages section to get your SESSION_NAME
"""
)
API_ID=int(input("Enter API ID: "))
API_HASH=input("Enter API HASH: ")

with Client(":memory:" ,api_id=API_ID ,api_hash=API_HASH, hide_password=False) as pyrogram:
    SESSION_NAME = "SESSION_NAME\n\n" + (pyrogram.export_session_string())
    print("\nGenerating your SESSION_NAME...\n")
    pyrogram.send_message("me", SESSION_NAME, parse_mode="html")
    print("Your SESSION_NAME have been sent to your Telegram Saved Messages")

他的代码并不够好,特别是当要生成一个Bot的Session string时就会出现错误,因为bot是无法给me(自己)发送信息的。晚些我会更新一下这段代码。到时大家会在这个文章看到更新的地址和代码的。

Did you find this article valuable?

Support 老房东的纸条箱 by becoming a sponsor. Any amount is appreciated!