templates.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. import logging, copy, pickle
  2. from weakref import ref
  3. from ..returnvalues import ReturnValue
  4. from ..utils import update_info_dict
  5. logger = logging.getLogger('itchat')
  6. class AttributeDict(dict):
  7. def __getattr__(self, value):
  8. keyName = value[0].upper() + value[1:]
  9. try:
  10. return self[keyName]
  11. except KeyError:
  12. raise AttributeError("'%s' object has no attribute '%s'" % (
  13. self.__class__.__name__.split('.')[-1], keyName))
  14. def get(self, v, d=None):
  15. try:
  16. return self[v]
  17. except KeyError:
  18. return d
  19. class UnInitializedItchat(object):
  20. def _raise_error(self, *args, **kwargs):
  21. logger.warning('An itchat instance is called before initialized')
  22. def __getattr__(self, value):
  23. return self._raise_error
  24. class ContactList(list):
  25. ''' when a dict is append, init function will be called to format that dict '''
  26. def __init__(self, *args, **kwargs):
  27. super(ContactList, self).__init__(*args, **kwargs)
  28. self.__setstate__(None)
  29. @property
  30. def core(self):
  31. return getattr(self, '_core', lambda: fakeItchat)() or fakeItchat
  32. @core.setter
  33. def core(self, value):
  34. self._core = ref(value)
  35. def set_default_value(self, initFunction=None, contactClass=None):
  36. if hasattr(initFunction, '__call__'):
  37. self.contactInitFn = initFunction
  38. if hasattr(contactClass, '__call__'):
  39. self.contactClass = contactClass
  40. def append(self, value):
  41. contact = self.contactClass(value)
  42. contact.core = self.core
  43. if self.contactInitFn is not None:
  44. contact = self.contactInitFn(self, contact) or contact
  45. super(ContactList, self).append(contact)
  46. def __deepcopy__(self, memo):
  47. r = self.__class__([copy.deepcopy(v) for v in self])
  48. r.contactInitFn = self.contactInitFn
  49. r.contactClass = self.contactClass
  50. r.core = self.core
  51. return r
  52. def __getstate__(self):
  53. return 1
  54. def __setstate__(self, state):
  55. self.contactInitFn = None
  56. self.contactClass = User
  57. def __str__(self):
  58. return '[%s]' % ', '.join([repr(v) for v in self])
  59. def __repr__(self):
  60. return '<%s: %s>' % (self.__class__.__name__.split('.')[-1],
  61. self.__str__())
  62. class AbstractUserDict(AttributeDict):
  63. def __init__(self, *args, **kwargs):
  64. super(AbstractUserDict, self).__init__(*args, **kwargs)
  65. @property
  66. def core(self):
  67. return getattr(self, '_core', lambda: fakeItchat)() or fakeItchat
  68. @core.setter
  69. def core(self, value):
  70. self._core = ref(value)
  71. def update(self):
  72. return ReturnValue({'BaseResponse': {
  73. 'Ret': -1006,
  74. 'ErrMsg': '%s can not be updated' % \
  75. self.__class__.__name__, }, })
  76. def set_alias(self, alias):
  77. return ReturnValue({'BaseResponse': {
  78. 'Ret': -1006,
  79. 'ErrMsg': '%s can not set alias' % \
  80. self.__class__.__name__, }, })
  81. def set_pinned(self, isPinned=True):
  82. return ReturnValue({'BaseResponse': {
  83. 'Ret': -1006,
  84. 'ErrMsg': '%s can not be pinned' % \
  85. self.__class__.__name__, }, })
  86. def verify(self):
  87. return ReturnValue({'BaseResponse': {
  88. 'Ret': -1006,
  89. 'ErrMsg': '%s do not need verify' % \
  90. self.__class__.__name__, }, })
  91. def get_head_image(self, imageDir=None):
  92. return self.core.get_head_img(self.userName, picDir=imageDir)
  93. def delete_member(self, userName):
  94. return ReturnValue({'BaseResponse': {
  95. 'Ret': -1006,
  96. 'ErrMsg': '%s can not delete member' % \
  97. self.__class__.__name__, }, })
  98. def add_member(self, userName):
  99. return ReturnValue({'BaseResponse': {
  100. 'Ret': -1006,
  101. 'ErrMsg': '%s can not add member' % \
  102. self.__class__.__name__, }, })
  103. def send_raw_msg(self, msgType, content):
  104. return self.core.send_raw_msg(msgType, content, self.userName)
  105. def send_msg(self, msg='Test Message'):
  106. return self.core.send_msg(msg, self.userName)
  107. def send_file(self, fileDir, mediaId=None):
  108. return self.core.send_file(fileDir, self.userName, mediaId)
  109. def send_image(self, fileDir, mediaId=None):
  110. return self.core.send_image(fileDir, self.userName, mediaId)
  111. def send_video(self, fileDir=None, mediaId=None):
  112. return self.core.send_video(fileDir, self.userName, mediaId)
  113. def send(self, msg, mediaId=None):
  114. return self.core.send(msg, self.userName, mediaId)
  115. def search_member(self, name=None, userName=None, remarkName=None, nickName=None,
  116. wechatAccount=None):
  117. return ReturnValue({'BaseResponse': {
  118. 'Ret': -1006,
  119. 'ErrMsg': '%s do not have members' % \
  120. self.__class__.__name__, }, })
  121. def __deepcopy__(self, memo):
  122. r = self.__class__()
  123. for k, v in self.items():
  124. r[copy.deepcopy(k)] = copy.deepcopy(v)
  125. r.core = self.core
  126. return r
  127. def __str__(self):
  128. return '{%s}' % ', '.join(
  129. ['%s: %s' % (repr(k),repr(v)) for k,v in self.items()])
  130. def __repr__(self):
  131. return '<%s: %s>' % (self.__class__.__name__.split('.')[-1],
  132. self.__str__())
  133. def __getstate__(self):
  134. return 1
  135. def __setstate__(self, state):
  136. pass
  137. class User(AbstractUserDict):
  138. def __init__(self, *args, **kwargs):
  139. super(User, self).__init__(*args, **kwargs)
  140. self.__setstate__(None)
  141. def update(self):
  142. r = self.core.update_friend(self.userName)
  143. if r:
  144. update_info_dict(self, r)
  145. return r
  146. def set_alias(self, alias):
  147. return self.core.set_alias(self.userName, alias)
  148. def set_pinned(self, isPinned=True):
  149. return self.core.set_pinned(self.userName, isPinned)
  150. def verify(self):
  151. return self.core.add_friend(**self.verifyDict)
  152. def __deepcopy__(self, memo):
  153. r = super(User, self).__deepcopy__(memo)
  154. r.verifyDict = copy.deepcopy(self.verifyDict)
  155. return r
  156. def __setstate__(self, state):
  157. super(User, self).__setstate__(state)
  158. self.verifyDict = {}
  159. self['MemberList'] = fakeContactList
  160. class MassivePlatform(AbstractUserDict):
  161. def __init__(self, *args, **kwargs):
  162. super(MassivePlatform, self).__init__(*args, **kwargs)
  163. self.__setstate__(None)
  164. def __setstate__(self, state):
  165. super(MassivePlatform, self).__setstate__(state)
  166. self['MemberList'] = fakeContactList
  167. class Chatroom(AbstractUserDict):
  168. def __init__(self, *args, **kwargs):
  169. super(Chatroom, self).__init__(*args, **kwargs)
  170. memberList = ContactList()
  171. userName = self.get('UserName', '')
  172. refSelf = ref(self)
  173. def init_fn(parentList, d):
  174. d.chatroom = refSelf() or \
  175. parentList.core.search_chatrooms(userName=userName)
  176. memberList.set_default_value(init_fn, ChatroomMember)
  177. if 'MemberList' in self:
  178. for member in self.memberList:
  179. memberList.append(member)
  180. self['MemberList'] = memberList
  181. @property
  182. def core(self):
  183. return getattr(self, '_core', lambda: fakeItchat)() or fakeItchat
  184. @core.setter
  185. def core(self, value):
  186. self._core = ref(value)
  187. self.memberList.core = value
  188. for member in self.memberList:
  189. member.core = value
  190. def update(self, detailedMember=False):
  191. r = self.core.update_chatroom(self.userName, detailedMember)
  192. if r:
  193. update_info_dict(self, r)
  194. self['MemberList'] = r['MemberList']
  195. return r
  196. def set_alias(self, alias):
  197. return self.core.set_chatroom_name(self.userName, alias)
  198. def set_pinned(self, isPinned=True):
  199. return self.core.set_pinned(self.userName, isPinned)
  200. def delete_member(self, userName):
  201. return self.core.delete_member_from_chatroom(self.userName, userName)
  202. def add_member(self, userName):
  203. return self.core.add_member_into_chatroom(self.userName, userName)
  204. def search_member(self, name=None, userName=None, remarkName=None, nickName=None,
  205. wechatAccount=None):
  206. with self.core.storageClass.updateLock:
  207. if (name or userName or remarkName or nickName or wechatAccount) is None:
  208. return None
  209. elif userName: # return the only userName match
  210. for m in self.memberList:
  211. if m.userName == userName:
  212. return copy.deepcopy(m)
  213. else:
  214. matchDict = {
  215. 'RemarkName' : remarkName,
  216. 'NickName' : nickName,
  217. 'Alias' : wechatAccount, }
  218. for k in ('RemarkName', 'NickName', 'Alias'):
  219. if matchDict[k] is None:
  220. del matchDict[k]
  221. if name: # select based on name
  222. contact = []
  223. for m in self.memberList:
  224. if any([m.get(k) == name for k in ('RemarkName', 'NickName', 'Alias')]):
  225. contact.append(m)
  226. else:
  227. contact = self.memberList[:]
  228. if matchDict: # select again based on matchDict
  229. friendList = []
  230. for m in contact:
  231. if all([m.get(k) == v for k, v in matchDict.items()]):
  232. friendList.append(m)
  233. return copy.deepcopy(friendList)
  234. else:
  235. return copy.deepcopy(contact)
  236. def __setstate__(self, state):
  237. super(Chatroom, self).__setstate__(state)
  238. if not 'MemberList' in self:
  239. self['MemberList'] = fakeContactList
  240. class ChatroomMember(AbstractUserDict):
  241. def __init__(self, *args, **kwargs):
  242. super(AbstractUserDict, self).__init__(*args, **kwargs)
  243. self.__setstate__(None)
  244. @property
  245. def chatroom(self):
  246. r = getattr(self, '_chatroom', lambda: fakeChatroom)()
  247. if r is None:
  248. userName = getattr(self, '_chatroomUserName', '')
  249. r = self.core.search_chatrooms(userName=userName)
  250. if isinstance(r, dict):
  251. self.chatroom = r
  252. return r or fakeChatroom
  253. @chatroom.setter
  254. def chatroom(self, value):
  255. if isinstance(value, dict) and 'UserName' in value:
  256. self._chatroom = ref(value)
  257. self._chatroomUserName = value['UserName']
  258. def get_head_image(self, imageDir=None):
  259. return self.core.get_head_img(self.userName, self.chatroom.userName, picDir=imageDir)
  260. def delete_member(self, userName):
  261. return self.core.delete_member_from_chatroom(self.chatroom.userName, self.userName)
  262. def send_raw_msg(self, msgType, content):
  263. return ReturnValue({'BaseResponse': {
  264. 'Ret': -1006,
  265. 'ErrMsg': '%s can not send message directly' % \
  266. self.__class__.__name__, }, })
  267. def send_msg(self, msg='Test Message'):
  268. return ReturnValue({'BaseResponse': {
  269. 'Ret': -1006,
  270. 'ErrMsg': '%s can not send message directly' % \
  271. self.__class__.__name__, }, })
  272. def send_file(self, fileDir, mediaId=None):
  273. return ReturnValue({'BaseResponse': {
  274. 'Ret': -1006,
  275. 'ErrMsg': '%s can not send message directly' % \
  276. self.__class__.__name__, }, })
  277. def send_image(self, fileDir, mediaId=None):
  278. return ReturnValue({'BaseResponse': {
  279. 'Ret': -1006,
  280. 'ErrMsg': '%s can not send message directly' % \
  281. self.__class__.__name__, }, })
  282. def send_video(self, fileDir=None, mediaId=None):
  283. return ReturnValue({'BaseResponse': {
  284. 'Ret': -1006,
  285. 'ErrMsg': '%s can not send message directly' % \
  286. self.__class__.__name__, }, })
  287. def send(self, msg, mediaId=None):
  288. return ReturnValue({'BaseResponse': {
  289. 'Ret': -1006,
  290. 'ErrMsg': '%s can not send message directly' % \
  291. self.__class__.__name__, }, })
  292. def __setstate__(self, state):
  293. super(ChatroomMember, self).__setstate__(state)
  294. self['MemberList'] = fakeContactList
  295. def wrap_user_dict(d):
  296. userName = d.get('UserName')
  297. if '@@' in userName:
  298. r = Chatroom(d)
  299. elif d.get('VerifyFlag', 8) & 8 == 0:
  300. r = User(d)
  301. else:
  302. r = MassivePlatform(d)
  303. return r
  304. fakeItchat = UnInitializedItchat()
  305. fakeContactList = ContactList()
  306. fakeChatroom = Chatroom()