You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 line
3.6KB

  1. import asyncio
  2. import re
  3. from wechaty import MessageType
  4. from wechaty.user import Message
  5. from bridge.context import ContextType
  6. from channel.chat_message import ChatMessage
  7. from common.log import logger
  8. from common.tmp_dir import TmpDir
  9. class aobject(object):
  10. """Inheriting this class allows you to define an async __init__.
  11. So you can create objects by doing something like `await MyClass(params)`
  12. """
  13. async def __new__(cls, *a, **kw):
  14. instance = super().__new__(cls)
  15. await instance.__init__(*a, **kw)
  16. return instance
  17. async def __init__(self):
  18. pass
  19. class WechatyMessage(ChatMessage, aobject):
  20. async def __init__(self, wechaty_msg: Message):
  21. super().__init__(wechaty_msg)
  22. room = wechaty_msg.room()
  23. self.msg_id = wechaty_msg.message_id
  24. self.create_time = wechaty_msg.payload.timestamp
  25. self.is_group = room is not None
  26. if wechaty_msg.type() == MessageType.MESSAGE_TYPE_TEXT:
  27. self.ctype = ContextType.TEXT
  28. self.content = wechaty_msg.text()
  29. elif wechaty_msg.type() == MessageType.MESSAGE_TYPE_AUDIO:
  30. self.ctype = ContextType.VOICE
  31. voice_file = await wechaty_msg.to_file_box()
  32. self.content = TmpDir().path() + voice_file.name # content直接存临时目录路径
  33. def func():
  34. loop = asyncio.get_event_loop()
  35. asyncio.run_coroutine_threadsafe(
  36. voice_file.to_file(self.content), loop
  37. ).result()
  38. self._prepare_fn = func
  39. else:
  40. raise NotImplementedError(
  41. "Unsupported message type: {}".format(wechaty_msg.type())
  42. )
  43. from_contact = wechaty_msg.talker() # 获取消息的发送者
  44. self.from_user_id = from_contact.contact_id
  45. self.from_user_nickname = from_contact.name
  46. # group中的from和to,wechaty跟itchat含义不一样
  47. # wecahty: from是消息实际发送者, to:所在群
  48. # itchat: 如果是你发送群消息,from和to是你自己和所在群,如果是别人发群消息,from和to是所在群和你自己
  49. # 但这个差别不影响逻辑,group中只使用到:1.用from来判断是否是自己发的,2.actual_user_id来判断实际发送用户
  50. if self.is_group:
  51. self.to_user_id = room.room_id
  52. self.to_user_nickname = await room.topic()
  53. else:
  54. to_contact = wechaty_msg.to()
  55. self.to_user_id = to_contact.contact_id
  56. self.to_user_nickname = to_contact.name
  57. if (
  58. self.is_group or wechaty_msg.is_self()
  59. ): # 如果是群消息,other_user设置为群,如果是私聊消息,而且自己发的,就设置成对方。
  60. self.other_user_id = self.to_user_id
  61. self.other_user_nickname = self.to_user_nickname
  62. else:
  63. self.other_user_id = self.from_user_id
  64. self.other_user_nickname = self.from_user_nickname
  65. if self.is_group: # wechaty群聊中,实际发送用户就是from_user
  66. self.is_at = await wechaty_msg.mention_self()
  67. if not self.is_at: # 有时候复制粘贴的消息,不算做@,但是内容里面会有@xxx,这里做一下兼容
  68. name = wechaty_msg.wechaty.user_self().name
  69. pattern = f"@{name}(\u2005|\u0020)"
  70. if re.search(pattern, self.content):
  71. logger.debug(f"wechaty message {self.msg_id} include at")
  72. self.is_at = True
  73. self.actual_user_id = self.from_user_id
  74. self.actual_user_nickname = self.from_user_nickname