Exemple #1
0
def get_ads(mmt_ads_acct):
    ad_params = {
        'fields':
        [Ad.Field.adset_id, Ad.Field.id, 'creative{object_story_spec}'],
        'limit':
        500,
        'filtering': [{
            'field':
            'ad.effective_status',
            'operator':
            AdsInsights.Operator.in_,
            'value': [
                Ad.EffectiveStatus.active,
                # Ad.EffectiveStatus.adset_paused, Ad.EffectiveStatus.campaign_paused,
                Ad.EffectiveStatus.paused
            ]
        }]
    }
    try:
        ads_generator = mmt_ads_acct.get_ads(params=ad_params)
        return {ad[AdsInsights.Field.adset_id]: ad for ad in ads_generator}
    except FacebookRequestError as e:
        if e.api_error_code() == 17:
            err('A: Hit api limit..backing off')
            time.sleep(60)
            return get_ads(mmt_ads_acct)
        else:
            raise e
Exemple #2
0
def get_adsets(mmt_ads_acct, adset_ids, ts):
    adset_params = {
        'fields': [
            AdSet.Field.name, AdSet.Field.created_time, AdSet.Field.start_time,
            AdSet.Field.end_time, AdSet.Field.effective_status,
            AdSet.Field.budget_remaining, AdSet.Field.daily_budget,
            AdSet.Field.lifetime_budget, AdSet.Field.id
        ],
        'filtering': [{
            'field': AdSet.Field.id,
            'operator': 'IN',
            'value': list(adset_ids)
        }],
        'limit':
        500
    }

    try:
        adsets_generator = mmt_ads_acct.get_ad_sets(params=adset_params)
        adsets = {adset[AdSet.Field.id]: adset for adset in adsets_generator}
    except FacebookRequestError as e:
        if e.api_error_code() == 17:
            err('AS: Hit api limit..backing off')
            time.sleep(60)
            return get_adsets(mmt_ads_acct, adset_ids, ts)
        else:
            raise e

    remove_adsets = []
    for adset_id in adsets:
        start_date = adsets[adset_id][AdSet.Field.start_time]
        end_date = adsets[adset_id][AdSet.Field.end_time]
        if get_datetime(ts) > get_datetime(end_date):
            print('{} already ended on {}'.format(adset_id, end_date))
            remove_adsets.append(adset_id)
        elif get_datetime(ts) < get_datetime(start_date):
            print('{} has not started yet, starts on {}'.format(
                adset_id, start_date))
            remove_adsets.append(adset_id)
    for adset_id in remove_adsets:
        adsets.pop(adset_id)

    return adsets
Exemple #3
0
def get_reach_estimate(adset):
    try:
        adset.remote_read(fields=['delivery_estimate'])
    except FacebookRequestError as e:
        if e.api_error_code() == 17:
            err('RE: reached api limit')
            time.sleep(60)
            return get_reach_estimate(adset)
        else:
            raise e

    reach_estimate = -1
    try:
        data = adset['delivery_estimate']['data'] if 'data' in adset[
            'delivery_estimate'] else []
        reach_estimate = data[0]['estimate_mau']
    except (KeyError, IndexError):
        pass

    return reach_estimate
Exemple #4
0
def find_my_fbid(search_term, quiet=True):
    """
    Tries to find a valid facebook page id for a search term (ie url)
    Args:
        search_term: url, canonical name, etc to search for fbid
        quiet: don't emit error

    Returns: valid fbid for search_term, or None
    """
    try:
        resp = requests.post('https://findmyfbid.com',
                             data={'url': search_term})
        resp.raise_for_status()
        fbid = json.loads(resp.text)['id']
    except Exception as e:
        if not quiet:
            from workbench.core.utils import err
            err(e)
        return None

    return fbid
Exemple #5
0
def get_adset_period_insight(adset, start_date, end_date):
    period_insight_parameters = {
        'fields': [
            AdsInsights.Field.reach, AdsInsights.Field.frequency,
            AdsInsights.Field.actions, AdsInsights.Field.date_start,
            AdsInsights.Field.date_stop
        ],
        'time_ranges': [{
            'since': tsify_datetime(start_date),
            'until': tsify_datetime(end_date)
        }]
    }
    try:
        return adset.get_insights(params=period_insight_parameters)
    except FacebookRequestError as e:
        if e.api_error_code() == 17:
            err('ASPI: Hit api limit..backing off')
            time.sleep(60)
            return get_adset_period_insight(adset, start_date, end_date)
        else:
            raise e
Exemple #6
0
def process_trends_model_input(fn, curs=None):
    """
    Processes flat file input into list of artist X locations

    Input is line-separated artist names, or 4-space delimited/line-separated artist names + nation isos
    Args:
        fn: full path to input file
        curs: a Redshift cursor to use (if needed)

    Returns: [{'name': <artist name>, 'location': <nation iso>, ...}, ...]

    """
    try:
        with open(fn, 'r') as f:
            raw = [l.rstrip().replace('!', '') for l in f.readlines()]
        assert len(raw) > 0 and all(len(raw_inp) > 0 for raw_inp in raw)
    except FileNotFoundError:
        raise ProcessError(
            'no such file {} (hint: must be absolute path)'.format(fn))
    except AssertionError:
        raise ProcessError(
            'file {} was empty or contained empty lines'.format(fn))

    if len(raw[0].split(TRENDS_SEPERATOR)) > 1:
        return [
            dict(zip(('name', 'location'), l.split(TRENDS_SEPERATOR)))
            for l in raw
        ]
    else:
        curs = curs or get_redshift_cursor()
        try:
            curs.execute(NATIONS_STMT)
        except Exception as e:
            err(e)
            raise ProcessError('failed to fetch whitelist biz dev nations')
        locs = [loc for loc in curs.fetchall()]
        return [
            dict(name=raw_artist, location=loc[0]) for raw_artist in raw
            for loc in locs
        ]
Exemple #7
0
def filter_by_facebook_likes(artists_and_locations,
                             min_likes_threshold=5000,
                             curs=None):
    """
    Args:
        artists_and_locations: [{'name': <artist name>, 'location': <nation iso>, ...}, ...]
        min_likes_threshold: minimum facebook likes to filter by
        curs: a Redshift cursor to use

    Returns: filtered by limit, [{'name': <artist name>, 'location': <nation iso>, ...}, ...]
    """
    curs = curs or get_redshift_cursor()
    try:
        artist_names = set(
            map(lambda a_l: a_l['name'].lower(), artists_and_locations))
        locations = set(map(lambda a_l: a_l['location'],
                            artists_and_locations))
    except KeyError as e:
        err(e)
        raise ProcessError(
            'artists_and_locations must be: '
            '[{\'name\': <artist name>, \'location\': <nation iso>, ...}, ...]'
        )

    try:
        curs.execute(
            FILTER_STMT,
            (min_likes_threshold, tuple(locations), tuple(artist_names)))
    except Exception as e:
        err(e)
        raise ProcessError('filter query failed')

    filter_by = set(
        '_'.join([str(row[0].lower()), str(row[1])])
        for row in curs.fetchall())
    return list(
        filter(
            lambda a_l: '_'.join([a_l['name'].lower(), a_l['location']]) in
            filter_by, artists_and_locations))
Exemple #8
0
def get_adset_insights(mmt_ads_acct, adset_ids, ts):

    insight_params = {
        'level':
        AdsInsights.Level.adset,
        'fields': [
            AdsInsights.Field.adset_id, AdsInsights.Field.reach,
            AdsInsights.Field.cpp, AdsInsights.Field.frequency,
            AdsInsights.Field.spend, AdsInsights.Field.actions,
            AdsInsights.Field.cost_per_action_type
        ],
        'filtering': [{
            'field': 'adset.id',
            'operator': AdsInsights.Operator.in_,
            'value': list(adset_ids)
        }],
        'time_ranges': [{
            'since': tsify_datetime(ts),
            'until': tsify_datetime(ts)
        }],
        'limit':
        500
    }

    try:
        insight_generator = mmt_ads_acct.get_insights(params=insight_params)
        return {
            insight[AdsInsights.Field.adset_id]: insight
            for insight in insight_generator
        }
    except FacebookRequestError as e:
        if e.api_error_code() == 17:
            err('ASI: Hit api limit..backing off')
            time.sleep(60)
            return get_adset_insights(mmt_ads_acct, adset_ids, ts)
        else:
            raise e