Nonebot2插件:逝世表情包(1)
前言已经懒得写辣,总之把入门教程官方文档都看一遍
纯小白,排版混乱,逻辑重复,代码屎山,随时跑路
广告
长期招租,快来404群玩(720053992)0.废话文集
搓表情包的想法之前看群里的bot可以生成就好想搞了,只是一直鸽——
总之官方商店里有强大的petpet和memes两个插件,已经足够满足大部分的表情包生成需求了(实际看下来常用的就两三个)
总而言之,这篇将会是实现的是下面这个表情包
0.5 水准备
使用了python的PIL(pillow)库来生成图片,(openCV的对着类似实现函数做下就好了吧)
用到了requests库(用于获取用户头像)
1.startswith!
设定的指令触发格式为"设定的命令起始符+找+@用户/qq号码+需要填写的字段(非必须)"
使用on_command() 作为事件响应器
大概前面
import nonebot
import requests
from nonebot.rule import *
from nonebot import *
from nonebot.plugin import on_keyword
from nonebot.adapters.onebot.v11 import Bot, Event, MessageEvent, GroupMessageEvent
from nonebot.adapters.onebot.v11.message import Message
import os
import re
import PIL
from PIL import Image, ImageDraw, ImageFont
async def handle_rule(bot: Bot, event: Event) -> bool:
with open("白名单群聊txt", encoding='utf-8') as file: # 提取白名单群文件中的群号
white_block = []
for line in file:
line = line.strip()
line = re.split("[ |#]", line) # 可能会有'#'注释或者空格分割
white_block.append(line[0]) # 新建一个表给它扔进去
try:
whatever, group_id, user_id = event.get_session_id().split('_') # 获取当前群聊id,发起人id,返回的格式为group_groupid_userid
except: # 如果上面报错了,意味着发起的是私聊,返回格式为userid
group_id = None
user_id = event.get_session_id()
if group_id in white_block or group_id == None:
return True
else:
return False
ct_pic_find = on_command({"找"}, rule=handle_rule, priority=50)
@ct_pic_find.handle()
async def ct_pic_find_handle(bot: Bot, event: Event):
try:
whatever, group_id, user_id = event.get_session_id().split('_') # 获取当前群聊id,发起人id,返回的格式为group_groupid_userid
data = await bot.call_api('get_group_member_list', **{
'group_id': int(group_id)
})
except: # 如果上面报错了,意味着发起的是私聊,返回格式为userid
group_id = None
user_id = event.get_session_id()
find_message = str(event.get_message()).replace('/找', '').split()
'''
nb2会过滤消息段中的第一个@自己的消息,所以那自己bot试的注意下(比如我查了半天报错)
上面这段按照指令格式进行分段
'''
if "[CQ" in find_message[0]: # 简单粗暴地判断下第一个分类是不是@类
for sbwwww in event.get_message():
if sbwwww.type == 'at':
pic_id = sbwwww.data['qq']
break # 读取完第一个退出即可
'''
Nb2的Messagement类会可以直接提取cq码的类型
这样就可以直接获取@的对象了
https://github.com/botuniverse/onebot-11/tree/master/message
Nb2的Message适配Onebot v11协议,所以好好看看上面的文档吧
同样的,file(图片缓存名称和地址),flash(闪照)等等都会用到
下面这段是还没啃透时自己的写法,使用正则匹配获取@的id号码(要用\转义下[])
pic_id = re.search('(?<=\[CQ:at,qq=).*?(?=\])', find_message[0]).group()
'''
else: # 如果不是@的人的形式,判断是否为中间给定的是否为QQ号的形式
try:
if find_message[0].isnumeric(): # 判断是否为全为数字字符
pic_id = find_message[0]
else:
await ct_pic_find.finish(Message("你找谁啊...."))
except:
await ct_pic_find.finish(Message("你找谁啊...."))
try:
pic_name = find_message[1] # 接着获取名字(请问看见xxx了吗)
except:
pic_name = ''
if pic_name == '': # 如果用户没有输入想要生成的名字,那么默认为群聊昵称,其次为QQ昵称
if isinstance(event, GroupMessageEvent): # 判断是否为群聊事件
for j in data:
if str(j['user_id']) == pic_id: # 如果想找的人在群聊内
if j['card'] != '': # 判断是否存在群昵称,并赋值
pic_name = j['card']
else:
pic_name = j['nickname']
if pic_name == '': # 如果是私聊事件或者不在群聊内
data = await bot.call_api('get_stranger_info',
**{'user_id': int(pic_id)}) # 参考go-cqhttp的官方api说明,获取陌生人的相关个人资料
pic_name = data['nickname']
user_name = pic_name
接着来对图片进行处理,示例中的表情包是(900,800),其中用户头像为(600,600),字号使用为("simhei", 50)
点我看代码~
user_url = f"http://q1.qlogo.cn/g?b=qq&nk={pic_id}&s=640"
'''
这个url获取的是任意一个用户的高清头像,pic_id就是指定的QQ号,之后会常用
'''
picfile = requests.get(user_url)
open(f"你头像图片存放的地址", "wb").write(picfile.content) # 从网上下载图片并保存到本地,若存在会覆写的
user_pic = Image.open(f"你头像图片存放的地址") # 准备复制
user_image = Image.new(mode="RGB", size=(900, 800), color="white") # 生成一块900*800的白色画布,具体自己定
user_pic = user_pic.resize((600, 600)) # 把获取到的用户图片resize一下,因为大部分图片并不是600*600
user_image.paste(user_pic, (150, 100)) # 放到指定位置,按照自己预留给文字的位置算一下(下面所有的涉及到位置的都建议使用自己的喜好)
# 添加文字
draw = ImageDraw.Draw(user_image)
font = ImageFont.truetype("simhei", 50)
word = f'请问你们看见{user_name}了吗' # 文案自己定
w, h = font.getsize(word) # 获取指定大小和文本后的字段长度,用于生成居中字体
# 参数:位置、文本、填充、字体
draw.text(xy=((900 - w) / 2, (100 - h) / 2), text=word, fill='black', font=font)
word = '非常可爱,简直是小天使,让大家都看看'
w, h = font.getsize(word)
draw.text(xy=((900 - w) / 2, 700 + (100 - h) / 2), text=word, fill='black', font=font)
user_image.save(f"生成完的表情包存放的地址")
user_url = f"file:///生成完的表情包存放的地址"
await ct_pic_find.finish(Message(f"[CQ:image,file={user_url},id=40000]"))
示例:大概就头图吧
2.大概问题
- 头像的位置大小和想要生成的字体类型都可以按照自己的需求改,只要计算预留出足够的空间即可
- 考虑到有的群友id实属逆天(的长度),生成第一行的时候可以考虑先获取总共的字节数,然后按照预留的宽度大小计算出最适合的字体大小(不过更简单的是按比例直接生成更大的画布?)
- 对id中的特殊字符不太适应