business_assistant.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. from __future__ import annotations
  2. from contextlib import suppress
  3. from pyrogram import filters
  4. from pyrogram.enums import ChatMemberStatus
  5. import wbb
  6. from wbb import SUDOERS, app
  7. from wbb.services.business_assistant import BusinessAssistantRuntime
  8. from wbb.utils.dbassistant import (
  9. get_account_settings,
  10. get_business_connection,
  11. get_conversation,
  12. resume_conversation,
  13. )
  14. __MODULE__ = "智能接待"
  15. __HELP__ = "Telegram Business 智能接待由 Web 管理后台配置。"
  16. _runtime: BusinessAssistantRuntime | None = None
  17. async def start_business_assistant_runtime() -> None:
  18. global _runtime
  19. if _runtime is not None:
  20. return
  21. session = getattr(wbb, "aiohttpsession", None)
  22. token = str(getattr(wbb, "BOT_TOKEN", ""))
  23. if not session or not token:
  24. wbb.log.error("智能接待未启动:Telegram Bot 会话或令牌不可用。")
  25. return
  26. _runtime = BusinessAssistantRuntime(token=token, session=session)
  27. status = await _runtime.start()
  28. if status.get("polling_state") == "running":
  29. wbb.log.info("Telegram Business 智能接待已启动。")
  30. else:
  31. wbb.log.error(f"Telegram Business 智能接待未运行:{status.get('last_error') or '未知原因'}")
  32. async def stop_business_assistant_runtime() -> None:
  33. global _runtime
  34. if _runtime is None:
  35. return
  36. await _runtime.stop()
  37. _runtime = None
  38. def get_business_assistant_runtime() -> BusinessAssistantRuntime | None:
  39. return _runtime
  40. async def _ops_group_admin_allowed(query, settings: dict) -> bool:
  41. ops_group_id = int(settings.get("ops_group_id") or 0)
  42. if not ops_group_id or not query.message or int(query.message.chat.id) != ops_group_id:
  43. return False
  44. with suppress(Exception):
  45. member = await app.get_chat_member(ops_group_id, query.from_user.id)
  46. return member.status in {
  47. ChatMemberStatus.OWNER,
  48. ChatMemberStatus.ADMINISTRATOR,
  49. }
  50. return False
  51. @app.on_callback_query(filters.regex(r"^ba:resume:[a-f0-9]{32}$"), group=-20)
  52. async def resume_business_assistant_callback(_, query):
  53. conversation_id = str(query.data).rsplit(":", 1)[-1]
  54. conversation = await get_conversation(conversation_id)
  55. if not conversation:
  56. return await query.answer("会话不存在或已清理。", show_alert=True)
  57. connection = await get_business_connection(conversation["connection_id"])
  58. if not connection:
  59. return await query.answer("Business 连接不存在。", show_alert=True)
  60. settings = await get_account_settings(connection["connection_id"])
  61. owner_id = int((connection.get("user") or {}).get("id") or 0)
  62. allowed = (
  63. query.from_user.id == owner_id
  64. or query.from_user.id in SUDOERS
  65. or await _ops_group_admin_allowed(query, settings)
  66. )
  67. if not allowed:
  68. return await query.answer("只有账号本人或运营群管理员可以恢复。", show_alert=True)
  69. await resume_conversation(conversation_id)
  70. with suppress(Exception):
  71. await query.message.edit_reply_markup(None)
  72. await query.answer("已恢复自动回复。", show_alert=True)