Skip to content

Commit 2763629

Browse files
committed
use OAuth 2.0 in InoreaderClient
1 parent c250e5a commit 2763629

File tree

1 file changed

+53
-33
lines changed

1 file changed

+53
-33
lines changed

inoreader/client.py

Lines changed: 53 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# coding: utf-8
22
from __future__ import print_function, unicode_literals
33

4+
import logging
45
from uuid import uuid4
6+
from datetime import datetime
57
from operator import itemgetter
68
try: # python2
79
from urlparse import urljoin
@@ -11,32 +13,67 @@
1113

1214
import requests
1315

14-
from .consts import BASE_URL, LOGIN_URL
16+
from .consts import BASE_URL
1517
from .exception import NotLoginError, APIError
1618
from .article import Article
1719
from .subscription import Subscription
1820

1921

22+
LOGGER = logging.getLogger(__name__)
23+
24+
2025
class InoreaderClient(object):
2126

22-
def __init__(self, app_id, app_key, userid=None, auth_token=None):
27+
# paths
28+
TOKEN_PATH = '/oauth2/token'
29+
30+
def __init__(self, app_id, app_key, access_token, refresh_token,
31+
expires_at, userid=None, config_manager=None):
2332
self.app_id = app_id
2433
self.app_key = app_key
25-
self.auth_token = auth_token
34+
self.access_token = access_token
35+
self.refresh_token = refresh_token
36+
self.expires_at = float(expires_at)
2637
self.session = requests.Session()
2738
self.session.headers.update({
2839
'AppId': self.app_id,
2940
'AppKey': self.app_key,
30-
'Authorization': 'GoogleLogin auth={}'.format(self.auth_token)
41+
'Authorization': 'Bearer {}'.format(self.access_token)
3142
})
32-
if userid:
33-
self.userid = userid
34-
else:
35-
self.userid = None if not self.auth_token else self.userinfo()['userId']
43+
self.userid = userid or self.userinfo()['userId']
44+
self.config_manager = config_manager
45+
if self.userid and self.config_manager and not self.config_manager.user_id:
46+
self.config_manager.user_id = self.userid
47+
self.config_manager.save()
48+
49+
def check_token(self):
50+
now = datetime.now().timestamp()
51+
if now >= self.expires_at:
52+
self.refresh_access_token()
53+
54+
def refresh_access_token(self):
55+
url = urljoin(BASE_URL, self.TOKEN_PATH)
56+
payload = {
57+
'client_id': self.app_id,
58+
'client_secret': self.app_key,
59+
'grant_type': 'refresh_token',
60+
'refresh_token': self.refresh_token,
61+
}
62+
resp = requests.post(url, json=payload)
63+
response = resp.json()
64+
self.access_token = response['access_token']
65+
self.refresh_token = response['refresh_token']
66+
self.expires_at = datetime.now().timestamp() + response['expires_in']
67+
self.session.headers['Authorization'] = 'Bear {}'.format(self.access_token)
68+
69+
if self.config_manager:
70+
self.config_manager.access_token = self.access_token
71+
self.config_manager.refresh_token = self.refresh_token
72+
self.config_manager.expires_at = self.expires_at
73+
self.config_manager.save()
3674

3775
def userinfo(self):
38-
if not self.auth_token:
39-
raise NotLoginError
76+
self.check_token()
4077

4178
url = urljoin(BASE_URL, 'user-info')
4279
resp = self.session.post(url)
@@ -45,20 +82,8 @@ def userinfo(self):
4582

4683
return resp.json()
4784

48-
def login(self, username, password):
49-
resp = self.session.get(LOGIN_URL, params={'Email': username, 'Passwd': password})
50-
if resp.status_code != 200:
51-
return False
52-
53-
for line in resp.text.split('\n'):
54-
if line.startswith('Auth'):
55-
self.auth_token = line.replace('Auth=', '').strip()
56-
57-
return bool(self.auth_token)
58-
5985
def get_folders(self):
60-
if not self.auth_token:
61-
raise NotLoginError
86+
self.check_token()
6287

6388
url = urljoin(BASE_URL, 'tag/list')
6489
params = {'types': 1, 'counts': 1}
@@ -78,8 +103,7 @@ def get_folders(self):
78103
return folders
79104

80105
def get_tags(self):
81-
if not self.auth_token:
82-
raise NotLoginError
106+
self.check_token()
83107

84108
url = urljoin(BASE_URL, 'tag/list')
85109
params = {'types': 1, 'counts': 1}
@@ -99,8 +123,7 @@ def get_tags(self):
99123
return tags
100124

101125
def get_subscription_list(self):
102-
if not self.auth_token:
103-
raise NotLoginError
126+
self.check_token()
104127

105128
url = urljoin(BASE_URL, 'subscription/list')
106129
resp = self.session.get(url)
@@ -119,8 +142,7 @@ def get_stream_contents(self, stream_id, c=''):
119142
break
120143

121144
def __get_stream_contents(self, stream_id, continuation=''):
122-
if not self.auth_token:
123-
raise NotLoginError
145+
self.check_token()
124146

125147
url = urljoin(BASE_URL, 'stream/contents/' + quote_plus(stream_id))
126148
params = {
@@ -139,8 +161,7 @@ def __get_stream_contents(self, stream_id, continuation=''):
139161
return resp.json()['items'], None
140162

141163
def fetch_unread(self, folder=None, tags=None):
142-
if not self.auth_token:
143-
raise NotLoginError
164+
self.check_token()
144165

145166
url = urljoin(BASE_URL, 'stream/contents/')
146167
if folder:
@@ -183,8 +204,7 @@ def fetch_unread(self, folder=None, tags=None):
183204
continuation = resp.json().get('continuation')
184205

185206
def add_general_label(self, articles, label):
186-
if not self.auth_token:
187-
raise NotLoginError
207+
self.check_token()
188208

189209
url = urljoin(BASE_URL, 'edit-tag')
190210
for start in range(0, len(articles), 10):

0 commit comments

Comments
 (0)