use https in Flattr callbacks
[mygpo.git] / mygpo / flattr.py
blob99e5c4d6b16c86343a635d1847575590c49f2078
1 # -*- coding: utf-8 -*-
3 # Flattr integration
4 # based on flattr.py from gPodder by Bernd Schlapsi <brot@gmx.info>
7 import urllib
8 import urllib2
9 import urlparse
10 from collections import namedtuple
12 from django.conf import settings
13 from django.core.urlresolvers import reverse
15 from mygpo.json import json
16 from mygpo.users.settings import FLATTR_TOKEN, FLATTR_USERNAME
17 from mygpo import utils
18 from django.utils.translation import ugettext as _
21 class Flattr(object):
22 """ a Flattr client """
24 # OAuth URLs
25 OAUTH_BASE = 'https://flattr.com/oauth'
26 AUTH_URL_TEMPLATE = (OAUTH_BASE + '/authorize?scope=flattr&' +
27 'response_type=code&client_id=%(client_id)s&' +
28 'redirect_uri=%(redirect_uri)s')
29 OAUTH_TOKEN_URL = OAUTH_BASE + '/token'
31 # REST API URLs
32 API_BASE = 'https://api.flattr.com/rest/v2'
33 USER_INFO_URL = API_BASE + '/user'
34 FLATTR_URL = API_BASE + '/flattr'
35 THING_INFO_URL_TEMPLATE = API_BASE + '/things/lookup/?url=%(url)s'
38 def __init__(self, user, domain):
39 self.user = user
40 self.domain = domain
43 def _get_callback(self):
44 return 'https://' + self.domain + reverse('flattr-token')
47 def request(self, url, data=None):
48 headers = {'Content-Type': 'application/json'}
50 if url == self.OAUTH_TOKEN_URL:
51 # Inject username and password into the request URL
52 url = utils.url_add_authentication(url, settings.FLATTR_KEY,
53 settings.FLATTR_SECRET)
54 elif self.user.settings.get('flattr_token', ''):
55 headers['Authorization'] = 'Bearer ' + self.user.get_wksetting(FLATTR_TOKEN)
57 if data is not None:
58 data = json.dumps(data)
60 try:
61 response = utils.urlopen(url, headers, data)
62 except urllib2.HTTPError, error:
63 return {'_gpodder_statuscode': error.getcode()}
64 except urllib2.URLError, error:
65 return {'_gpodder_no_connection': False}
67 if response.getcode() == 200:
68 return json.loads(response.read())
70 return {'_gpodder_statuscode': response.getcode()}
72 def get_auth_url(self):
73 return self.AUTH_URL_TEMPLATE % {
74 'client_id': settings.FLATTR_KEY,
75 'redirect_uri': self._get_callback(),
78 def has_token(self):
79 return bool(self.user.get_wksetting(FLATTR_TOKEN))
81 def process_retrieved_code(self, url):
82 url_parsed = urlparse.urlparse(url)
83 query = urlparse.parse_qs(url_parsed.query)
85 if 'code' in query:
86 code = query['code'][0]
87 token = self._request_access_token(code)
88 return token
90 return False
92 def _request_access_token(self, code):
93 request_url = 'https://flattr.com/oauth/token'
95 params = {
96 'code': code,
97 'grant_type': 'authorization_code',
98 'redirect_uri': self._get_callback(),
101 content = self.request(self.OAUTH_TOKEN_URL, data=params)
102 return content.get('access_token', '')
105 def get_thing_info(self, payment_url):
106 """Get information about a Thing on Flattr
108 Return a tuple (flattrs, flattred):
110 flattrs ... The number of Flattrs this thing received
111 flattred ... True if this user already flattred this thing
113 if not self.user.get_wksetting(FLATTR_TOKEN):
114 return (0, False)
116 quote_url = urllib.quote_plus(utils.sanitize_encoding(payment_url))
117 url = self.THING_INFO_URL_TEMPLATE % {'url': quote_url}
118 data = self.request(url)
119 return (int(data.get('flattrs', 0)), bool(data.get('flattred', False)))
122 def get_auth_username(self):
123 if not self.user.get_wksetting(FLATTR_TOKEN):
124 return ''
126 data = self.request(self.USER_INFO_URL)
127 return data.get('username', '')
130 def flattr_url(self, payment_url):
131 """Flattr an object given its Flattr payment URL
133 Returns a tuple (success, message):
135 success ... True if the item was Flattr'd
136 message ... The success or error message
138 params = {
139 'url': payment_url
142 content = self.request(self.FLATTR_URL, data=params)
144 if '_gpodder_statuscode' in content:
145 status_code = content['_gpodder_statuscode']
146 if status_code == 401:
147 return (False, _('Not enough means to flattr'))
148 elif status_code == 404:
149 return (False, _('Item does not exist on Flattr'))
150 elif status_code == 403:
151 return (False, _('Already flattred or own item'))
152 else:
153 return (False, _('Invalid request'))
155 if '_gpodder_no_connection' in content:
156 return (False, _('No internet connection'))
158 return (True, content.get('description', _('No description')))
161 def get_autosubmit_url(self, thing):
162 """ returns the auto-submit URL for the given FlattrThing """
164 publish_username = self.user.get_wksetting(FLATTR_USERNAME)
166 if not publish_username:
167 return None
169 URL_TEMPLATE = 'https://flattr.com/submit/auto?user_id=%s' % (publish_username,)
171 if not thing.url:
172 raise ValueError('Thing must at least have an url')
174 optional_args = set(thing._fields) - set(['url'])
176 args = [('url', self.domain + thing.url)]
177 args += [(arg, getattr(thing, arg, None)) for arg in optional_args]
178 args = filter(lambda (k, v): v, args) # filter out empty arguments
180 args_str = urllib.urlencode(args)
182 autosubmit = URL_TEMPLATE + '&' + args_str
184 return autosubmit
187 # A thing that can be flattred by other Flattr users
188 FlattrThing = namedtuple('FlattrThing', 'url title description language tags ' +
189 'hidden category')