瀏覽代碼

拼装请求json 本地测试完成

liyuyi@c-top.com.cn 4 年之前
父節點
當前提交
add9a1fe91

+ 1 - 1
.idea/ai_ads.iml

@@ -4,7 +4,7 @@
     <content url="file://$MODULE_DIR$">
       <excludeFolder url="file://$MODULE_DIR$/venv" />
     </content>
-    <orderEntry type="jdk" jdkName="Python 3.8" jdkType="Python SDK" />
+    <orderEntry type="jdk" jdkName="Python 3.7 (ai_ads)" jdkType="Python SDK" />
     <orderEntry type="sourceFolder" forTests="false" />
   </component>
   <component name="PyDocumentationSettings">

+ 1 - 1
.idea/misc.xml

@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
-  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8" project-jdk-type="Python SDK" />
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (ai_ads)" project-jdk-type="Python SDK" />
 </project>

+ 335 - 0
ai_callback_add_creative_handler.py

@@ -0,0 +1,335 @@
+from typing import Optional, Awaitable
+import pandas as pd
+import numpy as np
+import datetime
+import pymysql
+from sqlalchemy import create_engine
+import simplejson
+import requests
+import tornado.web
+import pandas as pd
+import json
+import numpy as np
+import datetime
+from sqlalchemy import create_engine
+from db_config import *
+import traceback
+import uuid
+
+
+class AiCallBackAddCreative(tornado.web.RequestHandler):
+    def initialize(self, logger):
+        self.logger = logger
+
+    def post(self):
+        data = self.request.body
+        data = str(data, 'utf8')
+        data = json.loads(data, encoding='utf8')
+        self.logger.info("***************************************  NEW REQUEST ***************************************")
+        self.logger.info("raw data from request is %s" % data)
+
+        create_group_and_creative_response_data = None
+        # 1、新增广告组操作
+        try:
+            if data["operation_type"] == 1:
+                inst = ParseAddCampaignOrAddGroupRequest(data)
+                inst.get_advertiser_strategy_info()
+                inst.write_intelligence_strategy_table()
+                if inst.campaign_id == "" or inst.campaign_id is None:
+                    if inst.add_campaign() == -1:
+                        self.write(json.dumps({"message": "广告计划创建失败"}))
+                        self.flush()
+                        return
+
+                inst.get_group_dict()
+                create_group_and_creative_res = inst.res_data
+                print("create_group_and_creative_res: ", create_group_and_creative_res)
+                request = requests.post(create_group_and_creative_url, create_group_and_creative_res)
+                create_group_and_creative_response_data = simplejson.loads(request.text)
+        except Exception:
+            self.logger.error(traceback.format_exc())
+
+        # 返回接口结果
+        self.write(json.dumps({'account_id': inst.account_id,'ai_strategy_id': inst.ai_strategy_uuid,
+                               'message': create_group_and_creative_response_data}))
+        self.flush()
+
+
+# 该类解析的是 手动请求的新增广告计划或者新增广告组的数据
+class ParseAddCampaignOrAddGroupRequest(object):
+    def __init__(self, request_data):
+        self.ai_strategy_uuid = str(uuid.uuid4())
+        self.request_data = request_data
+        self.video = self.request_data['video']
+        self.account_id = self.request_data['account_id']
+        self.campaign_info = self.request_data['campaign_info']
+        self.campaign_id = self.request_data['campaign_info'].get('campaign_id', None)
+        self.group_info = self.request_data['group_info']
+        self.creative_info = self.request_data['creative_info']
+        self.operation_type = self.request_data['operation_type']
+
+        self.advertiser_strategy_id = None
+        self.advertiser_strategy = {}
+        self.res_data = {}
+
+    def get_advertiser_strategy_info(self):
+        """
+        获取指定账户下客户的策略信息
+        为后续的写入库表,校验一致性做准备
+        :return:
+        """
+        sql = """
+        select * 
+        from ctop_ai_kuaishou_advertiser_strategy 
+        where account_id = %d 
+        and status = 1
+        limit 1
+        """ % self.account_id
+        advertiser_strategy_df = pd.read_sql(sql, engine)
+
+        self.advertiser_strategy_id = advertiser_strategy_df['id'].values[0]
+        self.advertiser_strategy = advertiser_strategy_df.T.to_dict()[0]
+
+    def write_intelligence_strategy_table(self):
+        """
+        请求信息写入 ctop_ai_kuaishou_intelligence_strategy 表中
+        :return:
+        """
+        intelligence_strategy_dict = \
+            {
+                'ai_strategy_uuid': self.ai_strategy_uuid,
+                'advertiser_strategy_id': self.advertiser_strategy_id,
+                'account_id': self.account_id,
+                'ai_strategy_request_content': str(self.request_data),
+                'ai_strategy_remark': self.request_data['ai_strategy_remark'],
+                'create_time': datetime.datetime.now()
+            }
+
+        df = pd.DataFrame.from_dict(intelligence_strategy_dict, orient='index').T
+        df.to_sql(name="ctop_ai_kuaishou_intelligence_strategy", con=engine, if_exists='append', index=False)
+
+    # 如果手动请求的数据结构中,"campaign" 中的 campaign_id 为空则调用该新增计划方法
+    def add_campaign(self):
+        """
+        新增广告计划
+        :return:
+        """
+        # 1、校验请求信息中 有没有 与客户策略信息 中存在冲突的地方 -- 计划层级只判断 campaign_type
+        if self.campaign_info['campaign_type'] != self.advertiser_strategy['campaign_type']:
+            self.logger.info("客户策略的campaign_type: %d 和 AI策略的campaign_type:%d 不一致!" %
+                             (self.advertiser_strategy['campaign_type'],
+                              self.campaign_info['campaign_type']))
+            return -1
+
+        # TODO 待联调测试
+        # create_campaign_req_data = {
+        #                             'account_id': self.account_id,
+        #                             'campaign_name': self.campaign_info['campaign_name'],
+        #                             'type': self.campaign_info['campaign_type']
+        #                             }
+        # request = requests.post(create_campaign_url, create_campaign_req_data)
+        # res_data = simplejson.loads(request.text)
+
+        res_data = {
+            "code": 0,
+            "data": {
+                "account_id": 23212,
+                "campaign_id": 30956133,
+                "campaign_create_time": "2021-01-13 13:50:16"
+            },
+            "message": "SUCCESS"}
+        if res_data['code'] == 0:
+            self.campaign_id = res_data['data']['campaign_id']
+            campaign_info_to_db = {
+                                   'campaign_uuid': str(uuid.uuid4()),
+                                   'account_id': self.account_id,
+                                   'ai_strategy_uuid': self.ai_strategy_uuid,
+                                   'campaign_name': self.campaign_info['campaign_name'],
+                                   'campaign_id': self.campaign_id,
+                                   'campaign_type': self.campaign_info['campaign_type'],
+                                   'operation_type': self.operation_type,
+                                   'campaign_create_time': res_data['data']['campaign_create_time'],
+                                   'create_time': datetime.datetime.now()
+                                   }
+            df = pd.DataFrame.from_dict(campaign_info_to_db, orient='index').T
+            df.to_sql(name="ctop_ai_kuaishou_campaign_level_operation_record", con=engine, if_exists='append', index=False)
+        else:
+            self.logger.info("广告计划创建失败:%s" % res_data['message'])
+            return -1
+
+    def get_group_dict(self):
+        """
+        拼接组和创意层级参数
+        写入数据库
+        返回 table_id
+        :return:
+        """
+        # 1、TODO 校验请求信息中 有没有 与客户策略信息 中存在冲突的地方 -- 暂时不实现
+        # 客户策略 和 请求信息 都有值 才会进行校验比对操作 -- 不得高于,不得不等于,不得超过集合
+        # 因此分为3类 字段
+        # is_equal_cols = ['template_id','bid_type']
+        # is_less_than_cols = []
+        # is_contain_cols = []
+        #
+        # for col in is_equal_cols:
+        #     if (self.advertiser_strategy[col] is not None) and \
+        #             (self.group_info.get(col, None) is not None) and \
+        #             (self.group_info.get(col) != self.advertiser_strategy[col]):
+        #         return -1
+        #
+        # for col in is_less_than_cols:
+        #     if (self.advertiser_strategy[col] is not None) and \
+        #             (self.group_info.get(col, None) is not None) and \
+        #             (self.group_info.get(col) > self.advertiser_strategy[col]):
+        #         return -1
+        #
+        # for col in is_contain_cols:
+        #     if (self.advertiser_strategy[col] is not None) and \
+        #             (self.group_info.get(col, None) is not None) and \
+        #             (self.group_info.get(col) > self.advertiser_strategy[col]):
+        #         return -1
+
+        basic_group_info = {'template_id': self.advertiser_strategy['template_id'],
+                                 'bid_type': self.advertiser_strategy['bid_type'],
+                                 'use_app_market': self.advertiser_strategy['use_app_market'],
+                                 'app_store': self.advertiser_strategy['app_store'],
+                                 'bid': self.advertiser_strategy['bid'],
+                                 'cpa_bid': self.advertiser_strategy['cpa_bid'],
+                                 'smart_bid': self.advertiser_strategy['smart_bid'],
+                                 'ocpx_action_type': self.advertiser_strategy['ocpx_action_type'],
+                                 'deep_conversion_type': self.advertiser_strategy['deep_conversion_type'],
+                                 'roi_ratio': self.advertiser_strategy['roi_ratio'],
+                                 'scene_id': self.advertiser_strategy['scene_id'],
+                                 'unit_type': self.advertiser_strategy['unit_type'],
+                                 'begin_time': self.advertiser_strategy['begin_time'],
+                                 'end_time': self.advertiser_strategy['end_time'],
+                                 'schedule_time': self.advertiser_strategy['schedule_time'],
+                                 'convert_id': self.advertiser_strategy['convert_id'],
+                                 'url_type': self.advertiser_strategy['url_type'],
+                                 'web_uri_type': self.advertiser_strategy['web_uri_type'],
+                                 'url': self.advertiser_strategy['url'],
+                                 'schema_uri': self.advertiser_strategy['schema_uri'],
+                                 'app_id': self.advertiser_strategy['app_id'],
+                                 'show_mode': self.advertiser_strategy['show_mode'],
+                                 'speed': self.advertiser_strategy['speed'],
+                                 'site_type': self.advertiser_strategy['site_type'],
+                                 'gift_data': self.advertiser_strategy['gift_data'],
+                                 'video_landing_page': self.advertiser_strategy['video_landing_page'],
+                                 'auto_target': self.advertiser_strategy['auto_target'],
+                                 'auto_create_photo': self.advertiser_strategy['auto_create_photo'],
+                                 'region': self.advertiser_strategy['region'],
+                                 'district_ids': self.advertiser_strategy['district_ids'],
+                                 'user_type': self.advertiser_strategy['user_type'],
+                                 'age_min': self.advertiser_strategy['age_min'],
+                                 'age_max': self.advertiser_strategy['age_max'],
+                                 'ages_range': self.advertiser_strategy['ages_range'],
+                                 'gender': self.advertiser_strategy['gender'],
+                                 'platform_os': self.advertiser_strategy['platform_os'],
+                                 'android_osv': self.advertiser_strategy['android_osv'],
+                                 'ios_osv': self.advertiser_strategy['ios_osv'],
+                                 'network': self.advertiser_strategy['network'],
+                                 'device_brand': self.advertiser_strategy['device_brand'],
+                                 'device_price': self.advertiser_strategy['device_price'],
+                                 'business_interest_type': self.advertiser_strategy['business_interest_type'],
+                                 'business_interest': self.advertiser_strategy['business_interest'],
+                                 'fans_star': self.advertiser_strategy['fans_star'],
+                                 'interest_video': self.advertiser_strategy['interest_video'],
+                                 'app_interest': self.advertiser_strategy['app_interest'],
+                                 'app_ids': self.advertiser_strategy['app_ids'],
+                                 'filter_converted_level': self.advertiser_strategy['filter_converted_level'],
+                                 'population': self.advertiser_strategy['population'],
+                                 'exclude_population': self.advertiser_strategy['exclude_population'],
+                                 'paid_audience': self.advertiser_strategy['paid_audience'],
+                                 'is_open': self.advertiser_strategy['is_open'],
+                                 'no_age_break': self.advertiser_strategy['no_age_break'],
+                                 'no_gender_break': self.advertiser_strategy['no_gender_break'],
+                                 'no_area_break': self.advertiser_strategy['no_area_break'],
+                                 'behavior_interest': self.advertiser_strategy['behavior_interest']}
+
+        # 3、从请求的信息中更新计划层级信息
+        if len(self.group_info) > 0:
+            for key, value in self.group_info.items():
+                basic_group_info.update({key: value})
+
+        self.res_data['group_list'] = []
+        group_cnt = 1
+        for video in self.video:
+            single_group_info = {'group_uuid': str(uuid.uuid4())}
+            single_group_info.update(basic_group_info)
+            single_group_info['unit_name'] = self.group_info['unit_name'] + '-' + str(group_cnt)
+
+            # 组信息写入数据表中
+            single_group_info_to_db = single_group_info.copy()
+            single_group_info_to_db['ai_strategy_uuid'] = self.ai_strategy_uuid
+            single_group_info_to_db['account_id'] = self.account_id
+            single_group_info_to_db['campaign_id'] = self.campaign_id
+            single_group_info_to_db['create_time'] = datetime.datetime.now()
+            single_group_info_to_db['operation_type'] = self.operation_type
+            df = pd.DataFrame.from_dict(single_group_info_to_db, orient='index').T
+            engine = create_engine(db_con_str, connect_args={'charset': 'utf8'})
+            df.to_sql(name="ctop_ai_kuaishou_unit_level_operation_record",
+                      con=engine,
+                      if_exists='append',
+                      index=False)
+
+            single_group_info['creative_list'] = []
+            group_cnt += 1
+
+            creative_cnt = 1
+            for image in video['imageList']:
+                single_creative_info = {
+                    'creative_uuid': str(uuid.uuid4()),
+                    'is_sticky': 0,
+                    'creative_name': self.creative_info['creative_name'] + '_' + str(creative_cnt),
+                    'photo_id': video['photo_id'],
+                    'image_md5': image,  # TODO 需要和蒙蒙确认字段名称
+                    'image_tokens': self.creative_info.get('image_tokens'),
+                    'action_bar_text': self.creative_info['action_bar_text'],
+                    'description': self.creative_info['description'],
+                    'short_slogan': self.creative_info.get('short_slogan'),
+                    'sticker_title': self.creative_info.get('sticker_title'),
+                    'overlay_type': self.creative_info.get('overlay_type'),
+                    'expose_tag': self.creative_info.get('expose_tag'),
+                    'new_expose_tag': self.creative_info.get('new_expose_tag'),
+                    'site_id': self.creative_info.get('site_id'),
+                    'click_track_url': self.advertiser_strategy.get('click_track_url'),
+                    'impression_url': self.advertiser_strategy.get('impression_url'),
+                    'ad_photo_played_t3s_url': self.advertiser_strategy.get('ad_photo_played_t3s_url'),
+                    'actionbar_click_url': self.advertiser_strategy.get('actionbar_click_url'),
+                    'creative_category': self.creative_info.get('creative_category'),
+                    'creative_tag': self.creative_info.get('creative_tag')}
+
+                single_group_info['creative_list'].append(single_creative_info)
+
+                # 创意层级写入数据表中
+                single_creative_info_to_db = single_creative_info.copy()
+                single_creative_info_to_db['ai_strategy_uuid'] = self.ai_strategy_uuid
+                single_creative_info_to_db['account_id'] = self.account_id
+                single_creative_info_to_db['campaign_id'] = self.campaign_id
+                single_creative_info_to_db['create_time'] = datetime.datetime.now()
+                single_creative_info_to_db['operation_type'] = self.operation_type
+                df = pd.DataFrame.from_dict(single_creative_info_to_db, orient='index').T
+                engine = create_engine(db_con_str, connect_args={'charset': 'utf8'})
+                df.to_sql(name="ctop_ai_kuaishou_creative_level_operation_record",
+                          con=engine,
+                          if_exists='append',
+                          index=False)
+
+                creative_cnt += 1
+            # 组和创意信息添加到最终返回数据 group_list 中
+            self.res_data['group_list'].append(single_group_info)
+
+        self.res_data['account_id'] = self.account_id
+        self.res_data['campaign_id'] = self.campaign_id
+
+
+# TODO 修改操作
+class ParseModifyRequest(object):
+    def __init__(self):
+        pass
+
+
+# TODO 关停操作
+class ParseShutDownRequest(object):
+    def __init__(self):
+        pass

+ 45 - 0
ai_callback_add_group_handler.py

@@ -0,0 +1,45 @@
+from typing import Optional, Awaitable
+import pandas as pd
+import numpy as np
+import datetime
+import pymysql
+from sqlalchemy import create_engine
+import simplejson
+import requests
+import tornado.web
+import pandas as pd
+import json
+import numpy as np
+import datetime
+from sqlalchemy import create_engine
+from db_config import *
+import traceback
+import uuid
+
+
+class AiCallBackAddGroup(tornado.web.RequestHandler):
+    def initialize(self, logger):
+        self.logger = logger
+
+    def post(self):
+        data = self.request.body
+        data = str(data, 'utf8')
+        data = json.loads(data, encoding='utf8')
+        self.logger.info("***************************************  NEW REQUEST ***************************************")
+        self.logger.info("raw data from request is %s" % data)
+
+        # 1、新增广告组操作
+        try:
+            pass
+        except Exception:
+            self.logger.error(traceback.format_exc())
+
+        # 返回接口结果
+        self.write(json.dumps({}))
+        self.flush()
+
+
+# 该类解析的是 手动请求的新增广告计划或者新增广告组的数据
+class UpdateGroupLevelRecordTable(object):
+    def __init__(self, request_data):
+        pass

+ 56 - 57
ai_strategy_request_handler.py

@@ -24,39 +24,41 @@ class AiStrategyRequestParse(tornado.web.RequestHandler):
     def post(self):
         data = self.request.body
         data = str(data, 'utf8')
+        data = json.loads(data, encoding='utf8')
         self.logger.info("***************************************  NEW REQUEST ***************************************")
         self.logger.info("raw data from request is %s" % data)
 
+        create_group_and_creative_response_data = None
         # 1、新增广告组操作
-        if data["operation_type"] == "add":
-            inst = ParseAddCampaignOrAddGroupRequest(data)
-            inst.get_advertiser_strategy_info()
-            inst.write_intelligence_strategy_table()
-            if inst.campaign_id == "" or inst.campaign_id is None:
-                if inst.add_campaign() == -1:
-                    self.write(json.dumps({"message": "广告计划创建失败"}))
-                    self.flush()
-                    return
-
-            inst.get_group_dict()
-            res = inst.res_data
-            url = ""
-            request = requests.post(url, res)
-            # TODO 先测试,如果有问题,让他们返回一个true,或者设置timeout=1,
-            res_data = simplejson.loads(request.text)
-
-
-
+        try:
+            if data["operation_type"] == 1:
+                inst = ParseAddCampaignOrAddGroupRequest(data)
+                inst.get_advertiser_strategy_info()
+                inst.write_intelligence_strategy_table()
+                if inst.campaign_id == "" or inst.campaign_id is None:
+                    if inst.add_campaign() == -1:
+                        self.write(json.dumps({"message": "广告计划创建失败"}))
+                        self.flush()
+                        return
+
+                inst.get_group_dict()
+                create_group_and_creative_res = inst.res_data
+                print("create_group_and_creative_res: ", create_group_and_creative_res)
+                request = requests.post(create_group_and_creative_url, create_group_and_creative_res)
+                create_group_and_creative_response_data = simplejson.loads(request.text)
+        except Exception:
+            self.logger.error(traceback.format_exc())
 
         # 返回接口结果
-        result_str = json.dumps(res)
-        self.write(result_str)
+        self.write(json.dumps({'account_id': inst.account_id,'ai_strategy_id': inst.ai_strategy_uuid,
+                               'message': create_group_and_creative_response_data}))
         self.flush()
 
 
 # 该类解析的是 手动请求的新增广告计划或者新增广告组的数据
 class ParseAddCampaignOrAddGroupRequest(object):
     def __init__(self, request_data):
+        self.ai_strategy_uuid = str(uuid.uuid4())
         self.request_data = request_data
         self.video = self.request_data['video']
         self.account_id = self.request_data['account_id']
@@ -67,7 +69,6 @@ class ParseAddCampaignOrAddGroupRequest(object):
         self.operation_type = self.request_data['operation_type']
 
         self.advertiser_strategy_id = None
-        self.ai_strategy_id = None
         self.advertiser_strategy = {}
         self.res_data = {}
 
@@ -82,30 +83,29 @@ class ParseAddCampaignOrAddGroupRequest(object):
         from ctop_ai_kuaishou_advertiser_strategy 
         where account_id = %d 
         and status = 1
+        limit 1
         """ % self.account_id
-        engine = create_engine(db_con_str, connect_args={'charset': 'utf8'})
         advertiser_strategy_df = pd.read_sql(sql, engine)
 
+        self.advertiser_strategy_id = advertiser_strategy_df['id'].values[0]
         self.advertiser_strategy = advertiser_strategy_df.T.to_dict()[0]
-        self.advertiser_strategy_id = self.advertiser_strategy['id']
 
     def write_intelligence_strategy_table(self):
         """
         请求信息写入 ctop_ai_kuaishou_intelligence_strategy 表中
         :return:
         """
-        self.ai_strategy_id = uuid.uuid4()
         intelligence_strategy_dict = \
             {
-                'ai_strategy_id': self.ai_strategy_id,
+                'ai_strategy_uuid': self.ai_strategy_uuid,
                 'advertiser_strategy_id': self.advertiser_strategy_id,
                 'account_id': self.account_id,
-                'ai_strategy_request_content': self.request_data,
+                'ai_strategy_request_content': str(self.request_data),
+                'ai_strategy_remark': self.request_data['ai_strategy_remark'],
                 'create_time': datetime.datetime.now()
             }
 
         df = pd.DataFrame.from_dict(intelligence_strategy_dict, orient='index').T
-        engine = create_engine(db_con_str, connect_args={'charset': 'utf8'})
         df.to_sql(name="ctop_ai_kuaishou_intelligence_strategy", con=engine, if_exists='append', index=False)
 
     # 如果手动请求的数据结构中,"campaign" 中的 campaign_id 为空则调用该新增计划方法
@@ -116,29 +116,34 @@ class ParseAddCampaignOrAddGroupRequest(object):
         """
         # 1、校验请求信息中 有没有 与客户策略信息 中存在冲突的地方 -- 计划层级只判断 campaign_type
         if self.campaign_info['campaign_type'] != self.advertiser_strategy['campaign_type']:
-            # TODO 写入日志信息
+            self.logger.info("客户策略的campaign_type: %d 和 AI策略的campaign_type:%d 不一致!" %
+                             (self.advertiser_strategy['campaign_type'],
+                              self.campaign_info['campaign_type']))
             return -1
 
-        # 3、从请求的信息中更新计划层级信息
-        # if len(self.request_data['campaign']) > 0:
-        #     for key, value in self.request_data['campaign'].items():
-        #         self.campaign_dict.update({key: value})
-
-        create_campaign_req_data = {
-                                    'account_id': self.account_id,
-                                    'campaign_name': self.campaign_info['campaign_name'],
-                                    'type': self.campaign_info['campaign_type']
-                                    }
-        url = "http://192.168.1.8:8080/jeecg-boot//jeecg-boot/kuaishou/create/campaignCreate"
-        request = requests.post(url, create_campaign_req_data)
-        res_data = simplejson.loads(request.text)
-
+        # TODO 待联调测试
+        # create_campaign_req_data = {
+        #                             'account_id': self.account_id,
+        #                             'campaign_name': self.campaign_info['campaign_name'],
+        #                             'type': self.campaign_info['campaign_type']
+        #                             }
+        # request = requests.post(create_campaign_url, create_campaign_req_data)
+        # res_data = simplejson.loads(request.text)
+
+        res_data = {
+            "code": 0,
+            "data": {
+                "account_id": 23212,
+                "campaign_id": 30956133,
+                "campaign_create_time": "2021-01-13 13:50:16"
+            },
+            "message": "SUCCESS"}
         if res_data['code'] == 0:
             self.campaign_id = res_data['data']['campaign_id']
             campaign_info_to_db = {
-                                   'uid': uuid.uuid4(),
+                                   'campaign_uuid': str(uuid.uuid4()),
                                    'account_id': self.account_id,
-                                   'ai_strategy_id': self.ai_strategy_id,
+                                   'ai_strategy_uuid': self.ai_strategy_uuid,
                                    'campaign_name': self.campaign_info['campaign_name'],
                                    'campaign_id': self.campaign_id,
                                    'campaign_type': self.campaign_info['campaign_type'],
@@ -147,10 +152,9 @@ class ParseAddCampaignOrAddGroupRequest(object):
                                    'create_time': datetime.datetime.now()
                                    }
             df = pd.DataFrame.from_dict(campaign_info_to_db, orient='index').T
-            engine = create_engine(db_con_str, connect_args={'charset': 'utf8'})
             df.to_sql(name="ctop_ai_kuaishou_campaign_level_operation_record", con=engine, if_exists='append', index=False)
         else:
-            # TODO 写入计划创建失败的原因
+            self.logger.info("广告计划创建失败:%s" % res_data['message'])
             return -1
 
     def get_group_dict(self):
@@ -160,9 +164,6 @@ class ParseAddCampaignOrAddGroupRequest(object):
         返回 table_id
         :return:
         """
-        # 一个视频一个广告组
-        # 先写入数据库,然后读取数据库组装参数
-
         # 1、TODO 校验请求信息中 有没有 与客户策略信息 中存在冲突的地方 -- 暂时不实现
         # 客户策略 和 请求信息 都有值 才会进行校验比对操作 -- 不得高于,不得不等于,不得超过集合
         # 因此分为3类 字段
@@ -203,8 +204,6 @@ class ParseAddCampaignOrAddGroupRequest(object):
                                  'begin_time': self.advertiser_strategy['begin_time'],
                                  'end_time': self.advertiser_strategy['end_time'],
                                  'schedule_time': self.advertiser_strategy['schedule_time'],
-                                 'day_budget': self.advertiser_strategy['day_budget'],
-                                 'day_budget_schedule': self.advertiser_strategy['day_budget_schedule'],
                                  'convert_id': self.advertiser_strategy['convert_id'],
                                  'url_type': self.advertiser_strategy['url_type'],
                                  'web_uri_type': self.advertiser_strategy['web_uri_type'],
@@ -255,13 +254,13 @@ class ParseAddCampaignOrAddGroupRequest(object):
         self.res_data['group_list'] = []
         group_cnt = 1
         for video in self.video:
-            single_group_info = {'group_uuid': uuid.uuid4()}
+            single_group_info = {'group_uuid': str(uuid.uuid4())}
             single_group_info.update(basic_group_info)
             single_group_info['unit_name'] = self.group_info['unit_name'] + '-' + str(group_cnt)
 
             # 组信息写入数据表中
             single_group_info_to_db = single_group_info.copy()
-            single_group_info_to_db['ai_strategy_id'] = self.ai_strategy_id
+            single_group_info_to_db['ai_strategy_uuid'] = self.ai_strategy_uuid
             single_group_info_to_db['account_id'] = self.account_id
             single_group_info_to_db['campaign_id'] = self.campaign_id
             single_group_info_to_db['create_time'] = datetime.datetime.now()
@@ -279,7 +278,7 @@ class ParseAddCampaignOrAddGroupRequest(object):
             creative_cnt = 1
             for image in video['imageList']:
                 single_creative_info = {
-                    'creative_uuid': uuid.uuid4(),
+                    'creative_uuid': str(uuid.uuid4()),
                     'is_sticky': 0,
                     'creative_name': self.creative_info['creative_name'] + '_' + str(creative_cnt),
                     'photo_id': video['photo_id'],
@@ -300,11 +299,11 @@ class ParseAddCampaignOrAddGroupRequest(object):
                     'creative_category': self.creative_info.get('creative_category'),
                     'creative_tag': self.creative_info.get('creative_tag')}
 
-                single_group_info.creative_list.append(single_creative_info)
+                single_group_info['creative_list'].append(single_creative_info)
 
                 # 创意层级写入数据表中
                 single_creative_info_to_db = single_creative_info.copy()
-                single_creative_info_to_db['ai_strategy_id'] = self.ai_strategy_id
+                single_creative_info_to_db['ai_strategy_uuid'] = self.ai_strategy_uuid
                 single_creative_info_to_db['account_id'] = self.account_id
                 single_creative_info_to_db['campaign_id'] = self.campaign_id
                 single_creative_info_to_db['create_time'] = datetime.datetime.now()

+ 36 - 1
db_config.py

@@ -1,5 +1,40 @@
+import pymysql
+from sqlalchemy import create_engine
+
 # 线上数据库连接字符串
 # db_con_str = "mysql+pymysql://%s:%s@%s:%d/%s" % ("readonly", "hcst@2021", "139.186.27.96", 4000, "jeecg-boot")
 
 # 测试数据库连接字符串
-db_con_str = "mysql+pymysql://%s:%s@%s:%d/%s" % ("hcst", "hcst@2020", "139.186.151.174", 3306, "jeecg-boot")
+db_con_str = "mysql+pymysql://%s:%s@%s:%d/%s" % ("hcst", "hcst@2020", "139.186.151.174", 3306, "jeecg-boot")
+engine = create_engine(db_con_str, connect_args={'charset': 'utf8'})
+
+# 创建计划url
+create_campaign_url = "http://192.168.1.8:8080/jeecg-boot/kuaishou/create/campaignCreate"
+
+# 获取上新视频url
+get_new_video_url = "http://192.168.1.8:8080/jeecg-boot/kuaishou/material/getNewVideoList"
+
+# 获取历史视频url
+get_history_video_url = "http://192.168.1.8:8080/jeecg-boot/kuaishou/material/getHistoryVideoList"
+
+# 创建组和创意url
+create_group_and_creative_url = ""
+
+
+
+# import MySQLdb
+# if __name__ == '__main__':
+#     connect = MySQLdb.connect(host="localhost", port=3306,
+#                               user="xxx", passwd="xxx", db='xxx', charset='utf8')
+#
+#     cursor = connect.cursor()
+#
+#     cursor.execute("""
+#        UPDATE tblTableName
+#        SET Year=%s, Month=%s, Day=%s, Hour=%s, Minute=%s
+#        WHERE Server=%s
+#     """, (Year, Month, Day, Hour, Minute, ServerID))
+#
+#     connect.commit()
+#     connect.close()
+

+ 0 - 0
logs/add_group_log/ai_callback_add_creative.log


+ 0 - 0
logs/add_group_log/ai_callback_add_group.log


+ 44 - 2
main.py

@@ -11,6 +11,8 @@ from logging.handlers import TimedRotatingFileHandler
 import logging
 
 import ai_strategy_request_handler
+import ai_callback_add_creative_handler
+import ai_callback_add_group_handler
 
 
 def create_application():
@@ -18,8 +20,8 @@ def create_application():
     log_formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s',
                                       '%m/%d/%Y %I:%M:%S %p')
 
-    # ai策略请求解析的日志对象
-    ai_strategy_request_log_handler = TimedRotatingFileHandler("logs/ai_strategy_request/ai_strategy_request.log",
+    # ai策略请求解析的日志对象-----------------------------------------------------------
+    ai_strategy_request_log_handler = TimedRotatingFileHandler("logs/add_group_log/ai_strategy_request.log",
                                                    when="midnight",
                                                    backupCount=100)
 
@@ -33,16 +35,56 @@ def create_application():
            format(t=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
     ai_strategy_request_logger.info(msg)
 
+    # 创建广告组回调日志对象-----------------------------------------------------------
+    ai_callback_add_group_log_handler = TimedRotatingFileHandler("logs/add_group_log/ai_callback_add_group.log",
+                                                               when="midnight",
+                                                               backupCount=100)
+
+    ai_callback_add_group_log_handler.setFormatter(log_formatter)
+    ai_callback_add_group_logger = logging.getLogger('ai_callback_add_group_logger')
+    ai_callback_add_group_logger.addHandler(ai_callback_add_group_log_handler)
+    ai_callback_add_group_logger.setLevel(logging.DEBUG)
+
+    print("ai_callback_add_group_logger's id is {}".format(id(ai_callback_add_group_logger)))
+    msg = "ai callback add group logger service started at {t}". \
+        format(t=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
+    ai_callback_add_group_logger.info(msg)
+
+    # 创建广告创意回调日志对象-----------------------------------------------------------
+    ai_callback_add_creative_log_handler = TimedRotatingFileHandler("logs/add_group_log/ai_callback_add_creative.log",
+                                                                 when="midnight",
+                                                                 backupCount=100)
+
+    ai_callback_add_creative_log_handler.setFormatter(log_formatter)
+    ai_callback_add_creative_logger = logging.getLogger('ai_callback_add_creative_logger')
+    ai_callback_add_creative_logger.addHandler(ai_callback_add_creative_log_handler)
+    ai_callback_add_creative_logger.setLevel(logging.DEBUG)
+
+    print("ai_callback_add_creative_logger's id is {}".format(id(ai_callback_add_creative_logger)))
+    msg = "ai callback add creative logger service started at {t}". \
+        format(t=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
+    ai_callback_add_creative_logger.info(msg)
+
     web_application = tornado.web.Application([
         (r"/ai_strategy_request",
          ai_strategy_request_handler.AiStrategyRequestParse,
          {"logger": ai_strategy_request_logger}),
+        (r"/ai_callback_add_group",
+         ai_callback_add_group_handler.AiCallBackAddGroup,
+         {"logger": ai_strategy_request_logger}),
+        (r"/ai_callback_add_creative",
+         ai_callback_add_creative_handler.AiCallBackAddCreative,
+         {"logger": ai_strategy_request_logger}),
     ])
 
     return web_application
 
 
 if __name__ == "__main__":
+    # import platform
+    # if platform.system() == 'Windows':
+    #     import asyncio
+    #     asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
     parser = argparse.ArgumentParser()
     parser.add_argument('-p', '--port', type=int, default=31012)
     args = parser.parse_args()

+ 1 - 2
manual_request_json.py

@@ -2,8 +2,7 @@ from typing import Optional, Awaitable
 import pandas as pd
 import numpy as np
 import datetime
-import pymysql
-from sqlalchemy import create_engine
+
 import simplejson
 import requests
 import tornado.web