nonebot-plugin-savepic 0.2.7__tar.gz → 0.3.1__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_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/PKG-INFO +1 -1
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/__init__.py +5 -40
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/config.py +6 -0
- nonebot_plugin_savepic-0.3.1/nonebot_plugin_savepic/listpic.py +84 -0
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/mvpic.py +0 -1
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/pic_sql.py +18 -64
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/pyproject.toml +1 -1
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/LICENSE +0 -0
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/README.md +0 -0
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/ai_utils.py +0 -0
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/countpic.py +0 -0
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/error.py +0 -0
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/ext_listener.py +0 -0
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/model.py +0 -0
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/networks/__init__.py +0 -0
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/networks/resnet_big.py +0 -0
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/picture.py +0 -0
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/randpic.py +0 -0
- {nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/rule.py +0 -0
{nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/__init__.py
RENAMED
|
@@ -11,7 +11,7 @@ from nonebot.matcher import Matcher
|
|
|
11
11
|
from nonebot.plugin import PluginMetadata
|
|
12
12
|
from nonebot.dependencies import Dependent
|
|
13
13
|
from sqlalchemy.exc import DBAPIError
|
|
14
|
-
from arclet.alconna import Alconna, Option, Args, CommandMeta
|
|
14
|
+
from arclet.alconna import Alconna, Option, Args, CommandMeta
|
|
15
15
|
import os
|
|
16
16
|
import random
|
|
17
17
|
from typing import (
|
|
@@ -46,20 +46,19 @@ from .config import Config
|
|
|
46
46
|
from .config import WORDS
|
|
47
47
|
from .pic_sql import ( # noqa: E402
|
|
48
48
|
savepic,
|
|
49
|
-
rename,
|
|
50
49
|
delete,
|
|
51
50
|
regexp_pic,
|
|
52
|
-
listpic,
|
|
53
51
|
)
|
|
54
52
|
from .rule import PIC_AMDIN
|
|
55
53
|
from .rule import BLACK_GROUP
|
|
56
54
|
from .rule import GROUP_ADMIN
|
|
57
|
-
from .
|
|
58
|
-
from .picture import write_pic, load_pic # noqa: E402
|
|
55
|
+
from .picture import write_pic, load_pic
|
|
59
56
|
from .ai_utils import img2vec
|
|
60
57
|
from .randpic import url_to_image
|
|
61
|
-
from .countpic import cpic
|
|
62
58
|
from .mvpic import INVALID_FILENAME_CHARACTERS
|
|
59
|
+
from .listpic import s_listpic
|
|
60
|
+
from .ext_listener import pic_listen
|
|
61
|
+
from .countpic import cpic
|
|
63
62
|
|
|
64
63
|
|
|
65
64
|
__plugin_meta__ = PluginMetadata(
|
|
@@ -89,7 +88,6 @@ a_spic = Alconna(
|
|
|
89
88
|
meta=CommandMeta(description="保存图片,默认保存到本群"),
|
|
90
89
|
)
|
|
91
90
|
s_simpic = on_command("simpic", priority=5, permission=BLACK_GROUP)
|
|
92
|
-
s_listpic = on_command("listpic", priority=5, permission=BLACK_GROUP)
|
|
93
91
|
|
|
94
92
|
|
|
95
93
|
def got_random_prompt(
|
|
@@ -162,39 +160,6 @@ async def _(bot: Bot, event, args: V11Msg = CommandArg()):
|
|
|
162
160
|
)
|
|
163
161
|
|
|
164
162
|
|
|
165
|
-
@s_listpic.handle()
|
|
166
|
-
async def _(bot: Bot, event, args: V11Msg = CommandArg()):
|
|
167
|
-
reg = args.extract_plain_text().strip().rsplit("\\page", maxsplit=1)
|
|
168
|
-
try:
|
|
169
|
-
if len(reg) > 1:
|
|
170
|
-
reg, pages = reg
|
|
171
|
-
else:
|
|
172
|
-
reg, pages = reg[0], 0
|
|
173
|
-
pages = int(pages)
|
|
174
|
-
except Exception as ex:
|
|
175
|
-
await repic.finish(
|
|
176
|
-
f'{random.choice(WORDS.get("error", ["出错了喵~"]))}\n\n{ex}'
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
group_id = (
|
|
180
|
-
"globe"
|
|
181
|
-
if not isinstance(event, GroupMessageEvent)
|
|
182
|
-
else f"qq_group:{event.group_id}"
|
|
183
|
-
)
|
|
184
|
-
try:
|
|
185
|
-
pic = await listpic(reg, group_id, pages=pages)
|
|
186
|
-
if pic:
|
|
187
|
-
await bot.send(event, "\n".join(pic))
|
|
188
|
-
except DBAPIError as ex:
|
|
189
|
-
await repic.finish(
|
|
190
|
-
f'{random.choice(WORDS.get("error", ["出错了喵~"]))}\n\n{ex.orig}'
|
|
191
|
-
)
|
|
192
|
-
except Exception as ex:
|
|
193
|
-
await repic.finish(
|
|
194
|
-
f'{random.choice(WORDS.get("error", ["出错了喵~"]))}\n\n{ex}'
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
|
|
198
163
|
@spic.handle()
|
|
199
164
|
async def _(
|
|
200
165
|
bot: Bot,
|
{nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/config.py
RENAMED
|
@@ -36,3 +36,9 @@ class Config(BaseModel):
|
|
|
36
36
|
|
|
37
37
|
notfound_with_jpg: bool = True
|
|
38
38
|
""" randpic 的时候,尝试带 .jpg 再度检索向量 """
|
|
39
|
+
count_per_page_in_list: int = 7
|
|
40
|
+
""" 每页最多多少条 """
|
|
41
|
+
forward_when_listpic: bool = True
|
|
42
|
+
""" listpic 的时候合并转发 """
|
|
43
|
+
max_page_in_listpic: int = 20
|
|
44
|
+
""" 合并转发中所能显示的最大页数 """
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import random
|
|
2
|
+
from nonebot import on_command
|
|
3
|
+
from nonebot import get_plugin_config
|
|
4
|
+
from nonebot.params import CommandArg
|
|
5
|
+
from nonebot.internal.adapter import Bot
|
|
6
|
+
from nonebot.adapters.onebot.v11.event import GroupMessageEvent as V11GME
|
|
7
|
+
from nonebot.adapters.onebot.v11.message import Message as V11Msg
|
|
8
|
+
from nonebot.adapters.onebot.v11.message import MessageSegment as V11Seg
|
|
9
|
+
from sqlalchemy.exc import DBAPIError
|
|
10
|
+
|
|
11
|
+
from .rule import BLACK_GROUP
|
|
12
|
+
from .config import WORDS
|
|
13
|
+
from .pic_sql import listpic
|
|
14
|
+
from .config import Config
|
|
15
|
+
|
|
16
|
+
p_config: Config = get_plugin_config(Config)
|
|
17
|
+
s_listpic = on_command("listpic", priority=5, permission=BLACK_GROUP)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@s_listpic.handle()
|
|
21
|
+
async def _(bot: Bot, event, args: V11Msg = CommandArg()):
|
|
22
|
+
reg = args.extract_plain_text().strip().rsplit("\\page", maxsplit=1)
|
|
23
|
+
try:
|
|
24
|
+
if len(reg) > 1:
|
|
25
|
+
reg, pages = reg
|
|
26
|
+
else:
|
|
27
|
+
reg, pages = reg[0], 1
|
|
28
|
+
pages = int(pages)
|
|
29
|
+
except Exception as ex:
|
|
30
|
+
await s_listpic.finish(
|
|
31
|
+
f'{random.choice(WORDS.get("error", ["出错了喵~"]))}\n\n{ex}'
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
group_id = (
|
|
35
|
+
"globe" if not isinstance(event, V11GME) else f"qq_group:{event.group_id}"
|
|
36
|
+
)
|
|
37
|
+
try:
|
|
38
|
+
pics = await listpic(reg, group_id, pages=pages)
|
|
39
|
+
if not pics:
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
cpp = max(p_config.count_per_page_in_list, 1)
|
|
43
|
+
if p_config.forward_when_listpic:
|
|
44
|
+
message = []
|
|
45
|
+
for i in range(len(pics) // cpp + 1):
|
|
46
|
+
if pics[i * cpp : (i + 1) * cpp]:
|
|
47
|
+
message.append(
|
|
48
|
+
{
|
|
49
|
+
"type": "node",
|
|
50
|
+
"data": {
|
|
51
|
+
"uin": str(event.get_user_id()),
|
|
52
|
+
"name": f"Page {pages+i}",
|
|
53
|
+
"content": V11Seg.text(
|
|
54
|
+
"\n".join(pics[i * cpp : (i + 1) * cpp])
|
|
55
|
+
+ f"\n\nPage {pages+i}"
|
|
56
|
+
),
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if isinstance(event, V11GME):
|
|
62
|
+
await bot.call_api(
|
|
63
|
+
"send_group_forward_msg",
|
|
64
|
+
group_id=event.group_id,
|
|
65
|
+
messages=message,
|
|
66
|
+
)
|
|
67
|
+
else:
|
|
68
|
+
await s_listpic.send(
|
|
69
|
+
V11Seg.forward(
|
|
70
|
+
await bot.call_api("send_forward_msg", messages=message)
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
await s_listpic.send("\n".join(pics[:cpp]))
|
|
76
|
+
|
|
77
|
+
except DBAPIError as ex:
|
|
78
|
+
await s_listpic.finish(
|
|
79
|
+
f'{random.choice(WORDS.get("error", ["出错了喵~"]))}\n\n{ex.orig}'
|
|
80
|
+
)
|
|
81
|
+
except Exception as ex:
|
|
82
|
+
await s_listpic.finish(
|
|
83
|
+
f'{random.choice(WORDS.get("error", ["出错了喵~"]))}\n\n{ex}'
|
|
84
|
+
)
|
{nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/pic_sql.py
RENAMED
|
@@ -6,7 +6,6 @@ import asyncpg
|
|
|
6
6
|
from nonebot import get_driver
|
|
7
7
|
import dashscope
|
|
8
8
|
import pathlib
|
|
9
|
-
from pinecone import Pinecone, ServerlessSpec
|
|
10
9
|
|
|
11
10
|
from .model import PicData
|
|
12
11
|
from .picture import del_pic
|
|
@@ -20,7 +19,6 @@ from .error import NoPictureException
|
|
|
20
19
|
gdriver = get_driver()
|
|
21
20
|
p_config = Config.parse_obj(gdriver.config)
|
|
22
21
|
_async_database = None
|
|
23
|
-
_pincone_index = None
|
|
24
22
|
_async_embedding_database = None
|
|
25
23
|
|
|
26
24
|
|
|
@@ -37,15 +35,15 @@ async def update_vec(pic: PicData):
|
|
|
37
35
|
return
|
|
38
36
|
|
|
39
37
|
async with AsyncSession(_async_database) as db_session:
|
|
40
|
-
if pic.u_vec_text:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
db_session.merge(pic)
|
|
48
|
-
db_session.commit()
|
|
38
|
+
# if pic.u_vec_text:
|
|
39
|
+
pic.u_vec_text = False
|
|
40
|
+
await _async_embedding_database.execute(
|
|
41
|
+
"UPDATE savepic_word2vec SET embedding = $1 WHERE id = $2",
|
|
42
|
+
str(word2vec(pic.name)),
|
|
43
|
+
pic.id,
|
|
44
|
+
)
|
|
45
|
+
await db_session.merge(pic)
|
|
46
|
+
await db_session.commit()
|
|
49
47
|
|
|
50
48
|
|
|
51
49
|
async def select_pic(filename: str, group: str):
|
|
@@ -64,37 +62,6 @@ async def select_pic(filename: str, group: str):
|
|
|
64
62
|
)
|
|
65
63
|
|
|
66
64
|
|
|
67
|
-
# async def get_most_similar_pic(
|
|
68
|
-
# img_vec: list[float],
|
|
69
|
-
# group_id: str,
|
|
70
|
-
# ignore_diagonal: bool = False,
|
|
71
|
-
# ignore_min: bool = False,
|
|
72
|
-
# ) -> tuple[float, PicData]:
|
|
73
|
-
# async with AsyncSession(_async_database) as db_session:
|
|
74
|
-
# ret = _pincone_index.query(img_vec, top_k=20)["matches"]
|
|
75
|
-
# if not ret:
|
|
76
|
-
# return None, None
|
|
77
|
-
# if not ret[0]["id"]:
|
|
78
|
-
# return None, None
|
|
79
|
-
# if ignore_diagonal and ret[0]["score"] >= 0.999:
|
|
80
|
-
# ret.pop(0)
|
|
81
|
-
|
|
82
|
-
# for i in ret:
|
|
83
|
-
# if i["score"] < 0.65 and not ignore_min:
|
|
84
|
-
# return None, None
|
|
85
|
-
# if i["id"]:
|
|
86
|
-
# despic = await db_session.scalar(
|
|
87
|
-
# select(PicData)
|
|
88
|
-
# .where(PicData.id == int(i["id"]))
|
|
89
|
-
# .where(PicData.name != "")
|
|
90
|
-
# .where(sa.or_(PicData.group == group_id, PicData.group == "globe"))
|
|
91
|
-
# )
|
|
92
|
-
# if despic:
|
|
93
|
-
# return i["score"], despic
|
|
94
|
-
|
|
95
|
-
# return None, None
|
|
96
|
-
|
|
97
|
-
|
|
98
65
|
async def savepic(
|
|
99
66
|
filename: str,
|
|
100
67
|
url: str,
|
|
@@ -173,7 +140,6 @@ async def delete(filename: str, group: str):
|
|
|
173
140
|
del_pic(pic.url)
|
|
174
141
|
pic.name = ""
|
|
175
142
|
await db_session.merge(pic)
|
|
176
|
-
# _pincone_index.delete(ids=[str(pic.id)])
|
|
177
143
|
await _async_embedding_database.execute(
|
|
178
144
|
"UPDATE savepic_word2vec SET embedding = NULL WHERE id = $1", pic.id
|
|
179
145
|
)
|
|
@@ -285,7 +251,12 @@ async def listpic(reg: str, group: str = "globe", pages: int = 0) -> list[str]:
|
|
|
285
251
|
reg = reg.strip()
|
|
286
252
|
if not reg:
|
|
287
253
|
reg = ".*"
|
|
288
|
-
|
|
254
|
+
|
|
255
|
+
pages = max(pages - 1, 0)
|
|
256
|
+
_count = min(
|
|
257
|
+
max(1, p_config.count_per_page_in_list * p_config.max_page_in_listpic), 1000
|
|
258
|
+
)
|
|
259
|
+
|
|
289
260
|
async with AsyncSession(_async_database) as db_session:
|
|
290
261
|
pics = await db_session.scalars(
|
|
291
262
|
select(PicData)
|
|
@@ -293,8 +264,8 @@ async def listpic(reg: str, group: str = "globe", pages: int = 0) -> list[str]:
|
|
|
293
264
|
.where(PicData.name != "")
|
|
294
265
|
.where(PicData.name.regexp_match(reg, flags="i"))
|
|
295
266
|
.order_by(PicData.name)
|
|
296
|
-
.offset(
|
|
297
|
-
.limit(
|
|
267
|
+
.offset(pages * p_config.count_per_page_in_list)
|
|
268
|
+
.limit(_count)
|
|
298
269
|
)
|
|
299
270
|
if pics:
|
|
300
271
|
return [str(pic.name) for pic in pics]
|
|
@@ -302,7 +273,7 @@ async def listpic(reg: str, group: str = "globe", pages: int = 0) -> list[str]:
|
|
|
302
273
|
|
|
303
274
|
async def init_db():
|
|
304
275
|
# check if the table exists
|
|
305
|
-
global _async_database,
|
|
276
|
+
global _async_database, _async_embedding_database
|
|
306
277
|
_async_database = create_async_engine(
|
|
307
278
|
p_config.savepic_sqlurl,
|
|
308
279
|
future=True,
|
|
@@ -350,22 +321,6 @@ async def init_db():
|
|
|
350
321
|
)
|
|
351
322
|
)
|
|
352
323
|
|
|
353
|
-
if not p_config.pinecone_apikey:
|
|
354
|
-
raise Exception("请配置 pinecone_apikey")
|
|
355
|
-
if not p_config.pinecone_environment:
|
|
356
|
-
raise Exception("请配置 pinecone_environment")
|
|
357
|
-
|
|
358
|
-
pc = Pinecone(api_key=p_config.pinecone_apikey)
|
|
359
|
-
if p_config.pinecone_index not in pc.list_indexes().names():
|
|
360
|
-
pc.create_index(
|
|
361
|
-
name=p_config.pinecone_index,
|
|
362
|
-
dimension=1536,
|
|
363
|
-
metric="euclidean",
|
|
364
|
-
spec=ServerlessSpec(cloud="aws", region="us-west-2"),
|
|
365
|
-
)
|
|
366
|
-
if not _pincone_index:
|
|
367
|
-
_pincone_index = pc.Index(p_config.pinecone_index)
|
|
368
|
-
|
|
369
324
|
|
|
370
325
|
@gdriver.on_startup
|
|
371
326
|
async def _():
|
|
@@ -388,7 +343,6 @@ async def _():
|
|
|
388
343
|
# .where(PicData.name != "")
|
|
389
344
|
# )
|
|
390
345
|
# if pic:
|
|
391
|
-
# _pincone_index.upsert([(str(pic.id), files[i])])
|
|
392
346
|
# print(f"{pic.name} 加载成功")
|
|
393
347
|
# except Exception as ex:
|
|
394
348
|
# print(ex)
|
|
File without changes
|
|
File without changes
|
{nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/ai_utils.py
RENAMED
|
File without changes
|
{nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/countpic.py
RENAMED
|
File without changes
|
{nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/error.py
RENAMED
|
File without changes
|
{nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/ext_listener.py
RENAMED
|
File without changes
|
{nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/picture.py
RENAMED
|
File without changes
|
{nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/randpic.py
RENAMED
|
File without changes
|
{nonebot_plugin_savepic-0.2.7 → nonebot_plugin_savepic-0.3.1}/nonebot_plugin_savepic/rule.py
RENAMED
|
File without changes
|