Browse Source

APP业务API-广告接口

linhaohong 1 year ago
parent
commit
5075509c9f

+ 0 - 0
Controller/CampaignController/CampaignController.py → AdminController/CampaignController.py


+ 3 - 3
Ansjer/urls.py

@@ -4,7 +4,7 @@ from django.urls import re_path
 
 
 from AdminController import UserManageController, RoleController, MenuController, TestServeController, \
 from AdminController import UserManageController, RoleController, MenuController, TestServeController, \
     ServeManagementController, LogManagementController, DeviceManagementController, VersionManagementController, \
     ServeManagementController, LogManagementController, DeviceManagementController, VersionManagementController, \
-    AiServeController, SurveysManageController, SerialManageController, IcloudManagementController
+    AiServeController, SurveysManageController, SerialManageController, IcloudManagementController, CampaignController
 from AdminController.CloudServiceManage import AgentDeviceController, AgentCustomerController, AgentOrderController
 from AdminController.CloudServiceManage import AgentDeviceController, AgentCustomerController, AgentOrderController
 from Controller import FeedBack, EquipmentOTA, EquipmentInfo, AdminManage, AppInfo, \
 from Controller import FeedBack, EquipmentOTA, EquipmentInfo, AdminManage, AppInfo, \
     Test, MealManage, DeviceManage, EquipmentStatus, SysManage, DeviceLog, LogAccess, \
     Test, MealManage, DeviceManage, EquipmentStatus, SysManage, DeviceLog, LogAccess, \
@@ -24,13 +24,13 @@ from Controller import FeedBack, EquipmentOTA, EquipmentInfo, AdminManage, AppIn
     RegionController, VPGController, LanguageController, TestController, DeviceConfirmRegion, S3GetStsController, \
     RegionController, VPGController, LanguageController, TestController, DeviceConfirmRegion, S3GetStsController, \
     DetectControllerV2, PcInfo, PctestController, DeviceDebug, PaymentCycle, \
     DetectControllerV2, PcInfo, PctestController, DeviceDebug, PaymentCycle, \
     DeviceLogController, CouponController, AiController, ShadowController, AppAccountManagement, InitController, \
     DeviceLogController, CouponController, AiController, ShadowController, AppAccountManagement, InitController, \
-    WeatherControl, AppCampaignController
+    WeatherControl
 from Controller.Cron import CronTaskController
 from Controller.Cron import CronTaskController
 from Controller.MessagePush import EquipmentMessagePush
 from Controller.MessagePush import EquipmentMessagePush
 from Controller.SensorGateway import SensorGatewayController, EquipmentFamilyController
 from Controller.SensorGateway import SensorGatewayController, EquipmentFamilyController
 from Controller.Surveys import CloudStorageController
 from Controller.Surveys import CloudStorageController
 from Controller.UserDevice import UserDeviceShareController
 from Controller.UserDevice import UserDeviceShareController
-from Controller.CampaignController import CampaignController
+from Controller.CampaignController import AppCampaignController
 from Model import views  # 定时任务,不要删除该行代码
 from Model import views  # 定时任务,不要删除该行代码
 
 
 urlpatterns = [
 urlpatterns = [

+ 0 - 558
Controller/AppCampaignController.py

@@ -1,558 +0,0 @@
-import time
-import pytz
-import json
-from datetime import datetime
-from datetime import time as Time
-
-from Model.models import AppAdvertiseCampaign, DeviceTypeModel, CountryModel, Device_User, OpenScreenCampaign
-from Ansjer.config import AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, SERVER_TYPE
-
-from django.core.paginator import Paginator
-from django.views import View
-from django.db.models import Prefetch
-from django.db.models import Q, F
-
-from Object.AWS.AmazonS3Util import AmazonS3Util
-from Object.ResponseObject import ResponseObject
-from Object.TokenObject import TokenObject
-
-
-class AppCampaignView(View):
-    def get(self, request, *args, **kwargs):
-        request.encoding = 'utf-8'
-        operation = kwargs.get('operation')
-        request_dict = request.GET
-        return self.validation(request_dict, request, operation)
-
-    def post(self, request, *args, **kwargs):
-        request.encoding = 'utf-8'
-        operation = kwargs.get('operation')
-        request_dict = request.POST
-        return self.validation(request_dict, request, operation)
-
-    def validation(self, request_dict, request, operation):
-        language = request_dict.get('language', 'en')
-        response = ResponseObject(language, 'pc')
-        if operation == 'getCampaignList':  # 获取广告活动列表
-            return self.get_campaign_list(request_dict, response)
-        elif operation == 'getCountryList':  # 查询国家列表
-            return self.get_country_list(response)
-        elif operation == 'addCampaign':  # 添加广告活动
-            return self.add_campaign(request, request_dict, response)
-        elif operation == 'updateCampaign':  # 更新广告活动
-            return self.update_campaign(request, request_dict, response)
-        elif operation == 'deleteCampaign':  # 删除广告活动
-            return self.delete_campaign(request_dict, response)
-        elif operation == 'switchCampaign':  # 广告活动开关
-            return self.switch_campaign(request_dict, response)
-        elif operation == 'appGetCampaigns':
-            return self.app_get_campaigns(request_dict)
-        elif operation == 'recordUserBehavior':
-            return self.record_user_behavior(request_dict)
-        elif operation == 'getUserBehaviorLog':
-            return self.get_user_behavior_log(request_dict, response)
-        else:
-            return response.json(414)
-
-    def get_campaign_list(self, request_dict, response):
-        """
-        查询广告活动列表
-        @param request_dict: 请求参数
-        @param response: 响应对象
-        @return: 响应对象包含广告活动列表
-        """
-        campaign_name = request_dict.get('campaign_name', None)
-        campaign_country = request_dict.get('campaign_country', None)
-        status = request_dict.get('status', None)
-        pageNo = request_dict.get('pageNo', 1)
-        pageSize = request_dict.get('pageSize', 20)
-        unknown_country = 0
-
-        # 连接并获取国家和设备类型
-        country_prefetch = Prefetch('country', queryset=CountryModel.objects.only('country_name'),
-                                    to_attr='country_list')
-        device_type_prefetch = Prefetch('device_type', queryset=DeviceTypeModel.objects.only('name'),
-                                        to_attr='device_type_list')
-        app_advertise_campaign_qs = AppAdvertiseCampaign.objects.prefetch_related(country_prefetch,
-                                                                                  device_type_prefetch)
-
-        # 过滤
-        if campaign_name:
-            app_advertise_campaign_qs = app_advertise_campaign_qs.filter(campaign_name=campaign_name)
-        if status:
-            app_advertise_campaign_qs = app_advertise_campaign_qs.filter(status=status)
-        if campaign_country:
-            campaign_country_list = campaign_country.split(',')
-            if "未知地区" in campaign_country_list:
-                unknown_country = 1
-            app_advertise_campaign_qs = app_advertise_campaign_qs.filter(
-                Q(country__country_name__in=campaign_country_list) | Q(unknown_country=unknown_country)).distinct()
-        app_advertise_campaign_qs = app_advertise_campaign_qs.filter(~Q(status=2))
-        # 分页
-        paginator = Paginator(app_advertise_campaign_qs.order_by('id'), pageSize)
-        campaigns = paginator.page(pageNo)
-
-        if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
-            s3_url = "https://ansjerfilemanager.s3.cn-northwest-1.amazonaws.com.cn/app/campaign/"
-        else:
-            s3_url = "https://ansjerfilemanager.s3.amazonaws.com/app/campaign/"
-
-        # 添加设备名和地区返回
-        campaign_list = []
-        for campaign in campaigns.object_list:
-            if campaign.unknown_country == 0:
-                countries = ",".join([country.country_name for country in campaign.country_list])
-            else:
-                country_list = campaign.country_list
-                country_names = []
-                for country in country_list:
-                    country_names.append(country.country_name)
-                country_names.append("未知地区")
-                countries = ",".join(country_names)
-            campaign_data = {
-                'id': campaign.id,
-                'image_url': s3_url + campaign.image_url,
-                'campaign_name': campaign.campaign_name,
-                'campaign_url': campaign.campaign_url,
-                'campaign_type': campaign.campaign_type,
-                'status': campaign.status,
-                'campaign_start_date': campaign.campaign_start_date,
-                'campaign_end_date': campaign.campaign_end_date,
-                'campaign_show_stime': campaign.campaign_show_stime,
-                'campaign_show_etime': campaign.campaign_show_etime,
-                'countries': countries,
-                'device_types': ",".join([device.name for device in campaign.device_type_list]),
-            }
-            campaign_list.append(campaign_data)
-
-        data = {
-            'list': campaign_list,
-            'total': paginator.count,
-        }
-
-        return response.json(0, data)
-
-    def add_campaign(self, request, request_dict, response):
-        """
-        添加新的广告活动
-        @param request_dict: 包含所有请求参数的字典
-        @param response: 响应对象
-        @return: 响应对象
-        """
-        file = request.FILES.get('posterFile', None)
-        campaign_name = request_dict.get('campaign_name', None)
-        campaign_url = request_dict.get('campaign_url', None)
-        campaign_type = request_dict.get('campaign_type', None)
-        status = request_dict.get('status', None)
-        device_type_names = json.loads(request_dict.get('device_type_list', None))  # 设备类型名称列表
-        country_name_list = json.loads(request_dict.get('country_name_list', None))  # 地区列表
-        campaign_start_time = request_dict.get('campaign_start_time', None)
-        campaign_end_time = request_dict.get('campaign_end_time', None)
-        campaign_show_stime = request_dict.get('campaign_show_stime', 0)
-        campaign_show_etime = request_dict.get('campaign_show_etime', 86399)
-
-        if not all([campaign_name, campaign_type, device_type_names, campaign_url,
-                    country_name_list, campaign_start_time, campaign_end_time, file]):
-            return response.json(444)
-
-        # 针对特殊地区的处理,表没设计好用这个处理挽救一下
-        unknown_country = 0
-        if "未知地区" in country_name_list:
-            unknown_country = 1
-            country_name_list.remove("未知地区")
-        if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
-            regin = 0
-            AWS_SES_ACCESS_REGION = "cn-northwest-1"
-        else:
-            regin = 1
-            AWS_SES_ACCESS_REGION = 'us-east-1'
-        fileName = file.name
-        try:
-            create_time = int(time.time())
-            update_time = int(time.time())
-            # 保存图片到存储桶
-            bucket_name = 'ansjerfilemanager'
-            file_key = f'app/campaign/OpenScreenAdvertise/{update_time}_{fileName}'
-            s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[regin], AWS_SECRET_ACCESS_KEY[regin], AWS_SES_ACCESS_REGION)
-            # 地址:https://ansjerfilemanager.s3.amazonaws.com/app/campaign/OpenScreenAdvertise/XXX.jpg
-            s3.upload_file_obj(
-                bucket_name,
-                file_key,
-                file,
-                {'ContentType': file.content_type, 'ACL': 'public-read'})
-            # 创建 AppAdvertiseCampaign 实例
-            new_campaign = AppAdvertiseCampaign.objects.create(
-                image_url=f"OpenScreenAdvertise/{update_time}_{fileName}",
-                campaign_name=campaign_name,
-                campaign_url=campaign_url,
-                campaign_type=campaign_type,
-                status=status,
-                unknown_country=unknown_country,
-                campaign_start_date=campaign_start_time,
-                campaign_end_date=campaign_end_time,
-                campaign_show_stime=campaign_show_stime,
-                campaign_show_etime=campaign_show_etime,
-                create_time=create_time,
-                update_time=update_time,
-            )
-
-            # 根据名称查找 DeviceTypeModel 的实例并建立关系
-            device_type_instances = DeviceTypeModel.objects.filter(name__in=device_type_names)
-            for device_type_instance in device_type_instances:
-                new_campaign.device_type.add(device_type_instance)
-
-            # 根据 ID 关联 CountryModel 实例
-            country_instances = CountryModel.objects.filter(country_name__in=country_name_list)
-            for country_instance in country_instances:
-                new_campaign.country.add(country_instance)
-
-        except Exception as e:
-            return response.json(178)
-
-        return response.json(0)
-
-    def update_campaign(self, request, request_dict, response):
-        campaign_id = request_dict.get('id', None)
-        campaign_name = request_dict.get('campaign_name', None)
-        campaign_url = request_dict.get('campaign_url', None)
-        campaign_type = request_dict.get('campaign_type', None)
-        device_type_names = json.loads(request_dict.get('device_type_list', '[]'))  # 设备类型名称列表
-        country_name_list = json.loads(request_dict.get('country_name_list', '[]'))  # 地区列表
-        campaign_start_time = request_dict.get('campaign_start_time', None)
-        campaign_end_time = request_dict.get('campaign_end_time', None)
-        campaign_show_stime = request_dict.get('campaign_show_stime', None)
-        campaign_show_etime = request_dict.get('campaign_show_etime', None)
-        file = request.FILES.get('posterFile', None)
-        if not campaign_id:
-            return response.json(444)
-
-        if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
-            regin = 0
-            AWS_SES_ACCESS_REGION = "cn-northwest-1"
-        else:
-            regin = 1
-            AWS_SES_ACCESS_REGION = 'us-east-1'
-
-        try:
-            update_time = int(time.time())
-            campaign = AppAdvertiseCampaign.objects.get(id=campaign_id)
-            if country_name_list is not None:
-                if "未知地区" in country_name_list:
-                    campaign.unknown_country = 1
-                    country_name_list.remove("未知地区")
-                else:
-                    campaign.unknown_country = 0
-            if file is not None:
-                # 删除存储桶原来的图片
-                s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[regin], AWS_SECRET_ACCESS_KEY[regin], AWS_SES_ACCESS_REGION)
-                bucket_name = 'ansjerfilemanager'
-                if campaign.image_url:
-                    s3.delete_obj(bucket_name, f"app/campaign/{campaign.image_url}")
-                # 添加新的图片
-                file_key = f'app/campaign/OpenScreenAdvertise/{update_time}_{file.name}'
-                s3.upload_file_obj(
-                    bucket_name,
-                    file_key,
-                    file,
-                    {'ContentType': file.content_type, 'ACL': 'public-read'}
-                )
-                campaign.image_url = f'OpenScreenAdvertise/{update_time}_{file.name}'
-            if campaign_name is not None:
-                campaign.campaign_name = campaign_name
-            if campaign_url is not None:
-                campaign.campaign_url = campaign_url
-            if campaign_type is not None:
-                campaign.campaign_type = campaign_type
-            if campaign_start_time is not None:
-                campaign.campaign_start_date = campaign_start_time
-            if campaign_end_time is not None:
-                campaign.campaign_end_date = campaign_end_time
-            if campaign_show_stime is not None:
-                campaign.campaign_show_stime = campaign_show_stime
-            if campaign_show_etime is not None:
-                campaign.campaign_show_etime = campaign_show_etime
-
-            # 更新多对多字段 - 设备类型
-            if device_type_names:
-                device_types = DeviceTypeModel.objects.filter(name__in=device_type_names)
-                campaign.device_type.set(device_types)
-
-            # 更新多对多字段 - 国家/地区
-            if country_name_list:
-                countries = CountryModel.objects.filter(country_name__in=country_name_list)
-                campaign.country.set(countries)
-
-            campaign.update_time = update_time
-
-            # 保存更新
-            campaign.save()
-        except Exception as e:
-            return response.json(177)
-
-        return response.json(0)
-
-    def switch_campaign(self, request_dict, response):
-        campaign_id = request_dict.get('id')
-        status = request_dict.get('status')
-        if not campaign_id:
-            return response.json(444)
-        try:
-            AppAdvertiseCampaign.objects.filter(pk=campaign_id).update(status=status, update_time=int(time.time()))
-            return response.json(0)
-        except Exception as e:
-            return response.json(444)
-
-    def delete_campaign(self, request_dict, response):
-        campaign_id = request_dict.get('id')
-        if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
-            regin = 0
-            AWS_SES_ACCESS_REGION = "cn-northwest-1"
-        else:
-            regin = 1
-            AWS_SES_ACCESS_REGION = 'us-east-1'
-        if not campaign_id:
-            return response.json(444)
-        try:
-            campaign = AppAdvertiseCampaign.objects.get(pk=campaign_id)
-            s3 = AmazonS3Util(AWS_ACCESS_KEY_ID[regin], AWS_SECRET_ACCESS_KEY[regin], AWS_SES_ACCESS_REGION)
-            bucket_name = 'ansjerfilemanager'
-            if campaign.image_url:
-                s3.delete_obj(bucket_name, f"app/campaign/{campaign.image_url}")
-            # 清除多对多关系
-            campaign.device_type.clear()
-            campaign.country.clear()
-            # 保留在广告表中
-            campaign.status = 2
-            campaign.update_time = int(time.time())
-            campaign.save()
-            return response.json(0)
-
-        except Exception as e:
-            return response.json(176)
-
-    def get_timezone_offset(self, tz):
-        """
-        将 "+8:00" 格式的时区字符串转换为包含分钟偏移的时区。
-        """
-        sign = tz[0]  # " " 或 "-"
-        hours, minutes = map(int, tz[1:].split('.'))  # 分离小时和分钟
-
-        # 计算总分钟数
-        total_minutes = hours * 60 + minutes
-        if sign == '-':
-            total_minutes = -total_minutes
-
-        # 使用 pytz.FixedOffset 创建时区
-        return pytz.FixedOffset(total_minutes)
-
-    def app_get_campaigns(cls, request_dict):
-        """
-        APP获取广告活动列表
-        @param request_dict: 请求参数
-        @param response: 响应对象
-        @return: 响应对象
-        """
-        language = request_dict.get('language', 'en')
-        tz = request_dict.get('tz', '+0:00')
-        token = request_dict.get('token', None)
-        response = ResponseObject(language)
-        if not token:
-            return response.json(444)
-        token = TokenObject(token)
-        if token.code != 0:
-            return response.json(token.code)
-        user_id = token.userID
-
-        if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
-            s3_url = "https://ansjerfilemanager.s3.cn-northwest-1.amazonaws.com.cn/app/campaign/"
-        else:
-            s3_url = "https://ansjerfilemanager.s3.amazonaws.com/app/campaign/"
-
-        # 当日时间戳区间获取
-        timezone = cls.get_timezone_offset(tz)
-        current_date = datetime.now().date()
-        start_of_day = datetime.combine(current_date, Time.min)
-        end_of_day = datetime.combine(current_date, Time.max)
-        start_timestamp = int(start_of_day.timestamp())
-        end_timestamp = int(end_of_day.timestamp())
-
-        open_screen_campaign_qs = OpenScreenCampaign.objects.filter(
-            user_id=user_id,
-            create_time__gt=start_timestamp,
-            create_time__lt=end_timestamp
-        )
-        if not open_screen_campaign_qs.exists():
-            OpenScreenCampaign.objects.create(user_id=user_id,
-                                              update_time=int(time.time()),
-                                              create_time=int(time.time()))
-        try:
-            country_prefetch = Prefetch('country', queryset=CountryModel.objects.only('id'), to_attr='country_list')
-            device_type_prefetch = Prefetch('device_type', queryset=DeviceTypeModel.objects.only('type'),
-                                            to_attr='device_type_list')
-            app_advertise_campaign_qs = AppAdvertiseCampaign.objects.prefetch_related(country_prefetch,
-                                                                                      device_type_prefetch)
-
-            device_info_qs = Device_User.objects.filter(userID=user_id).values("region_country").first()
-            country_id = device_info_qs.get('region_country')
-            if country_id != 0:
-                app_advertise_campaign_qs = app_advertise_campaign_qs.filter(country__id=country_id, status=1)
-            else:
-                app_advertise_campaign_qs = app_advertise_campaign_qs.filter(status=1, unknown_country=1)
-
-            # 返回 广告名称、广告类型、开始时间、结束时间、广告图片、活动链接
-            campaigns_list = []
-
-            for campaign in app_advertise_campaign_qs:
-                # campaign_end_date = (datetime.utcfromtimestamp(campaign.campaign_end_date) # 日期版本
-                #                      .replace(tzinfo=pytz.utc).astimezone(timezone).strftime('%Y-%m-%d'))
-
-                # 日期范围
-                campaigns_start_date = datetime.fromtimestamp(campaign.campaign_start_date, pytz.utc).astimezone(
-                    timezone).replace(hour=0, minute=0, second=0, microsecond=0).timestamp()  # 时间戳版本
-                campaign_end_date = datetime.fromtimestamp(campaign.campaign_end_date, pytz.utc).astimezone(
-                    timezone).replace(hour=0, minute=0, second=0, microsecond=0).timestamp()  # 时间戳版本
-
-                # 时间范围
-                campaign_start_firstday = sum(int(x) * 60 ** i for i, x in enumerate(reversed(
-                    datetime.utcfromtimestamp(campaign.campaign_start_date + campaign.campaign_show_stime).replace(
-                        tzinfo=pytz.utc).astimezone(timezone).strftime('%H:%M').split(':')))) * 60  # 秒数版本
-                campaign_end_firstday = sum(int(x) * 60 ** i for i, x in enumerate(reversed(
-                    datetime.utcfromtimestamp(campaign.campaign_start_date + campaign.campaign_show_etime).replace(
-                        tzinfo=pytz.utc).astimezone(timezone).strftime('%H:%M').split(':')))) * 60  # 秒数版本
-
-                # campaign_end_firstday = (
-                #     datetime.utcfromtimestamp(campaign.campaign_start_date + campaign.campaign_show_etime)
-                #     .replace(tzinfo=pytz.utc).astimezone(timezone).strftime('%H:%M')) # 时间版本
-
-                campaigns_list.append({
-                    'campaign_id': campaign.id,
-                    'image_url': s3_url + campaign.image_url,
-                    'campaign_url': campaign.campaign_url,
-                    'campaign_name': campaign.campaign_name,
-                    'campaign_type': campaign.campaign_type,
-                    'start_date': campaigns_start_date,
-                    'end_date': campaign_end_date,
-                    'start_time': campaign_start_firstday,
-                    'end_time': campaign_end_firstday,
-                    'device_types': [device.type for device in campaign.device_type_list],
-                })
-            return response.json(0, {
-                'interval_time': 86400,
-                'campaigns': campaigns_list
-            })
-        except Exception as e:
-            return response.json(173)
-
-    def record_user_behavior(cls, request_dict):
-        """
-        记录用户行为
-        @param request_dict: 请求参数
-        @param response: 响应对象
-        @return: 响应对象
-        """
-        language = request_dict.get('language', 'en')
-        status = request_dict.get('status', None)  # 1.未跳过 2.已跳过 3.点击广告
-        campaign_id = request_dict.get('campaign_id', None)
-        token = request_dict.get('token', None)
-        response = ResponseObject(language)
-        if not token:
-            return response.json(444)
-        token = TokenObject(token)
-        if token.code != 0:
-            return response.json(token.code)
-        user_id = token.userID
-
-        if not all([status, campaign_id]):
-            return response.json(444)
-
-        # 当日时间戳区间获取
-        current_date = datetime.now().date()
-        start_of_day = datetime.combine(current_date, Time.min)
-        end_of_day = datetime.combine(current_date, Time.max)
-        start_timestamp = int(start_of_day.timestamp())
-        end_timestamp = int(end_of_day.timestamp())
-
-        try:
-            # 筛选符合条件的记录
-            open_screen_campaigns = OpenScreenCampaign.objects.filter(
-                user_id=user_id,
-                create_time__gt=start_timestamp,
-                create_time__lt=end_timestamp,
-                status=0,
-            )
-
-            # 检查是否存在记录
-            if not open_screen_campaigns.exists():
-                # 如果不存在,则创建新记录
-                OpenScreenCampaign.objects.create(
-                    user_id=user_id,
-                    status=status,
-                    campaign_id_id=campaign_id,
-                    create_time=int(time.time()),
-                    update_time=int(time.time())
-                )
-
-            else:
-                # 如果存在,则更新最新的记录
-                latest_campaign = open_screen_campaigns.latest("create_time")
-                latest_campaign.status = status
-                latest_campaign.campaign_id_id = campaign_id
-                latest_campaign.update_time = int(time.time())
-                latest_campaign.save()
-
-        except Exception as e:
-            return response.json(177, {'error': '更新错误'})
-
-        return response.json(0)
-
-    def get_user_behavior_log(self, request_dict, response):
-        campaign_ids = request_dict.get('campaign_ids', None)
-        start_time = request_dict.get('start_time', None)
-        end_time = request_dict.get('end_time', None)
-        if not all([start_time, end_time]):
-            return response.json(444)
-        try:
-            open_screen_campaign_qs = OpenScreenCampaign.objects.filter(update_time__range=[int(start_time), int(end_time)])
-
-            if campaign_ids is not None:
-                open_screen_campaign_qs = open_screen_campaign_qs.filter(
-                    Q(campaign_id_id__isnull=True) | Q(campaign_id_id__in=json.loads(campaign_ids)))
-
-            open_screen_campaign_qs = open_screen_campaign_qs.select_related('campaign_id').annotate(
-                campaign_name=F('campaign_id__campaign_name'),
-                campaign_type=F('campaign_id__campaign_type'),
-                campaign_status=F('campaign_id__status'),
-                start_date=F('campaign_id__campaign_start_date'),
-                end_date=F('campaign_id__campaign_end_date'),
-                start_time=F('campaign_id__campaign_show_stime'),
-                end_time=F('campaign_id__campaign_show_etime')
-            ).values('id', 'user_id', 'status', 'update_time', 'create_time', 'campaign_id', 'campaign_name',
-                     'campaign_type', 'campaign_status', 'start_date', 'end_date', 'start_time', 'end_time')
-            if not open_screen_campaign_qs.exists():
-                return response.json(0, {'list': []})
-            campaigns_list = list(open_screen_campaign_qs)
-            return response.json(0, {'list': campaigns_list})
-        except Exception as e:
-            return response.json(173)
-
-    def get_country_list(self, response):
-        try:
-            if SERVER_TYPE == 'Ansjer.us_config.formal_settings':
-                region_api = 'https://www.dvema.com/'
-            elif SERVER_TYPE == 'Ansjer.eur_config.formal_settings':
-                region_api = 'https://api.zositeche.com/'
-            elif SERVER_TYPE == 'Ansjer.cn_config.formal_settings':
-                region_api = 'https://www.zositechc.cn/'
-            else:
-                region_api = 'https://test.zositechc.cn/'
-            country_qs = CountryModel.objects.filter(region__api=region_api).values('country_name')
-            if not country_qs.exists():
-                return response.json(173)
-
-            country_list = []
-            for country in country_qs:
-                country_list.append(country['country_name'])
-            return response.json(0, {'list': country_list})
-        except Exception as e:
-            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
-

+ 204 - 0
Controller/CampaignController/AppCampaignController.py

@@ -0,0 +1,204 @@
+import time
+import pytz
+from datetime import datetime
+from datetime import time as Time
+
+from Model.models import AppAdvertiseCampaign, DeviceTypeModel, CountryModel, Device_User, OpenScreenCampaign
+from Ansjer.config import SERVER_TYPE
+
+from django.views import View
+from django.db.models import Prefetch
+
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+
+
+class AppCampaignView(View):
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        request_dict = request.GET
+        return self.validation(request, request_dict, operation)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        request_dict = request.POST
+        return self.validation(request, request_dict, operation)
+
+    def validation(self, request, request_dict, operation):
+        language = request_dict.get('language', 'en')
+        response = ResponseObject(language)
+        tko = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
+        response.lang = tko.lang
+        if tko.code != 0:
+            return response.json(tko.code)
+        userID = tko.userID
+        if operation == 'appGetCampaigns':
+            return self.app_get_campaigns(userID, request_dict, response)
+        elif operation == 'recordUserBehavior':
+            return self.record_user_behavior(userID, request_dict)
+        else:
+            return response.json(414)
+
+    def app_get_campaigns(self, userID, request_dict, response):
+        tz = request_dict.get('tz', '+0:00')
+        app_type = request_dict.get('appType', 0)
+        if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
+            s3_url = "https://ansjerfilemanager.s3.cn-northwest-1.amazonaws.com.cn/app/campaign/"
+        else:
+            s3_url = "https://ansjerfilemanager.s3.amazonaws.com/app/campaign/"
+
+        # 当日时间戳区间获取
+        timezone = self.get_timezone_offset(tz)
+        current_date = datetime.now().date()
+        start_of_day = datetime.combine(current_date, Time.min)
+        end_of_day = datetime.combine(current_date, Time.max)
+        start_timestamp = int(start_of_day.timestamp())
+        end_timestamp = int(end_of_day.timestamp())
+
+        open_screen_campaign_qs = OpenScreenCampaign.objects.filter(
+            user_id=userID,
+            create_time__gt=start_timestamp,
+            create_time__lt=end_timestamp
+        )
+        if not open_screen_campaign_qs.exists():
+            OpenScreenCampaign.objects.create(user_id=userID,
+                                              update_time=int(time.time()),
+                                              create_time=int(time.time()))
+        try:
+            country_prefetch = Prefetch('country', queryset=CountryModel.objects.only('id'), to_attr='country_list')
+            device_type_prefetch = Prefetch('device_type', queryset=DeviceTypeModel.objects.only('type'),
+                                            to_attr='device_type_list')
+            app_advertise_campaign_qs = AppAdvertiseCampaign.objects.prefetch_related(country_prefetch,
+                                                                                      device_type_prefetch)
+
+            device_info_qs = Device_User.objects.filter(userID=userID).values("region_country").first()
+            country_id = device_info_qs.get('region_country')
+            if country_id != 0:
+                app_advertise_campaign_qs = app_advertise_campaign_qs.filter(country__id=country_id, status=1)
+            else:
+                app_advertise_campaign_qs = app_advertise_campaign_qs.filter(status=1, unknown_country=1)
+            if app_type is not None:
+                app_advertise_campaign_qs = app_advertise_campaign_qs.filter(app_bundle_type=app_type)
+            # 返回 广告名称、广告类型、开始时间、结束时间、广告图片、活动链接
+            campaigns_list = []
+
+            for campaign in app_advertise_campaign_qs:
+                # campaign_end_date = (datetime.utcfromtimestamp(campaign.campaign_end_date) # 日期版本
+                #                      .replace(tzinfo=pytz.utc).astimezone(timezone).strftime('%Y-%m-%d'))
+
+                # 日期范围
+                campaigns_start_date = datetime.fromtimestamp(campaign.campaign_start_date, pytz.utc).astimezone(
+                    timezone).replace(hour=0, minute=0, second=0, microsecond=0).timestamp()  # 时间戳版本
+                campaign_end_date = datetime.fromtimestamp(campaign.campaign_end_date, pytz.utc).astimezone(
+                    timezone).replace(hour=0, minute=0, second=0, microsecond=0).timestamp()  # 时间戳版本
+
+                # 时间范围
+                campaign_start_firstday = sum(int(x) * 60 ** i for i, x in enumerate(reversed(
+                    datetime.utcfromtimestamp(campaign.campaign_start_date + campaign.campaign_show_stime).replace(
+                        tzinfo=pytz.utc).astimezone(timezone).strftime('%H:%M').split(':')))) * 60  # 秒数版本
+                campaign_end_firstday = sum(int(x) * 60 ** i for i, x in enumerate(reversed(
+                    datetime.utcfromtimestamp(campaign.campaign_start_date + campaign.campaign_show_etime).replace(
+                        tzinfo=pytz.utc).astimezone(timezone).strftime('%H:%M').split(':')))) * 60  # 秒数版本
+
+                # campaign_end_firstday = (
+                #     datetime.utcfromtimestamp(campaign.campaign_start_date + campaign.campaign_show_etime)
+                #     .replace(tzinfo=pytz.utc).astimezone(timezone).strftime('%H:%M')) # 时间版本
+                # 轮播广告
+                banner_campaign = []
+                for sort in campaign.banner_campaign:
+                    banner = campaign.banner_campaign[sort]
+                    banner["image"] = s3_url + banner["image"]
+                    banner_campaign.append(banner)
+
+                campaigns_list.append({
+                    'campaign_id': campaign.id,
+                    'image_url': s3_url + campaign.image_url,
+                    'banner_campaign': banner_campaign,
+                    'campaign_url': campaign.campaign_url,
+                    'campaign_name': campaign.campaign_name,
+                    'campaign_type': campaign.campaign_type,
+                    'start_date': campaigns_start_date,
+                    'end_date': campaign_end_date,
+                    'start_time': campaign_start_firstday,
+                    'end_time': campaign_end_firstday,
+                    'device_types': [device.type for device in campaign.device_type_list],
+                })
+            return response.json(0, {
+                'interval_time': 86400,
+                'campaigns': campaigns_list
+            })
+        except Exception as e:
+            print(e)
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    def record_user_behavior(self, userID, request_dict, response):
+        """
+        记录用户行为
+        @param request_dict: 请求参数
+        @param response: 响应对象
+        @return: 响应对象
+        """
+        status = request_dict.get('status', None)  # 1.未跳过 2.已跳过 3.点击广告
+        campaign_id = request_dict.get('campaign_id', None)
+        user_id = userID
+
+        if not all([status, campaign_id]):
+            return response.json(444)
+
+        # 当日时间戳区间获取
+        current_date = datetime.now().date()
+        start_of_day = datetime.combine(current_date, Time.min)
+        end_of_day = datetime.combine(current_date, Time.max)
+        start_timestamp = int(start_of_day.timestamp())
+        end_timestamp = int(end_of_day.timestamp())
+
+        try:
+            # 筛选符合条件的记录
+            open_screen_campaigns = OpenScreenCampaign.objects.filter(
+                user_id=user_id,
+                create_time__gt=start_timestamp,
+                create_time__lt=end_timestamp,
+                status=0,
+            )
+
+            # 检查是否存在记录
+            if not open_screen_campaigns.exists():
+                # 如果不存在,则创建新记录
+                OpenScreenCampaign.objects.create(
+                    user_id=user_id,
+                    status=status,
+                    campaign_id_id=campaign_id,
+                    create_time=int(time.time()),
+                    update_time=int(time.time())
+                )
+
+            else:
+                # 如果存在,则更新最新的记录
+                latest_campaign = open_screen_campaigns.latest("create_time")
+                latest_campaign.status = status
+                latest_campaign.campaign_id_id = campaign_id
+                latest_campaign.update_time = int(time.time())
+                latest_campaign.save()
+
+            return response.json(0)
+
+        except Exception as e:
+            print(e)
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    def get_timezone_offset(self, tz):
+        """
+        将 "+8:00" 格式的时区字符串转换为包含分钟偏移的时区。
+        """
+        sign = tz[0]  # " " 或 "-"
+        hours, minutes = map(int, tz[1:].split('.'))  # 分离小时和分钟
+
+        # 计算总分钟数
+        total_minutes = hours * 60 + minutes
+        if sign == '-':
+            total_minutes = -total_minutes
+
+        # 使用 pytz.FixedOffset 创建时区
+        return pytz.FixedOffset(total_minutes)