messages.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  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 library.wechatpy.fields import (
  13. BaseField,
  14. StringField,
  15. IntegerField,
  16. DateTimeField,
  17. FieldDescriptor
  18. )
  19. from library import to_text, to_binary
  20. MESSAGE_TYPES = {}
  21. COMPONENT_MESSAGE_TYPES = {}
  22. def register_message(msg_type):
  23. def register(cls):
  24. MESSAGE_TYPES[msg_type] = cls
  25. return cls
  26. return register
  27. def register_component_message(msg_type):
  28. def register(cls):
  29. COMPONENT_MESSAGE_TYPES[msg_type] = cls
  30. return cls
  31. return register
  32. class MessageMetaClass(type):
  33. """Metaclass for all messages"""
  34. def __new__(mcs, name, bases, attrs):
  35. for b in bases:
  36. if not hasattr(b, "_fields"):
  37. continue
  38. for k, v in b.__dict__.items():
  39. if k in attrs:
  40. continue
  41. if isinstance(v, FieldDescriptor):
  42. attrs[k] = copy.deepcopy(v.field)
  43. mcs = super(MessageMetaClass, mcs).__new__(mcs, name, bases, attrs)
  44. mcs._fields = {}
  45. for name, field in mcs.__dict__.items():
  46. if isinstance(field, BaseField):
  47. field.add_to_class(mcs, name)
  48. return mcs
  49. class BaseMessage(six.with_metaclass(MessageMetaClass)):
  50. """Base class for all messages and events"""
  51. type = 'unknown'
  52. id = IntegerField('MsgId', 0)
  53. source = StringField('FromUserName')
  54. target = StringField('ToUserName')
  55. create_time = DateTimeField('CreateTime')
  56. time = IntegerField('CreateTime')
  57. def __init__(self, message):
  58. self._data = message
  59. def __repr__(self):
  60. _repr = "{klass}({msg})".format(
  61. klass=self.__class__.__name__,
  62. msg=repr(self._data)
  63. )
  64. if six.PY2:
  65. return to_binary(_repr)
  66. else:
  67. return to_text(_repr)
  68. @register_message('text')
  69. class TextMessage(BaseMessage):
  70. """
  71. 文本消息
  72. 详情请参阅
  73. https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
  74. """
  75. type = 'text'
  76. content = StringField('Content')
  77. @register_message('image')
  78. class ImageMessage(BaseMessage):
  79. """
  80. 图片消息
  81. 详情请参阅
  82. https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
  83. """
  84. type = 'image'
  85. media_id = StringField('MediaId')
  86. image = StringField('PicUrl')
  87. @register_message('voice')
  88. class VoiceMessage(BaseMessage):
  89. """
  90. 语音消息
  91. 详情请参阅
  92. https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
  93. """
  94. type = 'voice'
  95. media_id = StringField('MediaId')
  96. format = StringField('Format')
  97. recognition = StringField('Recognition')
  98. @register_message('shortvideo')
  99. class ShortVideoMessage(BaseMessage):
  100. """
  101. 短视频消息
  102. 详情请参阅
  103. https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
  104. """
  105. type = 'shortvideo'
  106. media_id = StringField('MediaId')
  107. thumb_media_id = StringField('ThumbMediaId')
  108. @register_message('video')
  109. class VideoMessage(BaseMessage):
  110. """
  111. 视频消息
  112. 详情请参阅
  113. https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
  114. """
  115. type = 'video'
  116. media_id = StringField('MediaId')
  117. thumb_media_id = StringField('ThumbMediaId')
  118. @register_message('location')
  119. class LocationMessage(BaseMessage):
  120. """
  121. 地理位置消息
  122. 详情请参阅
  123. https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
  124. """
  125. type = 'location'
  126. location_x = StringField('Location_X')
  127. location_y = StringField('Location_Y')
  128. scale = StringField('Scale')
  129. label = StringField('Label')
  130. @property
  131. def location(self):
  132. return self.location_x, self.location_y
  133. @register_message('link')
  134. class LinkMessage(BaseMessage):
  135. """
  136. 链接消息
  137. 详情请参阅
  138. https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
  139. """
  140. type = 'link'
  141. title = StringField('Title')
  142. description = StringField('Description')
  143. url = StringField('Url')
  144. @register_message('miniprogrampage')
  145. class MiniProgramPageMessage(BaseMessage):
  146. """
  147. 小程序卡片消息
  148. 详情请参阅
  149. https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/customer-message/receive.html#小程序卡片消息
  150. """
  151. type = 'miniprogrampage'
  152. app_id = StringField('AppId')
  153. title = StringField('Title')
  154. page_path = StringField('PagePath')
  155. thumb_url = StringField('ThumbUrl')
  156. thumb_media_id = StringField('ThumbMediaId')
  157. class UnknownMessage(BaseMessage):
  158. """未知消息类型"""
  159. pass
  160. class BaseComponentMessage(six.with_metaclass(MessageMetaClass)):
  161. """Base class for all component messages and events"""
  162. type = 'unknown'
  163. appid = StringField('AppId')
  164. create_time = DateTimeField('CreateTime')
  165. def __init__(self, message):
  166. self._data = message
  167. def __repr__(self):
  168. _repr = "{klass}({msg})".format(
  169. klass=self.__class__.__name__,
  170. msg=repr(self._data)
  171. )
  172. if six.PY2:
  173. return to_binary(_repr)
  174. else:
  175. return to_text(_repr)
  176. @register_component_message('component_verify_ticket')
  177. class ComponentVerifyTicketMessage(BaseComponentMessage):
  178. """
  179. component_verify_ticket协议
  180. """
  181. type = 'component_verify_ticket'
  182. verify_ticket = StringField('ComponentVerifyTicket')
  183. @register_component_message('unauthorized')
  184. class ComponentUnauthorizedMessage(BaseComponentMessage):
  185. """
  186. 取消授权通知
  187. """
  188. type = 'unauthorized'
  189. authorizer_appid = StringField('AuthorizerAppid')
  190. @register_component_message('authorized')
  191. class ComponentAuthorizedMessage(BaseComponentMessage):
  192. """
  193. 新增授权通知
  194. """
  195. type = 'authorized'
  196. authorizer_appid = StringField('AuthorizerAppid')
  197. authorization_code = StringField('AuthorizationCode')
  198. authorization_code_expired_time = StringField('AuthorizationCodeExpiredTime')
  199. pre_auth_code = StringField('PreAuthCode')
  200. @register_component_message('updateauthorized')
  201. class ComponentUpdateAuthorizedMessage(BaseComponentMessage):
  202. """
  203. 更新授权通知
  204. """
  205. type = 'updateauthorized'
  206. authorizer_appid = StringField('AuthorizerAppid')
  207. authorization_code = StringField('AuthorizationCode')
  208. authorization_code_expired_time = StringField('AuthorizationCodeExpiredTime')
  209. pre_auth_code = StringField('PreAuthCode')
  210. class ComponentUnknownMessage(BaseComponentMessage):
  211. """
  212. 未知通知
  213. """
  214. type = 'unknown'