人类的本质就是斗图机。
想要在Telegram上斗图,那么必然就要用到MTProto了。对于pyrogram来说,那是非常简单的!
@app.on_message(filters.incoming) def sticker_handler(client: "Client", message: "types.Message"): chat_id = message.chat.id sticker = "CAACAgUAAxkBAAEHooZhc87afMQjB-c10tBfkdcH1VSAWwACjwEAAjMDHAiv-7CBCwXTrR4E" client.send_chat_action(chat_id, "typing") message.reply_sticker(sticker, quote=True)
sticker可以为表情包的文件路径、HTTP URL、或者是文件ID。
如有需要可以对filters进行各种定制,比如说我要某个用户给我发某个特定表情包时才斗图,那么filter大概可以这样写
@app.on_message(filters.sticker & filters.incoming & filters.user(user_id))
然后判断一下
if message.sticker.file_unique_id == "abcd": client.send_chat_action(chat_id, "typing") message.reply_sticker(sticker, quote=True)
小提示:如何获取user_id? 试试这个bot呢? https://t.me/blog_update_bot
那么这个sticker的ID怎么获取呢?笨办法是,找个小号帮忙发个表情就好了。
我的Telegram里明明添加了那么多表情包,如果能一键使用就好了。既然MTProto是公开的,那么也一定有办法。
Raw Functions
pyrogram封装了许多易于使用的方法,比如上面的发sticker,最常用的回复消息等等。但是实际上这些都利用了Raw Function。很多功能并没有封装成高层的 Python方法,非常不幸的是,获取sticker set便是其中之一。
想要使用raw functions也很简单啦
from pyrogram.raw import functions app.send( functions.account.UpdateProfile( first_name="Dan", last_name="Tès", about="Bio written from Pyrogram") )
获取全部已添加的sticker
获取全部sticker的函数是 functions.messages.GetAllStickers
于是你兴致勃勃写好了代码,并且猜测猜测send方法会有返回值
这是怎么回事?这个参数hash是什么?要怎么写?
其实这个hash是为了节约双方的资源的,有点像etag。具体可以看这里 https://core.telegram.org/api/offsets#hash-generation
我们这随便传入一个数字就可以了,这个接口获取到的数据大概是这种结构:
获取sticker set
上面的all_stickers
就包含了这个用户所收藏的所有sticker,每一个sticker set都是list的一个元素。
然后我们看下获取sticker set的API
functions.messages.GetStickerSet
接受一个神奇的参数 stickerset: "raw.base.InputStickerSet"
很多人可能会问,这是啥参数类型啊,怎么构造?
要从raw_types里去搞啦,type hint已经给了提示是 raw.base.InputStickerSet
from pyrogram.raw import types as raw_types raw_types.InputStickerSetID
InputStickerSetID
接受两个参数,一个是id
,一个是access_hash
那这个就不用我多说了吧,每一个set都有这两个参数
这样我们就能拿到一个sticker的全部信息了!数据结构大致如下
set字段,表示sticker set的基本信息,和上面的一样
packs和documents,表示单个sticker的信息
packs的结构比较简单,看起来像是个索引一样
documents的结构比较复杂,包含了缩略图等信息
那看起来这个document就是我们想要的了!那么继续用functions.messages.send_xxx
想想就痛苦,有没有办法利用pyrogram的send_stickersn呢?
那一大长串file_id
是什么啊?
转换为file_id
要使用古娜拉黑暗之神——呼呼拉——黑仙魔光才能把sticker变到file_id!
具体怎么做我教给你们就好了!不用探索其中原理……反正就是看pyrogram的send_sticker
是怎么实现的,然后逆着来嘛😝
from pyrogram.file_id import FileId, FileType file_id = FileId(file_type=FileType.STICKER, dc_id=doc.dc_id, file_reference=doc.file_reference, media_id=doc.id, access_hash=doc.access_hash, sticker_set_id=set_id, sticker_set_access_hash=set_hash).encode()
set_id
是set_access_hash
是sticker set的,media_id
和access_hash
是这个sticker的,不要搞错了哦。
然后生成的一长串字符串,就可以喂给 send_sticker
啦。
建议事先把所有的sticker的file_id都跑出来,然后随机从里面选就好了~要不然容易触发rate limit导致Durov送你飞机票。
欢乐斗图
为了斗图更快乐,我们也要搞的更欢乐更随机!
那么最简单的办法,其实就random一下就好了,先随机选sticker,然后再自定义回复概率,比如我想要一半概率回复,那就……
if random.choice([1, 0]): client.send_chat_action(chat_id, "typing") message.reply_sticker("sticker file_id", quote=True)
或者比如我想要79%的概率回复,那就……
random.randint(1, 100) <= 79
要想要每次都随机的回复概率,那其实也不难
rand1 = random.randint(1, 100) rand2 = random.randint(1, 100) if rand1 > rand2: pass
当然啦,上述算法从整体上来讲,回复概率是50%的,样本数量越大就会越近于50%。毕竟嘛,要么发要么不发,这范围还是一样的……那肯定50%啦。
斗图结果
自然是非常开心了,24小时随时回复!小伙伴都惊呼我竟然大半夜不睡觉!