d68f0b31104205b06cec8a05db8a9f0d7b4f8d93
[diaspy.git] / diaspy / settings.py
1 """This module provides access to user's settings on Diaspora*.
2 """
3
4
5 import json
6 import os
7 import re
8 import urllib
9 import warnings
10
11 from diaspy import errors, streams
12
13
14 class Profile():
15 """Provides profile editing methods.
16 """
17 def __init__(self, connection):
18 self._connection = connection
19 self.data = {'utf-8': '✓',
20 '_method': 'put',
21 'profile[first_name]': '',
22 'profile[last_name]': '',
23 'profile[tag_string]': '',
24 'tags': '',
25 'file': '',
26 'profile[bio]': '',
27 'profile[location]': '',
28 'profile[gender]': '',
29 'profile[date][year]': '',
30 'profile[date][month]': '',
31 'profile[date][day]': '',
32 }
33
34 def setName(self, first='', last=''):
35 """Set first name.
36 """
37 data = self.data
38 data['profile[first_name]'] = first
39 data['profile[last_name]'] = last
40 data['authenticity_token'] = repr(self._connection)
41 print(data)
42 request = self._connection.post('profile', data=data, allow_redirects=False)
43 return request.status_code
44
45
46 class Settings():
47 """This object is used to get access to user's settings on
48 Diaspora* and provides interface for downloading user's stuff.
49 """
50 def __init__(self, connection):
51 self._connection = connection
52
53 def downloadxml(self):
54 """Returns downloaded XML.
55 """
56 request = self._connection.get('user/export')
57 return request.text
58
59 def downloadPhotos(self, size='large', path='.', mark_nsfw=True, _critical=False, _stream=None):
60 """Downloads photos into the current working directory.
61 Sizes are: large, medium, small.
62 Filename is: {post_guid}_{photo_guid}.{extension}
63
64 Normally, this method will catch urllib-generated errors and
65 just issue warnings about photos that couldn't be downloaded.
66 However, with _critical param set to True errors will become
67 critical - the will be reraised in finally block.
68
69 :param size: size of the photos to download - large, medium or small
70 :type size: str
71 :param path: path to download (defaults to current working directory
72 :type path: str
73 :param mark_nsfw: will append '-nsfw' to images from posts marked as nsfw,
74 :type mark_nsfw: bool
75 :param _stream: diaspy.streams.Generic-like object (only for testing)
76 :param _critical: if True urllib errors will be reraised after generating a warning (may be removed)
77
78 :returns: integer, number of photos downloaded
79 """
80 photos = 0
81 if _stream is None:
82 stream = streams.Activity(self._connection)
83 stream.full()
84 else:
85 stream = _stream
86 for i, post in enumerate(stream):
87 if post['nsfw'] is not False: nsfw = '-nsfw'
88 else: nsfw = ''
89 if post['photos']:
90 for n, photo in enumerate(post['photos']):
91 name = '{0}_{1}{2}.{3}'.format(post['guid'], photo['guid'], nsfw, photo['sizes'][size].split('.')[-1])
92 filename = os.path.join(path, name)
93 try:
94 urllib.request.urlretrieve(url=photo['sizes'][size], filename=filename)
95 except (urllib.error.HTTPError, urllib.error.URLError) as e:
96 warnings.warn('downloading image {0} from post {1}: {2}'.format(photo['guid'], post['guid'], e))
97 finally:
98 if _critical: raise
99 photos += 1
100 return photos
101
102 def setEmail(self, email):
103 """Changes user's email.
104 """
105 data = {'_method': 'put', 'utf8': '✓', 'user[email]': email, 'authenticity_token': repr(self._connection)}
106 request = self._connection.post('user', data=data, allow_redirects=False)
107
108 def getEmail(self):
109 """Returns currently used email.
110 """
111 data = self._connection.get('user/edit')
112 email = re.compile('<input id="user_email" name="user\[email\]" size="30" type="text" value=".+?"').search(data.text)
113 if email is None: raise errors.DiaspyError('cannot fetch email')
114 email = email.group(0)[:-1]
115 email = email[email.rfind('"')+1:]
116 return email
117
118 def setLanguage(self, lang):
119 """Changes user's email.
120
121 :param lang: language identifier from getLanguages()
122 """
123 data = {'_method': 'put', 'utf8': '✓', 'user[language]': lang, 'authenticity_token': repr(self._connection)}
124 request = self._connection.post('user', data=data, allow_redirects=False)
125 return request.status_code
126
127 def getLanguages(self):
128 """Returns a list of tuples containing ('Language name', 'identifier').
129 One of the Black Magic(tm) methods.
130 """
131 selection_start = '<select id="user_language" name="user[language]">'
132 selection_end = '</select>'
133 languages = []
134 request = self._connection.get('user/edit')
135 data = request.text[request.text.find(selection_start)+len(selection_start):]
136 data = data[:data.find(selection_end)].split('\n')
137 for item in data:
138 name = item[item.find('>')+1:item.rfind('<')]
139 identifier = item[item.find('"')+1:]
140 identifier = identifier[:identifier.find('"')]
141 languages.append((name, identifier))
142 return languages