AppCampaignController.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. import time
  2. import pytz
  3. from datetime import datetime
  4. from datetime import time as Time
  5. from Model.models import AppAdvertiseCampaign, DeviceTypeModel, CountryModel, Device_User, OpenScreenCampaign
  6. from Ansjer.config import SERVER_TYPE
  7. from django.views import View
  8. from django.db.models import Prefetch
  9. from Object.ResponseObject import ResponseObject
  10. from Object.TokenObject import TokenObject
  11. class AppCampaignView(View):
  12. def get(self, request, *args, **kwargs):
  13. request.encoding = 'utf-8'
  14. operation = kwargs.get('operation')
  15. request_dict = request.GET
  16. return self.validation(request, request_dict, operation)
  17. def post(self, request, *args, **kwargs):
  18. request.encoding = 'utf-8'
  19. operation = kwargs.get('operation')
  20. request_dict = request.POST
  21. return self.validation(request, request_dict, operation)
  22. def validation(self, request, request_dict, operation):
  23. language = request_dict.get('language', 'en')
  24. response = ResponseObject(language)
  25. tko = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
  26. response.lang = tko.lang
  27. if tko.code != 0:
  28. return response.json(tko.code)
  29. userID = tko.userID
  30. if operation == 'appGetCampaigns':
  31. return self.app_get_campaigns(userID, request_dict, response)
  32. elif operation == 'recordUserBehavior':
  33. return self.record_user_behavior(userID, request_dict)
  34. else:
  35. return response.json(414)
  36. def app_get_campaigns(self, userID, request_dict, response):
  37. tz = request_dict.get('tz', '+0:00')
  38. app_type = request_dict.get('appType', 0)
  39. if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
  40. s3_url = "https://ansjerfilemanager.s3.cn-northwest-1.amazonaws.com.cn/app/campaign/"
  41. else:
  42. s3_url = "https://ansjerfilemanager.s3.amazonaws.com/app/campaign/"
  43. # 当日时间戳区间获取
  44. timezone = self.get_timezone_offset(tz)
  45. current_date = datetime.now().date()
  46. start_of_day = datetime.combine(current_date, Time.min)
  47. end_of_day = datetime.combine(current_date, Time.max)
  48. start_timestamp = int(start_of_day.timestamp())
  49. end_timestamp = int(end_of_day.timestamp())
  50. open_screen_campaign_qs = OpenScreenCampaign.objects.filter(
  51. user_id=userID,
  52. create_time__gt=start_timestamp,
  53. create_time__lt=end_timestamp
  54. )
  55. if not open_screen_campaign_qs.exists():
  56. OpenScreenCampaign.objects.create(user_id=userID,
  57. update_time=int(time.time()),
  58. create_time=int(time.time()))
  59. try:
  60. country_prefetch = Prefetch('country', queryset=CountryModel.objects.only('id'), to_attr='country_list')
  61. device_type_prefetch = Prefetch('device_type', queryset=DeviceTypeModel.objects.only('type'),
  62. to_attr='device_type_list')
  63. app_advertise_campaign_qs = AppAdvertiseCampaign.objects.prefetch_related(country_prefetch,
  64. device_type_prefetch)
  65. device_info_qs = Device_User.objects.filter(userID=userID).values("region_country").first()
  66. country_id = device_info_qs.get('region_country')
  67. if country_id != 0:
  68. app_advertise_campaign_qs = app_advertise_campaign_qs.filter(country__id=country_id, status=1)
  69. else:
  70. app_advertise_campaign_qs = app_advertise_campaign_qs.filter(status=1, unknown_country=1)
  71. if app_type is not None:
  72. app_advertise_campaign_qs = app_advertise_campaign_qs.filter(app_bundle_type=app_type)
  73. # 返回 广告名称、广告类型、开始时间、结束时间、广告图片、活动链接
  74. campaigns_list = []
  75. for campaign in app_advertise_campaign_qs:
  76. # campaign_end_date = (datetime.utcfromtimestamp(campaign.campaign_end_date) # 日期版本
  77. # .replace(tzinfo=pytz.utc).astimezone(timezone).strftime('%Y-%m-%d'))
  78. # 日期范围
  79. campaigns_start_date = datetime.fromtimestamp(campaign.campaign_start_date, pytz.utc).astimezone(
  80. timezone).replace(hour=0, minute=0, second=0, microsecond=0).timestamp() # 时间戳版本
  81. campaign_end_date = datetime.fromtimestamp(campaign.campaign_end_date, pytz.utc).astimezone(
  82. timezone).replace(hour=0, minute=0, second=0, microsecond=0).timestamp() # 时间戳版本
  83. # 时间范围
  84. campaign_start_firstday = sum(int(x) * 60 ** i for i, x in enumerate(reversed(
  85. datetime.utcfromtimestamp(campaign.campaign_start_date + campaign.campaign_show_stime).replace(
  86. tzinfo=pytz.utc).astimezone(timezone).strftime('%H:%M').split(':')))) * 60 # 秒数版本
  87. campaign_end_firstday = sum(int(x) * 60 ** i for i, x in enumerate(reversed(
  88. datetime.utcfromtimestamp(campaign.campaign_start_date + campaign.campaign_show_etime).replace(
  89. tzinfo=pytz.utc).astimezone(timezone).strftime('%H:%M').split(':')))) * 60 # 秒数版本
  90. # campaign_end_firstday = (
  91. # datetime.utcfromtimestamp(campaign.campaign_start_date + campaign.campaign_show_etime)
  92. # .replace(tzinfo=pytz.utc).astimezone(timezone).strftime('%H:%M')) # 时间版本
  93. # 轮播广告
  94. banner_campaign = []
  95. for sort in campaign.banner_campaign:
  96. banner = campaign.banner_campaign[sort]
  97. banner["image"] = s3_url + banner["image"]
  98. banner_campaign.append(banner)
  99. campaigns_list.append({
  100. 'campaign_id': campaign.id,
  101. 'image_url': s3_url + campaign.image_url,
  102. 'banner_campaign': banner_campaign,
  103. 'campaign_url': campaign.campaign_url,
  104. 'campaign_name': campaign.campaign_name,
  105. 'campaign_type': campaign.campaign_type,
  106. 'start_date': campaigns_start_date,
  107. 'end_date': campaign_end_date,
  108. 'start_time': campaign_start_firstday,
  109. 'end_time': campaign_end_firstday,
  110. 'device_types': [device.type for device in campaign.device_type_list],
  111. })
  112. return response.json(0, {
  113. 'interval_time': 86400,
  114. 'campaigns': campaigns_list
  115. })
  116. except Exception as e:
  117. print(e)
  118. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  119. def record_user_behavior(self, userID, request_dict, response):
  120. """
  121. 记录用户行为
  122. @param request_dict: 请求参数
  123. @param response: 响应对象
  124. @return: 响应对象
  125. """
  126. status = request_dict.get('status', None) # 1.未跳过 2.已跳过 3.点击广告
  127. campaign_id = request_dict.get('campaign_id', None)
  128. user_id = userID
  129. if not all([status, campaign_id]):
  130. return response.json(444)
  131. # 当日时间戳区间获取
  132. current_date = datetime.now().date()
  133. start_of_day = datetime.combine(current_date, Time.min)
  134. end_of_day = datetime.combine(current_date, Time.max)
  135. start_timestamp = int(start_of_day.timestamp())
  136. end_timestamp = int(end_of_day.timestamp())
  137. try:
  138. # 筛选符合条件的记录
  139. open_screen_campaigns = OpenScreenCampaign.objects.filter(
  140. user_id=user_id,
  141. create_time__gt=start_timestamp,
  142. create_time__lt=end_timestamp,
  143. status=0,
  144. )
  145. # 检查是否存在记录
  146. if not open_screen_campaigns.exists():
  147. # 如果不存在,则创建新记录
  148. OpenScreenCampaign.objects.create(
  149. user_id=user_id,
  150. status=status,
  151. campaign_id_id=campaign_id,
  152. create_time=int(time.time()),
  153. update_time=int(time.time())
  154. )
  155. else:
  156. # 如果存在,则更新最新的记录
  157. latest_campaign = open_screen_campaigns.latest("create_time")
  158. latest_campaign.status = status
  159. latest_campaign.campaign_id_id = campaign_id
  160. latest_campaign.update_time = int(time.time())
  161. latest_campaign.save()
  162. return response.json(0)
  163. except Exception as e:
  164. print(e)
  165. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  166. def get_timezone_offset(self, tz):
  167. """
  168. 将 "+8:00" 格式的时区字符串转换为包含分钟偏移的时区。
  169. """
  170. sign = tz[0] # " " 或 "-"
  171. hours, minutes = map(int, tz[1:].split('.')) # 分离小时和分钟
  172. # 计算总分钟数
  173. total_minutes = hours * 60 + minutes
  174. if sign == '-':
  175. total_minutes = -total_minutes
  176. # 使用 pytz.FixedOffset 创建时区
  177. return pytz.FixedOffset(total_minutes)