From 1aed19035eddd65ad75bd45facdf95a8703f5199 Mon Sep 17 00:00:00 2001 From: HibiKier <775757368@qq.com> Date: Thu, 23 May 2024 14:28:48 +0800 Subject: [PATCH] =?UTF-8?q?feat=E2=9C=A8:=20search=5Fanime?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- poetry.lock | 36 ++++++++- pyproject.toml | 1 + zhenxun/plugins/poke/__init__.py | 85 +++++++++++++++++++++ zhenxun/plugins/search_anime/__init__.py | 67 ++++++++++++++++ zhenxun/plugins/search_anime/data_source.py | 53 +++++++++++++ 5 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 zhenxun/plugins/poke/__init__.py create mode 100644 zhenxun/plugins/search_anime/__init__.py create mode 100644 zhenxun/plugins/search_anime/data_source.py diff --git a/poetry.lock b/poetry.lock index a0e7fedb..35afa584 100644 --- a/poetry.lock +++ b/poetry.lock @@ -654,6 +654,25 @@ type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" reference = "ali" +[[package]] +name = "feedparser" +version = "6.0.11" +description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds" +optional = false +python-versions = ">=3.6" +files = [ + {file = "feedparser-6.0.11-py3-none-any.whl", hash = "sha256:0be7ee7b395572b19ebeb1d6aafb0028dee11169f1c934e0ed67d54992f4ad45"}, + {file = "feedparser-6.0.11.tar.gz", hash = "sha256:c9d0407b64c6f2a065d0ebb292c2b35c01050cc0dc33757461aaabdc4c4184d5"}, +] + +[package.dependencies] +sgmllib3k = "*" + +[package.source] +type = "legacy" +url = "https://mirrors.aliyun.com/pypi/simple" +reference = "ali" + [[package]] name = "filelock" version = "3.13.1" @@ -2347,6 +2366,21 @@ type = "legacy" url = "https://mirrors.aliyun.com/pypi/simple" reference = "ali" +[[package]] +name = "sgmllib3k" +version = "1.0.0" +description = "Py3k port of sgmllib." +optional = false +python-versions = "*" +files = [ + {file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"}, +] + +[package.source] +type = "legacy" +url = "https://mirrors.aliyun.com/pypi/simple" +reference = "ali" + [[package]] name = "six" version = "1.16.0" @@ -3171,4 +3205,4 @@ reference = "ali" [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "1d5f9655208fe3bde4ebf3e4f39979dcc961d338d3735d001eb234acfe58f8e3" +content-hash = "11beb90d388207c12255f2de15ad66f40ede82677ceb966a93bc31ebd97977f3" diff --git a/pyproject.toml b/pyproject.toml index 678d2d0b..af263298 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,7 @@ pypinyin = "^0.51.0" beautifulsoup4 = "^4.12.3" lxml = "^5.1.0" psutil = "^5.9.8" +feedparser = "^6.0.11" [tool.poetry.dev-dependencies] diff --git a/zhenxun/plugins/poke/__init__.py b/zhenxun/plugins/poke/__init__.py new file mode 100644 index 00000000..555ebf15 --- /dev/null +++ b/zhenxun/plugins/poke/__init__.py @@ -0,0 +1,85 @@ +import os +import random + +from nonebot import on_notice +from nonebot.adapters.onebot.v11 import PokeNotifyEvent +from nonebot.adapters.onebot.v11.message import MessageSegment +from nonebot.plugin import PluginMetadata +from nonebot_plugin_saa import Image, MessageFactory, Text + +from zhenxun.configs.path_config import IMAGE_PATH, RECORD_PATH +from zhenxun.configs.utils import PluginExtraData +from zhenxun.models.ban_console import BanConsole +from zhenxun.services.log import logger +from zhenxun.utils.utils import CountLimiter + +__plugin_meta__ = PluginMetadata( + name="戳一戳", + description="戳一戳发送语音美图萝莉图不美哉?", + usage=""" + 戳一戳随机掉落语音或美图萝莉图 + """.strip(), + extra=PluginExtraData(author="HibiKier", version="0.1", menu_type="其他").dict(), +) + +REPLY_MESSAGE = [ + "lsp你再戳?", + "连个可爱美少女都要戳的肥宅真恶心啊。", + "你再戳!", + "?再戳试试?", + "别戳了别戳了再戳就坏了555", + "我爪巴爪巴,球球别再戳了", + "你戳你🐎呢?!", + "那...那里...那里不能戳...绝对...", + "(。´・ω・)ん?", + "有事恁叫我,别天天一个劲戳戳戳!", + "欸很烦欸!你戳🔨呢", + "?", + "再戳一下试试?", + "???", + "正在关闭对您的所有服务...关闭成功", + "啊呜,太舒服刚刚竟然睡着了。什么事?", + "正在定位您的真实地址...定位成功。轰炸机已起飞", +] + + +_clmt = CountLimiter(3) + +poke_ = on_notice(priority=5, block=False) + + +@poke_.handle() +async def _(event: PokeNotifyEvent): + uid = str(event.user_id) if event.user_id else None + gid = str(event.group_id) if event.group_id else None + if event.self_id == event.target_id: + _clmt.increase(event.user_id) + if _clmt.check(event.user_id) or random.random() < 0.3: + rst = "" + if random.random() < 0.15: + await BanConsole.ban(uid, gid, 1, 60) + rst = "气死我了!" + await poke_.finish(rst + random.choice(REPLY_MESSAGE), at_sender=True) + rand = random.random() + path = random.choice(["luoli", "meitu"]) + if rand <= 0.3 and len(os.listdir(IMAGE_PATH / "image_management" / path)) > 0: + index = random.randint( + 0, len(os.listdir(IMAGE_PATH / "image_management" / path)) - 1 + ) + await MessageFactory( + [ + Text(f"id: {index}"), + Image(IMAGE_PATH / "image_management" / path / f"{index}.jpg"), + ] + ).send() + logger.info(f"USER {event.user_id} 戳了戳我") + elif 0.3 < rand < 0.6: + voice = random.choice(os.listdir(RECORD_PATH / "dinggong")) + result = MessageSegment.record(RECORD_PATH / "dinggong" / voice) + await poke_.send(result) + await poke_.send(voice.split("_")[1]) + logger.info( + f'USER {event.user_id} 戳了戳我 回复: {result} \n {voice.split("_")[1]}' + ) + else: + await poke_.send(MessageSegment("poke", {"qq": event.user_id})) diff --git a/zhenxun/plugins/search_anime/__init__.py b/zhenxun/plugins/search_anime/__init__.py new file mode 100644 index 00000000..b8aa1465 --- /dev/null +++ b/zhenxun/plugins/search_anime/__init__.py @@ -0,0 +1,67 @@ +from nonebot.adapters import Bot +from nonebot.plugin import PluginMetadata +from nonebot_plugin_alconna import Alconna, Args, Arparma, Match, on_alconna +from nonebot_plugin_saa import Text +from nonebot_plugin_session import EventSession + +from zhenxun.configs.config import Config +from zhenxun.configs.utils import BaseBlock, PluginExtraData, RegisterConfig +from zhenxun.services.log import logger + +from .data_source import from_anime_get_info + +__plugin_meta__ = PluginMetadata( + name="搜番", + description="找不到想看的动漫吗?", + usage=""" + 搜索动漫资源 + 指令: + 搜番 [番剧名称或者关键词] + 示例:搜番 刀剑神域 + """.strip(), + extra=PluginExtraData( + author="HibiKier", + version="0.1", + menu_type="一些工具", + limits=[BaseBlock(result="搜索还未完成,不要重复触发!")], + configs=[ + RegisterConfig( + key="SEARCH_ANIME_MAX_INFO", + value=20, + help="搜索动漫返回的最大数量", + default_value=20, + type=10, + ) + ], + ).dict(), +) + +_matcher = on_alconna(Alconna("搜番", Args["name?", str]), priority=5, block=True) + + +@_matcher.handle() +async def _(name: Match[str]): + if name.available: + _matcher.set_path_arg("name", name.result) + + +@_matcher.got_path("name", prompt="是不是少了番名?") +async def _(session: EventSession, arparma: Arparma, name: str): + gid = session.id3 or session.id2 + await Text(f"开始搜番 {name}...").send() + anime_report = await from_anime_get_info( + name, + Config.get_config("search_anime", "SEARCH_ANIME_MAX_INFO"), + ) + if anime_report: + if isinstance(anime_report, str): + await Text(anime_report).finish() + await Text("\n\n".join(anime_report)).send() + logger.info( + f"搜索番剧 {name} 成功: {anime_report}", + arparma.header_result, + session=session, + ) + else: + logger.info(f"未找到番剧 {name}...") + await Text(f"未找到番剧 {name}(也有可能是超时,再尝试一下?)").send() diff --git a/zhenxun/plugins/search_anime/data_source.py b/zhenxun/plugins/search_anime/data_source.py new file mode 100644 index 00000000..59d0ac61 --- /dev/null +++ b/zhenxun/plugins/search_anime/data_source.py @@ -0,0 +1,53 @@ +import time +from urllib import parse + +import feedparser +from lxml import etree + +from zhenxun.services.log import logger +from zhenxun.utils.http_utils import AsyncHttpx + + +async def from_anime_get_info(key_word: str, max_: int) -> str | list[str]: + s_time = time.time() + url = "https://share.dmhy.org/topics/rss/rss.xml?keyword=" + parse.quote(key_word) + try: + repass = await get_repass(url, max_) + except Exception as e: + logger.error(f"发生了一些错误 {type(e)}", e=e) + return "发生了一些错误!" + repass.insert(0, f"搜索 {key_word} 结果(耗时 {int(time.time() - s_time)} 秒):\n") + return repass + + +async def get_repass(url: str, max_: int) -> list[str]: + put_line = [] + text = (await AsyncHttpx.get(url)).text + d = feedparser.parse(text) + max_ = ( + max_ + if max_ < len([e.link for e in d.entries]) + else len([e.link for e in d.entries]) + ) + url_list = [e.link for e in d.entries][:max_] + for u in url_list: + try: + text = (await AsyncHttpx.get(u)).text + html = etree.HTML(text) # type: ignore + magent = html.xpath('.//a[@id="a_magnet"]/text()')[0] + title = html.xpath(".//h3/text()")[0] + item = html.xpath('//div[@class="info resource-info right"]/ul/li') + class_a = ( + item[0] + .xpath("string(.)")[5:] + .strip() + .replace("\xa0", "") + .replace("\t", "") + ) + size = item[3].xpath("string(.)")[5:].strip() + put_line.append( + "【{}】| {}\n【{}】| {}".format(class_a, title, size, magent) + ) + except Exception as e: + logger.error(f"搜番发生错误", e=e) + return put_line