Petpet - 生成各种奇怪的图片
-
Petpet - 生成各种奇怪的图片
已更新 5.3版本, 支持多线程, 可自定义 头像 文字 坐标 概率 关键词 频率限制 等参数
项目地址
releases
如果你觉得此插件对你有帮助, 请在此帖下回复
不错的插件
让更多人看到, 这对我非常重要!
Petpet
自定义合成图片的 Mirai 插件 / 独立程序, 灵感/部分数据来自 nonebot-plugin-petpet。
原生 java 编写, kotlin仅用于数据序列化, 使用底层API, 多线程优化: 轻量, 高性能, 易拓展
使用方法
-
下载 最新版本
-
将插件放入
Mirai/plugins/
-
下载 图片素材
-
将图片素材放入
Mirai/data/xmmt.dituon.petpet
-
使用 戳一戳 有
30%
的概率触发; 或发送pet @xxx
pet key @xxx
或key @xxx
可返回指定图片 例如pet kiss @xxx
kiss @xxx
可通过发送的图片生成Petpet
kiss [图片]
, 支持GIF可通过回复构造图片, 例如
[图片]
->[回复[图片]] 对称
可使用
pet
指令 获取keyList
以上配置 均可在配置文件中修改
配置文件
首次运行 Petpet 插件时,会生成
Mirai/config/xmmt.dituon.petpet/Petpet.yml
文件配置项说明
<details>
<summary>展开/收起</summary>
<br/>- command:
pet
触发petpet指令, 默认为
pet
例:
pet @xxx
pet kiss @xxx
仅发送
pet
时会返回keyList
<br/>- probability:
30
戳一戳 触发概率,
0-100
整数, 默认为30%
<br/>- antialias:
true
画布抗锯齿, 默认为
true
<br/>- disabled:
[]
禁用表列, 默认为空, 在此数组中的
key
不会被随机触发 (会覆盖data.json
中的配置)
<br/>- keyCommandHead:
''
key
作为指令头时的前缀, 默认为空例 (配置项为
'#'
时):#kiss @xxx
osu hso!
<br/>- respondReply:
true
响应回复的消息, 默认为
true
可通过回复消息 定位到之前发送的图片并构造petpet
启用后 会缓存接收到的图片(见
cachePoolSize
)例 :
[回复[图片]]kiss
(等价于kiss [图片]
)
<br/>- cachePoolSize:
10000
respondReply=true
时, 图片消息缓存池大小, 默认为10000
本质为
HashMap<imageId(long), imageUrl(String)>
, 超过此限制会清空Map
<br/>- respondSelfNudge:
false
某些情况下, 机器人会主动戳其他成员, 响应机器人自己发出的戳一戳, 默认为
false
<br/>- keyListFormat:
FORWARD
发送
pet
时keyList
响应格式, 默认为FORWARD
枚举:
MESSAGE
(发送普通消息)FORWARD
(发送转发消息)IMAGE
(发送图片)
<br/>- disablePolicy:
FULL
发送
pet on/off
时 禁用哪些功能, 默认为FULL
枚举:
NONE
(无效)NUDGE
(只禁用戳一戳)MESSAGE
(只禁用指令)FULL
(同时禁用戳一戳和指令)- fuzzy:
false
模糊匹配用户名, 默认为
false
例 : (配置项为
true
时):kiss @田所浩二
(响应)kiss 浩二
(响应)
<br/>- strictCommand:
true
严格匹配指令, 默认为
true
人话: 可以省略key后的空格例 : (配置项为
false
时):kiss 田所
(响应)kiss田所
(响应)
<br/>- synchronized:
false
消息事件同步锁, 会锁住相同的消息事件, 默认为
false
人话: 多机器人对于同一条指令只有一个会响应
<br/>- gifEncoder:
ANIMATED_LIB
GIF编码器, 默认为
ANIMATED_LIB
枚举:
BUFFERED_STREAM
:
基于缓存的STREAM
流, 在编码过程中对Gif进行压缩;- 编码速度较慢, 所需堆内存小, 生成Gif体积小
ANIMATED_LIB
:
基于byte[]
序列, 使用多线程分析像素;- 编码速度极快, 所需堆内存较多, 生成Gif体积较小
SQUAREUP_LIB
:
基于int[][]
数组, 编码时不使用awt
库, Gif压缩比低;- 编码速度极慢, 所需堆内存多, 生成Gif体积较大
<br/>
- gifMaxSize:
[]
GIF缩放阈值/尺寸, 默认为空 (不限制)
[width, height, frameLength]
:当Gif长度超过
frameLength
时, 会对Gif进行等比例缩放注: 缩放在图片合成时进行, 不会影响性能
例: (配置项为
-200 -200 -32]
时)- 当Gif长度超过
32
帧时, 检查Gif尺寸 - 当Gif尺寸大于
200*200
时, 对Gif进行等比例缩放 - Gif缩放后 最长边不会超过设定值
(当Gif中包含40
帧, 尺寸为300*500
时) - 输出的Gif长度不变, 尺寸为
120*200
- gifQuality:
10
Gif编码质量(
1
-99
), 默认为10
数字越小, 速度越慢, 质量越好 (大于
20
时, 速度不会有明显提升)仅适用于
ANIMATED_LIB
编码器- headless:
true
启用
headless
模式, 默认为true
人话: 有些服务器没有输入输出设备, 画图库无法正常运行, 启用这个配置项可以修复, 因为总是有人不看常见问题, 干脆默认启用了(
<br/>- autoUpdate:
true
自动更新
PetData
, 每次启动时都会检查并自动下载船新pet, 默认为true
注: 仅更新
PetData
, 不会更新插件版本, 请放心食用人话: 每次启动都会自动下载新的超赞梗图, 墙裂推荐
<br/>- repositoryUrl:
'https://dituon.github.io/petpet'
仓库地址, 用于自动更新, 默认为此仓库的
github page
- devMode:
false
开发模式, 启用后任何人都能使用
pet reload
指令热重载PetData
, 默认为false
<br/>- coolDown:
10
成功触发指令后对该用户的冷却时间(单位为秒), 默认为
1
设置为
-1
可禁用冷却
<br/>- groupCoolDown:
-1
成功触发指令后对该群聊的冷却时间, 默认为
1
<br/>- inCoolDownMessage:
技能冷却中...
在冷却时间中触发命令的回复消息
配置项为
[nudge]
时, 会以戳一戳形式回复
<br/></details>
修改后重启 Mirai 以重新加载
权限管理
群主或管理员使用
pet on
pet off
以 启用/禁用 戳一戳pet on/off
指令控制的事件可在配置文件中更改可在配置文件中禁用指定key, 被禁用的key不会随机触发, 但仍可以通过指令使用
图片预览
项目地址
key 预览 acclaim喝彩 欢呼 bible圣经 典中典 breakdown惊吓 击穿 carte佩可莉姆 菜单 单页 hold_sign唐可可 举牌 应援 kurumi胡桃 放大 monad唐可可 拍 单页 point_tv康纳 电视 remake泥头车 创 重开 reward伊蕾娜 赏金 报酬 watch_tv汤姆 电视 certificate喜报 anyasuki阿尼亚 喜欢 bite啃 咬 breast胸 凶 cast丢 center_symmetry中心对称 左上对称 coupon陪睡 cover_face挡 crawl爬 decent_kiss抱歉 distracted注意力 dont_touch不要靠近 down_symmetry对称 下对称 上下对称 eat吃 fencing击剑 🤺 garbage垃圾桶 垃圾 探头 hammer锤 interview采访 jiujiu么么 keep_away远离 kiss亲 热吻 knock敲 打 left_down_symmetry中心对称 左下对称 leg蹭 like永远喜欢 loading加载 加载中 make_friend加好友 marry结婚 nano纳米科技 need需要 osu painter画 pat拍 perfect完美 petpet摸 摸头 play玩 顶 police警察 pound捣 pr舔屏 punch打拳 record唱片 right_down_symmetry中心对称 右下对称 right_symmetry对称 右对称 左右对称 right_up_symmetry中心对称 右上对称 roll滚 推 rub舔 prpr safe_sense安全感 suck吸 support精神支柱 symmetry对称 左对称 左右对称 tear撕 thinkwhat想 throw扔 thump锤 tightly黏 twist抱 up_symmetry对称 上对称 上下对称 wallpaper瑞克 壁纸 worship膜拜 yoasobi群青 自定义
data.json
./data/xmmt.dituon.petpet/
下的目录名为key
,插件启动时会遍历./data/xmmt.dituon.petpet/$key/data.json
data.json
标准如下 (以thump/data.json
为例)// *为必须参数 { "type": "GIF", // 图片类型(enum)* "avatar": [{ // 头像(avatarObj[])*, 详见下文 "type": "TO", "pos": [ [65, 128, 77, 72], [67, 128, 73, 72], [54, 139, 94, 61], [57, 135, 86, 65] ], "round": true, "avatarOnTop": false }], "text": [], // 文字(textObj[])*, 详见下文 "inRandomList": false, // 在随机列表中(bolean) "reverse": false, // GIF倒放(bolean) "delay": 50, // 帧间延时(ms/int), 默认为65 "background": {}, // 背景(obj), 详见下文 "alias": [ "别名1", "别名2" ], // 别名(str[]) "hidden": false // 隐藏(bolean) }
部分配置项设计参考了
CSS
标准, 并尽可能实现CSS
渲染效果图片类型枚举
type
GIF
动图IMG
静态图片
坐标
坐标的基本组成单位是 4长度
int[]
数组其中,前两项为 左上角顶点坐标, 后两项为 宽度和高度
例:
[65, 128, 77, 72]
即 头像的左上角顶点坐标是(65,128)
, 宽度为77
, 高度为72
如果是
GIF
类型,坐标应为二维数组,GIF
的每一帧视为单个图像文件"pos": [ // pos的元素对应GIF的4帧 [65, 128, 77, 72], [67, 128, 73, 72], [54, 139, 94, 61], [57, 135, 86, 65] ],
如果是
IMG
类型, 可以使用一维数组"pos": [0, 0, 200, 200]
4.0
版本后, 坐标支持变量运算, 例如[100,100,"width/2","height*1.5^2"]
仿射变换/图像变形
坐标格式枚举
posType
ZOOM
缩放(见上文)DEFORM
变形
DEFORM
坐标格式为[[x1,y1],[x2,y2],[x3,y3],[x4,y4],[x_anchor,y_anchor]]
;
分别对应图片的[[左上角],[左下角],[右下角],[右上角],[锚点]]
,四角坐标用相对于锚点的偏移量表示目前仿射变换仅支持单帧
头像
3.0
版本后 提供了更灵活的头像构造方法, 与之前的版本有很大差别"avatar": [ { "type": "FROM", //头像类型枚举(enum), 非空 "pos": [[92, 64, 40, 40], [135, 40, 40, 40], [84, 105, 40, 40]], // 坐标 "round": true, // 值为true时, 头像裁切为圆形, 默认为false "avatarOnTop": true, // 值为true时, 头像图层在背景之上, 默认为true "angle": 90, // 初始角度 "opacity": 0.5 // 不透明度 }, { "type": "TO", "pos": [[5, 8], [60, 90], [50, 90], [50, 0], [60, 120]], "posType": "DEFORM", // 图像变形 坐标格式, 默认为ZOOM "antialias": true, // 抗锯齿, 对头像单独使用抗锯齿算法, 默认为false "rotate": false // 值为true时, GIF类型的头像会旋转, 默认为false }, { "type": "GROUP", "pos": [[182, 64, "width/2", "height*1.5^2"], [225, 40, "40", 40], [174, 105, 40, "height+width"]], // 支持变量运算 "crop": [0, 0, 50, 100], // 图片裁切坐标[x1, y1, x2, y2], 可简写为 [50, 100] "cropType": "PERCENT", // 裁切格式, 默认为NONE "style": [ // 风格化 "MIRROR", "GRAY" ], "fit": "CONTAIN" // 填充模式, 默认为 FILL } ]
在
IMG
中, 当rotate = true
时, 头像会随机旋转角度,angle
为最大值(angle = 0
时, 随机范围为0-359
)头像类型枚举
type
FROM
发送者头像TO
接收者头像, 或构造的图片GROUP
群头像BOT
机器人头像RANDOM
随机头像 (随机从群聊成员中选择, 不会重复)
裁切格式枚举
cropType
NONE
不裁切PIXEL
按像素裁切PERCENT
按百分比裁切
风格化枚举
style
MIRROR
水平镜像FLIP
上下翻转GRAY
灰度化BINARIZATION
二值化
填充模式
fit
CONTAIN
缩小以适应画布, 不改变原比例COVER
裁切以适应画布, 不改变原比例FILL
拉伸, 改变原比例
坐标变量
width
原图宽度height
原图高度
文字
如果你想在图片上添加文字,可以编辑
text
"text": [ // 这是一个数组, 可以添加很多文字 { "text": "Petpet!", // 文字内容 "color": "#66ccff", // 颜色, 默认为#191919 "pos": [100, 100], // 坐标, 默认为 [2,14] "size": 24 // 字号, 默认为12 }, { "text": "发送者: $from, 接收者: $to", // 支持变量 "color": [0,0,0,255], // 颜色可以使用RGB或RGBA的格式 "pos": [20, 150], // 坐标 "position": ["CENTER", "BOTTOM"], //坐标计算基准([x, y]) "font": "宋体", // 字体, 默认为黑体 "strokeColor": "#ffffff", // 描边颜色 "strokeSize": 2 // 描边宽度 }, { "text": "$txt1[我]超市$txt2[你]!", // 支持关键词变量 "pos": [0,200,300], // 第三个值为文本最大宽度 "align": "CENTER", // 对齐方式, 默认为LEFT "wrap": "ZOOM", // 显示设置, 默认为NONE "style": "BLOD", // 字体样式, 默认为PLAIN "greedy": true // 贪婪匹配模式, 会匹配多余的关键词 } ]
变量
$from
: 发送者, 会被替换为发送者群名片,如果没有群名片就替换为昵称$to
: 接收者, 被戳或At的对象, 发送图片构造时为"你"$group
: 群名称$txt(i)[(xxx)]
: 文本变量, 可用于生成meme图, i为关键词索引, xxx为默认值; 例:$txt1[我]超市$txt2[你]
指令为pet [key] 我 你
需要更多变量请提交 Issue
font
在
data/fonts
目录下的字体文件会注册到环境中align
LEFT
: 左对齐RIGHT
: 右对齐CENTER
: 居中对齐
wrap
NONE
: 不换行BREAK
: 自动换行ZOOM
: 自动缩放
使用
BREAK
或ZOOM
时,maxWidth
默认为200
style
PLAIN
: 默认BLOD
: 粗体ITALIC
: 斜体
position
LEFT
: 左定位(默认)RIGHT
: 右定位TOP
: 上定位(默认)BOTTOM
: 下定位CENTER
: 居中定位
background
4.0
版本后, 支持动态创建画布"background": { "size": ["avatar0Width*2","avatar0Height"], //支持变量运算 "color": "#f0f0f0" //支持hex或rgba数组 }
坐标变量
avatar(i)Width
i
号头像(i
为定义头像时的顺序, 从0
开始)处理后的宽度avatar(i)Height
i
号头像处理后的高度text(i)Width
i
号文本渲染后的宽度text(i)Height
i
号文本渲染后的高度
WebServer
除了作为
Mirai
插件,Petpet
也可以作为http服务器单独运行, 可被其它项目/语言使用java -jar petpet.jar
启动时会生成
config.json
:{ "port": 2333, // 监听端口 "webServerThreadPoolSize": 10, // HTTP服务器线程池容量 "dataPath": "data/xmmt.dituon.petpet", // PetData路径 "gifMaxSize": [200, 200, 32], // GIF缩放阈值, 详见上文 "gifEncoder": "ANIMATED_LIB", // GIF编码器, 详见上文 "gifQuality": 100, // GIF质量, 详见上文 "gifMakerThreadPoolSize": 0, // GIF编码器线程池容量, 详见上文 "headless": true // 使用headless模式 }
程序使用
com.sun.net.httpserver
实现http服务器
PetServer API
访问
127.0.0.1:2333/petpet
以获取PetDataList
GET
使用
GET
传递参数, 例如127.0.0.1:2333/petpet?key=petpet&toAvatar=$avatarUrl
127.0.0.1:2333/petpet?key=osu&textList=hso!
结构
<details>
<summary>展开/收起</summary>key
(str): 对应PetData
,例如kiss
rub
fromAvatar
toAvatar
groupAvatar
botAvatar
(url): 头像URL地址,encodeURIComponent(rawUrl)
randomAvatarList
(url[]): 随机头像列表, 使用,
分割多个urlfromName
toName
groupName
(str): 昵称, 有默认值textList
(str): 根据空格分割此字符串, 作为额外数据
</details>
POST
使用
POST
传递参数, 例如127.0.0.1:2333/petpet
{ "key": "petpet", "to": { "name":"d2n", "avatar":"https://q1.qlogo.cn/g?b=qq&nk=2544193782&s=640" }, "randomAvatarList": [ "url" ], "textList": [ "test" ] }
可参考
example-script
中的代码实现请求更多示例请参考
example-script
常见问题
-
戳一戳无法触发?
检查 Mirai 登录协议, 仅
ANDORID_PHONE
可以收到 戳一戳 消息 -
没有生成配置文件?
Mirai 2.11.0
提供了新的JavaAutoSaveConfig
方法, 请更新Mirai版本至2.11.0
(不是2.11.0-M1
), 旧版本不支持自定义配置项 -
Exception in coroutine <unnamed>
?图片素材应位于
Mirai/data/xmmt.dituon.petpet
目录下, 请检查路径 -
Could not initialize class java.awt.Toolkit
?对于无输入输出设备的服务器 需要启用
headless
-
自动更新下载速度慢 / 无法连接远程资源?
修改
Petpet.yml
中repositoryUrl
的值为'https://ghproxy.com/https://raw.githubusercontent.com/Dituon/petpet/main'
(高速镜像) -
自动更新后 读取
data.json
出错?自动更新时网络出错导致, 删除出错的文件 重新获取即可
-
其它错误? 问题?
若此文档无法解决您的问题, 欢迎提交
issue
性能 & 兼容性
程序使用底层
java.awt
类合成图片, 渲染时使用多线程, 静态图片渲染时间一般不会超过1ms
对GIF编码器的分析, 转换, 映射部分进行多线程优化, 速度极快
Android JVM没有实现
java.awt
, 推荐使用JDK 11+
版本分享你的作品 (模板)
如果你想分享自定义的 Petpet, 欢迎Pr
二次开发
程序提供超多实用API 拓展性极强, 附有互动式开发实例, 欢迎初学者学习!
-
在别的项目二次开发: mirai-simplepetpet-plugin
后话
如果此插件和您预期的一样正常工作,请给我一个
star
并在此帖下回复欢迎提交任何请求
交流群:
828350277
-
-
这个使用的意思是输入pet之后有30%概率发送一张随机的合成图片,不能指定发送哪个图片吗
-
@立于羽下 我也觉得()
-
能支持自定义发送概率吗
-
@YoinSama 请提交issue,近期更新
-
@立于羽下 是的,欢迎进行二次开发或提交issue
-
@YoinSama 已更新。
-
-
搬运一下
README.md
... -
有没有可能我是懒鬼
我只想有自行添加gif背景的功能 -
@dr_chenzs 使用
sendImage
快速进行二次开发 -
@Dituon 插件不错,群U很喜欢,下次还会光顾☺️☺️
-
击剑🤺🤺.GIF
-
@1106095212 谢谢😘
-
@xiaolu 🤺🤺
-
很不错的功能
-
很棒的插件!
-
图片素材下载完后似乎找不到安放的目录,jar包塞进plugins后生成了json,似乎除了json和jar包之外没有别的生成的文件夹了。是哪里遗漏了吗?
-
@豹离SIU 图片目录要自行创建
-
okok,之前把res丢进data里面搜不出来,现在把res放到mcl文件夹里就好了