├── .github └── workflows │ └── python-publish.yml ├── LICENSE ├── README.md ├── image ├── image.png └── image2.png ├── nonebot_plugin_dog ├── __init__.py ├── check.py ├── handle.py ├── update.py └── utils.py ├── pyproject.toml └── setup.py /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Build and Upload 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v3 25 | - name: Set up Python 26 | uses: actions/setup-python@v3 27 | with: 28 | python-version: '3.x' 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install build 33 | - name: Build package 34 | run: python -m build 35 | - name: Publish package 36 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 37 | with: 38 | user: __token__ 39 | password: ${{ secrets.PYPI_API_TOKEN }} 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Reversedeer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | NoneBot 4 | 5 |

6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | # nonebot-plugin-dog 14 | 15 | _✨随机返回一句舔狗日记...(~~舔狗,舔到最后一无所有~~)✨_ 16 | 17 |
18 | 19 |

20 | 21 | license 22 | 23 | 24 | python 25 | 26 | 27 | 28 | 29 |

30 | 31 | ## 介绍: 点点Star✨ 32 | 33 | > 在群聊里发送“舔狗日记/一言”(等)命令时,bot返回一句舔狗日记/一言等文案 34 | > 35 | > 你可能需要在env里配置指令响应头 " / ",取决于你的command_start设置 36 | > 37 | > SUPERUSER | 群主 | 管理 可以使用:“开启/关闭文案”来控制指令开关(默认=true) 38 | > 39 | > 插件所有配置文件和备份目录在/date/dog/下 40 | > 41 | > ⚠️插件支持手动检查更新:Command: "/检查更新",如果没有报错,发送: "/重启"完成bot更新,可不使用pip install --upgrade 更新 42 | 43 | ## 安装方式 44 | 45 | ### nb-cli(推荐) 46 | 47 | ``` 48 | nb plugin install nonebot_plugin_dog 49 | ``` 50 | 51 |
52 |

pip

53 | 54 | ``` 55 | pip install nonebot_plugin_dog 56 | ``` 57 | 58 |
59 | 60 | ### 更新 61 | 62 | ``` 63 | pip install --upgrade nonebot-plugin-dog 64 | ``` 65 | 66 | #### 还可以在群内发送指令:"/检查更新"来检查更新; 发送 "/重启"完成bot更新(推荐) 67 | 68 | ## 配置 69 | 70 | 在bot目录对应的.env.*文件中添加(有默认值,cd=0为不限制) 71 | 72 | | config | type | default | example | usage | 73 | | :---------: | :--: | :-----: | :------------: | :------------------------: | 74 | | dog_cd | int | 20 | dog_cd = 20 | 调用''舔狗日记'cd默认值 | 75 | | laugh_cd | int | 20 | laugh_cd=20 | 调用''讲个笑话''cd的默认值 | 76 | | hitokoto_cd | int | 20 | hitokoto_cd=20 | 调用"一言"cd的默认值 | 77 | | wenan_cd | int | 20 | wenan_cd=20 | 调用“文案”cd的默认值 | 78 | 79 | ## 示例 80 | 81 | 82 | 83 | 84 | 85 | ## TODO 86 | 87 | - [x] 增加指令开关 88 | - [x] 增加插件热更新 89 | - [x] 增加CD限制 90 | - [ ] 增加图片发送 91 | - [x] 整合更多的API 92 | 93 |
94 |

更新日志

95 | 96 | - 0.3.0 97 | 98 | - 适配插件元数据 99 | 100 | - 优化代码 101 | 102 | - 0.2.9 103 | - 修复热更新bug 104 | 105 | - 0.2.8 106 | - 实现插件热更新 107 | 108 | - 0.2.7.1 109 | - 增加"舔狗日记"api 110 | 111 | - 插件支持手动检测更新 112 | - 0.2.7 # 2023-3-13 113 | - 修复api 114 | - 0.2.6 #2023-3-5 115 | - 修复了文案中存在换行符,且无法换行的错误 116 | 117 | - 优化cd逻辑,可以分别对应每一个指令 118 | 119 | - 整合了更多的api 120 | - 0.2.5 #2023-3-3 121 | - 整合了更多的api 122 | - 优化cd模式 123 | - 0.2.3 #2023-2-1 124 | - 修复文本末多出的空行 125 | - 修复readme中的错误 126 | - 增加指令开关 127 | - 更改指令CD默认值为20 128 | - 0.1.9 #2023-1-30 129 | - 增加cd限制 130 | - 0.1.0 #2023-1-29 131 | - 发布并优化代码 132 | 133 |
134 | 135 | ## 关于 ISSUE 136 | 137 | 以下 ISSUE 会被直接关闭 138 | 139 | - 提交 BUG 不使用 Template 140 | - 询问已知问题 141 | - 提问找不到重点 142 | - 重复提问 143 | 144 | > 请注意, 开发者并没有义务回复您的问题. 您应该具备基本的提问技巧。 145 | > 有关如何提问,请阅读[《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md) 146 | 147 | 148 | 149 | ## 其他插件 150 | 151 | [QQ群消息,事件检测插件](https://github.com/Reversedeer/nonebot_plugin_eventmonitor) -------------------------------------------------------------------------------- /image/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reversedeer/nonebot_plugin_dog/9d638dd68c20e06e51cf11419a284b471613a3b1/image/image.png -------------------------------------------------------------------------------- /image/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reversedeer/nonebot_plugin_dog/9d638dd68c20e06e51cf11419a284b471613a3b1/image/image2.png -------------------------------------------------------------------------------- /nonebot_plugin_dog/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 插件入口''' 2 | import os 3 | import platform 4 | 5 | 6 | from nonebot.params import ArgStr 7 | from nonebot.matcher import Matcher 8 | from nonebot.permission import SUPERUSER 9 | from nonebot import on_command, on_endswith 10 | from nonebot.plugin import PluginMetadata 11 | from nonebot.adapters.onebot.v11.permission import GROUP_OWNER, GROUP_ADMIN 12 | 13 | from .utils import utils 14 | from .handle import dog 15 | 16 | on_endswith( 17 | "文案", 18 | permission=SUPERUSER | GROUP_ADMIN | GROUP_OWNER, 19 | priority=10, 20 | block=True, 21 | handlers=[dog.openstates] 22 | ) 23 | on_command( 24 | "舔狗日记", 25 | aliases={"舔狗嘤嘤嘤"}, 26 | priority=10, 27 | block=True, 28 | handlers=[dog.lickdog] 29 | ) 30 | on_command( 31 | "讲个笑话", 32 | aliases={"说个笑话"}, 33 | priority=10, 34 | block=True, 35 | handlers=[dog.laugh] 36 | ) 37 | on_command( 38 | "一言",aliases={"一言"}, 39 | priority=10, 40 | block=True, 41 | handlers=[dog.hitokoto] 42 | ) 43 | on_command( 44 | "文案语录", 45 | aliases={"语录"}, 46 | priority=10, 47 | block=True, 48 | handlers=[dog.wenan] 49 | ) 50 | on_command( 51 | "检查更新", 52 | priority=1, 53 | permission=SUPERUSER, 54 | block=True, 55 | handlers=[dog.check] 56 | ) 57 | restart = on_command( 58 | "重启", 59 | aliases={"restart"}, 60 | priority=1, 61 | permission=SUPERUSER, 62 | block=True 63 | ) 64 | 65 | @restart.got("flag", prompt="确定是否重启?确定请回复[是|好|确定](重启失败咱们将失去联系,请谨慎!)") 66 | async def _(matcher: Matcher, flag: str = ArgStr("flag")): 67 | if flag.lower() in {"true", "是", "好", "确定", "确定是"}: 68 | await matcher.send("开始重启..请稍等...") 69 | open("data/dog/new_version", "w") 70 | if str(platform.system()).lower() == "windows": 71 | import sys 72 | 73 | python = sys.executable 74 | os.execl(python, python, *sys.argv) 75 | else: 76 | os.system("./restart.sh") 77 | else: 78 | await matcher.send("已取消操作...") 79 | 80 | __plugin_meta__ = PluginMetadata( 81 | name="dog", 82 | description="随机返回一句舔狗日记...嘤嘤嘤和其他文案的插件", 83 | usage=utils.usage, 84 | type="application", 85 | homepage="https://github.com/Reversedeer/nonebot_plugin_dog", 86 | supported_adapters={"~onebot.v11"}, 87 | extra={ 88 | "author": "Reversedeer", 89 | "version": "0.3.0", 90 | "priority": 10, 91 | } 92 | ) -------------------------------------------------------------------------------- /nonebot_plugin_dog/check.py: -------------------------------------------------------------------------------- 1 | import os 2 | import httpx 3 | import shutil 4 | import tarfile 5 | 6 | from pathlib import Path 7 | from nonebot.log import logger 8 | from nonebot.adapters.onebot.v11 import Bot, Message 9 | 10 | from .update import config 11 | from .utils import utils 12 | 13 | 14 | async def fetch_data(tar_gz_url): 15 | async with httpx.AsyncClient() as client: 16 | return await client.get(tar_gz_url) 17 | 18 | async def download_file(tar_gz_url, latest_tar_gz): 19 | async with httpx.AsyncClient() as client: 20 | response = await client.get(tar_gz_url) 21 | if response.status_code == 200: 22 | with open(latest_tar_gz, "wb") as f: 23 | f.write(response.content) 24 | return True 25 | else: 26 | return False 27 | 28 | 29 | 30 | async def check_update(bot: Bot): 31 | global latest_version 32 | logger.info("开始更新插件...") 33 | data = await config.get_latest_version_data() 34 | if data: 35 | latest_version = data["name"] 36 | if utils.current_version != latest_version: 37 | tar_gz_url = data["tarball_url"] 38 | logger.info(f"检测插件dog:有更新,当前版本:{utils.current_version},最新版本:{latest_version}") 39 | await bot.send_private_msg( 40 | user_id=int(list(bot.config.superusers)[0]), 41 | message=f"检测插件:dog有更新,当前版本:{utils.current_version},最新版本:{latest_version}\n" f"开始更新.....", 42 | ) 43 | tar_gz_url = (await fetch_data(tar_gz_url)).headers.get("Location") 44 | if await download_file(tar_gz_url, config.latest_tar_gz): 45 | logger.info("下载插件最新版文件完成....") 46 | error = await _file_handle(latest_version) 47 | if error: 48 | return 998, error 49 | logger.info("更新完毕,清理文件完成....") 50 | await bot.send_private_msg( 51 | user_id=int(list(bot.config.superusers)[0]), 52 | message=Message( 53 | f"插件更新完成,版本:{utils.current_version} -> {latest_version}\n" 54 | f"插件更新日期:{data['created_at']}\n" 55 | ), 56 | ) 57 | return 200, "" 58 | else: 59 | logger.warning(f"下载最新版本失败..请检查网络是否通畅.版本号:{latest_version}") 60 | await bot.send_private_msg( 61 | user_id=int(list(bot.config.superusers)[0]), 62 | message=f"下载最新版本失败qwq..请检查网络是否通畅.版本号:{latest_version}", 63 | ) 64 | else: 65 | logger.info(f"自动获取版本成功:{latest_version},当前版本为最新版,无需更新...") 66 | await bot.send_private_msg( 67 | user_id=int(list(bot.config.superusers)[0]), 68 | message=f"自动获取版本成功:{latest_version},当前版本为最新版,无需更新...", 69 | ) 70 | else: 71 | logger.warning("自动获取版本失败....") 72 | await bot.send_private_msg( 73 | user_id=int(list(bot.config.superusers)[0]), message="自动获取版本失败...." 74 | ) 75 | return 999, "" 76 | 77 | 78 | async def _file_handle(latest_version: str) -> str: 79 | # 接收最新版本号作为参数,并返回处理结果字符串 80 | 81 | if not config.temp_dir.exists(): 82 | # 检查临时目录是否存在,如果不存在则创建 83 | config.temp_dir.mkdir(exist_ok=True, parents=True) 84 | 85 | if config.backup_dir.exists(): 86 | # 如果备份目录存在,则删除整个备份目录 87 | shutil.rmtree(config.backup_dir) 88 | 89 | tf = None 90 | # 初始化一个tarfile对象tf 91 | 92 | config.backup_dir.mkdir(exist_ok=True, parents=True) 93 | # 创建备份目录,如果备份目录已存在,则不会重新创建 94 | 95 | logger.info("开始解压文件压缩包....") 96 | # 记录日志,表示开始解压文件压缩包 97 | tf = tarfile.open(config.latest_tar_gz) 98 | # 打开文件压缩包,获取tarfile对象tf 99 | tf.extractall(config.temp_dir) 100 | # 将压缩包中的所有文件解压到临时目录temp_dir中 101 | logger.info("解压文件压缩包完成....") 102 | # 记录日志,表示解压文件压缩包完成 103 | 104 | latest_file = Path(config.temp_dir) / os.listdir(config.temp_dir)[0] 105 | # 获取临时目录中的第一个文件,作为最新版本的文件夹路径 106 | update_info_file = Path(latest_file) / os.listdir(latest_file)[1] 107 | # 获取最新版本文件夹中的第二个文件,作为更新信息文件的路径 108 | try: 109 | 110 | pycache_dir = os.path.join(config.destination_directory, '__pycache__') 111 | if os.path.exists(pycache_dir): 112 | shutil.rmtree(pycache_dir) 113 | 114 | for file in os.listdir(config.destination_directory): 115 | if file != '__pycache__': 116 | logger.info("正在备份插件目录...") 117 | temp_file = os.path.join(config.destination_directory, file) 118 | backup_file = os.path.join(config.backup_dir, file) 119 | shutil.copy2(temp_file, backup_file) 120 | logger.info("文件备份成功") 121 | 122 | 123 | for file in os.listdir(update_info_file): 124 | logger.info("开始更新插件...") 125 | updata_file = os.path.join(update_info_file, file) 126 | destination_file = os.path.join(config.destination_directory, file) 127 | shutil.copy2(updata_file, destination_file) 128 | logger.info("插件更新成功!") 129 | except Exception as e: 130 | raise e 131 | 132 | if tf: 133 | tf.close() 134 | # 关闭tarfile对象,释放资源 135 | if config.temp_dir.exists(): 136 | shutil.rmtree(config.temp_dir) 137 | # 删除临时目录及其中的所有文件 138 | if config.latest_tar_gz.exists(): 139 | config.latest_tar_gz.unlink() 140 | # 删除最新版本的压缩包文件 141 | 142 | with open(config.version_file, "w", encoding="utf-8") as f: 143 | f.write(f"{latest_version}") 144 | # 将最新版本号写入版本文件中 145 | 146 | os.system(f"poetry run pip install -r {(update_info_file / 'pyproject.toml').absolute()}") 147 | # 使用os.system命令执行shell命令,安装更新后的依赖包 148 | 149 | return "" 150 | # 返回一个空字符串 151 | 152 | -------------------------------------------------------------------------------- /nonebot_plugin_dog/handle.py: -------------------------------------------------------------------------------- 1 | import re 2 | import httpx 3 | import random 4 | import nonebot 5 | 6 | from nonebot.log import logger 7 | from nonebot.matcher import Matcher 8 | from nonebot.adapters.onebot.v11 import MessageEvent, MessageSegment, GroupMessageEvent, Bot 9 | 10 | from .check import check_update 11 | from .utils import utils, check_group_allow, write_group_data, groupdata 12 | 13 | class Dog: 14 | @staticmethod 15 | async def lickdog(matcher: Matcher, event: GroupMessageEvent): # 定义异步函数 dog 16 | if not (await check_group_allow(str(event.group_id))): 17 | await matcher.finish(utils.notAllow, at_sender=True) 18 | uid = event.get_user_id() # 获取用户id 19 | try: 20 | cd = event.time - utils.dog_CD_dir[uid] # 计算cd 21 | except KeyError: 22 | cd = utils.dog_cd + 1 # 没有记录则cd为cd_time+1 23 | if ( 24 | cd > utils.dog_cd 25 | or event.get_user_id() in nonebot.get_driver().config.superusers 26 | ): # 记录cd 27 | utils.dog_CD_dir.update({uid: event.time}) 28 | urls = ["https://api.mxycn.cn/api/tgrj.php", "https://api.oick.cn/dog/api.php"] 29 | url = random.choice(urls) 30 | try: 31 | # 使用 httpx.AsyncClient 获取 API,存储为 response 变量 32 | async with httpx.AsyncClient() as client: 33 | response = await client.get(url) 34 | response_text = response.text 35 | except Exception as error: 36 | await matcher.finish(MessageSegment.text(str(error))) 37 | await matcher.finish(MessageSegment.text(response_text.strip()), block=True) 38 | else: 39 | await matcher.finish( 40 | MessageSegment.text(f"不要深情了喵,休息{utils.dog_cd - cd:.0f}秒后再找我喵~"), 41 | at_sender=True, block=True) 42 | 43 | @staticmethod 44 | async def laugh(event: GroupMessageEvent, matcher: Matcher): # 定义异步函数 laugh 45 | if not (await check_group_allow(str(event.group_id))): 46 | await matcher.finish(utils.notAllow, at_sender=True) 47 | uid = event.get_user_id() # 获取用户id 48 | try: 49 | cd = event.time - utils.laugh_CD_dir[uid] # 计算cd 50 | except KeyError: 51 | cd = utils.laugh_cd + 1 # 没有记录则cd为cd_time+1 52 | if ( 53 | cd > utils.laugh_cd 54 | or event.get_user_id() in nonebot.get_driver().config.superusers 55 | ): # 记录cd 56 | utils.laugh_CD_dir.update({uid: event.time}) 57 | try: 58 | # 使用 httpx.AsyncClient 获取 API,存储为 response 变量 59 | async with httpx.AsyncClient() as client: 60 | response = await client.get("https://api.mxycn.cn/api/qwxh.php") 61 | response_text = response.text 62 | except Exception as error: 63 | await matcher.finish(MessageSegment.text(str(error))) 64 | response_text = re.sub(r'。。\\n', '\n', response_text) 65 | response_text = response_text.replace('。。', '') 66 | await matcher.finish(MessageSegment.text(response_text.strip()), block=True) 67 | else: 68 | await matcher.finish( 69 | MessageSegment.text(f"我在准备更精彩的笑话喵,等待{utils.laugh_cd - cd:.0f}秒后再找我喵~"), 70 | at_sender=True, block=True) 71 | 72 | 73 | @staticmethod 74 | async def hitokoto(event: GroupMessageEvent, matcher: Matcher): # 定义异步函数hitokoto 75 | if not (await check_group_allow(str(event.group_id))): 76 | await matcher.finish(utils.notAllow, at_sender=True) 77 | uid = event.get_user_id() # 获取用户id 78 | try: 79 | cd = event.time - utils.hitokoto_CD_dir[uid] # 计算cd 80 | except KeyError: 81 | # 没有记录则cd为cd_time+1 82 | cd = utils.hitokoto_cd + 1 83 | if ( 84 | cd > utils.hitokoto_cd 85 | or event.get_user_id() in nonebot.get_driver().config.superusers 86 | ): # 记录cd 87 | utils.hitokoto_CD_dir.update({uid: event.time}) 88 | try: 89 | async with httpx.AsyncClient() as client: 90 | response = await client.get("https://v1.hitokoto.cn?c=a&c=b&c=c&c=d&c=e&c=f&c=j") 91 | except Exception as error: 92 | await matcher.finish( 93 | MessageSegment.text("获取一言失败"), at_sender=True, block=True 94 | ) 95 | data = response.json() 96 | msg = data["hitokoto"] 97 | add = "" 98 | if works := data["from"]: 99 | add += f"《{works}》" 100 | if from_who := data["from_who"]: 101 | add += f"{from_who}" 102 | if add: 103 | msg += f"\n——{add}" 104 | await matcher.finish(msg) 105 | else: 106 | await matcher.finish( 107 | MessageSegment.text(f"休息 {utils.hitokoto_cd - cd:.0f}秒后才能再使用喵~"), 108 | at_sender=True, block=True) 109 | 110 | 111 | @staticmethod 112 | async def wenan(event: GroupMessageEvent, matcher: Matcher): # 定义异步函数wenan 113 | if not (await check_group_allow(str(event.group_id))): 114 | await matcher.finish(utils.notAllow, at_sender=True) 115 | uid = event.get_user_id() # 获取用户id 116 | try: 117 | cd = event.time - utils.wenan_CD_dir[uid] # 计算cd 118 | except KeyError: 119 | cd = utils.wenan_cd + 1 # 没有记录则cd为cd_time+1 120 | if ( 121 | cd > utils.wenan_cd 122 | or event.get_user_id() in nonebot.get_driver().config.superusers 123 | ): # 记录cd 124 | utils.wenan_CD_dir.update({uid: event.time}) 125 | try: 126 | # 使用 httpx.AsyncClient 获取 API,存储为 response 变量 127 | async with httpx.AsyncClient() as client: 128 | response = await client.get("https://api.mxycn.cn/api/sgyl.php") 129 | response_text = response.text 130 | except Exception as error: 131 | await matcher.finish(MessageSegment.text(str(error))) 132 | await matcher.finish(MessageSegment.text(response_text.strip()), block=True) 133 | else: 134 | await matcher.finish( 135 | MessageSegment.text(f"文案准备中喵,等待{utils.wenan_cd - cd:.0f}秒后再找我喵~"), 136 | at_sender=True, block=True) 137 | 138 | @staticmethod 139 | async def openstates(event: GroupMessageEvent, matcher: Matcher): 140 | gid = str(event.group_id) # 群号 141 | # 获取用户输入的参数 142 | command = event.message.extract_plain_text().replace("文案", "") 143 | if command == "开启": 144 | if gid in groupdata: 145 | groupdata[gid]["allow"] = True 146 | else: 147 | groupdata.update({gid: {"allow": True}}) 148 | write_group_data() 149 | await matcher.finish("功能已开启喵~") 150 | elif "关闭" in command: 151 | if gid in groupdata: 152 | groupdata[gid]["allow"] = False 153 | else: 154 | groupdata.update({gid: {"allow": False}}) 155 | write_group_data() 156 | await matcher.finish("功能已禁用喵~") 157 | else: 158 | return 159 | 160 | @staticmethod 161 | async def check(bot: Bot, event: MessageEvent): 162 | try: 163 | code, error = await check_update(bot) 164 | if error: 165 | logger.error(f"错误: {error}", "插件检查更新") 166 | await bot.send_private_msg( 167 | user_id=event.user_id, message=f"更新插件dog更新时发生未知错误 {error}" 168 | ) 169 | except Exception as e: 170 | logger.error("更新插件dog时发生未知错误", "检查更新", e=e) 171 | await bot.send_private_msg( 172 | user_id=event.user_id, 173 | message=f"更新插件dog时发生未知错误 {type(e)}: {e}", 174 | ) 175 | else: 176 | if code == 200: 177 | await bot.send_private_msg(user_id=event.user_id, message="更新完毕,请重启bot....") 178 | 179 | dog = Dog() -------------------------------------------------------------------------------- /nonebot_plugin_dog/update.py: -------------------------------------------------------------------------------- 1 | import os 2 | import httpx 3 | import nonebot 4 | import platform 5 | 6 | from pathlib import Path 7 | from nonebot.log import logger 8 | from nonebot.adapters.onebot.v11 import Bot 9 | 10 | 11 | class Config: 12 | 13 | release_url = "https://api.github.com/repos/Reversedeer/nonebot_plugin_dog/releases/latest" 14 | config_path = Path() / "data/dog" 15 | latest_tar_gz = config_path / "latest_file.tar.gz" 16 | temp_dir = config_path / "temp" 17 | backup_dir = config_path / "backup" 18 | version_file = config_path / "new_version" 19 | destination_directory = 'src/plugins/nonebot_plugin_dog' # 目标文件夹 20 | driver = nonebot.get_driver() 21 | 22 | @staticmethod 23 | @driver.on_bot_connect 24 | async def remind(bot: Bot): 25 | system = platform.system() 26 | if system != 'windows': 27 | restart = config.config_path / "restart.sh" 28 | if not restart.exists(): 29 | with open(restart, "w", encoding="utf8") as f: 30 | f.write( 31 | ( 32 | f"pid=$(netstat -tunlp | grep {str(bot.config.port)}" 33 | + " | awk '{print $7}')\n" 34 | "pid=${pid%/*}\n" 35 | "kill -9 $pid\n" 36 | "sleep 3\n" 37 | "nb run" 38 | ) 39 | ) 40 | os.system("chmod +x ./restart.sh") 41 | logger.info("已自动生成 restart.sh(重启) 文件,请检查脚本是否与本地指令符合...") 42 | Version = config.version_file 43 | if Version.exists(): 44 | await bot.send_private_msg( 45 | user_id=int(list(bot.config.superusers)[0]), 46 | message="插件更新成功" 47 | ) 48 | Version.unlink() 49 | 50 | @staticmethod 51 | async def get_latest_version_data() -> dict: 52 | for _ in range(3): 53 | try: 54 | async with httpx.AsyncClient() as client: 55 | res = await client.get(config.release_url) 56 | if res.status_code == 200: 57 | return res.json() 58 | except TimeoutError: 59 | pass 60 | except Exception as e: 61 | logger.error("检查最新版本失败") 62 | return {} 63 | 64 | config = Config() -------------------------------------------------------------------------------- /nonebot_plugin_dog/utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import nonebot 4 | 5 | class Utils: 6 | def __init__(self) -> None: 7 | 8 | self.usage = """ 9 | 指令1:/舔狗日记 10 | 指令2:/讲个笑话 11 | 指令3:/一言 12 | 指令4:/文案语录 13 | 指令5:/检查更新 14 | 指令6:/重启 15 | 指令7:/开启|关闭文案 16 | """ 17 | self.dog_CD_dir = {} # 记录舔狗日记cd的字典 18 | self.laugh_CD_dir = {} # 记录讲个笑话cd的字典 19 | self.hitokoto_CD_dir = {} # 记录一言cd的字典 20 | self.wenan_CD_dir = {} # 记录文案cd的字典 21 | self.current_version = '0.3.0' 22 | config = nonebot.get_driver().config # 获取配置 23 | self.dog_cd: int = getattr(config, "dog_cd", 20) 24 | self.laugh_cd: int = getattr(config, "laugh_cd", 20) 25 | self.hitokoto_cd: int = getattr(config, "hitokoto_cd", 20) 26 | self.wenan_cd: int = getattr(config, "wenan_cd", 20) 27 | self.notAllow = "群内还未开启文案功能, 请管理员或群主发送\"开启文案\", \"关闭文案\"以开启/关闭该功能" 28 | 29 | utils = Utils() 30 | 31 | if os.path.exists("data/dog/groupdata.json"): # 读取用户数据 32 | with open("data/dog/groupdata.json", "r", encoding="utf-8") as f: 33 | groupdata = json.load(f) 34 | else: # 不存在则创建 35 | if not os.path.exists("data/dog"): 36 | os.makedirs("data/dog") # 创建文件夹 37 | groupdata = {} 38 | 39 | async def check_group_allow(gid: str) -> bool: 40 | #检查群是否允许 41 | if gid not in groupdata: 42 | groupdata[gid] = {"allow": True}# 写入默认值为true 43 | return groupdata[gid]["allow"] 44 | 45 | 46 | def write_group_data() -> None: 47 | #写入群配置 48 | with open("data/dog/groupdata.json", "w", encoding="utf-8") as f: 49 | json.dump(groupdata, f, indent=4) 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "nonebot-plugin-dog" 3 | version = "0.3.01" 4 | description = "随机返回一句舔狗日记...嘤嘤嘤" 5 | license = "MIT" 6 | authors = ["Reversedeer"] 7 | readme = "README.md" 8 | homepage = "https://github.com/Reversedeer/nonebot_plugin_dog" 9 | repository = "https://github.com/Reversedeer/nonebot_plugin_dog" 10 | 11 | 12 | [tool.poetry.dependencies] 13 | python = "^3.8" 14 | nonebot2 = ">=2.0.0rc2" 15 | httpx = "^0.23.1" 16 | poetry = "^1.5.0" 17 | nonebot-adapter-onebot = ">=2.1.3" 18 | 19 | [build-system] 20 | requires = ["poetry-core>=1.0.0"] 21 | build-backend = "poetry.core.masonry.api" -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open("README.md", "r", encoding="utf-8") as fh: 4 | long_description = fh.read() 5 | 6 | setuptools.setup( 7 | name="nonebot_plugin_dog", 8 | version="0.3.01", 9 | author="Reversedeer", 10 | description="Lick the dog diary! Lick the dog and lick to the last nothing.", 11 | long_description=long_description, 12 | long_description_content_type="text/markdown", 13 | url="https://github.com/Reversedeer/nonebot_plugin_dog", 14 | project_urls={ 15 | "Bug Tracker": "https://github.com/Reversedeer/nonebot_plugin_dog/issues", 16 | }, 17 | classifiers=[ 18 | "Programming Language :: Python :: 3", 19 | "License :: OSI Approved :: MIT License", 20 | "Operating System :: OS Independent", 21 | ], 22 | packages=setuptools.find_packages(), 23 | python_requires=">=3.8", 24 | install_requires = [ 25 | 'httpx>=0.23.1', 26 | 'nonebot2>=2.0.0rc2', 27 | 'poetry>=1.5.0', 28 | "nonebot-adapter-onebot>=2.1.3" 29 | ] 30 | ) --------------------------------------------------------------------------------