Changes in login code and additions in diaspy/settings.py (don't use yet -
authorMarek Marecki <marekjm@taistelu.com>
Fri, 6 Sep 2013 19:44:20 +0000 (21:44 +0200)
committerMarek Marecki <marekjm@taistelu.com>
Fri, 6 Sep 2013 19:44:20 +0000 (21:44 +0200)
will reset your profile)

diaspy/connection.py
diaspy/settings.py

index 84d7d99dd96465830400989dca7f9a2562bb7027..c608d2c92614635cf2620749e0f471f68e41d888 100644 (file)
@@ -1,5 +1,10 @@
 #!/usr/bin/env python
 
+
+"""This module abstracts connection to pod.
+"""
+
+
 import re
 import requests
 import json
@@ -8,8 +13,7 @@ import warnings
 from diaspy import errors
 
 
-"""This module abstracts connection to pod.
-"""
+DEBUG = True
 
 
 class Connection():
@@ -19,7 +23,7 @@ class Connection():
     _userinfo_regex = re.compile(r'window.current_user_attributes = ({.*})')
     _userinfo_regex_2 = re.compile(r'gon.user=({.*});gon.preloads')
 
-    def __init__(self, pod, username='', password='', schema='https'):
+    def __init__(self, pod, username, password, schema='https'):
         """
         :param pod: The complete url of the diaspora pod to use.
         :type pod: str
@@ -30,22 +34,35 @@ class Connection():
         """
         self.pod = pod
         self._session = requests.Session()
-        self._login_data = {}
+        self._login_data = {'user[remember_me]': 1, 'utf8': '✓'}
         self._userdata = {}
         self._token = ''
         self._diaspora_session = ''
+        self._cookies = self._fetchcookies()
         try:
-            self._setlogin(username, password)
+            #self._setlogin(username, password)
+            self._login_data = {'user[username]': username,
+                                'user[password]': password,
+                                'authenticity_token': self._fetchtoken()}
+            success = True
         except requests.exceptions.MissingSchema:
             self.pod = '{0}://{1}'.format(schema, self.pod)
             warnings.warn('schema was missing')
+            success = False
         finally:
             pass
         try:
-            self._setlogin(username, password)
+            if not success:
+                self._login_data = {'user[username]': username,
+                                    'user[password]': password,
+                                    'authenticity_token': self._fetchtoken()}
         except Exception as e:
             raise errors.LoginError('cannot create login data (caused by: {0})'.format(e))
 
+    def _fetchcookies(self):
+        request = self.get('stream')
+        return request.cookies
+
     def __repr__(self):
         """Returns token string.
         It will be easier to change backend if programs will just use:
@@ -54,7 +71,7 @@ class Connection():
         """
         return self._fetchtoken()
 
-    def get(self, string, headers={}, params={}, direct=False):
+    def get(self, string, headers={}, params={}, direct=False, **kwargs):
         """This method gets data from session.
         Performs additional checks if needed.
 
@@ -68,9 +85,9 @@ class Connection():
         """
         if not direct: url = '{0}/{1}'.format(self.pod, string)
         else: url = string
-        return self._session.get(url, params=params, headers=headers)
+        return self._session.get(url, params=params, headers=headers, **kwargs)
 
-    def post(self, string, data, headers={}, params={}):
+    def post(self, string, data, headers={}, params={}, **kwargs):
         """This method posts data to session.
         Performs additional checks if needed.
 
@@ -86,18 +103,18 @@ class Connection():
         :type params: dict
         """
         string = '{0}/{1}'.format(self.pod, string)
-        request = self._session.post(string, data, headers=headers, params=params)
+        request = self._session.post(string, data, headers=headers, params=params, **kwargs)
         return request
 
-    def put(self, string, data=None, headers={}, params={}):
+    def put(self, string, data=None, headers={}, params={}, **kwargs):
         """This method PUTs to session.
         """
         string = '{0}/{1}'.format(self.pod, string)
-        if data is not None: request = self._session.put(string, data, headers=headers, params=params)
-        else: request = self._session.put(string, headers=headers, params=params)
+        if data is not None: request = self._session.put(string, data, headers=headers, params=params, **kwargs)
+        else: request = self._session.put(string, headers=headers, params=params, **kwargs)
         return request
 
-    def delete(self, string, data, headers={}):
+    def delete(self, string, data, headers={}, **kwargs):
         """This method lets you send delete request to session.
         Performs additional checks if needed.
 
@@ -108,7 +125,7 @@ class Connection():
         :type headers: dict
         """
         string = '{0}/{1}'.format(self.pod, string)
-        request = self._session.delete(string, data=data, headers=headers)
+        request = self._session.delete(string, data=data, headers=headers, **kwargs)
         return request
 
     def _setlogin(self, username, password):
@@ -126,20 +143,22 @@ class Connection():
         Raises LoginError if login failed.
         """
         request = self.post('users/sign_in',
-                            data=self._login_data)
-        if request.status_code not in [200, 201]:
+                            data=self._login_data,
+                            allow_redirects=False)
+        if request.status_code != 302:
             raise errors.LoginError('{0}: login failed'.format(request.status_code))
-        self._diaspora_session = request.cookies['_diaspora_session']
+        return request.status_code
 
-    def login(self, username='', password=''):
+    def login(self, remember_me=1):
         """This function is used to log in to a pod.
         Will raise LoginError if password or username was not specified.
         """
-        if username and password: self._setlogin(username, password)
         if not self._login_data['user[username]'] or not self._login_data['user[password]']:
             raise errors.LoginError('username and/or password is not specified')
-        self._login()
+        self._login_data['user[remember_me]'] = remember_me
+        status = self._login()
         self._login_data = {}
+        return status
 
     def logout(self):
         """Logs out from a pod.
@@ -174,6 +193,7 @@ class Connection():
         :returns: token string
         """
         request = self.get('stream')
+        if DEBUG: print('_fetchtoken(): status code:', request.status_code)
         token = self._token_regex.search(request.text).group(1)
         self._token = token
         return token
@@ -191,8 +211,7 @@ class Connection():
         :returns: string -- token used to authenticate
         """
         try:
-            if fetch: self._fetchtoken()
-            if not self._token: self._fetchtoken()
+            if fetch or not self._token: self._fetchtoken()
         except requests.exceptions.ConnectionError as e:
             warnings.warn('{0} was cought: reusing old token'.format(e))
         finally:
index 2cb9276247fb0411d31315c29156d74935967614..d68f0b31104205b06cec8a05db8a9f0d7b4f8d93 100644 (file)
@@ -11,6 +11,38 @@ import warnings
 from diaspy import errors, streams
 
 
+class Profile():
+    """Provides profile editing methods.
+    """
+    def __init__(self, connection):
+        self._connection = connection
+        self.data = {'utf-8': '✓',
+                     '_method': 'put',
+                     'profile[first_name]': '',
+                     'profile[last_name]': '',
+                     'profile[tag_string]': '',
+                     'tags': '',
+                     'file': '',
+                     'profile[bio]': '',
+                     'profile[location]': '',
+                     'profile[gender]': '',
+                     'profile[date][year]': '',
+                     'profile[date][month]': '',
+                     'profile[date][day]': '',
+                     }
+
+    def setName(self, first='', last=''):
+        """Set first name.
+        """
+        data = self.data
+        data['profile[first_name]'] = first
+        data['profile[last_name]'] = last
+        data['authenticity_token'] = repr(self._connection)
+        print(data)
+        request = self._connection.post('profile', data=data, allow_redirects=False)
+        return request.status_code
+
+
 class Settings():
     """This object is used to get access to user's settings on
     Diaspora* and provides interface for downloading user's stuff.
@@ -70,8 +102,8 @@ class Settings():
     def setEmail(self, email):
         """Changes user's email.
         """
-        data = {'_method': 'put', 'utf-8': '✓', 'user[email]': email, 'authenticity_token': repr(self._connection)}
-        request = self._connection.post('user')
+        data = {'_method': 'put', 'utf8': '✓', 'user[email]': email, 'authenticity_token': repr(self._connection)}
+        request = self._connection.post('user', data=data, allow_redirects=False)
 
     def getEmail(self):
         """Returns currently used email.
@@ -88,19 +120,20 @@ class Settings():
 
         :param lang: language identifier from getLanguages()
         """
-        data = {'_method': 'put', 'utf-8': '✓', 'user[language]': lang, 'authenticity_token': repr(self._connection)}
-        request = self._connection.post('user', data=data)
+        data = {'_method': 'put', 'utf8': '✓', 'user[language]': lang, 'authenticity_token': repr(self._connection)}
+        request = self._connection.post('user', data=data, allow_redirects=False)
+        return request.status_code
 
     def getLanguages(self):
         """Returns a list of tuples containing ('Language name', 'identifier').
         One of the Black Magic(tm) methods.
         """
-        select_start = '<select id="user_language" name="user[language]">'
-        select_end = '</select>'
+        selection_start = '<select id="user_language" name="user[language]">'
+        selection_end = '</select>'
         languages = []
         request = self._connection.get('user/edit')
-        data = request.text[request.text.find(select_start)+len(select_start):]
-        data = data[:data.find(select_end)].split('\n')
+        data = request.text[request.text.find(selection_start)+len(selection_start):]
+        data = data[:data.find(selection_end)].split('\n')
         for item in data:
             name = item[item.find('>')+1:item.rfind('<')]
             identifier = item[item.find('"')+1:]