vibego 0.2.36__py3-none-any.whl → 0.2.37__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.

Potentially problematic release.


This version of vibego might be problematic. Click here for more details.

bot.py CHANGED
@@ -482,6 +482,11 @@ _ESCAPED_CODE_BLOCK_PATTERN = re.compile(
482
482
  re.DOTALL
483
483
  )
484
484
 
485
+ _OPTIMIZE_CHECKBOX_PATTERN = re.compile(r"\\\[\s+\\\]")
486
+ _OPTIMIZE_DOT_PATTERN = re.compile(
487
+ r"(?P<prefix>[0-9A-Za-z\u4e00-\u9fff])\\\.(?=(?:\s|$|[)\]\u3002\uff0c\uff1b\uff1a\uff01\uff1f]))"
488
+ )
489
+
485
490
 
486
491
  def _is_already_escaped(text: str) -> bool:
487
492
  """检测文本是否已经包含 MarkdownV2 转义字符。
@@ -583,6 +588,47 @@ def _prepare_model_payload(text: str) -> str:
583
588
  return text
584
589
 
585
590
 
591
+ def _optimize_markdown_v2_payload(payload: str) -> str:
592
+ """在保留 MarkdownV2 合法性的前提下,移除常见的冗余反斜杠。"""
593
+
594
+ if not payload or "\\" not in payload:
595
+ return payload
596
+
597
+ preserved_segments: list[str] = []
598
+
599
+ def _preserve(segment: re.Match[str]) -> str:
600
+ placeholder = f"__OPT_CODE_BLOCK_{len(preserved_segments)}__"
601
+ preserved_segments.append(segment.group(0))
602
+ return placeholder
603
+
604
+ stripped = CODE_SEGMENT_RE.sub(_preserve, payload)
605
+ stripped = _OPTIMIZE_CHECKBOX_PATTERN.sub("[ ]", stripped)
606
+
607
+ def _dot_replacer(match: re.Match[str]) -> str:
608
+ prefix = match.group("prefix")
609
+ return f"{prefix}."
610
+
611
+ stripped = _OPTIMIZE_DOT_PATTERN.sub(_dot_replacer, stripped)
612
+
613
+ for index, segment in enumerate(preserved_segments):
614
+ stripped = stripped.replace(f"__OPT_CODE_BLOCK_{index}__", segment)
615
+
616
+ return stripped
617
+
618
+
619
+ def _prepare_model_payload_variants(text: str) -> tuple[str, Optional[str]]:
620
+ """返回首选与备用的 MarkdownV2 内容,首选尽量减少转义。"""
621
+
622
+ strict_payload = _prepare_model_payload(text)
623
+ if not _IS_MARKDOWN_V2:
624
+ return strict_payload, None
625
+
626
+ optimized_payload = _optimize_markdown_v2_payload(strict_payload)
627
+ if optimized_payload != strict_payload:
628
+ return optimized_payload, strict_payload
629
+ return strict_payload, None
630
+
631
+
586
632
  def _extract_bad_request_message(exc: TelegramBadRequest) -> str:
587
633
  message = getattr(exc, "message", None)
588
634
  if not message:
@@ -636,6 +682,7 @@ async def _send_with_markdown_guard(
636
682
  sender: Callable[[str], Awaitable[None]],
637
683
  *,
638
684
  raw_sender: Optional[Callable[[str], Awaitable[None]]] = None,
685
+ fallback_payload: Optional[str] = None,
639
686
  ) -> str:
640
687
  try:
641
688
  await sender(text)
@@ -644,6 +691,19 @@ async def _send_with_markdown_guard(
644
691
  if not _is_markdown_parse_error(exc):
645
692
  raise
646
693
 
694
+ if fallback_payload and fallback_payload != text:
695
+ try:
696
+ await sender(fallback_payload)
697
+ worker_log.debug(
698
+ "Markdown 优化回退为严格转义版本",
699
+ extra={"length": len(fallback_payload)},
700
+ )
701
+ return fallback_payload
702
+ except TelegramBadRequest as fallback_exc:
703
+ if not _is_markdown_parse_error(fallback_exc):
704
+ raise
705
+ exc = fallback_exc
706
+
647
707
  sanitized: Optional[str]
648
708
  if _IS_MARKDOWN_V2:
649
709
  sanitized = _escape_markdown_v2(text)
@@ -740,7 +800,11 @@ async def reply_large_text(
740
800
  """
741
801
  bot = current_bot()
742
802
  parse_mode_value = parse_mode if parse_mode is not None else _parse_mode_value()
743
- prepared = text if preformatted else _prepare_model_payload(text)
803
+ if preformatted:
804
+ prepared = text
805
+ fallback_payload = None
806
+ else:
807
+ prepared, fallback_payload = _prepare_model_payload_variants(text)
744
808
 
745
809
  async def _send_formatted_message(payload: str) -> None:
746
810
  await bot.send_message(
@@ -757,6 +821,7 @@ async def reply_large_text(
757
821
  prepared,
758
822
  _send_formatted_message,
759
823
  raw_sender=_send_raw_message,
824
+ fallback_payload=fallback_payload,
760
825
  )
761
826
 
762
827
  worker_log.info(
@@ -775,10 +840,12 @@ async def reply_large_text(
775
840
  f"内容较长,已生成附件 `{attachment_name}`,请下载查看全文。"
776
841
  )
777
842
 
843
+ summary_prepared, summary_fallback = _prepare_model_payload_variants(summary_text)
778
844
  delivered_summary = await _send_with_markdown_guard(
779
- summary_text,
845
+ summary_prepared,
780
846
  _send_formatted_message,
781
847
  raw_sender=_send_raw_message,
848
+ fallback_payload=summary_fallback,
782
849
  )
783
850
 
784
851
  document = BufferedInputFile(text.encode("utf-8"), filename=attachment_name)
@@ -1492,7 +1559,7 @@ async def _broadcast_worker_keyboard(bot: Bot) -> None:
1492
1559
  continue
1493
1560
 
1494
1561
  parse_mode = _parse_mode_value()
1495
- prepared = _prepare_model_payload(text)
1562
+ prepared, fallback_payload = _prepare_model_payload_variants(text)
1496
1563
 
1497
1564
  async def _send_formatted(payload: str) -> None:
1498
1565
  await bot.send_message(
@@ -1515,6 +1582,7 @@ async def _broadcast_worker_keyboard(bot: Bot) -> None:
1515
1582
  prepared,
1516
1583
  _send_formatted,
1517
1584
  raw_sender=_send_raw,
1585
+ fallback_payload=fallback_payload,
1518
1586
  )
1519
1587
  except TelegramForbiddenError as exc:
1520
1588
  worker_log.warning("推送任务列表被拒绝:%s", exc, extra={**_session_extra(), "chat": chat_id})
@@ -2772,13 +2840,32 @@ async def _answer_with_markdown(
2772
2840
  *,
2773
2841
  reply_markup: InlineKeyboardMarkup | ReplyKeyboardMarkup | None = None,
2774
2842
  ) -> Optional[Message]:
2775
- prepared = _prepare_model_payload(text)
2776
- try:
2777
- sent = await message.answer(
2778
- prepared,
2843
+ prepared, fallback_payload = _prepare_model_payload_variants(text)
2844
+ sent_message: Optional[Message] = None
2845
+
2846
+ async def _send(payload: str) -> None:
2847
+ nonlocal sent_message
2848
+ sent_message = await message.answer(
2849
+ payload,
2779
2850
  parse_mode=_parse_mode_value(),
2780
2851
  reply_markup=reply_markup,
2781
2852
  )
2853
+
2854
+ async def _send_raw(payload: str) -> None:
2855
+ nonlocal sent_message
2856
+ sent_message = await message.answer(
2857
+ payload,
2858
+ parse_mode=None,
2859
+ reply_markup=reply_markup,
2860
+ )
2861
+
2862
+ try:
2863
+ await _send_with_markdown_guard(
2864
+ prepared,
2865
+ _send,
2866
+ raw_sender=_send_raw,
2867
+ fallback_payload=fallback_payload,
2868
+ )
2782
2869
  except TelegramBadRequest as exc:
2783
2870
  worker_log.warning(
2784
2871
  "发送消息失败:%s",
@@ -2786,7 +2873,7 @@ async def _answer_with_markdown(
2786
2873
  extra={"chat": getattr(message.chat, "id", None)},
2787
2874
  )
2788
2875
  return None
2789
- return sent
2876
+ return sent_message
2790
2877
 
2791
2878
 
2792
2879
  async def _edit_message_with_markdown(
@@ -2795,11 +2882,27 @@ async def _edit_message_with_markdown(
2795
2882
  *,
2796
2883
  reply_markup: InlineKeyboardMarkup | None = None,
2797
2884
  ) -> None:
2798
- prepared = _prepare_model_payload(text)
2799
- await callback.message.edit_text(
2885
+ prepared, fallback_payload = _prepare_model_payload_variants(text)
2886
+
2887
+ async def _send(payload: str) -> None:
2888
+ await callback.message.edit_text(
2889
+ payload,
2890
+ parse_mode=_parse_mode_value(),
2891
+ reply_markup=reply_markup,
2892
+ )
2893
+
2894
+ async def _send_raw(payload: str) -> None:
2895
+ await callback.message.edit_text(
2896
+ payload,
2897
+ parse_mode=None,
2898
+ reply_markup=reply_markup,
2899
+ )
2900
+
2901
+ await _send_with_markdown_guard(
2800
2902
  prepared,
2801
- parse_mode=_parse_mode_value(),
2802
- reply_markup=reply_markup,
2903
+ _send,
2904
+ raw_sender=_send_raw,
2905
+ fallback_payload=fallback_payload,
2803
2906
  )
2804
2907
 
2805
2908
 
@@ -2811,13 +2914,29 @@ async def _try_edit_message(
2811
2914
  ) -> bool:
2812
2915
  if message is None:
2813
2916
  return False
2814
- prepared = _prepare_model_payload(text)
2815
- try:
2917
+ prepared, fallback_payload = _prepare_model_payload_variants(text)
2918
+
2919
+ async def _send(payload: str) -> None:
2816
2920
  await message.edit_text(
2817
- prepared,
2921
+ payload,
2818
2922
  parse_mode=_parse_mode_value(),
2819
2923
  reply_markup=reply_markup,
2820
2924
  )
2925
+
2926
+ async def _send_raw(payload: str) -> None:
2927
+ await message.edit_text(
2928
+ payload,
2929
+ parse_mode=None,
2930
+ reply_markup=reply_markup,
2931
+ )
2932
+
2933
+ try:
2934
+ await _send_with_markdown_guard(
2935
+ prepared,
2936
+ _send,
2937
+ raw_sender=_send_raw,
2938
+ fallback_payload=fallback_payload,
2939
+ )
2821
2940
  return True
2822
2941
  except TelegramBadRequest as exc:
2823
2942
  worker_log.info(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibego
3
- Version: 0.2.36
3
+ Version: 0.2.37
4
4
  Summary: vibego CLI:用于初始化与管理 Telegram Master Bot 的工具
5
5
  Author: Hypha
6
6
  License-Expression: LicenseRef-Proprietary
@@ -1,4 +1,4 @@
1
- bot.py,sha256=jVPxYu3rUCFmypgJzgc8iy97zOXidhvCnlZNwFtkxv4,270454
1
+ bot.py,sha256=RHE0IJcgiuXThExBQs4ZqxYF-Tfqpg3tIC5yYTGLr4o,274363
2
2
  logging_setup.py,sha256=gvxHi8mUwK3IhXJrsGNTDo-DR6ngkyav1X-tvlBF_IE,4613
3
3
  master.py,sha256=ZW4A3Gh0MUKFnfZX-VJ7OCNnBzlEcOWkPKYH92OfyKA,112967
4
4
  project_repository.py,sha256=UcthtSGOJK0cTE5bQCneo3xkomRG-kyc1N1QVqxeHIs,17577
@@ -427,14 +427,14 @@ tasks/fsm.py,sha256=rKXXLEieQQU4r2z_CZUvn1_70FXiZXBBugF40gpe_tQ,1476
427
427
  tasks/models.py,sha256=N_qqRBo9xMSV0vbn4k6bLBXT8C_dp_oTFUxvdx16ZQM,2459
428
428
  tasks/service.py,sha256=w_S_aWiVqRXzXEpimLDsuCCCX2lB5uDkff9aKThBw9c,41916
429
429
  telegram_markdown/__init__.py,sha256=bG3H9fWn5GfTqC6xvd49xbVdYWfSFeaX2nefweOYcWY,9757
430
- vibego_cli/__init__.py,sha256=p-CPmV5XSaL8LOoFcrAi-ds8pvLeygAon4JKakgK7MY,311
430
+ vibego_cli/__init__.py,sha256=n3G3v9lJLz5-SZnbrTB8h6FL6u1LF37J0JJ1pCcB_CM,311
431
431
  vibego_cli/__main__.py,sha256=qqTrYmRRLe4361fMzbI3-CqpZ7AhTofIHmfp4ykrrBY,158
432
432
  vibego_cli/config.py,sha256=VxkPJMq01tA3h3cOkH-z_tiP7pMgfSGGicRvUnCWkhI,3054
433
433
  vibego_cli/deps.py,sha256=1nRXI7Dd-S1hYE8DligzK5fIluQWETRUj4_OKL0DikQ,1419
434
434
  vibego_cli/main.py,sha256=X__NXwZnIDIFbdKSTbNyZgZHKcPlN0DQz9sqTI1aQ9E,12158
435
435
  vibego_cli/data/worker_requirements.txt,sha256=QSt30DSSSHtfucTFPpc7twk9kLS5rVLNTcvDiagxrZg,62
436
- vibego-0.2.36.dist-info/METADATA,sha256=MP9mOr2c7s7mckhdVFBeVeHx0MQH0VKuZqRPSFUoshE,10519
437
- vibego-0.2.36.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
438
- vibego-0.2.36.dist-info/entry_points.txt,sha256=Lsy_zm-dlyxt8-9DL9blBReIwU2k22c8-kifr46ND1M,48
439
- vibego-0.2.36.dist-info/top_level.txt,sha256=rWDj9KERtbJL6Lar9Xa0O6dthaFSY_jc1WNpQgUrXCM,87
440
- vibego-0.2.36.dist-info/RECORD,,
436
+ vibego-0.2.37.dist-info/METADATA,sha256=U_HSCRWJDsLvWIP2xu86nBcqrDhkJsOESZBJzLDnvSw,10519
437
+ vibego-0.2.37.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
438
+ vibego-0.2.37.dist-info/entry_points.txt,sha256=Lsy_zm-dlyxt8-9DL9blBReIwU2k22c8-kifr46ND1M,48
439
+ vibego-0.2.37.dist-info/top_level.txt,sha256=rWDj9KERtbJL6Lar9Xa0O6dthaFSY_jc1WNpQgUrXCM,87
440
+ vibego-0.2.37.dist-info/RECORD,,
vibego_cli/__init__.py CHANGED
@@ -7,6 +7,6 @@ from __future__ import annotations
7
7
 
8
8
  __all__ = ["main", "__version__"]
9
9
 
10
- __version__ = "0.2.36"
10
+ __version__ = "0.2.37"
11
11
 
12
12
  from .main import main # noqa: E402