Further work being done on streams; all basic streams implemented
[diaspy.git] / diaspy / client.py
index 70af42ffcf189d34fcf2e2fe2146a7e3734297c5..8eaab4461198257b7e1d2562d5af441b9bf6eba2 100644 (file)
@@ -1,13 +1,11 @@
-import requests
-import re
-import json
 import diaspy.models
+import diaspy.streams
+import diaspy.connection
 
-class Client:
-    """This is the client class to connect to diaspora.
 
+class Client:
+    """This is the client class to connect to Diaspora.
     """
-
     def __init__(self, pod, username, password):
         """
         :param pod: The complete url of the diaspora pod to use.
@@ -16,168 +14,103 @@ class Client:
         :type username: str
         :param password: The password used to log in.
         :type password: str
-
         """
-        self._token_regex = re.compile(r'content="(.*?)"\s+name="csrf-token')
+        self.connection = diaspy.connection.Connection(pod, username, password)
+        self.connection.login()
         self.pod = pod
-        self.session = requests.Session()
-        self._login(username, password)
-
-    def get_token(self):
-        """This function gets a token needed for authentication in most cases
-
-        :returns: string -- token used to authenticate
-
-        """
-
-        r = self.session.get(self.pod + '/stream')
-        token = self._token_regex.search(r.text).group(1)
-        return token
+        self.stream = diaspy.streams.Stream(self.connection, 'stream.json')
 
-    def _login(self, username, password):
-        """This function is used to connect to the pod and log in.
-        .. note::
-           This function shouldn't be called manually.
-        """
-        self._username = username
-        self._password = password
-        r = self.session.get(self.pod + '/users/sign_in')
-        token = self._token_regex.search(r.text).group(1)
-
-        data = {'user[username]': self._username,
-                'user[password]': self._password,
-                'authenticity_token': token,
-                'commit': ''}
-
-        r = self.session.post(self.pod +
-                              '/users/sign_in',
-                              data=data,
-                              headers={'accept': 'application/json'})
-
-        if r.status_code != 201:
-            raise Exception(str(r.status_code) + ': Login failed.')
-
-    def post(self, text, aspect_id='public', photos=None):
+    def post(self, text, aspect_ids='public', photos=None):
         """This function sends a post to an aspect
 
         :param text: Text to post.
         :type text: str
-        :param aspect_id: Aspect id to send post to.
-        :type aspect_id: str
+        :param aspect_ids: Aspect ids to send post to.
+        :type aspect_ids: str
 
         :returns: diaspy.models.Post -- the Post which has been created
-
-        """
-        data = {'aspect_ids': aspect_id,
-                'status_message': {'text': text}}
-
-        if photos:
-            data['photos'] = photos
-        r = self.session.post(self.pod +
-                              "/status_messages",
-                              data=json.dumps(data),
-                              headers={'content-type': 'application/json',
-                                       'accept': 'application/json',
-                                       'x-csrf-token': self.get_token()})
-        if r.status_code != 201:
-            raise Exception(str(r.status_code) + ': Post could not be posted.')
-
-        return diaspy.models.Post(str(r.json()['id']), self)
-
-    def get_user_info(self):
-        """This function returns the current user's attributes.
-
-        :returns: dict -- json formatted user info.
-
         """
-        r = self.session.get(self.pod + '/bookmarklet')
-        regex = re.compile(r'window.current_user_attributes = ({.*})')
-        userdata = json.loads(regex.search(r.text).group(1))
-        return userdata
+        post = self.stream.post(text, aspect_ids, photos)
+        return post
 
     def post_picture(self, filename):
-        aspects = self.get_user_info()['aspects']
-        params = {}
-        params['photo[pending]'] = 'true'
-        params['set_profile_image'] = ''
-        params['qqfile'] = filename
-        for i, aspect in enumerate(aspects):
-            params['photo[aspect_ids][%d]' % (i)] = aspect['id']
-
-        data = open(filename, 'rb')
-
-        headers = {'content-type': 'application/octet-stream',
-                   'x-csrf-token': self.get_token(),
-                   'x-file-name': filename}
-
-        r = self.session.post(self.pod + '/photos', params=params, data=data, headers=headers)
-
-        return r
+        """This method posts a picture to D*.
 
+        :param filename: Path to picture file.
+        :type filename: str
+        """
+        return self.stream.post_picture(filename)
 
+    def get_activity(self):
+        """This function returns activity stream.
+        :returns: diaspy.streams.Activity
+        """
+        activity = diaspy.streams.Activity(self.connection, 'activity.json')
+        return activity
 
     def get_stream(self):
-        """This functions returns a list of posts found in the stream.
-
-        :returns: list -- list of Post objects.
+        """This functions returns stream.
 
+        :returns: diaspy.streams.Stream
         """
-
-        data = {'authenticity_token': self.get_token()}
-        r = self.session.get(self.pod + "/stream.json")
-
-        if r.status_code != 200:
-            raise Exception('wrong status code: ' + str(r.status_code))
-
-        stream = r.json()
-
-        posts = []
-
-        for post in stream:
-            posts.append(diaspy.models.Post(str(post['id']), self))
-
-        return posts
+        self.stream.update()
+        return self.stream
 
     def get_notifications(self):
         """This functions returns a list of notifications.
 
         :returns: list -- list of json formatted notifications
-
         """
-
-
-        data = {'authenticity_token': self.get_token()}
-        r = self.session.get(self.pod + "/notifications.json")
+        r = self.connection.get('notifications.json')
 
         if r.status_code != 200:
-            raise Exception('wrong status code: ' + str(r.status_code))
+            raise Exception('wrong status code: {0}'.format(r.status_code))
 
         notifications = r.json()
         return notifications
 
-
     def get_mentions(self):
-        """This functions returns a list of posts the current user is being mentioned in.
+        """This functions returns a list of
+        posts the current user is being mentioned in.
 
         :returns: list -- list of Post objects
-
         """
+        r = self.connection.get('mentions.json')
+
+        if r.status_code != 200:
+            raise Exception('wrong status code: {0}'.format(r.status_code))
+
+        mentions = r.json()
+        return [diaspy.models.Post(str(post['id']), self.connection) for post in mentions]
 
+    def get_tag(self, tag):
+        """This functions returns a list of posts containing the tag.
+        :param tag: Name of the tag
+        :type tag: str
 
-        data = {'authenticity_token': self.get_token()}
-        r = self.session.get(self.pod + "/mentions.json")
+        :returns: list -- list of Post objects
+        """
+        r = self.connection.get('tags/{0}.json'.format(tag))
 
         if r.status_code != 200:
-            raise Exception('wrong status code: ' + str(r.status_code))
+            raise Exception('wrong status code: {0}'.format(r.status_code))
 
-        mentions = r.json()
+        tagged_posts = r.json()
+        return [diaspy.models.Post(str(post['id']), self.connection) for post in tagged_posts]
 
-        posts = []
+    def get_mailbox(self):
+        """This functions returns a list of messages found in the conversation.
 
-        for post in mentions:
-            posts.append(diaspy.models.Post(str(post['id']), self))
+        :returns: list -- list of Conversation objects.
+        """
+        r = self.connection.get('conversations.json')
 
-        return posts
+        if r.status_code != 200:
+            raise Exception('wrong status code: {0}'.format(r.status_code))
+
+        mailbox = r.json()
+        return [diaspy.conversations.Conversation(str(conversation['conversation']['id']), self.connection)
+                for conversation in mailbox]
 
     def add_user_to_aspect(self, user_id, aspect_id):
         """ this function adds a user to an aspect.
@@ -188,18 +121,22 @@ class Client:
         :type aspect_id: str
 
         """
-
-        data = {'authenticity_token': self.get_token(),
+        data = {'authenticity_token': self.connection.getToken(),
                 'aspect_id': aspect_id,
                 'person_id': user_id}
 
-        r = self.session.post(self.pod + '/aspect_memberships.json',
-                              data=data)
+        r = self.connection.post('aspect_memberships.json', data=data)
 
         if r.status_code != 201:
-            raise Exception('wrong status code: ' + str(r.status_code))
+            raise Exception('wrong status code: {0}'.format(r.status_code))
         return r.json()
 
+    def add_aspect(self, aspect_name, visible=0):
+        """ This function adds a new aspect.
+        """
+        aspects = diaspy.streams.Aspects(self.connection)
+        aspects.add(aspect_name, visible)
+
     def remove_user_from_aspect(self, user_id, aspect_id):
         """ this function removes a user from an aspect.
 
@@ -209,41 +146,49 @@ class Client:
         :type aspect_id: str
 
         """
-
-        data = {'authenticity_token': self.get_token(),
+        data = {'authenticity_token': self.connection.getToken(),
                 'aspect_id': aspect_id,
                 'person_id': user_id}
 
-        r = self.session.delete(self.pod + '/aspect_memberships/42.json',
-                                data=data)
+        r = self.connection.delete('aspect_memberships/42.json',
+                                   data=data)
 
         if r.status_code != 200:
-            raise Exception('wrong status code: ' + str(r.status_code))
+            raise Exception('wrong status code: {0}'.format(r.status_code))
 
         return r.json()
 
-    def add_aspect(self, aspect_name, visible=0):
+    def remove_aspect(self, aspect_id):
         """ This function adds a new aspect.
         """
+        data = {'authenticity_token': self.connection.getToken()}
 
-        data = {'authenticity_token': self.get_token(),
-                'aspect[name]': aspect_name,
-                'aspect[contacts_visible]': visible}
+        r = self.connection.delete('aspects/{}'.format(aspect_id),
+                                   data=data)
 
-        r = self.session.post(self.pod + '/aspects',
-                              data=data)
+        if r.status_code != 404:
+            raise Exception('wrong status code: {0}'.format(r.status_code))
 
-        if r.status_code != 200:
-            raise Exception('wrong status code: ' + str(r.status_code))
+    def new_conversation(self, contacts, subject, text):
+        """Start a new conversation.
 
-    def remove_aspect(self, aspect_id):
-        """ This function adds a new aspect.
+        :param contacts: recipients ids, no guids, comma sperated.
+        :type contacts: str
+        :param subject: subject of the message.
+        :type subject: str
+        :param text: text of the message.
+        :type text: str
         """
-
-        data = {'authenticity_token': self.get_token()}
-
-        r = self.session.delete(self.pod + '/aspects/' + aspect_id,
-                              data=data}
-
-        if r.status_code != 404:
-            raise Exception('wrong status code: ' + str(r.status_code))
+        data = {'contact_ids': contacts,
+                'conversation[subject]': subject,
+                'conversation[text]': text,
+                'utf8': '✓',
+                'authenticity_token': self.connection.getToken()}
+
+        r = self.connection.post('conversations/',
+                                 data=data,
+                                 headers={'accept': 'application/json'})
+        if r.status_code != 200:
+            raise Exception('{0}: Conversation could not be started.'
+                            .format(r.status_code))
+        return r.json()