glyde/attachment

A file attached to a message: what arrives with one, and what goes up on a send or an edit. Attachment is the received record with its CDN URLs; File is bytes to upload, paired with the attachments array by position.

The Clips-only fields, clip_participants, clip_created_at and application, are not modelled.

Types

pub type Attachment {
  Attachment(
    id: id.Id(id.Attachment),
    filename: String,
    title: option.Option(String),
    description: option.Option(String),
    content_type: option.Option(String),
    size: Int,
    url: String,
    proxy_url: String,
    dimensions: option.Option(Dimensions),
    placeholder: option.Option(Placeholder),
    ephemeral: Bool,
    duration_secs: option.Option(Float),
    waveform: option.Option(String),
    flags: flags.Flags(AttachmentFlag),
  )
}

Constructors

  • Attachment(
      id: id.Id(id.Attachment),
      filename: String,
      title: option.Option(String),
      description: option.Option(String),
      content_type: option.Option(String),
      size: Int,
      url: String,
      proxy_url: String,
      dimensions: option.Option(Dimensions),
      placeholder: option.Option(Placeholder),
      ephemeral: Bool,
      duration_secs: option.Option(Float),
      waveform: option.Option(String),
      flags: flags.Flags(AttachmentFlag),
    )

    Arguments

    description

    Alt text, up to 1024 characters.

    size

    Bytes.

    url

    A signed CDN URL that expires. Re-fetch the message, do not store it.

    proxy_url

    The same URL through Discord’s media proxy, and it expires too.

    dimensions

    Absent for anything that is not an image or a video. Discord sends both sides or neither, so one value carries both.

    placeholder

    A thumbhash: a blurred preview to paint while the image loads. The version only says how the hash is encoded, so one value carries both.

    ephemeral

    Garbage collected, so the URL dies before its signature expires.

    duration_secs

    Voice messages and videos. Discord sends a whole number of seconds as 3, not 3.0.

    waveform

    Base64 waveform preview for a voice message.

pub type AttachmentFlag {
  IsClip
  IsThumbnail
  IsRemix
  IsSpoiler
  IsAnimated
}

Constructors

  • IsClip
  • IsThumbnail
  • IsRemix

    Discord deprecated this one and still sends it.

  • IsSpoiler
  • IsAnimated

Pixels. An image or a video has both, anything else has neither.

pub type Dimensions {
  Dimensions(width: Int, height: Int)
}

Constructors

  • Dimensions(width: Int, height: Int)

What a message’s attachments should look like after an edit. Every route that edits a message takes one of these: the rule is the same wherever the field appears.

pub type EditAttachments {
  KeepAttachments
  SetAttachments(keep: List(KeptAttachment), add: List(File))
}

Constructors

  • KeepAttachments

    Leave them exactly as they are, and upload nothing.

  • SetAttachments(keep: List(KeptAttachment), add: List(File))

    The complete resulting set: keep plus add. Anything not listed is removed, so SetAttachments(keep: [], add: []) strips them all.

A file to upload.

pub type File {
  File(
    filename: String,
    content_type: String,
    data: BitArray,
    description: option.Option(String),
    title: option.Option(String),
    spoiler: Bool,
    voice: option.Option(Voice),
  )
}

Constructors

  • File(
      filename: String,
      content_type: String,
      data: BitArray,
      description: option.Option(String),
      title: option.Option(String),
      spoiler: Bool,
      voice: option.Option(Voice),
    )

    Arguments

    content_type

    Discord answers 500 on some endpoints when a part carries no content type. Use application/octet-stream when you do not know.

    description

    Alt text, max 1024 characters.

    spoiler

    The one place the spoiler lives. filename never carries the prefix: file moves it here and wire_filename puts it back.

    voice

    Set by voice_message. Discord needs both halves or neither, so they are one value.

pub type KeptAttachment {
  KeptAttachment(
    id: id.Id(id.Attachment),
    description: option.Option(String),
    title: option.Option(String),
  )
}

Constructors

A thumbhash and the layout it is encoded in. Discord documents 1 as the only version so far, so a hash that arrives without one reads as 1.

pub type Placeholder {
  Placeholder(hash: String, version: Int)
}

Constructors

  • Placeholder(hash: String, version: Int)

What makes an upload a voice message rather than an audio file.

pub type Voice {
  Voice(duration_secs: Float, waveform: String)
}

Constructors

  • Voice(duration_secs: Float, waveform: String)

    Arguments

    waveform

    Base64 of the sampled amplitudes.

Values

pub fn added_files(edit: EditAttachments) -> List(File)

The files an edit uploads, in files[n] order.

pub fn attachments_field(
  edit: EditAttachments,
) -> field.Field(json.Json)

The attachments field of an edit. An empty array removes every attachment, so SetAttachments always writes the key.

pub fn described(a_file: File, alt: String) -> File

Alt text, read out by screen readers.

pub fn dimensions_field(
  next: fn(option.Option(Dimensions)) -> decode.Decoder(a),
) -> decode.Decoder(a)

Read width and height and pair them. Discord sends both or neither on an attachment and on embed media, so one helper decodes both places.

pub fn file(
  filename filename: String,
  content_type content_type: String,
  data data: BitArray,
) -> File

A SPOILER_ prefix on filename is read as asking for a spoiler and moved onto the boolean, so the two never say different things.

pub fn has_flag(
  bits: flags.Flags(AttachmentFlag),
  flag: AttachmentFlag,
) -> Bool
pub fn new_attachments_field(
  files: List(File),
) -> field.Field(json.Json)

The attachments field of a create, where the array is only the uploads and no array at all means no uploads.

pub fn parts(files: List(File)) -> List(body.File)

In files[n] order, the same order the attachments array numbers, so part n points at entry n.

pub fn placeholder_field(
  next: fn(option.Option(Placeholder)) -> decode.Decoder(a),
) -> decode.Decoder(a)

Read placeholder and placeholder_version and pair them. Shared by attachments and embed media.

pub fn spoilered(a_file: File) -> File

Deliver it blurred, behind a click.

pub fn voice_message(
  a_file: File,
  duration_secs duration_secs: Float,
  waveform waveform: String,
) -> File

Send it as a voice message. Discord also wants the IS_VOICE_MESSAGE flag on the message and an audio content type on the part.

pub fn wire_filename(a_file: File) -> String

The filename as it goes on the wire, spoiler prefix included. spoiler decides, not the name: a record built by hand with a prefixed filename gets stripped rather than prefixed twice.

Search Document