add Flattr and auto-flattr support
[mygpo.git] / mygpo / flattr.py
blob5863c5fccb42376110df0365e8b68f7c80ada0e0
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
11 from django.conf import settings
12 from django.core.urlresolvers import reverse
14 from mygpo.json import json
15 from mygpo.users.settings import FLATTR_TOKEN
16 from mygpo import utils
17 from django.utils.translation import ugettext as _
20 class Flattr(object):
21 """ a Flattr client """
23 # OAuth URLs
24 OAUTH_BASE = 'https://flattr.com/oauth'
25 AUTH_URL_TEMPLATE = (OAUTH_BASE + '/authorize?scope=flattr&' +
26 'response_type=code&client_id=%(client_id)s&' +
27 'redirect_uri=%(redirect_uri)s')
28 OAUTH_TOKEN_URL = OAUTH_BASE + '/token'
30 # REST API URLs
31 API_BASE = 'https://api.flattr.com/rest/v2'
32 USER_INFO_URL = API_BASE + '/user'
33 FLATTR_URL = API_BASE + '/flattr'
34 THING_INFO_URL_TEMPLATE = API_BASE + '/things/lookup/?url=%(url)s'
37 def __init__(self, user, domain):
38 self.user = user
39 self.domain = domain
42 def _get_callback(self):
43 return 'http://' + self.domain + reverse('flattr-token')
46 def request(self, url, data=None):
47 headers = {'Content-Type': 'application/json'}
49 if url == self.OAUTH_TOKEN_URL:
50 # Inject username and password into the request URL
51 url = utils.url_add_authentication(url, settings.FLATTR_KEY,
52 settings.FLATTR_SECRET)
53 elif self.user.settings.get('flattr_token', ''):
54 headers['Authorization'] = 'Bearer ' + self.user.get_wksetting(FLATTR_TOKEN)
56 if data is not None:
57 data = json.dumps(data)
59 try:
60 response = utils.urlopen(url, headers, data)
61 except urllib2.HTTPError, error:
62 return {'_gpodder_statuscode': error.getcode()}
63 except urllib2.URLError, error:
64 return {'_gpodder_no_connection': False}
66 if response.getcode() == 200:
67 return json.loads(response.read())
69 return {'_gpodder_statuscode': response.getcode()}
71 def get_auth_url(self):
72 return self.AUTH_URL_TEMPLATE % {
73 'client_id': settings.FLATTR_KEY,
74 'redirect_uri': self._get_callback(),
77 def has_token(self):
78 return bool(self.user.get_wksetting(FLATTR_TOKEN))
80 def process_retrieved_code(self, url):
81 url_parsed = urlparse.urlparse(url)
82 query = urlparse.parse_qs(url_parsed.query)
84 if 'code' in query:
85 code = query['code'][0]
86 token = self._request_access_token(code)
87 return token
89 return False
91 def _request_access_token(self, code):
92 request_url = 'https://flattr.com/oauth/token'
94 params = {
95 'code': code,
96 'grant_type': 'authorization_code',
97 'redirect_uri': self._get_callback(),
100 content = self.request(self.OAUTH_TOKEN_URL, data=params)
101 return content.get('access_token', '')
104 def get_thing_info(self, payment_url):
105 """Get information about a Thing on Flattr
107 Return a tuple (flattrs, flattred):
109 flattrs ... The number of Flattrs this thing received
110 flattred ... True if this user already flattred this thing
112 if not self.user.get_wksetting(FLATTR_TOKEN):
113 return (0, False)
115 quote_url = urllib.quote_plus(utils.sanitize_encoding(payment_url))
116 url = self.THING_INFO_URL_TEMPLATE % {'url': quote_url}
117 data = self.request(url)
118 return (int(data.get('flattrs', 0)), bool(data.get('flattred', False)))
121 def get_auth_username(self):
122 if not self.user.get_wksetting(FLATTR_TOKEN):
123 return ''
125 data = self.request(self.USER_INFO_URL)
126 return data.get('username', '')
129 def flattr_url(self, payment_url):
130 """Flattr an object given its Flattr payment URL
132 Returns a tuple (success, message):
134 success ... True if the item was Flattr'd
135 message ... The success or error message
137 params = {
138 'url': payment_url
141 content = self.request(self.FLATTR_URL, data=params)
143 if '_gpodder_statuscode' in content:
144 status_code = content['_gpodder_statuscode']
145 if status_code == 401:
146 return (False, _('Not enough means to flattr'))
147 elif status_code == 404:
148 return (False, _('Item does not exist on Flattr'))
149 elif status_code == 403:
150 return (False, _('Already flattred or own item'))
151 else:
152 return (False, _('Invalid request'))
154 if '_gpodder_no_connection' in content:
155 return (False, _('No internet connection'))
157 return (True, content.get('description', _('No description')))