Skip to content

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