nonebot-plugin-latex 0.0.2.2__py3-none-any.whl → 0.0.3__py3-none-any.whl

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.
@@ -13,13 +13,13 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13
13
  See the Mulan PSL v2 for more details.
14
14
  """
15
15
 
16
- from nonebot import get_plugin_config
16
+ from nonebot import get_plugin_config, get_driver
17
17
  from nonebot.plugin import PluginMetadata
18
18
 
19
19
  from .config import Config
20
- from .converter import converter
20
+ from .converter import _converter, get_converter
21
21
 
22
- __version__ = "0.0.2.2"
22
+ __version__ = "0.0.3"
23
23
 
24
24
  __author__ = "Eilles"
25
25
 
@@ -27,11 +27,22 @@ __plugin_meta__ = PluginMetadata(
27
27
  name="LaTeX图形渲染插件",
28
28
  description="从互联网服务渲染LaTeX公式并发送",
29
29
  usage="发送 latex 或 公式,后接内容或回复公式信息。",
30
- type="application",
31
- homepage="https://github.com/LiteyukiStudio/nonebot-plugin-marshoai",
30
+ type="library",
31
+ homepage="https://github.com/EillesWan/nonebot-plugin-latex",
32
+ config=Config,
33
+ supported_adapters={
34
+ "~onebot.v11",
35
+ },
32
36
  extra={"License": "Mulan PSL v2", "Author": __author__},
33
37
  )
34
38
 
39
+ __all__ = ["get_converter"]
40
+
41
+
42
+ @get_driver().on_startup
43
+ async def init():
44
+ await _converter.load_channel()
45
+
35
46
 
36
47
  config = get_plugin_config(Config)
37
48
 
@@ -1,6 +1,13 @@
1
1
  from .data import ConvertLatex
2
2
 
3
- converter = ConvertLatex()
3
+ _converter = ConvertLatex()
4
4
  """
5
5
  Latex 渲染器
6
6
  """
7
+
8
+
9
+ def get_converter() -> ConvertLatex:
10
+ """
11
+ 获取渲染器
12
+ """
13
+ return _converter
@@ -13,10 +13,23 @@ MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13
13
  See the Mulan PSL v2 for more details.
14
14
  """
15
15
 
16
- from typing import Optional, Literal, Tuple
17
- import httpx
18
- import time
19
16
  import re
17
+ import time
18
+ import asyncio
19
+ from typing import Literal, Optional, Tuple
20
+
21
+ import httpx
22
+ from nonebot import logger
23
+
24
+
25
+ # 正则匹配 LaTeX 公式内容
26
+ LATEX_PATTERN = re.compile(
27
+ r"\\begin\{equation\}(.*?)\\end\{equation\}|(?<!\$)(\$(.*?)\$|\$\$(.*?)\$\$|\\\[(.*?)\\\]|\\\[.*?\\\]|\\\((.*?)\\\))",
28
+ re.DOTALL,
29
+ )
30
+
31
+
32
+ MAX_TIME = 0xFFFFFF
20
33
 
21
34
 
22
35
  class ConvertChannel:
@@ -33,8 +46,8 @@ class ConvertChannel:
33
46
  return False, "请勿直接调用母类"
34
47
 
35
48
  @staticmethod
36
- def channel_test() -> int:
37
- return -1
49
+ async def channel_test() -> int:
50
+ return MAX_TIME
38
51
 
39
52
 
40
53
  class L2PChannel(ConvertChannel):
@@ -52,6 +65,7 @@ class L2PChannel(ConvertChannel):
52
65
 
53
66
  async with httpx.AsyncClient(
54
67
  timeout=timeout,
68
+ verify=False,
55
69
  ) as client:
56
70
  while retry > 0:
57
71
  try:
@@ -87,36 +101,38 @@ class L2PChannel(ConvertChannel):
87
101
  return False, "未知错误"
88
102
 
89
103
  @staticmethod
90
- def channel_test() -> int:
91
- with httpx.Client(timeout=5) as client:
104
+ async def channel_test() -> int:
105
+ async with httpx.AsyncClient(timeout=5, verify=False) as client:
92
106
  try:
93
107
  start_time = time.time_ns()
94
108
  latex2png = (
95
- client.get(
109
+ await client.get(
96
110
  "http://www.latex2png.com{}"
97
- + client.post(
98
- "http://www.latex2png.com/api/convert",
99
- json={
100
- "auth": {"user": "guest", "password": "guest"},
101
- "latex": "\\\\int_{a}^{b} x^2 \\\\, dx = \\\\frac{b^3}{3} - \\\\frac{a^3}{5}\n",
102
- "resolution": 600,
103
- "color": "000000",
104
- },
111
+ + (
112
+ await client.post(
113
+ "http://www.latex2png.com/api/convert",
114
+ json={
115
+ "auth": {"user": "guest", "password": "guest"},
116
+ "latex": "\\\\int_{a}^{b} x^2 \\\\, dx = \\\\frac{b^3}{3} - \\\\frac{a^3}{5}\n",
117
+ "resolution": 600,
118
+ "color": "000000",
119
+ },
120
+ )
105
121
  ).json()["url"]
106
122
  ),
107
123
  time.time_ns() - start_time,
108
124
  )
109
125
  except:
110
- return 99999
126
+ return MAX_TIME
111
127
  if latex2png[0].status_code == 200:
112
128
  return latex2png[1]
113
129
  else:
114
- return 99999
130
+ return MAX_TIME
115
131
 
116
132
 
117
133
  class CDCChannel(ConvertChannel):
118
134
 
119
- URL = "http://latex.codecogs.com"
135
+ URL = "https://latex.codecogs.com"
120
136
 
121
137
  async def get_to_convert(
122
138
  self,
@@ -128,6 +144,7 @@ class CDCChannel(ConvertChannel):
128
144
  ) -> Tuple[Literal[True], bytes] | Tuple[Literal[False], bytes | str]:
129
145
  async with httpx.AsyncClient(
130
146
  timeout=timeout,
147
+ verify=False,
131
148
  ) as client:
132
149
 
133
150
  while retry > 0:
@@ -152,27 +169,27 @@ class CDCChannel(ConvertChannel):
152
169
  return False, "未知错误"
153
170
 
154
171
  @staticmethod
155
- def channel_test() -> int:
156
- with httpx.Client(timeout=5) as client:
172
+ async def channel_test() -> int:
173
+ async with httpx.AsyncClient(timeout=5, verify=False) as client:
157
174
  try:
158
175
  start_time = time.time_ns()
159
176
  codecogs = (
160
- client.get(
161
- r"http://latex.codecogs.com/png.image?\huge%20\dpi{600}\\int_{a}^{b}x^2\\,dx=\\frac{b^3}{3}-\\frac{a^3}{5}"
177
+ await client.get(
178
+ r"https://latex.codecogs.com/png.image?\huge%20\dpi{600}\\int_{a}^{b}x^2\\,dx=\\frac{b^3}{3}-\\frac{a^3}{5}"
162
179
  ),
163
180
  time.time_ns() - start_time,
164
181
  )
165
182
  except:
166
- return 99999
183
+ return MAX_TIME
167
184
  if codecogs[0].status_code == 200:
168
185
  return codecogs[1]
169
186
  else:
170
- return 99999
187
+ return MAX_TIME
171
188
 
172
189
 
173
190
  class JRTChannel(ConvertChannel):
174
191
 
175
- URL = "http://latex2image.joeraut.com"
192
+ URL = "https://latex2image.joeraut.com"
176
193
 
177
194
  async def get_to_convert(
178
195
  self,
@@ -185,6 +202,7 @@ class JRTChannel(ConvertChannel):
185
202
 
186
203
  async with httpx.AsyncClient(
187
204
  timeout=timeout,
205
+ verify=False,
188
206
  ) as client:
189
207
  while retry > 0:
190
208
  try:
@@ -196,7 +214,6 @@ class JRTChannel(ConvertChannel):
196
214
  "outputScale": "{}%".format(dpi / 3 * 5),
197
215
  },
198
216
  )
199
- print(post_response)
200
217
  if post_response.status_code == 200:
201
218
 
202
219
  if not (json_response := post_response.json())["error"]:
@@ -218,29 +235,31 @@ class JRTChannel(ConvertChannel):
218
235
  return False, "未知错误"
219
236
 
220
237
  @staticmethod
221
- def channel_test() -> int:
222
- with httpx.Client(timeout=5) as client:
238
+ async def channel_test() -> int:
239
+ async with httpx.AsyncClient(timeout=5, verify=False) as client:
223
240
  try:
224
241
  start_time = time.time_ns()
225
242
  joeraut = (
226
- client.get(
227
- client.post(
228
- "http://www.latex2png.com/api/convert",
229
- json={
230
- "latexInput": "\\\\int_{a}^{b} x^2 \\\\, dx = \\\\frac{b^3}{3} - \\\\frac{a^3}{5}",
231
- "outputFormat": "PNG",
232
- "outputScale": "1000%",
233
- },
243
+ await client.get(
244
+ (
245
+ await client.post(
246
+ "http://www.latex2png.com/api/convert",
247
+ json={
248
+ "latexInput": "\\\\int_{a}^{b} x^2 \\\\, dx = \\\\frac{b^3}{3} - \\\\frac{a^3}{5}",
249
+ "outputFormat": "PNG",
250
+ "outputScale": "1000%",
251
+ },
252
+ )
234
253
  ).json()["imageUrl"]
235
254
  ),
236
255
  time.time_ns() - start_time,
237
256
  )
238
257
  except:
239
- return 99999
258
+ return MAX_TIME
240
259
  if joeraut[0].status_code == 200:
241
260
  return joeraut[1]
242
261
  else:
243
- return 99999
262
+ return MAX_TIME
244
263
 
245
264
 
246
265
  CHANNEL_LIST: list[type[ConvertChannel]] = [L2PChannel, CDCChannel, JRTChannel]
@@ -248,20 +267,17 @@ CHANNEL_LIST: list[type[ConvertChannel]] = [L2PChannel, CDCChannel, JRTChannel]
248
267
 
249
268
  class ConvertLatex:
250
269
 
251
- channel: ConvertChannel
252
-
253
- def __init__(self, channel: Optional[ConvertChannel] = None) -> None:
254
- """
255
- LaTeX在线渲染类
270
+ channel: Optional[ConvertChannel]
256
271
 
257
- Args:
258
- channel (Optional[ConvertChannel], optional):
259
- 选择何种在线转换通道,若为空,则自动选择延迟最低的通道。默认为空。
260
- [WARNING] 请注意!选择通道时采取的是同步函数,因此可能造成阻塞。
261
- """
272
+ def __init__(self, channel: Optional[ConvertChannel] = None):
273
+ self.channel = channel
274
+ logger.info("LaTeX 转换服务将在 Bot 连接时异步加载")
262
275
 
276
+ async def load_channel(self, channel: ConvertChannel | None = None) -> None:
263
277
  if channel is None:
264
- self.channel = self.auto_choose_channel()
278
+ logger.info("正在选择 LaTeX 转换服务频道,请稍等...")
279
+ self.channel = await self.auto_choose_channel()
280
+ logger.info(f"已选择 {self.channel.__class__.__name__} 服务频道")
265
281
  else:
266
282
  self.channel = channel
267
283
 
@@ -276,8 +292,7 @@ class ConvertLatex:
276
292
  """
277
293
  LaTeX 在线渲染
278
294
 
279
- 参数
280
- ====
295
+ 参数:
281
296
 
282
297
  latex: str
283
298
  LaTeX 代码
@@ -289,26 +304,37 @@ class ConvertLatex:
289
304
  超时时间
290
305
  retry_: int
291
306
  重试次数
292
- 返回
293
- ====
307
+ 返回:
294
308
  bytes
295
309
  图片
296
310
  """
297
- return await self.channel.get_to_convert(
311
+ if self.channel is None:
312
+ await self.load_channel()
313
+
314
+ return await self.channel.get_to_convert( # type: ignore
298
315
  latex, dpi, foreground_colour, timeout_, retry_
299
316
  )
300
317
 
301
318
  @staticmethod
302
- def auto_choose_channel() -> ConvertChannel:
319
+ async def auto_choose_channel() -> ConvertChannel:
320
+ """
321
+ 依据访问延迟,自动选择 LaTeX 转换服务频道
303
322
 
304
- return min(
305
- CHANNEL_LIST,
306
- key=lambda channel: channel.channel_test(),
307
- )()
323
+ 返回
324
+ ====
325
+ ConvertChannel
326
+ LaTeX 转换服务实例
327
+ """
308
328
 
329
+ async def channel_test_wrapper(
330
+ channel: type[ConvertChannel],
331
+ ) -> Tuple[int, type[ConvertChannel]]:
332
+ score = await channel.channel_test()
333
+ return score, channel
309
334
 
310
- # 正则匹配 LaTeX 公式内容
311
- LATEX_PATTERN = re.compile(
312
- r"\\begin\{equation\}(.*?)\\end\{equation\}|(?<!\$)(\$(.*?)\$|\$\$(.*?)\$\$|\\\[(.*?)\\\]|\\\[.*?\\\]|\\\((.*?)\\\))",
313
- re.DOTALL,
314
- )
335
+ return min(
336
+ await asyncio.gather(
337
+ *(channel_test_wrapper(channel) for channel in CHANNEL_LIST)
338
+ ),
339
+ key=lambda x: x[0],
340
+ )[1]()
@@ -14,8 +14,8 @@ See the Mulan PSL v2 for more details.
14
14
  """
15
15
 
16
16
  import nonebot
17
- from nonebot.adapters.onebot.v11 import MessageEvent
18
17
 
18
+ from nonebot.adapters.onebot.v11 import MessageEvent
19
19
 
20
20
  # from nonebot.matcher import Matcher
21
21
 
@@ -29,7 +29,7 @@ from nonebot_plugin_alconna import (
29
29
  )
30
30
 
31
31
  from .data import LATEX_PATTERN
32
- from .converter import converter
32
+ from .converter import _converter
33
33
 
34
34
  command_heads = (
35
35
  "latex",
@@ -69,6 +69,7 @@ async def check_for_scan(
69
69
  # print("判断:这不是指令")
70
70
  return False
71
71
  return False
72
+ return False
72
73
 
73
74
 
74
75
  latexg = nonebot.on_message(
@@ -103,7 +104,7 @@ async def handle_pic(
103
104
 
104
105
  for tex_macher in latexes:
105
106
  tex = tex_macher.group().replace("$", "")
106
- if (result := await converter.generate_png(tex))[0]:
107
+ if (result := await _converter.generate_png(tex))[0]:
107
108
  result_msg.append(
108
109
  Alconna_Image(raw=result[1], mimetype="image/png", name="latex.png") # type: ignore
109
110
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: nonebot-plugin-latex
3
- Version: 0.0.2.2
3
+ Version: 0.0.3
4
4
  Summary: 通过互联网公共服务渲染LaTeX公式
5
5
  Author-email: Eilles <EillesWan@outlook.com>
6
6
  License: 木兰宽松许可证, 第2版
@@ -136,14 +136,10 @@ Project-URL: Bug Tracker, https://github.com/EillesWan/nonebot-plugin-latex/issu
136
136
  Requires-Python: <4.0,>=3.9
137
137
  Description-Content-Type: text/markdown
138
138
  License-File: LICENSE
139
- Requires-Dist: playwright>=1.17.2
140
- Requires-Dist: nonebot2>=2.2.0
141
- Requires-Dist: jinja2>=3.0.3
142
- Requires-Dist: markdown>=3.3.6
143
- Requires-Dist: Pygments>=2.10.0
144
- Requires-Dist: python-markdown-math>=0.8
145
- Requires-Dist: pymdown-extensions>=9.1
146
- Requires-Dist: aiofiles>=0.8.0
139
+ Requires-Dist: nonebot2
140
+ Requires-Dist: httpx<0.28.0,>=0.27.0
141
+ Requires-Dist: nonebot-adapter-onebot
142
+ Requires-Dist: nonebot-plugin-alconna
147
143
 
148
144
  # nonebot-plugin-latex
149
145
 
@@ -168,3 +164,8 @@ latex_enable_as_application = true
168
164
  ```
169
165
 
170
166
  这样就可以使用 `latex` 命令进行渲染了,例如 `latex $E=mc^2$` 就会返回这个方程式的渲染图片。
167
+
168
+ ## 提交
169
+
170
+ 各位可以搭建自己的 LaTeX 在线渲染服务,或者直接本地渲染,如果提交到本仓库,在下不胜感激。\
171
+ 对于本地渲染服务,请不要使用 nonebot-plugin-htmlrender
@@ -0,0 +1,10 @@
1
+ nonebot_plugin_latex/__init__.py,sha256=fIXI5w5E0KYMTqIVYWAMoogjzMHLE9V2wEFzNYUY40A,1476
2
+ nonebot_plugin_latex/config.py,sha256=5WOJF-vsuLqGTDGgklpMm-xLd_qdwVb0VCq-n8EwoJQ,198
3
+ nonebot_plugin_latex/converter.py,sha256=rTyeJoZOhXciLcfZ6FWOe0mHczmd2E_sTrqEbJRZ6d8,194
4
+ nonebot_plugin_latex/data.py,sha256=ygcJClUUM4lNR9PotPC1E0rtrRq1swanPWIBnwAvcWM,11443
5
+ nonebot_plugin_latex/main.py,sha256=mMbng0Eo1J3gnztTKbJe_PH63qMgJFZ6Ooj4EY8QKx4,3538
6
+ nonebot_plugin_latex-0.0.3.dist-info/LICENSE,sha256=ISc-fUbtRp39lxd4MpdVr2Saz7XF2yik0RTSRNuhlaM,9375
7
+ nonebot_plugin_latex-0.0.3.dist-info/METADATA,sha256=OWrGenR2OJ2mSyU-C2-kNAWt4XCaU_YZGEdBfE1QX2k,11737
8
+ nonebot_plugin_latex-0.0.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
9
+ nonebot_plugin_latex-0.0.3.dist-info/top_level.txt,sha256=AEtxXrscUdkhTvgg--hAE9WRsW0QVttzK2H-fI9xbGs,21
10
+ nonebot_plugin_latex-0.0.3.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- nonebot_plugin_latex/__init__.py,sha256=sX4NN2jsnbkd4RqLiT0INoRAi0vGgxuSmh40U-6iCZ8,1267
2
- nonebot_plugin_latex/config.py,sha256=5WOJF-vsuLqGTDGgklpMm-xLd_qdwVb0VCq-n8EwoJQ,198
3
- nonebot_plugin_latex/converter.py,sha256=08RmFCBrUda8PlnqazX71aHjntBzlSOJc_ZeUHfMQ_M,89
4
- nonebot_plugin_latex/data.py,sha256=S_KjGkOBGdJMUeKYRfhJ8yllJgbhg1XjPXyypJQ3CFA,10427
5
- nonebot_plugin_latex/main.py,sha256=uBN1bQm-i55RimDfwpOPMOx3bkCuPe-vli2NTzuoXRg,3518
6
- nonebot_plugin_latex-0.0.2.2.dist-info/LICENSE,sha256=ISc-fUbtRp39lxd4MpdVr2Saz7XF2yik0RTSRNuhlaM,9375
7
- nonebot_plugin_latex-0.0.2.2.dist-info/METADATA,sha256=SGjgpPfQFtnqKJ0RU-trNf_18pBT4-kZr0Xygqm10P4,11656
8
- nonebot_plugin_latex-0.0.2.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
9
- nonebot_plugin_latex-0.0.2.2.dist-info/top_level.txt,sha256=AEtxXrscUdkhTvgg--hAE9WRsW0QVttzK2H-fI9xbGs,21
10
- nonebot_plugin_latex-0.0.2.2.dist-info/RECORD,,