nonebot-plugin-randpic 1.2.2__tar.gz → 1.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/PKG-INFO +4 -3
- {nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/README.md +2 -2
- {nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/nonebot_plugin_randpic/__init__.py +50 -46
- {nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/nonebot_plugin_randpic/compress.py +6 -0
- {nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/pyproject.toml +2 -1
- {nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/LICENSE +0 -0
- {nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/nonebot_plugin_randpic/ali_oss.py +0 -0
- {nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/nonebot_plugin_randpic/config.py +0 -0
- {nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/nonebot_plugin_randpic/drivers/fastapi.py +0 -0
- {nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/nonebot_plugin_randpic/web.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nonebot-plugin-randpic
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: 一个通过指令随机发送你存储的图片的nonebot2插件
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
19
19
|
Requires-Dist: aiosqlite (>=0.13.0,<0.14.0)
|
|
20
20
|
Requires-Dist: alibabacloud_oss_v2 (>=1.1.0)
|
|
21
21
|
Requires-Dist: httpx (>=0.20.0,<1.0.0)
|
|
22
|
+
Requires-Dist: imagehash (>=4.3.0)
|
|
22
23
|
Requires-Dist: nonebot-adapter-onebot (>=2.1.5,<3.0.0)
|
|
23
24
|
Requires-Dist: nonebot-plugin-localstore (>=0.6.0,<0.7.0)
|
|
24
25
|
Requires-Dist: nonebot2[fastapi] (>=2.0.0,<3.0.0)
|
|
@@ -56,7 +57,7 @@ _✨ 一个发送指令就能让你的 bot 发出对应指令的图片的插件
|
|
|
56
57
|
|
|
57
58
|
你可以很方便地直接通过在配置文件里设置好触发指令(支持多个触发指令)后,在群聊中发送对应指令,从而使 Bot 随机发送出你所存储的图片。
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
插件除了能随机发送图片,还能在群聊内直接通过指令存储图片,同时为了避免重复加入同一张图片,该插件添加了图片感知哈希算法,相似的图片无法重复添加。
|
|
60
61
|
|
|
61
62
|
随机发送图片是利用 sql 语句随机选择指令。
|
|
62
63
|
|
|
@@ -224,7 +225,7 @@ randpic_oss_no_upload_list=["capoo"]
|
|
|
224
225
|
## TODO
|
|
225
226
|
- [x] 指令触发 bot 发送图片
|
|
226
227
|
- [x] 在 QQ 上让 bot 存储对应指令的图片
|
|
227
|
-
- [x]
|
|
228
|
+
- [x] 每次存储图片,判断相似图片是否已经存在,避免重复加入
|
|
228
229
|
- [X] 由capoo插件衍生成一个模板插件,即仅需修改参数就能发送别的图片
|
|
229
230
|
- [X] 添加图片压缩功能,避免图片文件夹空间过大
|
|
230
231
|
- [X] 以阿里云OSS对象存储搭建静态网页,便于浏览器查看图片
|
|
@@ -27,7 +27,7 @@ _✨ 一个发送指令就能让你的 bot 发出对应指令的图片的插件
|
|
|
27
27
|
|
|
28
28
|
你可以很方便地直接通过在配置文件里设置好触发指令(支持多个触发指令)后,在群聊中发送对应指令,从而使 Bot 随机发送出你所存储的图片。
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
插件除了能随机发送图片,还能在群聊内直接通过指令存储图片,同时为了避免重复加入同一张图片,该插件添加了图片感知哈希算法,相似的图片无法重复添加。
|
|
31
31
|
|
|
32
32
|
随机发送图片是利用 sql 语句随机选择指令。
|
|
33
33
|
|
|
@@ -195,7 +195,7 @@ randpic_oss_no_upload_list=["capoo"]
|
|
|
195
195
|
## TODO
|
|
196
196
|
- [x] 指令触发 bot 发送图片
|
|
197
197
|
- [x] 在 QQ 上让 bot 存储对应指令的图片
|
|
198
|
-
- [x]
|
|
198
|
+
- [x] 每次存储图片,判断相似图片是否已经存在,避免重复加入
|
|
199
199
|
- [X] 由capoo插件衍生成一个模板插件,即仅需修改参数就能发送别的图片
|
|
200
200
|
- [X] 添加图片压缩功能,避免图片文件夹空间过大
|
|
201
201
|
- [X] 以阿里云OSS对象存储搭建静态网页,便于浏览器查看图片
|
{nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/nonebot_plugin_randpic/__init__.py
RENAMED
|
@@ -15,10 +15,10 @@ from nonebot.params import Fullmatch
|
|
|
15
15
|
from urllib import parse
|
|
16
16
|
from urllib.parse import urlparse
|
|
17
17
|
import importlib
|
|
18
|
-
|
|
18
|
+
import imagehash
|
|
19
19
|
from .config import *
|
|
20
20
|
from .ali_oss import *
|
|
21
|
-
from .compress import compress_image_from_bytes, get_image_extension
|
|
21
|
+
from .compress import compress_image_from_bytes, get_image_extension, compute_phash
|
|
22
22
|
from .web import StaticImageGalleryGenerator
|
|
23
23
|
|
|
24
24
|
__plugin_meta__ = PluginMetadata(
|
|
@@ -77,8 +77,9 @@ async def create_dir():
|
|
|
77
77
|
await cursor.execute('DROP table if exists Pic_of_{command};'.format(command=command))
|
|
78
78
|
await cursor.execute('''
|
|
79
79
|
CREATE TABLE IF NOT EXISTS Pic_of_{command} (
|
|
80
|
-
|
|
81
|
-
img_url TEXT
|
|
80
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
81
|
+
img_url TEXT NOT NULL,
|
|
82
|
+
phash TEXT NOT NULL
|
|
82
83
|
)
|
|
83
84
|
'''.format(command=command))
|
|
84
85
|
await connection.commit()
|
|
@@ -123,12 +124,12 @@ async def create_dir():
|
|
|
123
124
|
with (path / filename).open('wb') as f:
|
|
124
125
|
f.write(data)
|
|
125
126
|
|
|
126
|
-
|
|
127
|
+
new_phash_str = compute_phash(data)
|
|
127
128
|
cursor = await connection.cursor()
|
|
128
129
|
command: str = randpic_command_tuple[index]
|
|
129
130
|
await cursor.execute(
|
|
130
|
-
'INSERT
|
|
131
|
-
(
|
|
131
|
+
'INSERT INTO Pic_of_{command}(img_url, phash) VALUES (?, ?)'.format(command=command),
|
|
132
|
+
(str(Path() / command / filename), new_phash_str))
|
|
132
133
|
await connection.commit()
|
|
133
134
|
|
|
134
135
|
def web_app_init(web_driver: Driver):
|
|
@@ -155,7 +156,7 @@ def web_app_init(web_driver: Driver):
|
|
|
155
156
|
web_app_init(driver)
|
|
156
157
|
|
|
157
158
|
|
|
158
|
-
picture = on_fullmatch(randpic_command_tuple, permission=GROUP, priority=
|
|
159
|
+
picture = on_fullmatch(randpic_command_tuple, permission=GROUP, priority=2, block=True)
|
|
159
160
|
|
|
160
161
|
|
|
161
162
|
@picture.handle()
|
|
@@ -178,7 +179,7 @@ async def pic(event: GroupMessageEvent):
|
|
|
178
179
|
await picture.send(f'{command}出不来了,稍后再试试吧~')
|
|
179
180
|
|
|
180
181
|
|
|
181
|
-
add = on_fullmatch(randpic_command_add_tuple, permission=GROUP_ADMIN | GROUP_OWNER, priority=
|
|
182
|
+
add = on_fullmatch(randpic_command_add_tuple, permission=GROUP_ADMIN | GROUP_OWNER, priority=2, block=True)
|
|
182
183
|
|
|
183
184
|
|
|
184
185
|
@add.got("pic", prompt="请发送图片!")
|
|
@@ -210,45 +211,48 @@ async def add_pic(args: str = Fullmatch(), pic_list: Message = Arg('pic')):
|
|
|
210
211
|
|
|
211
212
|
data = resp.content
|
|
212
213
|
data = compress_image_from_bytes(data) # 若图片超规格,压缩图片
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
await
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
214
|
+
new_phash_str = compute_phash(data)
|
|
215
|
+
new_phash = imagehash.hex_to_hash(new_phash_str)
|
|
216
|
+
|
|
217
|
+
await cursor.execute(f'SELECT phash FROM Pic_of_{command}')
|
|
218
|
+
existing = await cursor.fetchall()
|
|
219
|
+
SIMILARITY_THRESHOLD = 5 # 汉明距离 ≤5 认为相似
|
|
220
|
+
for ex_phash_str, in existing:
|
|
221
|
+
ex_phash = imagehash.hex_to_hash(ex_phash_str)
|
|
222
|
+
if (new_phash - ex_phash) < SIMILARITY_THRESHOLD:
|
|
223
|
+
await add.finish(pic_name + Message('\n这张已经有相似图,不能重复添加!'))
|
|
224
|
+
|
|
225
|
+
randpic_cur_picnum = len(os.listdir(randpic_img_path / command))
|
|
226
|
+
file_name = (randpic_filename.format(command=command, index=str(randpic_cur_picnum + 1).zfill(10))
|
|
227
|
+
+ get_image_extension(data))
|
|
228
|
+
file_path = randpic_img_path / command / file_name
|
|
229
|
+
|
|
230
|
+
try:
|
|
231
|
+
with file_path.open("wb") as f:
|
|
232
|
+
f.write(data)
|
|
233
|
+
await cursor.execute('insert into Pic_of_{command}(img_url, phash) values (?, ?)'.format(command=command),
|
|
234
|
+
(str(Path() / command / file_name), new_phash_str))
|
|
235
|
+
await connection.commit()
|
|
236
|
+
except Exception as e:
|
|
237
|
+
logger.warning(e)
|
|
238
|
+
await add.finish(pic_name + Message("\n导入失败!"), at_sender=True)
|
|
239
|
+
|
|
240
|
+
msg = "\n导入成功!"
|
|
241
|
+
if isOss and command not in randpic_oss_no_upload_list:
|
|
242
|
+
msg += f'可去 {endpoint}/{parse.quote(command)}/ 查看'
|
|
243
|
+
# StaticImageGalleryGenerator(randpic_img_path, randpic_path / 'public').generate_static_site()
|
|
244
|
+
StaticImageGalleryGenerator(randpic_img_path, randpic_path / 'public').generate_command_html(command, file_name, randpic_oss_no_upload_list)
|
|
245
|
+
await OSSUploaderV2().upload_file(str(randpic_path/ 'public' / command / 'index.html'), f'{command}/index.html') # 修改index.html文件
|
|
246
|
+
await OSSUploaderV2().upload_file(str(randpic_path / 'public' / 'index.html'), 'index.html')
|
|
247
|
+
await OSSUploaderV2().upload_file(file_path, f'{command}/{file_name}') # 上传新增的图片到OSS
|
|
248
|
+
await add.finish(pic_name + Message(msg), at_sender=True)
|
|
249
|
+
|
|
250
|
+
OSS = on_fullmatch('上传oss', ignorecase=True, permission=GROUP_ADMIN | GROUP_OWNER, priority=1, block=True, )
|
|
251
|
+
@OSS.handle()
|
|
248
252
|
async def handle_oss(event: GroupMessageEvent) -> None:
|
|
249
253
|
if not isOss:
|
|
250
254
|
return
|
|
251
|
-
await
|
|
255
|
+
await OSS.send('正在上传至OSS...')
|
|
252
256
|
start_time = time.time()
|
|
253
257
|
|
|
254
258
|
StaticImageGalleryGenerator(randpic_img_path, randpic_path / 'public').generate_static_site(randpic_oss_no_upload_list)
|
|
@@ -256,4 +260,4 @@ async def handle_oss(event: GroupMessageEvent) -> None:
|
|
|
256
260
|
|
|
257
261
|
end_time = time.time()
|
|
258
262
|
elapsed_time = end_time - start_time
|
|
259
|
-
await
|
|
263
|
+
await OSS.finish(f'上传完成,用时: {elapsed_time:.2f}秒,地址:{endpoint}/')
|
{nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/nonebot_plugin_randpic/compress.py
RENAMED
|
@@ -2,6 +2,7 @@ import zipfile
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from nonebot.log import logger
|
|
4
4
|
from PIL import Image
|
|
5
|
+
import imagehash
|
|
5
6
|
import io
|
|
6
7
|
|
|
7
8
|
|
|
@@ -199,6 +200,11 @@ def compress_folder_basic(folder_path, zip_path, include_subfolders=True):
|
|
|
199
200
|
return False
|
|
200
201
|
|
|
201
202
|
|
|
203
|
+
def compute_phash(image_bytes: bytes):
|
|
204
|
+
"""计算图片感知哈希,返回十六进制字符串"""
|
|
205
|
+
with Image.open(io.BytesIO(image_bytes)) as img:
|
|
206
|
+
return str(imagehash.phash(img))
|
|
207
|
+
|
|
202
208
|
# 测试
|
|
203
209
|
if __name__ == '__main__':
|
|
204
210
|
with open('C:\\Users\\hu_pa\\Desktop\\randpic\\lh\\randpic_lh_2.jpg', 'rb') as f:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "nonebot-plugin-randpic"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.3.0"
|
|
4
4
|
description = "一个通过指令随机发送你存储的图片的nonebot2插件"
|
|
5
5
|
authors = ["HuParry <hu_parry@qq.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -19,6 +19,7 @@ aiosqlite = "^0.13.0"
|
|
|
19
19
|
httpx = ">=0.20.0,<1.0.0"
|
|
20
20
|
alibabacloud_oss_v2 = ">=1.1.0"
|
|
21
21
|
pillow = ">=11.0.0"
|
|
22
|
+
imagehash = ">=4.3.0"
|
|
22
23
|
|
|
23
24
|
[build-system]
|
|
24
25
|
requires = ["poetry-core"]
|
|
File without changes
|
{nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/nonebot_plugin_randpic/ali_oss.py
RENAMED
|
File without changes
|
{nonebot_plugin_randpic-1.2.2 → nonebot_plugin_randpic-1.3.0}/nonebot_plugin_randpic/config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|