Slack
wagtail_live.receivers.slack.receivers.SlackWebhookMixin
Slack WebhookMixin.
post(self, request, *args, **kwargs)
Checks if Slack is trying to verify our Request URL.
Returns:
Type | Description |
---|---|
HttpResponse |
containing the challenge string if Slack is trying to verify our request URL. |
Source code in wagtail_live/receivers/slack/receivers.py
def post(self, request, *args, **kwargs):
"""
Checks if Slack is trying to verify our Request URL.
Returns:
HttpResponse:
containing the challenge string if Slack is trying to verify our request URL.
"""
payload = json.loads(request.body.decode("utf-8"))
if payload["type"] == "url_verification":
return HttpResponse(payload["challenge"], content_type="plain/text")
return super().post(request, *args, **kwargs)
set_webhook()
classmethod
This is done in Slack UI.
Source code in wagtail_live/receivers/slack/receivers.py
@classmethod
def set_webhook(cls):
"""This is done in Slack UI."""
pass
sign_slack_request(content)
staticmethod
Signs content from a Slack request using the SLACK_SIGNING_SECRET
as key.
Source code in wagtail_live/receivers/slack/receivers.py
@staticmethod
def sign_slack_request(content):
"""Signs content from a Slack request using the `SLACK_SIGNING_SECRET` as key."""
hasher = hmac.new(str.encode(settings.SLACK_SIGNING_SECRET), digestmod=sha256)
hasher.update(str.encode(content))
return hasher.hexdigest()
verify_request(self, request, body)
Verifies Slack requests. See: Verifying requests from Slack.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
request |
HttpRequest |
from Slack |
required |
Exceptions:
Type | Description |
---|---|
RequestVerificationError |
if request failed to be verified. |
Source code in wagtail_live/receivers/slack/receivers.py
def verify_request(self, request, body):
"""
Verifies Slack requests.
See: [Verifying requests from Slack](https://api.slack.com/authentication/
verifying-requests-from-slack).
Args:
request (HttpRequest): from Slack
Raises:
RequestVerificationError: if request failed to be verified.
"""
timestamp = request.headers.get("X-Slack-Request-Timestamp")
if not timestamp:
raise RequestVerificationError(
"X-Slack-Request-Timestamp not found in request's headers."
)
if abs(time.time() - float(timestamp)) > 60 * 5:
# The request timestamp is more than five minutes from local time.
# It could be a replay attack, so let's ignore it.
raise RequestVerificationError(
"The request timestamp is more than five minutes from local time."
)
sig_basestring = "v0:" + timestamp + ":" + body
my_signature = "v0=" + self.sign_slack_request(content=sig_basestring)
slack_signature = request.headers["X-Slack-Signature"]
if not hmac.compare_digest(slack_signature, my_signature):
raise RequestVerificationError("Slack signature couldn't be verified.")
webhook_connection_set()
classmethod
Assume that it's true.
Source code in wagtail_live/receivers/slack/receivers.py
@classmethod
def webhook_connection_set(cls):
"""Assume that it's true."""
return True
wagtail_live.receivers.slack.receivers.SlackEventsAPIReceiver
Slack Events API receiver.
dispatch_event(self, event)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def dispatch_event(self, event):
"""See base class."""
message = event["event"]
subtype = message.get("subtype")
if subtype:
if subtype == "message_changed":
self.change_message(message=message)
elif subtype == "message_deleted":
self.delete_message(message=message)
elif subtype == "file_share":
self.add_message(message=message)
return
self.add_message(message=message)
get_channel_id_from_message(self, message)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def get_channel_id_from_message(self, message):
"""See base class."""
return message["channel"]
get_embed(self, text)
Slack sends url in this format:
<https://twitter.com/wagtail/|https://twitter.com/wagtail/>
where the first part is the full url and the second part represents the user's input.
See Links in retrieved messages.
Source code in wagtail_live/receivers/slack/receivers.py
def get_embed(self, text):
"""
Slack sends url in this format:
`<https://twitter.com/wagtail/|https://twitter.com/wagtail/>`
where the first part is the full url and the second part represents the user's input.
See [Links in retrieved messages](https://api.slack.com/reference/surfaces/
formatting#links-in-retrieved-messages).
"""
# Check if the text provided is a Slack-like url
if text.startswith("<") and text.endswith(">"):
# Get the url resolved by Slack
url = text[1:-1].split("|")[0]
if is_embed(text=url):
return url
return ""
get_image_content(self, image)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def get_image_content(self, image):
"""See base class."""
slack_bot_token = getattr(settings, "SLACK_BOT_TOKEN", "")
if not slack_bot_token:
raise ImproperlyConfigured(
"You haven't specified SLACK_BOT_TOKEN in your settings."
+ "You won't be able to upload images from Slack without this setting defined."
)
headers = {"Authorization": f"Bearer {slack_bot_token}"}
response = requests.get(image["url_private"], headers=headers)
return ContentFile(response.content)
get_image_dimensions(self, image)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def get_image_dimensions(self, image):
"""See base class."""
try:
return (image["original_w"], image["original_h"])
except KeyError:
raise ValueError
get_image_mimetype(self, image)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def get_image_mimetype(self, image):
"""See base class."""
return image["mimetype"].split("/")[1]
get_image_name(self, image)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def get_image_name(self, image):
"""See base class."""
return image["name"]
get_image_title(self, image)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def get_image_title(self, image):
"""See base class."""
return image["title"]
get_message_files(self, message)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def get_message_files(self, message):
"""See base class."""
return message["files"] if "files" in message else []
get_message_files_from_edited_message(self, message)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def get_message_files_from_edited_message(self, message):
"""See base class."""
return self.get_message_files(message=message["message"])
get_message_id_from_edited_message(self, message)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def get_message_id_from_edited_message(self, message):
"""See base class."""
return self.get_message_id_from_message(message=message["previous_message"])
get_message_id_from_message(self, message)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def get_message_id_from_message(self, message):
"""See base class."""
return message["ts"]
get_message_text(self, message)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def get_message_text(self, message):
"""See base class."""
return message["text"]
get_message_text_from_edited_message(self, message)
See base class.
Source code in wagtail_live/receivers/slack/receivers.py
def get_message_text_from_edited_message(self, message):
"""See base class."""
return self.get_message_text(message=message["message"])
parse_text(self, text)
See Links in retrieved messages.
See also base class.
Source code in wagtail_live/receivers/slack/receivers.py
def parse_text(self, text):
"""
See [Links in retrieved messages](https://api.slack.com/reference/surfaces/
formatting#links-in-retrieved-messages).
See also base class.
"""
url_format = re.compile(r"<http([^|]+?)(\|([^|]+?))?>")
urls = url_format.finditer(text)
for url_match in urls:
match = url_match.group()[1:-1]
if "|" in match:
url, description = match.split("|")
else:
url = description = match
try:
validator = URLValidator()
validator(url)
except ValidationError:
continue
text = text.replace(url_match.group(), f"<a href='{url}'>{description}</a>")
return text