Exemplo n.º 1
0
class TodoRetriever:
    def __init__(self, address):
        self.client = DDPClient(address)

    async def go(self):
        await self.client.connect()

        lists = self.client.get_collection('lists')
        todos = self.client.get_collection('todos')

        sub = await self.client.subscribe('lists.public')
        await sub.wait()

        lists_sorted = sorted(lists.values(), key=lambda l: l.name)
        for l in lists_sorted:
            sub = await self.client.subscribe('todos.inList',
                                              {'listId': l._id})
            await sub.wait()

            print(l.name)

            for todo in filter(lambda t: t.listId == l._id, todos.values()):
                print('    [{}] {}'.format('X' if todo.checked else ' ',
                                           todo.text))

            print()
Exemplo n.º 2
0
 def __init__(self, address, loop):
     self.client = DDPClient(address)
     self.tasks = []
     self.subscriptions = {}
     self.loop = loop
Exemplo n.º 3
0
class Client:
    """RocketChat Client

    Implements all available rocketchat methods and subscriptions
    """
    def __init__(self, address, loop):
        self.client = DDPClient(address)
        self.tasks = []
        self.subscriptions = {}
        self.loop = loop

    async def connect(self) -> None:
        """Connect
        """
        await self.client.connect()

    async def disconnection(self) -> None:
        """Wait until the ddpclient disconnects
        """
        await self.client.disconnection()

    def disconnect(self) -> None:
        """Disconnect by caneling all running tasks
        """
        for task in self.tasks:
            task.cancel()

    async def login(self, username: str, password: str) -> m.LoginResult:
        """Login with the given credentials"""
        response = await self.client.call("login", {
            "user": {
                "username": username
            },
            "password": password
        })
        return m.LoginResult(**response)

    async def logout(self) -> None:
        """Logout"""
        await self.client.call("logout")

    # async def getUserRoles(self):
    #     """This method call is used to get server-wide special users and their
    #     roles. That information is used to identify key users on the server
    #     (ex.: admins).

    #     (Currently only returns admins)

    #     Returns:
    #         [
    #             {
    #                 '_id': 'noBbWB64vwJ7fgt2q',
    #                 'roles': ['admin'],
    #                 'username': '******'
    #             },
    #             ...
    #         ]
    #     """
    #     return await self.client.call("getUserRoles")

    # async def listEmojiCustom(self):
    #     """Returns a list of custom emoji registered with the server.

    #     Retrieve the custom emoji with:
    #     ${ path }/emoji-custom/${ encoded(name) } }.${ extension }.

    #     Eg.
    #     https://chat.fachschaft.tf/emoji-custom/ersti.png

    #     Returns:
    #         [
    #             {
    #                 '_id': 'GtqC2tbwPZvqir4W5',
    #                 'name': 'ersti',
    #                 'aliases': ['blb', 'bad_luck_brian', 'erstie'],
    #                 'extension': 'png',
    #                 '_updatedAt': {'$date': 1539586118866}
    #             },
    #             ...
    #         ]
    #     """
    #     return await self.client.call("listEmojiCustom")

    async def load_history(
            self,
            room_id: str,
            num_msgs: int = 50,
            until: Optional[m.RcDatetime] = None,
            from_: Optional[m.RcDatetime] = None) -> m.LoadHistoryResult:
        """Use this method to make the initial load of a room. After the initial
        load you may subscribe to the room messages stream.

        Loads messages starting from the newest until either the until-date is
        reached or num_msgs is exceeded. from_ can be used to specify a start
        date.

        num_msgs: the maximum number of loaded messages

        until: load all messages until this date. May be None.

        from_: load messages starting from this date. Useful for pagination. May be None
        """
        response = await self.client.call("loadHistory", room_id, from_,
                                          num_msgs, until)
        if isinstance(response, dict):
            return m.LoadHistoryResult(**response)
        raise RocketClientException("Cannot access room")

    # async def getRoomRoles(self, *room_ids):
    #     """This method call is used to get room-wide special users and their
    #     roles. You may send a collection of room ids (at least one).
    #     """
    #     return await self.client.call("getRoomRoles", room_ids)

    async def get_all_rooms(self) -> List[m.Room]:
        """Get all the rooms a user belongs to.
        """
        response = await self.client.call("rooms/get")
        return [m.create(m.Room, r) for r in response]

    async def get_rooms_since(self, date: m.RcDatetime) -> m.GetRoomsResult:
        """This is the method call used to get all the rooms a user belongs
        to. It accepts a timestamp with the latest client update time in order
        to just send what changed since last call.
        """
        response = await self.client.call("rooms/get", date)
        return m.GetRoomsResult(**response)

    async def create_direct_message(self, username: str) -> str:
        """Get the room id for a direct message with a user
        """
        response = await self.client.call("createDirectMessage", username)
        return response['rid']

    async def send_message(self, roomId: str, message: str) -> m.Message:
        """Send a message to a room
        """
        response = await self.client.call("sendMessage", {
            "rid": roomId,
            "msg": message
        })
        return m.create(m.Message, response)

    async def update_message(self, message: m.Message) -> None:
        """Update a message
        """
        return await self.client.call("updateMessage", message)

    async def delete_message(self, messageId: str) -> None:
        """Delete a message
        """
        await self.client.call("deleteMessage", {"_id": messageId})

    async def set_reaction(self,
                           emojiId: str,
                           messageId: str,
                           flag: Optional[bool] = None) -> None:
        """React to a message

        Flag:
            True = set reaction
            False = unset reaction
            None = toggle reaction
        """
        await self.client.call("setReaction", emojiId, messageId, flag)

    async def subscribe_room(
            self, roomId: str, callback: Callable[[m.SubscriptionResult],
                                                  Awaitable]) -> Subscription:
        """Subscribe for updates for the given room
        """
        col = self.client.get_collection('stream-room-messages')
        col._data['id'] = {}

        col_q = col.get_queue()
        task = self.loop.create_task(
            _subscription_cb_wrapper(col_q, roomId, callback))
        self.tasks.append(task)

        if roomId not in self.subscriptions:
            self.subscriptions[roomId] = await self.client.subscribe(
                "stream-room-messages", roomId, True)
        return self.subscriptions[roomId]

    async def subscribe_my_messages(
            self, callback: Callable[[m.SubscriptionResult],
                                     Awaitable]) -> Subscription:
        """Subscribe to the personal '__my_messages__' topic which receives updates for:
        - all public channels (joined and unjoined)
        - all joined private groups
        - all direct messages"""
        return await self.subscribe_room('__my_messages__', callback)
Exemplo n.º 4
0
 def __init__(self, address):
     self.client = DDPClient(address)
Exemplo n.º 5
0
 def __init__(self, address: str, loop: asyncio.AbstractEventLoop) -> None:
     self.logged_in = False
     self.client = DDPClient(address)
     self.subscription_tasks: List[asyncio.Task[Any]] = []
     self.subscriptions: Dict[str, Subscription] = {}
     self.loop = loop
Exemplo n.º 6
0
 def __init__(self, address):
     self.client = DDPClient(address)
     self.uploader = MeteorFilesUploader(self.client, 'uploadedFiles')
Exemplo n.º 7
0
 def __init__(self, address):
     self.client = DDPClient(address)
     
     self.lists_subs = {}
Exemplo n.º 8
0
class TodoWatcher:
    def __init__(self, address):
        self.client = DDPClient(address)
        
        self.lists_subs = {}
    
    async def watch_lists(self, lists, lists_q):
        while True:
            event = await lists_q.get()
            
            if event.type == 'added':
                print('List created: "{}"'.format(event.fields.name))

                sub = await self.client.subscribe('todos.inList', {'listId': event._id})
                self.lists_subs[event._id] = sub
            
            elif event.type == 'changed':
                if event.fields.get('name'):
                    print('List renamed to "{}"'.format(event.fields.name))
            
            elif event.type == 'removed':
                print('List deleted: "{}"'.format(event._id))
                
                await self.client.unsubscribe(self.lists_subs[event._id])
                del self.lists_subs[event._id]

    async def watch_todos(self, todos, todos_q):
        while True:
            event = await todos_q.get()
            
            if event.type == 'added':
                print('Task created: "{}"'.format(event.fields.text))
            
            elif event.type == 'changed':
                if event.fields.get('name'):
                    print('Task changed to "{}"'.format(event.fields.text))
                
                if not event.fields.get('checked') == None:
                    if event.fields.checked:
                        print('Task marked complete: "{}"'.format(todos[event._id].text))
                    else:
                        print('Task marked incomplete: "{}"'.format(todos[event._id].text))
            
            elif event.type == 'removed':
                print('Task deleted: "{}"'.format(event._id))

    async def go(self, loop):
        print('Connecting to server...')
        
        while True:
            try:
                session = await self.client.connect()
            except ConnectionRefusedError or ConnectionResetError:
                await asyncio.sleep(1)
                continue
            
            print('Connected to server.')
            
            lists = self.client.get_collection('lists')
            lists_q = lists.get_queue()
            lists_task = loop.create_task(self.watch_lists(lists, lists_q))
            
            todos = self.client.get_collection('todos')
            todos_q = todos.get_queue()
            todos_task = loop.create_task(self.watch_todos(todos, todos_q))
            
            sub = await self.client.subscribe('lists.public')
            await sub.wait()
            
            await self.client.disconnection()
            print('Lost connection to server, attempting to reestablish...')
            
            lists_task.cancel()
            todos_task.cancel()