nonebot-plugin-bililive 2.1.4__tar.gz → 2.1.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/PKG-INFO +2 -2
  2. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/database/db.py +82 -13
  3. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/version.py +1 -1
  4. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/pyproject.toml +2 -2
  5. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/tests/test_maintenance.py +8 -1
  6. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/LICENSE +0 -0
  7. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/README.md +0 -0
  8. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/__init__.py +0 -0
  9. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/__main__.py +0 -0
  10. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/bilibili_api.py +0 -0
  11. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/cli/__init__.py +0 -0
  12. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/cli/bot.py +0 -0
  13. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/cli/utils.py +0 -0
  14. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/config.py +0 -0
  15. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/database/__init__.py +0 -0
  16. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/database/models.py +0 -0
  17. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/libs/__init__.py +0 -0
  18. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/libs/dynamic/__init__.py +0 -0
  19. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/libs/dynamic/card.py +0 -0
  20. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/libs/dynamic/desc.py +0 -0
  21. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/libs/dynamic/display.py +0 -0
  22. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/libs/dynamic/user_profile.py +0 -0
  23. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/libs/dynamic/web.py +0 -0
  24. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/__init__.py +0 -0
  25. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/at/__init__.py +0 -0
  26. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/at/at_off.py +0 -0
  27. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/at/at_on.py +0 -0
  28. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/auto_agree.py +0 -0
  29. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/auto_delete.py +0 -0
  30. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/dynamic/__init__.py +0 -0
  31. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/dynamic/dynamic_off.py +0 -0
  32. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/dynamic/dynamic_on.py +0 -0
  33. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/help.py +0 -0
  34. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/live/__init__.py +0 -0
  35. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/live/live_now.py +0 -0
  36. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/live/live_off.py +0 -0
  37. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/live/live_on.py +0 -0
  38. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/permission/__init__.py +0 -0
  39. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/permission/permission_off.py +0 -0
  40. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/permission/permission_on.py +0 -0
  41. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/pusher/__init__.py +0 -0
  42. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/pusher/dynamic_pusher.py +0 -0
  43. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/pusher/live_pusher.py +0 -0
  44. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/sub/__init__.py +0 -0
  45. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/sub/add_sub.py +0 -0
  46. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/sub/delete_sub.py +0 -0
  47. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/plugins/sub/sub_list.py +0 -0
  48. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/utils/__init__.py +0 -0
  49. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/utils/browser.py +0 -0
  50. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/utils/captcha_solver.py +0 -0
  51. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/utils/fonts_provider.py +0 -0
  52. {nonebot_plugin_bililive-2.1.4 → nonebot_plugin_bililive-2.1.6}/nonebot_plugin_bililive/utils/mobile.js +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nonebot-plugin-bililive
3
- Version: 2.1.4
3
+ Version: 2.1.6
4
4
  Summary: Push bilibili dynamics and live notifications to QQ with NoneBot2.
5
5
  Keywords: nonebot,nonebot2,nonebot-plugin,bilibili,onebot,onebot-v11
6
6
  Author-Email: Akiyy_Lab <2806578374@qq.com>
@@ -27,7 +27,7 @@ Requires-Dist: nonebot2>=2.5.0
27
27
  Requires-Dist: playwright>=1.58.0
28
28
  Requires-Dist: pydantic<3.0,>=1.10.0
29
29
  Requires-Dist: python-dotenv>=1.2.2
30
- Requires-Dist: tortoise-orm[asyncpg]>=0.19.3
30
+ Requires-Dist: tortoise-orm[asyncpg]<2.0,>=1.0.0
31
31
  Requires-Dist: packaging>=26.0
32
32
  Requires-Dist: msvc-runtime>=14.34.31931; sys_platform == "win32"
33
33
  Description-Content-Type: text/markdown
@@ -1,11 +1,32 @@
1
1
  import asyncio
2
+ import inspect
2
3
  import json
4
+ from collections.abc import Callable
3
5
  from pathlib import Path
4
6
 
5
7
  from nonebot import get_driver, logger
6
8
  from packaging.version import Version as version_parser
7
9
  from tortoise import Tortoise
8
10
 
11
+ get_current_context: Callable[[], object | None] | None
12
+
13
+
14
+ def _detect_tortoise_v1() -> bool:
15
+ """Tortoise 1.x 才有 context 模块与 _enable_global_fallback 参数。"""
16
+ try:
17
+ from tortoise.context import get_current_context as _gcc
18
+ except ImportError:
19
+ return False
20
+
21
+ global get_current_context
22
+ get_current_context = _gcc
23
+ params = inspect.signature(Tortoise.init).parameters
24
+ return "_enable_global_fallback" in params
25
+
26
+
27
+ get_current_context = None
28
+ _TORTOISE_V1 = _detect_tortoise_v1()
29
+
9
30
  from ..utils import get_path
10
31
  from ..version import VERSION as APP_VERSION
11
32
  from .models import Group, Sub, User, Version
@@ -13,6 +34,8 @@ from .models import Group, Sub, User, Version
13
34
  uid_list = {"live": {"list": [], "index": 0}, "dynamic": {"list": [], "index": 0}}
14
35
  dynamic_offset = {}
15
36
 
37
+ _db_init_lock = asyncio.Lock()
38
+
16
39
 
17
40
  class DB:
18
41
  """数据库交互类,与增删改查无关的部分不应该在这里面实现"""
@@ -24,15 +47,20 @@ class DB:
24
47
  return Path(get_path("dynamic_offset.json"))
25
48
 
26
49
  @classmethod
27
- async def init(cls):
28
- """初始化数据库"""
50
+ def _orm_context_ok(cls) -> bool:
51
+ """_ready 与 Tortoise 1.x 全局上下文需同时成立,否则会出现 No TortoiseContext。"""
52
+ if not cls._ready:
53
+ return False
54
+ if not _TORTOISE_V1:
55
+ return True
56
+ return get_current_context() is not None
57
+
58
+ @classmethod
59
+ async def _do_init(cls) -> None:
60
+ """在持有 _db_init_lock 时执行完整初始化。"""
29
61
  cls._ready = False
30
62
  config = {
31
63
  "connections": {
32
- # "bililive": {
33
- # "engine": "tortoise.backends.sqlite",
34
- # "credentials": {"file_path": get_path("data.sqlite3")},
35
- # },
36
64
  "bililive": f"sqlite://{get_path('data.sqlite3')}"
37
65
  },
38
66
  "apps": {
@@ -43,7 +71,16 @@ class DB:
43
71
  },
44
72
  }
45
73
 
46
- await Tortoise.init(config, _enable_global_fallback=True)
74
+ init_kwargs = (
75
+ {"_enable_global_fallback": True} if _TORTOISE_V1 else {}
76
+ )
77
+ try:
78
+ await Tortoise.init(config, **init_kwargs)
79
+ except TypeError:
80
+ if init_kwargs:
81
+ await Tortoise.init(config)
82
+ else:
83
+ raise
47
84
 
48
85
  await Tortoise.generate_schemas()
49
86
  await cls.migrate()
@@ -52,26 +89,58 @@ class DB:
52
89
  await cls.save_dynamic_offsets()
53
90
  cls._ready = True
54
91
 
92
+ @classmethod
93
+ async def init(cls):
94
+ """初始化数据库"""
95
+ async with _db_init_lock:
96
+ await cls._do_init()
97
+
55
98
  @classmethod
56
99
  async def close(cls):
57
- cls._ready = False
58
- await cls.save_dynamic_offsets()
59
- await Tortoise.close_connections()
100
+ async with _db_init_lock:
101
+ cls._ready = False
102
+ await cls.save_dynamic_offsets()
103
+ await Tortoise.close_connections()
104
+
105
+ @classmethod
106
+ async def _recover_stale_orm(cls) -> None:
107
+ """_ready 仍为 True 但 Tortoise 上下文已丢失时,关闭并重新初始化。"""
108
+ if not _TORTOISE_V1:
109
+ return
110
+ async with _db_init_lock:
111
+ if get_current_context() is not None:
112
+ return
113
+ if not cls._ready:
114
+ return
115
+ logger.warning(
116
+ "Tortoise ORM 上下文已失效(可能被其他代码关闭连接),"
117
+ "正在重新初始化数据库"
118
+ )
119
+ try:
120
+ await Tortoise.close_connections()
121
+ except Exception:
122
+ logger.exception("关闭 Tortoise 连接时出错,仍将尝试重新初始化")
123
+ cls._ready = False
124
+ await cls._do_init()
60
125
 
61
126
  @classmethod
62
127
  async def wait_until_ready(cls, timeout: float = 30) -> bool:
63
- if cls._ready:
128
+ if cls._orm_context_ok():
64
129
  return True
65
130
 
66
131
  waited = 0.0
67
132
  interval = 0.1
68
133
  while waited < timeout:
69
- if cls._ready:
134
+ if cls._orm_context_ok():
70
135
  return True
136
+ if cls._ready and _TORTOISE_V1 and get_current_context() is None:
137
+ await cls._recover_stale_orm()
138
+ if cls._orm_context_ok():
139
+ return True
71
140
  await asyncio.sleep(interval)
72
141
  waited += interval
73
142
 
74
- return cls._ready
143
+ return cls._orm_context_ok()
75
144
 
76
145
  @classmethod
77
146
  async def load_dynamic_offsets(cls):
@@ -1,4 +1,4 @@
1
1
  from packaging.version import Version
2
2
 
3
- __version__ = "2.1.4"
3
+ __version__ = "2.1.6"
4
4
  VERSION = Version(__version__)
@@ -34,12 +34,12 @@ dependencies = [
34
34
  "playwright>=1.58.0",
35
35
  "pydantic>=1.10.0,<3.0",
36
36
  "python-dotenv>=1.2.2",
37
- "tortoise-orm[asyncpg]>=0.19.3",
37
+ "tortoise-orm[asyncpg]>=1.0.0,<2.0",
38
38
  "packaging>=26.0",
39
39
  "msvc-runtime>=14.34.31931; sys_platform == \"win32\"",
40
40
  ]
41
41
  dynamic = []
42
- version = "2.1.4"
42
+ version = "2.1.6"
43
43
 
44
44
  [project.license]
45
45
  text = "AGPL-3.0-or-later"
@@ -197,7 +197,14 @@ class DBPermissionTests(unittest.IsolatedAsyncioTestCase):
197
197
  ):
198
198
  await DB.init()
199
199
 
200
- self.assertTrue(init_db.await_args.kwargs["_enable_global_fallback"])
200
+ if db_module._TORTOISE_V1:
201
+ self.assertTrue(
202
+ init_db.await_args.kwargs["_enable_global_fallback"]
203
+ )
204
+ else:
205
+ self.assertNotIn(
206
+ "_enable_global_fallback", init_db.await_args.kwargs
207
+ )
201
208
  self.assertTrue(DB._ready)
202
209
  generate_schemas.assert_awaited_once()
203
210
  migrate.assert_awaited_once()