messages.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. # -*- coding: utf-8 -*-
  2. """
  3. wechatpy.messages
  4. ~~~~~~~~~~~~~~~~~~
  5. This module defines all the messages you can get from WeChat server
  6. :copyright: (c) 2014 by messense.
  7. :license: MIT, see LICENSE for more details.
  8. """
  9. from __future__ import absolute_import, unicode_literals
  10. import copy
  11. import six
  12. from wechatpy.fields import (
  13. BaseField,
  14. StringField,
  15. IntegerField,
  16. DateTimeField,
  17. FieldDescriptor
  18. )
  19. from wechatpy.utils import to_text, to_binary
  20. MESSAGE_TYPES = {}
  21. def register_message(msg_type):
  22. def register(cls):
  23. MESSAGE_TYPES[msg_type] = cls
  24. return cls
  25. return register
  26. class MessageMetaClass(type):
  27. """Metaclass for all messages"""
  28. def __new__(cls, name, bases, attrs):
  29. for b in bases:
  30. if not hasattr(b, '_fields'):
  31. continue
  32. for k, v in b.__dict__.items():
  33. if k in attrs:
  34. continue
  35. if isinstance(v, FieldDescriptor):
  36. attrs[k] = copy.deepcopy(v.field)
  37. cls = super(MessageMetaClass, cls).__new__(cls, name, bases, attrs)
  38. cls._fields = {}
  39. for name, field in cls.__dict__.items():
  40. if isinstance(field, BaseField):
  41. field.add_to_class(cls, name)
  42. return cls
  43. class BaseMessage(six.with_metaclass(MessageMetaClass)):
  44. """Base class for all messages and events"""
  45. type = 'unknown'
  46. id = IntegerField('MsgId', 0)
  47. source = StringField('FromUserName')
  48. target = StringField('ToUserName')
  49. create_time = DateTimeField('CreateTime')
  50. time = IntegerField('CreateTime')
  51. def __init__(self, message):
  52. self._data = message
  53. def __repr__(self):
  54. _repr = "{klass}({msg})".format(
  55. klass=self.__class__.__name__,
  56. msg=repr(self._data)
  57. )
  58. if six.PY2:
  59. return to_binary(_repr)
  60. else:
  61. return to_text(_repr)
  62. @register_message('text')
  63. class TextMessage(BaseMessage):
  64. """
  65. 文本消息
  66. 详情请参阅
  67. http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
  68. """
  69. type = 'text'
  70. content = StringField('Content')
  71. @register_message('image')
  72. class ImageMessage(BaseMessage):
  73. """
  74. 图片消息
  75. 详情请参阅
  76. http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
  77. """
  78. type = 'image'
  79. media_id = StringField('MediaId')
  80. image = StringField('PicUrl')
  81. @register_message('voice')
  82. class VoiceMessage(BaseMessage):
  83. """
  84. 语音消息
  85. 详情请参阅
  86. http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
  87. """
  88. type = 'voice'
  89. media_id = StringField('MediaId')
  90. format = StringField('Format')
  91. recognition = StringField('Recognition')
  92. @register_message('shortvideo')
  93. class ShortVideoMessage(BaseMessage):
  94. """
  95. 短视频消息
  96. 详情请参阅
  97. http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
  98. """
  99. type = 'shortvideo'
  100. media_id = StringField('MediaId')
  101. thumb_media_id = StringField('ThumbMediaId')
  102. @register_message('video')
  103. class VideoMessage(BaseMessage):
  104. """
  105. 视频消息
  106. 详情请参阅
  107. http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
  108. """
  109. type = 'video'
  110. media_id = StringField('MediaId')
  111. thumb_media_id = StringField('ThumbMediaId')
  112. @register_message('location')
  113. class LocationMessage(BaseMessage):
  114. """
  115. 地理位置消息
  116. 详情请参阅
  117. http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
  118. """
  119. type = 'location'
  120. location_x = StringField('Location_X')
  121. location_y = StringField('Location_Y')
  122. scale = StringField('Scale')
  123. label = StringField('Label')
  124. @property
  125. def location(self):
  126. return self.location_x, self.location_y
  127. @register_message('link')
  128. class LinkMessage(BaseMessage):
  129. """
  130. 链接消息
  131. 详情请参阅
  132. http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
  133. """
  134. type = 'link'
  135. title = StringField('Title')
  136. description = StringField('Description')
  137. url = StringField('Url')
  138. class UnknownMessage(BaseMessage):
  139. """未知消息类型"""
  140. pass