├── .gitignore ├── README.md ├── __init__.py ├── __pycache__ ├── __init__.cpython-311.pyc ├── forward_message.cpython-311.pyc ├── get_image.cpython-311.pyc └── main.cpython-311.pyc ├── forward_message.py ├── get_image.py ├── main.py ├── requirements.txt └── temp.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GiveMeSetuPlugin 2 | 3 | 30 | 31 | ## 安装 32 | 33 | 配置完成 [QChatGPT](https://github.com/RockChinQ/QChatGPT) 主程序后使用管理员账号向机器人发送命令即可安装: 34 | 35 | ``` 36 | !plugin get https://github.com/Hanschase/GiveMeSetuPlugin 37 | ``` 38 | 或查看详细的[插件安装说明](https://github.com/RockChinQ/QChatGPT/wiki/5-%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8) 39 | 40 | ## 使用 41 | 1.需要在napcat里新增端口为3000的http server(点击右上角新增)
42 | ![image](https://github.com/user-attachments/assets/0a5e68b4-ec3e-416c-96e9-da5f2a94b007)
43 | 2.搜图指令: 色图 (不需要感叹号,tag也可以不用加,注意色图和tag间有个空格)
44 | 3.效果展示:
45 | ![image](https://github.com/user-attachments/assets/6952b2e1-c022-4ce0-9eaa-d1a1604cfe9c) 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hanschase/GiveMeSetuPlugin/811744a1a0e8d3cdbb3dd716a7047e18119a327f/__init__.py -------------------------------------------------------------------------------- /__pycache__/__init__.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hanschase/GiveMeSetuPlugin/811744a1a0e8d3cdbb3dd716a7047e18119a327f/__pycache__/__init__.cpython-311.pyc -------------------------------------------------------------------------------- /__pycache__/forward_message.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hanschase/GiveMeSetuPlugin/811744a1a0e8d3cdbb3dd716a7047e18119a327f/__pycache__/forward_message.cpython-311.pyc -------------------------------------------------------------------------------- /__pycache__/get_image.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hanschase/GiveMeSetuPlugin/811744a1a0e8d3cdbb3dd716a7047e18119a327f/__pycache__/get_image.cpython-311.pyc -------------------------------------------------------------------------------- /__pycache__/main.cpython-311.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hanschase/GiveMeSetuPlugin/811744a1a0e8d3cdbb3dd716a7047e18119a327f/__pycache__/main.cpython-311.pyc -------------------------------------------------------------------------------- /forward_message.py: -------------------------------------------------------------------------------- 1 | import json 2 | import aiohttp 3 | import os 4 | 5 | class forward_message(): 6 | def __init__(self, host:str, port: int): 7 | self.url = f"http://{host}:{port}" 8 | 9 | async def send(self, group_id:str, img_info:list): 10 | image = self.get_media_path(img_info[3]) 11 | message_data = { 12 | "group_id": group_id, 13 | "user_id": "1900487324", 14 | "messages": [ 15 | { 16 | "type": "node", 17 | "data": { 18 | "user_id": "3870128501", 19 | "nickname": "BOT", 20 | "content": [ 21 | { 22 | "type": "text", 23 | "data": { 24 | "text": f"pid:{img_info[0]}\ntitle:{img_info[1]}\nauthor:{img_info[2]}" 25 | } 26 | }, 27 | { 28 | "type": "image", 29 | "data": { 30 | "file": image, 31 | } 32 | } 33 | ] 34 | } 35 | } 36 | ], 37 | "news": [ 38 | { 39 | "text": f"pid:{img_info[0]}" 40 | } 41 | ], 42 | "prompt": "冲就完事儿了", 43 | "summary": "一天就知道冲冲冲", 44 | "source": img_info[1] 45 | } 46 | headers = { 47 | 'Content-Type': 'application/json' 48 | } 49 | payload = json.dumps(message_data) 50 | async with aiohttp.ClientSession(self.url, headers=headers) as session: 51 | async with session.post("/send_forward_msg", data=payload) as response: 52 | await response.json() 53 | print(response) 54 | 55 | def get_media_path(self, media_path): 56 | """ 57 | 获取媒体的本地绝对路径或网络路径 58 | """ 59 | if media_path: 60 | if media_path.startswith('http'): 61 | return media_path 62 | elif os.path.isfile(media_path): 63 | abspath = os.path.abspath(os.path.join(os.getcwd(), media_path)).replace('\\', '\\\\') 64 | return f"file:///{abspath}" 65 | return '' 66 | -------------------------------------------------------------------------------- /get_image.py: -------------------------------------------------------------------------------- 1 | import httpx 2 | import sys 3 | import asyncio 4 | import json 5 | import re 6 | 7 | async def get_json(keyword: str,r18_flag: int = 0): 8 | url = "https://api.lolicon.app/setu/v2" 9 | params = { 10 | "keyword": keyword, 11 | "num": 1, 12 | "r18": r18_flag, 13 | "size": "regular", 14 | } 15 | async with httpx.AsyncClient() as client: 16 | response = await client.get(url, params=params) 17 | return response 18 | 19 | async def download_image(url: str): 20 | async with httpx.AsyncClient() as client: 21 | response = await client.get(url) 22 | if response.status_code == 404: 23 | raise Exception(404) 24 | content = response.content 25 | import aiofiles 26 | async with aiofiles.open("temp.jpg", 'wb') as f: 27 | await f.write(content) 28 | 29 | async def get_image(keyword: str, r18_flag: int = 0): 30 | img = await get_json(keyword, r18_flag) 31 | img = img.json() 32 | if img["data"] == []: 33 | raise Exception("输入了未知的tag") 34 | pid = img["data"][0]["pid"] 35 | title = img["data"][0]["title"] 36 | author = img["data"][0]["author"] 37 | img_url = img["data"][0]["urls"]["regular"] 38 | try: 39 | await download_image(img_url) 40 | return [pid,title,author, img_url] 41 | except Exception as e: 42 | raise e 43 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from mirai import MessageChain 2 | from pkg.plugin.context import register, handler, llm_func, BasePlugin, APIHost, EventContext 3 | from pkg.plugin.events import * # 导入事件类 4 | from pkg.platform.types import * 5 | from plugins.GiveMeSetuPlugin.get_image import get_image 6 | import re 7 | from plugins.GiveMeSetuPlugin.forward_message import forward_message 8 | 9 | # 注册插件 10 | @register(name="GiveMeSetuPlugin", description="功能正如其名,让她给,她不得不给!", version="0.2", author="Hanschase") 11 | class MyPlugin(BasePlugin): 12 | 13 | # 插件加载时触发 14 | def __init__(self, host: APIHost): 15 | self.forward_message = forward_message(host="127.0.0.1", port=3000) 16 | 17 | 18 | # 异步初始化 19 | async def initialize(self): 20 | pass 21 | 22 | @handler(PersonMessageReceived) 23 | @handler(GroupMessageReceived) 24 | async def message_received(self, ctx: EventContext): 25 | msg = str(ctx.event.message_chain).strip() 26 | #msg = ctx.event.text_message.strip() 27 | if re.search(r'setu|涩图|色图', msg, re.IGNORECASE): 28 | ctx.prevent_default() 29 | msg = msg.split(" ") 30 | if len(msg)==1 or len(msg)>2: 31 | keyword = "" 32 | else: 33 | keyword = msg[1] 34 | r18_flag = 1 if 'r' in msg[0].lower() else 0 35 | self.ap.logger.info(f"接收到关键词{keyword}") 36 | loop_flag = 3# 重定向次数 37 | while loop_flag: 38 | try: 39 | img_info = await get_image(keyword, r18_flag) 40 | self.ap.logger.info(f"Image info:{img_info}") 41 | loop_flag = 0 42 | except Exception as e: 43 | print(str(e)) 44 | if str(e) == "404": 45 | self.ap.logger.error("未查询到图片,正在进行重定向") 46 | loop_flag -= 1 47 | else: 48 | await ctx.send_message(ctx.event.launcher_type, str(ctx.event.launcher_id),MessageChain([f"发生了一个错误:{e}"])) 49 | self.ap.logger.error(e) 50 | return 51 | self.ap.logger.info(f"正在发送图片...") 52 | #await ctx.send_message(ctx.event.launcher_type, str(ctx.event.launcher_id),MessageChain(["已获取图片,正在发送...(没发送出来就是被风控了)"])) 53 | # await ctx.send_message(ctx.event.launcher_type, str(ctx.event.launcher_id), MessageChain([f"pid:{img_info[0]}\n", 54 | # f"title:{img_info[1]}\n", 55 | # f"author:{img_info[2]}\n", 56 | # Image(path="temp.png")])) 57 | await self.forward_message.send(str(ctx.event.launcher_id), img_info) 58 | 59 | # 插件卸载时触发 60 | def __del__(self): 61 | pass 62 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hanschase/GiveMeSetuPlugin/811744a1a0e8d3cdbb3dd716a7047e18119a327f/requirements.txt -------------------------------------------------------------------------------- /temp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hanschase/GiveMeSetuPlugin/811744a1a0e8d3cdbb3dd716a7047e18119a327f/temp.png --------------------------------------------------------------------------------