Compare commits

..

88 Commits
0.3.2 ... 0.4.1

Author SHA1 Message Date
scdhh
f600060b9e 🔖 0.4.1 2023-05-31 06:23:39 +08:00
渣渣120
a808bfb7f8 🐛 修复趋势对比错误的数据 (#123) 2023-05-31 06:22:42 +08:00
e5354d39c9 🔖 0.4.0.post1 2023-05-30 06:14:58 +08:00
9d37d05b24 💬 小改段位查询消息样式 2023-05-30 06:08:39 +08:00
d7b6e3cb17 🔖 0.4.0 2023-05-30 04:59:33 +08:00
渣渣120
32d34c93d7 新增查分段指令 (#121)
* 忽略 .idea 文件夹

* 新增查分段指令

* 修复未知段位可能导致程序无限死循环的异常

* 我 keys 呢

* 🎨 整理 import

* 🎨 规范引号

* 🐛 记得await

* ️ 一些优化

* 🐛 多个逗号

* 🚨 修正typing hint

* 🐛 返回值是 tuple 哦

* 🐛 少个逗号

* 🐛 你得删前缀啊

* 🐛 怎么能用 is 呢

* 🐛 记得await

* 试图匹配查询格式

* 💬 小改返回消息样式

* 🎨 修改变量名

* 🐛 修复查询大写问题

* 🐛 使用 get_db 获取数据库对象

---------

Co-authored-by: scdhh <wallfjjd@gmail.com>
2023-05-30 04:57:31 +08:00
972f7e90d2 🔖 0.3.3.post1 2023-02-15 07:52:04 +08:00
dependabot[bot]
fe412d5acd ⬆️ Bump starlette from 0.22.0 to 0.25.0 (#83)
Bumps [starlette](https://github.com/encode/starlette) from 0.22.0 to 0.25.0.
- [Release notes](https://github.com/encode/starlette/releases)
- [Changelog](https://github.com/encode/starlette/blob/master/docs/release-notes.md)
- [Commits](https://github.com/encode/starlette/compare/0.22.0...0.25.0)

---
updated-dependencies:
- dependency-name: starlette
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-15 07:37:31 +08:00
scdhh
ac8d332e69 👷 更改 dependabot 推送分支 2023-01-29 04:56:47 +08:00
2015917ca0 版本推进 2022-12-25 14:59:45 +08:00
dependabot[bot]
264c5c04e9 Bump playwright from 1.28.0 to 1.29.0 (#55)
Bumps [playwright](https://github.com/Microsoft/playwright-python) from 1.28.0 to 1.29.0.
- [Release notes](https://github.com/Microsoft/playwright-python/releases)
- [Commits](https://github.com/Microsoft/playwright-python/compare/v1.28.0...v1.29.0)

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-25 14:54:45 +08:00
14d646a2d0 允许使用python3.11 2022-12-20 13:26:35 +08:00
dependabot[bot]
d2a33ec5f8 Bump pandas-stubs from 1.5.1.221024 to 1.5.2.221213 (#53) 2022-12-20 04:16:50 +00:00
dependabot[bot]
c4c0faf64b Bump nonebot2 from 2.0.0rc1 to 2.0.0rc2 (#48) 2022-12-20 04:16:01 +00:00
dependabot[bot]
a8e769866f Bump pandas from 1.5.1 to 1.5.2 (#46)
Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/pandas-dev/pandas/releases)
- [Changelog](https://github.com/pandas-dev/pandas/blob/main/RELEASE.md)
- [Commits](https://github.com/pandas-dev/pandas/compare/v1.5.1...v1.5.2)

---
updated-dependencies:
- dependency-name: pandas
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-20 12:02:41 +08:00
dependabot[bot]
38595d46b9 Bump ujson from 5.5.0 to 5.6.0 (#51)
Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.5.0 to 5.6.0.
- [Release notes](https://github.com/ultrajson/ultrajson/releases)
- [Commits](https://github.com/ultrajson/ultrajson/compare/5.5.0...5.6.0)

---
updated-dependencies:
- dependency-name: ujson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-20 12:02:13 +08:00
scdhh
bd08166f45 Merge pull request #54 from shoucandanghehe/dependabot/pip/pylint-2.15.9
Bump pylint from 2.15.5 to 2.15.9
2022-12-20 12:01:34 +08:00
dependabot[bot]
5b1e2a1e28 Bump pylint from 2.15.5 to 2.15.9
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.15.5 to 2.15.9.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.15.5...v2.15.9)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 15:17:51 +00:00
scdhh
903fe34302 Merge pull request #45 from shoucandanghehe/dependabot/pip/playwright-1.28.0
Bump playwright from 1.27.1 to 1.28.0
2022-11-18 10:25:40 +08:00
scdhh
0ea597809f Merge pull request #44 from shoucandanghehe/dependabot/pip/mypy-0.991
Bump mypy from 0.990 to 0.991
2022-11-18 10:25:29 +08:00
dependabot[bot]
58b4c8ab9a Bump playwright from 1.27.1 to 1.28.0
Bumps [playwright](https://github.com/Microsoft/playwright-python) from 1.27.1 to 1.28.0.
- [Release notes](https://github.com/Microsoft/playwright-python/releases)
- [Commits](https://github.com/Microsoft/playwright-python/compare/v1.27.1...v1.28.0)

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-17 15:24:30 +00:00
dependabot[bot]
e82a9d4747 Bump mypy from 0.990 to 0.991
Bumps [mypy](https://github.com/python/mypy) from 0.990 to 0.991.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.990...v0.991)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-16 15:21:47 +00:00
scdhh
6125190fe0 Merge pull request #43 from shoucandanghehe/dependabot/pip/mypy-0.990
Bump mypy from 0.982 to 0.990
2022-11-08 23:32:13 +08:00
dependabot[bot]
402c30b32a Bump mypy from 0.982 to 0.990
Bumps [mypy](https://github.com/python/mypy) from 0.982 to 0.990.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.982...v0.990)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-08 15:14:02 +00:00
scdhh
4d51afa726 Merge pull request #42 from shoucandanghehe/dependabot/pip/autopep8-2.0.0
Bump autopep8 from 1.7.0 to 2.0.0
2022-11-02 08:53:18 +08:00
dependabot[bot]
4af6170470 Bump autopep8 from 1.7.0 to 2.0.0
Bumps [autopep8](https://github.com/hhatto/autopep8) from 1.7.0 to 2.0.0.
- [Release notes](https://github.com/hhatto/autopep8/releases)
- [Commits](https://github.com/hhatto/autopep8/compare/v1.7.0...v2.0.0)

---
updated-dependencies:
- dependency-name: autopep8
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-02 00:49:14 +00:00
scdhh
98244eed60 Merge pull request #40 from shoucandanghehe/dependabot/pip/pandas-stubs-1.5.1.221024
Bump pandas-stubs from 1.5.0.221012 to 1.5.1.221024
2022-11-02 08:45:54 +08:00
dependabot[bot]
2e222ed6f5 Bump pandas-stubs from 1.5.0.221012 to 1.5.1.221024
Bumps [pandas-stubs](https://github.com/pandas-dev/pandas-stubs) from 1.5.0.221012 to 1.5.1.221024.
- [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.0.221012...v1.5.1.221024)

---
updated-dependencies:
- dependency-name: pandas-stubs
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-02 00:42:33 +00:00
scdhh
c224a0f880 Merge pull request #39 from shoucandanghehe/dependabot/pip/pylint-2.15.5
Bump pylint from 2.15.4 to 2.15.5
2022-11-02 08:39:06 +08:00
dependabot[bot]
7df6cb3396 Bump pylint from 2.15.4 to 2.15.5
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.15.4 to 2.15.5.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.15.4...v2.15.5)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-24 16:34:20 +00:00
scdhh
ee9da6a5e8 Merge pull request #38 from shoucandanghehe/dependabot/pip/nonebot-adapter-onebot-2.1.5
Bump nonebot-adapter-onebot from 2.1.3 to 2.1.5
2022-10-24 00:37:12 +08:00
scdhh
cc3a53aa3b Merge pull request #37 from shoucandanghehe/dependabot/pip/pandas-1.5.1
Bump pandas from 1.5.0 to 1.5.1
2022-10-24 00:36:49 +08:00
scdhh
ea767291a2 Merge pull request #35 from shoucandanghehe/dependabot/pip/playwright-1.27.1
Bump playwright from 1.26.1 to 1.27.1
2022-10-24 00:36:39 +08:00
scdhh
cffe472ad3 Merge pull request #34 from shoucandanghehe/dependabot/pip/pandas-stubs-1.5.0.221012
Bump pandas-stubs from 1.5.0.221003 to 1.5.0.221012
2022-10-24 00:36:29 +08:00
scdhh
6e6b16c6f3 Merge pull request #31 from shoucandanghehe/dependabot/pip/pylint-2.15.4
Bump pylint from 2.15.3 to 2.15.4
2022-10-24 00:36:14 +08:00
dependabot[bot]
bdb0139cf1 Bump nonebot-adapter-onebot from 2.1.3 to 2.1.5
Bumps [nonebot-adapter-onebot](https://github.com/nonebot/adapter-onebot) from 2.1.3 to 2.1.5.
- [Release notes](https://github.com/nonebot/adapter-onebot/releases)
- [Commits](https://github.com/nonebot/adapter-onebot/compare/v2.1.3...v2.1.5)

---
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>
2022-10-20 15:52:02 +00:00
dependabot[bot]
ad9c7b24a6 Bump pandas from 1.5.0 to 1.5.1
Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.5.0 to 1.5.1.
- [Release notes](https://github.com/pandas-dev/pandas/releases)
- [Changelog](https://github.com/pandas-dev/pandas/blob/main/RELEASE.md)
- [Commits](https://github.com/pandas-dev/pandas/compare/v1.5.0...v1.5.1)

---
updated-dependencies:
- dependency-name: pandas
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-19 15:49:58 +00:00
dependabot[bot]
6285900e16 Bump playwright from 1.26.1 to 1.27.1
Bumps [playwright](https://github.com/Microsoft/playwright-python) from 1.26.1 to 1.27.1.
- [Release notes](https://github.com/Microsoft/playwright-python/releases)
- [Commits](https://github.com/Microsoft/playwright-python/compare/v1.26.1...v1.27.1)

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-13 16:13:02 +00:00
dependabot[bot]
a1d882c122 Bump pandas-stubs from 1.5.0.221003 to 1.5.0.221012
Bumps [pandas-stubs](https://github.com/pandas-dev/pandas-stubs) from 1.5.0.221003 to 1.5.0.221012.
- [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.0.221003...v1.5.0.221012)

---
updated-dependencies:
- dependency-name: pandas-stubs
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-12 15:47:18 +00:00
dependabot[bot]
f6d5be7cc0 Bump pylint from 2.15.3 to 2.15.4
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.15.3 to 2.15.4.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.15.3...v2.15.4)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-10 16:44:25 +00:00
09e18c526a 整理代码 2022-10-09 13:37:16 +08:00
af8fa05394 补回查bot本身的特判 2022-10-09 13:20:19 +08:00
scdhh
e099beeb6b Merge pull request #29 from shoucandanghehe/dependabot/pip/mypy-0.982
Bump mypy from 0.981 to 0.982
2022-10-09 08:55:37 +08:00
scdhh
5f8f8b67b2 Merge pull request #30 from shoucandanghehe/dependabot/pip/pandas-stubs-1.5.0.221003
Bump pandas-stubs from 1.5.0.220926 to 1.5.0.221003
2022-10-09 08:55:11 +08:00
scdhh
a0b6c85637 Merge pull request #28 from shoucandanghehe/dependabot/pip/nonebot2-2.0.0rc1
Bump nonebot2 from 2.0.0b5 to 2.0.0rc1
2022-10-09 08:54:57 +08:00
scdhh
163f0e139a Merge pull request #27 from shoucandanghehe/dependabot/pip/playwright-1.26.1
Bump playwright from 1.26.0 to 1.26.1
2022-10-09 08:54:44 +08:00
dependabot[bot]
9a02eb5cce Bump pandas-stubs from 1.5.0.220926 to 1.5.0.221003
Bumps [pandas-stubs](https://github.com/pandas-dev/pandas-stubs) from 1.5.0.220926 to 1.5.0.221003.
- [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.0.220926...v1.5.0.221003)

---
updated-dependencies:
- dependency-name: pandas-stubs
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-03 15:51:59 +00:00
dependabot[bot]
2f9849c74e Bump mypy from 0.981 to 0.982
Bumps [mypy](https://github.com/python/mypy) from 0.981 to 0.982.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.981...v0.982)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-03 15:51:25 +00:00
dependabot[bot]
650dfb0669 Bump nonebot2 from 2.0.0b5 to 2.0.0rc1
Bumps [nonebot2](https://github.com/nonebot/nonebot2) from 2.0.0b5 to 2.0.0rc1.
- [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.0-beta.5...v2.0.0-rc.1)

---
updated-dependencies:
- dependency-name: nonebot2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-03 15:50:51 +00:00
dependabot[bot]
a0e0ff2fa3 Bump playwright from 1.26.0 to 1.26.1
Bumps [playwright](https://github.com/Microsoft/playwright-python) from 1.26.0 to 1.26.1.
- [Release notes](https://github.com/Microsoft/playwright-python/releases)
- [Commits](https://github.com/Microsoft/playwright-python/compare/v1.26.0...v1.26.1)

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-29 16:14:50 +00:00
scdhh
f5188594f1 Merge pull request #24 from shoucandanghehe/dependabot/pip/mypy-0.981
Bump mypy from 0.971 to 0.981
2022-09-28 09:35:40 +08:00
scdhh
26374a96fb Merge pull request #25 from shoucandanghehe/dependabot/pip/playwright-1.26.0
Bump playwright from 1.25.2 to 1.26.0
2022-09-28 09:35:31 +08:00
scdhh
67ccf465ce Merge pull request #26 from shoucandanghehe/dependabot/pip/aiohttp-3.8.3
Bump aiohttp from 3.8.1 to 3.8.3
2022-09-28 09:35:22 +08:00
dependabot[bot]
6bcde5cf74 Bump playwright from 1.25.2 to 1.26.0
Bumps [playwright](https://github.com/Microsoft/playwright-python) from 1.25.2 to 1.26.0.
- [Release notes](https://github.com/Microsoft/playwright-python/releases)
- [Commits](https://github.com/Microsoft/playwright-python/compare/v1.25.2...v1.26.0)

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-28 01:31:49 +00:00
dependabot[bot]
1fffa560fb Bump aiohttp from 3.8.1 to 3.8.3
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.8.1 to 3.8.3.
- [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.1...v3.8.3)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-28 01:31:49 +00:00
dependabot[bot]
d995bfe74f Bump mypy from 0.971 to 0.981
Bumps [mypy](https://github.com/python/mypy) from 0.971 to 0.981.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.971...v0.981)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-28 01:31:44 +00:00
scdhh
9437d99ec4 Merge pull request #18 from shoucandanghehe/dependabot/pip/types-ujson-5.5.0
Bump types-ujson from 5.4.0 to 5.5.0
2022-09-28 09:28:24 +08:00
dependabot[bot]
4aed7862a3 Bump types-ujson from 5.4.0 to 5.5.0
Bumps [types-ujson](https://github.com/python/typeshed) from 5.4.0 to 5.5.0.
- [Release notes](https://github.com/python/typeshed/releases)
- [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>
2022-09-28 01:22:32 +00:00
scdhh
8ee6648d2a Merge pull request #19 from shoucandanghehe/dependabot/pip/ujson-5.5.0
Bump ujson from 5.4.0 to 5.5.0
2022-09-28 09:16:50 +08:00
scdhh
1e0ca7149d Merge pull request #20 from shoucandanghehe/dependabot/pip/pandas-1.5.0
Bump pandas from 1.4.4 to 1.5.0
2022-09-28 09:16:33 +08:00
scdhh
dafb4352fa Merge pull request #21 from shoucandanghehe/dependabot/pip/pylint-2.15.3
Bump pylint from 2.15.0 to 2.15.3
2022-09-28 09:16:20 +08:00
dependabot[bot]
ae74cdbc0c Bump pandas from 1.4.4 to 1.5.0
Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.4.4 to 1.5.0.
- [Release notes](https://github.com/pandas-dev/pandas/releases)
- [Changelog](https://github.com/pandas-dev/pandas/blob/main/RELEASE.md)
- [Commits](https://github.com/pandas-dev/pandas/compare/v1.4.4...v1.5.0)

---
updated-dependencies:
- dependency-name: pandas
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-28 01:08:28 +00:00
dependabot[bot]
364717f049 Bump ujson from 5.4.0 to 5.5.0
Bumps [ujson](https://github.com/ultrajson/ultrajson) from 5.4.0 to 5.5.0.
- [Release notes](https://github.com/ultrajson/ultrajson/releases)
- [Commits](https://github.com/ultrajson/ultrajson/compare/5.4.0...5.5.0)

---
updated-dependencies:
- dependency-name: ujson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-28 01:08:04 +00:00
dependabot[bot]
a05260ba4a Bump pylint from 2.15.0 to 2.15.3
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.15.0 to 2.15.3.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.15.0...v2.15.3)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-28 01:07:52 +00:00
scdhh
a80d9586ff Merge pull request #23 from shoucandanghehe/dependabot/pip/pandas-stubs-1.5.0.220926
Bump pandas-stubs from 1.4.4.220906 to 1.5.0.220926
2022-09-28 09:04:42 +08:00
d0a0baa275 拆分io部分 2022-09-28 09:04:21 +08:00
dependabot[bot]
625fc895ea Bump pandas-stubs from 1.4.4.220906 to 1.5.0.220926
Bumps [pandas-stubs](https://github.com/pandas-dev/pandas-stubs) from 1.4.4.220906 to 1.5.0.220926.
- [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.4.4.220906...v1.5.0.220926)

---
updated-dependencies:
- dependency-name: pandas-stubs
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-26 15:57:19 +00:00
scdhh
3b12d74193 Merge pull request #15 from shoucandanghehe/dependabot/pip/pandas-stubs-1.4.4.220906
Bump pandas-stubs from 1.4.3.220829 to 1.4.4.220906
2022-09-07 01:14:45 +08:00
scdhh
359f3964fb Merge pull request #14 from shoucandanghehe/dependabot/pip/pandas-1.4.4
Bump pandas from 1.4.3 to 1.4.4
2022-09-07 01:14:36 +08:00
dependabot[bot]
e655737935 Bump pandas-stubs from 1.4.3.220829 to 1.4.4.220906
Bumps [pandas-stubs](https://github.com/pandas-dev/pandas-stubs) from 1.4.3.220829 to 1.4.4.220906.
- [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.4.3.220829...v1.4.4.220906)

---
updated-dependencies:
- dependency-name: pandas-stubs
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-06 15:52:21 +00:00
dependabot[bot]
98cdf6a529 Bump pandas from 1.4.3 to 1.4.4
Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.4.3 to 1.4.4.
- [Release notes](https://github.com/pandas-dev/pandas/releases)
- [Changelog](https://github.com/pandas-dev/pandas/blob/main/RELEASE.md)
- [Commits](https://github.com/pandas-dev/pandas/compare/v1.4.3...v1.4.4)

---
updated-dependencies:
- dependency-name: pandas
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-01 15:59:37 +00:00
scdhh
53379eb951 Merge pull request #13 from shoucandanghehe/dependabot/pip/pandas-stubs-1.4.3.220829
Bump pandas-stubs from 1.4.3.220822 to 1.4.3.220829
2022-08-30 16:40:55 +08:00
scdhh
4567764079 Merge pull request #12 from shoucandanghehe/dependabot/pip/pylint-2.15.0
Bump pylint from 2.14.5 to 2.15.0
2022-08-30 16:40:47 +08:00
scdhh
60d6e487d2 Merge pull request #11 from shoucandanghehe/dependabot/pip/playwright-1.25.2
Bump playwright from 1.25.1 to 1.25.2
2022-08-30 16:40:38 +08:00
dependabot[bot]
09c57f52ea Bump pandas-stubs from 1.4.3.220822 to 1.4.3.220829
Bumps [pandas-stubs](https://github.com/pandas-dev/pandas-stubs) from 1.4.3.220822 to 1.4.3.220829.
- [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.4.3.220822...v1.4.3.220829)

---
updated-dependencies:
- dependency-name: pandas-stubs
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-29 16:06:46 +00:00
dependabot[bot]
bab4b06de0 Bump pylint from 2.14.5 to 2.15.0
Bumps [pylint](https://github.com/PyCQA/pylint) from 2.14.5 to 2.15.0.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.14.5...v2.15.0)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-26 15:46:36 +00:00
dependabot[bot]
175daafe5d Bump playwright from 1.25.1 to 1.25.2
Bumps [playwright](https://github.com/Microsoft/playwright-python) from 1.25.1 to 1.25.2.
- [Release notes](https://github.com/Microsoft/playwright-python/releases)
- [Commits](https://github.com/Microsoft/playwright-python/compare/v1.25.1...v1.25.2)

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-24 15:53:19 +00:00
scdhh
a2d8bc55cc Merge pull request #10 from shoucandanghehe/dependabot/pip/pandas-stubs-1.4.3.220822
Bump pandas-stubs from 1.4.3.220815 to 1.4.3.220822
2022-08-23 00:14:47 +08:00
dependabot[bot]
d1a2a20e13 Bump pandas-stubs from 1.4.3.220815 to 1.4.3.220822
Bumps [pandas-stubs](https://github.com/pandas-dev/pandas-stubs) from 1.4.3.220815 to 1.4.3.220822.
- [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.4.3.220815...v1.4.3.220822)

---
updated-dependencies:
- dependency-name: pandas-stubs
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-22 15:49:43 +00:00
scdhh
e32a32dee0 Merge pull request #8 from shoucandanghehe/dependabot/pip/pandas-stubs-1.4.3.220815
Bump pandas-stubs from 1.4.3.220807 to 1.4.3.220815
2022-08-22 16:51:46 +08:00
scdhh
540b01649d Merge pull request #9 from shoucandanghehe/dependabot/pip/playwright-1.25.1
Bump playwright from 1.24.1 to 1.25.1
2022-08-22 16:51:34 +08:00
dependabot[bot]
f224af7aa4 Bump playwright from 1.24.1 to 1.25.1
Bumps [playwright](https://github.com/Microsoft/playwright-python) from 1.24.1 to 1.25.1.
- [Release notes](https://github.com/Microsoft/playwright-python/releases)
- [Commits](https://github.com/Microsoft/playwright-python/compare/v1.24.1...v1.25.1)

---
updated-dependencies:
- dependency-name: playwright
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-19 15:56:06 +00:00
dependabot[bot]
c5db3fef3f Bump pandas-stubs from 1.4.3.220807 to 1.4.3.220815
Bumps [pandas-stubs](https://github.com/pandas-dev/pandas-stubs) from 1.4.3.220807 to 1.4.3.220815.
- [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.4.3.220807...v1.4.3.220815)

---
updated-dependencies:
- dependency-name: pandas-stubs
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-16 15:50:27 +00:00
scdhh
884cc08d77 Merge pull request #6 from shoucandanghehe/dependabot/pip/nonebot-adapter-onebot-2.1.3
Bump nonebot-adapter-onebot from 2.1.2 to 2.1.3
2022-08-12 10:10:38 +08:00
dependabot[bot]
b30d5e008d Bump nonebot-adapter-onebot from 2.1.2 to 2.1.3
Bumps [nonebot-adapter-onebot](https://github.com/nonebot/adapter-onebot) from 2.1.2 to 2.1.3.
- [Release notes](https://github.com/nonebot/adapter-onebot/releases)
- [Commits](https://github.com/nonebot/adapter-onebot/compare/v2.1.2...v2.1.3)

---
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>
2022-08-11 15:51:37 +00:00
scdhh
0a3e265272 Merge pull request #5 from shoucandanghehe/dependabot/pip/nonebot-adapter-onebot-2.1.2
Bump nonebot-adapter-onebot from 2.1.1 to 2.1.2
2022-08-11 00:30:54 +08:00
dependabot[bot]
b32c2f1895 Bump nonebot-adapter-onebot from 2.1.1 to 2.1.2
Bumps [nonebot-adapter-onebot](https://github.com/nonebot/adapter-onebot) from 2.1.1 to 2.1.2.
- [Release notes](https://github.com/nonebot/adapter-onebot/releases)
- [Commits](https://github.com/nonebot/adapter-onebot/compare/v2.1.1...v2.1.2)

---
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>
2022-08-10 16:26:14 +00:00
d62c53031e 只在bot结束运行的时候写入缓存 2022-08-10 15:20:37 +08:00
12 changed files with 2181 additions and 1819 deletions

View File

@@ -7,5 +7,6 @@ version: 2
updates:
- package-ecosystem: "pip" # See documentation for possible values
directory: "/" # Location of package manifests
target-branch: "dev"
schedule:
interval: "daily"

2
.gitignore vendored
View File

@@ -1,4 +1,6 @@
.idea
dist
test*
Untitled*
*copy*
.vscode

View File

@@ -1,360 +0,0 @@
import os
from asyncio import gather
from re import I
from typing import Any
import aiohttp
from nonebot import get_driver, on_regex
from nonebot.adapters.onebot.v11 import GROUP, MessageEvent
from nonebot.log import logger
from nonebot.matcher import Matcher
from playwright.async_api import Browser, Response, async_playwright
from ujson import JSONDecodeError, dumps, loads
from ..utils.config import Config
from ..utils.database import DataBase
from ..utils.message_analyzer import (
handle_bind_message,
handle_stats_query_message
)
IOBind = on_regex(pattern=r'^io绑定|^iobind', flags=I, permission=GROUP)
IOStats = on_regex(pattern=r'^io查|^iostats', flags=I, permission=GROUP)
driver = get_driver()
config = Config.parse_obj(get_driver().config)
@IOBind.handle()
async def _(event: MessageEvent, matcher: Matcher):
decoded_message = await handle_bind_message(message=event.raw_message, game_type='IO')
if decoded_message[0] is None:
await matcher.finish(decoded_message[1][0])
if decoded_message[0] == 'ID':
user_id_stats = await check_user_id(decoded_message[1][1])
if user_id_stats[0] is False:
await matcher.finish(user_id_stats[1])
else:
user_id = decoded_message[1][1]
elif decoded_message[0] == 'Name':
user_data = await get_user_data(user_name=decoded_message[1][1])
if user_data[0] is False:
await matcher.finish('用户信息请求失败')
elif user_data[1] is False:
await matcher.finish(f'用户信息请求错误:\n{user_data[2]["error"]}')
else:
user_id = await get_user_id(user_data[2])
if event.sender.user_id is None: # 理论上是不会有None出现的, ide快乐行属于是
logger.error('获取QQ号失败')
await matcher.finish('获取QQ号失败')
await matcher.finish(
await DataBase.write_bind_info(
qq_number=event.sender.user_id,
user=user_id,
game_type='IO'
)
)
@IOStats.handle()
async def _(event: MessageEvent, matcher: Matcher):
decoded_message = await handle_stats_query_message(message=event.raw_message, game_type='IO')
if decoded_message[0] is None:
await matcher.finish(decoded_message[1][0])
elif decoded_message[0] == 'AT':
if event.is_tome() is True:
await matcher.finish('不能查询bot的信息')
bind_info = await DataBase.query_bind_info(qq_number=decoded_message[1][1], game_type='IO')
if bind_info is None:
message = '未查询到绑定信息'
else:
message = (f'* 由于无法验证绑定信息, 不能保证查询到的用户为本人\n{await generate_message(user_id=bind_info)}')
elif decoded_message[0] == 'ME':
if event.sender.user_id is None:
logger.error('获取QQ号失败')
await matcher.finish('获取QQ号失败, 请联系bot主人')
bind_info = await DataBase.query_bind_info(qq_number=event.sender.user_id, game_type='IO')
if bind_info is None:
message = '未查询到绑定信息'
else:
message = (f'* 由于无法验证绑定信息, 不能保证查询到的用户为本人\n{await generate_message(user_id=bind_info)}')
elif decoded_message[0] == 'ID':
message = await generate_message(user_id=decoded_message[1][1])
elif decoded_message[0] == 'Name':
message = await generate_message(user_name=decoded_message[1][1])
await matcher.finish(message)
@driver.on_startup
async def _():
await Request.init_cache()
await Request.read_cache()
@driver.on_shutdown
async def _():
await Request.close_browser()
async def get_user_data(
user_name: str = None,
user_id: str = None
) -> tuple[bool, bool, dict[str, Any]]:
'''获取用户数据'''
if user_name is not None and user_id is None:
user_data_url = f'https://ch.tetr.io/api/users/{user_name}'
elif user_name is None and user_id is not None:
user_data_url = f'https://ch.tetr.io/api/users/{user_id}'
else:
raise ValueError('预期外行为, 请上报GitHub')
return await Request.request(user_data_url)
async def get_solo_data(
user_name: str = None,
user_id: str = None
) -> tuple[bool, bool, dict[str, Any]]:
'''获取Solo数据'''
if user_name is not None and user_id is None:
user_solo_url = f'https://ch.tetr.io/api/users/{user_name}/records'
elif user_name is None and user_id is not None:
user_solo_url = f'https://ch.tetr.io/api/users/{user_id}/records'
else:
raise ValueError('预期外行为, 请上报GitHub')
return await Request.request(user_solo_url)
async def get_user_id(user_data: dict) -> str:
'''获取用户ID'''
return user_data['data']['user']['_id']
async def check_user_id(user_id: str) -> tuple[bool, str]:
'''检查用户ID是否有效'''
user_data = await get_user_data(user_id=user_id)
if user_data[0] is False:
return False, '用户信息请求失败'
if user_data[1] is False:
return False, f'用户信息请求错误:\n{user_data[2]["error"]}'
if user_id == user_data[2]['data']['user']['_id']:
return True, ''
raise ValueError('服务器返回的userID和用户提供的不一致, 这种情况理论上不应该发生, 以防万一还是写一下x')
async def get_league_stats(user_data: dict) -> dict[str, Any]:
'''获取排位统计数据'''
league = user_data['data']['user']['league']
league_stats: dict[str, Any] = {}
if league['gamesplayed'] != 0:
league_stats['PPS'] = league['pps']
league_stats['APM'] = league['apm']
league_stats['VS'] = 0 if league['vs'] is None else league['vs']
league_stats['Rank'] = 'Z' if league['rank'] == 'z' else league['rank'].upper()
if league['rating'] == -1:
league_stats['Rank'] = None
else:
league_stats['Rating'] = round(league['rating'], 2)
league_stats['Glicko'] = round(league['glicko'], 2)
league_stats['RD'] = round(league['rd'], 2)
league_stats['Standing'] = league['standing']
league_stats['LPM'] = round((league['pps'] * 24), 2)
league_stats['APL'] = round(
(league_stats['APM'] / league_stats['LPM']), 2)
league_stats['ADPM'] = round((league_stats['VS'] * 0.6), 2)
league_stats['ADPL'] = round(
(league_stats['ADPM'] / league_stats['LPM']), 2)
return league_stats
async def get_sprint_stats(solo_data: dict) -> dict[str, Any]:
'''获取40L统计数据'''
sprint_stats = {}
solo = solo_data['data']['records']['40l']
if solo['record'] is not None:
sprint_stats['Time'] = round(
solo['record']['endcontext']['finalTime'] / 1000, 2)
if solo['rank'] is not None:
sprint_stats['Rank'] = solo['rank']
return sprint_stats
async def get_blitz_stats(solo_data: dict) -> dict[str, Any]:
'''获取Blitz统计数据'''
blitz_stats = {}
blitz = solo_data['data']['records']['blitz']
if blitz['record'] is not None:
blitz_stats['Score'] = blitz['record']['endcontext']['score']
if blitz['rank'] is not None:
blitz_stats['Rank'] = blitz['rank']
return blitz_stats
async def generate_message(user_name: str = None, user_id: str = None) -> str:
'''生成消息'''
user_data, solo_data = await gather(
get_user_data(user_name=user_name, user_id=user_id),
get_solo_data(user_name=user_name, user_id=user_id)
)
if user_data[0] is False:
return '用户信息请求失败'
if user_data[1] is False:
return f'用户信息请求错误:\n{user_data[2]["error"]}'
user_name = user_data[2]['data']['user']['username'].upper()
league_stats = await get_league_stats(user_data[2])
message = ''
if not league_stats:
message += f'用户 {user_name} 没有排位统计数据'
else:
if league_stats['Rank'] is None:
message += f'用户 {user_name} 暂未完成定级赛, 最近十场的数据:'
else:
if league_stats['Rank'] == 'Z':
message += f'用户 {user_name} 暂无段位, {league_stats["Rating"]} TR'
else:
message += f'{league_stats["Rank"]} 段用户 {user_name} {league_stats["Rating"]} TR (#{league_stats["Standing"]})'
message += f', 段位分 {league_stats["Glicko"]}±{league_stats["RD"]}, 最近十场的数据:'
message += f'\nL\'PM: {league_stats["LPM"]} ( {league_stats["PPS"]} pps )'
message += f'\nAPM: {league_stats["APM"]} ( x{league_stats["APL"]} )'
if league_stats["VS"] != 0:
message += f'\nADPM: {league_stats["ADPM"]} ( x{league_stats["ADPL"]} ) ( {league_stats["VS"]}vs )'
if solo_data[0] is False:
return f'{message}\nSolo统计数据请求失败'
if solo_data[1] is False:
return f'{message}\nSolo统计数据请求错误:\n{solo_data[2]["error"]}'
sprint_stats, blitz_stats = await gather(
get_sprint_stats(solo_data[2]),
get_blitz_stats(solo_data[2])
)
message += f'\n40L: {sprint_stats["Time"]}s' if 'Time' in sprint_stats else ''
message += f' ( #{sprint_stats["Rank"]} )' if 'Rank' in sprint_stats else ''
message += f'\nBlitz: {blitz_stats["Score"]}' if 'Score' in blitz_stats else ''
message += f' ( #{blitz_stats["Rank"]} )' if 'Rank' in blitz_stats else ''
return message
class Request:
'''网络请求相关类'''
_browser: Browser | None = None
_headers: dict | None = None
_cookies: dict | None = None
@classmethod
async def _init_playwright(cls) -> Browser:
'''初始化playwright'''
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._init_playwright()
@classmethod
async def _anti_cloudflare(cls, url: str) -> tuple[bool, bool, dict[str, Any]]:
'''用firefox硬穿五秒盾'''
browser = await cls._get_browser()
context = await browser.new_context()
page = await context.new_page()
response = await page.goto(url)
attempts = 0
while attempts < 60:
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':
# TODO 有无人来做一个过验证码(
break
try:
data = loads(text)
except JSONDecodeError:
await page.wait_for_timeout(1000)
else:
assert isinstance(response, Response)
cls._headers = await response.request.all_headers()
cls._cookies = {i['name']: i['value'] for i in await context.cookies()}
await cls._write_cache()
await page.close()
await context.close()
return True, data['success'], data
await page.close()
await context.close()
return True, False, {'error': '绕过五秒盾失败'}
@classmethod
async def init_cache(cls) -> None:
'''初始化缓存文件'''
if not os.path.exists(os.path.dirname(config.cache_path)):
os.makedirs(os.path.dirname(config.cache_path))
if not os.path.exists(config.cache_path):
with open(file=config.cache_path, mode='w', encoding='UTF-8') as file:
file.write(
dumps(
{
'headers': cls._headers,
'cookies': cls._cookies
}
)
)
@classmethod
async def read_cache(cls) -> None:
'''读取缓存文件'''
try:
with open(file=config.cache_path, mode='r', encoding='UTF-8') as file:
json = loads(file.read())
cls._headers = json['headers']
cls._cookies = json['cookies']
except FileNotFoundError:
await cls.init_cache()
except PermissionError:
os.remove(config.cache_path)
await cls.init_cache()
except JSONDecodeError:
os.remove(config.cache_path)
await cls.init_cache()
@classmethod
async def _write_cache(cls) -> None:
'''写入缓存文件'''
try:
with open(file=config.cache_path, mode='r+', encoding='UTF-8') as file:
file.write(
dumps(
{
'headers': cls._headers,
'cookies': cls._cookies
}
)
)
except FileNotFoundError:
await cls.init_cache()
except PermissionError:
os.remove(config.cache_path)
await cls.init_cache()
except JSONDecodeError:
os.remove(config.cache_path)
await cls.init_cache()
@classmethod
async def request(cls, url: str) -> tuple[bool, bool, dict[str, Any]]:
'''请求api'''
try:
async with aiohttp.ClientSession(cookies=cls._cookies) as session:
async with session.get(url, headers=cls._headers) as resp:
data = await resp.json()
return True, data['success'], data
except aiohttp.client_exceptions.ClientConnectorError as error:
logger.error(f'请求错误\n{error}')
return False, False, {}
except aiohttp.client_exceptions.ContentTypeError:
return await cls._anti_cloudflare(url)
@classmethod
async def close_browser(cls) -> None:
'''关闭浏览器对象'''
if isinstance(cls._browser, Browser):
await cls._browser.close()

View File

@@ -0,0 +1,40 @@
from re import I
from nonebot import on_regex
from nonebot.adapters.onebot.v11 import GROUP, MessageEvent
from nonebot.matcher import Matcher
from .processor import Processor
IOBind = on_regex(pattern=r'^io绑定|^iobind', flags=I, permission=GROUP)
IOStats = on_regex(pattern=r'^io查|^iostats', flags=I, permission=GROUP)
IORank = on_regex(pattern=r'^io段位|^iorank', flags=I, permission=GROUP)
@IOBind.handle()
async def _(event: MessageEvent, matcher: Matcher):
await matcher.finish(
await Processor.handle_bind(
message=event.raw_message,
qq_number=event.sender.user_id
)
)
@IOStats.handle()
async def _(event: MessageEvent, matcher: Matcher):
if event.is_tome():
await matcher.finish('不能查询bot的信息')
await matcher.finish(
await Processor.handle_query(
message=event.raw_message,
qq_number=event.sender.user_id
)
)
@IORank.handle()
async def _(event: MessageEvent, matcher: Matcher):
await matcher.finish(
await Processor.handle_rank(
message=event.raw_message
)
)

View File

@@ -0,0 +1,289 @@
import math
from asyncio import gather
from typing import Any
from nonebot.log import logger
from ...utils.database import DataBase
from ...utils.message_analyzer import (
handle_bind_message,
handle_rank_message,
handle_stats_query_message,
)
from .request import Request
class Processor:
@classmethod
async def handle_bind(cls, message: str, qq_number: int | None) -> str:
'''处理绑定消息'''
decoded_message = await handle_bind_message(message=message, game_type='IO')
if decoded_message[0] is None:
return decoded_message[1][0]
if decoded_message[0] == 'ID':
user_id_stats = await cls.check_user_id(decoded_message[1][1])
if user_id_stats[0] is False:
return user_id_stats[1]
user_id = decoded_message[1][1]
elif decoded_message[0] == 'Name':
user_data = await cls.get_user_data(user_name=decoded_message[1][1])
if user_data[0] is False:
return '用户信息请求失败'
if user_data[1] is False:
return f'用户信息请求错误:\n{user_data[2]["error"]}'
user_id = await cls.get_user_id(user_data[2])
if qq_number is None: # 理论上是不会有None出现的, ide快乐行属于是
logger.error('获取QQ号失败')
return '获取QQ号失败'
return (
await DataBase.write_bind_info(
qq_number=qq_number,
user=user_id,
game_type='IO'
)
)
logger.error('预期外行为, 请上报GitHub')
return '出现预期外行为,请查看后台信息'
@classmethod
async def handle_rank(cls, message: str):
query_rank = await handle_rank_message(message)
rank_info = await DataBase.query_rank_info_today(rank=query_rank.lower())
if rank_info is None:
ranks_percentiles = {
'x': 1,
'u': 5,
'ss': 11,
's+': 17,
's': 23,
's-': 30,
'a+': 38,
'a': 46,
'a-': 54,
'b+': 62,
'b': 70,
'b-': 78,
'c+': 84,
'c': 90,
'c-': 95,
'd+': 97.5,
'd': 100,
}
if query_rank.lower() not in (i for i in ranks_percentiles.keys()):
return '未知段位'
result = await Request.request('https://ch.tetr.io/api/users/lists/league/all')
users: list = result[2]['data']['users']
def avg(rank_users: list, column: str, playercount: int | None = None) -> float:
return sum(i['league'][column] for i in rank_users) / (playercount or len(rank_users))
for rank, percentile in ranks_percentiles.items():
offset = math.floor((percentile / 100) * len(users)) - 1
tr = users[offset]['league']['rating']
rank_users = list(filter(lambda x: x['league']['rank'] == rank, users))
playercount = len(rank_users)
avg_apm = avg(rank_users, 'apm', playercount)
avg_pps = avg(rank_users, 'pps', playercount)
avg_vs = avg(rank_users, 'vs', playercount)
await DataBase.write_rank_info_today(
rank=rank,
trline=tr,
playercount=playercount,
avgapm=avg_apm,
avgpps=avg_pps,
avgvs=avg_vs
)
return await Processor.handle_rank(message=message)
else:
avg_apm = round(rank_info[3], 2)
avg_pps = round(rank_info[4], 2)
avg_vs = round(rank_info[5], 2)
avg_lpm = round((avg_pps * 24), 2)
avg_apl = round((avg_apm / avg_lpm), 2)
avg_adpm = round((avg_vs * 0.6), 2)
avg_adpl = round((avg_adpm / avg_lpm), 2)
message = f'{query_rank.upper()} 段, 分数线 {round(rank_info[1], 2)} TR, {rank_info[2]} 名玩家'
message += f'\n对比昨日趋势: {rank_info[0]}'
message += '\n平均数据: '
message += f"\nL'PM: {avg_lpm} ( {avg_pps} pps )"
message += f'\nAPM: {avg_apm} ( x{avg_apl} )'
message += f'\nADPM: {avg_adpm} ( x{avg_adpl} ) ( {avg_vs}vs )'
message += '\n'
message += f'\n数据更新时间: {rank_info[6]}'
return message
@classmethod
async def handle_query(cls, message: str, qq_number: int | None):
'''处理查询消息'''
decoded_message = await handle_stats_query_message(message=message, game_type='IO')
if decoded_message[0] is None:
return decoded_message[1][0]
if decoded_message[0] == 'AT': # 在入口处判断是否@bot本身
bind_info = await DataBase.query_bind_info(qq_number=decoded_message[1][1], game_type='IO')
if bind_info is None:
return '未查询到绑定信息'
return f'* 由于无法验证绑定信息, 不能保证查询到的用户为本人\n{await Processor.generate_message(user_id=bind_info)}'
if decoded_message[0] == 'ME':
if qq_number is None:
logger.error('获取QQ号失败')
return '获取QQ号失败, 请联系bot主人'
bind_info = await DataBase.query_bind_info(qq_number=qq_number, game_type='IO')
if bind_info is None:
return '未查询到绑定信息'
return f'* 由于无法验证绑定信息, 不能保证查询到的用户为本人\n{await Processor.generate_message(user_id=bind_info)}'
if decoded_message[0] == 'ID':
return await Processor.generate_message(user_id=decoded_message[1][1])
if decoded_message[0] == 'Name':
return await Processor.generate_message(user_name=decoded_message[1][1])
@classmethod
async def get_user_data(
cls,
user_name: str | None = None,
user_id: str | None = None
) -> tuple[bool, bool, dict[str, Any]]:
'''获取用户数据'''
if user_name is not None and user_id is None:
user_data_url = f'https://ch.tetr.io/api/users/{user_name}'
elif user_name is None and user_id is not None:
user_data_url = f'https://ch.tetr.io/api/users/{user_id}'
else:
raise ValueError('预期外行为, 请上报GitHub')
return await Request.request(user_data_url)
@classmethod
async def get_solo_data(
cls,
user_name: str | None = None,
user_id: str | None = None
) -> tuple[bool, bool, dict[str, Any]]:
'''获取Solo数据'''
if user_name is not None and user_id is None:
user_solo_url = f'https://ch.tetr.io/api/users/{user_name}/records'
elif user_name is None and user_id is not None:
user_solo_url = f'https://ch.tetr.io/api/users/{user_id}/records'
else:
raise ValueError('预期外行为, 请上报GitHub')
return await Request.request(user_solo_url)
@classmethod
async def get_user_id(cls, user_data: dict) -> str:
'''获取用户ID'''
return user_data['data']['user']['_id']
@classmethod
async def check_user_id(cls, user_id: str) -> tuple[bool, str]:
'''检查用户ID是否有效 返回值为tuple[bool, message]'''
user_data = await cls.get_user_data(user_id=user_id)
if user_data[0] is False:
return False, '用户信息请求失败'
if user_data[1] is False:
return False, f'用户信息请求错误:\n{user_data[2]["error"]}'
if user_id == user_data[2]['data']['user']['_id']:
return True, ''
raise ValueError('服务器返回的userID和用户提供的不一致, 这种情况理论上不应该发生, 以防万一还是写一下x')
@classmethod
async def get_league_stats(cls, user_data: dict) -> dict[str, Any]:
'''获取排位统计数据'''
league = user_data['data']['user']['league']
league_stats: dict[str, Any] = {}
if league['gamesplayed'] != 0:
league_stats['PPS'] = league['pps']
league_stats['APM'] = league['apm']
league_stats['VS'] = 0 if league['vs'] is None else league['vs']
league_stats['Rank'] = 'Z' if league['rank'] == 'z' else league['rank'].upper(
)
if league['rating'] == -1:
league_stats['Rank'] = None
else:
league_stats['Rating'] = round(league['rating'], 2)
league_stats['Glicko'] = round(league['glicko'], 2)
league_stats['RD'] = round(league['rd'], 2)
league_stats['Standing'] = league['standing']
league_stats['LPM'] = round((league['pps'] * 24), 2)
league_stats['APL'] = round(
(league_stats['APM'] / league_stats['LPM']), 2)
league_stats['ADPM'] = round((league_stats['VS'] * 0.6), 2)
league_stats['ADPL'] = round(
(league_stats['ADPM'] / league_stats['LPM']), 2)
return league_stats
@classmethod
async def get_sprint_stats(cls, solo_data: dict) -> dict[str, Any]:
'''获取40L统计数据'''
sprint_stats = {}
solo = solo_data['data']['records']['40l']
if solo['record'] is not None:
sprint_stats['Time'] = round(
solo['record']['endcontext']['finalTime'] / 1000, 2)
if solo['rank'] is not None:
sprint_stats['Rank'] = solo['rank']
return sprint_stats
@classmethod
async def get_blitz_stats(cls, solo_data: dict) -> dict[str, Any]:
'''获取Blitz统计数据'''
blitz_stats = {}
blitz = solo_data['data']['records']['blitz']
if blitz['record'] is not None:
blitz_stats['Score'] = blitz['record']['endcontext']['score']
if blitz['rank'] is not None:
blitz_stats['Rank'] = blitz['rank']
return blitz_stats
@classmethod
async def generate_message(
cls,
user_name: str | None = None,
user_id: str | None = None
) -> str:
'''生成消息'''
user_data, solo_data = await gather(
cls.get_user_data(user_name=user_name, user_id=user_id),
cls.get_solo_data(user_name=user_name, user_id=user_id)
)
if user_data[0] is False:
return '用户信息请求失败'
if user_data[1] is False:
return f'用户信息请求错误:\n{user_data[2]["error"]}'
user_name = user_data[2]['data']['user']['username'].upper()
league_stats = await cls.get_league_stats(user_data[2])
message = ''
if not league_stats:
message += f'用户 {user_name} 没有排位统计数据'
else:
if league_stats['Rank'] is None:
message += f'用户 {user_name} 暂未完成定级赛, 最近十场的数据:'
else:
if league_stats['Rank'] == 'Z':
message += f'用户 {user_name} 暂无段位, {league_stats["Rating"]} TR'
else:
message += f'{league_stats["Rank"]} 段用户 {user_name} {league_stats["Rating"]} TR (#{league_stats["Standing"]})'
message += f', 段位分 {league_stats["Glicko"]}±{league_stats["RD"]}, 最近十场的数据:'
message += f'\nL\'PM: {league_stats["LPM"]} ( {league_stats["PPS"]} pps )'
message += f'\nAPM: {league_stats["APM"]} ( x{league_stats["APL"]} )'
if league_stats["VS"] != 0:
message += f'\nADPM: {league_stats["ADPM"]} ( x{league_stats["ADPL"]} ) ( {league_stats["VS"]}vs )'
if solo_data[0] is False:
return f'{message}\nSolo统计数据请求失败'
if solo_data[1] is False:
return f'{message}\nSolo统计数据请求错误:\n{solo_data[2]["error"]}'
sprint_stats, blitz_stats = await gather(
cls.get_sprint_stats(solo_data[2]),
cls.get_blitz_stats(solo_data[2])
)
message += f'\n40L: {sprint_stats["Time"]}s' if 'Time' in sprint_stats else ''
message += f' ( #{sprint_stats["Rank"]} )' if 'Rank' in sprint_stats else ''
message += f'\nBlitz: {blitz_stats["Score"]}' if 'Score' in blitz_stats else ''
message += f' ( #{blitz_stats["Rank"]} )' if 'Rank' in blitz_stats else ''
return message

View File

@@ -0,0 +1,155 @@
import os
from typing import Any
import aiohttp
from nonebot import get_driver
from nonebot.log import logger
from playwright.async_api import Browser, Response, async_playwright
from ujson import JSONDecodeError, dumps, loads
from ...utils.config import Config
driver = get_driver()
config = Config.parse_obj(get_driver().config)
@driver.on_startup
async def _():
await Request.init_cache()
await Request.read_cache()
@driver.on_shutdown
async def _():
await Request.close_browser()
await Request.write_cache()
class Request:
'''网络请求相关类'''
_browser: Browser | None = None
_headers: dict | None = None
_cookies: dict | None = None
@classmethod
async def _init_playwright(cls) -> Browser:
'''初始化playwright'''
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._init_playwright()
@classmethod
async def _anti_cloudflare(cls, url: str) -> tuple[bool, bool, dict[str, Any]]:
'''用firefox硬穿五秒盾'''
browser = await cls._get_browser()
context = await browser.new_context()
page = await context.new_page()
response = await page.goto(url)
attempts = 0
while attempts < 60:
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':
# TODO 有无人来做一个过验证码(
break
try:
data = loads(text)
except JSONDecodeError:
await page.wait_for_timeout(1000)
else:
assert isinstance(response, Response)
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 True, data['success'], data
await page.close()
await context.close()
return True, False, {'error': '绕过五秒盾失败'}
@classmethod
async def init_cache(cls) -> None:
'''初始化缓存文件'''
if not os.path.exists(os.path.dirname(config.cache_path)):
os.makedirs(os.path.dirname(config.cache_path))
if not os.path.exists(config.cache_path):
with open(file=config.cache_path, mode='w', encoding='UTF-8') as file:
file.write(
dumps(
{
'headers': cls._headers,
'cookies': cls._cookies
}
)
)
@classmethod
async def read_cache(cls) -> None:
'''读取缓存文件'''
try:
with open(file=config.cache_path, mode='r', encoding='UTF-8') as file:
json = loads(file.read())
cls._headers = json['headers']
cls._cookies = json['cookies']
except FileNotFoundError:
await cls.init_cache()
except PermissionError:
os.remove(config.cache_path)
await cls.init_cache()
except JSONDecodeError:
os.remove(config.cache_path)
await cls.init_cache()
@classmethod
async def write_cache(cls) -> None:
'''写入缓存文件'''
try:
with open(file=config.cache_path, mode='r+', encoding='UTF-8') as file:
file.write(
dumps(
{
'headers': cls._headers,
'cookies': cls._cookies
}
)
)
except FileNotFoundError:
await cls.init_cache()
except PermissionError:
os.remove(config.cache_path)
await cls.init_cache()
except JSONDecodeError:
os.remove(config.cache_path)
await cls.init_cache()
@classmethod
async def request(cls, url: str) -> tuple[bool, bool, dict[str, Any]]:
'''请求api'''
try:
async with aiohttp.ClientSession(cookies=cls._cookies) as session:
async with session.get(url, headers=cls._headers) as resp:
data = await resp.json()
return True, data['success'], data
except aiohttp.client_exceptions.ClientConnectorError as error: # type: ignore
logger.error(f'请求错误\n{error}')
return False, False, {}
except aiohttp.client_exceptions.ContentTypeError: # type: ignore
return await cls._anti_cloudflare(url)
@classmethod
async def close_browser(cls) -> None:
'''关闭浏览器对象'''
if isinstance(cls._browser, Browser):
await cls._browser.close()

View File

@@ -33,16 +33,16 @@ async def _(event: MessageEvent, matcher: Matcher):
if await check_user(user_data[1]) is False:
await matcher.finish('用户不存在')
user_name = await get_user_name(user_data[1])
if event.sender.user_id is None: # 理论上是不会有None出现的, ide快乐行属于是
logger.error('获取QQ号失败')
await matcher.finish('获取QQ号失败')
await matcher.finish(
await DataBase.write_bind_info(
qq_number=event.sender.user_id,
user=user_name,
game_type='TOP'
)
)
if event.sender.user_id is None: # 理论上是不会有None出现的, ide快乐行属于是
logger.error('获取QQ号失败')
await matcher.finish('获取QQ号失败')
await matcher.finish(
await DataBase.write_bind_info(
qq_number=event.sender.user_id,
user=user_name,
game_type='TOP'
)
)
@TopStats.handle()
@@ -69,6 +69,8 @@ async def _(event: MessageEvent, matcher: Matcher):
message = (f'* 由于无法验证绑定信息, 不能保证查询到的用户为本人\n{await generate_message(bind_info)}')
elif decoded_message[0] == 'Name':
message = await generate_message(decoded_message[1][1])
else:
raise ValueError('预期外行为, 请上报GitHub')
await matcher.finish(message)
@@ -79,7 +81,7 @@ async def get_user_data(user_name: str) -> tuple[bool, str]:
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
return True, await resp.text()
except aiohttp.client_exceptions.ClientConnectorError as error:
except aiohttp.client_exceptions.ClientConnectorError as error: # type: ignore
logger.error(error)
return False, ''

View File

@@ -30,6 +30,8 @@ async def _(event: MessageEvent, matcher: Matcher):
message = await generate_message(tea_id=event.sender.user_id)
elif decoded_message[0] == 'Name':
message = await generate_message(user_name=decoded_message[1][1])
else:
raise ValueError('预期外行为, 请上报GitHub')
await matcher.finish(message)
@@ -40,14 +42,14 @@ async def request(url: str) -> tuple[bool, bool, dict[str, Any]]:
async with session.get(url) as resp:
data = await resp.json()
return True, data['success'], data
except aiohttp.client_exceptions.ClientConnectorError as error:
except aiohttp.client_exceptions.ClientConnectorError as error: # type: ignore
logger.error(f'请求错误\n{error}')
return False, False, {}
async def get_user_info(
user_name: str = None,
tea_id: int = None
user_name: str | None = None,
tea_id: int | None = None
) -> tuple[bool, bool, dict[str, Any]]:
'''获取用户信息'''
if user_name is not None and tea_id is None:
@@ -60,8 +62,8 @@ async def get_user_info(
async def get_user_data(
user_name: str = None,
tea_id: int = None,
user_name: str | None = None,
tea_id: int | None = None,
other_parameter: str = ''
) -> tuple[bool, bool, dict[str, Any]]:
'''获取用户数据'''
@@ -77,8 +79,8 @@ async def get_user_data(
async def get_rank_stats(user_info: dict) -> dict[str, float]:
'''获取Rank数据'''
data = user_info['data']
rank_stats = {}
if int(data['rankedGames']) != 0:
rank_stats = {}
rank_stats['Rating'] = round(float(data['ratingNow']), 2)
rank_stats['RD'] = round(float(data['rdNow']), 2)
rank_stats['Vol'] = round(float(data['volNow']), 3)
@@ -87,8 +89,8 @@ async def get_rank_stats(user_info: dict) -> dict[str, float]:
async def get_game_data(user_data: dict) -> dict[str, int | float]:
'''获取游戏数据'''
game_data: dict[str, int | float] = {}
if user_data['data'] != []:
game_data: dict[str, int | float] = {}
weighted_total_lpm = weighted_total_apm = weighted_total_adpm = total_time = num = 0
for i in user_data['data']:
# 排除单人局和时间为0的游戏
@@ -136,7 +138,10 @@ async def get_pb_data(user_info: dict) -> dict[str, float | str]:
return pb_data
async def generate_message(user_name: str = None, tea_id: int = None) -> str:
async def generate_message(
user_name: str | None = None,
tea_id: int | None = None
) -> str:
'''生成消息'''
user_info, user_data = await gather(
get_user_info(user_name=user_name, tea_id=tea_id),

View File

@@ -1,3 +1,4 @@
import datetime
import os
from asyncio import gather
from sqlite3 import Connection, connect
@@ -39,10 +40,61 @@ class DataBase():
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 = '?'
else:
if result[0] > trline:
trending = ''
else:
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:
'''获取数据库对象'''
@@ -76,6 +128,8 @@ class DataBase():
cursor.execute(
f'INSERT INTO {game_type}BIND (QQ, USER) VALUES (?, ?)', (qq_number, user))
message = '绑定成功'
else:
raise ValueError('预期外行为, 请上报GitHub')
db.commit()
return message

View File

@@ -53,6 +53,19 @@ async def handle_stats_query_message(message: str, game_type: str) -> tuple[str
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':

3027
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "nonebot-plugin-tetris-stats"
version = "0.3.2"
version = "0.4.1"
description = "一个基于nonebot2的用于查询TETRIS相关游戏玩家数据的插件"
authors = ["scdhh <wallfjjd@gmail.com>"]
readme = "README.md"
@@ -9,7 +9,7 @@ repository = "https://github.com/shoucandanghehe/nonebot-plugin-tetris-stats"
license = "MIT"
[tool.poetry.dependencies]
python = "^3.10,<3.11"
python = "^3.10,<3.12"
nonebot-adapter-onebot = "^2.0.0-beta.1"
aiohttp = "^3.8.1"
asyncio = "^3.4.3"
@@ -21,12 +21,12 @@ ujson = "^5.4.0"
Brotli = "^1.0.9"
[tool.poetry.dev-dependencies]
mypy = "^0.971"
autopep8 = "^1.7.0"
pylint = "^2.14.5"
types-ujson = "^5.4.0"
mypy = "^0.991"
autopep8 = "^2.0.0"
pylint = "^2.15.9"
types-ujson = "^5.5.0"
lxml-stubs = "^0.4.0"
pandas-stubs = "^1.4.3"
pandas-stubs = "^1.5.2"
[build-system]
requires = ["poetry-core>=1.0.0"]