PushService.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. # -*- coding: utf-8 -*-
  2. """
  3. @Time : 2022/5/19 11:43
  4. @Auth : Locky
  5. @File :PushService.py
  6. @IDE :PyCharm
  7. """
  8. import logging
  9. import os
  10. import apns2
  11. import jpush
  12. import requests
  13. from pyfcm import FCMNotification
  14. from AnsjerPush.config import APP_BUNDLE_DICT, APNS_MODE, BASE_DIR, APNS_CONFIG, FCM_CONFIG, JPUSH_CONFIG, XMPUSH_CONFIG\
  15. , VIVOPUSH_CONFIG
  16. from Object.RedisObject import RedisObject
  17. from Service.CommonService import CommonService
  18. from Service.VivoPushService.push_admin.APIMessage import PushMessage
  19. from Service.VivoPushService.push_admin.APISender import APISender
  20. class PushObject:
  21. # 推送对象
  22. @staticmethod
  23. def get_msg_title(app_bundle_id, nickname):
  24. """
  25. 获取推送消息标题
  26. @param app_bundle_id: app包id
  27. @param nickname: 设备名
  28. @return: msg_title
  29. """
  30. if app_bundle_id in APP_BUNDLE_DICT.keys():
  31. msg_title = APP_BUNDLE_DICT[app_bundle_id] + '(' + nickname + ')'
  32. else:
  33. msg_title = nickname
  34. return msg_title
  35. @staticmethod
  36. def get_gateway_msg_text(n_time, tz, lang, alarm):
  37. """
  38. 获取网关推送消息内容
  39. @param n_time: 当前时间
  40. @param tz: 时区
  41. @param lang: 语言
  42. @param alarm: 警报
  43. @return: msg_text
  44. """
  45. n_date = CommonService.get_now_time_str(n_time=n_time, tz=tz, lang=lang)
  46. if lang == 'cn':
  47. msg_text = '{} 日期:{}'.format(alarm, n_date)
  48. else:
  49. msg_text = '{} date:{}'.format(alarm, n_date)
  50. return msg_text
  51. @staticmethod
  52. def get_ai_msg_text(channel, n_time, lang, tz, label):
  53. """
  54. 获取AI推送内容
  55. @param channel: 通道
  56. @param n_time: 当前时间
  57. @param lang: 语言
  58. @param tz: 时区
  59. @param label: 识别到的标签
  60. @return: ai_msg_text
  61. """
  62. n_date = CommonService.get_now_time_str(n_time=n_time, tz=tz, lang=lang)
  63. if lang == 'cn':
  64. msg = '摄像头AI识别到了{}'.format(label)
  65. ai_msg_text = '{msg} 通道:{channel} 日期:{date}'.format(msg=msg, channel=channel, date=n_date)
  66. else:
  67. msg = 'Camera AI recognizes {}'.format(label)
  68. ai_msg_text = '{msg} channel:{channel} date:{date}'.format(msg=msg, channel=channel, date=n_date)
  69. return ai_msg_text
  70. @staticmethod
  71. def get_low_power_msg_text(channel, n_time, lang, tz, electricity, is_sys=0):
  72. """
  73. 获取低电量推送内容
  74. @param channel: 通道
  75. @param n_time: 当前时间
  76. @param lang: 语言
  77. @param tz: 时区
  78. @param electricity: 电量
  79. @param is_sys: 是否为系统消息
  80. @return: low_power_msg_text
  81. """
  82. n_date = CommonService.get_now_time_str(n_time=n_time, tz=tz, lang=lang)
  83. if lang == 'cn':
  84. alarm = '剩余电量:' + electricity
  85. if is_sys:
  86. low_power_msg_text = '{} 通道:{}'.format(alarm, channel)
  87. else:
  88. low_power_msg_text = '{} 通道:{} 日期:{}'.format(alarm, channel, n_date)
  89. else:
  90. alarm = 'Battery remaining:' + electricity
  91. if is_sys:
  92. low_power_msg_text = '{} channel:{}'.format(alarm, channel)
  93. else:
  94. low_power_msg_text = '{} channel:{} date:{}'.format(alarm, channel, n_date)
  95. return low_power_msg_text
  96. @staticmethod
  97. def ios_apns_push(nickname, app_bundle_id, token_val, n_time, event_type, msg_title, msg_text,
  98. uid='', channel='1', launch_image=None):
  99. """
  100. ios apns 推送
  101. @param nickname: 设备昵称
  102. @param app_bundle_id: app包id
  103. @param token_val: 推送token
  104. @param n_time: 当前时间
  105. @param event_type: 事件类型
  106. @param msg_title: 推送标题
  107. @param msg_text: 推送内容
  108. @param uid: uid
  109. @param channel: 通道
  110. @param launch_image: 推送图片链接
  111. @return: None
  112. """
  113. logger = logging.getLogger('info')
  114. try:
  115. pem_path = os.path.join(BASE_DIR, APNS_CONFIG[app_bundle_id]['pem_path'])
  116. logger.info('apns推送app_bundle_id:{}, pem_path:{}'.format(app_bundle_id, pem_path))
  117. cli = apns2.APNSClient(mode=APNS_MODE, client_cert=pem_path)
  118. alert = apns2.PayloadAlert(title=msg_title, body=msg_text, launch_image=launch_image)
  119. push_data = {'alert': 'Motion', 'msg': '', 'sound': '', 'zpush': '1', 'uid': uid, 'channel': channel,
  120. 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname,
  121. 'image_url': launch_image
  122. }
  123. payload = apns2.Payload(alert=alert, custom=push_data, sound='default', category='myCategory',
  124. mutable_content=True)
  125. n = apns2.Notification(payload=payload, priority=apns2.PRIORITY_LOW)
  126. res = cli.push(n=n, device_token=token_val, topic=app_bundle_id)
  127. assert res.status_code == 200
  128. except Exception as e:
  129. logger.info('--->IOS推送异常{}'.format(repr(e)))
  130. return repr(e)
  131. @staticmethod
  132. def android_fcm_push(nickname, app_bundle_id, token_val, n_time, event_type, msg_title, msg_text,
  133. uid='', channel='1', image=''):
  134. """
  135. android fcm 推送
  136. @param nickname: 设备昵称
  137. @param app_bundle_id: app包id
  138. @param token_val: 推送token
  139. @param n_time: 当前时间
  140. @param event_type: 事件类型
  141. @param msg_title: 推送标题
  142. @param msg_text: 推送内容
  143. @param uid: uid
  144. @param channel: 通道
  145. @param image: 推送图片链接
  146. @return: None
  147. """
  148. logger = logging.getLogger('info')
  149. try:
  150. serverKey = FCM_CONFIG[app_bundle_id]
  151. push_service = FCMNotification(api_key=serverKey)
  152. push_data = {'alert': 'Motion', 'msg': '', 'sound': 'sound.aif', 'zpush': '1', 'image': image,
  153. 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname,
  154. 'uid': uid, 'channel': channel
  155. }
  156. result = push_service.notify_single_device(registration_id=token_val, message_title=msg_title,
  157. message_body=msg_text, data_message=push_data,
  158. extra_kwargs={'default_sound': True,
  159. 'default_vibrate_timings': True,
  160. 'default_light_settings': True,
  161. }
  162. )
  163. logger.info('fcm推送结果:{}'.format(result))
  164. except Exception as e:
  165. return repr(e)
  166. @staticmethod
  167. def android_jpush(nickname, app_bundle_id, token_val, n_time, event_type, msg_title, msg_text):
  168. """
  169. android 极光 推送
  170. @param nickname: 设备昵称
  171. @param app_bundle_id: app包id
  172. @param token_val: 推送token
  173. @param n_time: 当前时间
  174. @param event_type: 事件类型
  175. @param msg_title: 推送标题
  176. @param msg_text: 推送内容
  177. @return: None
  178. """
  179. try:
  180. app_key = JPUSH_CONFIG[app_bundle_id]['Key']
  181. master_secret = JPUSH_CONFIG[app_bundle_id]['Secret']
  182. # 换成各自的app_key和master_secret
  183. _jpush = jpush.JPush(app_key, master_secret)
  184. push = _jpush.create_push()
  185. push.audience = jpush.registration_id(token_val)
  186. push_data = {'alert': 'Motion', 'msg': '', 'sound': 'sound.aif', 'zpush': '1',
  187. 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname
  188. }
  189. android = jpush.android(title=msg_title, big_text=msg_text, alert=msg_text, extras=push_data,
  190. priority=1, style=1, alert_type=7
  191. )
  192. push.notification = jpush.notification(android=android)
  193. push.platform = jpush.all_
  194. res = push.send()
  195. assert res.status_code == 200
  196. except Exception as e:
  197. return repr(e)
  198. @staticmethod
  199. def android_xmpush(nickname, app_bundle_id, token_val, n_time, event_type, msg_title, msg_text,
  200. uid='', channel='1', image=''):
  201. """
  202. android 小米 推送
  203. @param nickname: 设备昵称
  204. @param app_bundle_id: app包id
  205. @param token_val: 推送token
  206. @param n_time: 当前时间
  207. @param event_type: 事件类型
  208. @param msg_title: 推送标题
  209. @param msg_text: 推送内容
  210. @param uid: uid
  211. @param channel: 通道
  212. @param image: 推送图片链接
  213. @return: None
  214. """
  215. logger = logging.getLogger('info')
  216. try:
  217. url = 'https://api.xmpush.xiaomi.com/v3/message/regid'
  218. app_secret = XMPUSH_CONFIG[app_bundle_id]
  219. payload = {'alert': 'Motion', 'msg': '', 'sound': 'sound.aif', 'zpush': '1',
  220. 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname,
  221. 'uid': uid, 'channel': channel
  222. }
  223. data = {
  224. 'title': msg_title,
  225. 'description': msg_text,
  226. 'payload': 'payload',
  227. 'restricted_package_name': app_bundle_id,
  228. 'registration_id': token_val,
  229. }
  230. if image:
  231. data['extra.notification_style_type'] = 2
  232. data['extra.notification_bigPic_uri'] = image
  233. headers = {
  234. 'Authorization': 'key={}'.format(app_secret)
  235. }
  236. response = requests.post(url, data=data, headers=headers)
  237. logger.info("小米推送返回值:{}".format(response.json()))
  238. assert response.status_code == 200
  239. except Exception as e:
  240. return repr(e)
  241. @staticmethod
  242. def android_vivopush(app_bundle_id, token_val, n_time, event_type, msg_title, msg_text,
  243. uid='', channel='1', image='', skip_type='1', nickname=''):
  244. """
  245. vivo 推送
  246. @param app_bundle_id: app包id
  247. @param token_val: 推送token
  248. @param event_type: 消息类型 (0:运营类消息,1:系统类消息。默认为 0)
  249. @param msg_title: 推送标题
  250. @param msg_text: 推送内容
  251. @param push_mode: 推送模式 (0:正式推送;1:测试推送,默认为0)
  252. @param m_code: 用户请求唯一标识 最大 64 字符
  253. @param skip_type: 跳转类型(1:打开 APP 首页 2:打开链接 3:自定义 4:打开 app 内指定页面)
  254. @param n_time: 当前时间
  255. @param nickname: 设备昵称
  256. @param uid: uid
  257. @param image: 推送图片链接
  258. @param channel: 通道
  259. @return: None
  260. """
  261. logger = logging.getLogger('info')
  262. try:
  263. authToken = 'authToken_' + app_bundle_id
  264. redisObj = RedisObject()
  265. # 获取redis里面的authToken
  266. redis_authToken = redisObj.get_data(key=authToken)
  267. if msg_title == '':
  268. msg_title = '设备'
  269. if redis_authToken is not False:
  270. app_secret = VIVOPUSH_CONFIG[app_bundle_id]['Secret']
  271. sender_send = APISender(app_secret)
  272. sender_send.set_token(redis_authToken)
  273. else:
  274. skip_type = int(skip_type)
  275. app_id = VIVOPUSH_CONFIG[app_bundle_id]['ID']
  276. app_key = VIVOPUSH_CONFIG[app_bundle_id]['Key']
  277. app_secret = VIVOPUSH_CONFIG[app_bundle_id]['Secret']
  278. sender = APISender(app_secret)
  279. rec = sender.get_token(app_id, app_key)
  280. # 存放authToken,有效期3个小时
  281. redisObj = RedisObject()
  282. redisObj.set_data(key=authToken, val=rec['authToken'], expire=10800)
  283. sender_send = APISender(app_secret)
  284. sender_send.set_token(rec['authToken'])
  285. push_data = {'alert': 'Motion', 'msg': '', 'sound': 'sound.aif', 'zpush': '1', 'image': image,
  286. 'received_at': n_time, 'event_time': n_time, 'event_type': event_type, 'nickname': nickname,
  287. 'uid': uid, 'channel': channel
  288. }
  289. # 推送
  290. message = PushMessage() \
  291. .reg_id(token_val) \
  292. .title(msg_title) \
  293. .content(msg_text) \
  294. .push_mode(1) \
  295. .notify_type(1) \
  296. .skip_type(skip_type) \
  297. .request_id('123456') \
  298. .classification(1) \
  299. .client_custom_map(**push_data) \
  300. .message_dict()
  301. rec2 = sender_send.send(message)
  302. logger.info('vivo推送结果:{}'.format(rec2))
  303. except Exception as e:
  304. logger.info('vivo推送异常:{}'.format(e))