def build_bot_request(self, event: Dict[str, Any]) -> Optional[Any]: # Because we don't have a place for the recipient of an # outgoing webhook to indicate whether it wants the raw # Markdown or the rendered HTML, we leave both the content and # rendered_content fields in the message payload. MessageDict.finalize_payload(event['message'], False, False, keep_rendered_content=True) request_data = {"data": event['command'], "message": event['message'], "bot_email": self.user_profile.email, "token": self.token, "trigger": event['trigger']} return json.dumps(request_data)
def get_client_payload(apply_markdown: bool, client_gravatar: bool) -> Dict[str, Any]: dct = copy.deepcopy(wide_dict) # Temporary transitional code: Zulip servers that have message # events in their event queues and upgrade to the new version # that expects sender_delivery_email in these events will # throw errors processing events. We can remove this block # once we don't expect anyone to be directly upgrading from # 2.0.x to the latest Zulip. if 'sender_delivery_email' not in dct: # nocoverage dct['sender_delivery_email'] = dct['sender_email'] MessageDict.finalize_payload(dct, apply_markdown, client_gravatar) return dct
def get_client_payload(apply_markdown: bool, client_gravatar: bool) -> Dict[str, Any]: return MessageDict.finalize_payload( wide_dict, apply_markdown=apply_markdown, client_gravatar=client_gravatar, )
def make_request(self, base_url: str, event: Dict[str, Any]) -> Optional[Response]: """ We send a simple version of the message to outgoing webhooks, since most of them really only need `content` and a few other fields. We may eventually allow certain bots to get more information, but that's not a high priority. We do send the gravatar info to the clients (so they don't have to compute it themselves). """ message_dict = MessageDict.finalize_payload( event["message"], apply_markdown=False, client_gravatar=False, keep_rendered_content=True, ) request_data = { "data": event["command"], "message": message_dict, "bot_email": self.user_profile.email, "bot_full_name": self.user_profile.full_name, "token": self.token, "trigger": event["trigger"], } return self.session.post(base_url, json=request_data)
def build_bot_request(self, event: Dict[str, Any]) -> Optional[Any]: ''' We send a simple version of the message to outgoing webhooks, since most of them really only need `content` and a few other fields. We may eventually allow certain bots to get more information, but that's not a high priority. We do send the gravatar info to the clients (so they don't have to compute it themselves). ''' message_dict = MessageDict.finalize_payload( event['message'], apply_markdown=False, client_gravatar=False, keep_rendered_content=True, ) request_data = { "data": event['command'], "message": message_dict, "bot_email": self.user_profile.email, "token": self.token, "trigger": event['trigger'] } return json.dumps(request_data)
def get_send_message_payload(msg_id: int, apply_markdown: bool, client_gravatar: bool) -> Dict[str, Any]: msg = reload_message(msg_id) wide_dict = MessageDict.wide_dict(msg) narrow_dict = MessageDict.finalize_payload( wide_dict, apply_markdown=apply_markdown, client_gravatar=client_gravatar, ) return narrow_dict
def get_client_payload(apply_markdown: bool, client_gravatar: bool) -> Dict[str, Any]: dct = copy.deepcopy(wide_dict) MessageDict.finalize_payload(dct, apply_markdown, client_gravatar) return dct
def process_message_event(event_template, users): # type: (Mapping[str, Any], Iterable[Mapping[str, Any]]) -> None send_to_clients = get_client_info_for_message_event(event_template, users) presence_idle_user_ids = set( event_template.get('presence_idle_user_ids', [])) message_dict = event_template['message_dict'] # type: Dict[str, Any] sender_id = message_dict['sender_id'] # type: int message_id = message_dict['id'] # type: int message_type = message_dict['type'] # type: str sending_client = message_dict['client'] # type: Text message_dict_html = copy.deepcopy(message_dict) MessageDict.finalize_payload(message_dict_html, apply_markdown=True) message_dict_text = copy.deepcopy(message_dict) MessageDict.finalize_payload(message_dict_text, apply_markdown=False) # Extra user-specific data to include extra_user_data = {} # type: Dict[int, Any] for user_data in users: user_profile_id = user_data['id'] # type: int flags = user_data.get('flags', []) # type: Iterable[str] # If the recipient was offline and the message was a single or group PM to them # or they were @-notified potentially notify more immediately private_message = message_type == "private" and user_profile_id != sender_id mentioned = 'mentioned' in flags and 'read' not in flags stream_push_notify = user_data.get('stream_push_notify', False) # We first check if a message is potentially mentionable, # since receiver_is_off_zulip is somewhat expensive. if private_message or mentioned or stream_push_notify: idle = receiver_is_off_zulip(user_profile_id) or ( user_profile_id in presence_idle_user_ids) always_push_notify = user_data.get('always_push_notify', False) stream_name = event_template.get('stream_name') result = maybe_enqueue_notifications(user_profile_id, message_id, private_message, mentioned, stream_push_notify, stream_name, always_push_notify, idle, {}) result['stream_push_notify'] = stream_push_notify extra_user_data[user_profile_id] = result for client_data in send_to_clients.values(): client = client_data['client'] flags = client_data['flags'] is_sender = client_data.get('is_sender', False) # type: bool extra_data = extra_user_data.get( client.user_profile_id, None) # type: Optional[Mapping[str, bool]] if not client.accepts_messages(): # The actual check is the accepts_event() check below; # this line is just an optimization to avoid copying # message data unnecessarily continue if client.apply_markdown: message_dict = message_dict_html else: message_dict = message_dict_text # Make sure Zephyr mirroring bots know whether stream is invite-only if "mirror" in client.client_type_name and event_template.get( "invite_only"): message_dict = message_dict.copy() message_dict["invite_only_stream"] = True user_event = dict(type='message', message=message_dict, flags=flags) # type: Dict[str, Any] if extra_data is not None: user_event.update(extra_data) if is_sender: local_message_id = event_template.get('local_id', None) if local_message_id is not None: user_event["local_message_id"] = local_message_id if not client.accepts_event(user_event): continue # The below prevents (Zephyr) mirroring loops. if ('mirror' in sending_client and sending_client.lower() == client.client_type_name.lower()): continue client.add_event(user_event)
def process_message_event(event_template, users): # type: (Mapping[str, Any], Iterable[Mapping[str, Any]]) -> None send_to_clients = get_client_info_for_message_event(event_template, users) presence_idle_user_ids = set(event_template.get('presence_idle_user_ids', [])) message_dict = event_template['message_dict'] # type: Dict[str, Any] sender_id = message_dict['sender_id'] # type: int message_id = message_dict['id'] # type: int message_type = message_dict['type'] # type: str sending_client = message_dict['client'] # type: Text message_dict_html = copy.deepcopy(message_dict) MessageDict.finalize_payload(message_dict_html, apply_markdown=True) message_dict_text = copy.deepcopy(message_dict) MessageDict.finalize_payload(message_dict_text, apply_markdown=False) # Extra user-specific data to include extra_user_data = {} # type: Dict[int, Any] for user_data in users: user_profile_id = user_data['id'] # type: int flags = user_data.get('flags', []) # type: Iterable[str] # If the recipient was offline and the message was a single or group PM to them # or they were @-notified potentially notify more immediately private_message = message_type == "private" and user_profile_id != sender_id mentioned = 'mentioned' in flags and 'read' not in flags stream_push_notify = user_data.get('stream_push_notify', False) # We first check if a message is potentially mentionable, # since receiver_is_off_zulip is somewhat expensive. if private_message or mentioned or stream_push_notify: idle = receiver_is_off_zulip(user_profile_id) or (user_profile_id in presence_idle_user_ids) always_push_notify = user_data.get('always_push_notify', False) stream_name = event_template.get('stream_name') result = maybe_enqueue_notifications(user_profile_id, message_id, private_message, mentioned, stream_push_notify, stream_name, always_push_notify, idle, {}) result['stream_push_notify'] = stream_push_notify extra_user_data[user_profile_id] = result for client_data in send_to_clients.values(): client = client_data['client'] flags = client_data['flags'] is_sender = client_data.get('is_sender', False) # type: bool extra_data = extra_user_data.get(client.user_profile_id, None) # type: Optional[Mapping[str, bool]] if not client.accepts_messages(): # The actual check is the accepts_event() check below; # this line is just an optimization to avoid copying # message data unnecessarily continue if client.apply_markdown: message_dict = message_dict_html else: message_dict = message_dict_text # Make sure Zephyr mirroring bots know whether stream is invite-only if "mirror" in client.client_type_name and event_template.get("invite_only"): message_dict = message_dict.copy() message_dict["invite_only_stream"] = True user_event = dict(type='message', message=message_dict, flags=flags) # type: Dict[str, Any] if extra_data is not None: user_event.update(extra_data) if is_sender: local_message_id = event_template.get('local_id', None) if local_message_id is not None: user_event["local_message_id"] = local_message_id if not client.accepts_event(user_event): continue # The below prevents (Zephyr) mirroring loops. if ('mirror' in sending_client and sending_client.lower() == client.client_type_name.lower()): continue client.add_event(user_event)
def get_client_payload(apply_markdown, client_gravatar): # type: (bool, bool) -> Mapping[str, Any] dct = copy.deepcopy(wide_dict) MessageDict.finalize_payload(dct, apply_markdown, client_gravatar) return dct