def __init__(self, args, kwargs): api = self.api # If authentication is required and no credentials # are provided, throw an error. if self.require_auth and not api.auth: raise TweepError('Authentication required!') self.post_data = kwargs.pop('post_data', None) self.retry_count = kwargs.pop('retry_count', api.retry_count) self.retry_delay = kwargs.pop('retry_delay', api.retry_delay) self.retry_errors = kwargs.pop('retry_errors', api.retry_errors) self.wait_on_rate_limit = kwargs.pop('wait_on_rate_limit', api.wait_on_rate_limit) self.wait_on_rate_limit_notify = kwargs.pop('wait_on_rate_limit_notify', api.wait_on_rate_limit_notify) self.parser = kwargs.pop('parser', api.parser) self.session.headers = kwargs.pop('headers', {}) self.build_parameters(args, kwargs) # Pick correct URL root to use if self.search_api: self.api_root = api.search_root elif self.upload_api: self.api_root = api.upload_root else: self.api_root = api.api_root # Perform any path variable substitution self.build_path() if self.search_api: self.host = api.search_host elif self.upload_api: self.host = api.upload_host else: self.host = api.host # Manually set Host header to fix an issue in python 2.5 # or older where Host is set including the 443 port. # This causes Twitter to issue 301 redirect. # See Issue https://github.com/tweepy/tweepy/issues/12 self.session.headers['Host'] = self.host # Monitoring rate limits self._remaining_calls = None self._reset_time = None
def _read_loop(self, resp): buf = ReadBuffer(resp.raw, self.chunk_size) while self.running and not resp.raw.closed: length = 0 while not resp.raw.closed: line = buf.read_line().strip() if not line: self.listener.keep_alive( ) # keep-alive new lines are expected elif line.isdigit(): length = int(line) break else: raise TweepError( 'Expecting length, unexpected value found') next_status_obj = buf.read_len(length) if self.running: self._data(next_status_obj) # # Note: keep-alive newlines might be inserted before each length value. # # read until we get a digit... # c = b'\n' # for c in resp.iter_content(decode_unicode=True): # if c == b'\n': # continue # break # # delimited_string = c # # # read rest of delimiter length.. # d = b'' # for d in resp.iter_content(decode_unicode=True): # if d != b'\n': # delimited_string += d # continue # break # # # read the next twitter status object # if delimited_string.decode('utf-8').strip().isdigit(): # status_id = int(delimited_string) # next_status_obj = resp.raw.read(status_id) # if self.running: # self._data(next_status_obj.decode('utf-8')) if resp.raw.closed: self.on_closed(resp)
def parse(self, method, payload, return_cursors=False): try: json = json_lib.loads(payload) except Exception as e: raise TweepError('Failed to parse JSON payload: %s' % e) if return_cursors and isinstance(json, dict): if 'next' in json: return json, json['next'] elif 'next_cursor' in json: if 'previous_cursor' in json: cursors = json['previous_cursor'], json['next_cursor'] return json, cursors else: return json, json['next_cursor'] return json
def test_publishing_when_an_error_occur_with_tweepy_api( mock_boto, mock_tweepy, mock_patch, lambda_event_publisher, caplog): mock_s3 = mock.MagicMock() mock_s3.download_fileobj.side_effect = None mock_ssm = mock.MagicMock() mock_boto.client.side_effect = [mock_s3, mock_ssm] mock_ssm.get_parameter.side_effect = None mock_tweepy.OAuthHandler.side_effect = TweepError( reason='something goes wrong') with pytest.raises(TweepError, match='something goes wrong'): lambda_handler(event=lambda_event_publisher, context={}) assert mock_ssm.get_parameter.call_count == 4 assert 'Error while trying to sending a tweet' in caplog.text mock_s3.download_fileobj.assert_called_once()
def get_authorization_url(self, signin_with_twitter=False, access_type=None): """Get the authorization URL to redirect the user""" try: if signin_with_twitter: url = self._get_oauth_url('authenticate') if access_type: logging.warning(WARNING_MESSAGE) else: url = self._get_oauth_url('authorize') self.request_token = self._get_request_token( access_type=access_type) return self.oauth.authorization_url(url) except Exception as e: raise TweepError(e)
def build_path(self): for variable in re_path_template.findall(self.path): name = variable.strip('{}') if name == 'user' and self.api.auth: value = self.api.auth.get_username() else: try: value = urllib.quote(self.parameters[name]) except KeyError: raise TweepError( 'No parameter value found for path variable: %s' % name) del self.parameters[name] self.path = self.path.replace(variable, value)
def __init__(self, api, args, kargs): # If authentication is required and no credentials # are provided, throw an error. if self.require_auth and not api.auth: raise TweepError('Authentication required!') self.api = api self.post_data = kargs.pop('post_data', None) self.retry_count = kargs.pop('retry_count', api.retry_count) self.retry_delay = kargs.pop('retry_delay', api.retry_delay) self.retry_errors = kargs.pop('retry_errors', api.retry_errors) self.monitor_rate_limit = kargs.pop('monitor_rate_limit', api.monitor_rate_limit) self.wait_on_rate_limit = kargs.pop('wait_on_rate_limit', api.wait_on_rate_limit) if self.monitor_rate_limit: self._path_category = path_category_pattern.findall(self.path)[0] if self._path_category == 'application': self.monitor_rate_limit = False self._path_without_ext = path_without_ext_pattern.findall(self.path)[0] self._remaining_calls = [sys.maxint]*len(self.api.auths) self._reset_times = [sys.maxint]*len(self.api.auths) self.headers = kargs.pop('headers', {}) self.build_parameters(args, kargs) # Pick correct URL root to use if self.search_api: self.api_root = api.search_root else: self.api_root = api.api_root # Perform any path variable substitution self.build_path() if api.secure: self.scheme = 'https://' else: self.scheme = 'http://' if self.search_api: self.host = api.search_host else: self.host = api.host # Manually set Host header to fix an issue in python 2.5 # or older where Host is set including the 443 port. # This causes Twitter to issue 301 redirect. # See Issue https://github.com/tweepy/tweepy/issues/12 self.headers['Host'] = self.host
def get_authorization_url(self, signin_with_twitter=False): """Get the authorization URL to redirect the user""" try: # get the request token self.request_token = self._get_request_token() # build auth request and return as url if signin_with_twitter: url = self._get_oauth_url('authenticate') else: url = self._get_oauth_url('authorize') request = oauth.OAuthRequest.from_token_and_callback( token=self.request_token, http_url=url) return request.to_url() except Exception as e: raise TweepError(e)
def get_authorization_url(self, signin_with_twitter=False): """Get the authorization URL to redirect the user""" try: # get the request token self.request_token = self._get_request_token() # build auth request and return as url if signin_with_twitter: auth_url = self.AUTHENTICATE_URL else: auth_url = self.AUTHORIZATION_URL request = oauth.OAuthRequest.from_token_and_callback( token=self.request_token, http_url=auth_url) return request.to_url() except Exception, e: raise TweepError(e)
def sample(self, *, languages=None, stall_warnings=False, threaded=False): if self.running: raise TweepError("Stream is already connected") method = "GET" endpoint = "statuses/sample" params = {} if languages: params["language"] = ','.join(map(str, languages)) if stall_warnings: params["stall_warnings"] = "true" if threaded: return self._threaded_connect(method, endpoint, params=params) else: self._connect(method, endpoint, params=params)
def build_path(self): for variable in re_path_template.findall(self.path): name = variable.strip('{}') if name == 'user' and 'user' not in self.session.params and self.api.auth: # No 'user' parameter provided, fetch it from Auth instead. value = self.api.auth.get_username() else: try: value = quote(self.session.params[name]) except KeyError: raise TweepError( 'No parameter value found for path variable: %s' % name) del self.session.params[name] self.path = self.path.replace(variable, value)
def get_access_token(self, verifier=None): """ After user has authorized the request token, get access token with user supplied verifier. """ try: url = self._get_oauth_url('access_token') self.oauth = OAuth1Session(self.consumer_key, client_secret=self.consumer_secret, resource_owner_key=self.request_token['oauth_token'], resource_owner_secret=self.request_token['oauth_token_secret'], verifier=verifier, callback_uri=self.callback) resp = self.oauth.fetch_access_token(url) self.access_token = resp['oauth_token'] self.access_token_secret = resp['oauth_token_secret'] return self.access_token, self.access_token_secret except Exception as e: raise TweepError(e)
def media_upload(self, filename, *args, **kwargs): """ :reference: https://dev.twitter.com/rest/reference/post/media/upload :reference https://dev.twitter.com/rest/reference/post/media/upload-chunked :allowed_param: """ f = kwargs.pop('file', None) mime, _ = mimetypes.guess_type(filename) size = getfilesize(filename, f) if mime in IMAGE_MIMETYPES and size < self.max_size_standard: return self.image_upload(filename, file=f, *args, **kwargs) elif mime in CHUNKED_MIMETYPES: return self.upload_chunked(filename, file=f, *args, **kwargs) else: raise TweepError("Can't upload media with mime type %s" % mime)
def post(self, url, data=None, json=None, **kwargs): kwargs['auth'] = self.oauth response = requests.post(url=url, data=data, json=json, **kwargs) if response.status_code and not 200 <= response.status_code < 300: try: error_msg, api_error_code = \ JSONParser().parse_error(response.text) except Exception: error_msg = "Twitter error response: status code = %s" % response.status_code api_error_code = None if is_rate_limit_error_message(error_msg): raise RateLimitError(error_msg, response) else: raise TweepError(error_msg, response, api_code=api_error_code) return response
def sitestream(self, follow, stall_warnings=False, with_='user', replies=False, is_async=False): self.body = {} if self.running: raise TweepError('Stream object already connected!') self.url = '/%s/site.json' % STREAM_VERSION self.body['follow'] = u','.join(map(six.text_type, follow)) self.body['delimited'] = 'length' if stall_warnings: self.body['stall_warnings'] = stall_warnings if with_: self.body['with'] = with_ if replies: self.body['replies'] = replies self._start(is_async)
def test_get_followers_by_screen_name_error(self, mock_logger, mock_api, tweepy_cursor, mock_get_rate_limit): mock_get_rate_limit.return_value = (1, 2, 3) error_msg = "Could not authenticate you" resp = "32" tweepy_cursor.return_value.pages.side_effect = TweepError( error_msg, resp) resource = 'followers' path = '/followers/ids' screen_name = "Wiz" ids, requests = get_followers_by_screen_name(mock_api, screen_name) mock_get_rate_limit.assert_called_once_with(mock_api, screen_name, resource, path, 5000) self.assertEqual(ids, []) self.assertEqual(requests, 0) mock_logger.error.assert_called_with('Could not authenticate you')
def get_authorization_url(self, signin_with_twitter=False, access_type=None): """Get the authorization URL to redirect the user""" try: if signin_with_twitter: url = self._get_oauth_url('authenticate') if access_type: logging.warning( "Warning! Due to a Twitter API bug, signin_with_twitter " "and access_type don't always play nice together. Details: " "https://dev.twitter.com/discussions/21281") else: url = self._get_oauth_url('authorize') self.request_token = self._get_request_token( access_type=access_type) return self.oauth.authorization_url(url) except Exception as e: raise TweepError(e)
def _get_request_token(self): try: url = self._get_oauth_url('request_token') request = oauth.OAuthRequest.from_consumer_and_token( self._consumer, http_url=url, callback=self.callback) request.sign_request(self._sigmethod, self._consumer, None) if not self.proxy_url: resp = urlopen(Request(url, headers=request.to_header())) else: opener = urllib2.build_opener( urllib2.HTTPHandler(), urllib2.HTTPSHandler(), urllib2.ProxyHandler({ 'https': 'http://' + self.proxy, 'http': 'http://' + self.proxy })) resp = opener.open(Request(url, headers=request.to_header())) return oauth.OAuthToken.from_string(resp.read()) except Exception, e: raise TweepError(e)
def __init__(self, api, args, kargs): # If authentication is required and no credentials # are provided, throw an error. if self.require_auth and not api.auth: raise TweepError('Authentication required!') self.api = api self.post_data = kargs.pop('post_data', None) self.retry_count = kargs.pop('retry_count', api.retry_count) self.retry_delay = kargs.pop('retry_delay', api.retry_delay) self.retry_errors = kargs.pop('retry_errors', api.retry_errors) self.headers = kargs.pop('headers', {}) self.build_parameters(args, kargs) # Pick correct URL root to use if self.upload_api: self.api_root = api.upload_root elif self.search_api: self.api_root = api.search_root else: self.api_root = api.api_root # Perform any path variable substitution self.build_path() if api.secure: self.scheme = 'https://' else: self.scheme = 'http://' if self.upload_api: self.host = api.upload_host elif self.search_api: self.host = api.search_host else: self.host = api.host # Manually set Host header to fix an issue in python 2.5 # or older where Host is set including the 443 port. # This causes Twitter to issue 301 redirect. # See Issue https://github.com/tweepy/tweepy/issues/12 self.headers['Host'] = self.host
def get_xauth_access_token(self, username, password): """ Get an access token from an username and password combination. In order to get this working you need to create an app at http://twitter.com/apps, after that send a mail to [email protected] and request activation of xAuth for it. """ try: url = self._get_oauth_url('access_token') oauth = OAuth1(self.consumer_key, client_secret=self.consumer_secret) r = requests.post(url=url, auth=oauth, headers={'x_auth_mode': 'client_auth', 'x_auth_username': username, 'x_auth_password': password}) credentials = parse_qs(r.content) return credentials.get('oauth_token')[0], credentials.get('oauth_token_secret')[0] except Exception as e: raise TweepError(e)
def parse(self, method, payload): try: if method.payload_type is None: return model = getattr(self.model_factory, method.payload_type) except AttributeError: raise TweepError('No model for this payload type: %s' % method.payload_type) json = JSONParser.parse(self, method, payload) if isinstance(json, tuple): json, cursors = json else: cursors = None if method.payload_list: result = model.parse_list(method.api, json) else: result = model.parse(method.api, json) if cursors: return result, cursors else: return result
def get_access_token(self, verifier=None): """ After user has authorized the request token, get access token with user supplied verifier. """ try: # build request request = oauth.OAuthRequest.from_consumer_and_token( self._consumer, token=self.request_token, http_url=self.ACCESS_TOKEN_URL, verifier=str(verifier)) request.sign_request(self._sigmethod, self._consumer, self.request_token) # send request resp = urlopen( Request(self.ACCESS_TOKEN_URL, headers=request.to_header())) self.access_token = oauth.OAuthToken.from_string(resp.read()) return self.access_token except Exception, e: raise TweepError(e)
def _read_loop(self, resp): buf = ReadBuffer(resp.raw, self.chunk_size) while self.running: length = 0 while True: line = buf.read_line().strip() if not line: pass # keep-alive new lines are expected elif line.isdigit(): length = int(line) break else: raise TweepError( 'Expecting length, unexpected value found') next_status_obj = buf.read_len(length) if self.running: self._data(next_status_obj) if resp.raw._fp.isclosed(): self.on_closed(resp)
def __init__(self, bearer_token=None, consumer_key=None, consumer_secret=None): if bearer_token: self._bearer_token = bearer_token else: self._bearer_token = '' self.consumer_key = consumer_key self.consumer_secret = consumer_secret if self.consumer_key and self.consumer_secret: resp = requests.post(self._get_oauth_url('token'), auth=(self.consumer_key, self.consumer_secret), data={'grant_type': 'client_credentials'}) data = resp.json() if data.get('token_type') != 'bearer': raise TweepError('Expected token_type to equal "bearer", ' 'but got %s instead' % data.get('token_type')) self._bearer_token = data['access_token']
def check_status(self, media_id, processing_info): if processing_info is None: return state = processing_info['state'] if state == u'succeeded': return if state == u'failed': raise TweepError("Uploading video has failed.") check_after_secs = processing_info['check_after_secs'] time.sleep(check_after_secs) request_params = {'command': 'STATUS', 'media_id': media_id} req = requests.get(url=MEDIA_ENDPOINT_URL, params=request_params, auth=self.oauth) processing_info = req.json().get('processing_info', None) self.check_status(media_id, processing_info)
def test_is_subscribed_list(self): api_return = self.check_api_call_success( api='is_subscribed_list', params={ 'list_id': 123, 'user_id': 456 }, mock_api='show_list_subscriber', mock_api_params={ 'list_id': 123, 'user_id': 456 }, mock_api_return=MagicMock()) self.assertEqual(api_return, True) api_return = self.check_api_call_success( api='is_subscribed_list', params={ 'list_id': 123, 'user_id': 456 }, mock_api='show_list_subscriber', mock_api_params={ 'list_id': 123, 'user_id': 456 }, mock_api_return=None, mock_api_effect=TweepError( api_code=TWITTER_USER_IS_NOT_LIST_MEMBER_SUBSCRIBER, reason='unknown')) self.assertEqual(api_return, False) self.check_api_call_errors(api='is_subscribed_list', params={ 'list_id': 123, 'user_id': 456 }, mock_api='show_list_subscriber')
def __init__(self, *args, **kwargs): self.api = api = kwargs.pop('api') self.path = kwargs.pop('path') self.payload_type = kwargs.pop('payload_type', None) self.payload_list = kwargs.pop('payload_list', False) self.allowed_param = kwargs.pop('allowed_param', []) self.method = kwargs.pop('method', 'GET') self.require_auth = kwargs.pop('require_auth', False) self.upload_api = kwargs.pop('upload_api', False) self.use_cache = kwargs.pop('use_cache', True) self.session = requests.Session() # If authentication is required and no credentials # are provided, throw an error. if self.require_auth and not api.auth: raise TweepError('Authentication required!') self.post_data = kwargs.pop('post_data', None) self.json_payload = kwargs.pop('json_payload', None) self.return_cursors = kwargs.pop('return_cursors', False) self.parser = kwargs.pop('parser', api.parser) self.headers = kwargs.pop('headers', {}) self.build_parameters(args, kwargs) # Pick correct URL root to use if self.upload_api: self.api_root = api.upload_root else: self.api_root = api.api_root if self.upload_api: self.host = api.upload_host else: self.host = api.host # Monitoring rate limits self._remaining_calls = None self._reset_time = None
def parse(self, method, payload): try: json = self.json_lib.loads(payload) except Exception as e: raise TweepError('Failed to parse JSON payload: %s' % e) needs_cursors = 'cursor' in method.session.params or \ 'tweepy_dmcursor' in method.session.headers if needs_cursors and isinstance(json, dict) \ and 'previous_cursor' in json \ and 'next_cursor' in json: cursors = json['previous_cursor'], json['next_cursor'] return json, cursors elif needs_cursors and isinstance(json, dict) \ and 'next_cursor' in json \ and 'previous_cursor' not in json: cursors = None, json['next_cursor'] return json, cursors elif needs_cursors and isinstance(json,dict): cursors = None, 0 return json, cursors else: return json
def parse(self, method, payload): try: if PY_MAJOR_VERSION == 2: payload = payload.read() json = self.json_lib.loads(payload) else: encoding = payload.headers.get_content_charset() body = payload.readall().decode(encoding) json = self.json_lib.loads(body) except Exception as e: raise TweepError('Failed to parse JSON payload: %s' % e) if PY_MAJOR_VERSION == 2: needsCursors = method.parameters.has_key('cursor') else: needsCursors = 'cursor' in method.parameters if needsCursors and isinstance( json, dict) and 'previous_cursor' in json and 'next_cursor' in json: cursors = json['previous_cursor'], json['next_cursor'] return json, cursors else: return json
def retweet(self, is_async=False): self.session.params = {'delimited': 'length'} if self.running: raise TweepError('Stream object already connected!') self.url = '/%s/statuses/retweet.json' % STREAM_VERSION self._start(is_async)