def set_secret(): """gets client id, client secret, dev token, account id. Saves to config.yaml and returns refresh url""" data = request.get_json(force=True) # determines if a reset to prev valid config or trying to setup new config is_reset = True if not data.get('config_valid'): data['refresh_token'] = None data['config_valid'] = 0 is_reset = False with open(CONFIG_FILE_PATH, 'w') as fi: yaml.dump(data, fi) setup.upload_file_to_gcs(CONFIG_FILE_PATH, CONFIG_FILE_PATH_GS) # If its just a reset - no need to generate a url if is_reset: return _build_response(msg=json.dumps( 'successfully restored previous configs'), status=200) init_flow( client_id=data['client_id'], client_secret=data['client_secret'] ) return _build_response(msg=json.dumps(""), status=200)
def _update_asset_struct(asset): """Update the asset_to_ag file with the new assets and their adgroups""" try: setup.download_file_from_gcs('asset_to_ag.json', asset_to_ag_json_path) except Exception as e: print(e) with open(asset_to_ag_json_path, 'r') as f: struct = json.load(f) struct.append(asset) with open(asset_to_ag_json_path, 'w') as f: json.dump(struct, f, indent=2) setup.upload_file_to_gcs(asset_to_ag_json_path, 'asset_to_ag.json')
def create_mcc_struct(client, mcc_struct_file, assets_file): builder = MCCStructureBuilder(client) for _ in range(_MAX_RETRIES): try: structure = builder.build() except Exception as e: logging.exception(e) err_msg = e.args[0] time.sleep(10) continue else: break else: logging.error('Could not create structure') raise ConnectionError(err_msg) with open(mcc_struct_file, 'w') as f: json.dump(structure, f, indent=2) setup.upload_file_to_gcs(mcc_struct_file, 'account_struct.json') assets = {} for account in structure: for campaign in account['campaigns']: for ad_group in campaign['adgroups']: for asset in ad_group['assets']: try: performance_type = 'nontext' if asset['type'] == 'TEXT': performance_type = asset['text_type'] key = str(asset['id']) + performance_type assets[key]['adgroups'].append( { 'id': ad_group['id'], 'performance': asset['performance'], 'performance_type': performance_type } ) except KeyError: assets[key] = asset assets[key]['adgroups'] = [ { 'id': ad_group['id'], 'performance': asset['performance'], 'performance_type': performance_type } ] with open(assets_file, 'w') as f: json.dump(list(assets.values()), f, indent=2) setup.upload_file_to_gcs(assets_file, 'asset_to_ag.json')
def set_yt(): """Set yt-conifg.json with channel id and API key. Will be used to get all the channel's videos. Gets a JSON with two keys: channel_id api_key """ data = request.get_json(force=True) try: channel_id = data['channel_id'] with open(YT_CONFIG_FILE_PATH, 'w') as f: json.dump({'channel_id':channel_id},f) setup.upload_file_to_gcs(YT_CONFIG_FILE_PATH, YT_CONFIG_FILE_PATH_GS) return _build_response(status=200) except Exception as e: logging.exception(e) return _build_response(msg=json.dumps(str(e)), status=400)
def init_clients(): """Sets up googleads.yaml and google-ads.yaml and inits both clients. tries to create struct. if succesful, marks config_valid=1 in config.yaml to mark config is valid. Marks 0 otherwise.""" status = 0 try: get_global_adwords_client() get_global_googleads_client() with open(CONFIG_FILE_PATH, 'r') as f: config = yaml.load(f, Loader=yaml.FullLoader) config['config_valid'] = 1 with open(CONFIG_FILE_PATH, 'w') as f: yaml.dump(config, f) setup.upload_file_to_gcs(CONFIG_FILE_PATH, CONFIG_FILE_PATH_GS) except Exception as e: logging.error(str(e)) status=1 return status
def _text_asset_mutate(data, aw_client, ga_client, asset_id, asset_struct): """Handles text asset mutations""" asset_handlers = [] index = 0 # to re-write back to location for entry in asset_struct: if entry['id'] == asset_id: asset_handlers.append({'asset':entry, 'index':index}) index += 1 # if only one of headlines/descriptions entries # exists in asset_struct, create the second one. # if the asset isn't assigned to any adgroup, create both entries # create headline entry only if text's len <= 30 if len(asset_handlers) < 2: new_asset = { 'id': data[0]['asset']['id'], 'type':'TEXT', 'asset_text':data[0]['asset']['asset_text'], 'adgroups':[] } append = False if len(data[0]['asset']['asset_text']) <= 30: headline_len = True else: headline_len = False if len(asset_handlers) == 1: existing_type = asset_handlers[0]['asset']['text_type'] if existing_type == 'headlines': new_asset['text_type'] = 'descriptions' append = True elif headline_len: new_asset['text_type'] = 'headlines' append = True if append: asset_handlers.append({'asset':new_asset, 'index':None}) elif len(asset_handlers) == 0: new_asset['text_type'] = 'descriptions' asset_handlers.append({'asset':new_asset, 'index':None}) if headline_len: new_asset_second = copy.copy(new_asset) new_asset_second['adgroups'] = [] new_asset_second['text_type'] = 'headlines' asset_handlers.append({'asset':new_asset_second, 'index':None}) successeful_assign = [] failed_assign = [] for item in data: account = item['account'] adgroup = item['adgroup'] action = item['action'] asset = item['asset'] text_type_to_assign = item['asset']['text_type_to_assign'] try: mutation = mutate_ad(aw_client, account, adgroup, asset, action, text_type_to_assign) except Exception as e: failed_assign.append( { 'adgroup': populate_adgroup_details(ga_client, account, adgroup), 'error_message': error_mapping(str(e)), 'err': str(e) } ) mutation = 'failed' logging.error( 'could not execute mutation on adgroup: %s, %s' ,str(adgroup), str(e)) if mutation is None: for obj in asset_handlers: if obj['asset']['text_type'] == text_type_to_assign: obj['asset'] = _asset_ag_update(obj['asset'],adgroup,action) successeful_assign.append(adgroup) Service_Class.reset_cid(aw_client) for obj in asset_handlers: if obj['index']: asset_struct[obj['index']] = obj['asset'] else: asset_struct.append(obj['asset']) with open(asset_to_ag_json_path, 'w') as f: json.dump(asset_struct, f,indent=2) setup.upload_file_to_gcs(asset_to_ag_json_path, 'asset_to_ag.json') if failed_assign and successeful_assign: status = 206 elif successeful_assign: status = 200 else: status = 500 logging.info( 'mutate response: msg={} , status={}'.format(str(asset_handlers),index)) return _build_response( msg=json.dumps( [{ 'asset': asset_handlers, 'failures': failed_assign }] ), status=status)
def mutate(): """Assign or remove an asset from adgroups. gets a dict with two entries: 1. refresh token to create clients 2. list of asset, account, adgourp and action. preforms all of the actions one by one. returns a list with the new asset objects with the changed adgroups list. if its a text asset, returns a list with both 'headlines' and 'descriptions' entries. also changes the asset_to_ag.json file. """ data = request.get_json(force=True) logging.info('Recived mutate request: %s', str(data['data'])) refresh_token = data['refresh_token'] data_load = data['data'] asset_id = data_load[0]['asset']['id'] asset_type = data_load[0]['asset']['type'] aw_client = init_user_adwords_client(refresh_token) ga_client = init_user_googleads_client(refresh_token) setup.download_file_from_gcs('asset_to_ag.json', asset_to_ag_json_path) with open(asset_to_ag_json_path, 'r') as f: asset_struct = json.load(f) # special func for text assets, as they have 2 entries in asset_to_ag.json if asset_type == 'TEXT': return _text_asset_mutate(data_load, aw_client, ga_client, asset_id, asset_struct) asset_handler = {} index = 0 # to re-write back to location for entry in asset_struct: if entry['id'] == asset_id: asset_handler = entry break index += 1 if not asset_handler: asset_handler = data_load[0]['asset'] asset_handler['adgroups'] = [] index = None failed_assign = [] successeful_assign = [] for item in data_load: account = item['account'] adgroup = item['adgroup'] action = item['action'] asset = item['asset'] try: mutation = mutate_ad(aw_client, account, adgroup, asset, action) except Exception as e: failed_assign.append( { 'adgroup': populate_adgroup_details(ga_client, account, adgroup), 'error_message': error_mapping(str(e)), 'err': str(e) } ) mutation = 'failed' logging.error('could not execute mutation on adgroup: %s',str(adgroup)) if mutation is None: successeful_assign.append(adgroup) asset_handler = _asset_ag_update(asset_handler,adgroup,action) Service_Class.reset_cid(aw_client) if index: asset_struct[index] = asset_handler else: asset_struct.append(asset_handler) with open(asset_to_ag_json_path, 'w') as f: json.dump(asset_struct, f,indent=2) setup.upload_file_to_gcs(asset_to_ag_json_path, 'asset_to_ag.json') if failed_assign and successeful_assign: status = 206 elif successeful_assign: status = 200 else: status = 500 logging.info( 'mutate response: msg={} , status={}'.format(asset_handler,index)) return _build_response(msg=json.dumps( [{'asset':asset_handler,'index':index, 'failures':failed_assign}]) , status=status)