Exemplo n.º 1
0
    def get_spends_and_properties(self):
        """Fetch spend metrics for the last 3 days and
        the requested properties of the working ad account"""

        fields = 'adaccounts{currency,account_status,disable_reason,age,' + \
            'amount_spent,insights.date_preset(last_3_days).' + \
            'level(account).time_increment(1)}'
        path = '{}/me'.format(self.version)
        response = self.request(path, {'fields': fields})
        results = response.get('adaccounts', {}).get('data')
        if not isinstance(results, list) or len(results) == 0:
            raise GraphAPIError('Wrong properties for fbaccount: {}'.format(
                self.account.name))
        ad_accounts = [acc for acc in results if acc.get('age', 0) > 0]
        if len(ad_accounts) == 0:
            raise GraphAPIError('Wrong properties for fbaccount: {}'.format(
                self.account.name))
        ad_account = ad_accounts[0]

        currency = ad_account.get('currency')
        if currency is None:
            raise GraphAPIError('Wrong currency for fbaccount: {}'.format(
                self.account.name))

        amount = ad_account.get('amount_spent')
        if amount is not None:
            offset = self.CURRENCIES_OFFSET.get(currency, 100)
            ad_account['amount_spent'] = float(amount) / offset

        ad_account['insights'] = ad_account.get('insights', {}).get('data', [])
        return ad_account
Exemplo n.º 2
0
 def get_ad_accounts_properties(self, fields):
     path = '{}/me'.format(self.version)
     params = {'fields': 'adaccounts{{account_id,{}}}'.format(fields)}
     response = self.request(path, params)
     try:
         result = response['adaccounts']['data']
     except (KeyError, TypeError):
         raise GraphAPIError('Wrong properties for fbaccount: {}'.format(
             self.account.name))
     if not isinstance(result, list):
         raise GraphAPIError('Wrong properties for fbaccount: {}'.format(
             self.account.name))
     return result
Exemplo n.º 3
0
 def get_version(self):
     path = '{}{}/me'.format(FACEBOOK_GRAPH_URL, self.version)
     response = self.open_url(path)
     info = response.info()
     version = info.getheader('facebook-api-version').replace('v', '')
     if version not in VALID_API_VERSIONS:
         raise GraphAPIError('API version "{}" no valid.'.format(version))
     return version
Exemplo n.º 4
0
def test_validate_credentials_error(event):

    with patch.object(GraphAPI,
                      "get_object",
                      side_effect=GraphAPIError("some error")) as mock:
        with pytest.raises(PublisherError):
            FacebookPublisher().validate_credentials()
        mock.assert_called()
Exemplo n.º 5
0
def test_send_error(event):

    with patch.object(GraphAPI,
                      "put_object",
                      side_effect=GraphAPIError("some error")) as mock:
        with pytest.raises(PublisherError):
            FacebookPublisher().send("abc", event)
        mock.assert_called()
Exemplo n.º 6
0
 def get_account_properties(self, fields):
     try:
         return [
             acc for acc in self.get_ad_accounts_properties(fields)
             if acc.get('account_id') == self.account.ad_fbaccount_id
         ][0]
     except IndexError:
         raise GraphAPIError('Wrong properties for fbaccount: {}'.format(
             self.account.name))
Exemplo n.º 7
0
    def request(self, path, args=None):
        """Fetches the given path in the Graph API."""
        response = self.open_url(path, args)
        result_text = response.read()
        if result_text:
            result_parse = parse_qs(result_text)
            if 'error' in result_parse:
                raise GraphAPIError(result_parse['error'])
            elif 'access_token' in result_parse:
                result = {'access_token': result_parse['access_token'][0]}
                if 'expires' in result_parse:
                    result['expires'] = result_parse['expires'][0]
            else:
                try:
                    result = json.loads(result_text)
                except ValueError:
                    result = result_text
        else:
            raise GraphAPIError('Query result has no data')

        return result
Exemplo n.º 8
0
 def open_url(self, path, args=None):
     args = args or {}
     args['access_token'] = self.access_token
     params = urllib.urlencode(args)
     url = '{}{}?{}'.format(FACEBOOK_GRAPH_URL, path, params)
     if self.account.use_luminati:
         opener = urllib2.build_opener(self.proxy_handler)
     else:
         opener = BindableOpenerDirector(self.account.ip_address)
     try:
         return opener.open(url)
     except (URLError, HTTPException) as err:
         raise GraphAPIError(err)
Exemplo n.º 9
0
def fetch_metrics(graph_id, metrics):
    """Fetch Facebook Insights metrics for an object with a given id.

    Parameters
    ----------
    graph_id : str
        The Facebook ID of a Graph API object.
    metrics : iterable of str
        The object's metrics to fetch (e.g. 'page_engaged_users').

    Returns
    -------
    dict
        A dictionary of mappings between metric names and instances
        of class 'Metric'.

    """
    if not metrics:
        raise MetricsNotSpecified('Specify metrics you want to fetch.')
    batch = []
    for metric in metrics:
        request_data = {
            'method': 'GET',
            'relative_url': '{}/insights/{}/'.format(graph_id, metric)
        }
        batch.append(request_data)
    batch_response = graph_api.put_object(
        parent_object='/',
        connection_name='',
        batch=json.dumps(batch),
    )
    extracted_metrics = {}
    for response in batch_response:
        body = json.loads(response['body'])
        # (nevimov/2016-11-09): Currently facebook-sdk is not
        # able to catch errors in responses to batch requests, so
        # we have to take care of those ourselves.
        if 'error' in body:
            raise GraphAPIError(body)
        data = body['data']
        if not data:
            raise EmptyData
        rearranged_values = {}
        for datum in data:
            name = datum['name']
            period = datum['period']
            rearranged_values[period] = datum['values']
        extracted_metrics[name] = Metric(name, rearranged_values)
    return extracted_metrics
 def test_setting_error_subcode(self):
     """Verify that error subcode is set properly."""
     # Generate random string.
     error_subcode = "".join(
         random.choice(string.ascii_letters + string.digits)
         for _ in range(10))
     result = {
         "error": {
             "message": "",
             "code": "",
             "error_subcode": error_subcode,
         }
     }
     error = GraphAPIError(result)
     self.assertEqual(error.error_subcode, error_subcode)
Exemplo n.º 11
0
def login():

    client = None

    if not path.exists(cookie('facebook')):

        for i in range(0, 3):
            token = multenterbox("Enter a valid Facebook access token",
                                 ['Access Token'], [''])[0]
            try:
                client = GraphAPI(token)
                client.request('me')
                fmutex('facebook').write(token)
                return client
            except GraphAPIError, e:
                print str(e)
                pass

        raise GraphAPIError('Unable to query GraphAPI')
 def test_default_error_subcode(self):
     """Verify that default error subcode is None."""
     error = GraphAPIError(None)
     self.assertEqual(error.error_subcode, None)
Exemplo n.º 13
0
def fetch_metrics(graph_id, metrics, token=None):
    """Fetch Facebook Insights metrics for an object with a given id.

    Parameters
    ----------
    graph_id : str
        The Facebook ID of a Graph API object.
    metrics : iterable of str
        The object's metrics to fetch (e.g. 'page_engaged_users').
    token: str
        A Facebook Graph API access token

    Returns
    -------
    dict
        A dictionary of mappings between metric names and instances
        of class 'Metric'.

    """
    if not metrics:
        raise MetricsNotSpecified('Specify metrics you want to fetch.')
    batch = []
    for metric in metrics:
        request_data = {
            'method': 'GET',
            'relative_url': '{}/insights/{}/'.format(graph_id, metric)
        }
        batch.append(request_data)

    # ##TODON'T##
    global graph_api
    if token and (token != graph_api.access_token):
        graph_api = GraphAPI(access_token=token, version=api_version)

    batch_response = graph_api.put_object(
        parent_object='/',
        connection_name='',
        batch=json.dumps(batch),
    )
    extracted_metrics = {}
    for response in batch_response:
        body = json.loads(response['body'])
        # (nevimov/2016-11-09): Currently facebook-sdk is not
        # able to catch errors in responses to batch requests, so
        # we have to take care of those ourselves.
        if 'error' in body:
            raise GraphAPIError(body)
        data = body['data']
        if not data:
            # We need a better middle ground for this but just
            #   raising exceptions doesn't work when some of a
            #   set can legitimately be empty
            continue
            # raise EmptyData
        rearranged_values = {}
        for datum in data:
            name = datum['name']
            period = datum['period']
            rearranged_values[period] = datum['values']
        extracted_metrics[name] = Metric(name, rearranged_values)
    return extracted_metrics