8 """This is the client class to connect to Diaspora.
11 def __init__(self
, pod
, username
, password
):
13 :param pod: The complete url of the diaspora pod to use.
15 :param username: The username used to log in.
17 :param password: The password used to log in.
20 self
._token
_regex
= re
.compile(r
'content="(.*?)"\s+name="csrf-token')
22 self
.session
= requests
.Session()
24 self
._setlogindata
(username
, password
)
27 def _sessionget(self
, string
):
28 """This method gets data from session.
29 Performs additional checks if needed.
32 To obtain 'foo' from pod one should call `_sessionget('foo')`.
34 :param string: URL to get without the pod's URL and slash eg. 'stream'.
37 return self
.session
.get('{0}/{1}'.format(self
.pod
, string
))
40 """This function gets a token needed for authentication in most cases
42 :returns: string -- token used to authenticate
44 r
= self
._sessionget
('stream')
45 token
= self
._token
_regex
.search(r
.text
).group(1)
48 def _setlogindata(self
, username
, password
):
49 """This function is used to set data for login.
52 It should be called before _login() function.
54 self
._username
, self
._password
= username
, password
56 'user[username]': self
._username
,
57 'user[password]': self
._password
,
58 'authenticity_token': self
.get_token(),
62 """This function is used to connect to the pod and log in.
64 r
= self
.session
.post('{0}/users/sign_in'.format(self
.pod
),
65 data
=self
._login
_data
,
66 headers
={'accept': 'application/json'})
68 if r
.status_code
!= 201: raise Exception('{0}: Login failed.'.format(r
.status_code
))
70 def _setpostdata(self
, text
, aspect_id
, photos
):
71 """This function prepares data for posting.
73 :param text: Text to post.
75 :param aspect_id: Aspect id to send post to.
79 data
['aspect_id'] = aspect_id
80 data
['status_message'] = {'text': text
}
81 if photos
: data
['photos'] = photos
82 self
._post
_data
= data
85 """Sends post to an aspect.
87 :returns: diaspy.models.Post -- the Post which has been created
89 r
= self
.session
.post('{0}/status_messages'.format(self
.pod
),
90 data
=json
.dumps(self
._post
_data
),
91 headers
={'content-type': 'application/json',
92 'accept': 'application/json',
93 'x-csrf-token': self
.get_token()})
94 if r
.status_code
!= 201: raise Exception('{0}: Post could not be posted.'.format(r
.status_code
))
96 return diaspy
.models
.Post(str(r
.json()['id']), self
)
98 def post(self
, text
, aspect_id
='public', photos
=None):
99 """This function sends a post to an aspect
101 :param text: Text to post.
103 :param aspect_id: Aspect id to send post to.
106 :returns: diaspy.models.Post -- the Post which has been created
108 self
._setpostdata
(text
, aspect_id
, photos
)
113 def get_user_info(self
):
114 """This function returns the current user's attributes.
116 :returns: dict -- json formatted user info.
118 r
= self
._sessionget
('bookmarklet')
119 regex
= re
.compile(r
'window.current_user_attributes = ({.*})')
120 userdata
= json
.loads(regex
.search(r
.text
).group(1))
123 def post_picture(self
, filename
):
124 """This method posts a picture to D*.
126 :param filename: Path to picture file.
129 aspects
= self
.get_user_info()['aspects']
131 params
['photo[pending]'] = 'true'
132 params
['set_profile_image'] = ''
133 params
['qqfile'] = filename
134 for i
, aspect
in enumerate(aspects
):
135 params
['photo[aspect_ids][%d]' % (i
)] = aspect
['id']
137 data
= open(filename
, 'rb')
139 headers
= {'content-type': 'application/octet-stream',
140 'x-csrf-token': self
.get_token(),
141 'x-file-name': filename
}
143 r
= self
.session
.post('{0}/photos'.format(self
.pod
),
144 params
=params
, data
=data
, headers
=headers
)
148 def get_stream(self
):
149 """This functions returns a list of posts found in the stream.
151 :returns: list -- list of Post objects.
153 data
= {'authenticity_token': self
.get_token()}
154 r
= self
._sessionget
('stream.json')
156 if r
.status_code
!= 200:
157 raise Exception('wrong status code: {0}'.format(r
.status_code
))
160 return [ diaspy
.models
.Post(str(post
['id']), self
) for post
in stream
]
162 def get_notifications(self
):
163 """This functions returns a list of notifications.
165 :returns: list -- list of json formatted notifications
167 data
= {'authenticity_token': self
.get_token()}
168 r
= self
._sessionget
('notifications.json')
170 if r
.status_code
!= 200:
171 raise Exception('wrong status code: {0}'.format(r
.status_code
))
173 notifications
= r
.json()
176 def get_mentions(self
):
177 """This functions returns a list of
178 posts the current user is being mentioned in.
180 :returns: list -- list of Post objects
182 data
= {'authenticity_token': self
.get_token()}
183 r
= self
._sessionget
('mentions.json')
185 if r
.status_code
!= 200:
186 raise Exception('wrong status code: {0}'.format(r
.status_code
))
189 return [ diaspy
.models
.Post(str(post
['id']), self
) for post
in mentions
]
191 def get_tag(self
, tag
):
192 """This functions returns a list of posts containing the tag.
193 :param tag: Name of the tag
196 :returns: list -- list of Post objects
198 data
= {'authenticity_token': self
.get_token()}
199 r
= self
._sessionget
('tags/{0}.json'.format(tag
))
201 if r
.status_code
!= 200:
202 raise Exception('wrong status code: {0}'.format(r
.status_code
))
204 tagged_posts
= r
.json()
205 return [ diaspy
.models
.Post(str(post
['id']), self
) for post
in tagged_posts
]
207 def add_user_to_aspect(self
, user_id
, aspect_id
):
208 """ this function adds a user to an aspect.
210 :param user_id: User ID
212 :param aspect_id: Aspect ID
217 data
= {'authenticity_token': self
.get_token(),
218 'aspect_id': aspect_id
,
219 'person_id': user_id
}
221 r
= self
.session
.post('{0}/aspect_memberships.json'.format(self
.pod
),
224 if r
.status_code
!= 201:
225 raise Exception('wrong status code: {0}'.format(r
.status_code
))
228 def remove_user_from_aspect(self
, user_id
, aspect_id
):
229 """ this function removes a user from an aspect.
231 :param user_id: User ID
233 :param aspect_id: Aspect ID
238 data
= {'authenticity_token': self
.get_token(),
239 'aspect_id': aspect_id
,
240 'person_id': user_id
}
242 r
= self
.session
.delete('{0}/aspect_memberships/42.json'.format(self
.pod
),
245 if r
.status_code
!= 200:
246 raise Exception('wrong status code: {0}'.format(r
.status_code
))
250 def add_aspect(self
, aspect_name
, visible
=0):
251 """ This function adds a new aspect.
254 data
= {'authenticity_token': self
.get_token(),
255 'aspect[name]': aspect_name
,
256 'aspect[contacts_visible]': visible
}
258 r
= self
.session
.post('{0}/aspects'.format(self
.pod
),
261 if r
.status_code
!= 200:
262 raise Exception('wrong status code: {0}'.format(r
.status_code
))
264 def remove_aspect(self
, aspect_id
):
265 """ This function adds a new aspect.
268 data
= {'authenticity_token': self
.get_token()}
270 r
= self
.session
.delete('{0}/aspects/{1}'.format(self
.pod
, aspect_id
),
273 if r
.status_code
!= 404:
274 raise Exception('wrong status code: {0}'.format(r
.status_code
))
276 def get_mailbox(self
):
277 """This functions returns a list of messages found in the conversation.
279 :returns: list -- list of Conversation objects.
281 data
= {'authenticity_token': self
.get_token()}
282 #r = self.session.get('{0}/conversations.json'.format(self.pod))
283 r
= self
.session
.get('{0}/conversations.json'.format(self
.pod
))
285 if r
.status_code
!= 200:
286 raise Exception('wrong status code: {0}'.format(r
.status_code
))
289 conversations
= [ diaspy
.conversations
.Conversation(str(conversation
['conversation']['id']), self
) for conversation
in mailbox
]
293 def new_conversation(self
, contacts
, subject
, text
):
294 """ start a new conversation
296 :param contacts: recipients ids, no guids, comma sperated.
298 :param subject: subject of the message.
300 :param text: text of the message.
305 data
= {'contact_ids': contacts
,
306 'conversation[subject]': subject
,
307 'conversation[text]': text
,
309 'authenticity_token': self
.get_token()}
311 r
= self
.session
.post('{0}/conversations/'.format(self
.pod
),
313 headers
={'accept': 'application/json'})
314 if r
.status_code
!= 200:
315 raise Exception('{0}: Conversation could not be started.'.format(r
.status_code
))