mirror of
https://github.com/A-Minos/nonebot-plugin-tetris-stats.git
synced 2026-03-05 05:36:54 +08:00
🔖 Release 1.0.0.a1 (#80)
* 使用 `pathlib` 替代 `os` * 防止建立多个数据库连接对象 * 调整数据库结构 # 破坏性更新 * 格式化代码 * ➖ 去除依赖Brotli ➖ 去除开发依赖autopep8 pylint ➕ 添加开发依赖ruff black 🔥 删除.pylintrc 🎨 使用black格式化代码 * 📝 一些很赞的小牌子 * ✏️ 修正`config`变量名 * 🐛 修复OperationalError语法错误 * ➕ 添加 debug 依赖 objprint * 🚧 数据记录器demo * 🔥 这个init好像没什么用( * 💡 ✏️ 修改错误的注释 * 📝 🍱 添加一个logo * 📝 添加logo的悬浮提示 * 🙈 更新 .gitignore * 🚨 消除了一些 init 文件中的错误警告 * ♻️ 💩 重构 IO 的 processor 模块 🐛 修复了 bind user_id 不能正确处理的bug 🎨 使用一些自定义类型和基于异常的编程( * 🐛 忘记写try了 * 👷 将 Release CI 切换到 Python 3.11 版本 * 🎨 修改 Exception 类的变量名 * 🎨 修改捕获的 aiohttp 的错误类型 * 🎨 将 AsyncCallable 放进 typing 模块 * 🏗️ 将 recorder 装饰器中执行函数的部分放在 collector 函数中 🚧 完善数据收集部分 * 🚧 receive 记录添加 message_id 以辅助消息上下文识别 * ➕ 添加依赖 tortoise-orm * ♻️ 🗃️ 将数据库操作替换成 tortoise-orm * 🎨 显式传递 locals 字典 * 🎨 将装饰器封装到类里 * 🐛 忘记 exec 需要拿变量了 * 🗃️ 微调数据类型 * 🗃️ 调整数据库索引 * Bump playwright from 1.29.0 to 1.30.0 (#72) * Bump ujson from 5.6.0 to 5.7.0 (#69) * Bump pandas-stubs from 1.5.2.221213 to 1.5.2.230105 (#57) * Bump types-ujson from 5.6.0.0 to 5.7.0.0 (#68) * ✨ 存储命令历史 #58 * Bump nonebot2 from 2.0.0rc2 to 2.0.0rc3 (#73) * Bump nonebot-adapter-onebot from 2.2.0 to 2.2.1 (#74) * Bump tortoise-orm from 0.19.2 to 0.19.3 (#75) * Bump black from 23.1a1 to 23.1.0 (#77) * Bump pandas from 1.5.2 to 1.5.3 (#76) * ⬆️ 更新 ruff * 🔧 启用更多的检查规则 * 🎨 使用单引号编写配置文件 * 💡 为 ignore 添加注释 * 🎨 使用 ruff 规范化引号 * 🔧 启用 PEP8 命名规范检查 * 🚨 添加一些 noqa( * 💡 添加和修改了一些注释 * 🔊 添加一条日志 * 🎨 🚨 使用 replace 替换 strip * 🎨 🚨 规范化命名 * 🎨 格式化代码 * 🔊 修改日志等级 * 🎨 去除重复的 get_driver() 调用 * ✨ 自动安装 playwright 浏览器 close #71 * 🙈 更新 gitignore * ✨ 将所有 playwright 相关整合进 BrowserManager 类 * 📝 更换开源许可证 (#78) * 📝 更新 README * Bump pandas-stubs from 1.5.2.230105 to 1.5.3.230203 (#79) * ➕ 添加依赖 nonebot-plugin-datastore * ✨ 使用 nonebot_plugin_datastore 提供的路径存储缓存 * Bump nonebot-plugin-datastore from 0.5.7 to 0.5.8 (#81) * ⬆️ Bump aiohttp from 3.8.3 to 3.8.4 (#82) Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.8.3 to 3.8.4. - [Release notes](https://github.com/aio-libs/aiohttp/releases) - [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst) - [Commits](https://github.com/aio-libs/aiohttp/compare/v3.8.3...v3.8.4) --- updated-dependencies: - dependency-name: aiohttp dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump pandas-stubs from 1.5.3.230203 to 1.5.3.230214 (#84) Bumps [pandas-stubs](https://github.com/pandas-dev/pandas-stubs) from 1.5.3.230203 to 1.5.3.230214. - [Release notes](https://github.com/pandas-dev/pandas-stubs/releases) - [Changelog](https://github.com/pandas-dev/pandas-stubs/blob/main/docs/release_procedure.md) - [Commits](https://github.com/pandas-dev/pandas-stubs/compare/v1.5.3.230203...v1.5.3.230214) --- updated-dependencies: - dependency-name: pandas-stubs dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump ruff from 0.0.239 to 0.0.253 (#90) * ⬆️ Bump playwright from 1.30.0 to 1.31.1 (#89) * ⬆️ Bump types-ujson from 5.7.0.0 to 5.7.0.1 (#86) * ⬆️ Bump pandas-stubs from 1.5.3.230214 to 1.5.3.230227 (#88) * ⬆️ Bump ruff from 0.0.253 to 0.0.254 (#91) * ⬆️ Bump pandas-stubs from 1.5.3.230227 to 1.5.3.230304 (#92) * ⬆️ Bump mypy from 0.991 to 1.0.1 (#93) * ⬆️ Bump mypy from 1.0.1 to 1.1.1 (#94) * ⬆️ Bump ruff from 0.0.254 to 0.0.284 (#139) Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.254 to 0.0.284. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md) - [Commits](https://github.com/astral-sh/ruff/compare/v0.0.254...v0.0.284) --- updated-dependencies: - dependency-name: ruff dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump nonebot-adapter-onebot from 2.2.1 to 2.2.4 (#137) Bumps [nonebot-adapter-onebot](https://github.com/nonebot/adapter-onebot) from 2.2.1 to 2.2.4. - [Release notes](https://github.com/nonebot/adapter-onebot/releases) - [Commits](https://github.com/nonebot/adapter-onebot/compare/v2.2.1...v2.2.4) --- updated-dependencies: - dependency-name: nonebot-adapter-onebot dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump playwright from 1.31.1 to 1.36.0 (#133) Bumps [playwright](https://github.com/Microsoft/playwright-python) from 1.31.1 to 1.36.0. - [Release notes](https://github.com/Microsoft/playwright-python/releases) - [Commits](https://github.com/Microsoft/playwright-python/compare/v1.31.1...v1.36.0) --- updated-dependencies: - dependency-name: playwright dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump pandas-stubs from 1.5.3.230304 to 2.0.2.230605 (#124) * ⬆️ Bump mypy from 1.1.1 to 1.5.1 (#144) Bumps [mypy](https://github.com/python/mypy) from 1.1.1 to 1.5.1. - [Commits](https://github.com/python/mypy/compare/v1.1.1...v1.5.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump types-ujson from 5.7.0.1 to 5.8.0.1 (#142) Bumps [types-ujson](https://github.com/python/typeshed) from 5.7.0.1 to 5.8.0.1. - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-ujson dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump nonebot2 from 2.0.0rc3 to 2.0.1 (#141) Bumps [nonebot2](https://github.com/nonebot/nonebot2) from 2.0.0rc3 to 2.0.1. - [Release notes](https://github.com/nonebot/nonebot2/releases) - [Changelog](https://github.com/nonebot/nonebot2/blob/master/CHANGELOG.md) - [Commits](https://github.com/nonebot/nonebot2/compare/v2.0.0rc3...v2.0.1) --- updated-dependencies: - dependency-name: nonebot2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump lxml from 4.9.2 to 4.9.3 (#140) Bumps [lxml](https://github.com/lxml/lxml) from 4.9.2 to 4.9.3. - [Release notes](https://github.com/lxml/lxml/releases) - [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt) - [Commits](https://github.com/lxml/lxml/compare/lxml-4.9.2...lxml-4.9.3) --- updated-dependencies: - dependency-name: lxml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump black from 23.1.0 to 23.9.1 (#148) Bumps [black](https://github.com/psf/black) from 23.1.0 to 23.9.1. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.1.0...23.9.1) --- updated-dependencies: - dependency-name: black dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump pandas-stubs from 2.0.2.230605 to 2.0.3.230814 (#149) Bumps [pandas-stubs](https://github.com/pandas-dev/pandas-stubs) from 2.0.2.230605 to 2.0.3.230814. - [Changelog](https://github.com/pandas-dev/pandas-stubs/blob/main/docs/release_procedure.md) - [Commits](https://github.com/pandas-dev/pandas-stubs/compare/v2.0.2.230605...v2.0.3.230814) --- updated-dependencies: - dependency-name: pandas-stubs dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump pandas from 1.5.3 to 2.1.1 (#152) Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.5.3 to 2.1.1. - [Release notes](https://github.com/pandas-dev/pandas/releases) - [Commits](https://github.com/pandas-dev/pandas/compare/v1.5.3...v2.1.1) --- updated-dependencies: - dependency-name: pandas dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump aiohttp from 3.8.4 to 3.8.5 (#155) Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.8.4 to 3.8.5. - [Release notes](https://github.com/aio-libs/aiohttp/releases) - [Changelog](https://github.com/aio-libs/aiohttp/blob/v3.8.5/CHANGES.rst) - [Commits](https://github.com/aio-libs/aiohttp/compare/v3.8.4...v3.8.5) --- updated-dependencies: - dependency-name: aiohttp dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump ruff from 0.0.284 to 0.0.291 (#154) Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.284 to 0.0.291. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md) - [Commits](https://github.com/astral-sh/ruff/compare/v0.0.284...v0.0.291) --- updated-dependencies: - dependency-name: ruff dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump playwright from 1.36.0 to 1.38.0 (#153) Bumps [playwright](https://github.com/Microsoft/playwright-python) from 1.36.0 to 1.38.0. - [Release notes](https://github.com/Microsoft/playwright-python/releases) - [Commits](https://github.com/Microsoft/playwright-python/compare/v1.36.0...v1.38.0) --- updated-dependencies: - dependency-name: playwright dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump nonebot-plugin-datastore from 0.5.8 to 1.1.2 (#151) Bumps [nonebot-plugin-datastore](https://github.com/he0119/nonebot-plugin-datastore) from 0.5.8 to 1.1.2. - [Release notes](https://github.com/he0119/nonebot-plugin-datastore/releases) - [Changelog](https://github.com/he0119/nonebot-plugin-datastore/blob/main/CHANGELOG.md) - [Commits](https://github.com/he0119/nonebot-plugin-datastore/compare/v0.5.8...v1.1.2) --- updated-dependencies: - dependency-name: nonebot-plugin-datastore dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump nonebot2 from 2.0.1 to 2.1.0 (#156) Bumps [nonebot2](https://github.com/nonebot/nonebot2) from 2.0.1 to 2.1.0. - [Release notes](https://github.com/nonebot/nonebot2/releases) - [Changelog](https://github.com/nonebot/nonebot2/blob/master/CHANGELOG.md) - [Commits](https://github.com/nonebot/nonebot2/compare/v2.0.1...v2.1.0) --- updated-dependencies: - dependency-name: nonebot2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump ujson from 5.7.0 to 5.8.0 (#157) Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.7.0 to 5.8.0. - [Release notes](https://github.com/ultrajson/ultrajson/releases) - [Commits](https://github.com/ultrajson/ultrajson/compare/5.7.0...5.8.0) --- updated-dependencies: - dependency-name: ujson dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⚡️ 移除无意义的async * 🎨 修正 type hint * ➕ 添加依赖 aiofiles * 🎨 将文件读写操作换成 aiofiles * ⚡️ 移除无意义的async * 🎨 重命名一些函数 * 🎨 去除不需要的转换 * ⬆️ Bump pandas-stubs from 2.0.3.230814 to 2.1.1.230928 (#158) Bumps [pandas-stubs](https://github.com/pandas-dev/pandas-stubs) from 2.0.3.230814 to 2.1.1.230928. - [Changelog](https://github.com/pandas-dev/pandas-stubs/blob/main/docs/release_procedure.md) - [Commits](https://github.com/pandas-dev/pandas-stubs/compare/v2.0.3.230814...v2.1.1.230928) --- updated-dependencies: - dependency-name: pandas-stubs dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump nonebot2 from 2.1.0 to 2.1.1 (#159) Bumps [nonebot2](https://github.com/nonebot/nonebot2) from 2.1.0 to 2.1.1. - [Release notes](https://github.com/nonebot/nonebot2/releases) - [Changelog](https://github.com/nonebot/nonebot2/blob/master/CHANGELOG.md) - [Commits](https://github.com/nonebot/nonebot2/compare/v2.1.0...v2.1.1) --- updated-dependencies: - dependency-name: nonebot2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ➕ 添加依赖 nonebot-plugin-orm ➕ 添加依赖 nonebot-plugin-localstore ➖ 移除依赖 nonebot-plugin-datastore * 📌 取消 python 最高版本限制 * ⬆️ Bump objprint from 0.2.2 to 0.2.3 (#161) Bumps [objprint](https://github.com/gaogaotiantian/objprint) from 0.2.2 to 0.2.3. - [Release notes](https://github.com/gaogaotiantian/objprint/releases) - [Commits](https://github.com/gaogaotiantian/objprint/compare/0.2.2...0.2.3) --- updated-dependencies: - dependency-name: objprint dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump ruff from 0.0.291 to 0.0.292 (#160) Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.291 to 0.0.292. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/BREAKING_CHANGES.md) - [Commits](https://github.com/astral-sh/ruff/compare/v0.0.291...v0.0.292) --- updated-dependencies: - dependency-name: ruff dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump mypy from 1.5.1 to 1.6.0 (#163) Bumps [mypy](https://github.com/python/mypy) from 1.5.1 to 1.6.0. - [Commits](https://github.com/python/mypy/compare/v1.5.1...v1.6.0) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ➕ 添加依赖 httpx * ⬆️ Bump nonebot-plugin-orm from 0.1.1 to 0.2.1 (#166) Bumps [nonebot-plugin-orm](https://github.com/nonebot/plugin-orm) from 0.1.1 to 0.2.1. - [Release notes](https://github.com/nonebot/plugin-orm/releases) - [Commits](https://github.com/nonebot/plugin-orm/compare/v0.1.1...v0.2.1) --- updated-dependencies: - dependency-name: nonebot-plugin-orm dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ➕ 添加开发依赖 nonebot2 * 🎨 改为直接使用 nonebot_plugin_localstore 提供缓存路径 * 🐛 忘记 require * 🐛 顺序错了 * 🗃️ 使用 nb orm * 🏗️ 再次重构 IO 模块 * 🐛 忘记 push 这个了 * 🏗️ 将 request 改成通用的 * ⬆️ Bump nonebot-plugin-orm from 0.2.1 to 0.2.2 (#167) Bumps [nonebot-plugin-orm](https://github.com/nonebot/plugin-orm) from 0.2.1 to 0.2.2. - [Release notes](https://github.com/nonebot/plugin-orm/releases) - [Commits](https://github.com/nonebot/plugin-orm/compare/v0.2.1...v0.2.2) --- updated-dependencies: - dependency-name: nonebot-plugin-orm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump ruff from 0.0.292 to 0.1.0 (#168) Bumps [ruff](https://github.com/astral-sh/ruff) from 0.0.292 to 0.1.0. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/v0.0.292...v0.1.0) --- updated-dependencies: - dependency-name: ruff dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump nonebot-adapter-onebot from 2.3.0 to 2.3.1 (#165) Bumps [nonebot-adapter-onebot](https://github.com/nonebot/adapter-onebot) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/nonebot/adapter-onebot/releases) - [Commits](https://github.com/nonebot/adapter-onebot/compare/v2.3.0...v2.3.1) --- updated-dependencies: - dependency-name: nonebot-adapter-onebot dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * 🏗️ 重构 TOS 模块 * 🩹 补充返回值类型标注 * 🐛 写错变量了 * 🐛 缺个 else * 🐛 忘记声明变量 * 🐛 忘记初始化变量 * 🎨 去除不需要的 else * 🎨 去除不需要的判断 * 🎨 减少一次函数调用 * 🐛 写错命令了 * ⬆️ Bump nonebot-plugin-orm from 0.2.2 to 0.2.3 (#170) Bumps [nonebot-plugin-orm](https://github.com/nonebot/plugin-orm) from 0.2.2 to 0.2.3. - [Release notes](https://github.com/nonebot/plugin-orm/releases) - [Commits](https://github.com/nonebot/plugin-orm/compare/v0.2.2...v0.2.3) --- updated-dependencies: - dependency-name: nonebot-plugin-orm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump black from 23.9.1 to 23.10.0 (#171) Bumps [black](https://github.com/psf/black) from 23.9.1 to 23.10.0. - [Release notes](https://github.com/psf/black/releases) - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md) - [Commits](https://github.com/psf/black/compare/23.9.1...23.10.0) --- updated-dependencies: - dependency-name: black dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump mypy from 1.6.0 to 1.6.1 (#172) Bumps [mypy](https://github.com/python/mypy) from 1.6.0 to 1.6.1. - [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md) - [Commits](https://github.com/python/mypy/compare/v1.6.0...v1.6.1) --- updated-dependencies: - dependency-name: mypy dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump playwright from 1.38.0 to 1.39.0 (#169) Bumps [playwright](https://github.com/Microsoft/playwright-python) from 1.38.0 to 1.39.0. - [Release notes](https://github.com/Microsoft/playwright-python/releases) - [Commits](https://github.com/Microsoft/playwright-python/compare/v1.38.0...v1.39.0) --- updated-dependencies: - dependency-name: playwright dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ➖ 去除开发依赖 lxml-stubs ➕ 添加开发依赖 types-lxml * 🏗️ 重构 TOP 模块 * 🐛 忘记传参了 * 🐛 忘记判断有没有绑定了 * 🎨 忘记用封好的函数了 * 📝 把 wakatime 的小牌牌放上去 并且格式化 * ⬆️ Bump ruff from 0.1.0 to 0.1.1 (#174) Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.0 to 0.1.1. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/v0.1.0...v0.1.1) --- updated-dependencies: - dependency-name: ruff dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump nonebot-plugin-orm from 0.2.3 to 0.2.4 (#173) Bumps [nonebot-plugin-orm](https://github.com/nonebot/plugin-orm) from 0.2.3 to 0.2.4. - [Release notes](https://github.com/nonebot/plugin-orm/releases) - [Commits](https://github.com/nonebot/plugin-orm/compare/v0.2.3...v0.2.4) --- updated-dependencies: - dependency-name: nonebot-plugin-orm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * 🏗️ 把 config 从 utils 里拿出来 * 🔥 orm 搞错用法了 * 🗃️ 创建新的迁移脚本 * ✨ 添加插件元数据 * 🐛 导包顺序又错了 * ➕ 添加依赖 nonebot-adapter-qq * ➕ 添加依赖 nonebot-plugin-alconna * ➖ 移除依赖 tortoise-orm * ⬆️ Bump nonebot-plugin-orm from 0.2.4 to 0.3.0 (#175) * ⬆️ Bump types-lxml from 2023.3.28 to 2023.10.21 (#176) * ⬆️ Bump black from 23.10.0 to 23.10.1 (#177) * ⬆️ Bump ruff from 0.1.1 to 0.1.2 (#178) * ➕ 添加debug依赖 viztracer * ➕ 添加开发依赖 nonebot-plugin-orm[default] * ✨ IO 基础查询功能适配所有平台 * ⬆️ Bump nonebot-plugin-alconna from 0.30.3 to 0.30.6 (#179) Bumps [nonebot-plugin-alconna](https://github.com/nonebot/plugin-alconna) from 0.30.3 to 0.30.6. - [Release notes](https://github.com/nonebot/plugin-alconna/releases) - [Commits](https://github.com/nonebot/plugin-alconna/compare/v0.30.3...v0.30.6) --- updated-dependencies: - dependency-name: nonebot-plugin-alconna dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * 🩹 防止在使用其他命令的时候意外触发 * 🚧 暂时去除记录器 待重构 * 🐛 修正输出信息格式 * ✨ TOP 基础查询功能适配所有平台 * ⬆️ Bump ruff from 0.1.2 to 0.1.3 (#180) * ⬆️ Bump nonebot-plugin-alconna from 0.30.6 to 0.30.7 (#181) * ✨ TOS 基础查询功能适配所有平台 * 🐛 修复一些输出消息问题 * 🔥 删除一些不需要的常量 * 🔥 把手搓的解析器爆了 * 🏷️ 添加一个不知道有什么用的类型注释 * 🎨 从 black 迁移 到 ruff format ➖ 删除开发依赖 black * ✨ 启用 pyupgrade 规则 * ✨ 启用 flake8-2020 规则 * ✨ 启用 flake8-annotations 规则 * ✨ 启用 flake8-async 规则 * ✨ 启用 flake8-bandit 规则 * ✨ 启用 flake8-blind-except 规则 * ✨ 启用 flake8-boolean-trap 规则 * ✨ 启用 flake8-builtins 规则 * ✨ 启用 flake8-datetimez 规则 * ✨ 启用 flake8-future-annotations 规则 * ✨ 启用 flake8-implicit-str-concat 规则 * ✨ 启用 flake8-pie 规则 * ✨ 启用 flake8-print 规则 * ✨ 启用 flake8-raise 规则 * ✨ 启用 flake8-return 规则 * ✨ 启用 flake8-simplify 规则 * ✨ 启用 flake8-use-pathlib 规则 * ✨ 启用 pandas-vet 规则 * ✨ 启用 tryceratops 规则 * ✨ 启用 flynt 规则 * ✨ 启用 Perflint 规则 * ⬆️ Bump nonebot-plugin-alconna from 0.30.7 to 0.31.0 (#183) Bumps [nonebot-plugin-alconna](https://github.com/nonebot/plugin-alconna) from 0.30.7 to 0.31.0. - [Release notes](https://github.com/nonebot/plugin-alconna/releases) - [Commits](https://github.com/nonebot/plugin-alconna/compare/v0.30.7...v0.31.0) --- updated-dependencies: - dependency-name: nonebot-plugin-alconna dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump nonebot-plugin-orm from 0.3.0 to 0.4.0 (#182) * ⬆️ Bump nonebot-plugin-orm from 0.4.0 to 0.4.1 (#186) Bumps [nonebot-plugin-orm](https://github.com/nonebot/plugin-orm) from 0.4.0 to 0.4.1. - [Release notes](https://github.com/nonebot/plugin-orm/releases) - [Commits](https://github.com/nonebot/plugin-orm/compare/v0.4.0...v0.4.1) --- updated-dependencies: - dependency-name: nonebot-plugin-orm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump nonebot2 from 2.1.1 to 2.1.2 (#185) Bumps [nonebot2](https://github.com/nonebot/nonebot2) from 2.1.1 to 2.1.2. - [Release notes](https://github.com/nonebot/nonebot2/releases) - [Changelog](https://github.com/nonebot/nonebot2/blob/master/CHANGELOG.md) - [Commits](https://github.com/nonebot/nonebot2/compare/v2.1.1...v2.1.2) --- updated-dependencies: - dependency-name: nonebot2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump nonebot-plugin-alconna from 0.31.0 to 0.31.3 (#187) Bumps [nonebot-plugin-alconna](https://github.com/nonebot/plugin-alconna) from 0.31.0 to 0.31.3. - [Release notes](https://github.com/nonebot/plugin-alconna/releases) - [Commits](https://github.com/nonebot/plugin-alconna/compare/v0.31.0...v0.31.3) --- updated-dependencies: - dependency-name: nonebot-plugin-alconna dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * 🐛 修复拼接 url 的 bug * ⬆️ Bump nonebot-plugin-orm from 0.4.1 to 0.5.0 (#189) Bumps [nonebot-plugin-orm](https://github.com/nonebot/plugin-orm) from 0.4.1 to 0.5.0. - [Release notes](https://github.com/nonebot/plugin-orm/releases) - [Commits](https://github.com/nonebot/plugin-orm/compare/v0.4.1...v0.5.0) --- updated-dependencies: - dependency-name: nonebot-plugin-orm dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump nonebot-plugin-alconna from 0.31.3 to 0.31.7 (#191) Bumps [nonebot-plugin-alconna](https://github.com/nonebot/plugin-alconna) from 0.31.3 to 0.31.7. - [Release notes](https://github.com/nonebot/plugin-alconna/releases) - [Commits](https://github.com/nonebot/plugin-alconna/compare/v0.31.3...v0.31.7) --- updated-dependencies: - dependency-name: nonebot-plugin-alconna dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ⬆️ Bump ruff from 0.1.3 to 0.1.4 (#190) * ⬆️ Bump httpx from 0.25.0 to 0.25.1 (#188) * ✨ 绑定适配所有平台 * ⬆️ Bump nonebot-plugin-alconna from 0.31.7 to 0.32.0 (#192) Bumps [nonebot-plugin-alconna](https://github.com/nonebot/plugin-alconna) from 0.31.7 to 0.32.0. - [Release notes](https://github.com/nonebot/plugin-alconna/releases) - [Commits](https://github.com/nonebot/plugin-alconna/compare/v0.31.7...v0.32.0) --- updated-dependencies: - dependency-name: nonebot-plugin-alconna dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ♻️ 重构 recorder * ➕ 添加依赖 nonebot-plugin-apscheduler * ⬆️ Bump mypy from 1.6.1 to 1.7.0 (#194) * ⬆️ Bump ruff from 0.1.4 to 0.1.5 (#193) * ✨ 将数据库内存储时间时区切换为UTC * ✨ 添加 iorank 指令 * 🎨 将行长限制改为120 * 🥚 :fkosk: * 🗃️ 迁移旧版本 sqlite 中的数据 * 🚨 添加 type: ignore * ✨ 更新 PluginMetadata * ➖ 移除所有 nonebot-adapter 依赖 * ➖ 移除依赖 aiohttp * ➖ 移除依赖 asyncio (为什么会有这个) * ➕ 添加开发依赖 nonebot-adapter-onebot * ➕ 添加开发依赖 nonebot-adapter-satori * 📝 更新 readme * 🔖 1.0.0.a1 * 🔒️ 修复 Incomplete URL substring sanitization * 🔒️ 修复 Incomplete URL substring sanitization --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1 +0,0 @@
|
||||
from . import config, database, message_analyzer
|
||||
92
nonebot_plugin_tetris_stats/utils/browser.py
Normal file
92
nonebot_plugin_tetris_stats/utils/browser.py
Normal file
@@ -0,0 +1,92 @@
|
||||
import sys
|
||||
from os import environ
|
||||
from platform import system
|
||||
|
||||
from nonebot import get_driver
|
||||
from nonebot.log import logger
|
||||
from playwright.__main__ import main
|
||||
from playwright.async_api import Browser, async_playwright
|
||||
|
||||
driver = get_driver()
|
||||
|
||||
global_config = driver.config
|
||||
|
||||
|
||||
@driver.on_startup
|
||||
async def _():
|
||||
await BrowserManager._init_playwright()
|
||||
|
||||
|
||||
@driver.on_shutdown
|
||||
async def _():
|
||||
await BrowserManager._close_browser()
|
||||
|
||||
|
||||
class BrowserManager:
|
||||
"""浏览器管理类"""
|
||||
|
||||
_browser: Browser | None = None
|
||||
|
||||
@classmethod
|
||||
async def _init_playwright(cls) -> None:
|
||||
if system() == 'Windows' and getattr(global_config, 'fastapi_reload', False):
|
||||
raise ImportError('加载失败, Windows 必须设置 FASTAPI_RELOAD=false 才能正常运行 playwright')
|
||||
logger.info('开始 安装/更新 playwright 浏览器')
|
||||
environ['PLAYWRIGHT_DOWNLOAD_HOST'] = 'https://npmmirror.com/mirrors/playwright/'
|
||||
if cls._handle_error(cls._call_playwright(['', 'install', 'firefox'])):
|
||||
logger.success('安装/更新 playwright 浏览器成功')
|
||||
else:
|
||||
logger.warning('playwright 浏览器 安装/更新 失败, 尝试使用原始仓库下载')
|
||||
del environ['PLAYWRIGHT_DOWNLOAD_HOST']
|
||||
if cls._handle_error(cls._call_playwright(['', 'install', 'firefox'])):
|
||||
logger.success('安装/更新 playwright 浏览器成功')
|
||||
else:
|
||||
logger.error('安装/更新 playwright 浏览器失败')
|
||||
try:
|
||||
await cls._start_browser()
|
||||
except BaseException as e: # noqa: BLE001 不知道会有什么异常, 交给用户解决
|
||||
raise ImportError(
|
||||
'playwright 启动失败, 请尝试在命令行运行 playwright install-deps firefox, 如果仍然启动失败, 请参考上面的报错👆'
|
||||
) from e
|
||||
else:
|
||||
logger.success('playwright 启动成功')
|
||||
|
||||
@classmethod
|
||||
def _call_playwright(cls, argv: list[str]) -> BaseException:
|
||||
"""等价于调用 playwright 的命令行程序"""
|
||||
argv_backup = sys.argv.copy()
|
||||
from re import sub
|
||||
|
||||
sys.argv[0] = sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
|
||||
sys.argv = argv
|
||||
try:
|
||||
main()
|
||||
except BaseException as e: # noqa: BLE001 不在这里处理 playwright 的异常
|
||||
return e
|
||||
finally:
|
||||
sys.argv = argv_backup
|
||||
return SystemExit(0)
|
||||
|
||||
@classmethod
|
||||
def _handle_error(cls, error: BaseException) -> bool:
|
||||
if isinstance(error, SystemExit) and error.code == 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def _start_browser(cls) -> Browser:
|
||||
"""启动浏览器实例"""
|
||||
playwright = await async_playwright().start()
|
||||
cls._browser = await playwright.firefox.launch()
|
||||
return cls._browser
|
||||
|
||||
@classmethod
|
||||
async def get_browser(cls) -> Browser:
|
||||
"""获取浏览器实例"""
|
||||
return cls._browser or await cls._start_browser()
|
||||
|
||||
@classmethod
|
||||
async def _close_browser(cls) -> None:
|
||||
"""关闭浏览器实例"""
|
||||
if isinstance(cls._browser, Browser):
|
||||
await cls._browser.close()
|
||||
@@ -1,7 +0,0 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class Config(BaseModel):
|
||||
'''配置类'''
|
||||
cache_path: str = 'cache/nonebot_plugin_tetris_stats/cache'
|
||||
db_path: str = 'data/nonebot_plugin_tetris_stats/data.db'
|
||||
@@ -1,141 +0,0 @@
|
||||
import datetime
|
||||
import os
|
||||
from asyncio import gather
|
||||
from sqlite3 import Connection, connect
|
||||
|
||||
from nonebot import get_driver
|
||||
from nonebot.log import logger
|
||||
|
||||
from .config import Config
|
||||
|
||||
driver = get_driver()
|
||||
|
||||
config = Config.parse_obj(get_driver().config)
|
||||
|
||||
|
||||
@driver.on_startup
|
||||
async def _():
|
||||
await DataBase.init_db()
|
||||
|
||||
|
||||
@driver.on_shutdown
|
||||
async def _():
|
||||
await DataBase.close_db()
|
||||
|
||||
|
||||
class DataBase():
|
||||
'''数据库交互类'''
|
||||
_db: Connection | None = None
|
||||
|
||||
@classmethod
|
||||
async def init_db(cls) -> Connection:
|
||||
'''初始化数据库'''
|
||||
if not os.path.exists(os.path.dirname(config.db_path)):
|
||||
os.makedirs(os.path.dirname(config.db_path))
|
||||
cls._db = connect(config.db_path)
|
||||
cursor = cls._db.cursor()
|
||||
cursor.execute('''CREATE TABLE IF NOT EXISTS IOBIND
|
||||
(QQ INTEGER NOT NULL,
|
||||
USER TEXT NOT NULL)''')
|
||||
cursor.execute('''CREATE TABLE IF NOT EXISTS TOPBIND
|
||||
(QQ INTEGER NOT NULL,
|
||||
USER TEXT NOT NULL)''')
|
||||
cursor.execute('''CREATE TABLE IF NOT EXISTS IORANK
|
||||
(RANK VARCHAR(2) NOT NULL,
|
||||
TRENDING CHAR(1) NOT NULL,
|
||||
TRLINE FLOAT NOT NULL,
|
||||
PLAYERCOUNT INTEGER NOT NULL,
|
||||
AVGAPM FLOAT NOT NULL,
|
||||
AVGPPS FLOAT NOT NULL,
|
||||
ARGVS FLOAT NOT NULL,
|
||||
DATE TEXT NOT NULL)''')
|
||||
cls._db.commit()
|
||||
logger.info('数据库初始化完成')
|
||||
return cls._db
|
||||
|
||||
@classmethod
|
||||
async def query_rank_info_today(cls, rank: str) -> list | None:
|
||||
'''查询段位信息'''
|
||||
db = await cls._get_db()
|
||||
cursor = db.cursor()
|
||||
cursor.execute('''SELECT TRENDING, TRLINE, PLAYERCOUNT, AVGAPM, AVGPPS, ARGVS, DATE
|
||||
FROM IORANK
|
||||
WHERE RANK = ? AND DATE = ?''', (rank, datetime.date.today()))
|
||||
result = cursor.fetchone()
|
||||
|
||||
if result is None:
|
||||
return None
|
||||
|
||||
return list(result)
|
||||
|
||||
@classmethod
|
||||
async def write_rank_info_today(cls, rank: str, trline: int, playercount: int, avgapm: float, avgpps: float, avgvs: float):
|
||||
'''写入段位信息'''
|
||||
|
||||
db = await cls._get_db()
|
||||
cursor = db.cursor()
|
||||
cursor.execute('''SELECT TRLINE
|
||||
FROM IORANK
|
||||
WHERE RANK = ? AND DATE = ?''', (rank, datetime.date.today() - datetime.timedelta(days=1)))
|
||||
|
||||
result = cursor.fetchone()
|
||||
|
||||
if result is None:
|
||||
trending = '?'
|
||||
elif trline > result[0]:
|
||||
trending = '↑'
|
||||
elif trline == result[0]:
|
||||
trending = '-'
|
||||
elif trline < result[0]:
|
||||
trending = '↓'
|
||||
|
||||
cursor.execute('''INSERT INTO IORANK
|
||||
(RANK, TRENDING, TRLINE, PLAYERCOUNT, AVGAPM, AVGPPS, ARGVS, DATE)
|
||||
VALUES (?,?,?,?,?,?,?,?)''',
|
||||
(rank, trending, trline, playercount, avgapm, avgpps, avgvs, datetime.date.today()))
|
||||
|
||||
db.commit()
|
||||
|
||||
@classmethod
|
||||
async def _get_db(cls) -> Connection:
|
||||
'''获取数据库对象'''
|
||||
return cls._db or await cls.init_db()
|
||||
|
||||
@classmethod
|
||||
async def query_bind_info(cls, qq_number: str | int, game_type: str) -> str | None:
|
||||
'''查询绑定信息'''
|
||||
db = await cls._get_db()
|
||||
cursor = db.cursor()
|
||||
cursor.execute(
|
||||
f'SELECT USER FROM {game_type}BIND WHERE QQ = {qq_number}')
|
||||
user = cursor.fetchone()
|
||||
if user is None:
|
||||
return None
|
||||
return user[0]
|
||||
|
||||
@classmethod
|
||||
async def write_bind_info(cls, qq_number: str | int, user: str, game_type: str) -> str:
|
||||
'''写入绑定信息'''
|
||||
bind_info, db = await gather(
|
||||
cls.query_bind_info(qq_number=qq_number, game_type=game_type),
|
||||
cls._get_db()
|
||||
)
|
||||
cursor = db.cursor()
|
||||
if bind_info is not None:
|
||||
cursor.execute(
|
||||
f'UPDATE {game_type}BIND SET USER = ? WHERE QQ = ?', (user, qq_number))
|
||||
message = '更新成功'
|
||||
elif bind_info is None:
|
||||
cursor.execute(
|
||||
f'INSERT INTO {game_type}BIND (QQ, USER) VALUES (?, ?)', (qq_number, user))
|
||||
message = '绑定成功'
|
||||
else:
|
||||
raise ValueError('预期外行为, 请上报GitHub')
|
||||
db.commit()
|
||||
return message
|
||||
|
||||
@classmethod
|
||||
async def close_db(cls) -> None:
|
||||
'''关闭数据库对象'''
|
||||
if isinstance(cls._db, Connection):
|
||||
cls._db.close()
|
||||
35
nonebot_plugin_tetris_stats/utils/exception.py
Normal file
35
nonebot_plugin_tetris_stats/utils/exception.py
Normal file
@@ -0,0 +1,35 @@
|
||||
class TetrisStatsError(Exception):
|
||||
"""所有 TetrisStats 发生的异常基类"""
|
||||
|
||||
def __init__(self, message: str = ''):
|
||||
self.message = message
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.message
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return self.message
|
||||
|
||||
|
||||
class NeedCatchError(TetrisStatsError):
|
||||
"""需要被捕获的异常基类"""
|
||||
|
||||
|
||||
class DoNotCatchError(TetrisStatsError):
|
||||
"""不应该被捕获的异常基类"""
|
||||
|
||||
|
||||
class RequestError(NeedCatchError):
|
||||
"""请求错误"""
|
||||
|
||||
|
||||
class MessageFormatError(NeedCatchError):
|
||||
"""用户发送的消息格式不正确"""
|
||||
|
||||
|
||||
class DatabaseVersionError(DoNotCatchError):
|
||||
"""数据库版本错误"""
|
||||
|
||||
|
||||
class WhatTheFuckError(DoNotCatchError):
|
||||
"""用于表示不应该出现的情况 ("""
|
||||
@@ -1,91 +0,0 @@
|
||||
from re import match, sub
|
||||
|
||||
|
||||
async def handle_bind_message(message: str, game_type: str) -> tuple[str | None, tuple]:
|
||||
'''返回值为tuple[gameType, tuple[message, user]]'''
|
||||
_cmd_aliases = {'IO': ['io绑定', 'iobind'],
|
||||
'TOP': ['top绑定', 'topbind']}
|
||||
# 剔除命令前缀
|
||||
for i in _cmd_aliases[game_type]:
|
||||
if match(rf'(?i){i}', message):
|
||||
message = sub(rf'(?i){i}', '', message)
|
||||
message = message.strip()
|
||||
break
|
||||
else:
|
||||
raise ValueError('预期外行为, 请上报GitHub')
|
||||
if message == '' or message.isspace():
|
||||
return None, ('用户名为空', None)
|
||||
return await check_name(message, game_type)
|
||||
|
||||
|
||||
async def handle_stats_query_message(message: str, game_type: str) -> tuple[str | None, tuple]:
|
||||
'''返回值为tuple[gameType, tuple[message, user]]'''
|
||||
_cmd_aliases = {'IO': ['io查', 'iostats'],
|
||||
'TOS': ['tos查', 'tostats', 'tosstats', '茶服查', '茶服stats'],
|
||||
'TOP': ['top查', 'topstats']}
|
||||
_me = [
|
||||
'我', '自己', '我等', '卑人', '愚', '老身', '爷', '老娘', '本姑娘', '本大爷', '鄙人', '寡人',
|
||||
'小生', '贫僧', '本人', '孤', '吾', '俺', '咱', '私', 'me', '洒家', '在下', '偶', '人家',
|
||||
'本小姐', '老夫', '老子', '朕', '本尊', '僕', '拙者', '妾', '儂', '自分', '吾輩', '我輩', '某',
|
||||
'己等', '俺等', '此方', '哥', '姐', '劳资', '本宝宝', '余', '本喵', 'watashi', 'i', 'myself',
|
||||
'self', 'oneself'
|
||||
]
|
||||
# 剔除命令前缀
|
||||
for i in _cmd_aliases[game_type]:
|
||||
if match(rf'(?i){i}', message):
|
||||
message = sub(rf'(?i){i}', '', message)
|
||||
message = message.strip()
|
||||
break
|
||||
if message == '' or message.isspace():
|
||||
return None, ('用户名为空', None)
|
||||
if message.startswith('[CQ:at,qq='):
|
||||
try:
|
||||
user = int(str(message).split('[CQ:at,qq=')[1].split(']')[0])
|
||||
except ValueError:
|
||||
return None, ('QQ号码不合法', None)
|
||||
else:
|
||||
return 'AT', (None, user)
|
||||
elif message in _me:
|
||||
# 会不会有人叫本姑娘 本大爷这种或许可以成为id的名字呢
|
||||
# TODO: 在判断是否可能是查自己的情况的时候 也去判断是否能成立为一个UserName
|
||||
return 'ME', (None, None)
|
||||
else:
|
||||
return await check_name(message, game_type)
|
||||
|
||||
|
||||
async def handle_rank_message(message: str) -> str:
|
||||
_cmd_aliases = ['io段位', 'iorank']
|
||||
# 剔除命令前缀
|
||||
for i in _cmd_aliases:
|
||||
if match(rf'(?i){i}', message):
|
||||
message = sub(rf'(?i){i}', '', message)
|
||||
message = message.strip()
|
||||
break
|
||||
else:
|
||||
raise ValueError('预期外行为, 请上报GitHub')
|
||||
return message
|
||||
|
||||
|
||||
async def check_name(name: str, game_type: str) -> tuple[str | None, tuple]:
|
||||
'''返回值为tuple[gameType, tuple[message, user]]'''
|
||||
if game_type == 'IO':
|
||||
if match(r'^[a-f0-9]{24}$', name):
|
||||
return 'ID', (None, name)
|
||||
if match(r'^[a-zA-Z0-9_-]{3,16}$', name):
|
||||
return 'Name', (None, name.lower())
|
||||
return None, ('用户名不合法', None)
|
||||
if game_type == 'TOP':
|
||||
if match(r'^[a-zA-Z0-9_]{1,16}$', name):
|
||||
return 'Name', (None, name)
|
||||
return None, ('用户名不合法', None)
|
||||
if game_type == 'TOS':
|
||||
if (match(r'^(?!\.)(?!com[0-9]$)(?!con$)(?!lpt[0-9]$)(?!nul$)(?!prn$)[^\-][^\+][^\|\*\?\\\s\!:<>/$"]*[^\.\|\*\?\\\s\!:<>/$"]+$', name)
|
||||
and name.isdigit() is False
|
||||
and 2 <= len(name) <= 18):
|
||||
# 虽然我也不想这么长 但是似乎确实得这么长
|
||||
# TODO 简化正则表达式
|
||||
return 'Name', (None, name)
|
||||
if name.isdigit() is True:
|
||||
return 'QQ', (None, name)
|
||||
return None, ('用户名不合法', None)
|
||||
return None, ('游戏类型错误', None)
|
||||
322
nonebot_plugin_tetris_stats/utils/metrics.py
Normal file
322
nonebot_plugin_tetris_stats/utils/metrics.py
Normal file
@@ -0,0 +1,322 @@
|
||||
from typing import overload
|
||||
|
||||
from .typing import Number
|
||||
|
||||
|
||||
class TetrisMetricsBaseWithPPS:
|
||||
def __init__(self, pps: Number, precision: int) -> None:
|
||||
self._pps = pps
|
||||
self.precision = precision
|
||||
|
||||
@property
|
||||
def _lpm(self) -> Number:
|
||||
return self._pps * 24
|
||||
|
||||
@property
|
||||
def lpm(self) -> Number:
|
||||
return round(self._lpm, self.precision)
|
||||
|
||||
@property
|
||||
def pps(self) -> Number:
|
||||
return round(self._pps, self.precision)
|
||||
|
||||
|
||||
class TetrisMetricsBaseWithLPM:
|
||||
def __init__(self, lpm: Number, precision: int) -> None:
|
||||
self._lpm = lpm
|
||||
self.precision = precision
|
||||
|
||||
@property
|
||||
def lpm(self) -> Number:
|
||||
return round(self._lpm, self.precision)
|
||||
|
||||
@property
|
||||
def _pps(self) -> Number:
|
||||
return self._lpm / 24
|
||||
|
||||
@property
|
||||
def pps(self) -> Number:
|
||||
return round(self._pps, self.precision)
|
||||
|
||||
|
||||
class TetrisMetricsBaseWithVS:
|
||||
def __init__(self, vs: Number, precision: int) -> None:
|
||||
self._vs = vs
|
||||
self.precision = precision
|
||||
|
||||
@property
|
||||
def vs(self) -> Number:
|
||||
return round(self._vs, self.precision)
|
||||
|
||||
@property
|
||||
def _adpm(self) -> Number:
|
||||
return self._vs * 0.6
|
||||
|
||||
@property
|
||||
def adpm(self) -> Number:
|
||||
return round(self._adpm, self.precision)
|
||||
|
||||
|
||||
class TetrisMetricsBaseWithADPM:
|
||||
def __init__(self, adpm: Number, precision: int) -> None:
|
||||
self._adpm = adpm
|
||||
self.precision = precision
|
||||
|
||||
@property
|
||||
def _vs(self) -> Number:
|
||||
return self._adpm / 0.6
|
||||
|
||||
@property
|
||||
def vs(self) -> Number:
|
||||
return round(self._vs, self.precision)
|
||||
|
||||
@property
|
||||
def adpm(self) -> Number:
|
||||
return round(self._adpm, self.precision)
|
||||
|
||||
|
||||
class TetrisMetricsBasicWithPPS(TetrisMetricsBaseWithPPS):
|
||||
def __init__(self, pps: Number, apm: Number, precision: int) -> None:
|
||||
super().__init__(pps=pps, precision=precision)
|
||||
self._apm = apm
|
||||
|
||||
@property
|
||||
def apm(self) -> Number:
|
||||
return round(self._apm, self.precision)
|
||||
|
||||
@property
|
||||
def apl(self) -> Number:
|
||||
return round(self._apm / self._lpm, self.precision)
|
||||
|
||||
|
||||
class TetrisMetricsBasicWithLPM(TetrisMetricsBaseWithLPM):
|
||||
def __init__(self, lpm: Number, apm: Number, precision: int):
|
||||
super().__init__(lpm=lpm, precision=precision)
|
||||
self._apm = apm
|
||||
|
||||
@property
|
||||
def apm(self) -> Number:
|
||||
return round(self._apm, self.precision)
|
||||
|
||||
@property
|
||||
def apl(self) -> Number:
|
||||
return round(self._apm / self._lpm, self.precision)
|
||||
|
||||
|
||||
class TetrisMetricsProWithPPSVS(TetrisMetricsBasicWithPPS, TetrisMetricsBaseWithVS):
|
||||
def __init__(self, pps: Number, apm: Number, vs: Number, precision: int) -> None:
|
||||
super().__init__(pps=pps, apm=apm, precision=precision)
|
||||
super(TetrisMetricsBaseWithPPS, self).__init__(vs=vs, precision=precision)
|
||||
|
||||
@property
|
||||
def adpl(self) -> Number:
|
||||
return round(self._adpm / self._lpm, self.precision)
|
||||
|
||||
|
||||
class TetrisMetricsProWithPPSADPM(TetrisMetricsBasicWithPPS, TetrisMetricsBaseWithADPM):
|
||||
def __init__(self, pps: Number, apm: Number, adpm: Number, precision: int) -> None:
|
||||
super().__init__(pps=pps, apm=apm, precision=precision)
|
||||
super(TetrisMetricsBaseWithPPS, self).__init__(adpm=adpm, precision=precision)
|
||||
|
||||
@property
|
||||
def adpl(self) -> Number:
|
||||
return round(self._adpm / self._lpm, self.precision)
|
||||
|
||||
|
||||
class TetrisMetricsProWithLPMVS(TetrisMetricsBasicWithLPM, TetrisMetricsBaseWithVS):
|
||||
def __init__(self, lpm: Number, apm: Number, vs: Number, precision: int) -> None:
|
||||
super().__init__(lpm=lpm, apm=apm, precision=precision)
|
||||
super(TetrisMetricsBaseWithLPM, self).__init__(vs=vs, precision=precision)
|
||||
|
||||
@property
|
||||
def adpl(self) -> Number:
|
||||
return round(self._adpm / self._lpm, self.precision)
|
||||
|
||||
|
||||
class TetrisMetricsProWithLPMADPM(TetrisMetricsBasicWithLPM, TetrisMetricsBaseWithADPM):
|
||||
def __init__(self, lpm: Number, apm: Number, adpm: Number, precision: int) -> None:
|
||||
super().__init__(lpm=lpm, apm=apm, precision=precision)
|
||||
super(TetrisMetricsBaseWithLPM, self).__init__(adpm=adpm, precision=precision)
|
||||
|
||||
@property
|
||||
def adpl(self) -> Number:
|
||||
return round(self._adpm / self._lpm, self.precision)
|
||||
|
||||
|
||||
@overload
|
||||
def get_metrics( # noqa: PLR0913
|
||||
*,
|
||||
pps: Number,
|
||||
lpm: None = None,
|
||||
apm: None = None,
|
||||
vs: None = None,
|
||||
adpm: None = None,
|
||||
precision: int = 2,
|
||||
) -> TetrisMetricsBaseWithPPS:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def get_metrics( # noqa: PLR0913
|
||||
*,
|
||||
pps: None = None,
|
||||
lpm: Number,
|
||||
apm: None = None,
|
||||
vs: None = None,
|
||||
adpm: None = None,
|
||||
precision: int = 2,
|
||||
) -> TetrisMetricsBaseWithLPM:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def get_metrics( # noqa: PLR0913
|
||||
*,
|
||||
pps: None = None,
|
||||
lpm: None = None,
|
||||
apm: None = None,
|
||||
vs: Number,
|
||||
adpm: None = None,
|
||||
precision: int = 2,
|
||||
) -> TetrisMetricsBaseWithVS:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def get_metrics( # noqa: PLR0913
|
||||
*,
|
||||
pps: None = None,
|
||||
lpm: None = None,
|
||||
apm: None = None,
|
||||
vs: None = None,
|
||||
adpm: Number,
|
||||
precision: int = 2,
|
||||
) -> TetrisMetricsBaseWithADPM:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def get_metrics( # noqa: PLR0913
|
||||
*,
|
||||
pps: Number,
|
||||
lpm: None = None,
|
||||
apm: Number,
|
||||
vs: None = None,
|
||||
adpm: None = None,
|
||||
precision: int = 2,
|
||||
) -> TetrisMetricsBasicWithPPS:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def get_metrics( # noqa: PLR0913
|
||||
*,
|
||||
pps: None = None,
|
||||
lpm: Number,
|
||||
apm: Number,
|
||||
vs: None = None,
|
||||
adpm: None = None,
|
||||
precision: int = 2,
|
||||
) -> TetrisMetricsBasicWithLPM:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def get_metrics( # noqa: PLR0913
|
||||
*,
|
||||
pps: Number,
|
||||
lpm: None = None,
|
||||
apm: Number,
|
||||
vs: Number,
|
||||
adpm: None = None,
|
||||
precision: int = 2,
|
||||
) -> TetrisMetricsProWithPPSVS:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def get_metrics( # noqa: PLR0913
|
||||
*,
|
||||
pps: Number,
|
||||
lpm: None = None,
|
||||
apm: Number,
|
||||
vs: None = None,
|
||||
adpm: Number,
|
||||
precision: int = 2,
|
||||
) -> TetrisMetricsProWithPPSADPM:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def get_metrics( # noqa: PLR0913
|
||||
*,
|
||||
pps: None = None,
|
||||
lpm: Number,
|
||||
apm: Number,
|
||||
vs: Number,
|
||||
adpm: None = None,
|
||||
precision: int = 2,
|
||||
) -> TetrisMetricsProWithLPMVS:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def get_metrics( # noqa: PLR0913
|
||||
*,
|
||||
pps: None = None,
|
||||
lpm: Number,
|
||||
apm: Number,
|
||||
vs: None = None,
|
||||
adpm: Number,
|
||||
precision: int = 2,
|
||||
) -> TetrisMetricsProWithLPMADPM:
|
||||
...
|
||||
|
||||
|
||||
def get_metrics( # noqa: PLR0911, PLR0912, PLR0913
|
||||
*,
|
||||
pps: Number | None = None,
|
||||
lpm: Number | None = None,
|
||||
apm: Number | None = None,
|
||||
vs: Number | None = None,
|
||||
adpm: Number | None = None,
|
||||
precision: int = 2,
|
||||
) -> (
|
||||
TetrisMetricsBaseWithPPS
|
||||
| TetrisMetricsBaseWithLPM
|
||||
| TetrisMetricsBaseWithVS
|
||||
| TetrisMetricsBaseWithADPM
|
||||
| TetrisMetricsBasicWithPPS
|
||||
| TetrisMetricsBasicWithLPM
|
||||
| TetrisMetricsProWithPPSVS
|
||||
| TetrisMetricsProWithLPMVS
|
||||
| TetrisMetricsProWithPPSADPM
|
||||
| TetrisMetricsProWithLPMADPM
|
||||
):
|
||||
if apm is None:
|
||||
if pps is not None:
|
||||
return TetrisMetricsBaseWithPPS(pps, precision=precision)
|
||||
if lpm is not None:
|
||||
return TetrisMetricsBaseWithLPM(lpm, precision=precision)
|
||||
if vs is not None:
|
||||
return TetrisMetricsBaseWithVS(vs, precision=precision)
|
||||
if adpm is not None:
|
||||
return TetrisMetricsBaseWithADPM(adpm, precision=precision)
|
||||
elif vs is None and adpm is None:
|
||||
if pps is not None:
|
||||
return TetrisMetricsBasicWithPPS(pps, apm, precision=precision)
|
||||
if lpm is not None:
|
||||
return TetrisMetricsBasicWithLPM(lpm, apm, precision=precision)
|
||||
else:
|
||||
if vs is not None:
|
||||
if pps is not None:
|
||||
return TetrisMetricsProWithPPSVS(pps, apm, vs, precision=precision)
|
||||
if lpm is not None:
|
||||
return TetrisMetricsProWithLPMVS(lpm, apm, vs, precision=precision)
|
||||
if adpm is not None:
|
||||
if pps is not None:
|
||||
return TetrisMetricsProWithPPSADPM(pps, apm, adpm, precision=precision)
|
||||
if lpm is not None:
|
||||
return TetrisMetricsProWithLPMADPM(lpm, apm, adpm, precision=precision)
|
||||
|
||||
raise TypeError
|
||||
19
nonebot_plugin_tetris_stats/utils/platform.py
Normal file
19
nonebot_plugin_tetris_stats/utils/platform.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from nonebot.adapters import Bot
|
||||
|
||||
|
||||
def get_platform(bot: Bot) -> str:
|
||||
try:
|
||||
from nonebot.adapters.onebot.v12 import Bot as OB12Bot
|
||||
|
||||
if isinstance(bot, OB12Bot):
|
||||
return bot.platform
|
||||
except ImportError:
|
||||
pass
|
||||
try:
|
||||
from nonebot.adapters.satori import Bot as SaBot
|
||||
|
||||
if isinstance(bot, SaBot):
|
||||
return bot.platform
|
||||
except ImportError:
|
||||
pass
|
||||
return bot.type
|
||||
79
nonebot_plugin_tetris_stats/utils/recorder.py
Normal file
79
nonebot_plugin_tetris_stats/utils/recorder.py
Normal file
@@ -0,0 +1,79 @@
|
||||
from datetime import UTC, datetime
|
||||
from typing import ClassVar
|
||||
|
||||
from nonebot import get_driver, get_plugin
|
||||
from nonebot.adapters import Bot, Event
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.message import run_postprocessor, run_preprocessor
|
||||
from nonebot_plugin_orm import get_session
|
||||
|
||||
from ..db.models import HistoricalData
|
||||
|
||||
driver = get_driver()
|
||||
|
||||
|
||||
class Recorder:
|
||||
matchers: ClassVar[set[type[Matcher]]] = set()
|
||||
historical_data: ClassVar[dict[int, tuple[HistoricalData, bool]]] = {}
|
||||
|
||||
@classmethod
|
||||
def create_historical_data(cls, event_id: int, historical_data: HistoricalData) -> None:
|
||||
cls.historical_data[event_id] = (historical_data, False)
|
||||
|
||||
@classmethod
|
||||
def update_historical_data(cls, event_id: int, historical_data: HistoricalData) -> None:
|
||||
if event_id not in cls.historical_data:
|
||||
raise KeyError
|
||||
cls.historical_data[event_id] = (historical_data, True)
|
||||
|
||||
@classmethod
|
||||
def get_historical_data(cls, event_id: int) -> HistoricalData:
|
||||
return cls.historical_data[event_id][0]
|
||||
|
||||
@classmethod
|
||||
async def save_historical_data(cls, event_id: int) -> None:
|
||||
if event_id not in cls.historical_data:
|
||||
raise KeyError
|
||||
historical_data, completed = cls.historical_data.pop(event_id)
|
||||
if completed:
|
||||
async with get_session() as session:
|
||||
session.add(historical_data)
|
||||
await session.commit()
|
||||
|
||||
@classmethod
|
||||
def del_historical_data(cls, event_id: int) -> None:
|
||||
cls.historical_data.pop(event_id)
|
||||
|
||||
|
||||
@driver.on_startup
|
||||
def _():
|
||||
plugin = get_plugin('nonebot_plugin_tetris_stats')
|
||||
if plugin is not None:
|
||||
Recorder.matchers = plugin.matcher
|
||||
else:
|
||||
raise RuntimeError('获取不到自身插件对象')
|
||||
|
||||
|
||||
@run_preprocessor
|
||||
def _(bot: Bot, event: Event, matcher: Matcher):
|
||||
if isinstance(matcher, tuple(Recorder.matchers)):
|
||||
Recorder.create_historical_data(
|
||||
event_id=id(event),
|
||||
historical_data=HistoricalData(
|
||||
trigger_time=datetime.now(tz=UTC),
|
||||
bot_platform=bot.type,
|
||||
bot_account=bot.self_id,
|
||||
source_type=event.get_type(),
|
||||
source_account=event.get_session_id(),
|
||||
message=event.get_message(),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@run_postprocessor
|
||||
async def _(event: Event, matcher: Matcher, exception: Exception | None):
|
||||
if isinstance(matcher, tuple(Recorder.matchers)):
|
||||
if exception is not None:
|
||||
Recorder.del_historical_data(id(event))
|
||||
else:
|
||||
await Recorder.save_historical_data(id(event))
|
||||
128
nonebot_plugin_tetris_stats/utils/request.py
Normal file
128
nonebot_plugin_tetris_stats/utils/request.py
Normal file
@@ -0,0 +1,128 @@
|
||||
from urllib.parse import urljoin, urlparse
|
||||
|
||||
from aiofiles import open
|
||||
from httpx import AsyncClient, HTTPError
|
||||
from nonebot import get_driver
|
||||
from nonebot.log import logger
|
||||
from playwright.async_api import Response
|
||||
from ujson import JSONDecodeError, dumps, loads
|
||||
|
||||
from ..config.config import CACHE_PATH
|
||||
from .browser import BrowserManager
|
||||
from .exception import RequestError
|
||||
|
||||
driver = get_driver()
|
||||
|
||||
|
||||
@driver.on_startup
|
||||
async def _():
|
||||
await Request._init_cache()
|
||||
await Request._read_cache()
|
||||
|
||||
|
||||
@driver.on_shutdown
|
||||
async def _():
|
||||
await Request._write_cache()
|
||||
|
||||
|
||||
def splice_url(url_list: list[str]) -> str:
|
||||
url = ''
|
||||
if len(url_list):
|
||||
url = url_list.pop(0)
|
||||
for i in url_list:
|
||||
url = urljoin(url, i)
|
||||
return url
|
||||
|
||||
|
||||
class Request:
|
||||
"""网络请求相关类"""
|
||||
|
||||
_CACHE_FILE = CACHE_PATH.joinpath('cloudflare_cache.json')
|
||||
_headers: dict | None = None
|
||||
_cookies: dict | None = None
|
||||
|
||||
@classmethod
|
||||
async def _anti_cloudflare(cls, url: str) -> bytes:
|
||||
"""用firefox硬穿五秒盾"""
|
||||
browser = await BrowserManager.get_browser()
|
||||
context = await browser.new_context()
|
||||
page = await context.new_page()
|
||||
response = await page.goto(url)
|
||||
attempts = 0
|
||||
while attempts < 60: # noqa: PLR2004
|
||||
attempts += 1
|
||||
text = await page.locator('body').text_content()
|
||||
if text is None:
|
||||
await page.wait_for_timeout(1000)
|
||||
continue
|
||||
if await page.title() == 'Please Wait... | Cloudflare':
|
||||
logger.warning('疑似触发了 Cloudflare 的验证码')
|
||||
break
|
||||
try:
|
||||
loads(text)
|
||||
except JSONDecodeError:
|
||||
await page.wait_for_timeout(1000)
|
||||
else:
|
||||
if not isinstance(response, Response):
|
||||
raise RequestError('api请求失败')
|
||||
cls._headers = await response.request.all_headers()
|
||||
try:
|
||||
cls._cookies = {i['name']: i['value'] for i in await context.cookies()}
|
||||
except KeyError:
|
||||
cls._cookies = None
|
||||
await page.close()
|
||||
await context.close()
|
||||
return await response.body()
|
||||
await page.close()
|
||||
await context.close()
|
||||
raise RequestError('绕过五秒盾失败')
|
||||
|
||||
@classmethod
|
||||
async def _init_cache(cls) -> None:
|
||||
"""初始化缓存文件"""
|
||||
if not cls._CACHE_FILE.exists():
|
||||
async with open(file=cls._CACHE_FILE, mode='w', encoding='UTF-8') as file:
|
||||
await file.write(dumps({'headers': cls._headers, 'cookies': cls._cookies}))
|
||||
|
||||
@classmethod
|
||||
async def _read_cache(cls) -> None:
|
||||
"""读取缓存文件"""
|
||||
try:
|
||||
async with open(file=cls._CACHE_FILE, mode='r', encoding='UTF-8') as file:
|
||||
json = loads(await file.read())
|
||||
except FileNotFoundError:
|
||||
await cls._init_cache()
|
||||
except (PermissionError, JSONDecodeError):
|
||||
cls._CACHE_FILE.unlink()
|
||||
await cls._init_cache()
|
||||
else:
|
||||
cls._headers = json['headers']
|
||||
cls._cookies = json['cookies']
|
||||
|
||||
@classmethod
|
||||
async def _write_cache(cls) -> None:
|
||||
"""写入缓存文件"""
|
||||
try:
|
||||
async with open(file=cls._CACHE_FILE, mode='r+', encoding='UTF-8') as file:
|
||||
await file.write(dumps({'headers': cls._headers, 'cookies': cls._cookies}))
|
||||
except FileNotFoundError:
|
||||
await cls._init_cache()
|
||||
except (PermissionError, JSONDecodeError):
|
||||
cls._CACHE_FILE.unlink()
|
||||
await cls._init_cache()
|
||||
|
||||
@classmethod
|
||||
async def request(cls, url: str, *, is_json: bool = True) -> bytes:
|
||||
"""请求api"""
|
||||
try:
|
||||
async with AsyncClient(cookies=cls._cookies) as session:
|
||||
response = await session.get(url, headers=cls._headers)
|
||||
if is_json:
|
||||
loads(response.content)
|
||||
return response.content
|
||||
except HTTPError as e:
|
||||
raise RequestError(f'请求错误\n{e!r}') from e
|
||||
except JSONDecodeError:
|
||||
if urlparse(url).netloc.lower().endswith('tetr.io'):
|
||||
return await cls._anti_cloudflare(url)
|
||||
raise
|
||||
61
nonebot_plugin_tetris_stats/utils/typing.py
Normal file
61
nonebot_plugin_tetris_stats/utils/typing.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from collections.abc import Awaitable, Callable
|
||||
from typing import Any, Literal
|
||||
|
||||
Number = int | float
|
||||
GameType = Literal['IO', 'TOP', 'TOS']
|
||||
CommandType = Literal['bind', 'query']
|
||||
AsyncCallable = Callable[..., Awaitable[Any]]
|
||||
Me = Literal[
|
||||
'我',
|
||||
'自己',
|
||||
'我等',
|
||||
'卑人',
|
||||
'愚',
|
||||
'老身',
|
||||
'爷',
|
||||
'老娘',
|
||||
'本姑娘',
|
||||
'本大爷',
|
||||
'鄙人',
|
||||
'寡人',
|
||||
'小生',
|
||||
'贫僧',
|
||||
'本人',
|
||||
'孤',
|
||||
'吾',
|
||||
'俺',
|
||||
'咱',
|
||||
'私',
|
||||
'me',
|
||||
'洒家',
|
||||
'在下',
|
||||
'偶',
|
||||
'人家',
|
||||
'本小姐',
|
||||
'老夫',
|
||||
'老子',
|
||||
'朕',
|
||||
'本尊',
|
||||
'僕',
|
||||
'拙者',
|
||||
'妾',
|
||||
'儂',
|
||||
'自分',
|
||||
'吾輩',
|
||||
'我輩',
|
||||
'某',
|
||||
'己等',
|
||||
'俺等',
|
||||
'此方',
|
||||
'哥',
|
||||
'姐',
|
||||
'劳资',
|
||||
'本宝宝',
|
||||
'余',
|
||||
'本喵',
|
||||
'watashi',
|
||||
'i',
|
||||
'myself',
|
||||
'self',
|
||||
'oneself',
|
||||
]
|
||||
Reference in New Issue
Block a user