[Admin] don't select related objects in podcasts admin
[mygpo.git] / mygpo / flattr.py
blob4a8d3c7427f5f38d298c226bbd262161edc5722d
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.core.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, is_secure):
39 self.user = user
40 self.domain = domain
41 self.is_secure = is_secure
44 def _get_callback(self):
45 return 'http{s}://{domain}{callback}'.format(
46 s='s' if self.is_secure else '',
47 domain=self.domain,
48 callback=reverse('flattr-token'))
51 def request(self, url, data=None):
52 headers = {'Content-Type': 'application/json'}
54 if url == self.OAUTH_TOKEN_URL:
55 # Inject username and password into the request URL
56 url = utils.url_add_authentication(url, settings.FLATTR_KEY,
57 settings.FLATTR_SECRET)
58 elif self.user.profile.settings.get_setting('flattr_token', ''):
59 headers['Authorization'] = 'Bearer ' + self.user.profile.settings.get_wksetting(FLATTR_TOKEN)
61 if data is not None:
62 data = json.dumps(data)
64 try:
65 response = utils.urlopen(url, headers, data)
66 except urllib2.HTTPError, error:
67 return {'_gpodder_statuscode': error.getcode()}
68 except urllib2.URLError, error:
69 return {'_gpodder_no_connection': False}
71 if response.getcode() == 200:
72 return json.loads(response.read())
74 return {'_gpodder_statuscode': response.getcode()}
76 def get_auth_url(self):
77 return self.AUTH_URL_TEMPLATE % {
78 'client_id': settings.FLATTR_KEY,
79 'redirect_uri': self._get_callback(),
82 def has_token(self):
83 return bool(self.user.profile.settings.get_wksetting(FLATTR_TOKEN))
85 def process_retrieved_code(self, url):
86 url_parsed = urlparse.urlparse(url)
87 query = urlparse.parse_qs(url_parsed.query)
89 if 'code' in query:
90 code = query['code'][0]
91 token = self._request_access_token(code)
92 return token
94 return False
96 def _request_access_token(self, code):
97 request_url = 'https://flattr.com/oauth/token'
99 params = {
100 'code': code,
101 'grant_type': 'authorization_code',
102 'redirect_uri': self._get_callback(),
105 content = self.request(self.OAUTH_TOKEN_URL, data=params)
106 return content.get('access_token', '')
109 def get_thing_info(self, payment_url):
110 """Get information about a Thing on Flattr
112 Return a tuple (flattrs, flattred):
114 flattrs ... The number of Flattrs this thing received
115 flattred ... True if this user already flattred this thing
117 if not self.user.profile.settings.get_wksetting(FLATTR_TOKEN):
118 return (0, False)
120 quote_url = urllib.quote_plus(utils.sanitize_encoding(payment_url))
121 url = self.THING_INFO_URL_TEMPLATE % {'url': quote_url}
122 data = self.request(url)
123 return (int(data.get('flattrs', 0)), bool(data.get('flattred', False)))
126 def get_auth_username(self):
127 if not self.user.profile.settings.get_wksetting(FLATTR_TOKEN):
128 return ''
130 data = self.request(self.USER_INFO_URL)
131 return data.get('username', '')
134 def flattr_url(self, payment_url):
135 """Flattr an object given its Flattr payment URL
137 Returns a tuple (success, message):
139 success ... True if the item was Flattr'd
140 message ... The success or error message
142 params = {
143 'url': payment_url
146 content = self.request(self.FLATTR_URL, data=params)
148 if '_gpodder_statuscode' in content:
149 status_code = content['_gpodder_statuscode']
150 if status_code == 401:
151 return (False, _('Not enough means to flattr'))
152 elif status_code == 404:
153 return (False, _('Item does not exist on Flattr'))
154 elif status_code == 403:
155 return (False, _('Already flattred or own item'))
156 else:
157 return (False, _('Invalid request'))
159 if '_gpodder_no_connection' in content:
160 return (False, _('No internet connection'))
162 return (True, content.get('description', _('No description')))
165 def get_autosubmit_url(self, thing):
166 """ returns the auto-submit URL for the given FlattrThing """
168 publish_username = self.user.profile.settings.get_wksetting(FLATTR_USERNAME)
170 if not publish_username:
171 return None
173 URL_TEMPLATE = 'https://flattr.com/submit/auto?user_id=%s' % (publish_username,)
175 if not thing.url:
176 raise ValueError('Thing must at least have an url')
178 optional_args = set(thing._fields) - set(['url'])
180 args = [(u'url', self.domain + thing.url)]
181 args += [(arg, getattr(thing, arg, None)) for arg in optional_args]
182 args = filter(lambda (k, v): v, args) # filter out empty arguments
184 # TODO: check encoding
185 args = [(k, v.encode('utf-8')) for (k, v) in args]
187 args_str = urllib.urlencode(args)
189 autosubmit = URL_TEMPLATE + '&' + args_str
191 return autosubmit
194 # A thing that can be flattred by other Flattr users
195 FlattrThing = namedtuple('FlattrThing', 'url title description language tags ' +
196 'hidden category')