AiController.py 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. @Copyright (C) ansjer cop Video Technology Co.,Ltd.All rights reserved.
  5. @AUTHOR: ASJRD018
  6. @NAME: AnsjerFormal
  7. @software: PyCharm
  8. @DATE: 2018/12/5 9:30
  9. @Version: python3.6
  10. @MODIFY DECORD:ansjer dev
  11. @file: cloudstorage.py
  12. @Contact: chanjunkai@163.com
  13. """
  14. import base64
  15. import json
  16. import os
  17. import time
  18. import glob
  19. import urllib
  20. from urllib.parse import quote, parse_qs, unquote
  21. import apns2
  22. import boto3
  23. import jpush
  24. import oss2
  25. import paypalrestsdk
  26. import threading
  27. import calendar
  28. import datetime
  29. import logging
  30. import sys
  31. import requests
  32. from aliyunsdkcore import client
  33. from aliyunsdksts.request.v20150401 import AssumeRoleRequest
  34. from boto3.session import Session
  35. from django.http import JsonResponse, HttpResponseRedirect, HttpResponse
  36. from django.db import transaction
  37. from django.views.generic.base import View
  38. import jwt
  39. from Object.ETkObject import ETkObject
  40. from pyfcm import FCMNotification
  41. from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, OSS_ROLE_ARN, SERVER_DOMAIN, PAYPAL_CRD, \
  42. SERVER_DOMAIN_SSL, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_ARN, APNS_MODE, APNS_CONFIG, BASE_DIR, \
  43. JPUSH_CONFIG, FCM_CONFIG, OAUTH_ACCESS_TOKEN_SECRET
  44. from Controller.CheckUserData import DataValid
  45. from Model.models import Device_Info, Order_Model, Store_Meal, VodHlsModel, OssCrdModel, UID_Bucket, StsCrdModel, \
  46. ExperienceContextModel, Pay_Type, CDKcontextModel, Device_User, SysMassModel, SysMsgModel, UidPushModel, \
  47. Unused_Uid_Meal, UIDMainUser, UserModel, PromotionRuleModel, VideoPlaybackTimeModel, CloudLogModel, CouponModel, \
  48. AiStoreMeal, AiService, UidSetModel, Ai_Push_Info, iotdeviceInfoModel, AiProcessTime
  49. from Object.AWS.S3Email import S3Email
  50. from Object.AliPayObject import AliPayObject
  51. from Object.AliSmsObject import AliSmsObject
  52. from Object.RedisObject import RedisObject
  53. from Object.ResponseObject import ResponseObject
  54. from Object.TokenObject import TokenObject
  55. from Object.UidTokenObject import UidTokenObject
  56. from Service.CommonService import CommonService
  57. from Object.m3u8generate import PlaylistGenerator
  58. from Object.WechatPayObject import WechatPayObject
  59. from django.db.models import Q, F, Count
  60. from Controller.PaymentCycle import Paypal
  61. from decimal import Decimal
  62. from Ansjer.config import SERVER_TYPE
  63. from Service.ModelService import ModelService
  64. from Object import MergePic
  65. import boto3
  66. import botocore
  67. from botocore import client
  68. # AI服务
  69. class AiView(View):
  70. def get(self, request, *args, **kwargs):
  71. request.encoding = 'utf-8'
  72. operation = kwargs.get('operation')
  73. return self.validation(request.GET, request, operation)
  74. def post(self, request, *args, **kwargs):
  75. request.encoding = 'utf-8'
  76. operation = kwargs.get('operation')
  77. return self.validation(request.POST, request, operation)
  78. def validation(self, request_dict, request, operation):
  79. response = ResponseObject()
  80. if operation is None:
  81. return response.json(444, 'error path')
  82. elif operation == 'identification': # ai识别
  83. return self.do_ai_identification(request.POST, response)
  84. elif operation == 'doPayPalCallBack': # paypal支付回调
  85. return self.do_pay_by_paypal_callback(request_dict, response)
  86. elif operation == 'doAlipayCallBack': # 支付宝支付回调
  87. return self.do_alipay_callback(request_dict, response)
  88. elif operation == 'doWechatCallBack': # 微信支付回调
  89. return self.do_wechat_callback(request, response)
  90. else:
  91. token = request_dict.get('token', None)
  92. # 设备主键uid
  93. tko = TokenObject(token)
  94. response.lang = tko.lang
  95. if tko.code != 0:
  96. return response.json(tko.code)
  97. userID = tko.userID
  98. if operation == 'createpayorder': # 创建支付订单
  99. return self.do_create_pay_order(request_dict, request, userID, response)
  100. elif operation == 'changeaistatus': # 修改AI开关状态
  101. return self.do_change_ai_status(userID, request_dict, response)
  102. elif operation == 'getAiStatus': # 获取AI开关状态
  103. return self.getAiStatus(userID, request_dict, response)
  104. elif operation == 'commoditylist': # 获取AI套餐列表
  105. return self.do_commodity_list(userID, request_dict, response)
  106. elif operation == 'identification': # ai识别
  107. return self.do_ai_identification(request_dict, response)
  108. elif operation == 'queryInfo': # 查询消息列表
  109. return self.queryInfo(userID, request_dict, response)
  110. elif operation == 'readInfo': # 消息已读
  111. return self.readInfo(userID, request_dict, response)
  112. elif operation == 'deleteInfo': # 删除消息
  113. return self.deleteInfo(userID, request_dict, response)
  114. elif operation == 'queryorderlist': # 查询订单
  115. return self.do_querylist(userID, request_dict, response)
  116. elif operation == 'getUsingPackage': # 获取设备当前使用的ai套餐
  117. return self.getUsingPackage(request_dict, userID, response)
  118. elif operation == 'updateJpushTime': # 测试ai识别app的推送时间
  119. return self.update_jpush_time(userID, request_dict, response)
  120. else:
  121. return response.json(414)
  122. def do_change_ai_status(self, userID, request_dict, response):
  123. token_val = request_dict.get('token_val', None)
  124. appBundleId = request_dict.get('appBundleId', None)
  125. app_type = request_dict.get('app_type', None)
  126. push_type = request_dict.get('push_type', None)
  127. status = request_dict.get('status', None)
  128. m_code = request_dict.get('m_code', None)
  129. uid = request_dict.get('uid', None)
  130. # 设备语言
  131. lang = request_dict.get('lang', 'en')
  132. tz = request_dict.get('tz', '0')
  133. # 消息提醒功能新增
  134. # 如果传空上来,就默认为0
  135. if tz == '':
  136. tz = 0
  137. else:
  138. tz = tz.replace("GMT", "")
  139. detect_group = request_dict.get('detect_group', None)
  140. interval = request_dict.get('interval', None)
  141. if not status:
  142. return response.json(444, 'status')
  143. # 关闭推送
  144. if not all([appBundleId, app_type, token_val, uid, m_code]):
  145. return response.json(444, 'appBundleId,app_type,token_val,uid,m_code')
  146. # 判断推送类型对应key是否存在
  147. if push_type == '0':
  148. if appBundleId not in APNS_CONFIG.keys():
  149. return response.json(904)
  150. elif push_type == '1':
  151. if appBundleId not in FCM_CONFIG.keys():
  152. return response.json(904)
  153. elif push_type == '2':
  154. if appBundleId not in JPUSH_CONFIG.keys():
  155. return response.json(904)
  156. else:
  157. return response.json(173)
  158. try:
  159. hasAiService = AiService.objects.filter(uid=uid, use_status=1)
  160. if not hasAiService.exists():
  161. return response.json(10053)
  162. nowTime = int(time.time())
  163. endTime = hasAiService.values('endTime')[0]['endTime']
  164. if nowTime > endTime:
  165. return response.json(10054)
  166. dvqs = Device_Info.objects.filter(userID_id=userID, UID=uid)
  167. status = int(status)
  168. nowTime = int(time.time())
  169. if not dvqs.exists():
  170. return response.json(14)
  171. uid_set_qs = UidSetModel.objects.filter(uid=uid)
  172. if uid_set_qs.exists():
  173. uid_set_id = uid_set_qs[0].id
  174. qs_data = {
  175. 'updTime': nowTime,
  176. }
  177. if interval:
  178. qs_data['detect_interval'] = int(interval)
  179. if detect_group:
  180. qs_data['detect_group'] = detect_group
  181. uid_set_qs.update(**qs_data)
  182. else:
  183. qs_data = {
  184. 'uid': uid,
  185. 'addTime': nowTime,
  186. 'updTime': nowTime,
  187. }
  188. if interval:
  189. qs_data['detect_interval'] = int(interval)
  190. if detect_group:
  191. qs_data['detect_group'] = detect_group
  192. # 添加设备配置
  193. uid_set_qs = UidSetModel.objects.create(**qs_data)
  194. uid_set_id = uid_set_qs.id
  195. topic_name = 'ansjer/generic/{}'.format(uid)
  196. if status == 0: # 关闭
  197. hasAiService.update(**qs_data)
  198. # mqtt通知设备关闭AI识别功能
  199. msg = {'commandType': 'AIDisable'}
  200. req_success = CommonService.req_publish_mqtt_msg(uid, topic_name, msg)
  201. if not req_success:
  202. return response.json(10044)
  203. return response.json(0)
  204. elif status == 1: # 开启
  205. hasAiService.update(**qs_data)
  206. uid_push_qs = UidPushModel.objects.filter(userID_id=userID, m_code=m_code, uid_set__uid=uid)
  207. if uid_push_qs.exists():
  208. uid_push_update_dict = {
  209. 'appBundleId': appBundleId,
  210. 'app_type': app_type,
  211. 'push_type': push_type,
  212. 'token_val': token_val,
  213. 'updTime': nowTime,
  214. 'lang': lang,
  215. 'tz': tz
  216. }
  217. uid_push_qs.update(**uid_push_update_dict)
  218. else:
  219. # uid_set_id = uid_set_qs[0].id
  220. uid_push_create_dict = {
  221. 'uid_set_id': uid_set_id,
  222. 'userID_id': userID,
  223. 'appBundleId': appBundleId,
  224. 'app_type': app_type,
  225. 'push_type': push_type,
  226. 'token_val': token_val,
  227. 'm_code': m_code,
  228. 'addTime': nowTime,
  229. 'updTime': nowTime,
  230. 'lang': lang,
  231. 'tz': tz
  232. }
  233. # 绑定设备推送
  234. UidPushModel.objects.create(**uid_push_create_dict)
  235. etkObj = ETkObject(etk='')
  236. etk = etkObj.encrypt(uid)
  237. aiIdentificationUrl = "{DETECT_PUSH_DOMAIN}AiService/identification".format(DETECT_PUSH_DOMAIN=SERVER_DOMAIN_SSL)
  238. # mqtt通知设备开启AI识别功能
  239. msg = {
  240. 'commandType': 'AIEnable',
  241. 'payload': {
  242. 'etk': etk,
  243. 'endTime': endTime,
  244. 'aiIdentificationUrl': aiIdentificationUrl,
  245. }
  246. },
  247. req_success = CommonService.req_publish_mqtt_msg(uid, topic_name, msg)
  248. if not req_success:
  249. return response.json(10044)
  250. return response.json(0, {'aiIdentificationUrl': aiIdentificationUrl, 'endTime': endTime, 'etk': etk})
  251. except Exception as e:
  252. print(e)
  253. return response.json(500, repr(e))
  254. def getAiStatus(self, userID, request_dict, response):
  255. uid = request_dict.get('uid', None)
  256. if not uid:
  257. return response.json(444)
  258. try:
  259. ai_server_qs = AiService.objects.filter(uid=uid).values('detect_status', 'detect_group')
  260. if not ai_server_qs.exists():
  261. return response.json(173)
  262. res = {
  263. 'detect_status': ai_server_qs[0]['detect_status'],
  264. 'detect_group': ai_server_qs[0]['detect_group'],
  265. }
  266. return response.json(0, {'data': res})
  267. except Exception as e:
  268. return response.json(500, repr(e))
  269. def do_commodity_list(self, userID, request_dict, response):
  270. uid = request_dict.get('uid', None)
  271. lang = request_dict.get('lang', 'en')
  272. nowTime = int(time.time())
  273. # DVR/NVR设备暂不返回套餐列表
  274. device_info_qs = Device_Info.objects.filter(Q(UID=uid), Q(Type__lte=4) | Q(Type=10001))
  275. if device_info_qs.exists():
  276. return response.json(0)
  277. qs = AiStoreMeal.objects
  278. qs = qs.filter(is_show=1) # 过滤隐藏套餐
  279. qs = qs.annotate(ai_meal_id=F('id'))
  280. qs = qs.values("ai_meal_id", "title", "content", "price", "effective_day", "currency",
  281. "virtual_price", "symbol")
  282. if not qs.exists():
  283. return response.json(0)
  284. # 查询每种套餐的所有支付方式
  285. ai_meal_list = list(qs)
  286. for ai_meal in ai_meal_list:
  287. pay_type_qs = Pay_Type.objects.filter(aistoremeal=ai_meal['ai_meal_id']).values('id', 'payment')
  288. ai_meal['pay_type'] = list(pay_type_qs)
  289. result = {
  290. 'meals': ai_meal_list,
  291. }
  292. return response.json(0, result)
  293. def do_querylist(self, userID, request_dict, response):
  294. page = request_dict.get('page', None)
  295. line = request_dict.get('line', None)
  296. uid = request_dict.get('uid', None)
  297. lang = request_dict.get('lang', 'en')
  298. if not page or not line:
  299. return response.json(444, 'page,line')
  300. page = int(page)
  301. line = int(line)
  302. omqs = Order_Model.objects.filter(userID_id=userID, status=1, order_type=1)
  303. # 筛选指定设备id的订单
  304. if uid:
  305. omqs.filter(UID=uid)
  306. if not omqs.exists():
  307. return response.json(173)
  308. count = omqs.count()
  309. omqs = omqs.annotate(rank__title=F('ai_rank__title'), rank__content=F('ai_rank__content'),
  310. rank__day=F('ai_rank__effective_day'), rank__price=F('ai_rank__price'),
  311. rank__expire=F('ai_rank__effective_day'), rank__id=F('ai_rank_id'), rank__currency=F('ai_rank__currency'))
  312. order_ql = omqs[(page - 1) * line:page * line].values("orderID", "UID", "channel", "desc", "price", "currency",
  313. "addTime",
  314. "updTime", "paypal", "rank__day", "payType",
  315. "rank__price", "status",
  316. "rank__content", "rank__title", "rank__currency",
  317. "rank__expire", "ai_rank_id")
  318. order_list = list(order_ql)
  319. data = []
  320. nowTime = int(time.time())
  321. # 这里需要进行优化
  322. uid_list = []
  323. for od in order_list:
  324. uid_list.append(od['UID'])
  325. didqs = Device_Info.objects.filter(userID_id=userID, UID__in=uid_list).values('id', 'UID', 'Type')
  326. for d in order_list:
  327. if d['status'] == 0:
  328. if d['addTime'] + 3600 < nowTime:
  329. d['status'] = 3
  330. for did in didqs:
  331. if d['UID'] == did['UID']:
  332. d['did'] = did['id']
  333. d['Type'] = did['Type']
  334. data.append(d)
  335. # d['rank__lang__content'] = '月' if lang == 'cn' else 'month'
  336. return response.json(0, {'data': data, 'count': count})
  337. # 获取设备当前使用的ai套餐
  338. def getUsingPackage(self, request_dict, userID, response):
  339. uid = request_dict.get('uid', None)
  340. lang = request_dict.get('lang', 'en')
  341. # dv_qs = Device_Info.objects.filter(userID_id=userID, UID=uid, isShare=False, isExist=1, vodPrimaryUserID=userID)
  342. # if not dv_qs.exists():
  343. # return response.json(12)
  344. ai_service_qs = AiService.objects.filter(uid=uid, use_status=1)
  345. if not ai_service_qs.exists():
  346. return response.json(0, [])
  347. ai_service_qs = ai_service_qs.order_by('addTime').annotate(bucket__content=F('orders__ai_rank__title')).\
  348. values('uid', 'use_status', 'endTime', 'bucket__content')
  349. return response.json(0, [ai_service_qs[0]])
  350. def do_create_pay_order(self, request_dict, request, userID, response):
  351. uid = request_dict.get('uid', None)
  352. channel = request_dict.get('channel', None)
  353. pay_type = int(request_dict.get('pay_type', 1))
  354. ai_meal_id = request_dict.get('ai_meal_id', None)
  355. lang = request_dict.get('lang', 'en')
  356. if not uid or not channel or not pay_type or not ai_meal_id:
  357. return response.json(444)
  358. try:
  359. # 判断是否为主用户
  360. # dv_qs = Device_Info.objects.filter(userID_id=userID, UID=uid, isShare=False, isExist=1).values(
  361. # 'vodPrimaryUserID',
  362. # 'vodPrimaryMaster')
  363. # if not dv_qs.exists():
  364. # return response.json(12)
  365. # dvq = Device_Info.objects.filter(UID=uid)
  366. # dvq = dvq.filter(~Q(vodPrimaryUserID='')).values('vodPrimaryUserID')
  367. # if dvq.exists():
  368. # if dvq[0]['vodPrimaryUserID'] != userID:
  369. # return response.json(10033)
  370. # 获取ai套餐数据
  371. ai_sm_qs = AiStoreMeal.objects.filter(id=ai_meal_id, pay_type=pay_type, is_show=1). \
  372. values('currency', 'price', 'content', 'effective_day', 'title')
  373. if not ai_sm_qs.exists():
  374. return response.json(173)
  375. title = ai_sm_qs[0]['title']
  376. content = ai_sm_qs[0]['content']
  377. currency = ai_sm_qs[0]['currency']
  378. price = ai_sm_qs[0]['price']
  379. day = ai_sm_qs[0]['effective_day']
  380. nowTime = int(time.time())
  381. orderID = CommonService.createOrderID()
  382. price = round(float(price), 2)
  383. order_dict = {
  384. 'orderID': orderID,
  385. 'UID': uid,
  386. 'channel': channel,
  387. 'userID_id': userID,
  388. 'desc': content,
  389. 'payType': pay_type,
  390. 'payTime': nowTime,
  391. 'price': price,
  392. 'currency': currency,
  393. 'addTime': nowTime,
  394. 'updTime': nowTime,
  395. 'ai_rank_id': ai_meal_id,
  396. 'rank_id': 1,
  397. 'order_type': 1,
  398. }
  399. if pay_type == 1: # PayPal支付
  400. order_dict['paymentID'], order_dict['pay_url'] = self.create_paypal_payment(lang, orderID, price, currency, content, response)
  401. res_data = {'redirectUrl': order_dict['pay_url'], 'orderID': orderID}
  402. elif pay_type == 2: # 支付宝
  403. order_dict['pay_url'] = self.create_alipay_payment(lang, orderID, price, title, content, response)
  404. res_data = {'redirectUrl': order_dict['pay_url'], 'orderID': orderID}
  405. elif pay_type == 3: # 微信支付
  406. ip = CommonService.get_ip_address(request)
  407. order_dict['pay_url'], sign_params = self.create_wechat_payment(orderID, ip, response)
  408. res_data = {'redirectUrl': order_dict['pay_url'], 'orderID': orderID, 'result': sign_params}
  409. Order_Model.objects.create(**order_dict)
  410. return response.json(0, res_data)
  411. except Exception as e:
  412. print(e)
  413. return response.json(500, repr(e))
  414. @staticmethod
  415. def create_paypal_payment(lang, orderID, price, currency, content, response):
  416. cancel_url = CommonService.get_payment_status_url(lang, 'fail')
  417. call_sub_url = "{}AiService/doPayPalCallBack?orderID={}&lang={}".format(SERVER_DOMAIN_SSL, orderID, lang)
  418. paypalrestsdk.configure(PAYPAL_CRD)
  419. payment = paypalrestsdk.Payment({
  420. "intent": "sale",
  421. "payer": {"payment_method": "paypal"},
  422. "redirect_urls": {"return_url": call_sub_url, "cancel_url": cancel_url},
  423. "transactions": [{
  424. "item_list": {"items": [
  425. {"name": "Cloud video", "sku": "1", "price": price, "currency": "USD", "quantity": 1}]},
  426. "amount": {"total": price, "currency": currency},
  427. "description": content}]})
  428. if not payment.create(): # 创建失败
  429. return response.json(10, payment.error)
  430. paymentID = payment['id'] # 获取paymentID
  431. for link in payment.links:
  432. if link.rel == "approval_url":
  433. pay_url = str(link.href)
  434. return paymentID, pay_url
  435. return response.json(10, 'create_ai_order_failed')
  436. @staticmethod
  437. def create_alipay_payment(lang, orderID, price, title, content, response):
  438. aliPayObj = AliPayObject()
  439. alipay = aliPayObj.conf()
  440. subject = title + content
  441. order_string = alipay.api_alipay_trade_wap_pay(
  442. out_trade_no=orderID,
  443. total_amount=price,
  444. subject=subject,
  445. return_url="{}web/paid2/success.html".format(SERVER_DOMAIN_SSL),
  446. notify_url="{}AiService/doAlipayCallBack".format(SERVER_DOMAIN_SSL),
  447. quit_url="{}web/paid2/fail.html".format(SERVER_DOMAIN_SSL),
  448. passback_params=quote("lang=" + lang)
  449. )
  450. if not order_string:
  451. return response.json(10, '生成订单错误.')
  452. return aliPayObj.alipay_prefix + order_string
  453. @staticmethod
  454. def create_wechat_payment(lang, orderID, price, ip, content, response):
  455. pay = WechatPayObject()
  456. pay_url = "{}AiService/doWechatCallBack".format(SERVER_DOMAIN_SSL)
  457. # 统一调用接口
  458. pay.get_parameter(orderID, content, float(price) * 100, ip, pay_url, quote("lang=" + lang))
  459. sign_params = pay.re_finall(orderid=orderID)
  460. if not sign_params:
  461. return response.json(10, '生成订单错误.')
  462. return pay_url, sign_params
  463. def do_pay_by_paypal_callback(self, request_dict, response):
  464. logger = logging.getLogger('info')
  465. logger.info('AI订单---paypal支付回调')
  466. paymentId = request_dict.get('paymentId', None)
  467. PayerID = request_dict.get('PayerID', None)
  468. orderID = request_dict.get('orderID', None)
  469. lang = request_dict.get('lang', 'en')
  470. if not orderID:
  471. pay_failed_url = CommonService.get_payment_status_url(lang, 'fail')
  472. return HttpResponseRedirect(pay_failed_url)
  473. logger.info("paymentID: {}, payerID: {}".format(paymentId, PayerID))
  474. # redis加锁,防止订单重复
  475. redisObj = RedisObject()
  476. isLock = redisObj.CONN.setnx(orderID + 'do_notify', 1)
  477. redisObj.CONN.expire(orderID + 'do_notify', 60)
  478. if not isLock:
  479. return response.json(5)
  480. try:
  481. order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
  482. if not order_qs.exists():
  483. return response.json(173)
  484. paypalrestsdk.configure(PAYPAL_CRD)
  485. payment = paypalrestsdk.Payment.find(paymentId)
  486. logger.info("payment: {}".format(payment))
  487. payer = payment.execute({"payer_id": PayerID})
  488. logger.info('payres: {}'.format(payer))
  489. if not payer:
  490. pay_failed_url = CommonService.get_payment_status_url(lang, 'fail')
  491. redisObj.del_data(key=orderID + 'do_notify')
  492. return HttpResponseRedirect(pay_failed_url)
  493. return self.payment_success(orderID, lang, order_qs, redisObj)
  494. except Exception as e:
  495. logger.info('AI订单paypal支付回调异常:{}'.format(repr(e)))
  496. order_qs.update(status=10)
  497. pay_failed_url = CommonService.get_payment_status_url(lang, 'fail')
  498. redisObj.del_data(key=orderID + 'do_notify')
  499. return HttpResponseRedirect(pay_failed_url)
  500. def do_alipay_callback(self, request_dict, response): # 支付宝支付回调
  501. logger = logging.getLogger('info')
  502. logger.info('AI订单---支付宝支付回调')
  503. try:
  504. data = request_dict.dict()
  505. passback_params = data['passback_params']
  506. parmap = dict([(k, v[0]) for k, v in parse_qs(unquote(passback_params)).items()])
  507. lang = parmap['lang']
  508. signature = data['sign']
  509. data.pop('sign')
  510. orderID = data['out_trade_no']
  511. # redis加锁,防止订单重复
  512. redisObj = RedisObject()
  513. isLock = redisObj.CONN.setnx(orderID + 'do_notify', 1)
  514. redisObj.CONN.expire(orderID + 'do_notify', 60)
  515. if not isLock:
  516. return response.json(5)
  517. order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
  518. if not order_qs.exists():
  519. return response.json(173)
  520. aliPayObj = AliPayObject()
  521. alipay = aliPayObj.conf()
  522. success = alipay.verify(data, signature)
  523. if not success or data["trade_status"] not in ("TRADE_SUCCESS", "TRADE_FINISHED"):
  524. return response.json(0, signature)
  525. return self.payment_success(orderID, lang, order_qs, redisObj)
  526. except Exception as e:
  527. logger.info('AI订单支付宝支付回调异常:{}'.format(repr(e)))
  528. order_qs.update(status=10)
  529. redisObj.del_data(key=orderID + 'do_notify')
  530. pay_failed_url = CommonService.get_payment_status_url(lang, 'fail')
  531. redisObj.del_data(key=orderID + 'do_notify')
  532. return HttpResponseRedirect(pay_failed_url)
  533. def do_wechat_callback(self, request, response): # 微信支付回调
  534. logger = logging.getLogger('info')
  535. logger.info('AI订单---微信支付回调')
  536. try:
  537. pay = WechatPayObject()
  538. data = pay.weixinpay_call_back(request.body)
  539. attach = data["attach"]
  540. parmap = dict([(k, v[0]) for k, v in parse_qs(unquote(attach)).items()])
  541. lang = parmap['lang']
  542. trade_status = data['result_code'] # 业务结果 SUCCESS/FAIL
  543. orderID = data['out_trade_no'] # 商户订单号
  544. order_qs = Order_Model.objects.filter(orderID=orderID, status=0)
  545. if not order_qs.exists():
  546. return response.json(173)
  547. if trade_status != 'SUCCESS':
  548. order_qs.update(status=10)
  549. return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL'}))
  550. check_sign = pay.get_notifypay(data)
  551. if not check_sign:
  552. return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL', 'return_msg': '签名失败'}))
  553. # redis加锁,防止订单重复
  554. redisObj = RedisObject()
  555. isLock = redisObj.CONN.setnx(orderID + 'do_notify', 1)
  556. redisObj.CONN.expire(orderID + 'do_notify', 60)
  557. if not isLock:
  558. return response.json(5)
  559. return self.payment_success(self, orderID, lang, order_qs, redisObj, True)
  560. except Exception as e:
  561. order_qs.update(status=10)
  562. redisObj.del_data(key=orderID + 'do_notify')
  563. return HttpResponse(pay.xml_to_dict({'return_code': 'FAIL', 'return_msg': repr(e)}))
  564. def payment_success(self, orderID, lang, order_qs, redisObj, is_wechat_pay=False):
  565. nowTime = int(time.time())
  566. order_list = order_qs.values("UID", "channel", "commodity_code", "ai_rank__effective_day", "isSelectDiscounts",
  567. "userID__userID", "userID__username", "coupon_id")
  568. userid = order_list[0]['userID__userID']
  569. username = order_list[0]['userID__username']
  570. UID = order_list[0]['UID']
  571. channel = order_list[0]['channel']
  572. effective_day = order_list[0]['ai_rank__effective_day']
  573. ai_service_qs = AiService.objects.filter(Q(uid=UID), Q(channel=channel), Q(use_status=1))
  574. ai_service_dict = {'orders_id': orderID,
  575. 'uid': UID,
  576. 'channel': channel,
  577. 'detect_status': 1,
  578. 'addTime': nowTime,
  579. 'updTime': nowTime,
  580. 'detect_group': '1'
  581. }
  582. if ai_service_qs.exists(): # 有正在使用的套餐,套餐结束时间保存为套餐有效期
  583. ai_service_dict['endTime'] = effective_day * 24 * 60 * 60
  584. else:
  585. ai_service_dict['use_status'] = 1
  586. ai_service_dict['endTime'] = nowTime + effective_day * 24 * 60 * 60
  587. with transaction.atomic():
  588. # 更新设备主用户
  589. Device_Info.objects.filter(UID=UID, vodPrimaryUserID='', vodPrimaryMaster=''). \
  590. update(vodPrimaryUserID=userid, vodPrimaryMaster=username)
  591. # 更新订单数据,返回支付成功url
  592. order_qs.update(status=1, updTime=nowTime)
  593. # 创建AiService数据
  594. AiService.objects.create(**ai_service_dict)
  595. pay_success_url = CommonService.get_payment_status_url(lang, 'success')
  596. redisObj.del_data(key=orderID + 'do_notify')
  597. if is_wechat_pay:
  598. return HttpResponse("<xml>\
  599. <return_code><![CDATA[SUCCESS]]></return_code>\
  600. <return_msg><![CDATA[OK]]></return_msg>\
  601. </xml>")
  602. else:
  603. return HttpResponseRedirect(pay_success_url)
  604. def do_ai_identification(self, request_dict,response):
  605. etk = request_dict.get('etk', None)
  606. n_time = request_dict.get('n_time', None)
  607. channel = request_dict.get('channel', '1')
  608. receiveTime = int(time.time())
  609. logger = logging.getLogger('info')
  610. logger.info('-----------into----ai--api')
  611. logger.info("etk={etk}".format(etk=etk))
  612. if not etk:
  613. return response.json(444)
  614. try:
  615. # 解密uid及判断长度
  616. eto = ETkObject(etk)
  617. uid = eto.uid
  618. logger.info("uid={uid}".format(uid=uid))
  619. if len(uid) != 20 and len(uid) != 14:
  620. return response.json(444)
  621. ##通过uid查出endTime是否过期,并且ai开关是否打开
  622. AiServiceQuery = AiService.objects.filter(uid=uid, detect_status=1, use_status=1, endTime__gt=receiveTime).\
  623. values('detect_group')
  624. if not AiServiceQuery.exists():
  625. logger.info('none-----aiService')
  626. return response.json(173)
  627. detect_group = AiServiceQuery[0]['detect_group']
  628. #{}??
  629. #
  630. file_post_one = request_dict.get('fileOne', None)
  631. file_post_two = request_dict.get('fileTwo', None)
  632. file_post_three = request_dict.get('fileThree', None)
  633. file_post_one = file_post_one.replace(' ', '+')
  634. file_post_two = file_post_two.replace(' ', '+')
  635. file_post_three = file_post_three.replace(' ', '+')
  636. file_post_one = base64.b64decode(file_post_one)
  637. file_post_two = base64.b64decode(file_post_two)
  638. file_post_three = base64.b64decode(file_post_three)
  639. file_list = [file_post_one, file_post_two, file_post_three]
  640. del file_post_one, file_post_two, file_post_three
  641. dir_path = os.path.join(BASE_DIR, 'static/ai/' + uid + '/' + str(receiveTime))
  642. if not os.path.exists(dir_path):
  643. os.makedirs(dir_path)
  644. file_path_list = []
  645. i = 1
  646. for index in file_list:
  647. file_path = dir_path + '/' + str(i) + '.jpg'
  648. file_path_list.append(file_path)
  649. with open(file_path, 'wb') as f:
  650. f.write(index)
  651. f.close()
  652. i += 1
  653. image_size = 500 # 每张小图片的大小
  654. image_colnum = 1 # 合并成一张图后,一行有几个小图
  655. MergePic.merge_images(dir_path, image_size, image_colnum)
  656. photo = open(dir_path + '.jpg', 'rb') #打开合成图
  657. cover = dir_path + '/' + str(i-1) + '.jpg'
  658. desc = dir_path + '.jpg'
  659. logger.info('----------------cover')
  660. logger.info(cover)
  661. logger.info(desc)
  662. # photo = open(r'E:\test---------------\test\snipaste20220121_215952.jpg', 'rb')
  663. #识别合成图片
  664. maxLabels = 50
  665. minConfidence = 70
  666. ai_start_time = int(time.time())
  667. client = boto3.client(
  668. 'rekognition',
  669. aws_access_key_id='AKIA2E67UIMD6JD6TN3J',
  670. aws_secret_access_key='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',
  671. region_name='us-east-1')
  672. # doc:
  673. rekognition_res = client.detect_labels(
  674. Image={'Bytes': photo.read()},
  675. MaxLabels=maxLabels,
  676. MinConfidence=minConfidence)
  677. if rekognition_res['ResponseMetadata']['HTTPStatusCode'] != 200:
  678. return response.json(173)
  679. ai_end_time = int(time.time())
  680. labels =rekognition_res['Labels']
  681. label_name = []
  682. logger.info('--------识别到的标签-------')
  683. logger.info(labels)
  684. for label in labels:
  685. label_name.append(label['Name'])
  686. for Parents in label['Parents']:
  687. label_name.append(Parents['Name'])
  688. labels = self.checkLabels(detect_group, label_name) #检查标签是否符合用户选择的识别类型
  689. if len(labels['label_list']) == 0:
  690. logger.info('没有识别到任何标签-----------------')
  691. return response.json(10055)
  692. event_type = ','.join(labels['label_type'])
  693. label_list = ','.join(labels['label_list'])
  694. logger.info(event_type)
  695. logger.info(label_list)
  696. # 上传缩略图到s3
  697. upload_cover_path = "{uid}/{channel}/cover{n_time}.jpg".format(uid=uid, channel=channel,
  698. n_time=n_time) # 封面图
  699. upload_desc_path = "{uid}/{channel}/desc{n_time}.jpg".format(uid=uid, channel=channel,
  700. n_time=n_time) # 详情内容图
  701. #多线程上传图片
  702. thread_cover = threading.Thread(target=self.upload_s3, args=(cover, upload_cover_path))
  703. thread_desc = threading.Thread(target=self.upload_s3, args=(desc, upload_desc_path))
  704. thread_cover.start()
  705. thread_desc.start()
  706. #需要删除图片
  707. #存储消息以及推送
  708. is_st = 1 #单图
  709. # 查询推送数据
  710. uid_push_qs = UidPushModel.objects.filter(uid_set__uid=uid). \
  711. values('token_val', 'app_type', 'appBundleId', 'm_code', 'push_type', 'userID_id',
  712. 'userID__NickName',
  713. 'lang', 'm_code', 'tz', 'uid_set__nickname', 'uid_set__detect_interval',
  714. 'uid_set__detect_group',
  715. 'uid_set__channel')
  716. if not uid_push_qs.exists():
  717. return response.json(173)
  718. uid_push_list = []
  719. for qs in uid_push_qs:
  720. uid_push_list.append(qs)
  721. nickname = uid_push_list[0]['uid_set__nickname']
  722. if not nickname:
  723. nickname = uid
  724. eq_list = []
  725. userID_ids = []
  726. apns_start_time = 0
  727. apns_end_time = 0
  728. for up in uid_push_list:
  729. push_type = up['push_type']
  730. appBundleId = up['appBundleId']
  731. token_val = up['token_val']
  732. lang = up['lang']
  733. tz = up['tz']
  734. if tz is None or tz == '':
  735. tz = 0
  736. # 以下是存库
  737. userID_id = up["userID_id"]
  738. if userID_id not in userID_ids:
  739. now_time = int(time.time())
  740. eq_list.append(Ai_Push_Info(
  741. userID_id=userID_id,
  742. eventTime=n_time,
  743. eventType=event_type,
  744. devUid=uid,
  745. devNickName=nickname,
  746. Channel=channel,
  747. alarm='检查到{labels} \tChannel:{channel}'.format(labels=','.join(labels['label_list']),
  748. channel=channel),
  749. is_st=is_st,
  750. receiveTime=receiveTime,
  751. addTime=now_time,
  752. storage_location=2
  753. ))
  754. userID_ids.append(userID_id)
  755. # 推送标题
  756. msg_title = self.get_msg_title(appBundleId=appBundleId, nickname=nickname)
  757. # 推送内容
  758. msg_text = self.get_msg_text(channel=channel, n_time=n_time, lang=lang, tz=tz, label_list=label_list)
  759. kwargs = {
  760. 'uid': uid,
  761. 'channel': channel,
  762. 'event_type': event_type,
  763. 'n_time': n_time,
  764. 'appBundleId': appBundleId,
  765. 'token_val': token_val,
  766. 'msg_title': msg_title,
  767. 'msg_text': msg_text,
  768. }
  769. try:
  770. # 推送消息
  771. if push_type == 0: # ios apns
  772. res = self.do_apns(**kwargs)
  773. elif push_type == 1: # android gcm
  774. self.do_fcm(**kwargs)
  775. elif push_type == 2: # android jpush
  776. self.do_jpush(**kwargs)
  777. # if push_type == 1: # android gcm
  778. # logger.info('into-------gcm')
  779. # apns_start_time = int(time.time())
  780. # res = self.do_fcm(**kwargs)
  781. # apns_end_time = int(time.time())
  782. except Exception as e:
  783. logger.info("errLine={errLine}, errMsg={errMsg}".format(errLine=e.__traceback__.tb_lineno,errMsg=repr(e)))
  784. continue
  785. Ai_Push_Info.objects.bulk_create(eq_list)
  786. return JsonResponse(status=200, data='success', safe=False)
  787. except Exception as e:
  788. print(e)
  789. data = {
  790. 'errLine':e.__traceback__.tb_lineno,
  791. 'errMsg':repr(e)
  792. }
  793. return response.json(500, data)
  794. def delfile(self, path):
  795. # read all the files under the folder
  796. fileNames = glob.glob(path + r'\*')
  797. for fileName in fileNames:
  798. try:
  799. # delete file
  800. os.remove(fileName)
  801. except:
  802. try:
  803. # delete empty folders
  804. os.rmdir(fileName)
  805. except:
  806. # Not empty, delete files under folders
  807. delfile(fileName)
  808. # now, folders are empty, delete it
  809. os.rmdir(fileName)
  810. ## 检查是否有符合条件的标签
  811. def checkLabels(self, user_detect_group, labels):
  812. labels_type = {
  813. '1': ['Person', 'Human'], #人
  814. '2': ['Dog', 'Pet', 'Canine', 'Animal'], #动物
  815. '3': ['Car', '', 'Vehicle', 'Transportation', 'Automobile'] #车
  816. }
  817. user_detect_list = user_detect_group.split(',')
  818. user_labels_type = {}
  819. for user_detect in user_detect_list:
  820. if user_detect in labels_type.keys():
  821. user_labels_type[user_detect] = labels_type[user_detect]
  822. label_list = []
  823. for k, labels_type in user_labels_type.items():
  824. for label in labels_type:
  825. if label in labels:
  826. label_list.append(label)
  827. user_labels_list = list(user_labels_type.keys())
  828. user_labels_list.sort()
  829. return {'label_type': user_labels_list, 'label_list': label_list}
  830. def upload_s3(self, file_path, upload_path):
  831. try:
  832. aws_key = "AKIA2MMWBR4DSFG67DTG" #【你的 aws_access_key】
  833. aws_secret = "aI9gxcAKPmiGgPy9axrtFKzjYGbvpuytEX4xWweL" # 【你的 aws_secret_key】
  834. session = Session(aws_access_key_id=aws_key,
  835. aws_secret_access_key=aws_secret,
  836. region_name="cn-northwest-1")
  837. s3 = session.resource("s3")
  838. # client = session.client("s3")
  839. bucket = "aipush" # 【你 bucket 的名字】 # 首先需要保.证 s3 上已经存在该存储桶,否则报错
  840. upload_data = open(file_path, "rb")
  841. # upload_key = "test"
  842. s3.Bucket(bucket).put_object(Key=upload_path, Body=upload_data)
  843. return True
  844. except Exception as e:
  845. print(repr(e))
  846. return False
  847. def get_msg_title(self, appBundleId, nickname):
  848. package_title_config = {
  849. 'com.ansjer.customizedd_a': 'DVS',
  850. 'com.ansjer.zccloud_a': 'ZosiSmart',
  851. 'com.ansjer.zccloud_ab': '周视',
  852. 'com.ansjer.adcloud_a': 'ADCloud',
  853. 'com.ansjer.adcloud_ab': 'ADCloud',
  854. 'com.ansjer.accloud_a': 'ACCloud',
  855. 'com.ansjer.loocamccloud_a': 'Loocam',
  856. 'com.ansjer.loocamdcloud_a': 'Anlapus',
  857. 'com.ansjer.customizedb_a': 'COCOONHD',
  858. 'com.ansjer.customizeda_a': 'Guardian365',
  859. 'com.ansjer.customizedc_a': 'PatrolSecure',
  860. }
  861. if appBundleId in package_title_config.keys():
  862. return package_title_config[appBundleId] + '(' + nickname + ')'
  863. else:
  864. return nickname
  865. def get_msg_text(self, channel, n_time, lang, tz, label_list):
  866. n_date = CommonService.get_now_time_str(n_time=n_time, tz=tz,lang=lang)
  867. if lang == 'cn':
  868. msg = '摄像头AI识别到了{}'.format(label_list)
  869. send_text = '{msg} 通道:{channel} 日期:{date}'.format(msg=msg, channel=channel, date=n_date)
  870. else:
  871. msg = 'Camera AI recognizes{}'.format(label_list)
  872. send_text = '{msg} channel:{channel} date:{date}'.format(msg=msg, channel=channel, date=n_date)
  873. return send_text
  874. def do_jpush(self, uid, channel, appBundleId, token_val, event_type, n_time, msg_title, msg_text):
  875. app_key = JPUSH_CONFIG[appBundleId]['Key']
  876. master_secret = JPUSH_CONFIG[appBundleId]['Secret']
  877. # 此处换成各自的app_key和master_secre
  878. _jpush = jpush.JPush(app_key, master_secret)
  879. push = _jpush.create_push()
  880. push.audience = jpush.registration_id(token_val)
  881. push_data = {"alert": "Motion ", "event_time": n_time, "event_type": event_type, "msg": "",
  882. "received_at": n_time, "sound": "sound.aif", "uid": uid, "zpush": "1", "channel": channel}
  883. android = jpush.android(alert=msg_text, priority=1, style=1, alert_type=7,
  884. big_text=msg_text, title=msg_title,
  885. extras=push_data)
  886. push.notification = jpush.notification(android=android)
  887. push.platform = jpush.all_
  888. res = push.send()
  889. print(res)
  890. return res.status_code
  891. def do_fcm(self, uid, channel, appBundleId, token_val, event_type, n_time, msg_title, msg_text):
  892. try:
  893. serverKey = FCM_CONFIG[appBundleId]
  894. push_service = FCMNotification(api_key=serverKey)
  895. data = {"alert": "Motion ", "event_time": n_time, "event_type": event_type, "msg": "",
  896. "received_at": n_time, "sound": "sound.aif", "uid": uid, "zpush": "1", "channel": channel}
  897. result = push_service.notify_single_device(registration_id=token_val, message_title=msg_title,
  898. message_body=msg_text, data_message=data,
  899. extra_kwargs={
  900. 'default_vibrate_timings': True,
  901. 'default_sound': True,
  902. 'default_light_settings': True
  903. })
  904. print('fcm push ing')
  905. print(result)
  906. return result
  907. except Exception as e:
  908. return 'serverKey abnormal'
  909. def do_apns(self, uid, channel, appBundleId, token_val, event_type, n_time, msg_title, msg_text):
  910. logger = logging.getLogger('info')
  911. logger.info("进来do_apns函数了")
  912. logger.info(token_val)
  913. logger.info(APNS_MODE)
  914. logger.info(os.path.join(BASE_DIR, APNS_CONFIG[appBundleId]['pem_path']))
  915. try:
  916. cli = apns2.APNSClient(mode=APNS_MODE, client_cert=os.path.join(BASE_DIR, APNS_CONFIG[appBundleId]['pem_path']))
  917. push_data = {"alert": "Motion ", "event_time": n_time, "event_type": event_type, "msg": "",
  918. "received_at": n_time, "sound": "", "uid": uid, "zpush": "1", "channel": channel}
  919. alert = apns2.PayloadAlert(body=msg_text, title=msg_title)
  920. payload = apns2.Payload(alert=alert, custom=push_data, sound="default")
  921. n = apns2.Notification(payload=payload, priority=apns2.PRIORITY_LOW)
  922. res = cli.push(n=n, device_token=token_val, topic=appBundleId)
  923. if res.status_code == 200:
  924. return res.status_code
  925. else:
  926. logger.info('apns push fail')
  927. logger.info(res.reason)
  928. return res.status_code
  929. except (ValueError, ArithmeticError):
  930. return 'The program has a numeric format exception, one of the arithmetic exceptions'
  931. except Exception as e:
  932. print(repr(e))
  933. logger.info(repr(e))
  934. return repr(e)
  935. def queryInfo(self, userID, request_dict, response):
  936. page = int(request_dict.get('page', None))
  937. line = int(request_dict.get('line', None))
  938. if not page or not line:
  939. return response.json(444, 'page,line')
  940. startTime = request_dict.get('startTime', None)
  941. endTime = request_dict.get('endTime', None)
  942. eventType = request_dict.get('eventType', None)
  943. now_time = int(time.time())
  944. seven_days_ago = now_time - 7 * 24 * 3600 # 查询7天内的数据
  945. qs = Ai_Push_Info.objects.filter(userID_id=userID, eventTime__gt=seven_days_ago).order_by('-eventTime')
  946. if startTime and endTime:
  947. qs = qs.filter(eventTime__range=(startTime, endTime))
  948. # if eventType:
  949. # qs = qs.filter(eventType__contains=eventType)
  950. uids = request_dict.get('uids', None)
  951. if uids:
  952. uid_list = uids.split(',')
  953. qs = qs.filter(devUid__in=uid_list)
  954. dvqs = Device_Info.objects.filter(UID__in=uid_list, userID_id=userID).values('UID', 'Type', 'NickName')
  955. uid_type_dict = {}
  956. for dv in dvqs:
  957. uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
  958. else:
  959. dvqs = Device_Info.objects.filter(userID_id=userID).values('UID', 'Type', 'NickName')
  960. uid_type_dict = {}
  961. for dv in dvqs:
  962. uid_type_dict[dv['UID']] = {'type': dv['Type'], 'NickName': dv['NickName']}
  963. if not qs.exists():
  964. return response.json(0, {'datas': [], 'count': 0})
  965. count = qs.count()
  966. qs = qs.values('id', 'devUid', 'devNickName', 'Channel', 'eventType', 'status', 'alarm', 'eventTime',
  967. 'receiveTime', 'is_st', 'addTime', 'storage_location')
  968. qs = qs[(page - 1) * line:page * line]
  969. res = []
  970. aws_s3_client = boto3.client(
  971. 's3',
  972. aws_access_key_id=AWS_ACCESS_KEY_ID[0],
  973. aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
  974. config=botocore.client.Config(signature_version='s3v4'),
  975. region_name='cn-northwest-1'
  976. )
  977. for p in qs:
  978. p['eventType'] = int(p['eventType'][0])
  979. devUid = p['devUid']
  980. eventTime = p['eventTime']
  981. channel = p['Channel']
  982. storage_location = p['storage_location']
  983. if p['is_st'] == 1:
  984. s3_img_cover = '{uid}/{channel}/cover{time}.jpg'.format(uid=devUid, channel=channel, time=eventTime)
  985. s3_img_desc = '{uid}/{channel}/desc{time}.jpg'.format(uid=devUid, channel=channel, time=eventTime)
  986. response_url_cover = aws_s3_client.generate_presigned_url('get_object',
  987. ExpiresIn=300,
  988. Params={
  989. 'Bucket': 'aipush', 'Key': s3_img_cover
  990. },
  991. )
  992. response_url_desc = aws_s3_client.generate_presigned_url('get_object',
  993. ExpiresIn=300,
  994. Params={
  995. 'Bucket': 'aipush', 'Key': s3_img_desc
  996. },
  997. )
  998. p['img'] = response_url_cover
  999. p['img_list'] = [response_url_desc]
  1000. elif p['is_st'] == 2:
  1001. pass
  1002. if devUid in uid_type_dict.keys():
  1003. p['uid_type'] = uid_type_dict[devUid]['type']
  1004. p['devNickName'] = uid_type_dict[devUid]['NickName']
  1005. else:
  1006. p['uid_type'] = ''
  1007. res.append(p)
  1008. return response.json(0, {'datas': res, 'count': count})
  1009. def readInfo(self, userID, request_dict, response):
  1010. is_update_all = request_dict.get('is_update_all', 0)
  1011. try:
  1012. if int(is_update_all) == 1: # 全部已读
  1013. is_update = Ai_Push_Info.objects.filter(userID_id=userID).update(status=1)
  1014. return response.json(0, {'update_count': is_update})
  1015. else:
  1016. id_list = request_dict.get('id_list', None)
  1017. if not id_list:
  1018. request_dict.getlist('id_list[]', None) # 获取IOS数组传参
  1019. logger = logging.getLogger('info')
  1020. logger.info('已读ai消息id_list:{}'.format(id_list))
  1021. if not id_list:
  1022. return response.json(444)
  1023. id_list = eval(id_list) # 字符串转列表
  1024. param_flag = CommonService.get_param_flag(data=id_list)
  1025. if not param_flag:
  1026. return response.json(444)
  1027. count = 0
  1028. for id in id_list:
  1029. ai_push_qs = Ai_Push_Info.objects.filter(id=int(id))
  1030. if ai_push_qs.exists():
  1031. own_dev = ModelService.check_own_device(userID, ai_push_qs[0].devUid)
  1032. if own_dev:
  1033. count += 1
  1034. ai_push_qs.update(status=1)
  1035. return response.json(0, {'update_success': count})
  1036. except Exception as e:
  1037. print(e)
  1038. return response.json(500, repr(e))
  1039. def deleteInfo(self, userID, request_dict, response):
  1040. id_list = request_dict.get('id_list', None)
  1041. if not id_list:
  1042. request_dict.getlist('id_list[]', None) # 获取IOS数组传参
  1043. logger = logging.getLogger('info')
  1044. logger.info('删除ai消息id_list:{}'.format(id_list))
  1045. if not id_list:
  1046. return response.json(444)
  1047. try:
  1048. id_list = eval(id_list) # 字符串转列表
  1049. param_flag = CommonService.get_param_flag(data=id_list)
  1050. if not param_flag:
  1051. return response.json(444)
  1052. for id in id_list:
  1053. ai_push_qs = Ai_Push_Info.objects.filter(id=id)
  1054. if ai_push_qs.exists():
  1055. own_dev = ModelService.check_own_device(userID, ai_push_qs[0].devUid)
  1056. if own_dev:
  1057. ai_push_qs.delete()
  1058. return response.json(0)
  1059. except Exception as e:
  1060. print(e)
  1061. return response.json(500, repr(e))
  1062. # 如果ai套餐过期,更新未使用的关联套餐
  1063. def updateUnusedAi(request):
  1064. now_time = int(time.time())
  1065. ai_service_qs = AiService.objects.filter(endTime__lte=now_time, use_status=1).values('id', 'uid')[0:200]
  1066. for ai_service in ai_service_qs:
  1067. try:
  1068. with transaction.atomic():
  1069. AiService.objects.filter(id=ai_service['id']).update(use_status=2) # 更新过期ai订单状态
  1070. # 如果存在未使用套餐,更新为使用
  1071. unused_ai_service = AiService.objects.filter(uid=ai_service['uid'], use_status=0).order_by('addTime')[:1].values('id', 'endTime')
  1072. if unused_ai_service.exists():
  1073. effective_day = unused_ai_service[0]['endTime'] # 未使用套餐的endTime在购买的时候保存为有效时间
  1074. endTime = now_time + effective_day
  1075. AiService.objects.filter(id=unused_ai_service[0]['id']).update(use_status=1, endTime=endTime, updTime=now_time)
  1076. except Exception as e:
  1077. continue
  1078. return HttpResponse()