mirror of
https://github.com/zulip/zulip.git
synced 2025-11-09 08:26:11 +00:00
python: Reformat with Black, except quotes.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
committed by
Tim Abbott
parent
5028c081cb
commit
11741543da
@@ -26,7 +26,6 @@ from zerver.models import (
|
||||
|
||||
|
||||
class OutgoingWebhookServiceInterface(metaclass=abc.ABCMeta):
|
||||
|
||||
def __init__(self, token: str, user_profile: UserProfile, service_name: str) -> None:
|
||||
self.token: str = token
|
||||
self.user_profile: UserProfile = user_profile
|
||||
@@ -44,10 +43,10 @@ class OutgoingWebhookServiceInterface(metaclass=abc.ABCMeta):
|
||||
def process_success(self, response_json: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||
raise NotImplementedError
|
||||
|
||||
class GenericOutgoingWebhookService(OutgoingWebhookServiceInterface):
|
||||
|
||||
class GenericOutgoingWebhookService(OutgoingWebhookServiceInterface):
|
||||
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
|
||||
@@ -55,7 +54,7 @@ class GenericOutgoingWebhookService(OutgoingWebhookServiceInterface):
|
||||
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,
|
||||
@@ -63,16 +62,16 @@ class GenericOutgoingWebhookService(OutgoingWebhookServiceInterface):
|
||||
keep_rendered_content=True,
|
||||
)
|
||||
|
||||
request_data = {"data": event['command'],
|
||||
"message": message_dict,
|
||||
"bot_email": self.user_profile.email,
|
||||
"token": self.token,
|
||||
"trigger": event['trigger']}
|
||||
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 send_data_to_server(self,
|
||||
base_url: str,
|
||||
request_data: Any) -> Response:
|
||||
def send_data_to_server(self, base_url: str, request_data: Any) -> Response:
|
||||
user_agent = 'ZulipOutgoingWebhook/' + ZULIP_VERSION
|
||||
headers = {
|
||||
'content-type': 'application/json',
|
||||
@@ -100,32 +99,31 @@ class GenericOutgoingWebhookService(OutgoingWebhookServiceInterface):
|
||||
|
||||
return None
|
||||
|
||||
class SlackOutgoingWebhookService(OutgoingWebhookServiceInterface):
|
||||
|
||||
class SlackOutgoingWebhookService(OutgoingWebhookServiceInterface):
|
||||
def build_bot_request(self, event: Dict[str, Any]) -> Optional[Any]:
|
||||
if event['message']['type'] == 'private':
|
||||
failure_message = "Slack outgoing webhooks don't support private messages."
|
||||
fail_with_message(event, failure_message)
|
||||
return None
|
||||
|
||||
request_data = [("token", self.token),
|
||||
("team_id", event['message']['sender_realm_str']),
|
||||
("team_domain", email_to_domain(event['message']['sender_email'])),
|
||||
("channel_id", event['message']['stream_id']),
|
||||
("channel_name", event['message']['display_recipient']),
|
||||
("timestamp", event['message']['timestamp']),
|
||||
("user_id", event['message']['sender_id']),
|
||||
("user_name", event['message']['sender_full_name']),
|
||||
("text", event['command']),
|
||||
("trigger_word", event['trigger']),
|
||||
("service_id", event['user_profile_id']),
|
||||
]
|
||||
request_data = [
|
||||
("token", self.token),
|
||||
("team_id", event['message']['sender_realm_str']),
|
||||
("team_domain", email_to_domain(event['message']['sender_email'])),
|
||||
("channel_id", event['message']['stream_id']),
|
||||
("channel_name", event['message']['display_recipient']),
|
||||
("timestamp", event['message']['timestamp']),
|
||||
("user_id", event['message']['sender_id']),
|
||||
("user_name", event['message']['sender_full_name']),
|
||||
("text", event['command']),
|
||||
("trigger_word", event['trigger']),
|
||||
("service_id", event['user_profile_id']),
|
||||
]
|
||||
|
||||
return request_data
|
||||
|
||||
def send_data_to_server(self,
|
||||
base_url: str,
|
||||
request_data: Any) -> Response:
|
||||
def send_data_to_server(self, base_url: str, request_data: Any) -> Response:
|
||||
response = requests.request('POST', base_url, data=request_data)
|
||||
return response
|
||||
|
||||
@@ -137,26 +135,32 @@ class SlackOutgoingWebhookService(OutgoingWebhookServiceInterface):
|
||||
|
||||
return None
|
||||
|
||||
|
||||
AVAILABLE_OUTGOING_WEBHOOK_INTERFACES: Dict[str, Any] = {
|
||||
GENERIC_INTERFACE: GenericOutgoingWebhookService,
|
||||
SLACK_INTERFACE: SlackOutgoingWebhookService,
|
||||
}
|
||||
|
||||
|
||||
def get_service_interface_class(interface: str) -> Any:
|
||||
if interface not in AVAILABLE_OUTGOING_WEBHOOK_INTERFACES:
|
||||
return AVAILABLE_OUTGOING_WEBHOOK_INTERFACES[GENERIC_INTERFACE]
|
||||
else:
|
||||
return AVAILABLE_OUTGOING_WEBHOOK_INTERFACES[interface]
|
||||
|
||||
|
||||
def get_outgoing_webhook_service_handler(service: Service) -> Any:
|
||||
|
||||
service_interface_class = get_service_interface_class(service.interface_name())
|
||||
service_interface = service_interface_class(token=service.token,
|
||||
user_profile=service.user_profile,
|
||||
service_name=service.name)
|
||||
service_interface = service_interface_class(
|
||||
token=service.token, user_profile=service.user_profile, service_name=service.name
|
||||
)
|
||||
return service_interface
|
||||
|
||||
def send_response_message(bot_id: int, message_info: Dict[str, Any], response_data: Dict[str, Any]) -> None:
|
||||
|
||||
def send_response_message(
|
||||
bot_id: int, message_info: Dict[str, Any], response_data: Dict[str, Any]
|
||||
) -> None:
|
||||
"""
|
||||
bot_id is the user_id of the bot sending the response
|
||||
|
||||
@@ -203,6 +207,7 @@ def send_response_message(bot_id: int, message_info: Dict[str, Any], response_da
|
||||
realm=realm,
|
||||
)
|
||||
|
||||
|
||||
def fail_with_message(event: Dict[str, Any], failure_message: str) -> None:
|
||||
bot_id = event['user_profile_id']
|
||||
message_info = event['message']
|
||||
@@ -210,6 +215,7 @@ def fail_with_message(event: Dict[str, Any], failure_message: str) -> None:
|
||||
response_data = dict(content=content)
|
||||
send_response_message(bot_id=bot_id, message_info=message_info, response_data=response_data)
|
||||
|
||||
|
||||
def get_message_url(event: Dict[str, Any]) -> str:
|
||||
bot_user = get_user_profile_by_id(event['user_profile_id'])
|
||||
message = event['message']
|
||||
@@ -220,11 +226,14 @@ def get_message_url(event: Dict[str, Any]) -> str:
|
||||
message=message,
|
||||
)
|
||||
|
||||
def notify_bot_owner(event: Dict[str, Any],
|
||||
status_code: Optional[int]=None,
|
||||
response_content: Optional[AnyStr]=None,
|
||||
failure_message: Optional[str]=None,
|
||||
exception: Optional[Exception]=None) -> None:
|
||||
|
||||
def notify_bot_owner(
|
||||
event: Dict[str, Any],
|
||||
status_code: Optional[int] = None,
|
||||
response_content: Optional[AnyStr] = None,
|
||||
failure_message: Optional[str] = None,
|
||||
exception: Optional[Exception] = None,
|
||||
) -> None:
|
||||
message_url = get_message_url(event)
|
||||
bot_id = event['user_profile_id']
|
||||
bot_owner = get_user_profile_by_id(bot_id).bot_owner
|
||||
@@ -236,10 +245,14 @@ def notify_bot_owner(event: Dict[str, Any],
|
||||
if status_code:
|
||||
notification_message += f"\nThe webhook got a response with status code *{status_code}*."
|
||||
if response_content:
|
||||
notification_message += f"\nThe response contains the following payload:\n```\n{response_content!r}\n```"
|
||||
notification_message += (
|
||||
f"\nThe response contains the following payload:\n```\n{response_content!r}\n```"
|
||||
)
|
||||
if exception:
|
||||
notification_message += "\nWhen trying to send a request to the webhook service, an exception " \
|
||||
f"of type {type(exception).__name__} occurred:\n```\n{exception}\n```"
|
||||
notification_message += (
|
||||
"\nWhen trying to send a request to the webhook service, an exception "
|
||||
f"of type {type(exception).__name__} occurred:\n```\n{exception}\n```"
|
||||
)
|
||||
|
||||
message_info = dict(
|
||||
type='private',
|
||||
@@ -248,8 +261,8 @@ def notify_bot_owner(event: Dict[str, Any],
|
||||
response_data = dict(content=notification_message)
|
||||
send_response_message(bot_id=bot_id, message_info=message_info, response_data=response_data)
|
||||
|
||||
def request_retry(event: Dict[str, Any],
|
||||
failure_message: Optional[str]=None) -> None:
|
||||
|
||||
def request_retry(event: Dict[str, Any], failure_message: Optional[str] = None) -> None:
|
||||
def failure_processor(event: Dict[str, Any]) -> None:
|
||||
"""
|
||||
The name of the argument is 'event' on purpose. This argument will hide
|
||||
@@ -261,14 +274,16 @@ def request_retry(event: Dict[str, Any],
|
||||
notify_bot_owner(event, failure_message=failure_message)
|
||||
logging.warning(
|
||||
"Maximum retries exceeded for trigger:%s event:%s",
|
||||
bot_user.email, event['command'],
|
||||
bot_user.email,
|
||||
event['command'],
|
||||
)
|
||||
|
||||
retry_event('outgoing_webhooks', event, failure_processor)
|
||||
|
||||
def process_success_response(event: Dict[str, Any],
|
||||
service_handler: Any,
|
||||
response: Response) -> None:
|
||||
|
||||
def process_success_response(
|
||||
event: Dict[str, Any], service_handler: Any, response: Response
|
||||
) -> None:
|
||||
try:
|
||||
response_json = json.loads(response.text)
|
||||
except json.JSONDecodeError:
|
||||
@@ -291,10 +306,10 @@ def process_success_response(event: Dict[str, Any],
|
||||
response_data = dict(content=content, widget_content=widget_content)
|
||||
send_response_message(bot_id=bot_id, message_info=message_info, response_data=response_data)
|
||||
|
||||
def do_rest_call(base_url: str,
|
||||
request_data: Any,
|
||||
event: Dict[str, Any],
|
||||
service_handler: Any) -> Optional[Response]:
|
||||
|
||||
def do_rest_call(
|
||||
base_url: str, request_data: Any, event: Dict[str, Any], service_handler: Any
|
||||
) -> Optional[Response]:
|
||||
"""Returns response of call if no exception occurs."""
|
||||
try:
|
||||
response = service_handler.send_data_to_server(
|
||||
@@ -304,12 +319,16 @@ def do_rest_call(base_url: str,
|
||||
if str(response.status_code).startswith('2'):
|
||||
process_success_response(event, service_handler, response)
|
||||
else:
|
||||
logging.warning("Message %(message_url)s triggered an outgoing webhook, returning status "
|
||||
"code %(status_code)s.\n Content of response (in quotes): \""
|
||||
"%(response)s\"",
|
||||
{'message_url': get_message_url(event),
|
||||
'status_code': response.status_code,
|
||||
'response': response.text})
|
||||
logging.warning(
|
||||
"Message %(message_url)s triggered an outgoing webhook, returning status "
|
||||
"code %(status_code)s.\n Content of response (in quotes): \""
|
||||
"%(response)s\"",
|
||||
{
|
||||
'message_url': get_message_url(event),
|
||||
'status_code': response.status_code,
|
||||
'response': response.text,
|
||||
},
|
||||
)
|
||||
failure_message = f"Third party responded with {response.status_code}"
|
||||
fail_with_message(event, failure_message)
|
||||
notify_bot_owner(event, response.status_code, response.content)
|
||||
@@ -317,15 +336,19 @@ def do_rest_call(base_url: str,
|
||||
except requests.exceptions.Timeout:
|
||||
logging.info(
|
||||
"Trigger event %s on %s timed out. Retrying",
|
||||
event["command"], event['service_name'],
|
||||
event["command"],
|
||||
event['service_name'],
|
||||
)
|
||||
failure_message = "A timeout occurred."
|
||||
request_retry(event, failure_message=failure_message)
|
||||
return None
|
||||
|
||||
except requests.exceptions.ConnectionError:
|
||||
logging.info("Trigger event %s on %s resulted in a connection error. Retrying",
|
||||
event["command"], event['service_name'])
|
||||
logging.info(
|
||||
"Trigger event %s on %s resulted in a connection error. Retrying",
|
||||
event["command"],
|
||||
event['service_name'],
|
||||
)
|
||||
failure_message = "A connection error occurred. Is my bot server down?"
|
||||
request_retry(event, failure_message=failure_message)
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user