Commit | Line | Data |
---|---|---|
a993a4b6 MK |
1 | import requests |
2 | import re | |
3 | import json | |
95d2d310 | 4 | import diaspy.models |
a993a4b6 MK |
5 | |
6 | class Client: | |
7 | """This is the client class to connect to diaspora. | |
8 | ||
a993a4b6 MK |
9 | """ |
10 | ||
a7661afd MK |
11 | def __init__(self, pod, username, password): |
12 | """ | |
13 | :param pod: The complete url of the diaspora pod to use. | |
14 | :type pod: str | |
15 | :param username: The username used to log in. | |
16 | :type username: str | |
17 | :param password: The password used to log in. | |
18 | :type password: str | |
19 | ||
20 | """ | |
a993a4b6 MK |
21 | self._token_regex = re.compile(r'content="(.*?)"\s+name="csrf-token') |
22 | self.pod = pod | |
23 | self.session = requests.Session() | |
a7661afd | 24 | self._login(username, password) |
a993a4b6 MK |
25 | |
26 | def get_token(self): | |
ae221396 MK |
27 | """This function gets a token needed for authentication in most cases |
28 | ||
29 | :returns: string -- token used to authenticate | |
30 | ||
31 | """ | |
32 | ||
a7661afd | 33 | r = self.session.get(self.pod + '/stream') |
a993a4b6 MK |
34 | token = self._token_regex.search(r.text).group(1) |
35 | return token | |
36 | ||
a7661afd | 37 | def _login(self, username, password): |
a993a4b6 | 38 | """This function is used to connect to the pod and log in. |
a7661afd MK |
39 | .. note:: |
40 | This function shouldn't be called manually. | |
a993a4b6 MK |
41 | """ |
42 | self._username = username | |
43 | self._password = password | |
a7661afd | 44 | r = self.session.get(self.pod + '/users/sign_in') |
a993a4b6 MK |
45 | token = self._token_regex.search(r.text).group(1) |
46 | ||
47 | data = {'user[username]': self._username, | |
48 | 'user[password]': self._password, | |
49 | 'authenticity_token': token, | |
50 | 'commit': ''} | |
51 | ||
a7661afd MK |
52 | r = self.session.post(self.pod + |
53 | '/users/sign_in', | |
54 | data=data, | |
55 | headers={'accept': 'application/json'}) | |
56 | ||
57 | if r.status_code != 201: | |
58 | raise Exception(str(r.status_code) + ': Login failed.') | |
a993a4b6 | 59 | |
28ca595a | 60 | def post(self, text, aspect_id='public', photos=None): |
a993a4b6 MK |
61 | """This function sends a post to an aspect |
62 | ||
63 | :param text: Text to post. | |
64 | :type text: str | |
65 | :param aspect_id: Aspect id to send post to. | |
66 | :type aspect_id: str | |
67 | ||
95d2d310 MK |
68 | :returns: diaspy.models.Post -- the Post which has been created |
69 | ||
a993a4b6 MK |
70 | """ |
71 | data = {'aspect_ids': aspect_id, | |
28ca595a MK |
72 | 'status_message': {'text': text}} |
73 | ||
74 | if photos: | |
75 | data['photos'] = photos | |
a7661afd MK |
76 | r = self.session.post(self.pod + |
77 | "/status_messages", | |
28ca595a MK |
78 | data=json.dumps(data), |
79 | headers={'content-type': 'application/json', | |
80 | 'accept': 'application/json', | |
81 | 'x-csrf-token': self.get_token()}) | |
a7661afd MK |
82 | if r.status_code != 201: |
83 | raise Exception(str(r.status_code) + ': Post could not be posted.') | |
84 | ||
95d2d310 | 85 | return diaspy.models.Post(str(r.json()['id']), self) |
a993a4b6 MK |
86 | |
87 | def get_user_info(self): | |
88 | """This function returns the current user's attributes. | |
89 | ||
90 | :returns: dict -- json formatted user info. | |
91 | ||
92 | """ | |
28ca595a | 93 | r = self.session.get(self.pod + '/bookmarklet') |
a993a4b6 MK |
94 | regex = re.compile(r'window.current_user_attributes = ({.*})') |
95 | userdata = json.loads(regex.search(r.text).group(1)) | |
96 | return userdata | |
b356c9f9 | 97 | |
28ca595a MK |
98 | def post_picture(self, filename): |
99 | aspects = self.get_user_info()['aspects'] | |
100 | params = {} | |
101 | params['photo[pending]'] = 'true' | |
102 | params['set_profile_image'] = '' | |
103 | params['qqfile'] = filename | |
104 | for i, aspect in enumerate(aspects): | |
105 | params['photo[aspect_ids][%d]' % (i)] = aspect['id'] | |
106 | ||
107 | data = open(filename, 'rb') | |
108 | ||
109 | headers = {'content-type': 'application/octet-stream', | |
110 | 'x-csrf-token': self.get_token(), | |
111 | 'x-file-name': filename} | |
112 | ||
113 | r = self.session.post(self.pod + '/photos', params=params, data=data, headers=headers) | |
114 | ||
115 | return r | |
116 | ||
117 | ||
118 | ||
b356c9f9 MK |
119 | def get_stream(self): |
120 | """This functions returns a list of posts found in the stream. | |
121 | ||
122 | :returns: list -- list of Post objects. | |
123 | ||
124 | """ | |
125 | ||
126 | data = {'authenticity_token': self.get_token()} | |
127 | r = self.session.get(self.pod + "/stream.json") | |
128 | ||
129 | if r.status_code != 200: | |
130 | raise Exception('wrong status code: ' + str(r.status_code)) | |
131 | ||
132 | stream = r.json() | |
133 | ||
134 | posts = [] | |
135 | ||
136 | for post in stream: | |
137 | posts.append(diaspy.models.Post(str(post['id']), self)) | |
138 | ||
139 | return posts | |
33f21ecf MK |
140 | |
141 | def get_notifications(self): | |
142 | """This functions returns a list of notifications. | |
143 | ||
144 | :returns: list -- list of json formatted notifications | |
145 | ||
146 | """ | |
147 | ||
148 | ||
149 | data = {'authenticity_token': self.get_token()} | |
150 | r = self.session.get(self.pod + "/notifications.json") | |
151 | ||
152 | if r.status_code != 200: | |
153 | raise Exception('wrong status code: ' + str(r.status_code)) | |
154 | ||
155 | notifications = r.json() | |
156 | return notifications | |
3d3dff8f MK |
157 | |
158 | ||
159 | def get_mentions(self): | |
160 | """This functions returns a list of posts the current user is being mentioned in. | |
161 | ||
162 | :returns: list -- list of Post objects | |
163 | ||
164 | """ | |
165 | ||
166 | ||
167 | data = {'authenticity_token': self.get_token()} | |
168 | r = self.session.get(self.pod + "/mentions.json") | |
169 | ||
170 | if r.status_code != 200: | |
171 | raise Exception('wrong status code: ' + str(r.status_code)) | |
172 | ||
173 | mentions = r.json() | |
174 | ||
175 | posts = [] | |
176 | ||
177 | for post in mentions: | |
178 | posts.append(diaspy.models.Post(str(post['id']), self)) | |
179 | ||
180 | return posts | |
5c2b6162 MK |
181 | |
182 | def add_user_to_aspect(self, user_id, aspect_id): | |
183 | """ this function adds a user to an aspect. | |
184 | ||
185 | :param user_id: User ID | |
186 | :type user_id: str | |
187 | :param aspect_id: Aspect ID | |
188 | :type aspect_id: str | |
189 | ||
190 | """ | |
191 | ||
192 | data = {'authenticity_token': self.get_token(), | |
193 | 'aspect_id': aspect_id, | |
194 | 'person_id': user_id} | |
195 | ||
196 | r = self.session.post(self.pod + '/aspect_memberships.json', | |
197 | data=data) | |
198 | ||
199 | if r.status_code != 201: | |
200 | raise Exception('wrong status code: ' + str(r.status_code)) | |
201 | return r.json() | |
202 | ||
203 | def remove_user_from_aspect(self, user_id, aspect_id): | |
204 | """ this function removes a user from an aspect. | |
205 | ||
206 | :param user_id: User ID | |
207 | :type user_id: str | |
208 | :param aspect_id: Aspect ID | |
209 | :type aspect_id: str | |
210 | ||
211 | """ | |
212 | ||
213 | data = {'authenticity_token': self.get_token(), | |
214 | 'aspect_id': aspect_id, | |
215 | 'person_id': user_id} | |
216 | ||
217 | r = self.session.delete(self.pod + '/aspect_memberships/42.json', | |
218 | data=data) | |
219 | ||
220 | if r.status_code != 200: | |
221 | raise Exception('wrong status code: ' + str(r.status_code)) | |
222 | ||
223 | return r.json() |