update 0.0.6.2

This commit is contained in:
HibiKi
2021-11-23 21:44:59 +08:00
parent c802dfda22
commit 3de487fb24
251 changed files with 14413 additions and 14002 deletions
Regular → Executable
+4 -4
View File
@@ -1,4 +1,4 @@
import nonebot
nonebot.load_plugins("plugins/send_setu_")
import nonebot
nonebot.load_plugins("plugins/send_setu_")
Regular → Executable
+177 -177
View File
@@ -1,177 +1,177 @@
from services.db_context import db
from typing import List, Optional
class Setu(db.Model):
__tablename__ = "setu"
__table_args__ = {'extend_existing': True}
id = db.Column(db.Integer(), primary_key=True)
local_id = db.Column(db.Integer(), nullable=False)
title = db.Column(db.String(), nullable=False)
author = db.Column(db.String(), nullable=False)
pid = db.Column(db.BigInteger(), nullable=False)
img_hash = db.Column(db.String(), nullable=False)
img_url = db.Column(db.String(), nullable=False)
is_r18 = db.Column(db.Boolean(), nullable=False)
tags = db.Column(db.String())
_idx1 = db.Index("setu_pid_img_url_idx1", "pid", "img_url", unique=True)
@classmethod
async def add_setu_data(
cls,
local_id: int,
title: str,
author: str,
pid: int,
img_hash: str,
img_url: str,
tags: str,
):
"""
说明:
添加一份色图数据
参数:
:param local_id: 本地存储id
:param title: 标题
:param author: 作者
:param pid: 图片pid
:param img_hash: 图片hash值
:param img_url: 图片链接
:param tags: 图片标签
"""
if not await cls._check_exists(pid, img_url):
await cls.create(
local_id=local_id,
title=title,
author=author,
pid=pid,
img_hash=img_hash,
img_url=img_url,
is_r18=True if "R-18" in tags else False,
tags=tags,
)
@classmethod
async def query_image(
cls,
local_id: Optional[int] = None,
tags: Optional[List[str]] = None,
r18: int = 0,
limit: int = 50,
):
"""
说明:
通过tag查找色图
参数:
:param local_id: 本地色图 id
:param tags: tags
:param r18: 是否 r18,0:非r18 1:r18 2:混合
:param limit: 获取数量
"""
if local_id:
flag = True if r18 == 1 else False
return await cls.query.where(
(cls.local_id == local_id) & (cls.is_r18 == flag)
).gino.first()
if r18 == 0:
query = cls.query.where(cls.is_r18 == False)
elif r18 == 1:
query = cls.query.where(cls.is_r18 == True)
else:
query = cls.query
if tags:
for tag in tags:
query = query.where(cls.tags.contains(tag) | cls.title.contains(tag) | cls.author.contains(tag))
query = query.order_by(db.func.random()).limit(limit)
return await query.gino.all()
@classmethod
async def get_image_count(cls, r18: int = 0) -> int:
"""
说明:
查询图片数量
"""
flag = False if r18 == 0 else True
setattr(Setu, 'count', db.func.count(cls.local_id).label('count'))
count = await cls.select('count').where(cls.is_r18 == flag).gino.first()
return count[0]
@classmethod
async def get_image_in_hash(cls, img_hash: str) -> "Setu":
"""
说明:
通过图像hash获取图像信息
参数:
:param img_hash: = 图像hash值
"""
query = await cls.query.where(cls.img_hash == img_hash).gino.first()
return query
@classmethod
async def _check_exists(cls, pid: int, img_url: str) -> bool:
"""
说明:
检测图片是否存在
参数:
:param pid: 图片pid
:param img_url: 图片链接
"""
return bool(
await cls.query.where(
(cls.pid == pid) & (cls.img_url == img_url)
).gino.first()
)
@classmethod
async def update_setu_data(
cls,
pid: int,
*,
local_id: Optional[int] = None,
title: Optional[str] = None,
author: Optional[str] = None,
img_hash: Optional[str] = None,
img_url: Optional[str] = None,
tags: Optional[str] = None,
) -> bool:
"""
说明:
根据PID修改图片数据
参数:
:param local_id: 本地id
:param pid: 图片pid
:param title: 标题
:param author: 作者
:param img_hash: 图片hash值
:param img_url: 图片链接
:param tags: 图片标签
"""
query = cls.query.where(cls.pid == pid).with_for_update()
image_list = await query.gino.all()
if image_list:
for image in image_list:
if local_id:
await image.update(local_id=local_id).apply()
if title:
await image.update(title=title).apply()
if author:
await image.update(author=author).apply()
if img_hash:
await image.update(img_hash=img_hash).apply()
if img_url:
await image.update(img_url=img_url).apply()
if tags:
await image.update(tags=tags).apply()
return True
return False
@classmethod
async def get_all_setu(cls) -> List["Setu"]:
"""
说明:
获取所有图片对象
"""
return await cls.query.gino.all()
from services.db_context import db
from typing import List, Optional
class Setu(db.Model):
__tablename__ = "setu"
__table_args__ = {'extend_existing': True}
id = db.Column(db.Integer(), primary_key=True)
local_id = db.Column(db.Integer(), nullable=False)
title = db.Column(db.String(), nullable=False)
author = db.Column(db.String(), nullable=False)
pid = db.Column(db.BigInteger(), nullable=False)
img_hash = db.Column(db.String(), nullable=False)
img_url = db.Column(db.String(), nullable=False)
is_r18 = db.Column(db.Boolean(), nullable=False)
tags = db.Column(db.String())
_idx1 = db.Index("setu_pid_img_url_idx1", "pid", "img_url", unique=True)
@classmethod
async def add_setu_data(
cls,
local_id: int,
title: str,
author: str,
pid: int,
img_hash: str,
img_url: str,
tags: str,
):
"""
说明:
添加一份色图数据
参数:
:param local_id: 本地存储id
:param title: 标题
:param author: 作者
:param pid: 图片pid
:param img_hash: 图片hash值
:param img_url: 图片链接
:param tags: 图片标签
"""
if not await cls._check_exists(pid, img_url):
await cls.create(
local_id=local_id,
title=title,
author=author,
pid=pid,
img_hash=img_hash,
img_url=img_url,
is_r18=True if "R-18" in tags else False,
tags=tags,
)
@classmethod
async def query_image(
cls,
local_id: Optional[int] = None,
tags: Optional[List[str]] = None,
r18: int = 0,
limit: int = 50,
):
"""
说明:
通过tag查找色图
参数:
:param local_id: 本地色图 id
:param tags: tags
:param r18: 是否 r18,0:非r18 1:r18 2:混合
:param limit: 获取数量
"""
if local_id:
flag = True if r18 == 1 else False
return await cls.query.where(
(cls.local_id == local_id) & (cls.is_r18 == flag)
).gino.first()
if r18 == 0:
query = cls.query.where(cls.is_r18 == False)
elif r18 == 1:
query = cls.query.where(cls.is_r18 == True)
else:
query = cls.query
if tags:
for tag in tags:
query = query.where(cls.tags.contains(tag) | cls.title.contains(tag) | cls.author.contains(tag))
query = query.order_by(db.func.random()).limit(limit)
return await query.gino.all()
@classmethod
async def get_image_count(cls, r18: int = 0) -> int:
"""
说明:
查询图片数量
"""
flag = False if r18 == 0 else True
setattr(Setu, 'count', db.func.count(cls.local_id).label('count'))
count = await cls.select('count').where(cls.is_r18 == flag).gino.first()
return count[0]
@classmethod
async def get_image_in_hash(cls, img_hash: str) -> "Setu":
"""
说明:
通过图像hash获取图像信息
参数:
:param img_hash: = 图像hash值
"""
query = await cls.query.where(cls.img_hash == img_hash).gino.first()
return query
@classmethod
async def _check_exists(cls, pid: int, img_url: str) -> bool:
"""
说明:
检测图片是否存在
参数:
:param pid: 图片pid
:param img_url: 图片链接
"""
return bool(
await cls.query.where(
(cls.pid == pid) & (cls.img_url == img_url)
).gino.first()
)
@classmethod
async def update_setu_data(
cls,
pid: int,
*,
local_id: Optional[int] = None,
title: Optional[str] = None,
author: Optional[str] = None,
img_hash: Optional[str] = None,
img_url: Optional[str] = None,
tags: Optional[str] = None,
) -> bool:
"""
说明:
根据PID修改图片数据
参数:
:param local_id: 本地id
:param pid: 图片pid
:param title: 标题
:param author: 作者
:param img_hash: 图片hash值
:param img_url: 图片链接
:param tags: 图片标签
"""
query = cls.query.where(cls.pid == pid).with_for_update()
image_list = await query.gino.all()
if image_list:
for image in image_list:
if local_id:
await image.update(local_id=local_id).apply()
if title:
await image.update(title=title).apply()
if author:
await image.update(author=author).apply()
if img_hash:
await image.update(img_hash=img_hash).apply()
if img_url:
await image.update(img_url=img_url).apply()
if tags:
await image.update(tags=tags).apply()
return True
return False
@classmethod
async def get_all_setu(cls) -> List["Setu"]:
"""
说明:
获取所有图片对象
"""
return await cls.query.gino.all()
+368 -368
View File
@@ -1,368 +1,368 @@
import random
from nonebot import on_command, on_regex
from services.log import logger
from models.sign_group_user import SignGroupUser
from nonebot.message import run_postprocessor
from nonebot.matcher import Matcher
from typing import Optional, Type
from gino.exceptions import UninitializedError
from utils.utils import (
is_number,
get_message_text,
get_message_imgs,
)
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import (
Bot,
MessageEvent,
GroupMessageEvent,
PrivateMessageEvent,
Message,
Event,
)
from .data_source import (
get_setu_list,
get_luoxiang,
search_online_setu,
get_setu_urls,
find_img_index,
gen_message,
check_local_exists_or_download,
add_data_to_database,
get_setu_count,
)
from nonebot.adapters.cqhttp.exception import ActionFailed
from configs.config import Config, NICKNAME
from utils.manager import withdraw_message_manager
import re
try:
import ujson as json
except ModuleNotFoundError:
import json
__zx_plugin_name__ = "色图"
__plugin_usage__ = f"""
usage:
搜索 lolicon 图库,每日色图time...
指令:
色图: 随机本地色图
色图r: 随机在线十张r18涩图
色图 [id]: 本地指定id色图
色图 *[tags]: 在线搜索指定tag色图
色图r *[tags]: 同上
[1-9]张涩图: 本地随机色图连发
[1-9]张[tags]的涩图: 指定tag色图连发
示例:色图 萝莉|少女 白丝|黑丝
示例:色图 萝莉 猫娘
注:
tag至多取前20项,| 为或,萝莉|少女=萝莉或者少女
""".strip()
__plugin_des__ = "不要小看涩图啊混蛋!"
__plugin_cmd__ = ["色图 ?[id]", "色图 ?[tags]", "色图r ?[tags]", "[1-9]张?[tags]色图"]
__plugin_type__ = ("来点好康的",)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 9,
"default_status": True,
"limit_superuser": False,
"cmd": ["色图", "涩图", "瑟图"],
}
__plugin_block_limit__ = {}
__plugin_cd_limit__ = {
"rst": "您冲的太快了,请稍后再冲.",
}
__plugin_configs__ = {
"WITHDRAW_SETU_MESSAGE": {
"value": (0, 1),
"help": "自动撤回,参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)",
"default_value": (0, 1),
},
"ONLY_USE_LOCAL_SETU": {
"value": False,
"help": "仅仅使用本地色图,不在线搜索",
"default_value": False,
},
"INITIAL_SETU_PROBABILITY": {
"value": 0.7,
"help": "初始色图概率,总概率 = 初始色图概率 + 好感度",
"default_value": 0.7
},
"DOWNLOAD_SETU": {
"value": True,
"help": "是否存储下载的色图,使用本地色图可以加快图片发送速度",
"default_value": True
},
"TIMEOUT": {
"value": 10,
"help": "色图下载超时限制(秒)",
"default_value": 10
}
}
Config.add_plugin_config(
"pixiv",
"PIXIV_NGINX_URL",
"i.pixiv.re",
help_="Pixiv反向代理"
)
setu_data_list = []
@run_postprocessor
async def do_something(
matcher: Matcher,
exception: Optional[Exception],
bot: Bot,
event: Event,
state: T_State,
):
global setu_data_list
if isinstance(event, MessageEvent):
if matcher.module == "send_setu":
# 添加数据至数据库
try:
await add_data_to_database(setu_data_list)
logger.info("色图数据自动存储数据库成功...")
setu_data_list = []
except UninitializedError:
pass
setu = on_command(
"色图", aliases={"涩图", "不够色", "来一发", "再来点", "色图r"}, priority=5, block=True
)
setu_reg = on_regex("(.*)[份|发|张|个|次|点](.*)[瑟|色|涩]图$", priority=5, block=True)
find_setu = on_command("查色图", priority=5, block=True)
@setu.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if isinstance(event, GroupMessageEvent):
impression = (
await SignGroupUser.ensure(event.user_id, event.group_id)
).impression
luox = get_luoxiang(impression)
if luox:
await setu.finish(luox)
r18 = 0
num = 1
# 是否看r18
if state["_prefix"]["raw_command"] == "色图r" and isinstance(
event, PrivateMessageEvent
):
r18 = 1
num = 10
elif state["_prefix"]["raw_command"] == "色图r" and isinstance(
event, GroupMessageEvent
):
await setu.finish(
random.choice(["这种不好意思的东西怎么可能给这么多人看啦", "羞羞脸!给我滚出克私聊!", "变态变态变态变态大变态!"])
)
# 有 数字 的话先尝试本地色图id
if msg and is_number(msg):
setu_list, code = await get_setu_list(int(msg), r18=r18)
if code != 200:
await setu.finish(setu_list[0], at_sender=True)
setu_img, code = await check_local_exists_or_download(setu_list[0])
msg_id = await setu.send(gen_message(setu_list[0]) + setu_img, at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 发送色图 {setu_list[0].local_id}.png"
)
if msg_id:
withdraw_message_manager.withdraw_message(
event,
msg_id["message_id"],
Config.get_config("send_setu", "WITHDRAW_SETU_MESSAGE"),
)
return
await send_setu_handle(setu, event, state["_prefix"]["raw_command"], msg, num, r18)
num_key = {
"一": 1,
"二": 2,
"两": 2,
"双": 2,
"三": 3,
"四": 4,
"五": 5,
"六": 6,
"七": 7,
"八": 8,
"九": 9,
}
@setu_reg.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
if isinstance(event, GroupMessageEvent):
impression = (
await SignGroupUser.ensure(event.user_id, event.group_id)
).impression
luox = get_luoxiang(impression)
if luox:
await setu.finish(luox, at_sender=True)
msg = get_message_text(event.json())
num = 1
msg = re.search(r"(.*)[份发张个次点](.*)[瑟涩色]图", msg)
# 解析 tags 以及 num
if msg:
num = msg.group(1)
tags = msg.group(2)
if tags:
tags = tags[:-1] if tags[-1] == "的" else tags
if num:
num = num[-1]
if num_key.get(num):
num = num_key[num]
elif is_number(num):
try:
num = int(num)
except ValueError:
num = 1
else:
num = 1
else:
return
await send_setu_handle(setu_reg, event, "色图", tags, num, 0)
@find_setu.args_parser
async def _(bot: Bot, event: MessageEvent, state: T_State):
if str(event.message) == "取消":
await find_setu.finish("取消了操作", at_sender=True)
imgs = get_message_imgs(event.json())
if not imgs:
await find_setu.reject("不搞错了,俺要图!")
state["img"] = imgs[0]
@find_setu.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
if get_message_text(event.json()) in ["帮助"]:
await find_setu.finish("通过图片获取本地色图id\n\t示例:查色图(图片)")
imgs = get_message_imgs(event.json())
if imgs:
state["img"] = imgs[0]
@find_setu.got("img", prompt="速速来图!")
async def _(bot: Bot, event: MessageEvent, state: T_State):
img = state["img"]
await find_setu.send(await find_img_index(img, event.user_id), at_sender=True)
async def send_setu_handle(
matcher: Type[Matcher],
event: MessageEvent,
command: str,
msg: str,
num: int,
r18: int,
):
global setu_data_list
# 非 id,在线搜索
tags = msg.split()
# 真寻的色图?怎么可能
if f"{NICKNAME}" in tags:
await matcher.finish("咳咳咳,虽然我很可爱,但是我木有自己的色图~~~有的话记得发我一份呀")
# 本地先拿图,下载失败补上去
setu_list, code = None, 200
setu_count = await get_setu_count(r18)
if (
not Config.get_config("send_setu", "ONLY_USE_LOCAL_SETU") and tags
) or setu_count <= 0:
# 先尝试获取在线图片
urls, text_list, add_databases_list, code = await get_setu_urls(
tags, num, r18, command
)
for x in add_databases_list:
setu_data_list.append(x)
# 未找到符合的色图,想来本地应该也没有
if code == 401:
await setu.finish(urls[0], at_sender=True)
if code == 200:
for i in range(len(urls)):
try:
setu_img, index = await search_online_setu(urls[i])
# 下载成功的话
if index != -1:
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 发送色图 {index}.png"
)
msg_id = await matcher.send(
Message(f"{text_list[i]}\n{setu_img}")
)
else:
if setu_list is None:
setu_list, code = await get_setu_list(tags=tags, r18=r18)
if code != 200:
await setu.finish(setu_list[0], at_sender=True)
if setu_list:
setu_image = random.choice(setu_list)
setu_list.remove(setu_image)
msg_id = await matcher.send(
Message(
gen_message(setu_image)
+ (
await check_local_exists_or_download(setu_image)
)[0]
)
)
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 发送本地色图 {setu_image.local_id}.png"
)
else:
msg_id = await matcher.send(text_list[i] + "\n" + setu_img)
if msg_id:
withdraw_message_manager.withdraw_message(
event,
msg_id["message_id"],
Config.get_config("send_setu", "WITHDRAW_SETU_MESSAGE"),
)
except ActionFailed:
await matcher.finish("坏了,这张图色过头了,我自己看看就行了!", at_sender=True)
return
if code != 200:
await matcher.finish("网络连接失败...", at_sender=True)
# 本地无图
if setu_list is None:
setu_list, code = await get_setu_list(tags=tags, r18=r18)
if code != 200:
await matcher.finish(setu_list[0], at_sender=True)
# 开始发图
for _ in range(num):
if not setu_list:
await setu.finish("坏了,已经没图了,被榨干了!")
setu_image = random.choice(setu_list)
setu_list.remove(setu_image)
try:
msg_id = await matcher.send(
Message(
gen_message(setu_image)
+ (await check_local_exists_or_download(setu_image))[0]
)
)
withdraw_message_manager.withdraw_message(
event,
msg_id["message_id"],
Config.get_config("send_setu", "WITHDRAW_SETU_MESSAGE"),
)
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 发送本地色图 {setu_image.local_id}.png"
)
except ActionFailed:
await matcher.finish("坏了,这张图色过头了,我自己看看就行了!", at_sender=True)
import random
from nonebot import on_command, on_regex
from services.log import logger
from models.sign_group_user import SignGroupUser
from nonebot.message import run_postprocessor
from nonebot.matcher import Matcher
from typing import Optional, Type
from gino.exceptions import UninitializedError
from utils.utils import (
is_number,
get_message_text,
get_message_imgs,
)
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import (
Bot,
MessageEvent,
GroupMessageEvent,
PrivateMessageEvent,
Message,
Event,
)
from .data_source import (
get_setu_list,
get_luoxiang,
search_online_setu,
get_setu_urls,
find_img_index,
gen_message,
check_local_exists_or_download,
add_data_to_database,
get_setu_count,
)
from nonebot.adapters.cqhttp.exception import ActionFailed
from configs.config import Config, NICKNAME
from utils.manager import withdraw_message_manager
import re
try:
import ujson as json
except ModuleNotFoundError:
import json
__zx_plugin_name__ = "色图"
__plugin_usage__ = f"""
usage:
搜索 lolicon 图库,每日色图time...
指令:
色图: 随机本地色图
色图r: 随机在线十张r18涩图
色图 [id]: 本地指定id色图
色图 *[tags]: 在线搜索指定tag色图
色图r *[tags]: 同上
[1-9]张涩图: 本地随机色图连发
[1-9]张[tags]的涩图: 指定tag色图连发
示例:色图 萝莉|少女 白丝|黑丝
示例:色图 萝莉 猫娘
注:
tag至多取前20项,| 为或,萝莉|少女=萝莉或者少女
""".strip()
__plugin_des__ = "不要小看涩图啊混蛋!"
__plugin_cmd__ = ["色图 ?[id]", "色图 ?[tags]", "色图r ?[tags]", "[1-9]张?[tags]色图"]
__plugin_type__ = ("来点好康的",)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 9,
"default_status": True,
"limit_superuser": False,
"cmd": ["色图", "涩图", "瑟图"],
}
__plugin_block_limit__ = {}
__plugin_cd_limit__ = {
"rst": "您冲的太快了,请稍后再冲.",
}
__plugin_configs__ = {
"WITHDRAW_SETU_MESSAGE": {
"value": (0, 1),
"help": "自动撤回,参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)",
"default_value": (0, 1),
},
"ONLY_USE_LOCAL_SETU": {
"value": False,
"help": "仅仅使用本地色图,不在线搜索",
"default_value": False,
},
"INITIAL_SETU_PROBABILITY": {
"value": 0.7,
"help": "初始色图概率,总概率 = 初始色图概率 + 好感度",
"default_value": 0.7
},
"DOWNLOAD_SETU": {
"value": True,
"help": "是否存储下载的色图,使用本地色图可以加快图片发送速度",
"default_value": True
},
"TIMEOUT": {
"value": 10,
"help": "色图下载超时限制(秒)",
"default_value": 10
}
}
Config.add_plugin_config(
"pixiv",
"PIXIV_NGINX_URL",
"i.pixiv.re",
help_="Pixiv反向代理"
)
setu_data_list = []
@run_postprocessor
async def do_something(
matcher: Matcher,
exception: Optional[Exception],
bot: Bot,
event: Event,
state: T_State,
):
global setu_data_list
if isinstance(event, MessageEvent):
if matcher.module == "send_setu":
# 添加数据至数据库
try:
await add_data_to_database(setu_data_list)
logger.info("色图数据自动存储数据库成功...")
setu_data_list = []
except UninitializedError:
pass
setu = on_command(
"色图", aliases={"涩图", "不够色", "来一发", "再来点", "色图r"}, priority=5, block=True
)
setu_reg = on_regex("(.*)[份|发|张|个|次|点](.*)[瑟|色|涩]图$", priority=5, block=True)
find_setu = on_command("查色图", priority=5, block=True)
@setu.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
if isinstance(event, GroupMessageEvent):
impression = (
await SignGroupUser.ensure(event.user_id, event.group_id)
).impression
luox = get_luoxiang(impression)
if luox:
await setu.finish(luox)
r18 = 0
num = 1
# 是否看r18
if state["_prefix"]["raw_command"] == "色图r" and isinstance(
event, PrivateMessageEvent
):
r18 = 1
num = 10
elif state["_prefix"]["raw_command"] == "色图r" and isinstance(
event, GroupMessageEvent
):
await setu.finish(
random.choice(["这种不好意思的东西怎么可能给这么多人看啦", "羞羞脸!给我滚出克私聊!", "变态变态变态变态大变态!"])
)
# 有 数字 的话先尝试本地色图id
if msg and is_number(msg):
setu_list, code = await get_setu_list(int(msg), r18=r18)
if code != 200:
await setu.finish(setu_list[0], at_sender=True)
setu_img, code = await check_local_exists_or_download(setu_list[0])
msg_id = await setu.send(gen_message(setu_list[0]) + setu_img, at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 发送色图 {setu_list[0].local_id}.png"
)
if msg_id:
withdraw_message_manager.withdraw_message(
event,
msg_id["message_id"],
Config.get_config("send_setu", "WITHDRAW_SETU_MESSAGE"),
)
return
await send_setu_handle(setu, event, state["_prefix"]["raw_command"], msg, num, r18)
num_key = {
"一": 1,
"二": 2,
"两": 2,
"双": 2,
"三": 3,
"四": 4,
"五": 5,
"六": 6,
"七": 7,
"八": 8,
"九": 9,
}
@setu_reg.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
if isinstance(event, GroupMessageEvent):
impression = (
await SignGroupUser.ensure(event.user_id, event.group_id)
).impression
luox = get_luoxiang(impression)
if luox:
await setu.finish(luox, at_sender=True)
msg = get_message_text(event.json())
num = 1
msg = re.search(r"(.*)[份发张个次点](.*)[瑟涩色]图", msg)
# 解析 tags 以及 num
if msg:
num = msg.group(1)
tags = msg.group(2)
if tags:
tags = tags[:-1] if tags[-1] == "的" else tags
if num:
num = num[-1]
if num_key.get(num):
num = num_key[num]
elif is_number(num):
try:
num = int(num)
except ValueError:
num = 1
else:
num = 1
else:
return
await send_setu_handle(setu_reg, event, "色图", tags, num, 0)
@find_setu.args_parser
async def _(bot: Bot, event: MessageEvent, state: T_State):
if str(event.message) == "取消":
await find_setu.finish("取消了操作", at_sender=True)
imgs = get_message_imgs(event.json())
if not imgs:
await find_setu.reject("不搞错了,俺要图!")
state["img"] = imgs[0]
@find_setu.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
if get_message_text(event.json()) in ["帮助"]:
await find_setu.finish("通过图片获取本地色图id\n\t示例:查色图(图片)")
imgs = get_message_imgs(event.json())
if imgs:
state["img"] = imgs[0]
@find_setu.got("img", prompt="速速来图!")
async def _(bot: Bot, event: MessageEvent, state: T_State):
img = state["img"]
await find_setu.send(await find_img_index(img, event.user_id), at_sender=True)
async def send_setu_handle(
matcher: Type[Matcher],
event: MessageEvent,
command: str,
msg: str,
num: int,
r18: int,
):
global setu_data_list
# 非 id,在线搜索
tags = msg.split()
# 真寻的色图?怎么可能
if f"{NICKNAME}" in tags:
await matcher.finish("咳咳咳,虽然我很可爱,但是我木有自己的色图~~~有的话记得发我一份呀")
# 本地先拿图,下载失败补上去
setu_list, code = None, 200
setu_count = await get_setu_count(r18)
if (
not Config.get_config("send_setu", "ONLY_USE_LOCAL_SETU") and tags
) or setu_count <= 0:
# 先尝试获取在线图片
urls, text_list, add_databases_list, code = await get_setu_urls(
tags, num, r18, command
)
for x in add_databases_list:
setu_data_list.append(x)
# 未找到符合的色图,想来本地应该也没有
if code == 401:
await setu.finish(urls[0], at_sender=True)
if code == 200:
for i in range(len(urls)):
try:
setu_img, index = await search_online_setu(urls[i])
# 下载成功的话
if index != -1:
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 发送色图 {index}.png"
)
msg_id = await matcher.send(
Message(f"{text_list[i]}\n{setu_img}")
)
else:
if setu_list is None:
setu_list, code = await get_setu_list(tags=tags, r18=r18)
if code != 200:
await setu.finish(setu_list[0], at_sender=True)
if setu_list:
setu_image = random.choice(setu_list)
setu_list.remove(setu_image)
msg_id = await matcher.send(
Message(
gen_message(setu_image)
+ (
await check_local_exists_or_download(setu_image)
)[0]
)
)
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 发送本地色图 {setu_image.local_id}.png"
)
else:
msg_id = await matcher.send(text_list[i] + "\n" + setu_img)
if msg_id:
withdraw_message_manager.withdraw_message(
event,
msg_id["message_id"],
Config.get_config("send_setu", "WITHDRAW_SETU_MESSAGE"),
)
except ActionFailed:
await matcher.finish("坏了,这张图色过头了,我自己看看就行了!", at_sender=True)
return
if code != 200:
await matcher.finish("网络连接失败...", at_sender=True)
# 本地无图
if setu_list is None:
setu_list, code = await get_setu_list(tags=tags, r18=r18)
if code != 200:
await matcher.finish(setu_list[0], at_sender=True)
# 开始发图
for _ in range(num):
if not setu_list:
await setu.finish("坏了,已经没图了,被榨干了!")
setu_image = random.choice(setu_list)
setu_list.remove(setu_image)
try:
msg_id = await matcher.send(
Message(
gen_message(setu_image)
+ (await check_local_exists_or_download(setu_image))[0]
)
)
withdraw_message_manager.withdraw_message(
event,
msg_id["message_id"],
Config.get_config("send_setu", "WITHDRAW_SETU_MESSAGE"),
)
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 发送本地色图 {setu_image.local_id}.png"
)
except ActionFailed:
await matcher.finish("坏了,这张图色过头了,我自己看看就行了!", at_sender=True)
+269 -278
View File
@@ -1,278 +1,269 @@
from configs.path_config import IMAGE_PATH
from utils.message_builder import image
from services.log import logger
from aiohttp.client_exceptions import ClientConnectorError
from utils.image_utils import get_img_hash, compressed_image
from asyncpg.exceptions import UniqueViolationError
from utils.utils import get_local_proxy
from asyncio.exceptions import TimeoutError
from typing import List, Optional
from configs.config import NICKNAME, Config
from ..model import Setu
import aiohttp
import aiofiles
import asyncio
import os
import random
try:
import ujson as json
except ModuleNotFoundError:
import json
url = "https://api.lolicon.app/setu/v2"
path = "_setu/"
r18_path = "_r18/"
# 获取url
async def get_setu_urls(
tags: List[str], num: int = 1, r18: int = 0, command: str = ""
) -> "List[str], List[str], List[tuple], int":
tags = tags[:3] if len(tags) > 3 else tags
params = {
"r18": r18, # 添加r18参数 0为否,1为是,2为混合
"tag": tags, # 若指定tag
"num": 100, # 一次返回的结果数量
"size": ["original"],
}
async with aiohttp.ClientSession() as session:
for count in range(3):
logger.info(f"get_setu_url: count --> {count}")
try:
async with session.get(
url, proxy=get_local_proxy(), timeout=Config.get_config("send_setu", "TIMEOUT"), params=params
) as response:
if response.status == 200:
data = await response.json()
if not data["error"]:
data = data["data"]
(
urls,
text_list,
add_databases_list,
) = await asyncio.get_event_loop().run_in_executor(
None, _setu_data_process, data, command
)
num = num if num < len(data) else len(data)
random_idx = random.sample(range(len(data)), num)
x_urls = []
x_text_lst = []
for x in random_idx:
x_urls.append(urls[x])
x_text_lst.append(text_list[x])
if not x_urls:
return ["没找到符合条件的色图..."], [], [], 401
return x_urls, x_text_lst, add_databases_list, 200
else:
return ["没找到符合条件的色图..."], [], [], 401
except (TimeoutError, ClientConnectorError):
pass
return ["我网线被人拔了..QAQ"], [], [], 999
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
" rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Referer": "https://www.pixiv.net",
}
async def search_online_setu(
url_: str, id_: Optional[int] = None, path_: Optional[str] = None
) -> "MessageSegment, int":
"""
下载色图
:param url_: 色图url
:param id_: 本地id
:param path_: 存储路径
"""
ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
if ws_url:
if ws_url.startswith("http"):
ws_url = ws_url.split("//")[-1]
url_ = url_.replace("i.pximg.net", ws_url).replace("i.pixiv.cat", ws_url)
async with aiohttp.ClientSession(headers=headers) as session:
for i in range(3):
logger.info(f"search_online_setu --> {i}")
try:
async with session.get(url_, proxy=get_local_proxy(), timeout=Config.get_config("send_setu", "TIMEOUT")) as res:
if res.status == 200:
index = random.randint(1, 100000) if id_ is None else id_
path_ = "temp" if not path_ else path_
file = f"{index}_temp_setu.jpg" if not path_ else f"{index}.jpg"
if not os.path.exists(f"{IMAGE_PATH}/{path_}"):
os.mkdir(f"{IMAGE_PATH}/{path_}")
async with aiofiles.open(
f"{IMAGE_PATH}/{path_}/{file}", "wb"
) as f:
try:
await f.write(await res.read())
except TimeoutError:
continue
if id_ is not None:
if (
os.path.getsize(f"{IMAGE_PATH}/{path_}/{index}.jpg")
> 1024 * 1024 * 1.5
):
compressed_image(
f"{IMAGE_PATH}/{path_}/{index}.jpg",
)
logger.info(f"下载 lolicon图片 {url_} 成功, id:{index}")
return image(file, path_), index
else:
logger.warning(f"访问 lolicon图片 {url_} 失败 status:{res.status}")
# return '\n这图好难下载啊!QAQ', -1, False
except (TimeoutError, ClientConnectorError):
pass
return "图片被小怪兽恰掉啦..!QAQ", -1
# 检测本地是否有id涩图,无的话则下载
async def check_local_exists_or_download(setu_image: Setu) -> "MessageSegment, int":
path_ = None
id_ = None
if Config.get_config("send_setu", "DOWNLOAD_SETU"):
id_ = setu_image.local_id
if setu_image.is_r18:
path_ = "_r18"
else:
path_ = path
if os.path.exists(f"{IMAGE_PATH}/{path_}/{setu_image.local_id}.jpg"):
return image(f"{setu_image.local_id}.jpg", path_), 200
return await search_online_setu(setu_image.img_url, id_, path_)
# 添加涩图数据到数据库
async def add_data_to_database(lst: List[tuple]):
tmp = []
for x in lst:
if x not in tmp:
tmp.append(x)
if tmp:
for x in tmp:
try:
r18 = 1 if "R-18" in x[5] else 0
idx = await Setu.get_image_count(r18)
await Setu.add_setu_data(
idx,
x[0],
x[1],
x[2],
x[3],
x[4],
x[5],
)
except UniqueViolationError:
pass
# 拿到本地色图列表
async def get_setu_list(
index: Optional[int] = None, tags: Optional[List[str]] = None, r18: int = 0
) -> "list, int":
if index:
image_count = await Setu.get_image_count(r18) - 1
if index < 0 or index > image_count:
return [f"超过当前上下限!({image_count})"], 999
image_list = [await Setu.query_image(index, r18=r18)]
elif tags:
image_list = await Setu.query_image(tags=tags, r18=r18)
else:
image_list = await Setu.query_image(r18=r18)
if not image_list:
return ["没找到符合条件的色图..."], 998
return image_list, 200
# 初始化消息
def gen_message(setu_image: Setu, img_msg: bool = False) -> str:
local_id = setu_image.local_id
title = setu_image.title
author = setu_image.author
pid = setu_image.pid
return (
f"id:{local_id}\n"
f"title:{title}\n"
f"author:{author}\n"
f"PID:{pid}\n"
f"{image(f'{local_id}', f'{r18_path if setu_image.is_r18 else path}') if img_msg else ''}"
)
# 罗翔老师!
def get_luoxiang(impression):
probability = (
impression + Config.get_config("send_setu", "INITIAL_SETU_PROBABILITY") * 100
)
if probability < random.randint(1, 101):
return (
"我为什么要给你发这个?"
+ image(random.choice(os.listdir(IMAGE_PATH + "luoxiang/")), "luoxiang")
+ f"\n(快向{NICKNAME}签到提升好感度吧!)"
)
return None
async def get_setu_count(r18: int) -> int:
"""
获取色图数量
:param r18: r18类型
"""
return await Setu.get_image_count(r18)
async def find_img_index(img_url, user_id):
async with aiohttp.ClientSession() as session:
async with session.get(img_url, proxy=get_local_proxy(), timeout=Config.get_config("send_setu", "TIMEOUT")) as res:
async with aiofiles.open(
IMAGE_PATH + f"temp/{user_id}_find_setu_index.jpg", "wb"
) as f:
await f.write(await res.read())
img_hash = str(get_img_hash(IMAGE_PATH + f"temp/{user_id}_find_setu_index.jpg"))
setu_img = await Setu.get_image_in_hash(img_hash)
if setu_img:
return (
f"id:{setu_img.local_id}\n"
f"title:{setu_img.title}\n"
f"author:{setu_img.author}\n"
f"PID:{setu_img.pid}"
)
return "该图不在色图库中或色图库未更新!"
# 处理色图数据
def _setu_data_process(data: dict, command: str) -> "list, list, list":
urls = []
text_list = []
add_databases_list = []
for i in range(len(data)):
img_url = data[i]["urls"]["original"]
img_url = (
img_url.replace("i.pixiv.cat", "i.pximg.net")
if "i.pixiv.cat" in img_url
else img_url
)
title = data[i]["title"]
author = data[i]["author"]
pid = data[i]["pid"]
urls.append(img_url)
text_list.append(f"title:{title}\nauthor:{author}\nPID:{pid}")
tags = []
for j in range(len(data[i]["tags"])):
tags.append(data[i]["tags"][j])
if command != "色图r":
if "R-18" in tags:
tags.remove("R-18")
add_databases_list.append(
(
title,
author,
pid,
"",
img_url,
",".join(tags),
)
)
return urls, text_list, add_databases_list
from configs.path_config import IMAGE_PATH
from utils.message_builder import image
from services.log import logger
from utils.image_utils import get_img_hash, compressed_image
from asyncpg.exceptions import UniqueViolationError
from asyncio.exceptions import TimeoutError
from typing import List, Optional
from configs.config import NICKNAME, Config
from utils.http_utils import AsyncHttpx
from ..model import Setu
import asyncio
import os
import random
try:
import ujson as json
except ModuleNotFoundError:
import json
url = "https://api.lolicon.app/setu/v2"
path = "_setu/"
r18_path = "_r18/"
# 获取url
async def get_setu_urls(
tags: List[str], num: int = 1, r18: int = 0, command: str = ""
) -> "List[str], List[str], List[tuple], int":
tags = tags[:3] if len(tags) > 3 else tags
params = {
"r18": r18, # 添加r18参数 0为否,1为是,2为混合
"tag": tags, # 若指定tag
"num": 100, # 一次返回的结果数量
"size": ["original"],
}
for count in range(3):
logger.info(f"get_setu_url: count --> {count}")
try:
response = await AsyncHttpx.get(
url, timeout=Config.get_config("send_setu", "TIMEOUT"), params=params
)
if response.status_code == 200:
data = await response.json()
if not data["error"]:
data = data["data"]
(
urls,
text_list,
add_databases_list,
) = await asyncio.get_event_loop().run_in_executor(
None, _setu_data_process, data, command
)
num = num if num < len(data) else len(data)
random_idx = random.sample(range(len(data)), num)
x_urls = []
x_text_lst = []
for x in random_idx:
x_urls.append(urls[x])
x_text_lst.append(text_list[x])
if not x_urls:
return ["没找到符合条件的色图..."], [], [], 401
return x_urls, x_text_lst, add_databases_list, 200
else:
return ["没找到符合条件的色图..."], [], [], 401
except TimeoutError:
pass
except Exception as e:
logger.error(f"send_setu 访问页面错误 {type(e)}:{e}")
return ["我网线被人拔了..QAQ"], [], [], 999
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
" rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Referer": "https://www.pixiv.net",
}
async def search_online_setu(
url_: str, id_: Optional[int] = None, path_: Optional[str] = None
) -> "MessageSegment, int":
"""
下载色图
:param url_: 色图url
:param id_: 本地id
:param path_: 存储路径
"""
ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
if ws_url:
url_ = url_.replace("i.pximg.net", ws_url).replace("i.pixiv.cat", ws_url)
for i in range(3):
logger.info(f"search_online_setu --> {i}")
try:
index = random.randint(1, 100000) if id_ is None else id_
path_ = "temp" if not path_ else path_
file = f"{index}_temp_setu.jpg" if not path_ else f"{index}.jpg"
if not os.path.exists(f"{IMAGE_PATH}/{path_}"):
os.mkdir(f"{IMAGE_PATH}/{path_}")
if not await AsyncHttpx.download_file(
url_,
f"{IMAGE_PATH}/{path_}/{file}",
timeout=Config.get_config("send_setu", "TIMEOUT"),
):
continue
if id_ is not None:
if (
os.path.getsize(f"{IMAGE_PATH}/{path_}/{index}.jpg")
> 1024 * 1024 * 1.5
):
compressed_image(
f"{IMAGE_PATH}/{path_}/{index}.jpg",
)
logger.info(f"下载 lolicon图片 {url_} 成功, id:{index}")
return image(file, path_), index
except TimeoutError:
pass
except Exception as e:
logger.error(f"send_setu 下载图片错误 {type(e)}:{e}")
return "图片被小怪兽恰掉啦..!QAQ", -1
# 检测本地是否有id涩图,无的话则下载
async def check_local_exists_or_download(setu_image: Setu) -> "MessageSegment, int":
path_ = None
id_ = None
if Config.get_config("send_setu", "DOWNLOAD_SETU"):
id_ = setu_image.local_id
if setu_image.is_r18:
path_ = "_r18"
else:
path_ = path
if os.path.exists(f"{IMAGE_PATH}/{path_}/{setu_image.local_id}.jpg"):
return image(f"{setu_image.local_id}.jpg", path_), 200
return await search_online_setu(setu_image.img_url, id_, path_)
# 添加涩图数据到数据库
async def add_data_to_database(lst: List[tuple]):
tmp = []
for x in lst:
if x not in tmp:
tmp.append(x)
if tmp:
for x in tmp:
try:
r18 = 1 if "R-18" in x[5] else 0
idx = await Setu.get_image_count(r18)
await Setu.add_setu_data(
idx,
x[0],
x[1],
x[2],
x[3],
x[4],
x[5],
)
except UniqueViolationError:
pass
# 拿到本地色图列表
async def get_setu_list(
index: Optional[int] = None, tags: Optional[List[str]] = None, r18: int = 0
) -> "list, int":
if index:
image_count = await Setu.get_image_count(r18) - 1
if index < 0 or index > image_count:
return [f"超过当前上下限!({image_count})"], 999
image_list = [await Setu.query_image(index, r18=r18)]
elif tags:
image_list = await Setu.query_image(tags=tags, r18=r18)
else:
image_list = await Setu.query_image(r18=r18)
if not image_list:
return ["没找到符合条件的色图..."], 998
return image_list, 200
# 初始化消息
def gen_message(setu_image: Setu, img_msg: bool = False) -> str:
local_id = setu_image.local_id
title = setu_image.title
author = setu_image.author
pid = setu_image.pid
return (
f"id:{local_id}\n"
f"title:{title}\n"
f"author:{author}\n"
f"PID:{pid}\n"
f"{image(f'{local_id}', f'{r18_path if setu_image.is_r18 else path}') if img_msg else ''}"
)
# 罗翔老师!
def get_luoxiang(impression):
probability = (
impression + Config.get_config("send_setu", "INITIAL_SETU_PROBABILITY") * 100
)
if probability < random.randint(1, 101):
return (
"我为什么要给你发这个?"
+ image(random.choice(os.listdir(IMAGE_PATH + "luoxiang/")), "luoxiang")
+ f"\n(快向{NICKNAME}签到提升好感度吧!)"
)
return None
async def get_setu_count(r18: int) -> int:
"""
获取色图数量
:param r18: r18类型
"""
return await Setu.get_image_count(r18)
async def find_img_index(img_url, user_id):
if not await AsyncHttpx.download_file(
img_url,
IMAGE_PATH + f"temp/{user_id}_find_setu_index.jpg",
timeout=Config.get_config("send_setu", "TIMEOUT"),
):
return "检索图片下载上失败..."
img_hash = str(get_img_hash(IMAGE_PATH + f"temp/{user_id}_find_setu_index.jpg"))
setu_img = await Setu.get_image_in_hash(img_hash)
if setu_img:
return (
f"id:{setu_img.local_id}\n"
f"title:{setu_img.title}\n"
f"author:{setu_img.author}\n"
f"PID:{setu_img.pid}"
)
return "该图不在色图库中或色图库未更新!"
# 处理色图数据
def _setu_data_process(data: dict, command: str) -> "list, list, list":
urls = []
text_list = []
add_databases_list = []
for i in range(len(data)):
img_url = data[i]["urls"]["original"]
img_url = (
img_url.replace("i.pixiv.cat", "i.pximg.net")
if "i.pixiv.cat" in img_url
else img_url
)
title = data[i]["title"]
author = data[i]["author"]
pid = data[i]["pid"]
urls.append(img_url)
text_list.append(f"title:{title}\nauthor:{author}\nPID:{pid}")
tags = []
for j in range(len(data[i]["tags"])):
tags.append(data[i]["tags"][j])
if command != "色图r":
if "R-18" in tags:
tags.remove("R-18")
add_databases_list.append(
(
title,
author,
pid,
"",
img_url,
",".join(tags),
)
)
return urls, text_list, add_databases_list
+48 -48
View File
@@ -1,48 +1,48 @@
from utils.utils import scheduler
from nonebot import on_command
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from nonebot.adapters import Bot, Event
from nonebot.rule import to_me
from .data_source import update_setu_img
from configs.config import Config
__zx_plugin_name__ = "更新色图 [Superuser]"
__plugin_usage__ = """
usage:
更新数据库内存在的色图
指令:
更新色图
""".strip()
__plugin_cmd__ = ["更新色图"]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_block_limit__ = {
"rst": "色图正在更新..."
}
update_setu = on_command(
"更新色图", rule=to_me(), permission=SUPERUSER, priority=1, block=True
)
@update_setu.handle()
async def _(bot: Bot, event: Event, state: T_State):
if Config.get_config("send_setu", "DOWNLOAD_SETU"):
await update_setu.send("开始更新色图...", at_sender=True)
await update_setu.send(await update_setu_img(), at_sender=True)
else:
await update_setu.finish("更新色图配置未开启")
# 更新色图
@scheduler.scheduled_job(
"cron",
hour=4,
minute=30,
)
async def _():
if Config.get_config("send_setu", "DOWNLOAD_SETU"):
await update_setu_img()
from utils.utils import scheduler
from nonebot import on_command
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from nonebot.adapters import Bot, Event
from nonebot.rule import to_me
from .data_source import update_setu_img
from configs.config import Config
__zx_plugin_name__ = "更新色图 [Superuser]"
__plugin_usage__ = """
usage:
更新数据库内存在的色图
指令:
更新色图
""".strip()
__plugin_cmd__ = ["更新色图"]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_block_limit__ = {
"rst": "色图正在更新..."
}
update_setu = on_command(
"更新色图", rule=to_me(), permission=SUPERUSER, priority=1, block=True
)
@update_setu.handle()
async def _(bot: Bot, event: Event, state: T_State):
if Config.get_config("send_setu", "DOWNLOAD_SETU"):
await update_setu.send("开始更新色图...", at_sender=True)
await update_setu.send(await update_setu_img(), at_sender=True)
else:
await update_setu.finish("更新色图配置未开启")
# 更新色图
@scheduler.scheduled_job(
"cron",
hour=4,
minute=30,
)
async def _():
if Config.get_config("send_setu", "DOWNLOAD_SETU"):
await update_setu_img()
+163 -177
View File
@@ -1,177 +1,163 @@
from configs.path_config import IMAGE_PATH, TEXT_PATH, TEMP_PATH
from services.log import logger
from datetime import datetime
from utils.image_utils import compressed_image, get_img_hash
from utils.utils import get_bot, get_local_proxy
from asyncio.exceptions import TimeoutError
from ..model import Setu
from aiohttp.client_exceptions import ClientConnectorError
from asyncpg.exceptions import UniqueViolationError
from configs.config import Config
from pathlib import Path
from nonebot import Driver
import nonebot
import aiofiles
import aiohttp
import os
import ujson as json
import shutil
driver: Driver = nonebot.get_driver()
_path = Path(IMAGE_PATH)
# 替换旧色图数据,修复local_id一直是50的问题
@driver.on_startup
async def update_old_setu_data():
path = Path(TEXT_PATH)
setu_data_file = path / "setu_data.json"
r18_data_file = path / "r18_setu_data.json"
if setu_data_file.exists() or r18_data_file.exists():
index = 0
r18_index = 0
count = 0
fail_count = 0
for file in [setu_data_file, r18_data_file]:
if file.exists():
data = json.load(open(file, "r", encoding="utf8"))
for x in data:
if file == setu_data_file:
idx = index
if 'R-18' in data[x]["tags"]:
data[x]["tags"].remove('R-18')
else:
idx = r18_index
img_url = (
data[x]["img_url"].replace("i.pixiv.cat", "i.pximg.net")
if "i.pixiv.cat" in data[x]["img_url"]
else data[x]["img_url"]
)
# idx = r18_index if 'R-18' in data[x]["tags"] else index
try:
await Setu.add_setu_data(
idx,
data[x]["title"],
data[x]["author"],
data[x]["pid"],
data[x]["img_hash"],
img_url,
",".join(data[x]["tags"]),
)
count += 1
if 'R-18' in data[x]["tags"]:
r18_index += 1
else:
index += 1
logger.info(f'添加旧色图数据成功 PID:{data[x]["pid"]} index:{idx}....')
except UniqueViolationError:
fail_count += 1
logger.info(f'添加旧色图数据失败,色图重复 PID:{data[x]["pid"]} index:{idx}....')
file.unlink()
setu_url_path = path / "setu_url.json"
setu_r18_url_path = path / "setu_r18_url.json"
if setu_url_path.exists():
setu_url_path.unlink()
if setu_r18_url_path.exists():
setu_r18_url_path.unlink()
logger.info(f"更新旧色图数据完成,成功更新数据:{count} 条,累计失败:{fail_count} 条")
# 删除色图rar文件夹
shutil.rmtree(Path(IMAGE_PATH) / "setu_rar", ignore_errors=True)
shutil.rmtree(Path(IMAGE_PATH) / "r18_rar", ignore_errors=True)
shutil.rmtree(Path(IMAGE_PATH) / "rar", ignore_errors=True)
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
" rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Referer": "https://www.pixiv.net",
}
async def update_setu_img():
image_list = await Setu.get_all_setu()
image_list.reverse()
_success = 0
error_info = []
error_type = []
count = 0
async with aiohttp.ClientSession(headers=headers) as session:
for image in image_list:
count += 1
path = _path / "_r18" if image.is_r18 else _path / "_setu"
rar_path = Path(TEMP_PATH)
local_image = path / f"{image.local_id}.jpg"
path.mkdir(exist_ok=True, parents=True)
rar_path.mkdir(exist_ok=True, parents=True)
if not local_image.exists() or not image.img_hash:
url_ = image.img_url
ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
if ws_url.startswith("http"):
ws_url = ws_url.split("//")[-1]
url_ = url_.replace("i.pximg.net", ws_url).replace("i.pixiv.cat", ws_url)
for _ in range(3):
try:
async with session.get(
url_, proxy=get_local_proxy(), timeout=30
) as response:
if response.status == 200:
async with aiofiles.open(
rar_path / f'{image.local_id}.jpg',
"wb",
) as f:
await f.write(await response.read())
_success += 1
try:
if (
os.path.getsize(
rar_path / f'{image.local_id}.jpg',
)
> 1024 * 1024 * 1.5
):
compressed_image(
rar_path / f"{image.local_id}.jpg",
path / f"{image.local_id}.jpg"
)
else:
logger.info(
f"不需要压缩,移动图片{rar_path}/{image.local_id}.jpg "
f"--> /{path}/{image.local_id}.jpg"
)
os.rename(
f"{rar_path}/{image.local_id}.jpg",
f"{path}/{image.local_id}.jpg",
)
except FileNotFoundError:
logger.warning(f"文件 {image.local_id}.jpg 不存在,跳过...")
continue
img_hash = str(
get_img_hash(
f"{path}/{image.local_id}.jpg"
)
)
await Setu.update_setu_data(
image.pid, img_hash=img_hash
)
break
except (TimeoutError, ClientConnectorError) as e:
logger.warning(f"{image.local_id}.jpg 更新失败 ..{type(e)}:{e}")
except Exception as e:
logger.error(f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}")
if type(e) not in error_type:
error_type.append(type(e))
error_info.append(
f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}"
)
else:
logger.info(f'更新色图 {image.local_id}.jpg 已存在')
error_info = ['无报错..'] if not error_info else error_info
if count or _success or (error_info and "无报错.." not in error_info):
await get_bot().send_private_msg(
user_id=int(list(get_bot().config.superusers)[0]),
message=f'{str(datetime.now()).split(".")[0]} 更新 色图 完成,本地存在 {count} 张,实际更新 {_success} 张,以下为更新时未知错误:\n'
+ "\n".join(error_info),
)
from configs.path_config import IMAGE_PATH, TEXT_PATH, TEMP_PATH
from services.log import logger
from datetime import datetime
from utils.image_utils import compressed_image, get_img_hash
from utils.utils import get_bot
from asyncio.exceptions import TimeoutError
from ..model import Setu
from asyncpg.exceptions import UniqueViolationError
from configs.config import Config
from utils.http_utils import AsyncHttpx
from pathlib import Path
from nonebot import Driver
import nonebot
import os
import ujson as json
import shutil
driver: Driver = nonebot.get_driver()
_path = Path(IMAGE_PATH)
# 替换旧色图数据,修复local_id一直是50的问题
@driver.on_startup
async def update_old_setu_data():
path = Path(TEXT_PATH)
setu_data_file = path / "setu_data.json"
r18_data_file = path / "r18_setu_data.json"
if setu_data_file.exists() or r18_data_file.exists():
index = 0
r18_index = 0
count = 0
fail_count = 0
for file in [setu_data_file, r18_data_file]:
if file.exists():
data = json.load(open(file, "r", encoding="utf8"))
for x in data:
if file == setu_data_file:
idx = index
if 'R-18' in data[x]["tags"]:
data[x]["tags"].remove('R-18')
else:
idx = r18_index
img_url = (
data[x]["img_url"].replace("i.pixiv.cat", "i.pximg.net")
if "i.pixiv.cat" in data[x]["img_url"]
else data[x]["img_url"]
)
# idx = r18_index if 'R-18' in data[x]["tags"] else index
try:
await Setu.add_setu_data(
idx,
data[x]["title"],
data[x]["author"],
data[x]["pid"],
data[x]["img_hash"],
img_url,
",".join(data[x]["tags"]),
)
count += 1
if 'R-18' in data[x]["tags"]:
r18_index += 1
else:
index += 1
logger.info(f'添加旧色图数据成功 PID:{data[x]["pid"]} index:{idx}....')
except UniqueViolationError:
fail_count += 1
logger.info(f'添加旧色图数据失败,色图重复 PID:{data[x]["pid"]} index:{idx}....')
file.unlink()
setu_url_path = path / "setu_url.json"
setu_r18_url_path = path / "setu_r18_url.json"
if setu_url_path.exists():
setu_url_path.unlink()
if setu_r18_url_path.exists():
setu_r18_url_path.unlink()
logger.info(f"更新旧色图数据完成,成功更新数据:{count} 条,累计失败:{fail_count} 条")
# 删除色图rar文件夹
shutil.rmtree(Path(IMAGE_PATH) / "setu_rar", ignore_errors=True)
shutil.rmtree(Path(IMAGE_PATH) / "r18_rar", ignore_errors=True)
shutil.rmtree(Path(IMAGE_PATH) / "rar", ignore_errors=True)
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6;"
" rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Referer": "https://www.pixiv.net",
}
async def update_setu_img():
image_list = await Setu.get_all_setu()
image_list.reverse()
_success = 0
error_info = []
error_type = []
count = 0
for image in image_list:
count += 1
path = _path / "_r18" if image.is_r18 else _path / "_setu"
rar_path = Path(TEMP_PATH)
local_image = path / f"{image.local_id}.jpg"
path.mkdir(exist_ok=True, parents=True)
rar_path.mkdir(exist_ok=True, parents=True)
if not local_image.exists() or not image.img_hash:
url_ = image.img_url
ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
if ws_url:
url_ = url_.replace("i.pximg.net", ws_url).replace("i.pixiv.cat", ws_url)
try:
if not await AsyncHttpx.download_file(url_, rar_path / f'{image.local_id}.jpg'):
continue
_success += 1
try:
if (
os.path.getsize(
rar_path / f'{image.local_id}.jpg',
)
> 1024 * 1024 * 1.5
):
compressed_image(
rar_path / f"{image.local_id}.jpg",
path / f"{image.local_id}.jpg"
)
else:
logger.info(
f"不需要压缩,移动图片{rar_path}/{image.local_id}.jpg "
f"--> /{path}/{image.local_id}.jpg"
)
os.rename(
f"{rar_path}/{image.local_id}.jpg",
f"{path}/{image.local_id}.jpg",
)
except FileNotFoundError:
logger.warning(f"文件 {image.local_id}.jpg 不存在,跳过...")
continue
img_hash = str(
get_img_hash(
f"{path}/{image.local_id}.jpg"
)
)
await Setu.update_setu_data(
image.pid, img_hash=img_hash
)
except Exception as e:
_success -= 1
logger.error(f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}")
if type(e) not in error_type:
error_type.append(type(e))
error_info.append(
f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}"
)
else:
logger.info(f'更新色图 {image.local_id}.jpg 已存在')
error_info = ['无报错..'] if not error_info else error_info
if count or _success or (error_info and "无报错.." not in error_info):
await get_bot().send_private_msg(
user_id=int(list(get_bot().config.superusers)[0]),
message=f'{str(datetime.now()).split(".")[0]} 更新 色图 完成,本地存在 {count} 张,实际更新 {_success} 张,以下为更新时未知错误:\n'
+ "\n".join(error_info),
)