twitter.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. # pylint: disable=too-many-instance-attributes
  2. # pylint: disable=unused-variable
  3. # pylint: disable=too-many-arguments
  4. '''
  5. twitter.py contains a handful of methods for interacting
  6. with Twitter data and returning the responses as JSON.
  7. '''
  8. import urlparse
  9. import oauth2 as oauth
  10. import requests
  11. import base64, random
  12. import urllib
  13. import binascii
  14. import time, collections, hmac, hashlib
  15. import simplejson as json2
  16. import codecs
  17. import json
  18. REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token'
  19. ACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token'
  20. AUTHORIZE_URL = 'https://api.twitter.com/oauth/authorize'
  21. class TwitterOauthClient(object):
  22. '''
  23. Python Client for Twitter API.
  24. '''
  25. oauth_token = None
  26. oauth_token_secret = None
  27. username = None
  28. is_authorized = False
  29. def __init__(self, consumer_key, consumer_secret, access_token, access_token_secret):
  30. '''
  31. Parameters:
  32. consumer_key: String
  33. - The consumer_key from registering application
  34. on Instagram.
  35. consumer_secret: String
  36. - The consumer_secret from registering application
  37. on Instagram.
  38. '''
  39. self.consumer_key = consumer_key
  40. self.consumer_secret = consumer_secret
  41. self.access_token = access_token
  42. self.access_token_secret = access_token_secret
  43. self.consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
  44. def get_authorize_url(self):
  45. '''
  46. Obtained oauth_token and oauth_token_secret from request_token_url,
  47. returns an authorize url.
  48. From the redirect url, we obtain the oauth verifier.
  49. Returns:
  50. authURL: String
  51. - The authorization url.
  52. '''
  53. client = oauth.Client(self.consumer)
  54. resp, content = client.request(REQUEST_TOKEN_URL, 'GET')
  55. #if int(resp['status']) != 200:
  56. # raise Exception('Invalid response %s' %resp['status'])
  57. requestToken = dict(urlparse.parse_qsl(content))
  58. #temporary
  59. self.oauth_token = requestToken['oauth_token']
  60. self.oauth_token_secret = requestToken['oauth_token_secret']
  61. #print self.oauth_token
  62. #link to authorize app access twitter data and return to twitter api example page
  63. redirectUri = '&redirect_uri=http%3A%2F%2Flocalhost%3A8000/hackathon/twitter/'
  64. authURL = AUTHORIZE_URL+"?oauth_token="+self.oauth_token+redirectUri
  65. return authURL
  66. def get_access_token_url(self, oauthVerifier):
  67. '''
  68. Get access token from redirect url.
  69. Parameters:
  70. oauthVerifier: String
  71. - A paramater retrieved from scraping the redirect url.
  72. Returns:
  73. data: Dictionary
  74. - A dictionary containing recent tagged 120 media
  75. counts data pertaining to each media.
  76. '''
  77. token = oauth.Token(self.oauth_token, self.oauth_token_secret)
  78. token.set_verifier(oauthVerifier)
  79. client = oauth.Client(self.consumer, token)
  80. resp, content = client.request(ACCESS_TOKEN_URL, 'POST')
  81. if int(resp['status']) != 200:
  82. raise Exception('Invalid response %s' %resp['status'])
  83. #print content
  84. accessToken = dict(urlparse.parse_qsl(content))
  85. #permanent
  86. self.oauth_token = accessToken['oauth_token']
  87. self.oauth_token_secret = accessToken['oauth_token_secret']
  88. self.username = accessToken['screen_name']
  89. self.is_authorized = True
  90. def get_tweets(self, tweet):
  91. '''
  92. Get tweets of relevant search query.
  93. '''
  94. method = 'get'
  95. link = 'https://api.twitter.com/1.1/search/tweets.json'
  96. linkParameters = {'q': tweet, 'count': '100', 'result_type': 'popular'}
  97. oauthParameters = getOauthParameters(
  98. self.consumer_key,
  99. self.access_token
  100. )
  101. oauthParameters['oauth_signature'] = generateSignature(
  102. method,
  103. link,
  104. linkParameters,
  105. oauthParameters,
  106. self.consumer_secret,
  107. self.access_token_secret
  108. )
  109. headers = {'Authorization': createAuthHeader(oauthParameters)}
  110. link += '?' + urllib.urlencode(linkParameters)
  111. req = requests.get(link, headers=headers)
  112. if int(req.status_code) != 200:
  113. raise Exception('Invalid response %s' %req.status_code)
  114. content = json2.loads(req.content)
  115. jsonlist = {}
  116. for contrib in content['statuses']:
  117. for e in contrib:
  118. if e == 'retweet_count':
  119. if contrib['user']['screen_name'] in jsonlist:
  120. jsonlist[contrib['user']['screen_name']][contrib[e]] = str(contrib['text'].encode('ascii', 'ignore'))
  121. else:
  122. jsonlist[contrib['user']['screen_name']] = { contrib[e]:str(contrib['text'].encode('ascii', 'ignore'))}
  123. return content['statuses'], json.dumps(jsonlist)
  124. def get_trends_available(self, yahooConsumerKey):
  125. '''
  126. Get the locations that Twitter has trending topic information for.
  127. '''
  128. method = 'get'
  129. link = 'https://api.twitter.com/1.1/trends/available.json'
  130. linkParameters = {}
  131. oauthParameters = getOauthParameters(
  132. self.consumer_key,
  133. self.access_token
  134. )
  135. oauthParameters['oauth_signature'] = generateSignature(
  136. method,
  137. link,
  138. linkParameters,
  139. oauthParameters,
  140. self.consumer_secret,
  141. self.access_token_secret
  142. )
  143. headers = {'Authorization': createAuthHeader(oauthParameters)}
  144. if linkParameters:
  145. link += '?'+urllib.urlencode(linkParameters)
  146. req = requests.get(link, headers=headers)
  147. #print req.status_code
  148. if int(req.status_code) != 200:
  149. raise Exception('Invalid response %s' %req.status_code)
  150. content = json2.loads(req.content)
  151. #print len(content)
  152. for place in content:
  153. for item in place:
  154. if item == 'url':
  155. url = place[item]+'/neighbors?appid='+yahooConsumerKey+'&format=json'
  156. requestNeighborData = requests.get(url)
  157. #print request_neighbor_data.status_code
  158. if requestNeighborData.status_code == 200:
  159. neighbor = json2.loads(requestNeighborData.content)
  160. else:
  161. neighbor = {}
  162. place['neighbor'] = neighbor
  163. #print place
  164. return content
  165. def percentEncode(string):
  166. '''
  167. Percent encode strings.
  168. '''
  169. return urllib.quote(string, safe='~')
  170. def getNonce():
  171. '''
  172. Generate unique token per request.
  173. '''
  174. nonce = base64.b64encode(''.join([str(random.randint(0, 9)) for i in range(24)]))
  175. return nonce
  176. def generateSignature(method, link, linkParameters, oauthParameters,
  177. oauthConsumerSecret, oauthTokenSecret=None):
  178. '''
  179. Generate signature.
  180. '''
  181. if linkParameters:
  182. newDict = dict(oauthParameters, **linkParameters)
  183. params = urllib.urlencode(collections.OrderedDict(sorted(newDict.items())))
  184. else:
  185. params = urllib.urlencode(collections.OrderedDict(sorted(oauthParameters.items())))
  186. #Create your Signature Base String
  187. signatureBaseString = (method.upper()+'&'+percentEncode(str(link))+'&'+percentEncode(params))
  188. #Get the signing key
  189. signingKey = createSigningKey(oauthConsumerSecret, oauthTokenSecret)
  190. return calculateSignature(signingKey, signatureBaseString)
  191. def calculateSignature(signingKey, signatureBaseString):
  192. '''
  193. Calculate signature using HMAC-SHA1 hashing algorithm.
  194. '''
  195. hashed = hmac.new(signingKey, signatureBaseString, hashlib.sha1)
  196. sig = binascii.b2a_base64(hashed.digest())[:-1]
  197. return percentEncode(sig)
  198. def createSigningKey(oauthConsumerSecret, oauthTokenSecret):
  199. '''
  200. Creates a key to sign the request with.
  201. '''
  202. signingKey = percentEncode(oauthConsumerSecret) + '&' + percentEncode(oauthTokenSecret)
  203. return signingKey
  204. def createAuthHeader(parameters):
  205. '''
  206. Format authorization header with oath parameters.
  207. '''
  208. orderedParameters = collections.OrderedDict(sorted(parameters.items()))
  209. authHeader = ('%s="%s"' % (k, v) for k, v in orderedParameters.iteritems())
  210. return "OAuth " + ', '.join(authHeader)
  211. def getOauthParameters(consumerKey, accessToken):
  212. '''
  213. Returns parameters for making requests.
  214. '''
  215. oauthParameters = {
  216. 'oauth_timestamp': str(int(time.time())),
  217. 'oauth_signature_method': "HMAC-SHA1",
  218. 'oauth_version': "1.0",
  219. 'oauth_token': accessToken,
  220. 'oauth_nonce': getNonce(),
  221. 'oauth_consumer_key': consumerKey
  222. }
  223. return oauthParameters