1 # -*- coding: utf-8 -*-
4 # based on flattr.py from gPodder by Bernd Schlapsi <brot@gmx.info>
8 import urllib
.request
, urllib
.parse
, urllib
.error
9 import urllib
.request
, urllib
.error
, urllib
.parse
11 from collections
import namedtuple
13 from django
.conf
import settings
14 from django
.urls
import reverse
16 from mygpo
.users
.settings
import FLATTR_TOKEN
, FLATTR_USERNAME
17 from mygpo
import utils
18 from django
.utils
.translation
import ugettext
as _
22 """ a Flattr client """
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'
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
):
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 '',
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
)
62 data
= json
.dumps(data
).encode('utf-8')
65 response
= utils
.urlopen(url
, headers
, data
)
66 except urllib
.error
.HTTPError
as error
:
67 return {'_gpodder_statuscode': error
.getcode()}
68 except urllib
.error
.URLError
as error
:
69 return {'_gpodder_no_connection': False}
71 if response
.getcode() == 200:
72 return json
.loads(response
.read().decode('utf-8'))
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
(),
83 return bool(self
.user
.profile
.settings
.get_wksetting(FLATTR_TOKEN
))
85 def process_retrieved_code(self
, url
):
86 url_parsed
= urllib
.parse
.urlparse(url
)
87 query
= urllib
.parse
.parse_qs(url_parsed
.query
)
90 code
= query
['code'][0]
91 token
= self
._request
_access
_token
(code
)
96 def _request_access_token(self
, code
):
97 request_url
= 'https://flattr.com/oauth/token'
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
):
120 quote_url
= urllib
.parse
.quote_plus(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
):
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
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'))
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
:
173 URL_TEMPLATE
= 'https://flattr.com/submit/auto?user_id=%s' % (publish_username
,)
176 raise ValueError('Thing must at least have an url')
178 optional_args
= set(thing
._fields
) - set(['url'])
180 args
= [('url', self
.domain
+ thing
.url
)]
181 args
+= [(arg
, getattr(thing
, arg
, None)) for arg
in optional_args
]
182 args
= filter(lambda kv
: kv
[1], 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
.parse
.urlencode(args
)
189 autosubmit
= URL_TEMPLATE
+ '&' + args_str
194 # A thing that can be flattred by other Flattr users
195 FlattrThing
= namedtuple('FlattrThing', 'url title description language tags ' +