glyde/model/message

Messages, and everything reachable from one.

content, embeds, attachments and components arrive EMPTY, not absent, without the MESSAGE_CONTENT intent. Nothing tells that apart from a genuinely empty message.

MESSAGE_UPDATE does not carry a Message, whatever the docs say. Use update_decoder, never decoder, on that event.

Types

pub type ChannelMention {
  ChannelMention(
    id: id.Id(id.Channel),
    guild_id: id.Id(id.Guild),
    type_: channel.ChannelType,
    name: String,
  )
}

Constructors

Discord splices member into each element of mentions.

pub type Mention {
  Mention(
    user: user.User,
    member: option.Option(member.GuildMember),
  )
}

Constructors

pub type Message {
  Message(
    id: id.Id(id.Message),
    channel_id: id.Id(id.Channel),
    guild_id: option.Option(id.Id(id.Guild)),
    author: user.User,
    member: option.Option(member.GuildMember),
    content: String,
    timestamp: String,
    edited_timestamp: option.Option(String),
    tts: Bool,
    mention_everyone: Bool,
    mentions: List(Mention),
    mention_roles: List(id.Id(id.Role)),
    mention_channels: List(ChannelMention),
    attachments: List(attachment.Attachment),
    embeds: List(embed.Embed),
    reactions: List(Reaction),
    nonce: option.Option(Nonce),
    pinned: Bool,
    webhook_id: option.Option(id.Id(id.Webhook)),
    type_: MessageType,
    application_id: option.Option(id.Id(id.Application)),
    flags: flags.Flags(MessageFlag),
    message_reference: option.Option(MessageReference),
    referenced_message: field.Field(Message),
    thread: option.Option(channel.Channel),
    components: List(component.Component),
    sticker_items: List(StickerItem),
    position: option.Option(Int),
  )
}

Constructors

pub type MessageFlag {
  Crossposted
  IsCrosspost
  SuppressEmbeds
  SourceMessageDeleted
  Urgent
  HasThread
  Ephemeral
  Loading
  FailedToMentionSomeRolesInThread
  SuppressNotifications
  IsVoiceMessage
  HasSnapshot
  IsComponentsV2
}

Constructors

  • Crossposted
  • IsCrosspost
  • SuppressEmbeds
  • SourceMessageDeleted
  • Urgent
  • HasThread
  • Ephemeral
  • Loading
  • FailedToMentionSomeRolesInThread
  • SuppressNotifications
  • IsVoiceMessage
  • HasSnapshot
  • IsComponentsV2

    Once set on a message this can never be removed.

pub type MessageReference {
  MessageReference(
    type_: MessageReferenceType,
    message_id: option.Option(id.Id(id.Message)),
    channel_id: option.Option(id.Id(id.Channel)),
    guild_id: option.Option(id.Id(id.Guild)),
  )
}

Constructors

pub type MessageReferenceType {
  DefaultReference
  ForwardReference
  UnknownReference(Int)
}

Constructors

  • DefaultReference

    Replies, crossposts, pins and thread starters. Populates referenced_message.

  • ForwardReference

    Forwards. Populates message_snapshots, which is not modelled.

  • UnknownReference(Int)

0 to 46, with holes at 13, 30, 33 to 35, 40 to 43 and 45. Never index this by position.

pub type MessageType {
  DefaultMessage
  RecipientAdd
  RecipientRemove
  Call
  ChannelNameChange
  ChannelIconChange
  ChannelPinnedMessage
  UserJoin
  GuildBoost
  GuildBoostTier1
  GuildBoostTier2
  GuildBoostTier3
  ChannelFollowAdd
  GuildDiscoveryDisqualified
  GuildDiscoveryRequalified
  GuildDiscoveryGracePeriodInitialWarning
  GuildDiscoveryGracePeriodFinalWarning
  ThreadCreated
  ReplyMessage
  ChatInputCommand
  ThreadStarterMessage
  GuildInviteReminder
  ContextMenuCommand
  AutoModerationAction
  RoleSubscriptionPurchase
  InteractionPremiumUpsell
  StageStart
  StageEnd
  StageSpeaker
  StageTopic
  GuildApplicationPremiumSubscription
  GuildIncidentAlertModeEnabled
  GuildIncidentAlertModeDisabled
  GuildIncidentReportRaid
  GuildIncidentReportFalseAlarm
  PurchaseNotification
  PollResult
  UnknownMessageType(Int)
}

Constructors

  • DefaultMessage
  • RecipientAdd
  • RecipientRemove
  • Call
  • ChannelNameChange
  • ChannelIconChange
  • ChannelPinnedMessage
  • UserJoin
  • GuildBoost
  • GuildBoostTier1
  • GuildBoostTier2
  • GuildBoostTier3
  • ChannelFollowAdd
  • GuildDiscoveryDisqualified
  • GuildDiscoveryRequalified
  • GuildDiscoveryGracePeriodInitialWarning
  • GuildDiscoveryGracePeriodFinalWarning
  • ThreadCreated
  • ReplyMessage
  • ChatInputCommand
  • ThreadStarterMessage
  • GuildInviteReminder
  • ContextMenuCommand
  • AutoModerationAction
  • RoleSubscriptionPurchase
  • InteractionPremiumUpsell
  • StageStart
  • StageEnd
  • StageSpeaker
  • StageTopic
  • GuildApplicationPremiumSubscription
  • GuildIncidentAlertModeEnabled
  • GuildIncidentAlertModeDisabled
  • GuildIncidentReportRaid
  • GuildIncidentReportFalseAlarm
  • PurchaseNotification
  • PollResult
  • UnknownMessageType(Int)

The MESSAGE_UPDATE payload, which is NOT a message object: an embed unfurl sends four keys. message is Some only when a full object arrived.

pub type MessageUpdate {
  MessageUpdate(
    id: id.Id(id.Message),
    channel_id: id.Id(id.Channel),
    guild_id: option.Option(id.Id(id.Guild)),
    message: option.Option(Message),
    raw: dynamic.Dynamic,
  )
}

Constructors

Discord echoes back whatever was sent, so both exist for reading. Always SEND a StringNonce: it is a dedup key, and a number can be reinterpreted.

There is no variant for a nonce too big to hold, because this type is also what a create sends: a lost value has to read as None and omit the key, not encode as a null Discord would take for an instruction.

pub type Nonce {
  StringNonce(String)
  IntNonce(Int)
}

Constructors

  • StringNonce(String)
  • IntNonce(Int)
pub type PinList {
  PinList(items: List(PinnedMessage), has_more: Bool)
}

Constructors

One entry from the pins API. The timestamp belongs to the pin, not to the message.

pub type PinnedMessage {
  PinnedMessage(pinned_at: String, message: Message)
}

Constructors

  • PinnedMessage(pinned_at: String, message: Message)
pub type Reaction {
  Reaction(
    count: Int,
    count_details: ReactionCountDetails,
    me: Bool,
    me_burst: Bool,
    emoji: emoji.Emoji,
    burst_colors: List(String),
  )
}

Constructors

  • Reaction(
      count: Int,
      count_details: ReactionCountDetails,
      me: Bool,
      me_burst: Bool,
      emoji: emoji.Emoji,
      burst_colors: List(String),
    )

    Arguments

    count

    Normal and super reactions added together.

    emoji

    A PARTIAL emoji, with a null id for a unicode reaction.

    burst_colors

    Hex colours for the super-reaction burst, with no leading #.

pub type ReactionCountDetails {
  ReactionCountDetails(burst: Int, normal: Int)
}

Constructors

  • ReactionCountDetails(burst: Int, normal: Int)

Discord’s two kinds of reaction, one type for both the gateway events and the type query parameter on the reactions route. A burst reaction is the animated “super reaction” a Nitro subscriber can send.

pub type ReactionType {
  NormalReaction
  BurstReaction
  UnknownReactionType(Int)
}

Constructors

  • NormalReaction
  • BurstReaction
  • UnknownReactionType(Int)

    Discord adds values here between releases.

Discord’s sticker format table. A missing format_type reads as UnknownStickerFormat(0), which is not a value Discord sends.

pub type StickerFormat {
  PngSticker
  ApngSticker
  LottieSticker
  GifSticker
  UnknownStickerFormat(Int)
}

Constructors

  • PngSticker
  • ApngSticker
  • LottieSticker
  • GifSticker
  • UnknownStickerFormat(Int)
pub type StickerItem {
  StickerItem(
    id: id.Id(id.Sticker),
    name: String,
    format_type: StickerFormat,
  )
}

Constructors

Values

pub fn has_flag(
  bits: flags.Flags(MessageFlag),
  flag: MessageFlag,
) -> Bool
pub fn is_deletable(value: MessageType) -> Bool

Whether DELETE /channels/{id}/messages/{id} accepts this message. An unknown type answers False, because a guess costs a confusing 400.

pub fn is_from_webhook(message: Message) -> Bool

author.bot is true of ordinary bots too, so it is a different question.

pub fn mention_decoder() -> decode.Decoder(Mention)

The user object is not nested: the spliced member sits beside its keys.

pub fn mentioned_users(message: Message) -> List(user.User)
pub fn message_flags(
  of chosen: List(MessageFlag),
) -> flags.Flags(MessageFlag)
pub fn message_reference_decoder() -> decode.Decoder(
  MessageReference,
)
pub fn message_reference_type_decoder() -> decode.Decoder(
  MessageReferenceType,
)
pub fn message_reference_type_from_int(
  value: Int,
) -> MessageReferenceType
pub fn message_reference_type_to_int(
  value: MessageReferenceType,
) -> Int
pub fn message_reference_type_to_json(
  value: MessageReferenceType,
) -> json.Json
pub fn message_type_decoder() -> decode.Decoder(MessageType)
pub fn message_type_from_int(value: Int) -> MessageType
pub fn message_type_to_int(value: MessageType) -> Int
pub fn message_type_to_json(value: MessageType) -> json.Json
pub fn nonce_decoder() -> decode.Decoder(option.Option(Nonce))

Total on purpose. wire.integer rejects a number too big to hold exactly, and decode.optional_field passes that failure up, so without the last alternative an oversized nonce would sink the whole message. Past 2^53-1 the low digits are already gone, so None is all there is to hand back.

pub fn nonce_to_json(value: Nonce) -> json.Json
pub fn pin_list_decoder() -> decode.Decoder(PinList)
pub fn reaction_count_details_decoder() -> decode.Decoder(
  ReactionCountDetails,
)
pub fn reaction_decoder() -> decode.Decoder(Reaction)

The super-reaction fields are documented as required and are missing from cached or replayed payloads, so they default.

pub fn reaction_type_decoder() -> decode.Decoder(ReactionType)
pub fn reaction_type_from_int(value: Int) -> ReactionType
pub fn reaction_type_to_int(value: ReactionType) -> Int

The exact inverse of reaction_type_from_int: a value this build does not know still goes back out as itself.

pub fn referenced(message: Message) -> option.Option(Message)

referenced_message collapsed to an Option.

pub fn sticker_format_from_int(value: Int) -> StickerFormat
pub fn sticker_format_to_int(value: StickerFormat) -> Int

The exact inverse of sticker_format_from_int: a value this build does not know still goes back out as itself.

pub fn sticker_item_decoder() -> decode.Decoder(StickerItem)
Search Document