Skip to content

Commit ce0fc76

Browse files
committed
🎨 改进结构和代码格式
1 parent e9ecc1b commit ce0fc76

File tree

7 files changed

+82
-49
lines changed

7 files changed

+82
-49
lines changed

YetAnotherPicSearch/__init__.py

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import re
2+
from typing import Any, Dict, List, Optional, Tuple, Union
23

34
import arrow
4-
from nonebot.adapters.onebot.v11 import (
5+
from nonebot.adapters.onebot.v11 import ( # type: ignore
56
ActionFailed,
67
Bot,
78
GroupMessageEvent,
@@ -19,13 +20,9 @@
1920
from .ascii2d import ascii2d_search
2021
from .cache import clear_expired_cache, exist_in_cache
2122
from .config import config
23+
from .result import Result
2224
from .saucenao import saucenao_search
2325

24-
if config.proxy:
25-
PROXY = config.proxy
26-
else:
27-
PROXY = None
28-
2926

3027
async def _to_me(bot: Bot, event: MessageEvent) -> bool:
3128
msgs = event.message
@@ -52,46 +49,52 @@ async def handle_first_receive(matcher: Matcher, args: Message = CommandArg()) -
5249

5350

5451
async def image_search(
55-
url: str, mode: str, purge: bool, proxy: str, hide_img: bool = config.hide_img
56-
) -> list[str]:
52+
url: str,
53+
mode: str,
54+
purge: bool,
55+
proxy: Optional[str],
56+
hide_img: bool = config.hide_img,
57+
) -> Union[List[str], Any]:
5758
db = TinyDB(
5859
"cache.json",
59-
storage=CachingMiddleware(JSONStorage),
60+
storage=CachingMiddleware(JSONStorage), # type: ignore
6061
encoding="utf-8",
6162
sort_keys=True,
6263
indent=4,
6364
ensure_ascii=False,
6465
)
65-
image_md5 = re.search("[A-F0-9]{32}", url)[0]
66-
result = await exist_in_cache(db, image_md5, mode)
67-
cached = bool(result)
68-
if purge or not cached:
69-
result = {}
66+
image_md5 = re.search("[A-F0-9]{32}", url)[0] # type: ignore
67+
_result = await exist_in_cache(db, image_md5, mode)
68+
cached = bool(_result)
69+
if purge or not _result:
70+
result_dict: Dict[str, Any] = {}
7071
if mode == "a2d":
71-
result["ascii2d"] = await ascii2d_search(url, proxy, hide_img)
72+
result_dict["ascii2d"] = await ascii2d_search(url, proxy, hide_img)
7273
else:
73-
result["saucenao"] = await saucenao_search(url, mode, proxy, hide_img)
74-
result["mode"] = mode
75-
result["image_md5"] = image_md5
76-
result["update_at"] = arrow.now().for_json()
77-
db.upsert(result, (Query().image_md5 == image_md5) & (Query().mode == mode))
78-
db.insert(result)
74+
result_dict["saucenao"] = await saucenao_search(url, mode, proxy, hide_img)
75+
result_dict["mode"] = mode
76+
result_dict["image_md5"] = image_md5
77+
result_dict["update_at"] = arrow.now().for_json()
78+
_result = Result(result_dict)
79+
db.upsert(
80+
_result.__dict__, (Query().image_md5 == image_md5) & (Query().mode == mode)
81+
)
7982
await clear_expired_cache(db)
8083
db.close()
8184
if mode == "a2d":
82-
final_res = result["ascii2d"]
85+
final_res = _result.ascii2d
8386
else:
84-
final_res = result["saucenao"]
87+
final_res = _result.saucenao
8588
if cached and not purge:
86-
final_res = [f"[缓存] {i}" for i in final_res]
89+
return [f"[缓存] {i}" for i in final_res] # type: ignore
8790
return final_res
8891

8992

90-
async def get_image_urls(msg: Message) -> list[str]:
93+
async def get_image_urls(msg: Message) -> List[str]:
9194
return [i.data["url"] for i in msg if i.type == "image" and i.data.get("url")]
9295

9396

94-
async def get_args(msg: Message) -> (str, bool):
97+
async def get_args(msg: Message) -> Tuple[str, bool]:
9598
mode = "all"
9699
plain_text = msg.extract_plain_text()
97100
args = ["a2d", "pixiv", "danbooru", "doujin", "anime"]
@@ -112,7 +115,7 @@ async def handle_image_search(bot: Bot, event: MessageEvent) -> None:
112115
await IMAGE_SEARCH_MODE.reject()
113116
mode, purge = await get_args(event.message)
114117
for i in image_urls:
115-
msg_list = await image_search(i, mode, purge, PROXY)
118+
msg_list = await image_search(i, mode, purge, config.proxy)
116119
if isinstance(event, PrivateMessageEvent):
117120
for msg in msg_list:
118121
await bot.send_private_msg(user_id=event.user_id, message=msg)

YetAnotherPicSearch/ascii2d.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
from PicImageSearch import Ascii2D, Network
2-
from PicImageSearch.Utils import Ascii2DResponse
1+
from typing import List, Optional
2+
3+
from PicImageSearch import Ascii2D, Network # type: ignore
4+
from PicImageSearch.Utils import Ascii2DResponse # type: ignore
35

46
from .utils import handle_img, shorten_url
57

68

7-
async def ascii2d_search(url: str, proxy: str, hide_img: bool) -> list[str]:
9+
async def ascii2d_search(url: str, proxy: Optional[str], hide_img: bool) -> List[str]:
810
async with Network(proxies=proxy) as client:
911
ascii2d_color = Ascii2D(client=client)
1012
ascii2d_bovw = Ascii2D(bovw=True, client=client)
@@ -15,11 +17,14 @@ async def get_final_res(res: Ascii2DResponse) -> str:
1517
if not res.raw[0].url:
1618
res.raw[0] = res.raw[1]
1719
thumbnail = await handle_img(res.raw[0].thumbnail, proxy, hide_img)
20+
_url = ""
21+
if res.raw[0]:
22+
_url = await shorten_url(res.raw[0].url)
1823
res_list = [
1924
f"{thumbnail}",
2025
f"{res.raw[0].title}" if res.raw[0].title else "",
2126
f"Author:{res.raw[0].author}" if res.raw[0].author else "",
22-
f"{await shorten_url(res.raw[0].url)}" if res.raw[0].url else "",
27+
_url,
2328
]
2429
return "\n".join([i for i in res_list if i != ""])
2530

YetAnotherPicSearch/cache.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
1+
from typing import List, Optional
2+
13
import arrow
24
from tinydb import Query, TinyDB
35
from tinydb.operations import set
6+
from tinydb.table import Document
47

58
from .config import config
9+
from .result import Result
610

711

8-
async def exist_in_cache(db: TinyDB, image_md5: str, mode: str) -> dict:
9-
cache_result = db.search((Query().image_md5 == image_md5) & (Query().mode == mode))
12+
async def exist_in_cache(db: TinyDB, image_md5: str, mode: str) -> Optional[Result]:
13+
result: Optional[Result] = None
14+
cache_result: List[Document] = db.search(
15+
(Query().image_md5 == image_md5) & (Query().mode == mode)
16+
)
1017
if cache_result:
1118
db.update(
12-
set("update_at", arrow.now().for_json()), Query().image_md5 == image_md5
19+
set("update_at", arrow.now().for_json()), Query().image_md5 == image_md5 # type: ignore
1320
)
14-
return cache_result[-1]
15-
else:
16-
return {}
21+
result = Result(cache_result[-1])
22+
return result
1723

1824

1925
async def clear_expired_cache(db: TinyDB) -> None:

YetAnotherPicSearch/config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Optional
2+
13
from nonebot import get_driver
24
from pydantic import BaseSettings
35

@@ -8,7 +10,7 @@ class Config(BaseSettings):
810
saucenao_low_acc: int = 60 # saucenao 相似度低于这个百分比将被认定为相似度过低
911
use_ascii2d_when_low_acc: bool = True # 是否在 saucenao 相似度过低时自动使用 ascii2d
1012
group_forward_search_result: bool = True # 若结果消息有多条,采用合并转发方式发送搜图结果(私聊不生效)
11-
proxy: str = "" # 大部分请求所使用的代理,支持 http(s):// 和 socks://
13+
proxy: Optional[str] = None # 大部分请求所使用的代理: http(s)://
1214
cache_expire: int = 7 # 搜图结果缓存过期时间(天)
1315
saucenao_api_key: str = "" # saucenao APIKEY,必填,否则无法使用 saucenao 搜图
1416

YetAnotherPicSearch/result.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from typing import Any, Dict, List, Optional
2+
3+
4+
class Result:
5+
def __init__(self, mapping: Dict[str, Any]):
6+
self.ascii2d: Optional[List[str]] = []
7+
self.saucenao: Optional[List[str]] = []
8+
self.image_md5: Optional[str] = None
9+
self.update_at: Optional[str] = None
10+
self.mode: str = "all"
11+
for key, value in mapping.items():
12+
setattr(self, key, value)

YetAnotherPicSearch/saucenao.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import re
2+
from typing import List, Optional
23

3-
from PicImageSearch import Network, SauceNAO
4+
from PicImageSearch import Network, SauceNAO # type: ignore
45

56
from .ascii2d import ascii2d_search
67
from .config import config
78
from .utils import get_source, handle_img, shorten_url
89

910

10-
async def saucenao_search(url: str, mode: str, proxy: str, hide_img: bool) -> list[str]:
11+
async def saucenao_search(
12+
url: str, mode: str, proxy: Optional[str], hide_img: bool
13+
) -> List[str]:
1114
saucenao_db = {"all": 999, "pixiv": 5, "danbooru": 9, "anime": 21, "doujin": 18}
1215
async with Network(proxies=proxy) as client:
1316
saucenao = SauceNAO(
@@ -31,7 +34,7 @@ async def saucenao_search(url: str, mode: str, proxy: str, hide_img: bool) -> li
3134
if len(pixiv_res_list) > 1:
3235
selected_res = min(
3336
pixiv_res_list,
34-
key=lambda x: int(re.search(r"\d+", x.url).group()),
37+
key=lambda x: int(re.search(r"\d+", x.url).group()), # type: ignore
3538
)
3639
# 如果地址有多个,优先取 danbooru
3740
elif ext_urls and len(ext_urls) > 1:
@@ -48,12 +51,13 @@ async def saucenao_search(url: str, mode: str, proxy: str, hide_img: bool) -> li
4851
"data"
4952
].get("jp_name"):
5053
selected_res.title = selected_res.origin["data"]["jp_name"]
54+
_url = await shorten_url(selected_res.url)
5155
res_list = [
5256
f"SauceNAO({selected_res.similarity}%)",
5357
f"{thumbnail}",
5458
f"{selected_res.title}",
5559
f"Author:{selected_res.author}" if selected_res.author else "",
56-
f"{await shorten_url(selected_res.url)}",
60+
_url,
5761
f"Source:{source}" if source else "",
5862
]
5963
final_res.append("\n".join([i for i in res_list if i != ""]))

YetAnotherPicSearch/utils.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import base64
22
import re
33
from io import BytesIO
4+
from typing import Optional
45

56
import httpx
6-
from pyquery import PyQuery
7+
from pyquery import PyQuery # type: ignore
78

89

910
# 将图片转化为 base64
10-
async def get_pic_base64_by_url(url: str, proxy: str) -> str:
11-
async with httpx.AsyncClient(proxies=proxy) as client:
11+
async def get_pic_base64_by_url(url: str, proxy: Optional[str]) -> str:
12+
async with httpx.AsyncClient(proxies=proxy) as client: # type: ignore
1213
r = await client.get(url)
1314
image_buffer = BytesIO(r.content)
1415
return str(base64.b64encode(image_buffer.getvalue()), encoding="utf-8")
1516

1617

17-
async def handle_img(url: str, proxy: str, hide_img: bool) -> str:
18+
async def handle_img(url: str, proxy: Optional[str], hide_img: bool) -> str:
1819
if hide_img:
1920
return ""
2021
img_base64 = await get_pic_base64_by_url(url, proxy)
@@ -23,9 +24,9 @@ async def handle_img(url: str, proxy: str, hide_img: bool) -> str:
2324
return f"图片下载失败: {url}"
2425

2526

26-
async def get_source(url: str, proxy: str) -> str:
27+
async def get_source(url: str, proxy: Optional[str]) -> str:
2728
source = ""
28-
async with httpx.AsyncClient(proxies=proxy) as client:
29+
async with httpx.AsyncClient(proxies=proxy) as client: # type: ignore
2930
if httpx.URL(url).host == "danbooru.donmai.us":
3031
source = PyQuery((await client.get(url)).content)(".image-container").attr(
3132
"data-normalized-source"
@@ -46,7 +47,7 @@ async def get_source(url: str, proxy: str) -> str:
4647
async def shorten_url(url: str) -> str:
4748
pid_search = re.compile(r"pixiv.+(?:illust_id=|artworks/)([0-9]+)")
4849
if pid_search.search(url):
49-
return f"https://pixiv.net/i/{pid_search.search(url).group(1)}"
50+
return f"https://pixiv.net/i/{pid_search.search(url).group(1)}" # type: ignore
5051
if httpx.URL(url).host == "danbooru.donmai.us":
5152
return url.replace("/post/show/", "/posts/")
5253
return url

0 commit comments

Comments
 (0)