Bladeren bron

Merge branch 'test' of http://192.168.136.99:3000/servers/ASJServer into locky

locky 1 jaar geleden
bovenliggende
commit
3df730cd5c

+ 7 - 6
AdminController/CampaignController.py

@@ -149,7 +149,7 @@ class CampaignView(View):
         """
         try:
             campaign_name = request_dict.get('campaign_name', None)
-            campaign_url = request_dict.get('campaign_url', None)
+            campaign_url = request_dict.get('campaign_url', "")
             status = request_dict.get('status', 2)
             campaign_start_time = request_dict.get('campaign_start_time', None)
             campaign_end_time = request_dict.get('campaign_end_time', None)
@@ -162,9 +162,9 @@ class CampaignView(View):
             device_type_names = json.loads(request_dict.get('device_type_list', "[]"))  # 设备类型名称列表
             country_name_list = json.loads(request_dict.get('country_name_list', "[]"))  # 地区列表
 
-            required_fields = [campaign_name, campaign_url, campaign_start_time, campaign_end_time,
+            required_fields = [campaign_name, campaign_start_time, campaign_end_time,
                                app_bundle_type]
-            list_fields = [device_type_names, country_name_list, banner_campaign_urls]
+            list_fields = [device_type_names, country_name_list]
 
             # 检查基本字段是否为None
             if any(field is None for field in required_fields):
@@ -191,8 +191,11 @@ class CampaignView(View):
             poster_image_url = self.upload_files_to_s3(poster_file,
                                                        "OpenScreenAdvertise")[0] if poster_file is not None else ""
             campaign_type = []
-            if banner_image_urls is not []:
+            if poster_image_url != "":
                 campaign_type.append(1)
+
+            if banner_image_urls:
+                campaign_type.append(2)
                 banner_campaign = {
                     str(index): {"image": image_url, "url": campaign_url}
                     for index, (image_url, campaign_url) in
@@ -201,8 +204,6 @@ class CampaignView(View):
             else:
                 banner_campaign = {}
 
-            if poster_image_url != "":
-                campaign_type.append(2)
             create_time = int(time.time())
             update_time = int(time.time())
             # 创建 AppAdvertiseCampaign 实例

+ 267 - 0
AdminController/MessageMangementController.py

@@ -0,0 +1,267 @@
+import time
+import boto3
+import botocore
+import oss2
+from botocore import client
+from django.core.paginator import Paginator
+from django.db.models import Q
+from django.views.generic.base import View
+
+from Ansjer.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, \
+    SERVER_TYPE
+from Model.models import Device_Info, VodBucketModel, DeviceTypeModel
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+from Model import models
+from Object.utils import LocalDateTimeUtil
+from Service.EquipmentInfoService import EquipmentInfoService
+from Service.VodHlsService import SplitVodHlsObject
+
+
+class MassageView(View):
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request, request.GET, operation)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request, request.POST, operation)
+
+    def validation(self, request, request_dict, operation):
+        language = request_dict.get('language', 'en')
+        response = ResponseObject(language, 'pc')
+        if operation == 'XXX':
+            return 0
+        else:
+            tko = TokenObject(request.META.get('HTTP_AUTHORIZATION'), returntpye='pc')
+            if tko.code != 0:
+                return response.json(tko.code)
+            if operation == 'queryInfoList':
+                return self.query_info_list(request_dict, response)
+            else:
+                return response.json(414)
+
+    def query_info_list(self, request_dict, response):
+        """
+        查询推送数据
+        @param request_dict: 请求参数
+        @request_dict uids: 设备id
+        @request_dict eventType: 事件类型
+        @request_dict eventType: userID
+        @request_dict startTime: 开始时间戳
+        @request_dict endTime: 结束时间戳
+        @request_dict pageNo: 开始时间戳
+        @request_dict pageSize: 结束时间戳
+        @param response:
+        @return:
+        """
+        uids = request_dict.get('uids', None)
+        event_type = request_dict.get('eventType', None)
+        user_id = request_dict.get('userID', None)
+        # 时间
+        start_time = request_dict.get('startTime', None)
+        end_time = request_dict.get('endTime', None)
+        # 分页
+        page = int(request_dict.get('pageNo', None))
+        size = int(request_dict.get('pageSize', None))
+        # 区域
+        if SERVER_TYPE == 'Ansjer.cn_config.formal_settings' or SERVER_TYPE == 'Ansjer.cn_config.test_settings':
+            region = 2
+        else:
+            region = 1
+
+        query = Q()
+        if not start_time and not end_time:
+            # 默认查询近七天内数据
+            end_time = int(time.time())
+            start_time = LocalDateTimeUtil.get_before_days_timestamp(end_time, 7)
+            query &= Q(event_time__range=(start_time, end_time))
+
+        elif start_time and end_time:
+            query &= Q(event_time__range=(start_time, end_time))
+
+        else:
+            response.json(10, "需要给出一个时间段")
+
+        if user_id is None and uids is None:
+            return response.json(0, {"list": [], "total": 0})
+
+        # 过滤条件
+        if user_id is not None and user_id != "":
+            query &= Q(device_user_id=user_id)
+
+        if uids is not None and uids != "":
+            uid_list = uids.split(',')
+            query &= Q(device_uid__in=uid_list)
+
+        if event_type is not None:
+            event_type_list = EquipmentInfoService.get_comb_event_type(event_type)
+            event_type_list = list(set(event_type_list))
+            tags = EquipmentInfoService.get_event_tag(event_type)
+            if event_type_list:
+                query &= Q(event_type__in=event_type_list)
+                tags = ''
+                query &= Q(event_tag__regex=tags)
+            elif tags:
+                query &= Q(event_tag__regex=tags)
+
+        # 联表查询
+        querysets = []
+        for i in range(1, 21):
+            table_name = f'EquipmentInfo{i}'
+            model_class = getattr(models, table_name)
+            annotated_queryset = model_class.objects.filter(query)
+            querysets.append(annotated_queryset)
+
+        equipment_info_combined_qs = querysets[0].union(*querysets[1:], all=True)
+
+        # 创建分页对象
+        equipment_info_combined_qs = equipment_info_combined_qs.order_by("-event_time")
+        paginator = Paginator(equipment_info_combined_qs, size)
+        # 获取请求页的数据
+        packages_page = paginator.page(page)
+
+        # 连接存储桶
+        auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+        oss_img_bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'apg')
+        aws_s3 = boto3.client(
+            's3',
+            aws_access_key_id=AWS_ACCESS_KEY_ID[1],
+            aws_secret_access_key=AWS_SECRET_ACCESS_KEY[1],
+            config=botocore.client.Config(signature_version='s3v4'),
+            region_name='us-east-1'
+        )
+        aws_s3_cn = boto3.client(
+            's3',
+            aws_access_key_id=AWS_ACCESS_KEY_ID[0],
+            aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
+            config=botocore.client.Config(signature_version='s3v4'),
+            region_name='cn-northwest-1'
+        )
+
+        # ai消息标识所有组合标签
+        ai_all_event_type = EquipmentInfoService.get_all_comb_event_type()
+
+        # 遍历调整返回数据
+        equipment_info_list = []
+        for equipment_info in packages_page:
+            uid = equipment_info.device_uid
+            channel = equipment_info.channel
+            event_time = equipment_info.event_time
+            storage_location = equipment_info.storage_location
+            border_coords = equipment_info.border_coords
+            event_tag = equipment_info.event_tag
+
+            img_url = ""
+            if equipment_info.is_st == 1:
+                thumbspng = '{}/{}/{}.jpeg'.format(uid, channel, event_time)
+                if storage_location == 1:  # 阿里云oss
+                    img_url = oss_img_bucket.sign_url('GET', thumbspng, 300)
+                else:
+                    params = {'Key': thumbspng}
+                    if region == 1:  # AWS国外
+                        params['Bucket'] = 'foreignpush'
+                        img_url = aws_s3.generate_presigned_url(
+                            'get_object', Params=params, ExpiresIn=300)
+                    else:  # AWS国内
+                        params['Bucket'] = 'push'
+                        img_url = aws_s3_cn.generate_presigned_url(
+                            'get_object', Params=params, ExpiresIn=300)
+
+                img_url = img_url
+                img_list = [img_url]
+
+            elif equipment_info.is_st == 2:
+                # 列表装载回放时间戳标记
+                split_vod_hls_obj = SplitVodHlsObject()
+                vodqs = split_vod_hls_obj.get_vod_hls_data(
+                    uid=uid, channel=channel, start_time=int(event_time)).values('bucket_id')
+                if not vodqs.exists():
+                    return response.json(173)
+                vod_bucket_qs = VodBucketModel.objects.filter(id=vodqs[0]['bucket_id']).values('bucket', 'endpoint')
+                if not vod_bucket_qs.exists():
+                    return response.json(173)
+                bucket_name = vod_bucket_qs[0]['bucket']
+                endpoint = vod_bucket_qs[0]['endpoint']
+                bucket = oss2.Bucket(auth, endpoint, bucket_name)
+                ts = '{}/vod{}/{}/ts0.ts'.format(uid, channel, event_time)
+                if storage_location == 1:  # 阿里云oss
+                    thumb0 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_0000,w_700'})
+                    thumb1 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_1000,w_700'})
+                    thumb2 = bucket.sign_url('GET', ts, 3600, params={'x-oss-process': 'video/snapshot,t_2000,w_700'})
+                    img_url = ""
+                    img_list = [thumb0, thumb1, thumb2]
+                else:
+                    params = {'Key': ts}
+                    if region == 1:  # AWS国外
+                        params['Bucket'] = 'foreignpush'
+                        img_url = aws_s3.generate_presigned_url(
+                            'get_object', Params=params, ExpiresIn=300)
+                    else:  # AWS国内
+                        params['Bucket'] = 'push'
+                        img_url = aws_s3_cn.generate_presigned_url(
+                            'get_object', Params=params, ExpiresIn=300)
+                    img_list = [img_url]
+
+            elif equipment_info.is_st == 3 or equipment_info.is_st == 4:
+                # 列表装载回放时间戳标记
+                img_list = []
+                for i in range(equipment_info.is_st):
+                    thumbspng = '{}/{}/{}_{}.jpeg'.format(uid, channel, event_time, i)
+                    if storage_location == 1:  # 阿里云oss
+                        img_url = oss_img_bucket.sign_url('GET', thumbspng, 300)
+                    else:
+                        params = {'Key': thumbspng}
+                        if region == 1:  # 国外AWS
+                            params['Bucket'] = 'foreignpush'
+                            img_url = aws_s3.generate_presigned_url(
+                                'get_object', Params=params, ExpiresIn=300)
+                        else:  # 国内AWS
+                            params['Bucket'] = 'push'
+                            img_url = aws_s3_cn.generate_presigned_url(
+                                'get_object', Params=params, ExpiresIn=300)
+                    img_list.append(img_url)
+
+            else:
+                img_list = []
+
+            uid_type = Device_Info.objects.filter(UID=uid).values('Type').first()
+            device_type = DeviceTypeModel.objects.filter(type=uid_type['Type']).values('name').first()
+            border_coords = '' if border_coords == '' else eval(border_coords)
+            ai_event_type_list = []
+
+            # 如果是ai消息类型,则分解eventType, 如:123 -> [1,2,3]
+            if border_coords and event_type in ai_all_event_type:
+                ai_event_type_list = list(map(int, str(event_type)))
+            if EquipmentInfoService.is_combo_tag(event_type, event_tag):
+                ai_event_type_list += EquipmentInfoService.get_combo_types(event_type, event_tag)
+            equipment_info_data = {
+                "uid": uid,
+                "status": equipment_info.status,
+                "answerStatus": equipment_info.answer_status,
+                "alarm": equipment_info.alarm,
+                "isSt": equipment_info.is_st,
+                "storageLocation": storage_location,
+                "devNickName": equipment_info.device_nick_name,
+                "channel": channel,
+                "eventType": equipment_info.event_type,
+                "eventTime": int(event_time),
+                "addTime": equipment_info.add_time,
+                "borderCoords": border_coords,
+                "eventTag": event_tag,
+                "img": img_url,
+                "imgList": img_list,
+                "uidType": device_type["name"],
+                "aiEventTypeList": str(ai_event_type_list),
+            }
+            equipment_info_list.append(equipment_info_data)
+
+        data = {
+            "list": equipment_info_list,
+            "total": paginator.count
+        }
+
+        return response.json(0, data)

+ 18 - 0
Ansjer/cn_config/config_formal.py

@@ -140,3 +140,21 @@ APNS_CONFIG = {
         'pem_path': 'Ansjer/file/apns_pem/commissionf.pem',
     }
 }
+
+OCI_CONFIG = {
+    'us': {
+        'user': 'ocid1.user.oc1..aaaaaaaa63vtn64izdujrghlfby6xrlrrdce4yldtnjm7tmqzoc5i2b36s5q',
+        'fingerprint': '09:ff:f4:fa:64:bd:7b:72:64:67:5e:9a:ba:01:68:7b',
+        'tenancy': 'ocid1.tenancy.oc1..aaaaaaaaemreyqoegf4wbegfzetg63bwvzxa7ahfptbziexslzfmc7gnuwmq',
+        'region': 'us-phoenix-1',
+        'key_file': 'Ansjer/file/oci_pem/servers@ansjer.com_2023-12-20T07_21_33.069Z.pem'
+    },
+    'eur': {
+        'user': 'ocid1.user.oc1..aaaaaaaa63vtn64izdujrghlfby6xrlrrdce4yldtnjm7tmqzoc5i2b36s5q',
+        'fingerprint': '09:ff:f4:fa:64:bd:7b:72:64:67:5e:9a:ba:01:68:7b',
+        'tenancy': 'ocid1.tenancy.oc1..aaaaaaaaemreyqoegf4wbegfzetg63bwvzxa7ahfptbziexslzfmc7gnuwmq',
+        'region': 'uk-london-1',
+        'key_file': 'Ansjer/file/oci_pem/servers@ansjer.com_2023-12-20T07_21_33.069Z.pem'
+    }
+}
+OCI_NAMESPACE_NAME = 'cnmlmfa4fooi'

+ 18 - 0
Ansjer/cn_config/config_test.py

@@ -149,3 +149,21 @@ APNS_CONFIG = {
         'pem_path': 'Ansjer/file/apns_pem/commissionf-dev.pem',
     }
 }
+
+OCI_CONFIG = {
+    'us': {
+        'user': 'ocid1.user.oc1..aaaaaaaa63vtn64izdujrghlfby6xrlrrdce4yldtnjm7tmqzoc5i2b36s5q',
+        'fingerprint': '09:ff:f4:fa:64:bd:7b:72:64:67:5e:9a:ba:01:68:7b',
+        'tenancy': 'ocid1.tenancy.oc1..aaaaaaaaemreyqoegf4wbegfzetg63bwvzxa7ahfptbziexslzfmc7gnuwmq',
+        'region': 'us-phoenix-1',
+        'key_file': 'Ansjer/file/oci_pem/servers@ansjer.com_2023-12-20T07_21_33.069Z.pem'
+    },
+    'eur': {
+        'user': 'ocid1.user.oc1..aaaaaaaa63vtn64izdujrghlfby6xrlrrdce4yldtnjm7tmqzoc5i2b36s5q',
+        'fingerprint': '09:ff:f4:fa:64:bd:7b:72:64:67:5e:9a:ba:01:68:7b',
+        'tenancy': 'ocid1.tenancy.oc1..aaaaaaaaemreyqoegf4wbegfzetg63bwvzxa7ahfptbziexslzfmc7gnuwmq',
+        'region': 'uk-london-1',
+        'key_file': 'Ansjer/file/oci_pem/servers@ansjer.com_2023-12-20T07_21_33.069Z.pem'
+    }
+}
+OCI_NAMESPACE_NAME = 'cnmlmfa4fooi'

+ 18 - 0
Ansjer/eur_config/config_formal.py

@@ -140,3 +140,21 @@ APNS_CONFIG = {
         'pem_path': 'Ansjer/file/apns_pem/commissionf.pem',
     }
 }
+
+OCI_CONFIG = {
+    'us': {
+        'user': 'ocid1.user.oc1..aaaaaaaa63vtn64izdujrghlfby6xrlrrdce4yldtnjm7tmqzoc5i2b36s5q',
+        'fingerprint': '09:ff:f4:fa:64:bd:7b:72:64:67:5e:9a:ba:01:68:7b',
+        'tenancy': 'ocid1.tenancy.oc1..aaaaaaaaemreyqoegf4wbegfzetg63bwvzxa7ahfptbziexslzfmc7gnuwmq',
+        'region': 'us-phoenix-1',
+        'key_file': 'Ansjer/file/oci_pem/servers@ansjer.com_2023-12-20T07_21_33.069Z.pem'
+    },
+    'eur': {
+        'user': 'ocid1.user.oc1..aaaaaaaa63vtn64izdujrghlfby6xrlrrdce4yldtnjm7tmqzoc5i2b36s5q',
+        'fingerprint': '09:ff:f4:fa:64:bd:7b:72:64:67:5e:9a:ba:01:68:7b',
+        'tenancy': 'ocid1.tenancy.oc1..aaaaaaaaemreyqoegf4wbegfzetg63bwvzxa7ahfptbziexslzfmc7gnuwmq',
+        'region': 'uk-london-1',
+        'key_file': 'Ansjer/file/oci_pem/servers@ansjer.com_2023-12-20T07_21_33.069Z.pem'
+    }
+}
+OCI_NAMESPACE_NAME = 'cnmlmfa4fooi'

+ 28 - 0
Ansjer/file/oci_pem/servers@ansjer.com_2023-12-20T07_21_33.069Z.pem

@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCRP0y7XdQ04WV7
+pMGtdCMx5Kdq+NIBzCNSbn4sEzjsAGnmqNuJYLYDtKZaWZp2xwq3+0EoRiHkN+P9
+Jrzb5MplbAzGEDWMevdYdqCxPL0H+KIEd2Zy7e3npYUipQ56astPq/9HytwvfbsL
+5ED8/csRqyPy8/JfuRlQ/i7XhhAG7HNx+hEVaiJLhfi0Y7IYX5+Zx4040fmDybfE
+J+IGB0qYNm/OfPIK8x8lr3RcOla86nFPrkgbxQOW1c0hbZ5NYILBJuzhCDsiU62A
+3o557ur8Tr2xAeS3ZVtW1yzbqwZwMyRtN0Anl3inVrSyDgXcEjWlckCi24OVnu2F
+QAd1d4ujAgMBAAECggEAClQyjDZ5c0M+GMNYJJIYOKGWiERmhssyDdger9q0FxBW
+d5k1d3kBqJTNqaoqklzINdovwYHvQg/5bhS1pHuKKxk6dVFMxY8vDMLu3XvAw5La
+TrABAJZL70e1hoevVmRGzgUgs8XIz7XEue1C89rGeJyvg0T2zPjYRIq24Qu/Ewbd
+JvVmjz4nAe28VjgEwzOnrPFkykT9YojUF1Bl26dJBj+oVk+O6Jf74TMhoT9O/B35
+VGDypqm2qyQQ9ra8myNKmTOCpi1RiK433k6RRCywyf6o+Lehot31eFFO6caIayVG
+j2aWe5N2gaWBPGeioFInKXqkw4tjLafWb3oEDJpAdQKBgQDD9CY8M9K3GQekE0Fb
+dh6a6Aza47WXdoOP/wnO+w3DsaqL42ZCp5/L3D3LtNBJiHXQZhXTuciV5qEtjszt
+XquXYJqyz29A7SNLOXLilvjPq71qWzJF6ViWcHBjX1R/7XqJkK0FuaJWaQFJ5uvS
+kEw55IrKnJ8DQ4m1ZJECn4nWLwKBgQC9wWpkmNNOTLyNJ5Ukf5IE2onL3aaa7iUG
+nLCXCUOXBUUGt9FE9As0PdNjXeTqqH80mWIEgyTBkvFNG5yGwNiVVIMd4Sa9Sm7W
+GND1NFeU3TDJ00rV9FSnVSbrJywi8NEst7qZqy4CS7xjr1+qP6xqIKhHS9n4+K8S
+idlsWB94zQKBgFUv7+teMC3vULYQtOoZGMcJOIV0Vv6IxDs2icIUvHAl7dmwu0Ug
+8ERE9Ax6B87f5y/5IWYRL1WTlOBkY0ySSpCdq8MukNQuA5jxWbOOJI7Lv6XcDaf9
+AMkuCn349JhE2m+xmLaTdDKSpb/GByFcH/dPFtNscWiO1PApzyzPxLF7AoGAMZ8M
+pXXZfBZREFCTjdHWa3KCqk8yLD2ubQY4n6aKiEmWfWVAUlnHPEgWqVt6a2rYqPab
+TTbGO+CjPVjFG+/+Mz7AcuXX7ZQzW8Vtj1G6vXECOyUH4t9b6842uTOrNQ/og1sg
+buL2yx7nCuJnj+vKuI4Fs29Adv0BO0XVF6ILyNkCgYAvP+bOLbPCS3u9Sw23e63t
+9EqeyNfR88KmQzVQGcP5yL3yUytQp5RrDqDdndP3uQa1TY6WQLKPqMh7sMWH9yWB
+6B/CudtduRWbWxLjXVN8Lhb9w7ORLRcY23xDQwdueOER3PHnp3UwaebHJ4+JXcdA
+KtygcG+9e3hWuUzyV/QdLQ==
+-----END PRIVATE KEY-----

+ 6 - 2
Ansjer/urls.py

@@ -4,7 +4,8 @@ from django.urls import re_path
 
 from AdminController import UserManageController, RoleController, MenuController, TestServeController, \
     ServeManagementController, LogManagementController, DeviceManagementController, VersionManagementController, \
-    AiServeController, SurveysManageController, SerialManageController, IcloudManagementController, CampaignController
+    AiServeController, SurveysManageController, SerialManageController, IcloudManagementController, CampaignController, \
+    MessageMangementController
 from AdminController.CloudServiceManage import AgentDeviceController, AgentCustomerController, AgentOrderController
 from Controller import FeedBack, EquipmentOTA, EquipmentInfo, AdminManage, AppInfo, \
     Test, MealManage, DeviceManage, EquipmentStatus, SysManage, DeviceLog, LogAccess, \
@@ -271,7 +272,6 @@ urlpatterns = [
     re_path(r'^weather/(?P<operation>.*)$', WeatherControl.WeatherView.as_view()),
     re_path(r'^alexaApi/', include("Ansjer.server_urls.alexa_url")),
     re_path('appCampaign/(?P<operation>.*)', AppCampaignController.AppCampaignView.as_view()),
-    re_path('campaign/(?P<operation>.*)', CampaignController.CampaignView.as_view()),
 
     # 后台界面接口 -------------------------------------------------------------------------------------------------------
     # 登录,用户信息,权限
@@ -309,6 +309,10 @@ urlpatterns = [
     re_path(r'^agent/customer/manage/(?P<operation>.*)', AgentCustomerController.AgentCustomerView.as_view()),
     re_path(r'^agent/device/manage/(?P<operation>.*)', AgentDeviceController.AgentDeviceView.as_view()),
     re_path(r'^agent/order/manage/(?P<operation>.*)', AgentOrderController.AgentOrderView.as_view()),
+    # APP广告模块
+    re_path('campaign/(?P<operation>.*)', CampaignController.CampaignView.as_view()),
+    # 查询消息推送模块
+    re_path('messageManagement/(?P<operation>.*)', MessageMangementController.MassageView.as_view()),
     # 后台界面接口 -------------------------------------------------------------------------------------------------------
 
     # 定时任务接口

+ 18 - 0
Ansjer/us_config/config_formal.py

@@ -140,3 +140,21 @@ APNS_CONFIG = {
         'pem_path': 'Ansjer/file/apns_pem/commissionf.pem',
     }
 }
+
+OCI_CONFIG = {
+    'us': {
+        'user': 'ocid1.user.oc1..aaaaaaaa63vtn64izdujrghlfby6xrlrrdce4yldtnjm7tmqzoc5i2b36s5q',
+        'fingerprint': '09:ff:f4:fa:64:bd:7b:72:64:67:5e:9a:ba:01:68:7b',
+        'tenancy': 'ocid1.tenancy.oc1..aaaaaaaaemreyqoegf4wbegfzetg63bwvzxa7ahfptbziexslzfmc7gnuwmq',
+        'region': 'us-phoenix-1',
+        'key_file': 'Ansjer/file/oci_pem/servers@ansjer.com_2023-12-20T07_21_33.069Z.pem'
+    },
+    'eur': {
+        'user': 'ocid1.user.oc1..aaaaaaaa63vtn64izdujrghlfby6xrlrrdce4yldtnjm7tmqzoc5i2b36s5q',
+        'fingerprint': '09:ff:f4:fa:64:bd:7b:72:64:67:5e:9a:ba:01:68:7b',
+        'tenancy': 'ocid1.tenancy.oc1..aaaaaaaaemreyqoegf4wbegfzetg63bwvzxa7ahfptbziexslzfmc7gnuwmq',
+        'region': 'uk-london-1',
+        'key_file': 'Ansjer/file/oci_pem/servers@ansjer.com_2023-12-20T07_21_33.069Z.pem'
+    }
+}
+OCI_NAMESPACE_NAME = 'cnmlmfa4fooi'

+ 3 - 3
Controller/CloudStorage.py

@@ -989,7 +989,7 @@ class CloudStorageView(View):
                         CouponModel.objects.filter(id=order_list[0]['coupon_id']).update(use_status=2,
                                                                                          update_time=now_time)
 
-                    order_qs.update(status=1, updTime=now_time, uid_bucket_id=uid_bucket_id,
+                    order_qs.update(status=1, updTime=now_time, uid_bucket_id=uid_bucket_id, payTime=now_time,
                                     promotion_rule_id=promotion_rule_id, create_vod=1)
                     date_time = time.strftime("%Y-%m-%d", time.localtime())
                     # 开通云盘服务
@@ -1165,7 +1165,7 @@ class CloudStorageView(View):
                 logger.info(
                     'uid:{},uid_bucket_id:{},update_status:{},order_id:{}'.format(uid, uid_bucket_id, update_status,
                                                                                   order_id))
-                order_qs.update(status=1, updTime=now_time, uid_bucket_id=uid_bucket_id,
+                order_qs.update(status=1, updTime=now_time, uid_bucket_id=uid_bucket_id, payTime=now_time,
                                 promotion_rule_id=promotion_rule_id, create_vod=1)
                 date_time = time.strftime("%Y-%m-%d", time.localtime())
                 # 开通AI服务
@@ -1321,7 +1321,7 @@ class CloudStorageView(View):
                         CouponModel.objects.filter(id=order_list[0]['coupon_id']).update(use_status=2,
                                                                                          update_time=now_time)
 
-                    order_qs.update(status=1, updTime=now_time, uid_bucket_id=uid_bucket_id,
+                    order_qs.update(status=1, updTime=now_time, uid_bucket_id=uid_bucket_id, payTime=now_time,
                                     promotion_rule_id=promotion_rule_id, create_vod=1)
                     date_time = time.strftime("%Y-%m-%d", time.localtime())
                     # 开通云盘服务

+ 33 - 6
Controller/CloudTransfer.py

@@ -13,7 +13,7 @@ from django.db.models import Q
 from django.views.generic.base import View
 
 from Model.models import Device_User, Device_Info, Order_Model, UID_Bucket, StsCrdModel, VodHlsModel, Unused_Uid_Meal, \
-    VodBucketModel, UnicomDeviceInfo, LogModel, UidPushModel, AiService, UidSetModel
+    VodBucketModel, UnicomDeviceInfo, LogModel, UidPushModel, AiService, UidSetModel, UserFamily, FamilyRoomDevice
 from Object.ResponseObject import ResponseObject
 from Object.TokenObject import TokenObject
 from Service.CommonService import CommonService
@@ -57,13 +57,14 @@ class cloudTestView(View):
         oldUserID = request_dict.get("oldUserID", None)
         username = request_dict.get("username", None)
         uid = request_dict.get('uid', None)
-        now_time = CommonService.timestamp_to_str(int(time.time()))
-        # print('now_time: ', now_time)
+        lang = request_dict.get('lang', None)
+        now_time_stamp = int(time.time())
+        now_time = CommonService.timestamp_to_str(now_time_stamp)
 
         try:
             # 查询该userID下是否存在此设备
             old_deviceInfo_qs = Device_Info.objects.filter(userID_id=oldUserID, UID=uid, isExist=1) \
-                .values('isShare', 'vodPrimaryUserID', 'serial_number', 'userID__username')
+                .values('isShare', 'vodPrimaryUserID', 'serial_number', 'userID__username', 'id')
             if not old_deviceInfo_qs.exists():
                 return response.json(10008)
             old_user_name = old_deviceInfo_qs[0]['userID__username']
@@ -98,11 +99,16 @@ class cloudTestView(View):
             if hasCycle.exists():
                 return response.json(10056)
 
-            # 获取新设备的username
-            newUserName = Device_User.objects.get(userID=newUserID).username
+            # 获取新设备的username、userEmail
+            newUserQs = Device_User.objects.get(userID=newUserID)
+            newUserName = newUserQs.username
+            newUserEmail = newUserQs.userEmail
             vodPrimaryUserID = newUserID
             vodPrimaryMaster = newUserName
 
+            # 获取用户家庭信息
+            device_id = old_deviceInfo_qs[0]['id']
+            user_family_qs = UserFamily.objects.filter(user_id=newUserID).values('id')
             with transaction.atomic():
                 serial_number = old_deviceInfo_qs[0]['serial_number']
                 # 删除旧用户此设备的uid_push数据
@@ -122,6 +128,27 @@ class cloudTestView(View):
                 if u_dev_info_qs.exists():
                     now_time = int(time.time())
                     u_dev_info_qs.update(user_id=newUserID, updated_time=now_time)
+                # 转移设备到家庭
+                if user_family_qs.exists():
+                    family_id = user_family_qs[0]['id']
+
+                else:
+                    family_name = newUserName if newUserName else newUserEmail
+                    family_name = family_name + "的家" if lang == 'cn' else family_name + " home"
+                    user_family = UserFamily.objects.create(user_id=newUserID, name=family_name,
+                                                            updated_time=now_time_stamp,
+                                                            created_time=now_time_stamp)
+                    family_id = user_family.id
+                family_device = FamilyRoomDevice.objects.filter(family_id=family_id, category=1).values('category_sort')
+                category_sort = family_device[0]['category_sort'] if family_device.exists() else 0
+                old_family_device = FamilyRoomDevice.objects.filter(device_id=device_id)
+                if old_family_device.exists():
+                    old_family_device.update(family_id=family_id, category_sort=category_sort,
+                                             updated_time=now_time_stamp, room_id=0, sort=0)
+                else:
+                    FamilyRoomDevice.objects.create(family_id=family_id, category=1, device_id=device_id,
+                                                    updated_time=now_time_stamp, created_time=now_time_stamp)
+
                 # 记录设备转移日志
                 ip = CommonService.get_ip_address(request)
                 content = json.loads(json.dumps(request_dict))

+ 111 - 107
Controller/Cron/CronTaskController.py

@@ -1519,78 +1519,80 @@ class CronComparedDataView(View):
 
     @staticmethod
     def thread_compared_paypal_order(order_list, start_time):
-        LOGGER.info('paypal每日对账开始时间:{}'.format(int(time.time())))
-        now_time = int(time.time())
-        timestamp = int(start_time.timestamp())
-        count = len(order_list)
-        total = 0
-        more_order_list = []
-        for item in order_list:
-            total += float(item['transaction_info']['transaction_amount']['value'])
-            trade_no = item['transaction_info']['transaction_id']
-            if item['transaction_info']['transaction_event_code'] in ['T1106', 'T1107']:  # 付款退款
-                trade_no = item['transaction_info']['paypal_reference_id']
-            transaction_subject = item['transaction_info'].get('transaction_subject', '')
-            agreement_id = item['transaction_info'].get('paypal_reference_id', '')
-            refund_order = False
-            if item['transaction_info']['transaction_event_code'] in ['T1106', 'T1107', 'T1201', 'T0114']:
-                agreement_id = ''
-                if item['transaction_info']['transaction_event_code'] in ['T0114']:
-                    transaction_subject = '争议费'
-                else:
-                    refund_order = True
-                    transaction_subject = '退款费'
-                more_order_list.append(trade_no)
-            pay_time = int(datetime.datetime.strptime(item['transaction_info']['transaction_updated_date'],
-                                                      "%Y-%m-%dT%H:%M:%S%z").timestamp())
-            order_qs = Order_Model.objects.filter(trade_no=trade_no, payType=1)
-            if not order_qs.exists():
-                order_dict = {
-                    'trade_no': trade_no,
-                    'agreement_id': agreement_id,
-                    'pay_time': pay_time,
-                    'username': item['payer_info'].get('email_address', ''),
-                    'price': item['transaction_info']['transaction_amount']['value'],
-                    'pay_type': 1,
-                    'upd_time': now_time,
-                    'status': 0,
-                    'meal_name': transaction_subject
-                }
-                if agreement_id:
-                    order_dict['pay_type'] = 0
-                    order_dict['meal_name'] = 'paypal_cycle'
-                    order_dict['order_id'] = transaction_subject
-                params = {'trade_no': trade_no, 'pay_time': pay_time, 'refund_order': refund_order}
-                response = requests.get('https://www.zositeche.com/testApi/checkOrderExist', params=params)
-                if response.status_code != 200:
-                    # 如果响应失败,记录在数据库
-                    abnormal_qs = AbnormalOrder.objects.filter(trade_no=trade_no)
-                    if not abnormal_qs.exists():
-                        AbnormalOrder.objects.create(**order_dict)
-                    continue
-                result = response.json()
-                if result['result_code'] != 0 or not result['result']['is_exist']:
-                    # 如果响应结果为空,记录在数据库
-                    abnormal_qs = AbnormalOrder.objects.filter(trade_no=trade_no)
-                    if not abnormal_qs.exists():
-                        AbnormalOrder.objects.create(**order_dict)
+        try:
+            now_time = int(time.time())
+            timestamp = int(start_time.timestamp())
+            count = len(order_list)
+            total = 0
+            more_order_list = []
+            for item in order_list:
+                total += float(item['transaction_info']['transaction_amount']['value'])
+                trade_no = item['transaction_info']['transaction_id']
+                if item['transaction_info']['transaction_event_code'] in ['T1106', 'T1107']:  # 付款退款
+                    trade_no = item['transaction_info']['paypal_reference_id']
+                transaction_subject = item['transaction_info'].get('transaction_subject', '')
+                agreement_id = item['transaction_info'].get('paypal_reference_id', '')
+                refund_order = False
+                if item['transaction_info']['transaction_event_code'] in ['T1106', 'T1107', 'T1201', 'T0114']:
+                    agreement_id = ''
+                    if item['transaction_info']['transaction_event_code'] in ['T0114']:
+                        transaction_subject = '争议费'
+                    else:
+                        refund_order = True
+                        transaction_subject = '退款费'
                     more_order_list.append(trade_no)
+                pay_time = int(datetime.datetime.strptime(item['transaction_info']['transaction_updated_date'],
+                                                          "%Y-%m-%dT%H:%M:%S%z").timestamp())
+                order_qs = Order_Model.objects.filter(trade_no=trade_no, payType=1)
+                if not order_qs.exists():
+                    order_dict = {
+                        'trade_no': trade_no,
+                        'agreement_id': agreement_id,
+                        'pay_time': pay_time,
+                        'username': item['payer_info'].get('email_address', ''),
+                        'price': item['transaction_info']['transaction_amount']['value'],
+                        'pay_type': 1,
+                        'upd_time': now_time,
+                        'status': 0,
+                        'meal_name': transaction_subject
+                    }
+                    if agreement_id:
+                        order_dict['pay_type'] = 0
+                        order_dict['meal_name'] = 'paypal_cycle'
+                        order_dict['order_id'] = transaction_subject
+                    params = {'trade_no': trade_no, 'pay_time': pay_time, 'refund_order': refund_order}
+                    response = requests.get('https://www.zositeche.com/testApi/checkOrderExist', params=params)
+                    if response.status_code != 200:
+                        # 如果响应失败,记录在数据库
+                        abnormal_qs = AbnormalOrder.objects.filter(trade_no=trade_no)
+                        if not abnormal_qs.exists():
+                            AbnormalOrder.objects.create(**order_dict)
+                        continue
+                    result = response.json()
+                    if result['result_code'] != 0 or not result['result']['is_exist']:
+                        # 如果响应结果为空,记录在数据库
+                        abnormal_qs = AbnormalOrder.objects.filter(trade_no=trade_no)
+                        if not abnormal_qs.exists():
+                            AbnormalOrder.objects.create(**order_dict)
+                        more_order_list.append(trade_no)
+                else:
+                    if not refund_order:
+                        order_qs.update(payTime=pay_time)
+            total = round(total, 2)
+            daily_reconciliation = DailyReconciliation.objects.filter(time=timestamp)
+            if daily_reconciliation.exists():
+                if daily_reconciliation.first().order_ids:
+                    old_order_list = daily_reconciliation.first().order_ids.split(',')
+                    more_order_list = list(set(old_order_list) | set(more_order_list))
+                order_ids = ','.join(more_order_list)
+                daily_reconciliation.update(paypal_num=count, paypal_total=total, upd_time=now_time, order_ids=order_ids)
             else:
-                if not refund_order:
-                    order_qs.update(payTime=pay_time)
-        total = round(total, 2)
-        daily_reconciliation = DailyReconciliation.objects.filter(time=timestamp)
-        if daily_reconciliation.exists():
-            if daily_reconciliation.first().order_ids:
-                old_order_list = daily_reconciliation.first().order_ids.split(',')
-                more_order_list = list(set(old_order_list) | set(more_order_list))
-            order_ids = ','.join(more_order_list)
-            daily_reconciliation.update(paypal_num=count, paypal_total=total, upd_time=now_time, order_ids=order_ids)
-        else:
-            order_ids = ','.join(more_order_list)
-            DailyReconciliation.objects.create(paypal_num=count, paypal_total=total, time=timestamp,
-                                               order_ids=order_ids, creat_time=now_time, upd_time=now_time)
-        LOGGER.info('paypal每日对账结束时间:{}'.format(int(time.time())))
+                order_ids = ','.join(more_order_list)
+                DailyReconciliation.objects.create(paypal_num=count, paypal_total=total, time=timestamp,
+                                                   order_ids=order_ids, creat_time=now_time, upd_time=now_time)
+        except Exception as e:
+            LOGGER.info('paypal每日对账异常:errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
 
     @staticmethod
     def compared_wechat_order(response):
@@ -1718,7 +1720,6 @@ class CronComparedDataView(View):
 
     @staticmethod
     def thread_compared_ansjer_order(order_list, start_time):
-        LOGGER.info('后台每日对账开始时间:{}'.format(int(time.time())))
         while True:
             response = requests.get('https://www.zositeche.com/cron/compared/AnsjerOrder',
                                     params={'time': int(start_time.timestamp())})
@@ -1727,39 +1728,42 @@ class CronComparedDataView(View):
                 if result['result_code'] == 0:
                     eur_order_list = result['result']
                     break
-        begin_date = start_time - datetime.timedelta(days=15)
-        end_date = start_time + datetime.timedelta(days=15)
-        start_timestamp = int(start_time.timestamp())
-        now_time = int(time.time())
-        more_order_list = []
-        total = 0
-        all_order_list = order_list + eur_order_list
-        count = len(all_order_list)
-        paypal_api = paypalrestsdk.Api(PAYPAL_CRD)
-        for index, order in enumerate(all_order_list):
-            total += float(order['price'])
-            if not order['trade_no']:
-                more_order_list.append(order['orderID'])
-                continue
-            if all_order_list.index(order) != index:
-                more_order_list.append(order['orderID'])
-                continue
-            paypal_url = 'v1/reporting/transactions?start_date={}-{}-{}T00:00:00-0000&end_date={}-{}-{}T00:00:00-0000&transaction_id={}&fields=all&page_size=100&page=1'.format(
-                begin_date.year, begin_date.month, begin_date.day, end_date.year, end_date.month, end_date.day,
-                order['trade_no'])
-            paypal_order_list = paypal_api.get(paypal_url)
-            if not paypal_order_list['transaction_details']:
-                more_order_list.append(order['orderID'])
-        total = round(total, 2)
-        daily_reconciliation = DailyReconciliation.objects.filter(time=start_timestamp)
-        if daily_reconciliation.exists():
-            if daily_reconciliation.first().order_ids:
-                old_order_list = daily_reconciliation.first().order_ids.split(',')
-                more_order_list = list(set(old_order_list) | set(more_order_list))
-            order_ids = ','.join(more_order_list)
-            daily_reconciliation.update(ansjer_total=total, ansjer_num=count, order_ids=order_ids, upd_time=now_time)
-        else:
-            order_ids = ','.join(more_order_list)
-            DailyReconciliation.objects.create(order_ids=order_ids, ansjer_total=total, ansjer_num=count,
-                                               time=start_timestamp, creat_time=now_time, upd_time=now_time)
-        LOGGER.info('后台每日对账结束时间:{}'.format(int(time.time())))
+        try:
+            begin_date = start_time - datetime.timedelta(days=15)
+            end_date = start_time + datetime.timedelta(days=15)
+            start_timestamp = int(start_time.timestamp())
+            now_time = int(time.time())
+            more_order_list = []
+            total = 0
+            all_order_list = order_list + eur_order_list
+            count = len(all_order_list)
+            paypal_api = paypalrestsdk.Api(PAYPAL_CRD)
+            for index, order in enumerate(all_order_list):
+                total += float(order['price'])
+                if not order['trade_no']:
+                    more_order_list.append(order['orderID'])
+                    continue
+                if all_order_list.index(order) != index:
+                    more_order_list.append(order['orderID'])
+                    continue
+                paypal_url = 'v1/reporting/transactions?start_date={}-{}-{}T00:00:00-0000&end_date={}-{}-{}T00:00:00-0000&transaction_id={}&fields=all&page_size=100&page=1'.format(
+                    begin_date.year, begin_date.month, begin_date.day, end_date.year, end_date.month, end_date.day,
+                    order['trade_no'])
+                paypal_order_list = paypal_api.get(paypal_url)
+                if not paypal_order_list['transaction_details']:
+                    more_order_list.append(order['orderID'])
+            total = round(total, 2)
+            daily_reconciliation = DailyReconciliation.objects.filter(time=start_timestamp)
+            if daily_reconciliation.exists():
+                if daily_reconciliation.first().order_ids:
+                    old_order_list = daily_reconciliation.first().order_ids.split(',')
+                    more_order_list = list(set(old_order_list) | set(more_order_list))
+                order_ids = ','.join(more_order_list)
+                daily_reconciliation.update(ansjer_total=total, ansjer_num=count, order_ids=order_ids, upd_time=now_time)
+            else:
+                order_ids = ','.join(more_order_list)
+                DailyReconciliation.objects.create(order_ids=order_ids, ansjer_total=total, ansjer_num=count,
+                                                   time=start_timestamp, creat_time=now_time, upd_time=now_time)
+        except Exception as e:
+            LOGGER.info('后台每日对账异常:errLine:{}, errMsg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+

+ 1 - 1
Controller/PaymentCycle.py

@@ -326,7 +326,7 @@ class PaypalCycleNotify(View):
                 logger.info(
                     'uid:{},uid_bucket_id:{},update_status:{},order_id:{}'.format(UID, uid_bucket_id, update_status,
                                                                                   orderID))
-                order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id, create_vod=1,
+                order_qs.update(status=1, updTime=nowTime, uid_bucket_id=uid_bucket_id, create_vod=1, payTime=nowTime,
                                 promotion_rule_id=promotion_rule_id, agreement_id=agreement_id)
                 # 如果存在序列号,消息提示用序列号
                 device_name = CommonService.query_serial_with_uid(uid=UID)

+ 35 - 0
Controller/TestApi.py

@@ -58,6 +58,7 @@ from Object.AWS.AmazonS3Util import AmazonS3Util
 from Object.CeleryBeatObject import CeleryBeatObj
 from Object.ContentSecurityObject import ContentSecurity
 from Object.IPWeatherObject import IPQuery, OpenWeatherMap, GeoIP2
+from Object.OCIObjectStorage import OCIObjectStorage
 from Object.m3u8generate import PlaylistGenerator
 from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
@@ -183,9 +184,43 @@ class testView(View):
             return self.celery(request_dict, response)
         elif operation == 'tz':
             return self.tz(request_dict, response)
+        elif operation == 'createPreauthRequest':
+            return self.create_preauth_request(request_dict, response)
+        elif operation == 'getOciUrl':
+            return self.get_oci_url(request_dict, request, response)
         else:
             return response.json(414)
 
+    @classmethod
+    def create_preauth_request(cls, request_dict, response):
+
+        oci = OCIObjectStorage(request_dict.get('region'))
+        bucket_name = request_dict.get('bucketName')
+        name = 'oci-test'
+        object_name = request_dict.get('objectName')
+        time_expires = datetime.datetime.utcnow() + datetime.timedelta(minutes=10)
+        result = oci.create_ereauthenticated_request(bucket_name, name, object_name, time_expires)
+        return response.json(0, {'fullPath': result.full_path + result.object_name})
+
+    @classmethod
+    def get_oci_url(cls, request_dict, request, response):
+        """
+        获取Oci存储地址
+        """
+        try:
+            object_name = request_dict.get('objectName', None)
+            if not object_name:
+                return response.json(404)
+            oci = OCIObjectStorage(request_dict.get('region'))
+            bucket_name = request_dict.get('bucketName')
+            name = 'oci-test'
+            time_expires = datetime.datetime.utcnow() + datetime.timedelta(minutes=10)
+            result = oci.get_preauthenticated_request_url(bucket_name, name, object_name, time_expires)
+            return response.json(0, {'data': result.full_path})
+        except Exception as e:
+            print(repr(e))
+            return response.json(500)
+
     @staticmethod
     def generate_token(request_dict):
         tko = TokenObject()

+ 1 - 1
Controller/UserController.py

@@ -954,7 +954,7 @@ class v2authCodeView(TemplateView):
         ses = SesClassObject()
         body = send_data['body'].replace("{username}", user_email).replace("{captcha}", str(identifyingCode))
         title = send_data['title']
-        if CONFIG_INFO == CONFIG_EUR:
+        if CONFIG_INFO == CONFIG_EUR or CONFIG_INFO == CONFIG_US:
             send_res = S3Email().send_email(send_data['title'], send_data['body'].replace("{username}", user_email)
                                             .replace("{captcha}", str(identifyingCode)), user_email)
             return send_res

+ 114 - 0
Object/OCIObjectStorage.py

@@ -0,0 +1,114 @@
+# -*- encoding: utf-8 -*-
+"""
+@File    : OCIObjectStorage.py
+@Time    : 2024/4/10 15:06
+@Author  : stephen
+@Email   : zhangdongming@asj6.wecom.work
+@Software: PyCharm
+"""
+
+import oci
+
+from Ansjer.config import OCI_CONFIG, OCI_NAMESPACE_NAME
+
+
+class OCIObjectStorage:
+
+    # Create a default oci_config using DEFAULT profile in default location
+    # Refer to
+    # https://docs.cloud.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm#SDK_and_CLI_Configuration_File
+    # for more info
+
+    def __init__(self, region):
+        # Initialize service client with default oci_config file
+        self.object_storage_client = oci.object_storage.ObjectStorageClient(OCI_CONFIG[region])
+
+    def create_ereauthenticated_request(self, bucket_name, name, object_name, time_expires):
+        """
+        创建特定于桶的预认证请求。
+        api:https://docs.oracle.com/en-us/iaas/api/#/en/objectstorage/20160918/PreauthenticatedRequest/CreatePreauthenticatedRequest
+        @param bucket_name: 存储桶名称
+        @param name: 请求名称 是创建的预授权链接的名称,是方便管理用的,不会影响功能。比如对每个桶分别创建链接,如果要删除或者查看,可以根据name看出来是对哪个桶的链接。
+        @param object_name: 对象名
+        @param time_expires: 失效时间 需要datetime类型格式 例如:datetime.utcnow() + timedelta(minutes=30)
+        @return: 预认证请求URL
+        """
+        try:
+            object_storage_client = self.object_storage_client
+
+            # Send the request to service, some parameters are not required, see API
+            # doc for more info
+            response = object_storage_client.create_preauthenticated_request(
+                namespace_name=OCI_NAMESPACE_NAME,
+                bucket_name=bucket_name,
+                create_preauthenticated_request_details=oci.object_storage.models.CreatePreauthenticatedRequestDetails(
+                    name=name,
+                    access_type="AnyObjectWrite",
+                    time_expires=time_expires,
+                    bucket_listing_action="Deny",
+                    object_name=object_name))
+
+            assert response.status == 200
+            return response.data
+
+        except Exception as e:
+            print(repr(e))
+            return None
+
+    def get_preauthenticated_request_url(self, bucket_name, name, object_name, time_expires):
+        """
+        获取指定对象预认证请求URL。
+        @param bucket_name: 存储桶名称
+        @param name: 请求名称 是创建的预授权链接的名称,是方便管理用的,不会影响功能。比如对每个桶分别创建链接,如果要删除或者查看,可以根据name看出来是对哪个桶的链接。
+        @param object_name: 对象名
+        @param time_expires: 失效时间 需要datetime类型格式 例如:datetime.utcnow() + timedelta(minutes=30)
+        @return: 预认证请求URL
+        """
+        try:
+            object_storage_client = self.object_storage_client
+            # 创建预认证请求
+            response = object_storage_client.create_preauthenticated_request(
+                namespace_name=OCI_NAMESPACE_NAME,
+                bucket_name=bucket_name,
+                create_preauthenticated_request_details=oci.object_storage.models.CreatePreauthenticatedRequestDetails(
+                    name=name,
+                    object_name=object_name,
+                    access_type="ObjectRead",
+                    time_expires=time_expires
+                )
+            )
+
+            assert response.status == 200
+            return response.data
+
+        except Exception as e:
+            print(repr(e))
+            return None
+
+    def put_object(self, bucket_name, object_name, obj, content_type=None):
+        """
+        上传对象
+        @param bucket_name: 存储桶名称
+        @param object_name: 对象名
+        @param obj: 数据内容
+        @param content_type: 文件类型
+        @return: 可访问对象URL
+        """
+        try:
+            object_storage_client = self.object_storage_client
+
+            # 发送上传请求
+            put_object_response = object_storage_client.put_object(
+                namespace_name=OCI_NAMESPACE_NAME,
+                bucket_name=bucket_name,
+                object_name=object_name,
+                put_object_body=obj,
+                content_type=content_type
+            )
+
+            # 打印响应头信息
+            assert put_object_response.status == 200
+        except Exception as e:
+            print(repr(e))
+            return None
+

+ 2 - 1
requirements.txt

@@ -84,4 +84,5 @@ alibabacloud_green20220302==1.0.8
 django-apscheduler==0.6.2
 geoip2==4.7.0
 celery==5.3.6
-django-celery-beat==2.6.0
+django-celery-beat==2.6.0
+oci~=2.125.2