11# coding: utf-8
22from __future__ import print_function , unicode_literals
33
4+ import logging
45from uuid import uuid4
6+ from datetime import datetime
57from operator import itemgetter
68try : # python2
79 from urlparse import urljoin
1113
1214import requests
1315
14- from .consts import BASE_URL , LOGIN_URL
16+ from .consts import BASE_URL
1517from .exception import NotLoginError , APIError
1618from .article import Article
1719from .subscription import Subscription
1820
1921
22+ LOGGER = logging .getLogger (__name__ )
23+
24+
2025class 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