def load(klass, account, params):
     resource = klass.RESOURCE.format(account_id=account.id)
     headers = {'Content-Type': 'application/json'}
     response = Request(account.client,
                        'post',
                        resource,
                        headers=headers,
                        body=json.dumps(params)).perform()
     return klass(account).from_response(response.body['data'])
예제 #2
0
 def opt_out(klass, account, file_path, list_type):
     """
     Updates the global opt-out list for the specified advertiser account.
     """
     upload = TONUpload(account.client, file_path)
     params = {'input_file_path': upload.perform(), 'list_type': list_type}
     resource = klass.OPT_OUT.format(account_id=account.id)
     Request(account.client, 'put', resource, params=params).perform()
     return True
    def all(klass, account, line_item_id, **kwargs):
        """Returns a Cursor instance for a given resource."""
        params = {'line_item_id': line_item_id}
        params.update(kwargs)

        resource = klass.RESOURCE_COLLECTION.format(account_id=account.id)
        request = Request(account.client, 'get', resource, params=params)

        return Cursor(klass, request, init_with=[account])
예제 #4
0
    def create(self, name, *ids):
        if isinstance(ids, list):
            ids = ','.join(map(str, ids))

        resource = self.RESOURCE_COLLECTION.format(account_id=self.account.id)
        params = self.to_params.update({'app_store_identifiers': ids, 'name': name})
        response = Request(self.account.client, 'post', resource, params=params).perform()

        return self.from_response(response.body['data'])
예제 #5
0
 def save(self):
     """
     Update the current object instance.
     """
     resource = self.RESOURCE.format(account_id=self.account.id)
     response = Request(
         self.account.client, 'put',
         resource, params=self.to_params()).perform()
     return self.from_response(response.body['data'])
예제 #6
0
    def all(klass, account, tailored_audience_id, **kwargs):
        """Returns a Cursor instance for the given tailored audience permission resource."""

        resource = klass.RESOURCE_COLLECTION.format(
            account_id=account.id,
            tailored_audience_id=tailored_audience_id)
        request = Request(account.client, 'get', resource, params=kwargs)

        return Cursor(klass, request, init_with=[account])
예제 #7
0
    def load(klass, account, **kwargs):
        # check whether both are specified or neither are specified
        if all([kwargs.get('card_uris'), kwargs.get('card_id')]) or \
           not any([kwargs.get('card_uris'), kwargs.get('card_id')]):
            raise ValueError(
                'card_uris and card_id are exclusive parameters. ' +
                'Please supply one or the other, but not both.')

        if kwargs.get('card_uris'):
            resource = klass.FETCH_URI.format(account_id=account.id)
            request = Request(account.client, 'get', resource, params=kwargs)
            return Cursor(klass, request, init_with=[account])
        else:
            resource = klass.FETCH_ID.format(account_id=account.id,
                                             id=kwargs.get('card_id'))
            response = Request(account.client, 'get', resource,
                               params=kwargs).perform()
            return klass(account).from_response(response.body['data'])
 def preview(self):
     """
     Returns an HTML preview for a Scheduled Tweet.
     """
     if self.id:
         resource = self.PREVIEW
         resource = resource.format(account_id=self.account.id, id=self.id)
         response = Request(self.account.client, 'get', resource).perform()
         return response.body['data']
예제 #9
0
    def save(self):
        """
        Saves or updates the current object instance depending on the
        presence of `object.id`.
        """
        params = self.to_params()
        if 'tweet_id' in params:
            params['tweet_ids'] = [params['tweet_id']]
            del params['tweet_id']

        if self.id:
            resource = self.RESOURCE.format(account_id=self.account.id, id=self.id)
            response = Request(self.account.client, 'put', resource, params=params).perform()
            return self.from_response(response.body['data'])

        resource = self.RESOURCE_COLLECTION.format(account_id=self.account.id)
        response = Request(self.account.client, 'post', resource, params=params).perform()
        return self.from_response(response.body['data'][0])
예제 #10
0
    def all(klass, account, custom_audience_id, **kwargs):
        """Returns a Cursor instance for the given targeted custom audience resource."""

        resource = klass.RESOURCE.format(
            account_id=account.id,
            custom_audience_id=custom_audience_id)
        request = Request(account.client, 'get', resource, params=kwargs)

        return Cursor(klass, request, init_with=[account])
예제 #11
0
    def update(self):
        resource = self.RESOURCE.format(account_id=self.account.id,
                                        id=self.media_key)
        response = Request(self.account.client,
                           'put',
                           resource,
                           params=self.to_params()).perform()

        return self.from_response(response.body['data'])
예제 #12
0
    def all_stats(klass, account, ids, metric_groups, **kwargs):
        """
        Pulls a list of metrics for a specified set of object IDs.
        """
        params = klass._standard_params(ids, metric_groups, **kwargs)

        resource = klass.RESOURCE_SYNC.format(account_id=account.id)
        response = Request(account.client, 'get', resource, params=params).perform()
        return response.body['data']
예제 #13
0
 def create(klass, account, status, **kwargs):
     """
     Creates a "Promoted-Only" Tweet using the specialized Ads API end point.
     """
     params = {'status': status}
     params.update(kwargs)
     resource = klass.TWEET_CREATE.format(account_id=account.id)
     response = Request(account.client, 'post', resource, params=params).perform()
     return response.body['data']
예제 #14
0
    def reload(self, **kwargs):
        if not self.media_key:
            return self

        resource = self.RESOURCE.format(account_id=self.account.id,
                                        id=self.media_key)
        response = Request(self.account.client, 'get', resource,
                           params=kwargs).perform()

        return self.from_response(response.body['data'])
예제 #15
0
    def __update_audience__(self, location, list_type, operation):
        params = {
            'tailored_audience_id': self.id,
            'input_file_path': location,
            'list_type': list_type,
            'operation': operation
        }

        resource = self.RESOURCE_UPDATE.format(account_id=self.account.id)
        return Request(self.account.client, 'post', resource, params=params).perform()
예제 #16
0
def get_resource(stream_name, client, path, params=None):
    resource = '/{}/{}'.format(API_VERSION, path)
    try:
        request = Request(client, 'get', resource, params=params) #, stream=True)
    except Error as err:
        # see twitter_ads.error for more details
        LOGGER.error('Stream: {} - ERROR: {}'.format(stream_name, err.details))
        raise err
    cursor = Cursor(None, request)
    return cursor
예제 #17
0
    def features(self):
        """
        Returns a collection of features available to the current account.
        """
        self._validate_loaded()

        resource = self.FEATURES.format(id=self.id)
        response = Request(self.client, 'get', resource).perform()

        return response.body['data']
예제 #18
0
def post_resource(report_name, client, path, params=None, body=None):
    resource = '/{}/{}'.format(API_VERSION, path)
    try:
        response = Request(client, 'post', resource, params=params, body=body).perform()
    except Error as err:
        # see twitter_ads.error for more details
        LOGGER.error('Report: {} - ERROR: {}'.format(report_name, err.details))
        raise err
    response_body = response.body # Dictionary response of POST request
    return response_body
예제 #19
0
 def delete(self):
     """
     Deletes the current tailored audience permission.
     """
     resource = self.RESOURCE.format(
         account_id=self.account.id,
         tailored_audience_id=self.tailored_audience_id,
         id=self.id)
     response = Request(self.account.client, 'delete', resource).perform()
     return self.from_response(response.body['data'])
    def get(self, request):
        account_id = request.query_params.get('account_id')
        next_cursor = request.query_params.get('next_cursor')
        objective = request.query_params.get('objective', 'APP_INSTALLS')
        promotable_user_id = request.query_params.get('promotable_user_id')

        if objective == 'APP_INSTALLS':
            objective = 1
        elif objective == 'WEBSITE_CLICKS':
            objective = 5
        else:
            objective = 0

        if not account_id:
            return Response([])

        account = TwitterAccount.objects_raw.get(pk=account_id)
        account_id_base36 = int_to_base36(int(account_id))

        oauth_token = account.tw_twitter_user_id.oauth_token
        oauth_secret = account.tw_twitter_user_id.oauth_secret
        client = Client(settings.TW_CONSUMER_KEY, settings.TW_CONSUMER_SECRET,
                        oauth_token, oauth_secret)
        api_domain = 'https://ads.twitter.com'

        if next_cursor:
            next_cursor = '&cursor=%s' % next_cursor
        else:
            next_cursor = ''
        resource = '/accounts/{account_id}/tweets/dashboard/tweet_rows?' \
            'manage_campaigns=true&objective={objective}&account={account_id}' \
            '&lang=en&promotable_user={promotable_user}{next_cursor}' \
            .format(
                account_id=account_id_base36,
                next_cursor=next_cursor,
                objective=objective,
                promotable_user=promotable_user_id
            )
        response = Request(client, 'get', resource,
                           domain=api_domain).perform()

        results = []
        html = response.body['tweetRows']
        soup = BeautifulSoup(html, 'html.parser')
        checkboxes = soup.find_all("input", {"class": "tweet-checkbox"})
        tweets = soup.find_all("div", {"class": "Tweet--timeline"})
        for i in range(len(tweets)):
            result = {
                'preview': tweets[i].prettify(),
                'tweet_id': str(checkboxes[i]['value'])
            }
            results.append(result)

        return Response(
            dict(results=results, next_cursor=response.body.get('cursor')))
예제 #21
0
    def async_stats_job_result(klass, account, job_id, **kwargs):
        """
        Returns the results of the specified async job IDs
        """
        params = {'job_ids': job_id}

        resource = klass.RESOURCE_ASYNC.format(account_id=account.id)
        response = Request(account.client, 'get', resource,
                           params=params).perform()

        return response.body['data'][0]
예제 #22
0
    def async_stats_job_data(klass, account, url, **kwargs):
        """
        Returns the results of the specified async job IDs
        """
        resource = urlparse(url)
        domain = '{0}://{1}'.format(resource.scheme, resource.netloc)

        response = Request(account.client, 'get', resource.path, domain=domain,
                           raw_body=True, stream=True).perform()

        return response.body
예제 #23
0
    def reload(self, **kwargs):
        """
        Reloads all attributes for the current object instance from the API.
        """
        if not self.id:
            return self

        resource = self.RESOURCE.format(account_id=self.account.id, id=self.id)
        response = Request(self.account.client, 'get', resource, params=kwargs).perform()

        return self.from_response(response.body['data'])
예제 #24
0
 def create(klass, account, name, components):
     method = 'post'
     resource = klass.RESOURCE_COLLECTION.format(account_id=account.id)
     headers = {'Content-Type': 'application/json'}
     payload = {'name': name, 'components': components}
     response = Request(account.client,
                        method,
                        resource,
                        headers=headers,
                        body=json.dumps(payload)).perform()
     return klass(account).from_response(response.body['data'])
예제 #25
0
    def __get(klass, account, client, params):
        """
        Helper function to get the conversation data
        Returns a Cursor instance
        """
        resource = klass.RESOURCE_CONVERSATIONS.format(account_id=account.id)

        request = Request(
            account.client, klass.METHOD,
            resource, headers=klass.HEADERS, body=params)
        return Cursor(klass, request, init_with=[account])
예제 #26
0
    def load(klass, account, card_uris=None, card_id=None, with_deleted=None):
        # check whether both are specified or neither are specified
        if all([card_uris, card_id]) or not any([card_uris, card_id]):
            raise ValueError(
                'card_uris and card_id are exclusive parameters. ' +
                'Please supply one or the other, but not both.')
        params = {}
        if with_deleted:
            params['with_deleted'] = 'true'

        if card_uris:
            params['card_uris'] = ','.join(card_uris)
            resource = klass.FETCH_URI.format(account_id=account.id)
            request = Request(account.client, 'get', resource, params=params)
            return Cursor(klass, request, init_with=[account])
        else:
            params['card_id'] = card_id
            resource = klass.FETCH_ID.format(account_id=account.id, id=card_id)
            response = Request(account.client, 'get', resource,
                               params=params).perform()
            return klass(account).from_response(response.body['data'])
예제 #27
0
def get_async_data(report_name, client, url):
    resource = urlparse(url)
    domain = '{0}://{1}'.format(resource.scheme, resource.netloc)
    try:
        response = Request(
            client, 'get', resource.path, domain=domain, raw_body=True, stream=True).perform()
        response_body = response.body
    except Error as err:
        # see twitter_ads.error for more details
        LOGGER.error('Report: {} - ERROR: {}'.format(report_name, err.details))
        raise err
    return response_body
예제 #28
0
    def get_published_tweets(self):
        """
        Step 1 of 'ENTITY - CARD' report generation process:
        Returns details on 'PUBLISHED' tweets, as a generator of dictionaries
        Documentation: https://developer.twitter.com/en/docs/ads/creatives/api-reference/tweets
        """

        resource = f"/{API_VERSION}/accounts/{self.account.id}/tweets"
        params = {"tweet_type": "PUBLISHED"}
        request = Request(self.client, "get", resource, params=params)

        yield from Cursor(None, request)
예제 #29
0
    def status(self):
        """
        Returns the status of all changes for the current tailored audience instance.
        """
        if not self.id:
            return None

        resource = self.RESOURCE_UPDATE.format(account_id=self.account.id)
        request = Request(self.account.client, 'get', resource, params=self.to_params())
        cursor = list(Cursor(None, request))

        return filter(lambda change: change['tailored_audience_id'] == self.id, cursor)
예제 #30
0
    def save(self):
        if self.media_key:
            method = 'put'
            resource = self.RESOURCE.format(account_id=self.account.id, id=self.media_key)
        else:
            method = 'post'
            resource = self.RESOURCE_COLLECTION.format(account_id=self.account.id)

        response = Request(
            self.account.client, method,
            resource, params=self.to_params()).perform()

        return self.from_response(response.body['data'])