Nonebot2插件:逝世表情包(1)

前言已经懒得写辣,总之把入门教程官方文档都看一遍

纯小白,排版混乱,逻辑重复,代码屎山,随时跑路

广告 长期招租,快来404群玩(720053992)

0.废话文集

搓表情包的想法之前看群里的bot可以生成就好想搞了,只是一直鸽——

总之官方商店里有强大的petpet和memes两个插件,已经足够满足大部分的表情包生成需求了(实际看下来常用的就两三个)

代码全copy(bushi
总而言之,这篇将会是实现的是下面这个表情包

嘿嘿

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.大概问题

  1. 头像的位置大小和想要生成的字体类型都可以按照自己的需求改,只要计算预留出足够的空间即可
  2. 考虑到有的群友id实属逆天(的长度),生成第一行的时候可以考虑先获取总共的字节数,然后按照预留的宽度大小计算出最适合的字体大小(不过更简单的是按比例直接生成更大的画布?)
  3. 对id中的特殊字符不太适应
posted @ 2022-05-21 18:35  FPICZEIT  阅读(413)  评论(0编辑  收藏  举报