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' )
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' )
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')
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)
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)
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)
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')