Skip to content

Models

django_slack_tools.slack_messages.models.SlackMention

Bases: TimestampMixin, Model

People or group in channels receive messages.

Source code in django_slack_tools/slack_messages/models/mention.py
class SlackMention(TimestampMixin, models.Model):
    """People or group in channels receive messages."""

    class MentionType(models.TextChoices):
        """Possible mention types."""

        USER = "U", _("User")
        "User mentions. e.g. `@lasuillard`."

        GROUP = "G", _("Group")
        "Team mentions. e.g. `@backend`."

        SPECIAL = "S", _("Special")
        "Special mentions. e.g. `@here`, `@channel`, `@everyone`."

        UNKNOWN = "?", _("Unknown")
        "Unknown mention type."

    type = models.CharField(
        verbose_name=_("Type"),
        help_text=_("Type of mentions."),
        max_length=1,
        choices=MentionType.choices,
        blank=False,
    )
    name = models.CharField(
        verbose_name=_("Name"),
        help_text=_("Human-friendly mention name."),
        max_length=128,
    )
    mention_id = models.CharField(
        verbose_name=_("Mention ID"),
        help_text=_("User or group ID, or raw mention itself."),
        max_length=32,
    )

    objects: SlackMentionManager = SlackMentionManager()

    class Meta:  # noqa: D106
        verbose_name = _("Mention")
        verbose_name_plural = _("Mentions")

    def __str__(self) -> str:
        return _("{name} ({type}, {mention_id})").format(
            name=self.name,
            type=self.get_type_display(),
            mention_id=self.mention_id,
        )

    @property
    def mention(self) -> str:
        """Mention string for use in messages, e.g. `"<@{USER_ID}>"`."""
        if self.type == SlackMention.MentionType.USER:
            return f"<@{self.mention_id}>"

        if self.type == SlackMention.MentionType.GROUP:
            return f"<!subteam^{self.mention_id}>"

        return self.mention_id

mention: str property

Mention string for use in messages, e.g. "<@{USER_ID}>".

MentionType

Bases: TextChoices

Possible mention types.

Source code in django_slack_tools/slack_messages/models/mention.py
class MentionType(models.TextChoices):
    """Possible mention types."""

    USER = "U", _("User")
    "User mentions. e.g. `@lasuillard`."

    GROUP = "G", _("Group")
    "Team mentions. e.g. `@backend`."

    SPECIAL = "S", _("Special")
    "Special mentions. e.g. `@here`, `@channel`, `@everyone`."

    UNKNOWN = "?", _("Unknown")
    "Unknown mention type."

GROUP = ('G', _('Group')) class-attribute instance-attribute

Team mentions. e.g. @backend.

SPECIAL = ('S', _('Special')) class-attribute instance-attribute

Special mentions. e.g. @here, @channel, @everyone.

UNKNOWN = ('?', _('Unknown')) class-attribute instance-attribute

Unknown mention type.

USER = ('U', _('User')) class-attribute instance-attribute

User mentions. e.g. @lasuillard.

django_slack_tools.slack_messages.models.SlackMessage

Bases: TimestampMixin, Model

An Slack message.

Source code in django_slack_tools/slack_messages/models/message.py
class SlackMessage(TimestampMixin, models.Model):
    """An Slack message."""

    policy = models.ForeignKey(
        SlackMessagingPolicy,
        verbose_name=_("Messaging Policy"),
        help_text=_("Messaging policy for this message."),
        null=True,  # Message can be built from scratch without using templates
        blank=True,
        on_delete=models.SET_NULL,
    )
    channel = models.CharField(
        verbose_name=_("Channel"),
        help_text=_("ID of channel this message sent to."),
        blank=False,
        max_length=128,  # Maximum length of channel name is 80 characters
    )
    header = models.JSONField(
        verbose_name=_("Header"),
        help_text=_(
            "Slack control arguments."
            " Allowed fields are `mrkdwn`, `parse`, `reply_broadcast`, `thread_ts`, `unfurl_links`, `unfurl_media`.",
        ),
        validators=[header_validator],
    )
    body = models.JSONField(
        verbose_name=_("Body"),
        help_text=_(
            "Message body."
            " Allowed fields are `attachments`, `body`, `text`, `icon_emoji`, `icon_url`, `metadata`, `username`.",
        ),
        validators=[body_validator],
    )
    ok = models.BooleanField(
        verbose_name=_("OK"),
        help_text=_("Whether Slack API respond with OK. If never sent, will be `null`."),
        null=True,
        default=None,
    )
    permalink = models.CharField(
        verbose_name=_("Permalink"),
        help_text=_("Permanent link for this message."),
        max_length=256,
        default="",
        blank=True,
    )

    # As ID, `ts` assigned by Slack, it is known after received response
    # By known, `ts` refers to timestamp (Format of `datetime.timestamp()`, e.g. `"1702737142.945359"`)
    ts = models.CharField(
        verbose_name=_("Message ID"),
        help_text=_("ID of an Slack message."),
        max_length=32,
        null=True,
        blank=True,
        unique=True,
    )
    parent_ts = models.CharField(
        verbose_name=_("Thread ID"),
        help_text=_("ID of current conversation thread."),
        max_length=32,
        default="",
        blank=True,
    )

    # Extraneous call detail for debugging
    request = models.JSONField(
        verbose_name=_("Request"),
        help_text=_("Dump of request content for debugging."),
        null=True,
        blank=True,
    )
    response = models.JSONField(
        verbose_name=_("Response"),
        help_text=_("Dump of response content for debugging."),
        null=True,
        blank=True,
    )
    exception = models.TextField(
        verbose_name=_("Exception"),
        help_text=_("Exception message if any."),
        blank=True,
    )

    objects: SlackMessageManager = SlackMessageManager()

    class Meta:  # noqa: D106
        verbose_name = _("Message")
        verbose_name_plural = _("Messages")
        ordering = ("-created",)

    def __str__(self) -> str:
        if self.ok is True:
            return _("Message ({ts}, OK)").format(id=self.id, ts=self.ts)

        if self.ok is False:
            return _("Message ({id}, not OK)").format(id=self.id)

        return _("Message ({id}, not sent)").format(id=self.id)

django_slack_tools.slack_messages.models.SlackMessageRecipient

Bases: TimestampMixin, Model

People or group in channels receive messages.

Source code in django_slack_tools/slack_messages/models/message_recipient.py
class SlackMessageRecipient(TimestampMixin, models.Model):
    """People or group in channels receive messages."""

    alias = models.CharField(
        verbose_name=_("Alias"),
        help_text=_("Alias for this recipient."),
        max_length=256,
        unique=True,
    )
    channel = models.CharField(
        verbose_name=_("Channel"),
        help_text=_("Slack channel ID where messages will be sent."),
        max_length=128,
        blank=False,
    )
    channel_name = models.CharField(
        verbose_name=_("Channel name"),
        help_text=_("Display name of channel."),
        max_length=256,
        blank=True,
        default="",
    )
    mentions = models.ManyToManyField(
        SlackMention,
        verbose_name=_("Mentions"),
        help_text=_("List of mentions."),
        blank=True,
    )

    objects: SlackMessageRecipientManager = SlackMessageRecipientManager()

    class Meta:  # noqa: D106
        verbose_name = _("Recipient")
        verbose_name_plural = _("Recipients")

    def __str__(self) -> str:
        num_mentions = self.mentions.count()

        return _("{alias} ({channel}, {num_mentions} mentions)").format(
            alias=self.alias,
            channel=self.channel,
            num_mentions=num_mentions,
        )

django_slack_tools.slack_messages.models.SlackMessagingPolicy

Bases: TimestampMixin, Model

An Slack messaging policy which determines message content and those who receive messages.

Source code in django_slack_tools/slack_messages/models/messaging_policy.py
class SlackMessagingPolicy(TimestampMixin, models.Model):
    """An Slack messaging policy which determines message content and those who receive messages."""

    code = models.CharField(
        verbose_name=_("Code"),
        help_text=_("Unique message code for lookup, mostly by human."),
        max_length=32,
        unique=True,
    )
    enabled = models.BooleanField(
        verbose_name=_("Enabled"),
        help_text=_("Turn on or off current messaging policy."),
        default=True,
    )
    recipients = models.ManyToManyField(
        SlackMessageRecipient,
        verbose_name=_("Message recipients"),
        help_text=_("Those who will receive messages."),
    )
    header_defaults = models.JSONField(
        verbose_name=_("Default header"),
        help_text=_("Default header values applied to messages on creation."),
        validators=[header_validator],
        blank=True,
        default=dict,
    )
    template = models.JSONField(
        verbose_name=_("Message template object"),
        help_text=_("Dictionary-based template object."),
        validators=[dict_template_validator],
        null=True,
        blank=True,
    )
    # Type is too obvious but due to limits...
    objects: SlackMessagingPolicyManager = SlackMessagingPolicyManager()

    class Meta:  # noqa: D106
        verbose_name = _("Messaging Policy")
        verbose_name_plural = _("Messaging Policies")

    def __str__(self) -> str:
        num_recipients = self.recipients.all().count()
        if self.enabled:
            return _("{code} (enabled, {num_recipients} recipients)").format(
                code=self.code,
                num_recipients=num_recipients,
            )

        return _("{code} (disabled, {num_recipients} recipients)").format(code=self.code, num_recipients=num_recipients)