8 from diaspy
import errors
11 """This module abstracts connection to pod.
16 """Object representing connection with the pod.
18 _token_regex
= re
.compile(r
'content="(.*?)"\s+name="csrf-token')
19 _userinfo_regex
= re
.compile(r
'window.current_user_attributes = ({.*})')
20 _userinfo_regex_2
= re
.compile(r
'gon.user=({.*});gon.preloads')
22 def __init__(self
, pod
, username
='', password
='', schema
='https'):
24 :param pod: The complete url of the diaspora pod to use.
26 :param username: The username used to log in.
28 :param password: The password used to log in.
32 self
._session
= requests
.Session()
36 self
._diaspora
_session
= ''
38 self
._setlogin
(username
, password
)
39 except requests
.exceptions
.MissingSchema
:
40 self
.pod
= '{0}://{1}'.format(schema
, self
.pod
)
41 warnings
.warn('schema was missing')
45 self
._setlogin
(username
, password
)
46 except Exception as e
:
47 raise errors
.LoginError('cannot create login data (caused by: {0})'.format(e
))
50 """Returns token string.
51 It will be easier to change backend if programs will just use:
53 instead of calling a specified method.
55 return self
._fetchtoken
()
57 def get(self
, string
, headers
={}, params
={}, direct
=False):
58 """This method gets data from session.
59 Performs additional checks if needed.
62 To obtain 'foo' from pod one should call `get('foo')`.
64 :param string: URL to get without the pod's URL and slash eg. 'stream'.
66 :param direct: if passed as True it will not be expanded
69 if not direct
: url
= '{0}/{1}'.format(self
.pod
, string
)
71 return self
._session
.get(url
, params
=params
, headers
=headers
)
73 def post(self
, string
, data
, headers
={}, params
={}):
74 """This method posts data to session.
75 Performs additional checks if needed.
78 To post to 'foo' one should call `post('foo', data={})`.
80 :param string: URL to post without the pod's URL and slash eg. 'status_messages'.
82 :param data: Data to post.
83 :param headers: Headers (optional).
85 :param params: Parameters (optional).
88 string
= '{0}/{1}'.format(self
.pod
, string
)
89 request
= self
._session
.post(string
, data
, headers
=headers
, params
=params
)
92 def put(self
, string
, data
=None, headers
={}, params
={}):
93 """This method PUTs to session.
95 string
= '{0}/{1}'.format(self
.pod
, string
)
96 if data
is not None: request
= self
._session
.put(string
, data
, headers
=headers
, params
=params
)
97 else: request
= self
._session
.put(string
, headers
=headers
, params
=params
)
100 def delete(self
, string
, data
, headers
={}):
101 """This method lets you send delete request to session.
102 Performs additional checks if needed.
104 :param string: URL to use.
106 :param data: Data to use.
107 :param headers: Headers to use (optional).
110 string
= '{0}/{1}'.format(self
.pod
, string
)
111 request
= self
._session
.delete(string
, data
=data
, headers
=headers
)
114 def _setlogin(self
, username
, password
):
115 """This function is used to set data for login.
118 It should be called before _login() function.
120 self
._login
_data
= {'user[username]': username
,
121 'user[password]': password
,
122 'authenticity_token': self
._fetchtoken
()}
125 """Handles actual login request.
126 Raises LoginError if login failed.
128 request
= self
.post('users/sign_in',
129 data
=self
._login
_data
)
130 if request
.status_code
not in [200, 201]:
131 raise errors
.LoginError('{0}: login failed'.format(request
.status_code
))
132 self
._diaspora
_session
= request
.cookies
['_diaspora_session']
134 def login(self
, username
='', password
=''):
135 """This function is used to log in to a pod.
136 Will raise LoginError if password or username was not specified.
138 if username
and password
: self
._setlogin
(username
, password
)
139 if not self
._login
_data
['user[username]'] or not self
._login
_data
['user[password]']:
140 raise errors
.LoginError('username and/or password is not specified')
142 self
._login
_data
= {}
145 """Logs out from a pod.
146 When logged out you can't do anything.
148 self
.get('users/sign_out')
151 def podswitch(self
, pod
, username
, password
):
152 """Switches pod from current to another one.
155 self
._setlogin
(username
, password
)
158 def getUserInfo(self
, fetch
=False):
159 """This function returns the current user's attributes.
161 :returns: dict -- json formatted user info.
163 request
= self
.get('bookmarklet')
164 userdata
= self
._userinfo
_regex
.search(request
.text
)
165 if userdata
is None: userdata
= self
._userinfo
_regex
_2.search(request
.text
)
166 if userdata
is None: raise errors
.DiaspyError('cannot find user data')
167 userdata
= userdata
.group(1)
168 warnings
.warn(userdata
)
169 return json
.loads(userdata
)
171 def _fetchtoken(self
):
172 """This method tries to get token string needed for authentication on D*.
174 :returns: token string
176 request
= self
.get('stream')
177 token
= self
._token
_regex
.search(request
.text
).group(1)
181 def get_token(self
, fetch
=True):
182 """This function returns a token needed for authentication in most cases.
183 **Notice:** using repr() is recommended method for getting token.
185 Each time it is run a _fetchtoken() is called and refreshed token is stored.
187 It is more safe to use than _fetchtoken().
188 By setting new you can request new token or decide to get stored one.
189 If no token is stored new one will be fetched anyway.
191 :returns: string -- token used to authenticate
194 if fetch
: self
._fetchtoken
()
195 if not self
._token
: self
._fetchtoken
()
196 except requests
.exceptions
.ConnectionError
as e
:
197 warnings
.warn('{0} was cought: reusing old token'.format(e
))
199 if not self
._token
: raise errors
.TokenError('cannot obtain token and no previous token found for reuse')
202 def getSessionToken(self
):
203 """Returns session token string (_diaspora_session).
205 return self
._diaspora
_session