├── .github └── workflows │ └── pypi-publish.yml ├── .gitignore ├── LICENSE ├── README.md ├── nonebot_plugin_fishing ├── __init__.py ├── config.py ├── data_source.py ├── migrations │ ├── 1be1c9b715a9_add_achievements.py │ ├── 68463f3e5f33_.py │ ├── 7609e6d106dd_init_db.py │ ├── c5ab992c9af3_add_achievements.py │ ├── e9015df43907_add_special_fishes_field.py │ └── f70bdeaec7a4_add_specialfishes_table.py └── model.py ├── pdm.lock └── pyproject.toml /.github/workflows/pypi-publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | workflow_dispatch: 8 | 9 | jobs: 10 | pypi-publish: 11 | name: Upload release to PyPI 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@master 15 | - name: Set up Python 16 | uses: actions/setup-python@v1 17 | with: 18 | python-version: "3.x" 19 | - name: Install pypa/build 20 | run: >- 21 | python -m 22 | pip install 23 | build 24 | --user 25 | - name: Build a binary wheel and a source tarball 26 | run: >- 27 | python -m 28 | build 29 | --sdist 30 | --wheel 31 | --outdir dist/ 32 | . 33 | - name: Publish distribution to PyPI 34 | uses: pypa/gh-action-pypi-publish@release/v1 35 | with: 36 | password: ${{ secrets.PYPI_API_TOKEN }} 37 | -------------------------------------------------------------------------------- /.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 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 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 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration 104 | poetry.toml 105 | 106 | # pdm 107 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 108 | #pdm.lock 109 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 110 | # in version control. 111 | # https://pdm.fming.dev/#use-with-ide 112 | .pdm-python 113 | 114 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 115 | __pypackages__/ 116 | 117 | # Celery stuff 118 | celerybeat-schedule 119 | celerybeat.pid 120 | 121 | # SageMath parsed files 122 | *.sage.py 123 | 124 | # Environments 125 | .env 126 | .venv 127 | env/ 128 | venv/ 129 | ENV/ 130 | env.bak/ 131 | venv.bak/ 132 | 133 | # Spyder project settings 134 | .spyderproject 135 | .spyproject 136 | 137 | # Rope project settings 138 | .ropeproject 139 | 140 | # mkdocs documentation 141 | /site 142 | 143 | # mypy 144 | .mypy_cache/ 145 | .dmypy.json 146 | dmypy.json 147 | 148 | # Pyre type checker 149 | .pyre/ 150 | 151 | # pytype static type analyzer 152 | .pytype/ 153 | 154 | # Cython debug symbols 155 | cython_debug/ 156 | 157 | # ruff 158 | .ruff_cache/ 159 | 160 | # LSP config files 161 | pyrightconfig.json 162 | 163 | # PyCharm 164 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 165 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 166 | # and can be added to the global gitignore or merged into this file. For a more nuclear 167 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 168 | .idea/ 169 | 170 | # VisualStudioCode 171 | .vscode/* 172 | !.vscode/settings.json 173 | !.vscode/tasks.json 174 | !.vscode/launch.json 175 | !.vscode/extensions.json 176 | !.vscode/*.code-snippets 177 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 C14H22O 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 | NoneBotPluginLogo 3 |
4 |

NoneBotPluginText

5 |
6 | 7 |
8 | 9 | # nonebot-plugin-fishing 10 | 11 | _✨ 你甚至可以电子钓鱼 ✨_ 12 | 13 | 14 | license 15 | 16 | 17 | pypi 18 | 19 | python 20 | 21 |
22 | 23 | ## 💿 安装 24 | 25 |
26 | 使用 nb-cli 安装 27 | 在 nonebot2 项目的根目录下打开命令行, 输入以下指令即可安装 28 | 29 | nb plugin install nonebot-plugin-fishing 30 | 31 |
32 | 33 |
34 | 使用包管理器安装 35 | 在 nonebot2 项目的插件目录下, 打开命令行, 根据你使用的包管理器, 输入相应的安装命令 36 | 37 |
38 | pip 39 | 40 | pip install nonebot-plugin-fishing 41 |
42 |
43 | pdm 44 | 45 | pdm add nonebot-plugin-fishing 46 |
47 |
48 | poetry 49 | 50 | poetry add nonebot-plugin-fishing 51 |
52 |
53 | conda 54 | 55 | conda install nonebot-plugin-fishing 56 |
57 | 58 | 打开 nonebot2 项目根目录下的 `pyproject.toml` 文件, 在 `[tool.nonebot]` 部分追加写入 59 | 60 | plugins = ["nonebot_plugin_fishing"] 61 | 62 |
63 | 64 | 注意:安装过后,需在控制台输入 `nb orm upgrade` 指令以初始化数据库。 65 | 66 | ## ⚙️ 配置 67 | 68 | 在 nonebot2 项目的`.env`文件中添加下表中的必填配置 69 | 70 | | 配置项 | 必填 | 说明 | 71 | |:-----:|:----:|:----:| 72 | | fishes | 否 | 配置鱼塘内鱼们的名称、权重、等待时间和价格 | 73 | | fishing_limit | 否 | 填入每次钓鱼后,限制钓鱼的秒数 | 74 | | fishing_coin_name | 否 | 填入卖鱼获取的货币名称 | 75 | | special_fish_enabled | 否 | 是否启用赛博放生功能(默认为否) | 76 | | special_fish_price | 否 | 每放生一次所需的货币数量 | 77 | | special_fish_probability | 否 | 钓鱼时钓到用户放生的鱼的概率 | 78 | 79 | 其中 `fishes` 配置项说明如下: 80 | 81 | ```dotenv 82 | FISHES=' 83 | [ 84 | { 85 | "name": "小鱼", # 鱼的名称 86 | "frequency": 2, # 鱼上钩的时间 87 | "weight": 100, # 权重 88 | "price": 2 # 价格 89 | } 90 | ] 91 | ' 92 | ``` 93 | 94 | ## 🔨 更新 95 | 96 | 每一次更新后,需执行 `nb orm upgrade`。 97 | 98 | 由于此前版本数据库迁移存在问题,故插件无法对 [v0.2.1](https://pypi.org/project/nonebot-plugin-fishing/0.2.1/) 版本及以前的数据进行迁移。 99 | 100 | ## 🎉 使用 101 | 102 | ### 指令表 103 | | 指令 | 范围 | 说明 | 104 | |:-----:|:----:|:----:| 105 | | 钓鱼 | 所有 | 放下鱼竿 | 106 | | 统计信息 | 所有 | 查看钓鱼次数 | 107 | | 背包 | 所有 | 查看背包 | 108 | | 卖鱼 | 所有 | 卖鱼 | 109 | | 余额 | 所有 | 查看当前余额 | 110 | | 放生 | 所有 | 赛博放生 | 111 | 112 | ### 赛博放生 113 | 114 | 当用户使用货币放生由自己取名的一条鱼后,每个用户在钓鱼时都有机会钓到那一条鱼。但此功能开关 `special_fish_enabled` 默认关闭,原因是用户生成内容如果不符合规范,可能导致出现不可预料的情况,请谨慎开启。 115 | 116 | ## 🔨 更新 117 | 118 | 每一次升级后,都需执行 `nb orm upgrade`。 119 | 120 | ## 📝 Todo 121 | 122 | - [x] 重写数据库逻辑(改为使用 [nonebot/plugin-orm](https://github.com/nonebot/plugin-orm)) 123 | - [x] 增加系统商店,卖出钓到的鱼们 124 | - [ ] 赛博放生 [#4](https://github.com/C14H22O/nonebot-plugin-fishing/issues/4) (已基本完成) 125 | - [ ] 使用 [nonebot_plugin_chikari_economy](https://github.com/mrqx0195/nonebot_plugin_chikari_economy) 经济系统 126 | - [ ] 为鱼竿增加耐久度,耐久度为0时需重新购买鱼竿 127 | - [ ] 为钓鱼背包添加排序 128 | - [ ] 添加成就系统 129 | -------------------------------------------------------------------------------- /nonebot_plugin_fishing/__init__.py: -------------------------------------------------------------------------------- 1 | from nonebot import on_command, require 2 | 3 | require("nonebot_plugin_orm") # noqa 4 | 5 | from nonebot.plugin import PluginMetadata 6 | from nonebot.adapters import Event, Message 7 | from nonebot.params import CommandArg 8 | from nonebot.permission import SUPERUSER 9 | 10 | import asyncio 11 | 12 | from .config import Config, config 13 | from .data_source import ( 14 | choice, 15 | can_fishing, 16 | can_catch_special_fish, 17 | can_free_fish, 18 | get_stats, 19 | save_fish, 20 | save_special_fish, 21 | get_backpack, 22 | sell_fish, 23 | get_balance, 24 | free_fish, 25 | random_get_a_special_fish, 26 | lottery, 27 | give, 28 | check_achievement, 29 | get_achievements 30 | ) 31 | 32 | __plugin_meta__ = PluginMetadata( 33 | name="赛博钓鱼", 34 | description="你甚至可以电子钓鱼", 35 | usage="发送“钓鱼”,放下鱼竿。", 36 | type="application", 37 | homepage="https://github.com/ALittleBot/nonebot-plugin-fishing", 38 | config=Config, 39 | supported_adapters=None 40 | ) 41 | 42 | fishing = on_command("fishing", aliases={"钓鱼"}, priority=5) 43 | stats = on_command("stats", aliases={"统计信息", "钓鱼统计信息"}, priority=5) 44 | backpack = on_command("backpack", aliases={"背包", "钓鱼背包"}, priority=5) 45 | sell = on_command("sell", aliases={"卖鱼"}, priority=5) 46 | balance = on_command("balance", aliases={"余额", "钓鱼余额"}, priority=5) 47 | free_fish_cmd = on_command("free_fish", aliases={"放生", "钓鱼放生"}, priority=5) 48 | lottery_cmd = on_command("lottery", aliases={"祈愿"}, priority=5) 49 | achievement_cmd = on_command("achievement", aliases={"成就", "钓鱼成就"}, priority=5) 50 | give_cmd = on_command("give", permission=SUPERUSER, priority=5) 51 | 52 | 53 | @fishing.handle() 54 | async def _(event: Event): 55 | user_id = event.get_user_id() 56 | if not await can_fishing(user_id): 57 | await fishing.finish("河累了, 休息一下吧") 58 | await fishing.send("正在钓鱼…") 59 | if await can_catch_special_fish(): 60 | special_fish_name = await random_get_a_special_fish() 61 | result = f"你钓到了别人放生的 {special_fish_name}" 62 | await save_special_fish(user_id, special_fish_name) 63 | await fishing.finish(result) 64 | choice_result = choice() 65 | fish = choice_result[0] 66 | sleep_time = choice_result[1] 67 | result = f"钓到了一条{fish}, 你把它收进了背包里" 68 | await save_fish(user_id, fish) 69 | await asyncio.sleep(sleep_time) 70 | achievements = await check_achievement(user_id) 71 | if achievements is not None: 72 | for achievement in achievements: 73 | await fishing.send(achievement) 74 | await fishing.finish(result) 75 | 76 | 77 | @stats.handle() 78 | async def _(event: Event): 79 | user_id = event.get_user_id() 80 | await stats.finish(await get_stats(user_id)) 81 | 82 | 83 | @backpack.handle() 84 | async def _(event: Event): 85 | user_id = event.get_user_id() 86 | await backpack.finish(await get_backpack(user_id)) 87 | 88 | 89 | @sell.handle() 90 | async def _(event: Event, arg: Message = CommandArg()): 91 | fish_info = arg.extract_plain_text() 92 | if fish_info == "": 93 | await sell.finish("请输入要卖出的鱼的名字和数量 (数量为1时可省略), 如 /卖鱼 小鱼 1") 94 | user_id = event.get_user_id() 95 | if len(fish_info.split()) == 1: 96 | await sell.finish(await sell_fish(user_id, fish_info)) 97 | else: 98 | fish_name, fish_quantity = fish_info.split() 99 | await sell.finish(await sell_fish(user_id, fish_name, int(fish_quantity))) 100 | 101 | 102 | @balance.handle() 103 | async def _(event: Event): 104 | user_id = event.get_user_id() 105 | await balance.finish(await get_balance(user_id)) 106 | 107 | 108 | @free_fish_cmd.handle() 109 | async def _(event: Event, arg: Message = CommandArg()): 110 | if not can_free_fish(): 111 | await free_fish_cmd.finish("未开启此功能, 请联系机器人管理员") 112 | fish_name = arg.extract_plain_text() 113 | if fish_name == "": 114 | await free_fish_cmd.finish("请输入要放生的鱼的名字, 如 /放生 测试鱼") 115 | user_id = event.get_user_id() 116 | await free_fish_cmd.finish(await free_fish(user_id, fish_name)) 117 | 118 | 119 | @lottery_cmd.handle() 120 | async def _(event: Event): 121 | user_id = event.get_user_id() 122 | await lottery_cmd.finish(await lottery(user_id)) 123 | 124 | 125 | @give_cmd.handle() 126 | async def _(arg: Message = CommandArg()): 127 | info = arg.extract_plain_text().split() 128 | if len(info) < 2 or len(info) > 3: 129 | await give_cmd.finish("请输入用户的 id 和鱼的名字和数量 (数量为1时可省略), 如 /give 114514 开发鱼 1") 130 | else: 131 | quantity = int(info[2]) if len(info) == 3 else 1 132 | await give_cmd.finish(await give(info[0], info[1], quantity)) 133 | 134 | 135 | @achievement_cmd.handle() 136 | async def _(event: Event): 137 | user_id = event.get_user_id() 138 | await achievement_cmd.finish(await get_achievements(user_id)) 139 | -------------------------------------------------------------------------------- /nonebot_plugin_fishing/config.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | from typing import List, Dict 3 | from nonebot import get_plugin_config 4 | 5 | 6 | class Config(BaseModel): 7 | fishes: List[Dict] = [ 8 | { 9 | "name": "小鱼", 10 | "frequency": 2, 11 | "weight": 100, 12 | "price": 2 13 | }, 14 | { 15 | "name": "尚方宝剑", 16 | "frequency": 2, 17 | "weight": 100, 18 | "price": 1 19 | }, 20 | { 21 | "name": "小杂鱼~♡", 22 | "frequency": 3, 23 | "weight": 5, 24 | "price": 100 25 | }, 26 | { 27 | "name": "烤激光鱼", 28 | "frequency": 10, 29 | "weight": 1, 30 | "price": 1000 31 | } 32 | ] 33 | 34 | fishing_limit: int = 30 35 | 36 | fishing_coin_name: str = "FC" # It means Fishing Coin. 37 | 38 | special_fish_enabled: bool = False 39 | 40 | special_fish_price: int = 50 41 | 42 | special_fish_probability: float = 0.01 43 | 44 | fishing_achievement: List[Dict] = [ 45 | { 46 | "type": "fishing_frequency", 47 | "name": "腥味十足的生意", 48 | "data": 1, 49 | "description": "钓到一条鱼。" 50 | }, 51 | { 52 | "type": "fishing_frequency", 53 | "name": "还是钓鱼大佬", 54 | "data": 100, 55 | "description": "累计钓鱼一百次。" 56 | }, 57 | { 58 | "type": "fish_type", 59 | "name": "那是鱼吗?", 60 | "data": "小杂鱼~♡", 61 | "description": "获得#####。[原文如此]" 62 | }, 63 | { 64 | "type": "fish_type", 65 | "name": "那一晚, 激光鱼和便携式烤炉都喝醉了", 66 | "data": "烤激光鱼", 67 | "description": "获得烤激光鱼。" 68 | } 69 | ] 70 | 71 | 72 | config = get_plugin_config(Config) 73 | -------------------------------------------------------------------------------- /nonebot_plugin_fishing/data_source.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | import json 4 | 5 | from sqlalchemy import select, update, delete 6 | from sqlalchemy.sql.expression import func 7 | from nonebot_plugin_orm import get_session 8 | 9 | from .config import config 10 | from .model import FishingRecord, SpecialFishes 11 | 12 | fishing_coin_name = config.fishing_coin_name 13 | 14 | 15 | def choice() -> tuple: 16 | config_fishes = config.fishes 17 | weights = [weight["weight"] for weight in config_fishes] 18 | choices = random.choices( 19 | config_fishes, 20 | weights=weights, 21 | ) 22 | return choices[0]["name"], choices[0]["frequency"] 23 | 24 | 25 | def get_price(fish_name: str) -> int: 26 | """获取鱼的价格""" 27 | config_fishes = config.fishes 28 | return next( 29 | ( 30 | fish["price"] 31 | for fish in config_fishes 32 | if fish["name"] == fish_name 33 | ), 34 | 0 35 | ) 36 | 37 | 38 | async def random_get_a_special_fish() -> str: 39 | """随机返回一条别人放生的鱼""" 40 | session = get_session() 41 | async with session.begin(): 42 | random_select = select(SpecialFishes).order_by(func.random()) 43 | data = await session.scalar(random_select) 44 | return data.fish 45 | 46 | 47 | async def can_fishing(user_id: str) -> bool: 48 | """判断是否可以钓鱼""" 49 | time_now = int(time.time()) 50 | session = get_session() 51 | async with session.begin(): 52 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 53 | record = await session.scalar(select_user) 54 | return True if not record else record.time < time_now 55 | 56 | 57 | def can_free_fish() -> bool: 58 | return config.special_fish_enabled 59 | 60 | 61 | async def check_achievement(user_id: str) -> str | None: 62 | session = get_session() 63 | async with session.begin(): 64 | record = await session.scalar(select(FishingRecord).where(FishingRecord.user_id == user_id)) 65 | if not record: 66 | return None 67 | fishing_frequency = record.frequency 68 | user_fishes = json.loads(record.fishes) 69 | achievements = config.fishing_achievement 70 | result_list = [] 71 | for achievement in achievements: 72 | achievement_name = achievement["name"] 73 | if await is_exists_achievement(user_id, achievement_name): 74 | continue 75 | if (achievement["type"] == "fishing_frequency" and achievement["data"] <= fishing_frequency) or \ 76 | (achievement["type"] == "fish_type" and achievement["data"] in user_fishes): 77 | await save_achievement(user_id, achievement_name) 78 | result_list.append(f"""达成成就: {achievement_name}\n{achievement["description"]}""") 79 | return result_list if result_list != [] else None 80 | 81 | 82 | async def is_exists_achievement(user_id: str, achievement_name: str) -> bool: 83 | session = get_session() 84 | async with session.begin(): 85 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 86 | record = await session.scalar(select_user) 87 | if record: 88 | loads_achievements = json.loads(record.achievements) 89 | return achievement_name in loads_achievements 90 | return False 91 | 92 | 93 | async def save_achievement(user_id: str, achievement_name: str): 94 | time_now = int(time.time()) 95 | session = get_session() 96 | async with session.begin(): 97 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 98 | record = await session.scalar(select_user) 99 | if record: 100 | loads_achievements = json.loads(record.achievements) 101 | loads_achievements.append(achievement_name) 102 | dump_achievements = json.dumps(loads_achievements) 103 | user_update = update(FishingRecord).where( 104 | FishingRecord.user_id == user_id 105 | ).values( 106 | achievements=dump_achievements 107 | ) 108 | await session.execute(user_update) 109 | await session.commit() 110 | return 111 | data = [] 112 | dump_achievements = json.dumps(data) 113 | new_record = FishingRecord( 114 | user_id=user_id, 115 | time=time_now, 116 | frequency=0, 117 | fishes="{}", 118 | special_fishes="{}", 119 | coin=0, 120 | achievements=dump_achievements 121 | ) 122 | session.add(new_record) 123 | await session.commit() 124 | 125 | 126 | async def save_fish(user_id: str, fish_name: str) -> None: 127 | """向数据库写入鱼以持久化保存""" 128 | time_now = int(time.time()) 129 | fishing_limit = config.fishing_limit 130 | session = get_session() 131 | async with session.begin(): 132 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 133 | record = await session.scalar(select_user) 134 | if record: 135 | loads_fishes = json.loads(record.fishes) 136 | try: 137 | loads_fishes[fish_name] += 1 138 | except KeyError: 139 | loads_fishes[fish_name] = 1 140 | dump_fishes = json.dumps(loads_fishes) 141 | new_frequency = record.frequency + 1 142 | user_update = update(FishingRecord).where( 143 | FishingRecord.user_id == user_id 144 | ).values( 145 | time=time_now + fishing_limit, 146 | frequency=new_frequency, 147 | fishes=dump_fishes 148 | ) 149 | await session.execute(user_update) 150 | await session.commit() 151 | return 152 | data = { 153 | fish_name: 1 154 | } 155 | dump_fishes = json.dumps(data) 156 | new_record = FishingRecord( 157 | user_id=user_id, 158 | time=time_now + fishing_limit, 159 | frequency=1, 160 | fishes=dump_fishes, 161 | special_fishes="{}", 162 | coin=0, 163 | achievements="[]" 164 | ) 165 | session.add(new_record) 166 | await session.commit() 167 | 168 | 169 | async def can_catch_special_fish(): 170 | session = get_session() 171 | async with session.begin(): 172 | records = await session.execute(select(SpecialFishes)) 173 | return len(records.all()) != 0 and random.random() <= config.special_fish_probability 174 | 175 | 176 | async def save_special_fish(user_id: str, fish_name: str) -> None: 177 | time_now = int(time.time()) 178 | fishing_limit = config.fishing_limit 179 | session = get_session() 180 | async with session.begin(): 181 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 182 | record = await session.scalar(select_user) 183 | if record: 184 | loads_fishes = json.loads(record.special_fishes) 185 | try: 186 | loads_fishes[fish_name] += 1 187 | except KeyError: 188 | loads_fishes[fish_name] = 1 189 | dump_fishes = json.dumps(loads_fishes) 190 | user_update = update(FishingRecord).where( 191 | FishingRecord.user_id == user_id 192 | ).values( 193 | time=time_now + fishing_limit, 194 | frequency=record.frequency + 1, 195 | special_fishes=dump_fishes 196 | ) 197 | await session.execute(user_update) 198 | else: 199 | data = { 200 | fish_name: 1 201 | } 202 | dump_fishes = json.dumps(data) 203 | new_record = FishingRecord( 204 | user_id=user_id, 205 | time=time_now + fishing_limit, 206 | frequency=1, 207 | fishes="{}", 208 | special_fishes=dump_fishes, 209 | coin=0, 210 | achievements=[] 211 | ) 212 | session.add(new_record) 213 | select_fish = select(SpecialFishes).where( 214 | SpecialFishes.fish == fish_name 215 | ).order_by(SpecialFishes.id).limit(1) 216 | record = await session.scalar(select_fish) 217 | fish_id = record.id 218 | delete_fishes = delete(SpecialFishes).where(SpecialFishes.id == fish_id) 219 | await session.execute(delete_fishes) 220 | await session.commit() 221 | 222 | 223 | async def get_stats(user_id: str) -> str: 224 | """获取钓鱼统计信息""" 225 | session = get_session() 226 | async with session.begin(): 227 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 228 | fishing_record = await session.scalar(select_user) 229 | if fishing_record: 230 | return f"你钓鱼了 {fishing_record.frequency} 次" 231 | return "你还没有钓过鱼,快去钓鱼吧" 232 | 233 | 234 | def print_backpack(backpack: dict, special_backpack=None) -> str: 235 | """输出背包内容""" 236 | result = [ 237 | f"{fish_name}×{str(quantity)}" 238 | for fish_name, quantity in backpack.items() 239 | ] 240 | if special_backpack: 241 | special_result = [ 242 | f"{fish_name}×{str(quantity)}" 243 | for fish_name, quantity in special_backpack.items() 244 | ] 245 | return "背包:\n" + "\n".join(result) + "\n\n特殊鱼:\n" + "\n".join(special_result) 246 | return "背包:\n" + "\n".join(result) 247 | 248 | 249 | async def get_backpack(user_id: str) -> str: 250 | """从数据库查询背包内容""" 251 | session = get_session() 252 | async with session.begin(): 253 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 254 | fishes_record = await session.scalar(select_user) 255 | if fishes_record: 256 | load_fishes = json.loads(fishes_record.fishes) 257 | load_special_fishes = json.loads(fishes_record.special_fishes) 258 | if load_special_fishes: 259 | return print_backpack(load_fishes, load_special_fishes) 260 | return "你的背包里空无一物" if load_fishes == {} else print_backpack(load_fishes) 261 | return "你的背包里空无一物" 262 | 263 | 264 | async def sell_fish(user_id: str, fish_name: str, quantity: int = 1) -> str: 265 | """ 266 | 卖鱼 267 | 268 | 参数: 269 | - user_id: 用户标识符 270 | - fish_name: 将要卖鱼的鱼名称 271 | - quantity: 卖出鱼的数量 272 | 273 | 返回: 274 | - (str): 回复的文本 275 | """ 276 | if quantity <= 0: 277 | return "你在卖什么 w(゚Д゚)w" 278 | session = get_session() 279 | async with session.begin(): 280 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 281 | fishes_record = await session.scalar(select_user) 282 | if fishes_record := fishes_record: 283 | loads_fishes = json.loads(fishes_record.fishes) 284 | if fish_name in loads_fishes and loads_fishes[fish_name] > 0: 285 | fish_price = get_price(fish_name) 286 | if loads_fishes[fish_name] < quantity: 287 | return f"{fish_name} 太少了!" 288 | loads_fishes[fish_name] -= quantity 289 | if loads_fishes[fish_name] == 0: 290 | del loads_fishes[fish_name] 291 | dump_fishes = json.dumps(loads_fishes) 292 | user_update = update(FishingRecord).where( 293 | FishingRecord.user_id == user_id 294 | ).values( 295 | coin=fishes_record.coin + fish_price * quantity, 296 | fishes=dump_fishes 297 | ) 298 | await session.execute(user_update) 299 | await session.commit() 300 | return (f"你以 {fish_price} {fishing_coin_name} / 条的价格卖出了 {quantity} 条 {fish_name}, " 301 | f"你获得了 {fish_price * quantity} {fishing_coin_name}") 302 | return "查无此鱼" 303 | else: 304 | return "还没钓鱼就想卖鱼?" 305 | 306 | 307 | async def get_balance(user_id: str) -> str: 308 | """获取余额""" 309 | session = get_session() 310 | async with session.begin(): 311 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 312 | fishes_record = await session.scalar(select_user) 313 | if fishes_record: 314 | return f"你有 {fishes_record.coin} {fishing_coin_name}" 315 | return "你什么也没有 :)" 316 | 317 | 318 | async def free_fish(user_id: str, fish_name: str) -> str: 319 | session = get_session() 320 | async with session.begin(): 321 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 322 | fishes_record = await session.scalar(select_user) 323 | if fishes_record: 324 | user_coin = fishes_record.coin 325 | if user_coin < config.special_fish_price: 326 | special_fish_coin_less = str(config.special_fish_price - fishes_record.coin) 327 | return f"你没有足够的 {fishing_coin_name}, 还需 {special_fish_coin_less} {fishing_coin_name}" 328 | user_coin -= config.special_fish_price 329 | new_record = SpecialFishes( 330 | user_id=user_id, 331 | fish=fish_name 332 | ) 333 | session.add(new_record) 334 | user_update = update(FishingRecord).where( 335 | FishingRecord.user_id == user_id 336 | ).values( 337 | coin=user_coin 338 | ) 339 | await session.execute(user_update) 340 | await session.commit() 341 | return f"你花费 {config.special_fish_price} {fishing_coin_name} 放生了 {fish_name}, 未来或许会被有缘人钓到呢" 342 | return "你甚至还没钓过鱼" 343 | 344 | 345 | async def lottery(user_id: str) -> str: 346 | """算法来自于 https://github.com/fossifer/minesweeperbot/blob/master/cards.py""" 347 | session = get_session() 348 | async with session.begin(): 349 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 350 | fishes_record = await session.scalar(select_user) 351 | if fishes_record: 352 | user_coin = fishes_record.coin 353 | if user_coin <= 0: 354 | return f"你只有 {user_coin} {fishing_coin_name}, 不足以祈愿" 355 | new_coin = abs(user_coin) / 3 356 | new_coin = random.randrange(5000, 15000) / 10000 * new_coin 357 | new_coin = int(new_coin) if new_coin > 1 else 1 358 | new_coin *= random.randrange(-1, 2, 2) 359 | user_update = update(FishingRecord).where( 360 | FishingRecord.user_id == user_id 361 | ).values( 362 | coin=fishes_record.coin + new_coin, 363 | ) 364 | await session.execute(user_update) 365 | await session.commit() 366 | return f'你{"获得" if new_coin >= 0 else "血亏"}了 {abs(new_coin)} {fishing_coin_name}' 367 | 368 | 369 | async def give(user_id: str, fish_name: str, quantity: int = 1) -> str: 370 | session = get_session() 371 | async with session.begin(): 372 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 373 | record = await session.scalar(select_user) 374 | if record: 375 | loads_fishes = json.loads(record.fishes) 376 | try: 377 | loads_fishes[fish_name] += quantity 378 | except KeyError: 379 | loads_fishes[fish_name] = quantity 380 | dump_fishes = json.dumps(loads_fishes) 381 | user_update = update(FishingRecord).where( 382 | FishingRecord.user_id == user_id 383 | ).values( 384 | fishes=dump_fishes 385 | ) 386 | await session.execute(user_update) 387 | await session.commit() 388 | return f"使用滥权之力成功使 {fish_name} 添加到 {user_id} 的背包之中 ヾ(≧▽≦*)o" 389 | return "未查找到用户信息, 无法执行滥权操作 w(゚Д゚)w" 390 | 391 | 392 | async def get_achievements(user_id: str) -> str: 393 | session = get_session() 394 | async with session.begin(): 395 | select_user = select(FishingRecord).where(FishingRecord.user_id == user_id) 396 | record = await session.scalar(select_user) 397 | if record: 398 | achievements = json.loads(record.achievements) 399 | return "已完成成就:\n" + "\n".join(achievements) 400 | return "你甚至还没钓过鱼 (╬▔皿▔)╯" 401 | -------------------------------------------------------------------------------- /nonebot_plugin_fishing/migrations/1be1c9b715a9_add_achievements.py: -------------------------------------------------------------------------------- 1 | """add achievements 2 | 3 | 迁移 ID: 1be1c9b715a9 4 | 父迁移: e9015df43907 5 | 创建时间: 2024-09-22 17:12:51.193361 6 | 7 | """ 8 | from __future__ import annotations 9 | 10 | from collections.abc import Sequence 11 | 12 | from alembic import op 13 | import sqlalchemy as sa 14 | 15 | 16 | revision: str = '1be1c9b715a9' 17 | down_revision: str | Sequence[str] | None = 'e9015df43907' 18 | branch_labels: str | Sequence[str] | None = None 19 | depends_on: str | Sequence[str] | None = None 20 | 21 | 22 | def upgrade(name: str = "") -> None: 23 | if name: 24 | return 25 | # ### commands auto generated by Alembic - please adjust! ### 26 | with op.batch_alter_table('nonebot_plugin_fishing_fishingrecord', schema=None) as batch_op: 27 | batch_op.add_column(sa.Column('achievements', sa.TEXT(), nullable=False)) 28 | 29 | # ### end Alembic commands ### 30 | 31 | 32 | def downgrade(name: str = "") -> None: 33 | if name: 34 | return 35 | # ### commands auto generated by Alembic - please adjust! ### 36 | with op.batch_alter_table('nonebot_plugin_fishing_fishingrecord', schema=None) as batch_op: 37 | batch_op.drop_column('achievements') 38 | 39 | # ### end Alembic commands ### -------------------------------------------------------------------------------- /nonebot_plugin_fishing/migrations/68463f3e5f33_.py: -------------------------------------------------------------------------------- 1 | """Update version 2 | 3 | 迁移 ID: 68463f3e5f33 4 | 父迁移: 7609e6d106dd 5 | 创建时间: 2024-04-13 01:21:12.144452 6 | 7 | """ 8 | from __future__ import annotations 9 | 10 | from collections.abc import Sequence 11 | 12 | from alembic import op 13 | import sqlalchemy as sa 14 | 15 | 16 | revision: str = '68463f3e5f33' 17 | down_revision: str | Sequence[str] | None = '7609e6d106dd' 18 | branch_labels: str | Sequence[str] | None = None 19 | depends_on: str | Sequence[str] | None = None 20 | 21 | 22 | def upgrade(name: str = "") -> None: 23 | if name: 24 | return 25 | # ### commands auto generated by Alembic - please adjust! ### 26 | pass 27 | # ### end Alembic commands ### 28 | 29 | 30 | def downgrade(name: str = "") -> None: 31 | if name: 32 | return 33 | # ### commands auto generated by Alembic - please adjust! ### 34 | pass 35 | # ### end Alembic commands ### -------------------------------------------------------------------------------- /nonebot_plugin_fishing/migrations/7609e6d106dd_init_db.py: -------------------------------------------------------------------------------- 1 | """init db 2 | 3 | 迁移 ID: 7609e6d106dd 4 | 父迁移: 5 | 创建时间: 2024-04-05 19:08:58.835014 6 | 7 | """ 8 | from __future__ import annotations 9 | 10 | from collections.abc import Sequence 11 | 12 | from alembic import op 13 | import sqlalchemy as sa 14 | 15 | 16 | revision: str = '7609e6d106dd' 17 | down_revision: str | Sequence[str] | None = None 18 | branch_labels: str | Sequence[str] | None = ('nonebot_plugin_fishing',) 19 | depends_on: str | Sequence[str] | None = None 20 | 21 | 22 | def upgrade(name: str = "") -> None: 23 | if name: 24 | return 25 | # ### commands auto generated by Alembic - please adjust! ### 26 | op.create_table('nonebot_plugin_fishing_fishingrecord', 27 | sa.Column('id', sa.Integer(), nullable=False), 28 | sa.Column('user_id', sa.String(length=32), nullable=False), 29 | sa.Column('time', sa.Integer(), nullable=False), 30 | sa.Column('frequency', sa.Integer(), nullable=False), 31 | sa.Column('fishes', sa.TEXT(), nullable=False), 32 | sa.Column('coin', sa.Integer(), nullable=False), 33 | sa.PrimaryKeyConstraint('id', name=op.f('pk_nonebot_plugin_fishing_fishingrecord')), 34 | info={'bind_key': 'nonebot_plugin_fishing'} 35 | ) 36 | # ### end Alembic commands ### 37 | 38 | 39 | def downgrade(name: str = "") -> None: 40 | if name: 41 | return 42 | # ### commands auto generated by Alembic - please adjust! ### 43 | op.drop_table('nonebot_plugin_fishing_fishingrecord') 44 | # ### end Alembic commands ### -------------------------------------------------------------------------------- /nonebot_plugin_fishing/migrations/c5ab992c9af3_add_achievements.py: -------------------------------------------------------------------------------- 1 | """add achievements 2 | 3 | 迁移 ID: c5ab992c9af3 4 | 父迁移: e9015df43907 5 | 创建时间: 2024-09-22 16:44:24.934270 6 | 7 | """ 8 | from __future__ import annotations 9 | 10 | from collections.abc import Sequence 11 | 12 | from alembic import op 13 | import sqlalchemy as sa 14 | 15 | 16 | revision: str = 'c5ab992c9af3' 17 | down_revision: str | Sequence[str] | None = 'e9015df43907' 18 | branch_labels: str | Sequence[str] | None = None 19 | depends_on: str | Sequence[str] | None = None 20 | 21 | 22 | def upgrade(name: str = "") -> None: 23 | if name: 24 | return 25 | # ### commands auto generated by Alembic - please adjust! ### 26 | with op.batch_alter_table('nonebot_plugin_fishing_fishingrecord', schema=None) as batch_op: 27 | batch_op.add_column(sa.Column('achievements', sa.TEXT(), nullable=False)) 28 | 29 | # ### end Alembic commands ### 30 | 31 | 32 | def downgrade(name: str = "") -> None: 33 | if name: 34 | return 35 | # ### commands auto generated by Alembic - please adjust! ### 36 | with op.batch_alter_table('nonebot_plugin_fishing_fishingrecord', schema=None) as batch_op: 37 | batch_op.drop_column('achievements') 38 | 39 | # ### end Alembic commands ### -------------------------------------------------------------------------------- /nonebot_plugin_fishing/migrations/e9015df43907_add_special_fishes_field.py: -------------------------------------------------------------------------------- 1 | """add special_fishes field 2 | 3 | 迁移 ID: e9015df43907 4 | 父迁移: f70bdeaec7a4 5 | 创建时间: 2024-04-20 12:43:35.168261 6 | 7 | """ 8 | from __future__ import annotations 9 | 10 | from collections.abc import Sequence 11 | 12 | from alembic import op 13 | import sqlalchemy as sa 14 | 15 | 16 | revision: str = 'e9015df43907' 17 | down_revision: str | Sequence[str] | None = 'f70bdeaec7a4' 18 | branch_labels: str | Sequence[str] | None = None 19 | depends_on: str | Sequence[str] | None = None 20 | 21 | 22 | def upgrade(name: str = "") -> None: 23 | if name: 24 | return 25 | # ### commands auto generated by Alembic - please adjust! ### 26 | with op.batch_alter_table('nonebot_plugin_fishing_fishingrecord', schema=None) as batch_op: 27 | batch_op.add_column(sa.Column('special_fishes', sa.TEXT(), nullable=False)) 28 | 29 | # ### end Alembic commands ### 30 | 31 | 32 | def downgrade(name: str = "") -> None: 33 | if name: 34 | return 35 | # ### commands auto generated by Alembic - please adjust! ### 36 | with op.batch_alter_table('nonebot_plugin_fishing_fishingrecord', schema=None) as batch_op: 37 | batch_op.drop_column('special_fishes') 38 | 39 | # ### end Alembic commands ### 40 | -------------------------------------------------------------------------------- /nonebot_plugin_fishing/migrations/f70bdeaec7a4_add_specialfishes_table.py: -------------------------------------------------------------------------------- 1 | """add SpecialFishes table 2 | 3 | 迁移 ID: f70bdeaec7a4 4 | 父迁移: 68463f3e5f33 5 | 创建时间: 2024-04-11 12:59:25.138990 6 | 7 | """ 8 | from __future__ import annotations 9 | 10 | from collections.abc import Sequence 11 | 12 | from alembic import op 13 | import sqlalchemy as sa 14 | 15 | 16 | revision: str = 'f70bdeaec7a4' 17 | down_revision: str | Sequence[str] | None = '68463f3e5f33' 18 | branch_labels: str | Sequence[str] | None = None 19 | depends_on: str | Sequence[str] | None = None 20 | 21 | 22 | def upgrade(name: str = "") -> None: 23 | if name: 24 | return 25 | # ### commands auto generated by Alembic - please adjust! ### 26 | op.create_table('nonebot_plugin_fishing_specialfishes', 27 | sa.Column('id', sa.Integer(), nullable=False), 28 | sa.Column('user_id', sa.String(length=32), nullable=False), 29 | sa.Column('fish', sa.TEXT(), nullable=False), 30 | sa.PrimaryKeyConstraint('id', name=op.f('pk_nonebot_plugin_fishing_specialfishes')), 31 | info={'bind_key': 'nonebot_plugin_fishing'} 32 | ) 33 | # ### end Alembic commands ### 34 | 35 | 36 | def downgrade(name: str = "") -> None: 37 | if name: 38 | return 39 | # ### commands auto generated by Alembic - please adjust! ### 40 | op.drop_table('nonebot_plugin_fishing_specialfishes') 41 | # ### end Alembic commands ### 42 | -------------------------------------------------------------------------------- /nonebot_plugin_fishing/model.py: -------------------------------------------------------------------------------- 1 | from nonebot_plugin_orm import Model 2 | from sqlalchemy import String, TEXT 3 | from sqlalchemy.orm import Mapped, mapped_column 4 | 5 | 6 | class FishingRecord(Model): 7 | id: Mapped[int] = mapped_column(primary_key=True) 8 | user_id: Mapped[str] = mapped_column(String(32)) 9 | time: Mapped[int] 10 | frequency: Mapped[int] 11 | fishes: Mapped[str] = mapped_column(TEXT) 12 | special_fishes: Mapped[str] = mapped_column(TEXT, default="{}") 13 | coin: Mapped[int] = mapped_column(default=0) 14 | achievements: Mapped[str] = mapped_column(TEXT, default="[]") 15 | 16 | 17 | class SpecialFishes(Model): 18 | id: Mapped[int] = mapped_column(primary_key=True) 19 | user_id: Mapped[str] = mapped_column(String(32)) 20 | fish: Mapped[str] = mapped_column(TEXT, default="{}") 21 | -------------------------------------------------------------------------------- /pdm.lock: -------------------------------------------------------------------------------- 1 | # This file is @generated by PDM. 2 | # It is not intended for manual editing. 3 | 4 | [metadata] 5 | groups = ["default"] 6 | strategy = ["cross_platform", "inherit_metadata"] 7 | lock_version = "4.4.1" 8 | content_hash = "sha256:ab940abf33ccfcf918d9946cc634d334aab185d1ad43a2ecaae17ef8efd4066a" 9 | 10 | [[package]] 11 | name = "aiosqlite" 12 | version = "0.20.0" 13 | requires_python = ">=3.8" 14 | summary = "asyncio bridge to the standard sqlite3 module" 15 | groups = ["default"] 16 | dependencies = [ 17 | "typing-extensions>=4.0", 18 | ] 19 | files = [ 20 | {file = "aiosqlite-0.20.0-py3-none-any.whl", hash = "sha256:36a1deaca0cac40ebe32aac9977a6e2bbc7f5189f23f4a54d5908986729e5bd6"}, 21 | {file = "aiosqlite-0.20.0.tar.gz", hash = "sha256:6d35c8c256637f4672f843c31021464090805bf925385ac39473fb16eaaca3d7"}, 22 | ] 23 | 24 | [[package]] 25 | name = "alembic" 26 | version = "1.13.1" 27 | requires_python = ">=3.8" 28 | summary = "A database migration tool for SQLAlchemy." 29 | groups = ["default"] 30 | dependencies = [ 31 | "Mako", 32 | "SQLAlchemy>=1.3.0", 33 | "importlib-metadata; python_version < \"3.9\"", 34 | "importlib-resources; python_version < \"3.9\"", 35 | "typing-extensions>=4", 36 | ] 37 | files = [ 38 | {file = "alembic-1.13.1-py3-none-any.whl", hash = "sha256:2edcc97bed0bd3272611ce3a98d98279e9c209e7186e43e75bbb1b2bdfdbcc43"}, 39 | {file = "alembic-1.13.1.tar.gz", hash = "sha256:4932c8558bf68f2ee92b9bbcb8218671c627064d5b08939437af6d77dc05e595"}, 40 | ] 41 | 42 | [[package]] 43 | name = "annotated-types" 44 | version = "0.6.0" 45 | requires_python = ">=3.8" 46 | summary = "Reusable constraint types to use with typing.Annotated" 47 | groups = ["default"] 48 | dependencies = [ 49 | "typing-extensions>=4.0.0; python_version < \"3.9\"", 50 | ] 51 | files = [ 52 | {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, 53 | {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, 54 | ] 55 | 56 | [[package]] 57 | name = "click" 58 | version = "8.1.7" 59 | requires_python = ">=3.7" 60 | summary = "Composable command line interface toolkit" 61 | groups = ["default"] 62 | dependencies = [ 63 | "colorama; platform_system == \"Windows\"", 64 | ] 65 | files = [ 66 | {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, 67 | {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, 68 | ] 69 | 70 | [[package]] 71 | name = "colorama" 72 | version = "0.4.6" 73 | requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 74 | summary = "Cross-platform colored terminal text." 75 | groups = ["default"] 76 | marker = "sys_platform == \"win32\" or platform_system == \"Windows\"" 77 | files = [ 78 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 79 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 80 | ] 81 | 82 | [[package]] 83 | name = "greenlet" 84 | version = "3.0.3" 85 | requires_python = ">=3.7" 86 | summary = "Lightweight in-process concurrent programming" 87 | groups = ["default"] 88 | marker = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\"" 89 | files = [ 90 | {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"}, 91 | {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"}, 92 | {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"}, 93 | {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"}, 94 | {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"}, 95 | {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"}, 96 | {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"}, 97 | {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"}, 98 | {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"}, 99 | {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"}, 100 | ] 101 | 102 | [[package]] 103 | name = "idna" 104 | version = "3.6" 105 | requires_python = ">=3.5" 106 | summary = "Internationalized Domain Names in Applications (IDNA)" 107 | groups = ["default"] 108 | files = [ 109 | {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, 110 | {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, 111 | ] 112 | 113 | [[package]] 114 | name = "importlib-metadata" 115 | version = "7.0.2" 116 | requires_python = ">=3.8" 117 | summary = "Read metadata from Python packages" 118 | groups = ["default"] 119 | marker = "python_version < \"3.10\"" 120 | dependencies = [ 121 | "zipp>=0.5", 122 | ] 123 | files = [ 124 | {file = "importlib_metadata-7.0.2-py3-none-any.whl", hash = "sha256:f4bc4c0c070c490abf4ce96d715f68e95923320370efb66143df00199bb6c100"}, 125 | {file = "importlib_metadata-7.0.2.tar.gz", hash = "sha256:198f568f3230878cb1b44fbd7975f87906c22336dba2e4a7f05278c281fbd792"}, 126 | ] 127 | 128 | [[package]] 129 | name = "importlib-resources" 130 | version = "6.1.3" 131 | requires_python = ">=3.8" 132 | summary = "Read resources from Python packages" 133 | groups = ["default"] 134 | marker = "python_version < \"3.12\"" 135 | dependencies = [ 136 | "zipp>=3.1.0; python_version < \"3.10\"", 137 | ] 138 | files = [ 139 | {file = "importlib_resources-6.1.3-py3-none-any.whl", hash = "sha256:4c0269e3580fe2634d364b39b38b961540a7738c02cb984e98add8b4221d793d"}, 140 | {file = "importlib_resources-6.1.3.tar.gz", hash = "sha256:56fb4525197b78544a3354ea27793952ab93f935bb4bf746b846bb1015020f2b"}, 141 | ] 142 | 143 | [[package]] 144 | name = "loguru" 145 | version = "0.7.2" 146 | requires_python = ">=3.5" 147 | summary = "Python logging made (stupidly) simple" 148 | groups = ["default"] 149 | dependencies = [ 150 | "colorama>=0.3.4; sys_platform == \"win32\"", 151 | "win32-setctime>=1.0.0; sys_platform == \"win32\"", 152 | ] 153 | files = [ 154 | {file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"}, 155 | {file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"}, 156 | ] 157 | 158 | [[package]] 159 | name = "mako" 160 | version = "1.3.2" 161 | requires_python = ">=3.8" 162 | summary = "A super-fast templating language that borrows the best ideas from the existing templating languages." 163 | groups = ["default"] 164 | dependencies = [ 165 | "MarkupSafe>=0.9.2", 166 | ] 167 | files = [ 168 | {file = "Mako-1.3.2-py3-none-any.whl", hash = "sha256:32a99d70754dfce237019d17ffe4a282d2d3351b9c476e90d8a60e63f133b80c"}, 169 | {file = "Mako-1.3.2.tar.gz", hash = "sha256:2a0c8ad7f6274271b3bb7467dd37cf9cc6dab4bc19cb69a4ef10669402de698e"}, 170 | ] 171 | 172 | [[package]] 173 | name = "markupsafe" 174 | version = "2.1.5" 175 | requires_python = ">=3.7" 176 | summary = "Safely add untrusted strings to HTML/XML markup." 177 | groups = ["default"] 178 | files = [ 179 | {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, 180 | {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, 181 | {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, 182 | {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, 183 | {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, 184 | {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, 185 | {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, 186 | {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, 187 | {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, 188 | {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, 189 | {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, 190 | {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, 191 | {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, 192 | {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, 193 | {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, 194 | {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, 195 | {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, 196 | {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, 197 | {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, 198 | {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, 199 | {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, 200 | {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, 201 | {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, 202 | {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, 203 | {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, 204 | {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, 205 | {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, 206 | {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, 207 | {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, 208 | {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, 209 | {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, 210 | {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, 211 | {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, 212 | {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, 213 | {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, 214 | {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, 215 | {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, 216 | {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, 217 | {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, 218 | {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, 219 | {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, 220 | {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, 221 | {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, 222 | {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, 223 | {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, 224 | {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, 225 | {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, 226 | {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, 227 | {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, 228 | {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, 229 | {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, 230 | ] 231 | 232 | [[package]] 233 | name = "multidict" 234 | version = "6.0.5" 235 | requires_python = ">=3.7" 236 | summary = "multidict implementation" 237 | groups = ["default"] 238 | files = [ 239 | {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, 240 | {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, 241 | {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, 242 | {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, 243 | {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, 244 | {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, 245 | {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, 246 | {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, 247 | {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, 248 | {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, 249 | {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, 250 | {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, 251 | {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, 252 | {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, 253 | {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, 254 | {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, 255 | {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, 256 | ] 257 | 258 | [[package]] 259 | name = "nonebot-plugin-localstore" 260 | version = "0.6.0" 261 | requires_python = ">=3.8,<4.0" 262 | summary = "Local Storage Support for NoneBot2" 263 | groups = ["default"] 264 | dependencies = [ 265 | "nonebot2<3.0.0,>=2.2.0", 266 | "pydantic!=2.5.0,!=2.5.1,<3.0.0,>=1.10.0", 267 | "typing-extensions>=4.0.0", 268 | ] 269 | files = [ 270 | {file = "nonebot_plugin_localstore-0.6.0-py3-none-any.whl", hash = "sha256:59f0126d85680601166a9a62cca886a33e1b0a8fef7cd67fff52747bd47f42d3"}, 271 | {file = "nonebot_plugin_localstore-0.6.0.tar.gz", hash = "sha256:7eb4039cb2e76c54b860b2b98f2b90cd25284919603e81dedec367f215662fcd"}, 272 | ] 273 | 274 | [[package]] 275 | name = "nonebot-plugin-orm" 276 | version = "0.7.1" 277 | requires_python = "<4.0,>=3.8" 278 | summary = "SQLAlchemy ORM support for nonebot" 279 | groups = ["default"] 280 | dependencies = [ 281 | "alembic~=1.13", 282 | "click~=8.1", 283 | "importlib-metadata~=7.0; python_version < \"3.10\"", 284 | "importlib-resources~=6.1; python_version < \"3.12\"", 285 | "nonebot-plugin-localstore~=0.6", 286 | "nonebot2~=2.2", 287 | "sqlalchemy~=2.0", 288 | "typing-extensions~=4.9; python_version < \"3.11\"", 289 | ] 290 | files = [ 291 | {file = "nonebot_plugin_orm-0.7.1-py3-none-any.whl", hash = "sha256:8e663094b0521a4838a4f7e65d53b603bfc5da77bafe9a89c912385918efb569"}, 292 | {file = "nonebot_plugin_orm-0.7.1.tar.gz", hash = "sha256:e6ae8f93e7e2a0f3de40a4f3dbfd48684654468aea1ea3ca31009fa5aaff42d8"}, 293 | ] 294 | 295 | [[package]] 296 | name = "nonebot2" 297 | version = "2.2.1" 298 | requires_python = ">=3.8,<4.0" 299 | summary = "An asynchronous python bot framework." 300 | groups = ["default"] 301 | dependencies = [ 302 | "loguru<1.0.0,>=0.6.0", 303 | "pydantic!=2.5.0,!=2.5.1,<3.0.0,>=1.10.0", 304 | "pygtrie<3.0.0,>=2.4.1", 305 | "python-dotenv<2.0.0,>=0.21.0", 306 | "tomli<3.0.0,>=2.0.1; python_version < \"3.11\"", 307 | "typing-extensions<5.0.0,>=4.4.0", 308 | "yarl<2.0.0,>=1.7.2", 309 | ] 310 | files = [ 311 | {file = "nonebot2-2.2.1-py3-none-any.whl", hash = "sha256:88f2bb456bf90922925bbe489a9effe3b09300f3aa50bfa75ee50d8a83d7330f"}, 312 | {file = "nonebot2-2.2.1.tar.gz", hash = "sha256:fe57692300571b00724999238545d8d894523460e6835a11b326a2e1cdf98fc4"}, 313 | ] 314 | 315 | [[package]] 316 | name = "pydantic" 317 | version = "2.6.3" 318 | requires_python = ">=3.8" 319 | summary = "Data validation using Python type hints" 320 | groups = ["default"] 321 | dependencies = [ 322 | "annotated-types>=0.4.0", 323 | "pydantic-core==2.16.3", 324 | "typing-extensions>=4.6.1", 325 | ] 326 | files = [ 327 | {file = "pydantic-2.6.3-py3-none-any.whl", hash = "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a"}, 328 | {file = "pydantic-2.6.3.tar.gz", hash = "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"}, 329 | ] 330 | 331 | [[package]] 332 | name = "pydantic-core" 333 | version = "2.16.3" 334 | requires_python = ">=3.8" 335 | summary = "" 336 | groups = ["default"] 337 | dependencies = [ 338 | "typing-extensions!=4.7.0,>=4.6.0", 339 | ] 340 | files = [ 341 | {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"}, 342 | {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"}, 343 | {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"}, 344 | {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"}, 345 | {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"}, 346 | {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"}, 347 | {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"}, 348 | {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"}, 349 | {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"}, 350 | {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"}, 351 | {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"}, 352 | {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"}, 353 | {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"}, 354 | {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"}, 355 | {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"}, 356 | {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"}, 357 | {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"}, 358 | {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"}, 359 | {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"}, 360 | {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"}, 361 | {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"}, 362 | {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"}, 363 | {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"}, 364 | {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"}, 365 | {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"}, 366 | {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"}, 367 | {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"}, 368 | {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"}, 369 | {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"}, 370 | {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"}, 371 | ] 372 | 373 | [[package]] 374 | name = "pygtrie" 375 | version = "2.5.0" 376 | summary = "A pure Python trie data structure implementation." 377 | groups = ["default"] 378 | files = [ 379 | {file = "pygtrie-2.5.0-py3-none-any.whl", hash = "sha256:8795cda8105493d5ae159a5bef313ff13156c5d4d72feddefacaad59f8c8ce16"}, 380 | {file = "pygtrie-2.5.0.tar.gz", hash = "sha256:203514ad826eb403dab1d2e2ddd034e0d1534bbe4dbe0213bb0593f66beba4e2"}, 381 | ] 382 | 383 | [[package]] 384 | name = "python-dotenv" 385 | version = "1.0.1" 386 | requires_python = ">=3.8" 387 | summary = "Read key-value pairs from a .env file and set them as environment variables" 388 | groups = ["default"] 389 | files = [ 390 | {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, 391 | {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, 392 | ] 393 | 394 | [[package]] 395 | name = "sqlalchemy" 396 | version = "2.0.27" 397 | requires_python = ">=3.7" 398 | summary = "Database Abstraction Library" 399 | groups = ["default"] 400 | dependencies = [ 401 | "greenlet!=0.4.17; platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\"", 402 | "typing-extensions>=4.6.0", 403 | ] 404 | files = [ 405 | {file = "SQLAlchemy-2.0.27-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d04e579e911562f1055d26dab1868d3e0bb905db3bccf664ee8ad109f035618a"}, 406 | {file = "SQLAlchemy-2.0.27-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fa67d821c1fd268a5a87922ef4940442513b4e6c377553506b9db3b83beebbd8"}, 407 | {file = "SQLAlchemy-2.0.27-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c7a596d0be71b7baa037f4ac10d5e057d276f65a9a611c46970f012752ebf2d"}, 408 | {file = "SQLAlchemy-2.0.27-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:954d9735ee9c3fa74874c830d089a815b7b48df6f6b6e357a74130e478dbd951"}, 409 | {file = "SQLAlchemy-2.0.27-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5cd20f58c29bbf2680039ff9f569fa6d21453fbd2fa84dbdb4092f006424c2e6"}, 410 | {file = "SQLAlchemy-2.0.27-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:03f448ffb731b48323bda68bcc93152f751436ad6037f18a42b7e16af9e91c07"}, 411 | {file = "SQLAlchemy-2.0.27-cp310-cp310-win32.whl", hash = "sha256:d997c5938a08b5e172c30583ba6b8aad657ed9901fc24caf3a7152eeccb2f1b4"}, 412 | {file = "SQLAlchemy-2.0.27-cp310-cp310-win_amd64.whl", hash = "sha256:eb15ef40b833f5b2f19eeae65d65e191f039e71790dd565c2af2a3783f72262f"}, 413 | {file = "SQLAlchemy-2.0.27-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6c5bad7c60a392850d2f0fee8f355953abaec878c483dd7c3836e0089f046bf6"}, 414 | {file = "SQLAlchemy-2.0.27-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3012ab65ea42de1be81fff5fb28d6db893ef978950afc8130ba707179b4284a"}, 415 | {file = "SQLAlchemy-2.0.27-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbcd77c4d94b23e0753c5ed8deba8c69f331d4fd83f68bfc9db58bc8983f49cd"}, 416 | {file = "SQLAlchemy-2.0.27-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d177b7e82f6dd5e1aebd24d9c3297c70ce09cd1d5d37b43e53f39514379c029c"}, 417 | {file = "SQLAlchemy-2.0.27-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:680b9a36029b30cf063698755d277885d4a0eab70a2c7c6e71aab601323cba45"}, 418 | {file = "SQLAlchemy-2.0.27-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1306102f6d9e625cebaca3d4c9c8f10588735ef877f0360b5cdb4fdfd3fd7131"}, 419 | {file = "SQLAlchemy-2.0.27-cp311-cp311-win32.whl", hash = "sha256:5b78aa9f4f68212248aaf8943d84c0ff0f74efc65a661c2fc68b82d498311fd5"}, 420 | {file = "SQLAlchemy-2.0.27-cp311-cp311-win_amd64.whl", hash = "sha256:15e19a84b84528f52a68143439d0c7a3a69befcd4f50b8ef9b7b69d2628ae7c4"}, 421 | {file = "SQLAlchemy-2.0.27-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0de1263aac858f288a80b2071990f02082c51d88335a1db0d589237a3435fe71"}, 422 | {file = "SQLAlchemy-2.0.27-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce850db091bf7d2a1f2fdb615220b968aeff3849007b1204bf6e3e50a57b3d32"}, 423 | {file = "SQLAlchemy-2.0.27-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dfc936870507da96aebb43e664ae3a71a7b96278382bcfe84d277b88e379b18"}, 424 | {file = "SQLAlchemy-2.0.27-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4fbe6a766301f2e8a4519f4500fe74ef0a8509a59e07a4085458f26228cd7cc"}, 425 | {file = "SQLAlchemy-2.0.27-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4535c49d961fe9a77392e3a630a626af5baa967172d42732b7a43496c8b28876"}, 426 | {file = "SQLAlchemy-2.0.27-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0fb3bffc0ced37e5aa4ac2416f56d6d858f46d4da70c09bb731a246e70bff4d5"}, 427 | {file = "SQLAlchemy-2.0.27-cp312-cp312-win32.whl", hash = "sha256:7f470327d06400a0aa7926b375b8e8c3c31d335e0884f509fe272b3c700a7254"}, 428 | {file = "SQLAlchemy-2.0.27-cp312-cp312-win_amd64.whl", hash = "sha256:f9374e270e2553653d710ece397df67db9d19c60d2647bcd35bfc616f1622dcd"}, 429 | {file = "SQLAlchemy-2.0.27-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ec1f5a328464daf7a1e4e385e4f5652dd9b1d12405075ccba1df842f7774b4fc"}, 430 | {file = "SQLAlchemy-2.0.27-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ad862295ad3f644e3c2c0d8b10a988e1600d3123ecb48702d2c0f26771f1c396"}, 431 | {file = "SQLAlchemy-2.0.27-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48217be1de7d29a5600b5c513f3f7664b21d32e596d69582be0a94e36b8309cb"}, 432 | {file = "SQLAlchemy-2.0.27-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e56afce6431450442f3ab5973156289bd5ec33dd618941283847c9fd5ff06bf"}, 433 | {file = "SQLAlchemy-2.0.27-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:611068511b5531304137bcd7fe8117c985d1b828eb86043bd944cebb7fae3910"}, 434 | {file = "SQLAlchemy-2.0.27-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b86abba762ecfeea359112b2bb4490802b340850bbee1948f785141a5e020de8"}, 435 | {file = "SQLAlchemy-2.0.27-cp38-cp38-win32.whl", hash = "sha256:30d81cc1192dc693d49d5671cd40cdec596b885b0ce3b72f323888ab1c3863d5"}, 436 | {file = "SQLAlchemy-2.0.27-cp38-cp38-win_amd64.whl", hash = "sha256:120af1e49d614d2525ac247f6123841589b029c318b9afbfc9e2b70e22e1827d"}, 437 | {file = "SQLAlchemy-2.0.27-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d07ee7793f2aeb9b80ec8ceb96bc8cc08a2aec8a1b152da1955d64e4825fcbac"}, 438 | {file = "SQLAlchemy-2.0.27-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cb0845e934647232b6ff5150df37ceffd0b67b754b9fdbb095233deebcddbd4a"}, 439 | {file = "SQLAlchemy-2.0.27-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fc19ae2e07a067663dd24fca55f8ed06a288384f0e6e3910420bf4b1270cc51"}, 440 | {file = "SQLAlchemy-2.0.27-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b90053be91973a6fb6020a6e44382c97739736a5a9d74e08cc29b196639eb979"}, 441 | {file = "SQLAlchemy-2.0.27-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2f5c9dfb0b9ab5e3a8a00249534bdd838d943ec4cfb9abe176a6c33408430230"}, 442 | {file = "SQLAlchemy-2.0.27-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:33e8bde8fff203de50399b9039c4e14e42d4d227759155c21f8da4a47fc8053c"}, 443 | {file = "SQLAlchemy-2.0.27-cp39-cp39-win32.whl", hash = "sha256:d873c21b356bfaf1589b89090a4011e6532582b3a8ea568a00e0c3aab09399dd"}, 444 | {file = "SQLAlchemy-2.0.27-cp39-cp39-win_amd64.whl", hash = "sha256:ff2f1b7c963961d41403b650842dc2039175b906ab2093635d8319bef0b7d620"}, 445 | {file = "SQLAlchemy-2.0.27-py3-none-any.whl", hash = "sha256:1ab4e0448018d01b142c916cc7119ca573803a4745cfe341b8f95657812700ac"}, 446 | {file = "SQLAlchemy-2.0.27.tar.gz", hash = "sha256:86a6ed69a71fe6b88bf9331594fa390a2adda4a49b5c06f98e47bf0d392534f8"}, 447 | ] 448 | 449 | [[package]] 450 | name = "tomli" 451 | version = "2.0.1" 452 | requires_python = ">=3.7" 453 | summary = "A lil' TOML parser" 454 | groups = ["default"] 455 | marker = "python_version < \"3.11\"" 456 | files = [ 457 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 458 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 459 | ] 460 | 461 | [[package]] 462 | name = "typing-extensions" 463 | version = "4.10.0" 464 | requires_python = ">=3.8" 465 | summary = "Backported and Experimental Type Hints for Python 3.8+" 466 | groups = ["default"] 467 | files = [ 468 | {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, 469 | {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, 470 | ] 471 | 472 | [[package]] 473 | name = "win32-setctime" 474 | version = "1.1.0" 475 | requires_python = ">=3.5" 476 | summary = "A small Python utility to set file creation time on Windows" 477 | groups = ["default"] 478 | marker = "sys_platform == \"win32\"" 479 | files = [ 480 | {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, 481 | {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, 482 | ] 483 | 484 | [[package]] 485 | name = "yarl" 486 | version = "1.9.4" 487 | requires_python = ">=3.7" 488 | summary = "Yet another URL library" 489 | groups = ["default"] 490 | dependencies = [ 491 | "idna>=2.0", 492 | "multidict>=4.0", 493 | ] 494 | files = [ 495 | {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, 496 | {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, 497 | {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, 498 | {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, 499 | {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, 500 | {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, 501 | {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, 502 | {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, 503 | {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, 504 | {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, 505 | {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, 506 | {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, 507 | {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, 508 | {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, 509 | {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, 510 | {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, 511 | {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, 512 | ] 513 | 514 | [[package]] 515 | name = "zipp" 516 | version = "3.17.0" 517 | requires_python = ">=3.8" 518 | summary = "Backport of pathlib-compatible object wrapper for zip files" 519 | groups = ["default"] 520 | marker = "python_version < \"3.10\"" 521 | files = [ 522 | {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, 523 | {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, 524 | ] 525 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "nonebot-plugin-fishing" 3 | version = "0.2.4_alpha5" 4 | description = "你甚至可以电子钓鱼" 5 | authors = [ 6 | {name = "ALittleBot", email = "160833462+C14H22O@users.noreply.github.com"}, 7 | ] 8 | dependencies = [ 9 | "nonebot2>=2.2.1", 10 | "pydantic>=1.10", 11 | "nonebot-plugin-localstore>=0.6.0", 12 | "sqlalchemy>=2.0.27", 13 | "aiosqlite>=0.20.0", 14 | "nonebot-plugin-orm>=0.7.1", 15 | ] 16 | readme = "README.md" 17 | license = {text = "MIT"} 18 | requires-python = ">=3.8" 19 | --------------------------------------------------------------------------------