#!/usr/bin/env python
+
+"""This module abstracts connection to pod.
+"""
+
+
import re
import requests
import json
from diaspy import errors
-"""This module abstracts connection to pod.
-"""
+DEBUG = True
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
"""
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:
"""
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.
"""
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.
: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.
: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):
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.
: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
: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:
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.
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.
: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:]