Exemple #1
0
    def _move_topic(
        self,
        message: Dict[str, Any],
        dest: str,
        count: int
    ) -> Union[Response, Iterable[Response]]:
        if count < 1:
            return Response.build_message(message, 'Error: Message count must be >= 1.')

        # Get the stream id ...
        stream_id: int = message['stream_id']
        # ... and the topic of the current message.
        topic: str = message['subject']

        # Get the message that is count "hops" before the given message
        # in this topic.
        request: Dict[str, Any] = {
            'anchor': 'newest',
            'num_before': count + 1,
            'num_after': 0,
            'narrow': [
                {'operator': 'stream', 'operand': stream_id},
                {'operator': 'topic', 'operand': topic},
                {'operator': 'near', 'operand': str(message['id'])}
            ]
        }
        result = self.client.get_messages(request)
        if result['result'] != 'success':
            return Response.error(message)
        if len(result['messages']) < 2:
            return Response.build_message(message, 'No message to move.')
        first_message: Dict[str, Any] = result['messages'][0]

        # Move message (and all following in the same topic) to the new topic.
        request = {
            'message_id': first_message['id'],
            'topic': dest,
            'stream_id': stream_id,
            'send_notification_to_old_thread': False,
            'send_notification_to_new_thread': False,
            'propagate_mode': 'change_later'
        }
        result = self.client.update_message(request)
        if result['result'] != 'success':
            return Response.error(message)

        # Remove requesting message.
        self.client.delete_message(message['id'])

        # Get current stream name.
        stream_name: Optional[str] = self.client.get_stream_name(stream_id)
        from_loc: str = (stream_name if stream_name is not None else "unknown") + ">" + topic
        to_loc: str = (stream_name if stream_name is not None else "unknown") + ">" + dest

        return Response.build_message(
            first_message,
            self.msg_template_topic.format(first_message['sender_full_name'], from_loc, to_loc),
            msg_type = 'private'
        )
Exemple #2
0
    def _move_stream(
        self,
        message: Dict[str, Any],
        dest: str
    ) -> Union[Response, Iterable[Response]]:
        # Get destination stream name.
        dest_stream: Optional[str] = Regex.get_stream_name(dest)
        if dest_stream is None:
            return Response.command_not_found(message)

        # Get destination stream id.
        result: Dict[str, Any] = self.client.get_stream_id(dest_stream)
        if result['result'] != 'success':
            return Response.error(message)
        dest_stream_id: int = result['stream_id']

        # Get the stream id ...
        src_stream_id: int = message['stream_id']
        # ... and the topic of the current message.
        topic: str = message['subject']

        # Get message which started the topic.
        request: Dict[str, Any] = {
            'anchor': 'oldest',
            'num_before': 0,
            'num_after': 1,
            'narrow': [
                { 'operator': 'stream', 'operand': src_stream_id },
                { 'operator': 'topic', 'operand': topic }
            ]
        }
        result = self.client.get_messages(request)
        if result['result'] != 'success':
            return Response.error(message)
        first_message: Dict[str, Any] = result['messages'][0]

        # Move message (and all following in the same topic) = move topic.
        request = {
            'message_id': first_message['id'],
            'topic': topic,
            'stream_id': dest_stream_id,
            'send_notification_to_old_thread': False,
            'propagate_mode': 'change_all'
        }
        result = self.client.update_message(request)
        if result['result'] != 'success':
            return Response.error(message)

        # Remove requesting message.
        self.client.delete_message(message['id'])

        return Response.build_message(
            first_message,
            self.msg_template_stream.format(first_message['sender_full_name'], topic, dest_stream),
            msg_type = 'private'
        )
Exemple #3
0
    def handle_message(
        self,
        message: Dict[str, Any],
        **kwargs: Any
    ) -> Union[Response, Iterable[Response]]:
        if not self.client.user_is_privileged(message['sender_id']):
            return Response.admin_err(message)

        failed: List[str] = []

        stream_tuples: Optional[List[Any]] = split(
            message['command'], converter = [lambda t: split(
                t, sep = ',', exact_split = 2, discard_empty = False
            )]
        )
        if stream_tuples is None or None in stream_tuples:
            return Response.error(message)

        for stream, desc in stream_tuples:
            if not stream:
                failed.append('one empty stream name')
                continue
            result: Dict[str, Any] = self.client.add_subscriptions(
                streams = [{'name': stream, 'description': desc}]
            )
            if result['result'] != 'success':
                failed.append(f'stream: {stream}, description: {desc}')

        if not failed:
            return Response.ok(message)

        response: str = 'Failed to create the following streams:\n' + '\n'.join(failed)

        return Response.build_message(message, response, msg_type = 'private')
Exemple #4
0
    def subscribe_users(
        self, message: Dict[str, Any], dest_stream: str,
        users: List[Union[str, Tuple[str, Optional[int]]]]
    ) -> Union[Response, Iterable[Response]]:
        # First, get all the ids of the users whose ids we do not already know.
        user_ids: Optional[
            List[int]] = self.client.get_user_ids_from_display_names(
                map(
                    lambda o: o[0] if isinstance(o, tuple) else o,
                    filter(
                        lambda o: isinstance(o, str) or
                        (isinstance(o, tuple) and o[1] is None), users)))
        if user_ids is None:
            return Response.build_message(
                message, 'error: could not get the user ids.')

        user_ids.extend(
            map(
                lambda t: cast(int, t[1]),
                filter(
                    lambda o: isinstance(o, tuple) and isinstance(o[1], int),
                    users)))

        if not self.client.subscribe_users(user_ids, dest_stream):
            return Response.error(message)

        return Response.ok(message)
Exemple #5
0
    def subscribe_all_users(
        self,
        message: Dict[str, Any],
        dest_stream: str,
    ) -> Union[Response, Iterable[Response]]:
        if not self.client.user_is_privileged(message['sender_id']):
            return Response.admin_err(message)

        result: Dict[str, Any] = self.client.get_users()
        if result['result'] != 'success':
            return Response.error(message)
        user_ids: List[int] = [user['user_id'] for user in result['members']]

        if not self.client.subscribe_users(user_ids, dest_stream):
            return Response.error(message)

        return Response.ok(message)
Exemple #6
0
    def subscribe_user_emails(
            self, message: Dict[str, Any], dest_stream: str,
            user_emails: List[str]) -> Union[Response, Iterable[Response]]:
        user_ids: Optional[List[int]] = self.client.get_user_ids_from_emails(
            user_emails)
        if user_ids is None:
            return Response.build_message(
                message, 'error: could not get the user ids.')

        if not self.client.subscribe_users(
                user_ids, dest_stream, allow_private_streams=True):
            return Response.error(message)

        return Response.ok(message)
Exemple #7
0
    def handle_message(
        self,
        message: Dict[str, Any],
        **kwargs: Any
    ) -> Union[Response, Iterable[Response]]:
        if not self.client.user_is_privileged(message['sender_id']):
            return Response.admin_err(message)

        failed: List[str] = []

        stream_tuples: Optional[List[Any]] = split(
            message['command'], converter = [lambda t: split(t, sep = ',', exact_split = 2)]
        )
        if stream_tuples is None or None in stream_tuples:
            return Response.error(message)

        for old, new in stream_tuples:
            # Used for error messages.
            line: str = f'{old} -> {new}'

            try:
                old_id: int = self.client.get_stream_id(old)['stream_id']
            except Exception as e:
                logging.exception(e)
                failed.append(line)
                continue

            result: Dict[str, Any] = self.client.update_stream(
                {'stream_id': old_id, 'new_name': '"{}"'.format(new)}
            )
            if result['result'] != 'success':
                failed.append(line)

        if not failed:
            return Response.ok(message)

        response: str = 'Failed to perform the following renamings:\n' + '\n'.join(failed)

        return Response.build_message(message, response, msg_type = 'private')