8 """This is the client class to connect to Diaspora.
10 def __init__(self
, pod
, username
, password
):
12 :param pod: The complete url of the diaspora pod to use.
14 :param username: The username used to log in.
16 :param password: The password used to log in.
19 self
._token
_regex
= re
.compile(r
'content="(.*?)"\s+name="csrf-token')
21 self
.session
= requests
.Session()
23 self
._setlogindata
(username
, password
)
26 def _sessionget(self
, string
):
27 """This method gets data from session.
28 Performs additional checks if needed.
31 To obtain 'foo' from pod one should call `_sessionget('foo')`.
33 :param string: URL to get without the pod's URL and slash eg. 'stream'.
36 return self
.session
.get('{0}/{1}'.format(self
.pod
, string
))
38 def _sessionpost(self
, string
, data
, headers
={}, params
={}):
39 """This method posts data to session.
40 Performs additional checks if needed.
43 To post to 'foo' one should call `_sessionpost('foo', data={})`.
45 :param string: URL to post without the pod's URL and slash eg. 'status_messages'.
47 :param data: Data to post.
48 :param headers: Headers.
50 :param params: Optional parameters.
53 string
= '{0}/{1}'.format(self
.pod
, string
)
54 if headers
and params
: r
= self
.session
.post(string
, data
=data
, headers
=headers
, params
=params
)
55 elif headers
and not params
: r
= self
.session
.post(string
, data
=data
, headers
=headers
)
56 elif not headers
and params
: r
= self
.session
.post(string
, data
=data
, params
=params
)
57 else: r
= self
.session
.post(string
, data
=data
)
61 """This function gets a token needed for authentication in most cases
63 :returns: string -- token used to authenticate
65 r
= self
._sessionget
('stream')
66 token
= self
._token
_regex
.search(r
.text
).group(1)
69 def _setlogindata(self
, username
, password
):
70 """This function is used to set data for login.
72 It should be called before _login() function.
74 self
._username
, self
._password
= username
, password
75 self
._login
_data
= {'user[username]': self
._username
,
76 'user[password]': self
._password
,
77 'authenticity_token': self
.get_token()}
80 """This function is used to connect to the pod and log in.
82 r
= self
._sessionpost
('users/sign_in',
83 data
=self
._login
_data
,
84 headers
={'accept': 'application/json'})
85 if r
.status_code
!= 201:
86 raise Exception('{0}: Login failed.'.format(r
.status_code
))
88 def _setpostdata(self
, text
, aspect_ids
, photos
):
89 """This function prepares data for posting.
91 :param text: Text to post.
93 :param aspect_ids: Aspect ids to send post to.
97 data
['aspect_ids'] = aspect_ids
98 data
['status_message'] = {'text': text
}
100 data
['photos'] = photos
101 self
._post
_data
= data
104 """Sends post to an aspect.
106 :returns: diaspy.models.Post -- the Post which has been created
108 r
= self
._sessionpost
('status_messages',
109 data
=json
.dumps(self
._post
_data
),
110 headers
={'content-type': 'application/json',
111 'accept': 'application/json',
112 'x-csrf-token': self
.get_token()})
113 if r
.status_code
!= 201:
114 raise Exception('{0}: Post could not be posted.'.format(
117 return diaspy
.models
.Post(str(r
.json()['id']), self
)
119 def post(self
, text
, aspect_ids
='public', photos
=None):
120 """This function sends a post to an aspect
122 :param text: Text to post.
124 :param aspect_ids: Aspect ids to send post to.
125 :type aspect_ids: str
127 :returns: diaspy.models.Post -- the Post which has been created
129 self
._setpostdata
(text
, aspect_ids
, photos
)
134 def get_user_info(self
):
135 """This function returns the current user's attributes.
137 :returns: dict -- json formatted user info.
139 r
= self
._sessionget
('bookmarklet')
140 regex
= re
.compile(r
'window.current_user_attributes = ({.*})')
141 userdata
= json
.loads(regex
.search(r
.text
).group(1))
144 def post_picture(self
, filename
):
145 """This method posts a picture to D*.
147 :param filename: Path to picture file.
150 aspects
= self
.get_user_info()['aspects']
152 params
['photo[pending]'] = 'true'
153 params
['set_profile_image'] = ''
154 params
['qqfile'] = filename
155 for i
, aspect
in enumerate(aspects
):
156 params
['photo[aspect_ids][%d]' % (i
)] = aspect
['id']
158 data
= open(filename
, 'rb')
160 headers
= {'content-type': 'application/octet-stream',
161 'x-csrf-token': self
.get_token(),
162 'x-file-name': filename
}
164 r
= self
._sessionpost
('photos', params
=params
, data
=data
, headers
=headers
)
167 def get_stream(self
):
168 """This functions returns a list of posts found in the stream.
170 :returns: list -- list of Post objects.
172 r
= self
._sessionget
('stream.json')
174 if r
.status_code
!= 200:
175 raise Exception('wrong status code: {0}'.format(r
.status_code
))
178 return [diaspy
.models
.Post(str(post
['id']), self
) for post
in stream
]
180 def get_notifications(self
):
181 """This functions returns a list of notifications.
183 :returns: list -- list of json formatted notifications
185 r
= self
._sessionget
('notifications.json')
187 if r
.status_code
!= 200:
188 raise Exception('wrong status code: {0}'.format(r
.status_code
))
190 notifications
= r
.json()
193 def get_mentions(self
):
194 """This functions returns a list of
195 posts the current user is being mentioned in.
197 :returns: list -- list of Post objects
199 r
= self
._sessionget
('mentions.json')
201 if r
.status_code
!= 200:
202 raise Exception('wrong status code: {0}'.format(r
.status_code
))
205 return [diaspy
.models
.Post(str(post
['id']), self
) for post
in mentions
]
207 def get_tag(self
, tag
):
208 """This functions returns a list of posts containing the tag.
209 :param tag: Name of the tag
212 :returns: list -- list of Post objects
214 r
= self
._sessionget
('tags/{0}.json'.format(tag
))
216 if r
.status_code
!= 200:
217 raise Exception('wrong status code: {0}'.format(r
.status_code
))
219 tagged_posts
= r
.json()
220 return [diaspy
.models
.Post(str(post
['id']), self
) for post
in tagged_posts
]
222 def get_mailbox(self
):
223 """This functions returns a list of messages found in the conversation.
225 :returns: list -- list of Conversation objects.
227 r
= self
._sessionget
('conversations.json')
229 if r
.status_code
!= 200:
230 raise Exception('wrong status code: {0}'.format(r
.status_code
))
233 return [diaspy
.conversations
.Conversation(str(conversation
['conversation']['id']), self
)
234 for conversation
in mailbox
]
236 def add_user_to_aspect(self
, user_id
, aspect_id
):
237 """ this function adds a user to an aspect.
239 :param user_id: User ID
241 :param aspect_id: Aspect ID
245 data
= {'authenticity_token': self
.get_token(),
246 'aspect_id': aspect_id
,
247 'person_id': user_id
}
249 r
= self
._sessionpost
('aspect_memberships.json', data
=data
)
251 if r
.status_code
!= 201:
252 raise Exception('wrong status code: {0}'.format(r
.status_code
))
255 def add_aspect(self
, aspect_name
, visible
=0):
256 """ This function adds a new aspect.
259 data
= {'authenticity_token': self
.get_token(),
260 'aspect[name]': aspect_name
,
261 'aspect[contacts_visible]': visible
}
263 r
= self
._sessionpost
('aspects', data
=data
)
265 if r
.status_code
!= 200:
266 raise Exception('wrong status code: {0}'.format(r
.status_code
))
268 def remove_user_from_aspect(self
, user_id
, aspect_id
):
269 """ this function removes a user from an aspect.
271 :param user_id: User ID
273 :param aspect_id: Aspect ID
278 data
= {'authenticity_token': self
.get_token(),
279 'aspect_id': aspect_id
,
280 'person_id': user_id
}
282 r
= self
.session
.delete('{0}/aspect_memberships/42.json'.format(
286 if r
.status_code
!= 200:
287 raise Exception('wrong status code: {0}'.format(r
.status_code
))
291 def remove_aspect(self
, aspect_id
):
292 """ This function adds a new aspect.
294 data
= {'authenticity_token': self
.get_token()}
296 r
= self
.session
.delete('{0}/aspects/{1}'.format(self
.pod
, aspect_id
),
299 if r
.status_code
!= 404:
300 raise Exception('wrong status code: {0}'.format(r
.status_code
))
302 def new_conversation(self
, contacts
, subject
, text
):
303 """Start a new conversation.
305 :param contacts: recipients ids, no guids, comma sperated.
307 :param subject: subject of the message.
309 :param text: text of the message.
312 data
= {'contact_ids': contacts
,
313 'conversation[subject]': subject
,
314 'conversation[text]': text
,
316 'authenticity_token': self
.get_token()}
318 r
= self
._sessionpost
('conversations/',
320 headers
={'accept': 'application/json'})
321 if r
.status_code
!= 200:
322 raise Exception('{0}: Conversation could not be started.'
323 .format(r
.status_code
))