On This Page

Messages

91 symbols from @neontechspace/fluxerly

Variables#

MessageFlags#

Known bits in a received message's flags, including server-managed publishing state

Test an observed bit with bitwise AND, such as (message.flags & MessageFlags.IsCrosspost) !== 0. Only SuppressEmbeds and SuppressNotifications are writable through message or webhook send and edit operations. Combine those two with bitwise OR. Server-managed bits and all other bits are rejected locally before dispatch

const MessageFlags: Readonly<{ … }>
Crossposted#

Server-managed bit on an announcement message that has been published to following channels

1
FailedToMentionSomeRolesInThread#

Server-managed bit on a message in a thread that mentions a role, when Fluxer could not add every member of that role to the thread

256
HasThread#

Server-managed bit on a message that a thread was started from

Its thread field describes that thread while it exists

32
IsCrosspost#

Server-managed bit on a published copy delivered to a following channel

Its messageReference identifies the source

2
SourceMessageDeleted#

Server-managed bit on a published copy whose source was deleted or can no longer be delivered

Fluxer replaces the copy's content with "[Original message deleted]" and clears attachments, embeds and stickers

8
SuppressEmbeds#

Writable bit that hides embeds on this message

4
SuppressNotifications#

Writable bit that suppresses push and desktop notifications

4096
VoiceMessage#

Bit that marks a voice message

Message and webhook send and edit operations reject it before dispatch

8192

MessageType#

Fluxer's message types, the values of Message.type, such as message.type === MessageType.UserJoin

Every type shares the one Message shape. A value missing here, added by Fluxer later, is still kept in Message.type

const MessageType: Readonly<{ … }>
Call#

A call in a private conversation

3
ChannelFollowAdd#

A notice that this channel began following an announcement channel

Its messageReference identifies the followed channel without a source message ID

12
ChannelIconChange#

A notice that the conversation's icon changed

5
ChannelNameChange#

A notice that a group conversation or thread was renamed

4
ChannelPinnedMessage#

A notice that a message was pinned

6
Default#

A regular message

0
RecipientAdd#

A notice that a user was added to a group conversation or a thread

1
RecipientRemove#

A notice that a user was removed from a group conversation or a thread

2
Reply#

A reply to another message, whose messageReference names the target

19
ThreadCreated#

A notice in a text or announcement channel that a public or announcement thread was started there

Its content is the thread name, its author started the thread, and its messageReference names the thread without a message ID

18
ThreadStarterMessage#

The first message of a thread started from a message

Its messageReference names that message, and referencedMessage holds it, or null once it is deleted. Fluxer builds it on read and never stores it

21
UserJoin#

A notice that a user joined the community

7

Interfaces#

AllowedMentions#

Choose which existing mentions may notify users when sending, replying or editing

All notification categories are disabled unless explicitly enabled. ID arrays are copied by index when the operation starts. These settings allow notifications but do not add mention text or bypass Fluxer's permissions

interface AllowedMentions
everyone optional#

Permit @everyone and @here notifications, default false

boolean
repliedUser optional#

Permit notification of the reply target's author, default false

boolean
roles optional#

Permit notifications for textual mentions of these role IDs, at most 100

Fluxer's community permissions still apply

readonly string[]
users optional#

Permit notifications for textual mentions of these account IDs, at most 100

Omit to permit none

readonly string[]

Attachment#

Information about a file attached to a received message

Use client.attachments to refresh its URL explicitly, then download or stream its bytes. This object is frozen. Its URLs may expire, and the SDK never refreshes or downloads them automatically

interface Attachment
contentHash optional#

Optional server content hash

string
contentType optional#

Optional detected MIME type

string
description optional#

Optional alternative-text description

string
duration optional#

Optional audio/video duration in seconds

number
expired optional#

Optional server expiry observation, not a live availability check

boolean
expiresAt optional#

Optional ISO timestamp supplied by Fluxer for expiry

string
filename#

Display filename returned by Fluxer

string
flags#

Platform attachment bit flags, including spoiler bit 1 << 3

number
height optional#

Optional image/video height in pixels

number
id#

Decimal attachment ID

string
nsfw optional#

Optional server adult-content classification

boolean
placeholder optional#

Optional encoded preview placeholder

string
proxyUrl optional#

Proxy URL returned by Fluxer

string
size#

File size in bytes, not the SDK's retained metadata size

number
title optional#

Optional display title

string
url optional#

File URL returned by Fluxer

string
waveform optional#

Optional base64-encoded audio waveform

string
width optional#

Optional image/video width in pixels

number

AttachmentBytesInput#

New caller-owned bytes supplied as an attachment

Bytes are copied when the operation starts, before waiting. Later caller mutation cannot change an accepted upload

interface AttachmentBytesInput
contentType optional#

Optional MIME type hint, at most 255 printable ASCII characters

The upload request defaults to application/octet-stream. Fluxer's upload plan chooses the MIME type used for transfer and may override this hint based on the filename

string
data#

File bytes, including Node buffers and subarray views

Shared-memory buffers are rejected. Empty files are accepted. At most 50 MiB per file, the deployed server may impose a lower limit

Uint8Array
description optional#

Optional alternative-text description, 1–4,096 normalized UTF-16 code units

string
file optional#

Do not combine a file source with data

undefined
filename#

Display filename, not a filesystem path

Nonempty, at most 255 string.length units, without control characters or path separators. Fluxer may normalize the filename when preparing the upload

string
id optional#

Not accepted for new uploads, use AttachmentReference to keep an existing attachment during an edit

undefined
size optional#

Do not supply size, the SDK uses data.byteLength

undefined
spoiler optional#

Mark the file as a spoiler

Defaults to false

boolean
stream optional#

Do not combine a stream source with data

undefined
title optional#

Optional display title, 1–1,024 normalized UTF-16 code units

string

AttachmentDownloadOptions#

Limit the bytes and time used by an attachment download

The maxBytes option is required, a positive safe integer no greater than 52,428,800. This limits returned bytes, not the file size on Fluxer, total JavaScript memory or buffering while the SDK assembles the result. The timeoutMs option covers endpoint discovery, URL validation and the full GET, and defaults to the client's rest.defaultTimeoutMs, 30,000 unless configured. The SDK still waits for cleanup after the deadline. Media discovery and GETs use client-local media slots, separate from the REST/upload slots. The media slots default to four (rest.mediaConcurrency), and the REST slots to four per local shard (rest.concurrency). Both pools share the pending-request budget. Media does not wait for bot API rate limits

interface AttachmentDownloadOptions extends OperationOptionsinterface AttachmentDownloadOptions
  extends OperationOptions

Aborting the signal cancels this download, not the client or other operations

maxBytes#

Maximum bytes to accept, required and from 1 through 52,428,800

Exceeding it fails with reason tooLarge rather than truncating

number
timeoutMs optional#

Total deadline in milliseconds, an integer from 1 through 2,147,483,647, including discovery and the GET

Defaults to the client's rest.defaultTimeoutMs, 30,000 unless configured. Cleanup is still awaited after expiry

number

Inherited from OperationOptions: signal

AttachmentFileInput#

Attach a caller-owned file whose size is known

The SDK streams the file without copying or storing its bytes first. Empty files are accepted. The reported size must be a nonnegative safe integer no greater than 50 MiB. Node openAsBlob files can fail during reading if the file changes. A caller may retry only with a stable source and a new message operation. An inline multipart 429 reports rateLimit rather than reopening a mutable file source

interface AttachmentFileInput
contentType optional#

Optional MIME type hint, at most 255 printable ASCII characters

The upload request defaults to application/octet-stream. Fluxer's upload plan chooses the MIME type used for transfer and may override this hint based on the filename

string
data optional#

Do not combine copied bytes with a file source

undefined
description optional#

Optional alternative-text description, 1–4,096 normalized UTF-16 code units

string
file#

A Blob, File or compatible sized source, not a path string

Keep its underlying data stable while the operation reads it

AttachmentFileSource
filename#

Display filename, not a filesystem path

Nonempty, at most 255 string.length units, without control characters or path separators. Fluxer may normalize the filename when preparing the upload

string
id optional#

Not accepted for new uploads, use AttachmentReference to keep an existing attachment during an edit

undefined
size optional#

Do not supply size separately, the SDK uses file.size

undefined
spoiler optional#

Mark the file as a spoiler

Defaults to false

boolean
stream optional#

Do not combine a separate stream with a file source

undefined
title optional#

Optional display title, 1–1,024 normalized UTF-16 code units

string

AttachmentFileSource#

A file-like source the SDK can read in byte ranges for an attachment upload

Node Blob and File values, including fs.openAsBlob results, fit this type without requiring Node or browser type declarations. The SDK opens streams for individual upload parts only after planning. It does not close a caller's path or FileHandle and cannot protect against file changes during reading

interface AttachmentFileSource
size#

Exact file length in bytes, a nonnegative safe integer no larger than 52,428,800 for an upload

number

slice#

Return a source for the byte range from start inclusive to end exclusive

The SDK uses explicit offsets for upload parts

slice(
    start?: number,
    end?: number,
    contentType?: string
): AttachmentFileSourceslice(
  start?: number,
  end?: number,
  contentType?: string
): AttachmentFileSource

Parameters

start optional
number
end optional
number
contentType optional
string

stream#

Create a byte stream for this source

The SDK calls it on selected file slices and owns only the readers it acquires

stream(): AttachmentStreamSource

AttachmentReference#

Keep an existing attachment while editing a message, optionally changing its display title or description

Fluxer may ignore unknown IDs. Omit title and description to preserve their current values. Pass null to clear either value. Non-null title and description limits are measured after U+000C and U+202E removal and surrounding-whitespace trimming. This normalization is validation-only, and the original metadata strings are sent unchanged. The SDK does not fetch the attachment, find it by position, rename it or change its flags

interface AttachmentReference
contentType optional#

The existing attachment's media type cannot be replaced

undefined
data optional#

Keeping an attachment does not accept new byte data

undefined
description optional#

Replacement alternative-text description, 1–4,096 normalized UTF-16 code units, or null to clear

string | null
file optional#

Keeping an attachment does not accept a new file source

undefined
filename optional#

The existing attachment cannot be renamed through this reference

undefined
id#

Decimal attachment ID from the message being edited, not its message ID

string
size optional#

The existing attachment's byte size cannot be replaced

undefined
spoiler optional#

The existing attachment's spoiler flag cannot be replaced

undefined
stream optional#

Keeping an attachment does not accept a new stream source

undefined
title optional#

Replacement display title, 1–1,024 normalized UTF-16 code units, or null to clear

string | null

AttachmentStreamInput#

Attach a caller-owned stream that ends after a known number of bytes

Size is the exact nonnegative byte count, not a maximum. The SDK streams without copying or storing bytes first and reads it at most once after planning succeeds. It cannot limit chunks the source already allocated. An early end, extra bytes, source failure, cancellation or inline multipart 429 stops the operation without reading it again

interface AttachmentStreamInput
contentType optional#

Optional MIME type hint, at most 255 printable ASCII characters

The upload request defaults to application/octet-stream. Fluxer's upload plan chooses the MIME type used for transfer and may override this hint based on the filename

string
data optional#

Do not combine copied bytes with a stream source

undefined
description optional#

Optional alternative-text description, 1–4,096 normalized UTF-16 code units

string
file optional#

Do not combine a file source with a stream source

undefined
filename#

Display filename, not a filesystem path

Nonempty, at most 255 string.length units, without control characters or path separators. Fluxer may normalize the filename when preparing the upload

string
id optional#

Not accepted for new uploads, use AttachmentReference to keep an existing attachment during an edit

undefined
size#

Exact byte count from 0 through 52,428,800

Too few or too many source bytes fail the upload

number
spoiler optional#

Mark the file as a spoiler

Defaults to false

boolean
stream#

A finite byte stream that can be consumed once, not a stream factory or an unbounded live feed

AttachmentStreamSource
title optional#

Optional display title, 1–1,024 normalized UTF-16 code units

string

AttachmentStreamOptions#

Add an optional AbortSignal to the stream limits

Aborting stops this stream's consumption, not the client or other operations

interface AttachmentStreamOptions extends OperationOptionsinterface AttachmentStreamOptions
  extends OperationOptions
maxBytes#

Maximum bytes to accept, required and from 1 through 52,428,800

Exceeding it fails with reason tooLarge rather than truncating

number
timeoutMs optional#

Total deadline in milliseconds, an integer from 1 through 2,147,483,647, including discovery and the GET

Defaults to the client's rest.defaultTimeoutMs, 30,000 unless configured. Cleanup is still awaited after expiry

number

Inherited from OperationOptions: signal

AttachmentStreamReader#

Reader owned by the SDK only after an upload begins consuming its AttachmentStreamSource

The SDK releases it on normal completion and cancels then releases it after a read, transport or cancellation failure

interface AttachmentStreamReader

cancel#

Stop reading and release source resources

The SDK awaits this after an interrupted or failed read, normally without a reason

cancel(reason?: unknown): PromiseLike<void>cancel(
  reason?: unknown
): PromiseLike<void>

Parameters

reason optional
unknown
Returns
PromiseLike<void>

read#

Resolve with the next Uint8Array chunk, or done true when no bytes remain

A rejected read stops the upload. Empty chunks are accepted. Sustained empty reads periodically yield to host timers and cancellation, including while checking for EOF. This does not impose a time limit on a caller's read or cancel implementation

read(): PromiseLike<AttachmentStreamReadResult>read(): PromiseLike<
  AttachmentStreamReadResult
>
Returns
PromiseLike<AttachmentStreamReadResult>PromiseLike<
  AttachmentStreamReadResult
>

releaseLock#

Release this reader's exclusive stream lock

The SDK calls this after completion and also attempts it if cancellation fails

releaseLock(): void

AttachmentStreamReaderOptions#

Optional native stream-reader mode

Attachment uploads always acquire the default byte reader

interface AttachmentStreamReaderOptions
mode optional#

Native bring-your-own-buffer mode, included for compatibility

The SDK does not request this mode

"byob"

AttachmentStreamSource#

Finite byte stream accepted as an attachment source

Its exact byte count must be supplied by AttachmentStreamInput. The SDK reads it once and cannot replay it

interface AttachmentStreamSource

getReader#

Native bring-your-own-buffer reader form, included for compatibility

The SDK does not use it

getReader(options: { readonly mode: "byob" }): unknowngetReader(
  options: {
    readonly mode: "byob"
  }
): unknown

Parameters

options
mode

Select the native bring-your-own-buffer reader, which SDK uploads do not request

"byob"
Returns
unknown

Return the default byte reader, locking the stream until releaseLock

The SDK validates the reader before consuming it

getReader(): AttachmentStreamReader

Native optional-options overload, included for compatibility with ReadableStream

getReader(options?: AttachmentStreamReaderOptions): unknowngetReader(
  options?:
    AttachmentStreamReaderOptions
): unknown

Parameters

Returns
unknown

Attachments#

Refresh signed attachment URL strings explicitly, or download received Attachment data all at once or as chunks

Refresh uses the selected instance's authenticated API. Downloads use its media path, with no gateway connection or cache required. The SDK never sends bot credentials to a download URL or substitutes attachment.proxyUrl

interface Attachments

download#

Download attachment.url into one Uint8Array

Pass maxBytes explicitly, from 1 through 52,428,800 bytes (50 MiB). The limit caps the returned bytes, not total memory, because response chunks can coexist with the packed result

download(
    attachment: Attachment,
    options: AttachmentDownloadOptions
): ResultAsync<
    Uint8Array<ArrayBufferLike>,
    AttachmentDownloadFailure | ConfigurationError | CancelledError
>download(
  attachment: Attachment,
  options:
    AttachmentDownloadOptions
): ResultAsync<
  Uint8Array<ArrayBufferLike>,
  | AttachmentDownloadFailure
  | ConfigurationError
  | CancelledError
>

The URL must match this instance's discovered media /attachments/ path. The GET sends no Authorization header, follows no redirects, stores no cached copy and never falls back to proxyUrl. The timeoutMs option defaults to the client's rest.defaultTimeoutMs, 30,000 unless configured, for endpoint discovery, waiting for a media slot and downloading. By default four media downloads can run at once (rest.mediaConcurrency), separately from REST and uploads, without waiting for bot API rate limits. Cancellation waits for response-reader cleanup, but cannot undo bytes already received

Size and expiry metadata do not prove that the URL is available or the bytes are safe. Expected failures contain a safe reason and status, including busy, without the URL or response body. Discovery and download transport failures retain a sanitized cause with a safe transport code when available, never the raw error

Parameters

attachment
Attachment
Returns
ResultAsync<
    Uint8Array<ArrayBufferLike>,
    AttachmentDownloadFailure | ConfigurationError | CancelledError
>ResultAsync<
  Uint8Array<ArrayBufferLike>,
  | AttachmentDownloadFailure
  | ConfigurationError
  | CancelledError
>

refreshUrls#

Ask Fluxer's bot-authenticated API to reissue signatures for 1 through 50 URL strings

Each string may contain at most 2,048 UTF-16 code units. Strings, duplicate entries and query parameters are sent unchanged

refreshUrls(
    urls: readonly string[],
    options?: RequestOptions
): ResultAsync<
    readonly RefreshedAttachmentUrl[],
    AttachmentRefreshFailure | ConfigurationError | CancelledError
>refreshUrls(
  urls: readonly string[],
  options?: RequestOptions
): ResultAsync<
  readonly RefreshedAttachmentUrl[],
  | AttachmentRefreshFailure
  | ConfigurationError
  | CancelledError
>

The frozen result has one original and refreshed pair per input in the same order. A string outside this instance's attachment URL space is returned unchanged by Fluxer. Refreshing does not check attachment existence, community or channel membership, permission to download, or media availability

This method never downloads media and sends the bot credential only to the selected instance's API, never to a requested or refreshed URL. The credentialed POST follows no redirect. Use download explicitly afterward for a returned URL that belongs to this instance

The timeoutMs option defaults to the client's rest.defaultTimeoutMs, 30,000 unless configured, for endpoint discovery, waiting for a REST request slot, rate-limit waits and the limited response read. A confirmed 429 can retry after its required wait. A POST with an unknown outcome or a malformed success is not retried automatically. Cancellation affects only this refresh and waits for request cleanup. HTTP 404 cannot distinguish an older unsupported deployment from an unavailable route or denied access. No refresh happens automatically when reading messages or downloading attachments

Parameters

urls
readonly string[]
options optional
RequestOptions

stream#

Read attachment.url as chunks without combining the file into one array

Pass maxBytes explicitly, from 1 through 52,428,800 bytes (50 MiB), for the total bytes delivered

stream(
    attachment: Attachment,
    options: AttachmentStreamOptions
): AsyncIterable<
    Result<
        Uint8Array<ArrayBufferLike>,
        | AttachmentDownloadFailure | ConfigurationError
        | CancelledError
    >
>stream(
  attachment: Attachment,
  options: AttachmentStreamOptions
): AsyncIterable<
  Result<
    Uint8Array<ArrayBufferLike>,
    | AttachmentDownloadFailure
    | ConfigurationError
    | CancelledError
  >
>

The first pull reads the inputs, resolves endpoints, waits for a media slot (four by default, rest.mediaConcurrency) and starts the GET. Media slots are separate from the REST and upload slots. Later pulls read at most one response chunk. No byte packing, spooling, automatic retry or durable storage is added

The URL must match this instance's media /attachments/ path. The GET sends no Authorization header, follows no redirects, caches nothing and never uses proxyUrl. A Content-Length above maxBytes fails before any chunk, but actual byte counting is still enforced

The result can be consumed only once. The timeoutMs option defaults to the client's rest.defaultTimeoutMs, 30,000 unless configured, for the whole download, including pauses between chunks. Ending consumption early, cancellation, failure and client shutdown cancel the body, wait for reader cleanup and release the media slot. Expected failures include safe local busy, network, response, limit and deadline reasons and client closure. Transport failures during discovery, opening or reading retain sanitized causes with safe transport codes when available, never raw errors. Size and expiry metadata do not establish availability or byte safety

Parameters

attachment
Attachment
Returns
AsyncIterable<
    Result<
        Uint8Array<ArrayBufferLike>,
        | AttachmentDownloadFailure | ConfigurationError
        | CancelledError
    >
>AsyncIterable<
  Result<
    Uint8Array<ArrayBufferLike>,
    | AttachmentDownloadFailure
    | ConfigurationError
    | CancelledError
  >
>

Consume the iterable with a for await loop. Each item is a Result containing one Uint8Array, and an expected failure yields one Err and ends the loop. Overlapping next calls return busy without cancelling the pending read. Breaking the loop, return, throw and signal cancellation all end the download. Listener or cleanup failures reject with SdkDefect after independent cleanup is attempted

export async function downloadChunks(client, attachment) {
    for await (const chunk of client.attachments.stream(attachment, { maxBytes: 1_024 })) {
        if (chunk.isErr())
            return chunk
        void chunk.value
    }
}
import type { Attachment, Client } from "@neontechspace/fluxerly"
export async function downloadChunks(client: Client, attachment: Attachment) {
    for await (const chunk of client.attachments.stream(attachment, { maxBytes: 1_024 })) {
        if (chunk.isErr()) return chunk
        void chunk.value
    }
}

CrosspostSource#

Frozen source metadata for a published message copy or a channel-follow notice

It describes the source community without fetching the original message or retaining a Guild snapshot

interface CrosspostSource
guild#

Frozen public source community snapshot

CrosspostSourceGuild

CrosspostSourceGuild#

A public community snapshot identifying where a published copy or follow notice originated

This is not a complete Guild and never populates the client's community cache

interface CrosspostSourceGuild
approximateMemberCount#

Approximate member count, with null meaning unavailable rather than zero

number | null
approximatePresenceCount#

Approximate online-member count, with null meaning unavailable rather than zero

number | null
banner optional#

Source banner hash, with null meaning no banner and omission meaning unavailable

string | null
description#

Public discovery description, with null meaning unavailable

string | null
discoverable#

Whether the source community is discoverable

boolean
features#

Provider-supplied public badge features, currently VERIFIED, PARTNERED and DISCOVERABLE

Unknown strings are preserved

readonly string[]
icon optional#

Source icon hash, with null meaning no icon and omission meaning unavailable

string | null
id#

Decimal source community ID

string
name#

Source community name

string

Embed#

A rich card or generated link preview received with a message, including any child preview

This object is frozen, but later message observations may contain different media-processing results

interface Embed extends EmbedChild
children optional#

At most one server-generated child, with no further nesting

readonly EmbedChild[]

Inherited from EmbedChild: audio, author, color, description, fields, footer, html, htmlHeight, htmlWidth, image, nsfw, provider, thumbnail, timestamp, title, type, url, video

EmbedAuthor#

Author information received with a message

The object is frozen, missing or null server fields become omitted properties

interface EmbedAuthor
iconUrl optional#

Original icon URL

string
name#

Server-provided label

string
proxyIconUrl optional#

Icon URL served through Fluxer's media proxy, when supplied

string
url optional#

Destination for the label

string

EmbedAuthorInput#

Label above the embed body, with optional links for its name and icon

interface EmbedAuthorInput
iconUrl optional#

HTTP(S) icon URL, at most 2048 characters

Attachment URLs are not accepted here

string
name#

Required author name, 1–256 normalized UTF-16 code units

string
url optional#

Destination for the author label

string

EmbedChild#

One received card or link preview, without its optional child previews

This frozen object cannot be changed. Missing or null server fields are omitted. Use EmbedInput to send a card. A received card can include server-generated fields, but unknown fields are omitted

interface EmbedChild
audio optional#

Audio metadata, not a playable SDK resource

EmbedMedia
author optional#

Author metadata

EmbedAuthor
color optional#

Server-provided color integer

number
description optional#

Body text

string
fields optional#

Frozen named sections in received order

readonly EmbedField[]
html optional#

Preview HTML supplied by Fluxer

The SDK does not render or sanitize it. Treat it as untrusted when displaying it on a page

string
htmlHeight optional#

Preferred HTML preview height in pixels

number
htmlWidth optional#

Preferred HTML preview width in pixels

number
image optional#

Full-size image metadata

EmbedMedia
nsfw optional#

Whether Fluxer marks the embed as NSFW

boolean
provider optional#

Preview provider metadata

EmbedProvider
thumbnail optional#

Thumbnail metadata

EmbedMedia
timestamp optional#

Server-provided ISO timestamp string

string
title optional#

Linked title

string
type#

Server-provided type, including types unknown to this SDK

string
url optional#

Destination URL

string
video optional#

Video metadata, not a playable SDK resource

EmbedMedia

EmbedField#

A heading and body pair received within an embed

This object is frozen

interface EmbedField
inline#

Whether inline display was requested

boolean
name#

Server-provided heading

string
value#

Server-provided body

string

EmbedFieldInput#

One heading and body pair within an embed, such as a Status field with value Passed

interface EmbedFieldInput
inline optional#

Request side-by-side display when space permits

Defaults to false

boolean
name#

Required heading, 1–256 normalized UTF-16 code units

string
value#

Required body, 0–1,024 normalized UTF-16 code units

An empty string is accepted

string

EmbedFooter#

Footer information received with a message

The object is frozen, missing or null server fields become omitted properties

interface EmbedFooter
iconUrl optional#

Original icon URL

string
proxyIconUrl optional#

Icon URL served through Fluxer's media proxy, when supplied

string
text#

Server-provided label

string

EmbedFooterInput#

Text beneath the embed body, with an optional icon

interface EmbedFooterInput
iconUrl optional#

HTTP(S) icon URL, at most 2048 characters

Attachment URLs are not accepted here

string
text#

Required footer text, 1–2,048 normalized UTF-16 code units

string

EmbedInput#

A card for a message's embeds array, with optional text, images and named sections

Message operations reject unknown keys and null values locally

interface EmbedInput

Text length limits count UTF-16 code units, the units used by JavaScript string length. For validation, the SDK removes U+000C and U+202E and trims surrounding whitespace. It sends the original text unchanged

URLs must use HTTP/HTTPS and contain at most 2048 characters, except image and thumbnail URLs may use attachment://filename. An attachment URL must exactly and case-sensitively match one new upload filename in the same send, reply or edit. Its extension must map to an image or video MIME type in Fluxer's filename lookup, such as PNG, AVIF, MP4 or WebM. Its filename may contain letters, marks, numbers, underscores, dots and hyphens only

The SDK does not look up existing attachments, so an existing attachment ID cannot supply an attachment URL. Fluxer moves referenced uploads into embed media, so they are not returned in the message's attachment list

Fluxer also limits the combined text of all embeds in one message to 6,000 UTF-16 code units: Every title, description, footer text, author name, field name and field value counts, measured after normalization. Some bots receive a higher limit, so the SDK does not check this locally. A message over the limit fails remotely with reason rejected and an apiError with code invalidFormBody, so shorten long text, for example with text.truncate, or send fewer embeds

Fluxer fetches remote media and may normalize text. Permissions and instance-specific limits remain server-owned

export const exampleEmbed = {
    title: "Build finished",
    description: "Checks passed",
    url: "https://example.com/builds/42",
    color: 0x3d66b8,
    timestamp: "2026-09-08T14:30:00.000Z",
    author: { name: "Build service", url: "https://example.com", iconUrl: "https://example.com/author.png" },
    footer: { text: "Build #42", iconUrl: "https://example.com/footer.png" },
    image: { url: "https://example.com/results.png", description: "Build results" },
    thumbnail: { url: "https://example.com/icon.png", description: "Project icon" },
    fields: [{ name: "Status", value: "Passed", inline: true }, { name: "Details", value: "" }],
}
import type { EmbedInput } from "@neontechspace/fluxerly"

export const exampleEmbed = {
    title: "Build finished",
    description: "Checks passed",
    url: "https://example.com/builds/42",
    color: 0x3d66b8,
    timestamp: "2026-09-08T14:30:00.000Z",
    author: { name: "Build service", url: "https://example.com", iconUrl: "https://example.com/author.png" },
    footer: { text: "Build #42", iconUrl: "https://example.com/footer.png" },
    image: { url: "https://example.com/results.png", description: "Build results" },
    thumbnail: { url: "https://example.com/icon.png", description: "Project icon" },
    fields: [{ name: "Status", value: "Passed", inline: true }, { name: "Details", value: "" }],
} satisfies EmbedInput

Pass this object in the embeds array of send, reply or edit. The example URLs are placeholders

author optional#

Author label and optional links

EmbedAuthorInput
color optional#

RGB integer from 0x000000 through 0xffffff

number
description optional#

Main body text

An empty string is omitted by Fluxer. A nonempty value must contain 1–4,096 normalized UTF-16 code units

string
fields optional#

Up to 25 named sections, in display order

Entries are copied by index when the operation starts

readonly EmbedFieldInput[]
image optional#

Full-size HTTP(S) image or attachment://filename for one same-message uploaded image or video

EmbedMediaInput
thumbnail optional#

Small HTTP(S) image or attachment://filename for one same-message uploaded image or video

EmbedMediaInput
timestamp optional#

Time shown with the embed, an ISO 8601 string with a timezone such as new Date().toISOString()

Invalid calendar dates are rejected locally

string
title optional#

Heading text, up to 256 normalized UTF-16 code units

Supply url to make it a link

string
url optional#

Destination URL for the title

string

EmbedMedia#

Information about an embed image, video or audio file, not downloaded bytes

The object is frozen, missing or null server fields become omitted properties. Reading these fields does not download or play media

interface EmbedMedia
contentHash optional#

Server's identifier for the media contents

The SDK does not verify it against downloaded bytes

string
contentType optional#

Media type such as image/png, when known

string
description optional#

Alternative text when provided

string
duration optional#

Duration in seconds

number
flags#

Numeric Fluxer media flags, kept as received, including flags unknown to this SDK

number
height optional#

Height in pixels

number
placeholder optional#

Base64 placeholder supplied by Fluxer, not decoded by the SDK

string
proxyUrl optional#

Media URL served through Fluxer's media proxy, when supplied

string
url#

Original media location

string
width optional#

Width in pixels

number

EmbedMediaInput#

Media for an image or thumbnail field in a rich card

Use an HTTP(S) image URL or attachment://filename for a new image or video uploaded with the same message. The SDK neither uploads through this object nor fetches remote or retained attachment bytes

interface EmbedMediaInput
description optional#

Optional description for readers who cannot see the media, 1–4,096 normalized UTF-16 code units

string
url#

Required HTTP(S) image URL or attachment://filename naming an uploaded image or video for image and thumbnail fields

string

EmbedProvider#

Preview-provider information received with a message, such as the site a link preview came from

Fluxer supplies only a name and a link, so unlike an author, a provider has no icon. The object is frozen, missing or null server fields become omitted properties

interface EmbedProvider
name#

Server-provided label

string
url optional#

Destination for the label

string

ForwardMessageInput#

Input for copying a source message into a new forward

Fluxer captures the source. The SDK does not fetch it, check access beforehand or upload new content. Omit both media selectors to copy source text and media. A nonempty selector copies only selected media and omits source text. Empty selectors behave like omitted selectors. Selector arrays are copied by index when the operation starts

interface ForwardMessageInput
attachmentIds optional#

Source attachment IDs to copy, at most ten

A nonempty list makes the forward media-only

readonly string[]
embedIndices optional#

Source embed positions to copy, at most ten, with 0 identifying the first embed

A nonempty list makes the forward media-only

readonly number[]
nonce optional#

Application-chosen correlation nonce, or omit for one SDK-generated nonce per messages.forward execution

Webhook forwards send no nonce unless supplied on the message or this source. Fluxer's matching-nonce suppression is best-effort for five minutes after persistence, not guaranteed exactly-once creation

MessageNonce
source#

Source address Fluxer should capture

It may be in another channel, and the SDK does not fetch it beforehand

MessageReference

HistoryIterationQuery#

Limits and starting point for messages.iterateHistory, reading newest messages first

For newer-than or centered windows, use messages.fetchHistory with after or around instead

interface HistoryIterationQuery extends PaginationQueryinterface HistoryIterationQuery
  extends PaginationQuery
before optional#

Start with messages older than this decimal message ID, excluding it

Omit to start with the latest visible messages

string

Inherited from PaginationQuery: maxItems, maxPages, pageSize

Message#

Message data returned by a request or delivered through messageCreate and messageUpdate

This object and its nested data cannot be changed. They record what Fluxer returned at that time, not a live message with methods. Later edits, deletions and reaction changes do not update it. If an optional field is missing, Fluxer did not supply it. Do not read that as false or empty. A null value preserves the explicit value Fluxer returned. References and mentioned accounts are included only as supplied, without extra fetches. Clients configured with messageFields return SelectedMessage instead of the complete Message shape

interface Message extends MessageReferenceinterface Message
  extends MessageReference
export function messageMetadataExample(message) {
    const forwardedFrom = message.messageReference?.type === 1 ? message.messageReference.channelId : undefined
    const totals = message.reactions?.map(({ emoji, count }) => `${emoji.name}: ${count}`) ?? []
    return { createdAt: message.createdAt, forwardedFrom, totals }
}
import type { Message } from "@neontechspace/fluxerly"
export function messageMetadataExample(message: Message) {
    const forwardedFrom = message.messageReference?.type === 1 ? message.messageReference.channelId : undefined
    const totals = message.reactions?.map(({ emoji, count }) => `${emoji.name}: ${count}`) ?? []
    return { createdAt: message.createdAt, forwardedFrom, totals }
}
attachments#

Attached file metadata in received order, or an empty array

File contents are not downloaded

readonly Attachment[]
author#

Partial account identity supplied as the author, without profile lookup or account methods

Webhook and deleted-user authors remain partial MessageUser values and must not be treated as complete User objects

MessageUser
channelType optional#

Fluxer's numeric type of the channel the message was sent in, such as ChannelType.Text

A direct message reports 1 and a group direct message 3, which ChannelType does not name. Values added by Fluxer in the future are retained, so do not assume a closed set. Absent when Fluxer supplied none, and reading it performs no request. Gateway messageCreate events only: REST reads and messageUpdate events never carry it. It is delivered on the event only and is not kept in the message cache, whose copy of the message omits it

number
content#

Message text without trimming, possibly empty for a message containing only media

string
createdAt optional#

Creation timestamp as an ISO 8601 string with a timezone, when supplied

string
editedAt optional#

Latest edit timestamp as an ISO 8601 string with a timezone

Null means no edit was reported, absence means unknown

string | null
embeds#

Received embeds in display order, or an empty array when none were supplied

readonly Embed[]
flags optional#

Fluxer's integer flag set, when supplied

Unrecognized bits are retained, and absence does not mean zero

number
guildId optional#

Community containing the message, when supplied

Absence alone does not establish that the channel is private

string
member optional#

The author's community membership as Fluxer attached it to a messageCreate or messageUpdate event, read from the community's current state at dispatch time

It is a frozen observation completed with the author's username and bot flag, with the community taken from guildId. Gateway events only: REST reads never carry it. It is also omitted for direct messages, webhook messages and authors who left the community, and when the member Fluxer sent does not decode, which never costs the event itself. It is delivered on the event only and is not kept in the message cache, whose copy of the message omits it, so a later cache read never shows a stale member. The members cache holds the current one: With it enabled, the SDK stores this member there whether or not messageFields selects it

GuildMember
mentionChannels optional#

Channel mentions supplied with the message

Null and absence preserve distinct response values

readonly MessageChannelMention[] | null| readonly MessageChannelMention[]
| null
mentionedEveryone optional#

Whether Fluxer reports an @everyone or @here mention

Absence means unknown

boolean
mentionedHere optional#

Whether Fluxer reported a here mention on a messageCreate event

Fluxer sends the flag only as true, so absence means it reported none rather than false. Gateway messageCreate events only: REST reads and messageUpdate events never carry it. It is delivered on the event only and is not kept in the message cache, whose copy of the message omits it

boolean
mentionRoleIds optional#

Mentioned role IDs in received order

An empty array means none were reported, absence means unknown

readonly string[]
mentions optional#

Mentioned accounts in received order

An empty array means no mentions were reported, absence means unknown

readonly MessageUser[]
messageReference optional#

Received context for a reply, forward, published copy or channel-follow notice, when supplied

A channel-follow notice can identify only a source channel, without a message ID. Reading this field performs no request

MessageContextReference | null
messageSnapshots optional#

Copies captured when Fluxer created a forward

They contain no source ID and do not follow later source edits

readonly MessageSnapshot[] | null
nicknames optional#

The nicknames of a group direct message, keyed by decimal user ID, as Fluxer attached them to a messageCreate event

It is frozen, and an ID without an entry has no nickname there. Fluxer omits it for every other channel and when the group has no nicknames, so absence does not mean the channel is not a group direct message. Gateway messageCreate events only: REST reads and messageUpdate events never carry it. It is delivered on the event only and is not kept in the message cache, whose copy of the message omits it

Readonly<Record<string, string>>
nonce optional#

Correlation nonce returned by Fluxer, null when explicitly reported, or absent when not supplied

string | null
nsfwEmojiIds optional#

Custom emoji IDs that Fluxer classified as explicit

An empty array is known empty and absence is unknown

readonly string[]
pinned optional#

Pin status at observation time

Absence means unknown, not unpinned

boolean
reactions optional#

Reaction counts at observation time, not a list of users or counts that update after delivery

readonly MessageReactionSummary[] | null| readonly MessageReactionSummary[]
| null
referencedMessage optional#

Resolved reply snapshot

Null means the target was missing and absence means no resolution was supplied. Fluxer omits a second referencedMessage from this snapshot, so reply nesting is bounded to one level. Reading this field performs no request

ReferencedMessage | null
referencedUsers optional#

Accounts referenced by non-notifying text, embeds or forward snapshots

These are separate from active mentions and never change notification behavior. Null, absence and an empty array preserve the distinct values supplied by Fluxer

readonly MessageUser[] | null
stickers#

Attached sticker metadata in received order, or an empty array

Sticker images are not downloaded

readonly MessageSticker[]
thread optional#

The thread started from this message, as observed when Fluxer supplied the message

Fluxer includes it only while the thread exists, on a message with MessageFlags.HasThread. Reading this field performs no request

GuildThreadChannel
tts optional#

Whether the message was sent as text-to-speech

Absence means unknown, not false. Fluxer does not store this value, so it is meaningful only on the message returned by a send and on messageCreate events. Every other read, including fetches, history pages and later message events, reports false. In a community, Fluxer creates a normal message and reports false when the sender lacks the Send TTS Messages permission

boolean
type optional#

Fluxer's integer message type, when supplied, such as MessageType.Reply

Values added by Fluxer in the future are retained

number
webhookId optional#

Webhook that sent this message, when Fluxer supplied its ID

A missing or null response value omits this field

string

Inherited from MessageReference: channelId, id

MessageChannelMention#

Channel identity supplied in message or forward-snapshot mention data

It contains only an ID, name and type, not cached channel settings or a decision that the bot may access it

interface MessageChannelMention
id#

Mentioned channel ID as a decimal string

string
name#

Channel name captured with the mention

string
type#

Fluxer's numeric channel type

Unrecognized future values are retained

number

MessageCleanupBatch#

Exact IDs in one cleanup bulk-delete request, containing at most 100 IDs

Batches run sequentially. A successful HTTP response means Fluxer accepted the request. It does not prove that every ID existed or was deleted

interface MessageCleanupBatch
batchIndex#

Submission position, with 0 identifying the first batch

number
messageIds#

Selected IDs assigned to this request, in preview order

Cleanup does not rescan history

readonly string[]

MessageCleanupOptions#

Settings for cleanup's batch submissions

One timeoutMs deadline covers the entire cleanup execution, including rate-limit waits between batches. Preview has its own separate per-call deadline and does not accept onProgress

interface MessageCleanupOptions extends RequestOptionsinterface MessageCleanupOptions
  extends RequestOptions

Aborting the signal returns CancelledError rather than a partial report. Earlier requests may already have been submitted. Use progress observations for application-owned reconciliation

onProgress optional#

Observe submitting, submitted and failed batches synchronously

Return values are not awaited, and the callback does not schedule retries or recovery. A throw, a rejected asynchronous return or a returned or resolved Err result goes to the client-level onError as a progress FailureReport with the thrown, rejected or Err error, or is logged at Error, and cleanup continues. The callback runs synchronously in both entry points, so a returned Effect is not run. It is reported as a progress FailureReport with a TypeError instead of being ignored

(progress: MessageCleanupProgress) => unknown(progress: MessageCleanupProgress)
  => unknown

Inherited from RequestOptions: signal, timeoutMs

MessageCleanupPlan#

Frozen preview of the exact messages to inspect before requesting deletion

Pass the original object to cleanup on the client that produced it. Reconstructed JSON and plans from another client are rejected. Cleanup marks a valid plan as used before it sends any deletion request, even if it then fails before sending one. A consumed plan cannot be retried. Use a fresh preview or explicit deleteMany requests after application-owned reconciliation. The plan does not store a reference to its client or save requests to disk. The SDK cannot recover it after a crash

interface MessageCleanupPlan<M extends MessageCore = Message>interface MessageCleanupPlan<
  M extends MessageCore = Message
>
channelId#

Channel inspected by preview and the only channel this plan can delete from

string
scannedCount#

Number of messages inspected, including messages rejected by the selection

number
selectedMessages#

Exact selected message snapshots, newest first

Changes after preview do not update this selection

readonly M[]
stopReason#

Condition that ended preview

Even historyExhausted describes an observed empty page, not a stable remote snapshot

MessageCleanupStopReason

MessageCleanupReport#

Report returned after cleanup received successful responses for its selected batches

This reports submissions, not a verified number of deleted messages. Deletion is not atomic and the SDK does not roll back earlier batches. An empty selection produces a successful report without a delete request

interface MessageCleanupReport
channelId#

Channel targeted by the preview plan

string
scannedCount#

Number of history messages inspected during the earlier preview, not during deletion

number
selectedMessageIds#

Exact IDs copied from the plan, newest first

readonly string[]
submittedBatches#

Batch requests that received successful HTTP responses, in submission order

readonly MessageCleanupBatch[]

MessageCleanupSelection#

Choose messages for previewCleanup without deleting them

Set explicit scan and selection limits, and supply authorId, filter, or both. With both supplied, a message must match the author before the filter runs. Messages are inspected newest first, using this client's messageFields selection. The SDK keeps the preview and deletion plan only in memory, not on disk

interface MessageCleanupSelection<M extends MessageCore = Message>interface MessageCleanupSelection<
  M extends MessageCore = Message
>
authorId optional#

Select only messages authored by this account ID, as a decimal string

string
filter optional#

Return true to select a message, false to skip it

Runs synchronously, so do not block or return a Promise. A throw or non-boolean return fails preview with reason filter, before any deletion. Cancellation and timeouts cannot preempt blocking JavaScript. Mistaken asynchronous work is not awaited or cancelled

(message: M) => boolean
maxScanned#

Maximum history messages to fetch and inspect, a required integer from 1 through 10,000

number
maxSelected#

Maximum selected snapshots to keep in the plan, a required integer from 1 through 10,000

number

MessageContextReference#

Received source context for a reply, forward, published copy or channel-follow notice

A channel-follow notice identifies the followed announcement channel without a source message ID. Type 0 is a default reference and type 1 is a forward. The containing message's type and flags distinguish replies, published copies and channel-follow notices. Future numeric reference types are retained

interface MessageContextReference

Check that id is present before constructing a MessageReference for a fetch, reply or other message operation. Reading this context performs no request and does not establish access to the source

channelId#

Source channel ID as a decimal string, required even when no source message is identified

string
guildId optional#

Source community ID, or null when Fluxer explicitly supplied no community

Absence means unknown

string | null
id optional#

Source message ID as a decimal string

A missing or null response value omits this field

string
type optional#

Reference kind, when supplied

A partial gateway observation can omit it

number

MessagePin#

One pin observed by a request, pairing a message snapshot with the time it was pinned

Later unpins, repins and message edits do not update this frozen object

interface MessagePin<M extends MessageCore = Message>interface MessagePin<
  M extends MessageCore = Message
>
message#

Message as returned by this page, using the client's messageFields selection

M
pinnedAt#

Time Fluxer pinned the message, preserved as an ISO 8601 string with a timezone

string

MessagePinsPage#

One frozen page of pins, ordered newest pin time first

Pins added or removed during traversal, or pins with the same timestamp, can cause a multi-page list to miss messages. A message can recur on later timestamp pages, even though IDs are unique within one page

interface MessagePinsPage<M extends MessageCore = Message>interface MessagePinsPage<
  M extends MessageCore = Message
>
hasMore#

True when Fluxer reports more visible pins after this page

boolean
items#

Pins in Fluxer's received order, with no more entries than the requested limit

readonly MessagePin<M>[]
nextBefore#

Timestamp to pass as before, using the last pin time when hasMore is true, otherwise null

In a manual loop, deduplicate message IDs and stop if this cursor fails to move to an older time

string | null

MessagePinsQuery#

Choose one page of pins for messages.fetchPins

Pages are ordered by when messages were pinned, not when they were created. Use iteratePins for bounded multi-page traversal. Fields are captured once. Invalid timestamps, limits and unknown properties are rejected before the request

interface MessagePinsQuery
before optional#

Pin-time cursor as an ISO 8601 timestamp with seconds and a Z or ±hh:mm offset, such as "2026-01-01T00:00:00Z"

Any fraction length is accepted and the value is sent unchanged. Page ordering and cursor progress retain every fractional digit and compare timestamps by instant across timezone offsets. Select older pin times. Omit to use Fluxer's current-time default. Other forms and impossible calendar dates are rejected before dispatch

string
limit optional#

Maximum pins requested in this page, an integer from 1 through 50, default 50

number

MessageReactionEmoji#

Emoji information supplied beside a message's reaction count

Optional values preserve both null and absence when Fluxer distinguishes them

interface MessageReactionEmoji
animated optional#

Animation flag when supplied, retaining null separately from absence

boolean | null
id optional#

Custom emoji ID, or null for an explicitly identified Unicode emoji

Absence means the ID field was not supplied

string | null
name#

Literal Unicode emoji text or the custom emoji's name

string

MessageReactionSummary#

Count of reactions using one emoji when Fluxer supplied this message

This is not a user list or a count that updates after delivery

interface MessageReactionSummary
count#

Nonnegative reaction count reported at observation time

number
emoji#

Emoji to which this count belongs

MessageReactionEmoji
me optional#

Whether the observing bot had reacted, when supplied

Null and absence preserve distinct response values

boolean | null

MessageReference#

Identify a message by its channel ID and message ID

Pass this plain object to message operations without fetching the message first. The SDK captures and validates both IDs once when an operation starts. It holds no client and makes no request by itself

interface MessageReference
channelId#

Channel ID as a decimal string, identifying where to send the operation

string
id#

Message ID as a decimal string

Keep it as a string to avoid losing integer precision

string

MessageSearchChannel#

Channel information supplied beside message search results

This frozen snapshot is not a complete channel, cached channel or permission check

interface MessageSearchChannel
guildId optional#

Owning community ID, when Fluxer supplied it

string
id#

Channel ID as a decimal string

string
name optional#

Observed channel name, when supplied

An unnamed group DM has null, and other private channels may omit it

string | null
type#

Fluxer's numeric channel type, including unrecognized future values

number

MessageSearchIndexingPage#

Successful search response indicating that Fluxer is still preparing an index

No messages or result total are available yet. Retry later with another explicit search request. The SDK does not poll or retry indexing automatically

interface MessageSearchIndexingPage
indexing#

True distinguishes this response from a MessageSearchResultsPage

true

MessageSearchIterationLimits#

Limit how many messages and pages messages.iterateSearch can read

Each consumption starts at page 1 for the given context and filters, then reads later numbered pages as Fluxer's total requires. Limits are captured once when that consumption starts. Fluxer supports at most 400 numbered pages. If more results remain after page 400, traversal fails with PaginationError reason pageLimit. No background prefetch runs. An indexing response fails traversal with PaginationError reason indexing rather than polling

interface MessageSearchIterationLimits extends PaginationQueryinterface MessageSearchIterationLimits
  extends PaginationQuery
pageSize optional#

Maximum messages per request, an integer from 1 through 25, default 25

Request capacity is the smaller of this value and maxItems, fixed throughout the scan to preserve page offsets

number

Inherited from PaginationQuery: maxItems, maxPages

MessageSearchQuery#

Filters and paging settings for one messages.search request

Fluxer searches an index that may not yet include recent edits or deletions. Search does not read message history or the local cache. Results are not added to the message cache. Omit a filter to leave that criterion unspecified. Fluxer combines and interprets the supplied search criteria. Unknown properties, invalid values and lists exceeding the documented limits are rejected locally. The SDK copies each filter array when the operation starts, so later changes to the array do not affect this request. All ID filters use decimal strings. Text limits count UTF-16 code units, the units used by JavaScript string.length

interface MessageSearchQuery
attachmentExtensions optional#

Attached file extensions to match, at most 50 strings of 1 through 32 UTF-16 code units each

readonly string[]
attachmentFilenames optional#

Attached file names to match, at most 100 strings of 1 through 1,024 UTF-16 code units each

readonly string[]
authorIds optional#

Match messages from these author IDs, at most 100 decimal strings

readonly string[]
authorTypes optional#

Author categories to include, at most 20 entries

readonly MessageSearchAuthorType[]
channelIds optional#

Limit matches to these channel IDs, at most 500 decimal strings

readonly string[]
content optional#

Text for Fluxer to search, from 1 through 1,024 UTF-16 code units, without local trimming

string
contents optional#

Multiple search texts, at most 100 strings, each from 1 through 1,024 UTF-16 code units

readonly string[]
embedProviders optional#

Embed provider names to match, at most 50 strings of 1 through 256 UTF-16 code units each

readonly string[]
embedTypes optional#

Embed categories to require, at most 20 entries, including generated and explicitly supplied embeds

readonly MessageSearchEmbedType[]
exactPhrases optional#

Contiguous phrases to match, at most 10 strings, each from 1 through 1,024 UTF-16 code units

readonly string[]
excludeAttachmentExtensions optional#

Attached file extensions to exclude, at most 50 strings of 1 through 32 UTF-16 code units each

readonly string[]
excludeAttachmentFilenames optional#

Attached file names to exclude, at most 100 strings of 1 through 1,024 UTF-16 code units each

readonly string[]
excludeAuthorIds optional#

Exclude messages from these author IDs, at most 100 decimal strings

readonly string[]
excludeAuthorTypes optional#

Author categories to exclude, at most 20 entries

readonly MessageSearchAuthorType[]
excludeChannelIds optional#

Exclude matches from these channels, at most 500 decimal ID strings

readonly string[]
excludeEmbedProviders optional#

Embed provider names to exclude, at most 50 strings of 1 through 256 UTF-16 code units each

readonly string[]
excludeEmbedTypes optional#

Embed categories to exclude, at most 20 entries, including generated and explicitly supplied embeds

readonly MessageSearchEmbedType[]
excludeHas optional#

Content categories to exclude, at most 20 entries

readonly MessageSearchContentType[]
excludeLinkHostnames optional#

Link hostnames to exclude, at most 100 strings of 1 through 255 UTF-16 code units each

readonly string[]
excludeMentions optional#

Exclude matches mentioning these accounts, at most 100 decimal ID strings

readonly string[]
has optional#

Content categories to require, at most 20 entries

readonly MessageSearchContentType[]
includeNsfw optional#

Request results from channels Fluxer marks NSFW, default false

In an age-restricted community, guild search includes NSFW results for eligible callers, including bots, even when omitted or false. Channel access checks still apply

boolean
limit optional#

Maximum indexed messages requested, an integer from 1 through 25, default 25

number
linkHostnames optional#

Link hostnames to match, at most 100 strings of 1 through 255 UTF-16 code units each

readonly string[]
maxId optional#

Include message IDs smaller than this decimal ID

string
mentionedEveryone optional#

Require or exclude messages that Fluxer's index marks as mentioning @everyone or @here

boolean
mentions optional#

Match account mentions using these IDs, at most 100 decimal strings

readonly string[]
minId optional#

Include message IDs greater than this decimal ID

string
page optional#

Numbered result page, an integer from 1 through 400 with 1 meaning the first page

Defaults to 1

number
pinned optional#

Require pinned messages with true, or unpinned messages with false, according to the index

boolean
sortBy optional#

Rank results by timestamp or relevance, default timestamp

"timestamp" | "relevance"
sortOrder optional#

Ascending or descending result order, default desc

"desc" | "asc"

MessageSearchResultsPage#

Search results returned once Fluxer's index can answer the request

The page and its nested results are frozen. Later index updates can change later pages and totals. Check indexing before reading results, since search can instead return MessageSearchIndexingPage

interface MessageSearchResultsPage<M extends MessageCore = Message>interface MessageSearchResultsPage<
  M extends MessageCore = Message
>
channels#

One channel snapshot per distinct channel in messages that is not a thread, without extras, private recipient lists or permission data

readonly MessageSearchChannel[]
hitsPerPage#

Page capacity Fluxer reported for this response, not necessarily the number of returned messages

number
indexing#

False distinguishes this response from an index-preparation response

false
messages#

Indexed message snapshots using the client's messageFields selection, without extra fetches or cache writes

readonly M[]
page#

Page number Fluxer applied, starting at 1

number
threads#

One thread snapshot per distinct thread in messages, with membership set on each thread the bot has joined

Each message's channelId names exactly one entry of channels or threads. These snapshots never enter the channel cache

readonly GuildThreadChannel[]
total#

Indexed match count observed with this response, not a stable count for a multi-page run

number

MessageSnapshot#

Copy of source content captured by Fluxer when a message was forwarded

The snapshot is deeply frozen and contains no source message or author ID. Later source edits and deletions do not change this copy. Optional null and absent values remain distinct

interface MessageSnapshot
attachments optional#

Copied attachment metadata in display order, without downloading file contents

readonly Attachment[] | null
content optional#

Source text at capture time, including null when explicitly supplied

string | null
createdAt#

Source message creation time as an ISO 8601 string with a timezone

string
editedAt optional#

Source edit time at capture, as an ISO 8601 string, or null when explicitly supplied

string | null
embeds optional#

Source embed copies in captured display order

readonly Embed[] | null
flags#

Source flag set at capture, retaining unrecognized bits

number
mentionChannels optional#

Source channel mentions in captured display order

readonly MessageChannelMention[] | null| readonly MessageChannelMention[]
| null
mentionRoleIds optional#

Role IDs mentioned in the source at capture time

readonly string[] | null
mentionUserIds optional#

Account IDs mentioned in the source, not account objects

No account lookup is performed

readonly string[] | null
stickers optional#

Source sticker metadata in captured display order, without downloading images

readonly MessageSticker[] | null
type#

Fluxer's integer source message type at capture, retaining unrecognized future values

number

MessageSticker#

Sticker metadata supplied with a message or forward snapshot

This frozen observation is not the editable community sticker resource

interface MessageSticker
animated#

Whether Fluxer identifies this sticker as animated

boolean
id#

Sticker ID as a decimal string

string
name#

Sticker name at observation time

string

MessageUser#

Partial account identity embedded in a message response

This deeply frozen observation can describe an author, active mention or non-notifying referenced account. It is not a complete User, community member or live cached object. Optional fields remain absent when Fluxer omitted them, including for webhook and deleted-user placeholders. The mentionFlags value is descriptive only and never enables a notification or overrides AllowedMentions

interface MessageUser
avatar optional#

Avatar asset hash, null when explicitly absent

string | null
avatarColor optional#

Dominant avatar color, null when explicitly absent

number | null
discriminator optional#

Provider discriminator when supplied

string
displayName optional#

Account-wide display name, null when explicitly unset

string | null
flags optional#

Public account flags when supplied

Unrecognized 32-bit values are retained

number
id#

Account or webhook identity as a decimal string

string
isBot#

True when Fluxer marked the identity as a bot, otherwise false

boolean
isSystem optional#

Whether Fluxer marked this as an official system account

boolean
mentionFlags optional#

Account-wide reply mention preference: 0 for none, 1 to prefer a mention, or 2 to prefer no mention

This is displayable context only. Sending and replying continue to use explicit AllowedMentions

0 | 2 | 1
username#

Username or webhook name at observation time

string

Messages#

Read, send and change messages with client.messages, or collect future messages and reactions

HTTP operations and local get lookups do not need a gateway connection. Received messages are frozen copies. They do not update when Fluxer changes. Their fields follow this client's messageFields selection, which defaults to the full Message. That selection also applies to nested messages, callbacks and cached snapshots. The delete, deleteMany, pin and unpin methods accept AuditedRequestOptions. Other message operations reject auditReason

interface Messages<M extends MessageCore = Message>interface Messages<
  M extends MessageCore = Message
>

Remote calls start when called and normally return ResultAsync. Await one to get Ok or Err. The default timeoutMs is the client's rest.defaultTimeoutMs, 30,000 unless configured, for the whole call, including queue, rate-limit and retry waits. The SDK waits for request cleanup afterward, so the timeout is not a hard cleanup time limit. By default this client runs four REST or upload requests at once per local shard, up to 64 (rest.concurrency), and four separate attachment downloads (rest.mediaConcurrency). Both pools together allow at most 256 waiting requests or 4 MiB of queued JSON bodies by default. The rest client option changes these limits. These limits apply across the shards assigned to this client

Text with a lone surrogate, half of a character such as an emoji left by slice, fails locally with reason input, because Fluxer answers it with HTTP 503 and stores nothing. The text.truncate and text.split helpers and toWellFormed() clean it

The fetch, fetchCrosspostSource, fetchHistory, fetchReactionUsers, fetchHasReaction and fetchPins methods retry transport failures and HTTP 500, 502, 503 or 504 at most twice. The retry delays are 125–250 ms, then 250–500 ms, or a longer valid Retry-After. Retries use the same target and query and never reset the deadline. When a retry could not start before the deadline, the received failure is returned at once. Results can change between attempts. Confirmed HTTP 429 rejections have separate route and global waits and do not consume those two retries. Writes retry only confirmed rate-limit rejections. A write with no clear result may already have succeeded and is not retried. Other rejections and malformed successes are not retried. Successful JSON bodies are limited to 16 MiB before parsing, not total memory usage

Expected failures return Err. Unexpected SDK or cleanup failures reject with SdkDefect, or throw from synchronous get. An aborted signal returns CancelledError. Closing the client makes pending and new operations fail with ClientClosedError. After a write is sent, cancellation or closure can leave the change applied, and neither proves rollback. Collectors need a ready gateway connection as described on collect and collectReactions

addReaction#

Add the bot's own reaction to a message

Pass Unicode such as "👍", custom markup such as "<a:party:123>", a parsed custom emoji, or a received emoji snapshot. ReactionEmojiInput defines accepted identities and local validation, and custom emoji are encoded as name:id. Fluxer decides emoji availability and permissions. Adding the same own reaction again leaves it present. Success follows HTTP 204, without waiting for or synthesizing a gateway event, and no gateway connection is required. The request uses a per-channel reaction rate limit separate from message operations, the client's request limits and the client's default deadline (rest.defaultTimeoutMs, 30,000 ms unless configured). Only confirmed rate-limit rejections retry, and unknown outcomes are never retried. Cancellation after dispatch cannot undo the reaction. Expected failures use MessageOperationError, or ClientClosedError after closure. The SDK does not retain reaction state, counts or reactor lists

addReaction(
    message: MessageReference,
    emoji: ReactionEmojiInput,
    options?: RequestOptions
): ResultAsync<
    void,
    ConfigurationError | MessageOperationFailure | CancelledError
>addReaction(
  message: MessageReference,
  emoji: ReactionEmojiInput,
  options?: RequestOptions
): ResultAsync<
  void,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Parameters

options optional
RequestOptions
export async function reactionExample(client, message) {
    const added = await client.messages.addReaction(message, "👍")
    if (added.isErr())
        return added
    return client.messages.removeReaction(message, "👍")
}
import type { Client, MessageReference } from "@neontechspace/fluxerly"
export async function reactionExample(client: Client, message: MessageReference) {
    const added = await client.messages.addReaction(message, "👍")
    if (added.isErr()) return added
    return client.messages.removeReaction(message, "👍")
}

cleanup#

Delete the exact IDs in a plan returned by previewCleanup, in sequential batches of at most 100

No history reread or filter rerun is performed. Each batch has the ManageMessages and two-factor authentication requirements of deleteMany. A plan is single-use even when cleanup fails or is cancelled, preventing accidental replay. To resolve an unknown outcome, preview again or call deleteMany with separately recorded IDs

cleanup(
    plan: MessageCleanupPlan<M>,
    options?: MessageCleanupOptions
): ResultAsync<
    MessageCleanupReport,
    ConfigurationError | MessageCleanupError | CancelledError
>cleanup(
  plan: MessageCleanupPlan<M>,
  options?: MessageCleanupOptions
): ResultAsync<
  MessageCleanupReport,
  | ConfigurationError
  | MessageCleanupError
  | CancelledError
>

One default deadline, rest.defaultTimeoutMs (30,000 ms unless configured), covers all batch submissions. The submittedBatches field records only earlier HTTP-success submissions, in the report or MessageCleanupError. The rejected or unknown terminal batch is reported separately. These records do not prove each deletion, a deletion count, atomicity or that retrying is safe

The onProgress callback runs synchronously and cleanup continues after it fails. A throw, a rejected promise or a returned or resolved Err result goes to the client-level onError as a progress FailureReport, or is logged at Error. A returned Effect is not run and is reported the same way as a TypeError, so run Effect work explicitly inside the callback. Cancellation can leave the batch being submitted with an unknown outcome. Batches retry only confirmed rate-limit rejections as deleteMany does, never an unknown outcome

Parameters

options optional
MessageCleanupOptions
export async function cleanupWorkflowExample(client, channelId, authorId) {
    const preview = await client.messages.previewCleanup(channelId, {
        authorId,
        filter: message => message.attachments.length > 0,
        maxScanned: 500,
        maxSelected: 200,
    })
    return preview.isErr() ? preview : client.messages.cleanup(preview.value)
}
import type { Client } from "@neontechspace/fluxerly"
export async function cleanupWorkflowExample(client: Client, channelId: string, authorId: string) {
    const preview = await client.messages.previewCleanup(channelId, {
        authorId,
        filter: message => message.attachments.length > 0,
        maxScanned: 500,
        maxSelected: 200,
    })
    return preview.isErr() ? preview : client.messages.cleanup(preview.value)
}

clearReaction#

Remove all users' reactions for one emoji on the message

Other emoji groups remain. Success follows HTTP 204, even if no matching reactions existed. The removeUserReaction method's permissions, request limits, deadline, failure and cleanup rules apply. Expected failures identify clearReaction. Fluxer emits a clear-emoji event, not individual removals, and the SDK does not create or wait for that event. Other users' reactions cannot be restored by the bot as those users

clearReaction(
    message: MessageReference,
    emoji: ReactionEmojiInput,
    options?: RequestOptions
): ResultAsync<
    void,
    ConfigurationError | MessageOperationFailure | CancelledError
>clearReaction(
  message: MessageReference,
  emoji: ReactionEmojiInput,
  options?: RequestOptions
): ResultAsync<
  void,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Parameters

options optional
RequestOptions

clearReactions#

Remove all users' reactions for all emoji on the message, without deleting the message

No emoji selector is needed. Success follows HTTP 204, whether reactions existed or not. The clearReaction method's permissions, request limits, deadline, failure and cleanup rules apply. Expected failures identify clearReactions. Fluxer emits one clear-all event, and the SDK does not create per-emoji or per-user events or wait for notification. Other users' reactions cannot be restored by the bot as those users

clearReactions(
    message: MessageReference,
    options?: RequestOptions
): ResultAsync<
    void,
    ConfigurationError | MessageOperationFailure | CancelledError
>clearReactions(
  message: MessageReference,
  options?: RequestOptions
): ResultAsync<
  void,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Parameters

options optional
RequestOptions

collect#

Collect a bounded set of future messageCreate events from one channel

Register before sending a prompt. It does not fetch history, read the cache, connect the client or match replies to a prompt automatically. With guildId, only that community's ready shard assigned to this client can feed the collector, and events with a known conflicting community are discarded without a channel lookup. Without guildId, the client must be Connected, and any gateway gap ends collection because the community is unknown. A gap fails with CollectorError connectionLost, even if the client later resumes, and collection is not restarted

collect(
    channelId: string,
    options?: CollectorOptions<M>
): Collector<M>collect(
  channelId: string,
  options?: CollectorOptions<M>
): Collector<M>

Defaults are one accepted message, a 30,000 ms lifetime and 4 MiB of retained selected-message JSON. After channel selection and before filtering, the pending queue allows 256 payloads or 4 MiB of source JSON. Options are copied at registration. Budgets must be positive safe integers, and timeoutMs and optional idleMs must be at most 2,147,483,647 ms

The total timeout starts at registration and never resets. The idleMs timer also starts at registration, then resets after each newly accepted message ID, before its callback. Rejected, queued or duplicate messages do not reset idleMs. Callback time counts toward both deadlines. The earlier deadline wins, with timeout winning ties. Messages processed at or after the deadline are excluded, including slow filter returns. Each accepted ID counts once, and later edits and deletions do not change collected snapshots

The synchronous filter decides acceptance. Filter failure or queue or retained-byte overflow ends this collector with a failure, without partial messages. A slow synchronous filter blocks JavaScript and cannot be preempted. Optional onMessage runs sequentially after filtering, duplicate removal and the retained-byte check. Reaching maxMessages waits for the final callback, and later messages are ignored while it completes. Idle, timeout or stop can retain a message whose callback was cancelled. Pending budgets exclude the active message. Callback failure ends collection with CollectorError reason handler. Callbacks are not retried and their effects are not undone. Filter the bot out when callbacks send acknowledgements, to avoid collecting those acknowledgements

Invalid options are misuse: The default API throws ConfigurationError and the native API dies with it. A client that is not ready returns a collector whose result is CollectorError notConnected, and a client that began shutting down, such as when a handler still running during shutdown registers, returns one whose result is ClientClosedError. A timeout can succeed with no messages. The application still manages the client's lifetime

Parameters

channelId
string
options optional
CollectorOptions<M>
Returns
Collector<M>

Returns a ready Collector handle synchronously. Return or await callback work, and closure waits for the callback promise. A callback that returns or resolves an Err result fails like a throw. The options.signal value controls the collection itself: Aborting it makes result return CancelledError, and a pre-aborted signal starts no collection. Use await using to close the collector when the block ends. Unexpected registration failures throw SdkDefect

import { orThrow } from "@neontechspace/fluxerly"

export async function askName(client, channelId, userId) {
    await using collector = client.messages.collect(channelId, { filter: message => message.author.id === userId })
    orThrow(await client.messages.send(channelId, { content: "What name should the bot use?" }))
    return orThrow(await collector.result())
}
import { orThrow, type Client } from "@neontechspace/fluxerly"

export async function askName(client: Client, channelId: string, userId: string) {
    await using collector = client.messages.collect(channelId, { filter: message => message.author.id === userId })
    orThrow(await client.messages.send(channelId, { content: "What name should the bot use?" }))
    return orThrow(await collector.result())
}
export async function messageCollectorProgressExample(client, channelId, userId) {
    const collector = client.messages.collect(channelId, {
        filter: message => message.author.id === userId,
        maxMessages: 3,
        idleMs: 5_000,
        // A failed reply is returned as an Err, which ends collection like a throw
        onMessage: (message, signal) => client.messages.reply(message, { content: "Reply received" }, { signal }),
    })
    return await collector.result()
}
import type { Client } from "@neontechspace/fluxerly"

export async function messageCollectorProgressExample(client: Client, channelId: string, userId: string) {
    const collector = client.messages.collect(channelId, {
        filter: message => message.author.id === userId,
        maxMessages: 3,
        idleMs: 5_000,
        // A failed reply is returned as an Err, which ends collection like a throw
        onMessage: (message, signal) => client.messages.reply(message, { content: "Reply received" }, { signal }),
    })
    return await collector.result()
}

collectReactions#

Collect future reaction additions for one message

Use decimal id and channelId, and register before the expected reaction. This does not fetch existing reactors, verify the message remotely, read the cache or connect the client. With guildId, only that community's ready shard assigned to this client feeds the collector, and known conflicting event communities are discarded without a membership lookup. Without guildId, the client must be Connected and any gateway gap ends collection with connectionLost, without restarting it

collectReactions(
    message: MessageReference,
    options?: ReactionCollectorOptions
): ReactionCollectorcollectReactions(
  message: MessageReference,
  options?:
    ReactionCollectorOptions
): ReactionCollector

Defaults are one accepted addition, a 30,000 ms lifetime and 4 MiB of retained reaction JSON. The target and options are copied at registration. After message selection, the pending queue allows 256 payloads or 4 MiB of full source JSON. Optional emoji uses addReaction's input shape and is checked after queueing, before the synchronous filter. Unicode emoji match exact text without a custom ID, and custom emoji match by ID, ignoring name changes. An invalid emoji selector fails with ConfigurationError for emoji

Single events and batch entries follow receive order. A batch uses one pending slot and its entries count individually. Repeated user and emoji pairs count again, and no batching flag is enabled. Removals, clears and message deletion neither undo additions nor stop collection, so this is not a vote tally

The total timeout starts at registration and never resets, and excludes additions processed at or after it, including slow filter returns. Optional idleMs starts then too and resets after each accepted addition, before its callback. Rejected, queued and unprocessed batch entries do not reset it. Callback time counts, and the earlier deadline wins, with timeout winning ties. The timeoutMs and idleMs values must be integers from 1 through 2,147,483,647 ms

Optional onReaction runs sequentially after acceptance and the retained-byte check. Limit completion waits for the final callback. Idle, timeout or stop can retain an addition whose callback was cancelled. Pending budgets exclude the active payload and its unprocessed batch entries. Callback failure ends collection with CollectorError reason handler, and no callback is retried or earlier effect undone. Filter or overflow failure ends with CollectorError without partial results. An invalid target or options are misuse: The default API throws ConfigurationError and the native API dies with it. A client that is not ready returns a collector whose result is CollectorError notConnected, and a client that began shutting down, such as when a handler still running during shutdown registers, returns one whose result is ClientClosedError. The example needs a connected client and an existing message, and idle or timeout may succeed with no reactions

Parameters

options optional
ReactionCollectorOptions

Returns a ready ReactionCollector synchronously. Closure waits for the callback's returned promise. A callback that returns or resolves an Err result fails like a throw. The options.signal value controls collection: Aborting it makes result return CancelledError, and a pre-aborted signal starts nothing. Use await using to close the collector when the block ends. Unexpected registration failures throw SdkDefect

import { orThrow } from "@neontechspace/fluxerly"

export async function reactionCollectorExample(client, message, userId) {
    let count = 0
    await using collector = client.messages.collectReactions(message, {
        maxReactions: 3,
        idleMs: 5_000,
        emoji: "✅",
        filter: reaction => reaction.userId === userId,
        onReaction: (_reaction, signal) => client.messages.edit(message, { content: `Accepted additions: ${++count}` }, { signal }),
    })
    return orThrow(await collector.result())
}
import { orThrow, type Client, type MessageReference } from "@neontechspace/fluxerly"

export async function reactionCollectorExample(client: Client, message: MessageReference, userId: string) {
    let count = 0
    await using collector = client.messages.collectReactions(message, {
        maxReactions: 3,
        idleMs: 5_000,
        emoji: "✅",
        filter: reaction => reaction.userId === userId,
        onReaction: (_reaction, signal) =>
            client.messages.edit(message, { content: `Accepted additions: ${++count}` }, { signal }),
    })
    return orThrow(await collector.result())
}

delete#

Delete one message, succeeding with no value after HTTP 204

Deleting another author's message requires ManageMessages, and Fluxer rejects that deletion with HTTP 400 and apiError.code twoFactorRequired in a community whose mfaLevel is GuildMfaLevels.Elevated, unless the bot owns the community or its application owner has two-factor authentication enabled. No gateway notification is awaited. A missing message fails with MessageOperationError reason notFound, including a repeated delete. The auditReason option supplies an optional community audit-log explanation. Successful deletions and deletions with unknown outcomes remove the cached message. A lost response, timeout, cancellation or closure can leave the deletion applied. Request cleanup is awaited, but the deletion cannot be undone. Deletes with unknown outcomes are never retried automatically

delete(
    message: MessageReference,
    options?: AuditedRequestOptions
): ResultAsync<
    void,
    ConfigurationError | MessageOperationFailure | CancelledError
>delete(
  message: MessageReference,
  options?: AuditedRequestOptions
): ResultAsync<
  void,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Parameters

options optional
AuditedRequestOptions

deleteAttachment#

Delete one attachment by its decimal ID from a message authored by this bot

The target is copied when execution starts, and the attachment list is neither fetched nor replaced. No gateway connection is needed. Success follows HTTP 204, without waiting for an event. If the last attachment is removed, Fluxer can also delete a message it considers otherwise empty. Successful deletions and deletions with unknown outcomes remove this message's cached copy, and no events are created locally. A notFound failure can mean the attachment is missing without proving the message is absent. Message request limits and deadlines apply, and only confirmed HTTP 429 rejection retries. Storage removal and message updates are separate changes, so a lost response can leave either applied. Cancellation waits for cleanup but cannot undo deletion or guarantee physical erasure

deleteAttachment(
    message: MessageReference,
    attachmentId: string,
    options?: RequestOptions
): ResultAsync<
    void,
    ConfigurationError | MessageOperationFailure | CancelledError
>deleteAttachment(
  message: MessageReference,
  attachmentId: string,
  options?: RequestOptions
): ResultAsync<
  void,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Parameters

attachmentId
string
options optional
RequestOptions
export function attachmentDeleteExample(client, message, attachmentId) {
    return client.messages.deleteAttachment(message, attachmentId)
}
import type { Client, MessageReference } from "@neontechspace/fluxerly"
export function attachmentDeleteExample(client: Client, message: MessageReference, attachmentId: string) {
    return client.messages.deleteAttachment(message, attachmentId)
}

deleteMany#

Delete 1–100 distinct decimal message IDs from one community channel

Fluxer requires ManageMessages, even for the bot's own messages. Fluxer rejects the request with HTTP 400 and apiError.code twoFactorRequired in a community whose mfaLevel is GuildMfaLevels.Elevated, unless the bot owns the community or its application owner has two-factor authentication enabled. IDs are copied once when execution starts, and that copy is validated and sent, so an entry that changes between reads cannot pass validation with one value and be sent with another. Success follows HTTP 204, not a deletion count or proof that each ID existed, and missing messages are ignored. No gateway connection, automatic selection, chunking or age filter is added. The auditReason option supplies an optional community audit-log explanation. Dispatched requests remove selected cache entries even on rejection, because partial deletion is possible. Only confirmed rate-limit rejection retries. A lost response, timeout, cancellation or closure can leave deletions applied. Input, capacity and HTTP failures use MessageOperationError, and cancellation waits for request cleanup

deleteMany(
    channelId: string,
    messageIds: readonly string[],
    options?: AuditedRequestOptions
): ResultAsync<
    void,
    ConfigurationError | MessageOperationFailure | CancelledError
>deleteMany(
  channelId: string,
  messageIds: readonly string[],
  options?: AuditedRequestOptions
): ResultAsync<
  void,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Parameters

channelId
string
messageIds
readonly string[]
options optional
AuditedRequestOptions
async function cleanupExample(client, channelId, selectedIds) {
    return await client.messages.deleteMany(channelId, selectedIds)
}
import type { Client } from "@neontechspace/fluxerly"
async function cleanupExample(client: Client, channelId: string, selectedIds: readonly string[]) {
    return await client.messages.deleteMany(channelId, selectedIds)
}

deleteOwnMessages#

Irreversibly delete this bot's entire authored message history in one channel and in every thread under it, active or archived

Use a decimal channel ID. A thread ID clears only that thread, and for a forum or media channel the deleted messages are the ones in its posts. Other authors' messages are preserved, and no gateway connection, community leave or role change is performed

deleteOwnMessages(
    channelId: string,
    options: OwnMessageDeletionOptions
): ResultAsync<
    void,
    ConfigurationError | MessageOperationFailure | CancelledError
>deleteOwnMessages(
  channelId: string,
  options:
    OwnMessageDeletionOptions
): ResultAsync<
  void,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Success follows Fluxer's empty HTTP 202 response. It is not a completed-job report, deletion count, gateway event or proof the channel is empty. Deletion can be partial and can leave new or concurrent messages. There is no recovery token, automatic reconciliation or atomicity guarantee

Bot credentials satisfy Fluxer's extra authentication checks, called sudo checks, and no extra sudo input is accepted. Fluxer handles attachment removal without guaranteeing physical provider-storage or CDN erasure. The default deadline, rest.defaultTimeoutMs (30,000 ms unless configured), includes capacity and rate-limit waits. Only confirmed HTTP 429 rejection retries, and a 5xx or lost response never causes a replay. After dispatch, the entire enabled message cache is cleared and older pending reads cannot restore it. No gateway events are created locally. Cancellation or closure waits for request cleanup but cannot undo deletion. Options must include confirm: true. Without it, the call fails before any request with reason input and path options.confirm. Input, capacity and HTTP failures use MessageOperationError for deleteOwnMessages

Parameters

channelId
string

edit#

Change a message's supplied fields and return its frozen updated snapshot after HTTP, without waiting for a gateway event

A plain string replaces only the text, as shorthand for { content }. Omitted fields remain unchanged. No hidden fetch or cache merge is performed. Mentions default off. Existing stickers are preserved and cannot be replaced here. An empty content string requests removal of text, subject to Fluxer's validation. To remove embeds, send nonempty content with embeds: []. An otherwise empty edit is rejected by Fluxer. Omitted rich embeds remain, but link previews may be regenerated

edit(
    message: MessageReference,
    input: string | EditMessageInput,
    options?: RequestOptions
): ResultAsync<
    M,
    ConfigurationError | MessageOperationFailure | CancelledError
>edit(
  message: MessageReference,
  input: string | EditMessageInput,
  options?: RequestOptions
): ResultAsync<
  M,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

To keep existing files while adding new uploads, include their IDs in attachments. The supplied list replaces the old one. An empty list clears files when nonempty text or embeds remain. Retained file title or description can be replaced or cleared with null. Unknown IDs may be ignored, and a stale list can remove concurrent additions. An attachment:// image or thumbnail URL must match a new image or video upload, not a retained attachment. New uploads use send's copying, attachment source, size, budget and cleanup rules, and inline multipart 429 responses do not replay file or stream sources. Failed edits may leave temporary server data, without physical-erasure guarantees. A flags-only edit is allowed. Omission preserves flags, supplied flags replace only MessageFlags.SuppressEmbeds and MessageFlags.SuppressNotifications, and 0 clears those two bits. Server-managed flags, including the crosspost flags, fail locally before dispatch

Eligible responses can enter the cache. A dispatched edit with an unknown outcome removes the old cached copy. A missing message fails with notFound. A lost response, timeout, cancellation or closure can leave the edit applied. The SDK does not automatically retry edits with unknown outcomes

Parameters

input
string | EditMessageInput
options optional
RequestOptions

fetch#

Fetch one message from Fluxer, rather than reading the cache

Pass a reference with id and channelId, or an existing Message. The result is a frozen snapshot after response decoding and target-ID checks. A missing target fails with MessageOperationError reason notFound, not an empty value. An enabled cache can retain eligible results, but a full cache does not prevent the read from succeeding. The namespace's bounded read retries apply, so no caller retry loop is needed for eligible transient failures. Cancellation stops this request only and waits for cleanup

fetch(
    message: MessageReference,
    options?: RequestOptions
): ResultAsync<
    M,
    ConfigurationError | MessageOperationFailure | CancelledError
>fetch(
  message: MessageReference,
  options?: RequestOptions
): ResultAsync<
  M,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Parameters

options optional
RequestOptions
export async function readExample(client, message) {
    const result = await client.messages.fetch(message, { timeoutMs: 2_000 })
    if (result.isErr())
        throw result.error
    return result.value.content
}
import type { Client, MessageReference } from "@neontechspace/fluxerly"
export async function readExample(client: Client, message: MessageReference) {
    const result = await client.messages.fetch(message, { timeoutMs: 2_000 })
    if (result.isErr()) throw result.error
    return result.value.content
}

fetchCrosspostSource#

Fetch frozen public source-community metadata for a published copy or a ChannelFollowAdd notice

Fluxer applies ordinary message access checks and returns UNKNOWN_MESSAGE for other targets, including a published source. The profile reflects the community when fetched, not when the original message was published. It preserves public badge feature strings, including unknown values, and unavailable approximate counts as null, never zero. Counts can be cached upstream for up to 60 seconds

fetchCrosspostSource(
    target: MessageReference,
    options?: RequestOptions
): ResultAsync<
    CrosspostSource,
    ConfigurationError | MessageOperationFailure | CancelledError
>fetchCrosspostSource(
  target: MessageReference,
  options?: RequestOptions
): ResultAsync<
  CrosspostSource,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

This is not a complete Guild and never populates community or message caches. No original-message fetch, gateway connection or subscription is required. The auditReason option is not supported

Parameters

options optional
RequestOptions

fetchHasReaction#

Check whether one user currently has a given reaction on a message, with one request and no cache

The answer can change right after the request. A deleted or unavailable message fails instead of answering false. This call shares the channel reaction rate limit and the client's default deadline (rest.defaultTimeoutMs, 30,000 ms unless configured), which timeoutMs overrides. The namespace's bounded read retries apply within the original deadline

fetchHasReaction(
    message: MessageReference,
    emoji: ReactionEmojiInput,
    userId: string,
    options?: RequestOptions
): ResultAsync<
    boolean,
    ConfigurationError | MessageOperationFailure | CancelledError
>fetchHasReaction(
  message: MessageReference,
  emoji: ReactionEmojiInput,
  userId: string,
  options?: RequestOptions
): ResultAsync<
  boolean,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Invalid input, malformed pages, HTTP failures and timeout fail with MessageOperationError for fetchHasReaction. HTTP 404 is notFound. No gateway connection is needed, and cancellation waits for request cleanup

Parameters

userId
string
options optional
RequestOptions
export const hasReactionExample = (client, message, userId) => client.messages.fetchHasReaction(message, "✅", userId)
import type { Client, MessageReference } from "@neontechspace/fluxerly"
export const hasReactionExample = (client: Client, message: MessageReference, userId: string) =>
    client.messages.fetchHasReaction(message, "✅", userId)

fetchHistory#

Fetch one page of channel messages from Fluxer, newest first

Pass a decimal channel ID. With no query, this reads the latest 50 messages. The limit option accepts 1–100. Choose at most one before, after or around message-ID cursor. Use the oldest returned ID as before to request an older page

fetchHistory(
    channelId: string,
    query?: MessageHistoryQuery,
    options?: RequestOptions
): ResultAsync<
    readonly M[],
    ConfigurationError | MessageOperationFailure | CancelledError
>fetchHistory(
  channelId: string,
  query?: MessageHistoryQuery,
  options?: RequestOptions
): ResultAsync<
  readonly M[],
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

The entire page is validated before returning a frozen array of frozen snapshots. No gateway connection, cache read, automatic traversal or prefetch is required. An empty or short page describes currently accessible results, not necessarily complete history. Pages are separate observations, not a consistent point-in-time snapshot. An enabled cache receives eligible messages oldest first, so tight limits keep the newest

Invalid input, malformed pages or HTTP failures fail with MessageOperationError for fetchHistory, and HTTP 404 remains notFound. The namespace's shared limits, default deadline and bounded read retries apply. Cancellation affects only this request and waits for cleanup, and client closure fails with ClientClosedError

Parameters

channelId
string
query optional
MessageHistoryQuery
options optional
RequestOptions
Returns
ResultAsync<
    readonly M[],
    ConfigurationError | MessageOperationFailure | CancelledError
>ResultAsync<
  readonly M[],
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

fetchPins#

Fetch one frozen page of pinned messages in descending pin-time order

Use a decimal channel ID. The limit option defaults to 50 and accepts 1–50. The before option is an ISO timestamp and defaults to the server's current time

fetchPins(
    channelId: string,
    query?: MessagePinsQuery,
    options?: RequestOptions
): ResultAsync<
    MessagePinsPage<M>,
    ConfigurationError | MessageOperationFailure | CancelledError
>fetchPins(
  channelId: string,
  query?: MessagePinsQuery,
  options?: RequestOptions
): ResultAsync<
  MessagePinsPage<M>,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Use nextBefore for the next page and pinnedAt for each pin's time. Page ordering and the before bound use every fractional digit and normalize timezone offsets, while equal instants remain valid. Equal timestamps can repeat messages, so skip duplicate IDs and stop if the cursor does not advance. This call neither traverses further pages nor reads or populates the message cache. Visibility and history permissions can limit the page, so an empty page does not prove there are no pins. Returned messages are snapshots, not live state

The call uses the pins rate limit, the client's default deadline (rest.defaultTimeoutMs, 30,000 ms unless configured) and the namespace's bounded read retries. Invalid input or malformed responses fail with MessageOperationError operation fetchPins, not a partial page. Client closure fails with ClientClosedError, and cancellation affects this request only

Parameters

channelId
string
query optional
MessagePinsQuery
options optional
RequestOptions

fetchReactionUsers#

Fetch one page of users who currently have a selected reaction on the message

Accepts the same ReactionEmojiInput forms as addReaction. The limit option defaults to 25 and accepts 1–100. The after option is an exclusive user-ID cursor. Users are ordered by ascending ID, not reaction time. Use nextAfter for another page

fetchReactionUsers(
    message: MessageReference,
    emoji: ReactionEmojiInput,
    query?: ReactionUsersQuery,
    options?: RequestOptions
): ResultAsync<
    ReactionUsersPage,
    ConfigurationError | MessageOperationFailure | CancelledError
>fetchReactionUsers(
  message: MessageReference,
  emoji: ReactionEmojiInput,
  query?: ReactionUsersQuery,
  options?: RequestOptions
): ResultAsync<
  ReactionUsersPage,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

An empty reaction produces an empty terminal page. No automatic page traversal, user cache or message cache update is performed. Pages can change between requests, so they are not a stable voter list. This call shares the channel reaction rate limit and the client's default deadline (rest.defaultTimeoutMs, 30,000 ms unless configured), which timeoutMs overrides. The namespace's bounded read retries apply within the original deadline

Invalid input, malformed pages, HTTP failures and timeout fail with MessageOperationError for fetchReactionUsers. HTTP 404 is notFound. Fluxer decides visibility and history access. No gateway connection is needed, and cancellation waits for request cleanup

Parameters

query optional
ReactionUsersQuery
options optional
RequestOptions
export async function reactionUsersExample(client, message) {
    const result = await client.messages.fetchReactionUsers(message, "👍", { limit: 25 })
    if (result.isErr() || result.value.nextAfter === null)
        return result
    return client.messages.fetchReactionUsers(message, "👍", { after: result.value.nextAfter })
}
import type { Client, MessageReference } from "@neontechspace/fluxerly"
export async function reactionUsersExample(client: Client, message: MessageReference) {
    const result = await client.messages.fetchReactionUsers(message, "👍", { limit: 25 })
    if (result.isErr() || result.value.nextAfter === null) return result
    return client.messages.fetchReactionUsers(message, "👍", { after: result.value.nextAfter })
}

forward#

Copy an accessible source message into the destination channel and return the new message

Pass the source reference in input.source. No source fetch or cache lookup is performed, and no gateway connection is required. Optional media selections must belong to the source. Extra content, files, mentions and flags are rejected. The result's messageSnapshots are frozen copies, not live views of later source edits

forward(
    channelId: string,
    input: ForwardMessageInput,
    options?: RequestOptions
): ResultAsync<M, ConfigurationError | SendError | CancelledError>forward(
  channelId: string,
  input: ForwardMessageInput,
  options?: RequestOptions
): ResultAsync<
  M,
  | ConfigurationError | SendError
  | CancelledError
>

Fluxer checks source access and destination permissions. This uses send's shared request limits, the client's default deadline (rest.defaultTimeoutMs, 30,000 ms unless configured) and optional destination-message caching. The nonce input follows send's accepted values, generated default and reuse on confirmed rate-limit retries. Fluxer's five-minute duplicate suppression is best effort, not exactly-once delivery. Success follows HTTP, not recipient acknowledgement. A lost response or cancellation can leave the forward posted. Only confirmed rate-limit rejection retries, and no write with an unknown outcome is replayed or rolled back. Expected failures are MessageError or ClientClosedError

Parameters

channelId
string
options optional
RequestOptions
Returns
ResultAsync<M, ConfigurationError | SendError | CancelledError>ResultAsync<
  M,
  | ConfigurationError | SendError
  | CancelledError
>
export function forwardExample(client, destinationId, source) {
    return client.messages.forward(destinationId, { source })
}
import type { Client, MessageReference } from "@neontechspace/fluxerly"
export function forwardExample(client: Client, destinationId: string, source: MessageReference) {
    return client.messages.forward(destinationId, { source })
}

get#

Look up a message in this client's cache, without an HTTP request

Pass decimal id and channelId, or an existing message with those fields. The result is undefined when caching is disabled or the entry is absent, expired, evicted or in a different channel. It does not mean Fluxer has no such message, so use fetch for a remote read. A hit is a frozen snapshot that can be stale. Lookup makes it more recently used without extending its age. An invalid reference is misuse: The default API throws MessageOperationError with operation messages.get and reason input, and the native API dies with it. A closing or closed client has no cache, so the result is undefined

get(message: MessageReference): M | undefinedget(
  message: MessageReference
): M | undefined

Parameters

Returns
M | undefined

Returns the value synchronously. Unexpected failures throw SdkDefect

iterateHistory#

Read older messages newest first, without connecting the gateway

The maxItems option is required, and pageSize and maxPages use the limits and defaults in PaginationQuery. Creating the result makes no request. Each consumption copies the inputs and has independent progress. The SDK keeps one page at a time and fetches the next only when needed. Items are frozen message snapshots. The timeoutMs option applies to each page, not to the whole scan. Remote errors identify fetchHistory, and PaginationError reports invalid input, cursorStalled or pageLimit. An empty page or maxItems ends the scan, while a short page does not, and pages are not a consistent snapshot. If message caching is enabled, page reads can populate it as fetchHistory does. Client closure releases the buffer and fails the next pull. Messages already delivered to the caller are not rolled back, and caller processing is not retried

iterateHistory(
    channelId: string,
    query: HistoryIterationQuery,
    options?: RequestOptions
): AsyncIterable<
    Result<
        M,
        | PaginationError | ConfigurationError
        | MessageOperationFailure | CancelledError
    >
>iterateHistory(
  channelId: string,
  query: HistoryIterationQuery,
  options?: RequestOptions
): AsyncIterable<
  Result<
    M,
    | PaginationError
    | ConfigurationError
    | MessageOperationFailure
    | CancelledError
  >
>

Parameters

channelId
string
options optional
RequestOptions

Consume the iterable with a for await loop, which starts the first request. An expected failure yields one Err and ends iteration. Breaking the loop releases the buffered page. Abort interrupts pending request work and waits for cleanup. Completion and early exit leave no listener registered. Unexpected SDK failures, or an operation failure combined with a cleanup failure, reject with SdkDefect

export async function paginationHistoryExample(client, channelId) {
    for await (const result of client.messages.iterateHistory(channelId, { maxItems: 500 })) {
        if (result.isErr())
            return result
        if (result.value.content === "stop")
            break
    }
}
import type { Client } from "@neontechspace/fluxerly"
export async function paginationHistoryExample(client: Client, channelId: string) {
    for await (const result of client.messages.iterateHistory(channelId, { maxItems: 500 })) {
        if (result.isErr()) return result
        if (result.value.content === "stop") break
    }
}

iteratePins#

Read pinned messages newest pin first, without adding message cache entries

Pass maxItems to bound the scan, and PinIterationQuery defines the remaining limits. Like iterateHistory, this is lazy, with timeoutMs applying to each fetchPins page, and remote errors identify that operation. At most maxItems IDs are kept to skip duplicates. Valid items on a stalled page can be delivered before cursorStalled on the next pull. The scan stops at maxItems or hasMore false. Cursor progress uses the full fractional timestamp precision and compares equivalent timezone offsets as the same instant. Pins with equal timestamps can prevent a complete scan even without concurrent edits

iteratePins(
    channelId: string,
    query: PinIterationQuery,
    options?: RequestOptions
): AsyncIterable<
    Result<
        MessagePin<M>,
        | PaginationError | ConfigurationError
        | MessageOperationFailure | CancelledError
    >
>iteratePins(
  channelId: string,
  query: PinIterationQuery,
  options?: RequestOptions
): AsyncIterable<
  Result<
    MessagePin<M>,
    | PaginationError
    | ConfigurationError
    | MessageOperationFailure
    | CancelledError
  >
>

Parameters

channelId
string
options optional
RequestOptions

Consume the iterable with a for await loop, which starts the first request. An expected failure yields one Err and ends iteration. Breaking the loop releases the buffered page. Abort interrupts pending request work and waits for cleanup

export async function paginationPinsExample(client, channelId) {
    const ids = []
    for await (const result of client.messages.iteratePins(channelId, { maxItems: 20 })) {
        if (result.isErr())
            return result
        ids.push(result.value.message.id)
    }
    return ids
}
import type { Client } from "@neontechspace/fluxerly"
export async function paginationPinsExample(client: Client, channelId: string) {
    const ids: string[] = []
    for await (const result of client.messages.iteratePins(channelId, { maxItems: 20 })) {
        if (result.isErr()) return result
        ids.push(result.value.message.id)
    }
    return ids
}

iterateReactionUsers#

Read users who reacted with one selected emoji, in ascending user-ID order

Pass a literal Unicode emoji or custom emoji input, plus maxItems to bound the scan. Like iterateHistory, this is lazy and keeps bounded results. The timeoutMs option applies to each fetchReactionUsers page, and remote errors identify that operation. The scan ends at maxItems or hasMore false, without caching reactors or fetching members. Reactions may change during the scan. Not finding a user within the bound does not prove the user never reacted

iterateReactionUsers(
    message: MessageReference,
    emoji: ReactionEmojiInput,
    query: UserIterationQuery,
    options?: RequestOptions
): AsyncIterable<
    Result<
        ReactionUser,
        | PaginationError | ConfigurationError
        | MessageOperationFailure | CancelledError
    >
>iterateReactionUsers(
  message: MessageReference,
  emoji: ReactionEmojiInput,
  query: UserIterationQuery,
  options?: RequestOptions
): AsyncIterable<
  Result<
    ReactionUser,
    | PaginationError
    | ConfigurationError
    | MessageOperationFailure
    | CancelledError
  >
>

Parameters

options optional
RequestOptions

Consume the iterable with a for await loop, which starts the first request. An expected failure yields one Err and ends iteration. Breaking the loop releases the buffered page. Abort interrupts pending request work and waits for cleanup

export async function paginationReactionExample(client, message, userId) {
    for await (const result of client.messages.iterateReactionUsers(message, "👍", { maxItems: 500 })) {
        if (result.isErr())
            return result
        if (result.value.id === userId)
            return result
    }
    return undefined
}
import type { Client, MessageReference } from "@neontechspace/fluxerly"
export async function paginationReactionExample(client: Client, message: MessageReference, userId: string) {
    for await (const result of client.messages.iterateReactionUsers(message, "👍", { maxItems: 500 })) {
        if (result.isErr()) return result
        if (result.value.id === userId) return result
    }
    return undefined
}

iterateSearch#

Read indexed search hits from the supplied community or channel context, following numbered pages without polling, prefetching or cache population

The maxItems option is required, pageSize accepts 1–25, and maxPages defaults to the pages maxItems needs at pageSize plus 100, never above 400. Each consumption copies the filters, including recognized inherited and nonenumerable fields and their arrays, and holds one page at a time. Request capacity stays at the smaller of pageSize and maxItems throughout the scan, and at most maxItems hits are delivered. Reaching maxPages or Fluxer's 400-page ceiling with more matches fails with PaginationError pageLimit. An unexpected echoed page number or capacity fails with cursorStalled, and index changes can still skip or repeat observations. An indexing response fails with PaginationError indexing rather than polling or claiming an empty result. Search hits do not trigger full-message fetches. Delivered hits remain with the caller after a later failure. The timeoutMs option applies separately to each page request, not to the whole traversal

iterateSearch(
    context: MessageSearchContext,
    filters: Omit<MessageSearchQuery, "limit" | "page">,
    limits: MessageSearchIterationLimits,
    options?: RequestOptions
): AsyncIterable<
    Result<
        M,
        | PaginationError | ConfigurationError
        | MessageOperationFailure | CancelledError
    >
>iterateSearch(
  context: MessageSearchContext,
  filters: Omit<
    MessageSearchQuery,
    "limit" | "page"
  >,
  limits:
    MessageSearchIterationLimits,
  options?: RequestOptions
): AsyncIterable<
  Result<
    M,
    | PaginationError
    | ConfigurationError
    | MessageOperationFailure
    | CancelledError
  >
>

Parameters

filters
Omit<MessageSearchQuery, "limit" | "page">Omit<
  MessageSearchQuery, "limit" | "page"
>
options optional
RequestOptions

Consume the iterable with a for await loop, which starts the first request. An expected failure yields one Err and ends iteration. Breaking the loop releases the buffered page. Abort interrupts pending request work and waits for cleanup

export async function messageSearchTraversalExample(client, guildId) {
    for await (const hit of client.messages.iterateSearch({ guildId }, { content: "todo" }, { maxItems: 100 })) {
        if (hit.isErr())
            return hit
    }
}
import type { Client } from "@neontechspace/fluxerly"
export async function messageSearchTraversalExample(client: Client, guildId: string) {
    for await (const hit of client.messages.iterateSearch({ guildId }, { content: "todo" }, { maxItems: 100 })) {
        if (hit.isErr()) return hit
    }
}

keepTyping#

Keep the bot's typing indicator active while a task runs, returning the task's value

The first typing request must succeed before the task starts, and an initial failure prevents the task from running. Refreshes run no sooner than every 8,000 ms until the task settles, below Fluxer's documented limit of 20 requests per 10 seconds per channel. A later typing or client-close failure stops refreshes without interrupting the task, and never changes the result, which is the task's own. Only a typing failure other than client closure is logged, once at Warn with code rest.typingRefreshStopped. Client shutdown stops and waits for the helper's refresh work, not arbitrary application work. No detached refresh loop, cache entry, presence change or gateway state change is created

keepTyping<A>(
    channelId: string,
    task: (signal: AbortSignal) => PromiseLike<A>,
    options?: RequestOptions
): ResultAsync<
    A,
    ConfigurationError | MessageOperationFailure | CancelledError
>keepTyping<A>(
  channelId: string,
  task: (signal: AbortSignal)
    => PromiseLike<A>,
  options?: RequestOptions
): ResultAsync<
  A,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Parameters

channelId
string
task
(signal: AbortSignal) => PromiseLike<A>(signal: AbortSignal)
  => PromiseLike<A>
options optional
RequestOptions

The task is an async function that receives a signal aborted on caller cancellation or helper cleanup. The task must cooperate with that signal, because a promise that ignores it can delay cancellation. A thrown or rejected task rejects with SdkDefect rather than returning an expected Err. A defect in the refresh work also rejects with SdkDefect, which retains safe details for both when the task rejected too

export async function typingExample(client, channelId) {
    return await client.messages.keepTyping(channelId, async (signal) => {
        if (signal.aborted)
            throw new Error("work cancelled")
        return "prepared"
    })
}
import type { Client } from "@neontechspace/fluxerly"
export async function typingExample(client: Client, channelId: string) {
    return await client.messages.keepTyping(channelId, async signal => {
        if (signal.aborted) throw new Error("work cancelled")
        return "prepared"
    })
}

paginate#

Show several pages in one message that people flip with ◀ and ▶ reactions, because Fluxer has no buttons

Sends the first page, adds both arrows as the bot, then shows the previous or next page on each click, wrapping around at the ends. A single page is only sent, with reason singlePage and without arrows or listening. Pages and options are copied when the operation starts, but embed objects stay shared with the caller. Invalid page-list shapes and options fail with ConfigurationError before the first send. Page bodies are validated when sent or shown, so an invalid later page can fail after the first message and arrows have been sent

paginate(
    channelId: string,
    pages: readonly PageInput[],
    options: ChannelPaginateOptions
): ResultAsync<PaginateResult<M>, CancelledError | PaginateFailure>paginate(
  channelId: string,
  pages: readonly PageInput[],
  options: ChannelPaginateOptions
): ResultAsync<
  PaginateResult<M>,
  CancelledError | PaginateFailure
>

The users option is required here, because no message identifies an asker. Pass account IDs, or a check such as () => true to let anyone flip. A command context's paginate defaults to the command's author instead. Adding or removing an arrow counts as one click, so only Add Reactions and Read Message History are needed. With removeClicks, only additions count and the bot removes the clicker's arrow after each change, which needs Manage Messages. Clicks are handled one at a time through messages.collectReactions machinery, with its connection requirement, pending-event budget and gateway-loss behavior

Listening stops after idleMs without a click, 60,000 ms by default, and at most timeoutMs after registration, 300,000 ms by default. Cancellation also stops it, as described in the remarks. However it stops, the bot then removes only its own arrows, and the current page stays shown. Each send, edit and reaction request uses the client's default deadline, rate limits and retry rules, and is never replayed after an unknown outcome

A failed page change, arrow or click removal stops listening and returns that failure after the arrows are removed. A users check that throws or returns a non-boolean fails with CollectorError reason filter and is reported to the client-level onError. A failure to remove the arrows is returned after an otherwise normal end, while an earlier failure or cancellation wins over it

Parameters

channelId
string
pages
readonly PageInput[]

Aborting options.signal stops listening and returns CancelledError once the arrows are removed. The ResultAsync settles only after that cleanup. Unexpected SDK failures reject with SdkDefect

export function pagesExample(client, channelId, userId) {
    return client.messages.paginate(channelId, ["First page", "Second page"], { users: [userId], idleMs: 30_000 })
}
import type { Client } from "@neontechspace/fluxerly"
export function pagesExample(client: Client, channelId: string, userId: string) {
    return client.messages.paginate(channelId, ["First page", "Second page"], { users: [userId], idleMs: 30_000 })
}

pin#

Pin a message using its decimal id and channelId

Success follows HTTP 204, not gateway notification. No gateway connection is required

pin(
    message: MessageReference,
    options?: AuditedRequestOptions
): ResultAsync<
    void,
    ConfigurationError | MessageOperationFailure | CancelledError
>pin(
  message: MessageReference,
  options?: AuditedRequestOptions
): ResultAsync<
  void,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

The auditReason option supplies an optional community audit-log explanation. Fluxer checks channel access and PIN_MESSAGES for community pins. A new pin creates a system message and notifications. An already-pinned message stays unchanged. The pin, unpin and fetchPins methods share the per-channel pins rate limit and the client's request limits. The default deadline is the client's rest.defaultTimeoutMs, 30,000 ms unless configured, and only confirmed HTTP 429 rejections are retried

Expected failures use MessageOperationError operation pin, or ClientClosedError after shutdown. Invalid local input fails with outcome notDispatched. Cancellation or a lost response after sending the request can leave the pin applied. Successful writes and writes with unknown outcomes remove the cached target without guessing its new pinned status. The SDK does not fetch to confirm, create events itself, unpin automatically or roll back the change. The example's steps are separate operations, not a transaction

Parameters

options optional
AuditedRequestOptions
export async function pinsExample(client, message) {
    const pinned = await client.messages.pin(message)
    if (pinned.isErr())
        throw pinned.error
    const page = await client.messages.fetchPins(message.channelId, { limit: 25 })
    if (page.isErr())
        throw page.error
    const unpinned = await client.messages.unpin(message)
    if (unpinned.isErr())
        throw unpinned.error
    return page.value
}
import type { Client, MessageReference } from "@neontechspace/fluxerly"

export async function pinsExample(client: Client, message: MessageReference) {
    const pinned = await client.messages.pin(message)
    if (pinned.isErr()) throw pinned.error
    const page = await client.messages.fetchPins(message.channelId, { limit: 25 })
    if (page.isErr()) throw page.error
    const unpinned = await client.messages.unpin(message)
    if (unpinned.isErr()) throw unpinned.error
    return page.value
}

previewCleanup#

Preview a bounded message-deletion selection without deleting anything

Pass authorId, a synchronous filter, or both. When both are supplied, a message must match both. The maxScanned and maxSelected values are required integers from 1 through 10,000. History is scanned newest first until an empty page or either bound, without prefetch, and a short page does not end the scan. History reads can populate an enabled message cache

previewCleanup(
    channelId: string,
    selection: MessageCleanupSelection<M>,
    options?: RequestOptions
): ResultAsync<
    MessageCleanupPlan<M>,
    ConfigurationError | MessageCleanupError | CancelledError
>previewCleanup(
  channelId: string,
  selection:
    MessageCleanupSelection<M>,
  options?: RequestOptions
): ResultAsync<
  MessageCleanupPlan<M>,
  | ConfigurationError
  | MessageCleanupError
  | CancelledError
>

The result is an in-memory plan with frozen selected messages, usable once by this client only. It cannot be reconstructed from JSON or given to another client. A thrown filter, non-boolean return or promise-like return fails with MessageCleanupError before deletion. A blocking synchronous filter cannot be interrupted. One default deadline, rest.defaultTimeoutMs (30,000 ms unless configured), covers the history scan. Cancellation submits no deletion. No gateway connection or cache reread is needed

Parameters

channelId
string
options optional
RequestOptions

publish#

Publish an ordinary source message from an announcement channel and return its frozen updated snapshot

Fluxer requires announcements and message sending enabled, SendMessages, and ManageMessages for another author's message. Replies, system messages, already published messages, published copies and forwarded messages cannot be published. Fluxer enforces moderation and a shared per-channel publication budget of 10 messages per hour

publish(
    target: MessageReference,
    options?: RequestOptions
): ResultAsync<
    M,
    ConfigurationError | MessageOperationFailure | CancelledError
>publish(
  target: MessageReference,
  options?: RequestOptions
): ResultAsync<
  M,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Success means publication was accepted and follower delivery was queued, not that every target received a copy. Fluxer sets Crossposted, visible in flags when this client's messageFields selection retains flags. A successful response updates the enabled source-message cache without inserting guessed follower copies. An unknown outcome evicts the cached source. A lost or malformed response is never resent automatically. Cancellation after dispatch cannot establish rollback. No gateway event is awaited and auditReason is not supported

Parameters

options optional
RequestOptions

removeReaction#

Remove only the bot's own reaction for the selected emoji

Other users' reactions stay unchanged. Success follows HTTP 204, even if the bot had not reacted, so it does not prove the reaction existed. The addReaction method's emoji inputs, request limits, deadline, retry, failure and cancellation rules apply. Neither this operation nor gateway reaction events change the message cache

removeReaction(
    message: MessageReference,
    emoji: ReactionEmojiInput,
    options?: RequestOptions
): ResultAsync<
    void,
    ConfigurationError | MessageOperationFailure | CancelledError
>removeReaction(
  message: MessageReference,
  emoji: ReactionEmojiInput,
  options?: RequestOptions
): ResultAsync<
  void,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Parameters

options optional
RequestOptions

removeUserReaction#

Remove one user's reaction for one emoji, leaving other users and emoji groups unchanged

The userId input is required as a decimal string, and the bot's own ID removes its reaction. Accepts the same ReactionEmojiInput forms as addReaction

removeUserReaction(
    message: MessageReference,
    emoji: ReactionEmojiInput,
    userId: string,
    options?: RequestOptions
): ResultAsync<
    void,
    ConfigurationError | MessageOperationFailure | CancelledError
>removeUserReaction(
  message: MessageReference,
  emoji: ReactionEmojiInput,
  userId: string,
  options?: RequestOptions
): ResultAsync<
  void,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Fluxer checks visibility and history access. For another user, the bot must have authored the message or have MANAGE_MESSAGES in its community. Success follows HTTP 204, whether the reaction was present or already absent, without waiting for or synthesizing events. The call uses addReaction's request limits, deadline, confirmed rate-limit retries and cancellation rules. Expected failures identify removeUserReaction. No reaction cache is changed or retained

After dispatch, cancellation or a lost response can leave the reaction removed, and an unknown outcome is not replayed. The bot cannot restore another user's reaction as that user, and no restoration is attempted

Parameters

userId
string
options optional
RequestOptions
export async function reactionModerationExample(client, message, userId) {
    const removed = await client.messages.removeUserReaction(message, "👍", userId)
    if (removed.isErr())
        return removed
    const cleared = await client.messages.clearReaction(message, "👍")
    if (cleared.isErr())
        return cleared
    return client.messages.clearReactions(message)
}
import type { Client, MessageReference } from "@neontechspace/fluxerly"
export async function reactionModerationExample(client: Client, message: MessageReference, userId: string) {
    const removed = await client.messages.removeUserReaction(message, "👍", userId)
    if (removed.isErr()) return removed
    const cleared = await client.messages.clearReaction(message, "👍")
    if (cleared.isErr()) return cleared
    return client.messages.clearReactions(message)
}

reply#

Send a reply that references an existing message and return the new reply

A plain string replies with only that text, as shorthand for { content }. Pass the target's id and channelId, plus the reply content or files. A missing target fails instead of silently sending an unreferenced message. An invalid target, or input with its own messageReference, fails before the client-closure check. The body is then validated as send validates it. Author notifications are off by default. The send method's mention defaults, attachment source handling, size limits, deadline, nonce and retry rules apply, and inline multipart 429 responses do not replay file or stream sources. Eligible replies can enter the message cache. A lost response can leave the reply posted, and the SDK does not replay a send with an unknown outcome

reply(
    message: MessageReference,
    input: string | ReplyInput,
    options?: RequestOptions
): ResultAsync<M, ConfigurationError | SendError | CancelledError>reply(
  message: MessageReference,
  input: string | ReplyInput,
  options?: RequestOptions
): ResultAsync<
  M,
  | ConfigurationError | SendError
  | CancelledError
>

Parameters

input
string | ReplyInput
options optional
RequestOptions
Returns
ResultAsync<M, ConfigurationError | SendError | CancelledError>ResultAsync<
  M,
  | ConfigurationError | SendError
  | CancelledError
>

Search messages in one explicit community or channel and return one page from Fluxer's search index

The SDK always sends the current search scope (scope: "current"). It neither connects the gateway nor reads or fills a cache

search(
    context: MessageSearchContext,
    query?: MessageSearchQuery,
    options?: RequestOptions
): ResultAsync<
    MessageSearchPage<M>,
    ConfigurationError | MessageOperationFailure | CancelledError
>search(
  context: MessageSearchContext,
  query?: MessageSearchQuery,
  options?: RequestOptions
): ResultAsync<
  MessageSearchPage<M>,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

The result is a frozen page or an indexing state. The indexing result means Fluxer accepted the search but is not ready, and the SDK never polls. The caller decides whether and when to search again. Use page numbers from 1 through 400 for later requests, keeping limit unchanged. Fluxer does not honor returned cursors, so the SDK exposes no cursor continuation

Recognized query fields, including inherited and nonenumerable fields, are read and their arrays copied when execution starts. The results and their channel context can change and are not a stable snapshot. Invalid input, POST failure or malformed success fails with MessageOperationError operation search. Search does not use the transient read retries described for this namespace, but confirmed rate-limit handling still applies within the deadline. Cancellation releases only this request

Parameters

query optional
MessageSearchQuery
options optional
RequestOptions
export async function messageSearchPageExample(client, channelId) {
    const page = await client.messages.search({ channelId }, { content: "release notes" })
    return page.isOk() && !page.value.indexing ? page.value.messages : page
}
import type { Client } from "@neontechspace/fluxerly"
export async function messageSearchPageExample(client: Client, channelId: string) {
    const page = await client.messages.search({ channelId }, { content: "release notes" })
    return page.isOk() && !page.value.indexing ? page.value.messages : page
}

send#

Send text, embeds, files or stickers to a channel and return the created message

A plain string sends only that text, as shorthand for { content }, and embeds accept plain objects or EmbedBuilder instances. Success follows the decoded HTTP response, not gateway notification or recipient acknowledgement, and no gateway connection is needed. Mentions are disabled by default, and allowedMentions opts in. Embed image and thumbnail URLs can use attachment://filename for a matching new image or video upload. The flags input accepts only MessageFlags.SuppressEmbeds and MessageFlags.SuppressNotifications. Server-managed flags, including the crosspost flags, fail locally before dispatch. Suppressing previews is different from omitting embeds

send(
    channelId: string,
    input: string | MessageInput,
    options?: RequestOptions
): ResultAsync<M, ConfigurationError | SendError | CancelledError>send(
  channelId: string,
  input: string | MessageInput,
  options?: RequestOptions
): ResultAsync<
  M,
  | ConfigurationError | SendError
  | CancelledError
>

Each attachment uses exactly one source: Bytes in data, a sized Blob or File source, or a finite stream with its exact byte count. Data bytes are copied when execution starts, before any wait. File and stream bytes are read when uploading starts, after upload planning, without copying or spooling. Keep a file source stable while it is read. A finite stream is consumed at most once and must match its declared size. A path string or URL alone is not accepted, and the SDK owns only the readers it acquires

All sources have a 50 MiB per-file maximum and share the client uploads.maxBytes reservation budget. A full upload or request queue fails with busy before copying or reading. Fluxer can impose lower limits. Uploads use presigned planning or an inline multipart fallback. Upload-plan and completion responses have their own 1 MiB limit, and neither response limit caps total memory use. Cleanup releases copied bytes and cancels and releases acquired readers on failure. Failed uploads can leave temporary server data, without a guarantee of physical erasure. Eligible created messages can enter an enabled cache, independently of send completion

The default total deadline, rest.defaultTimeoutMs (30,000 ms unless configured), includes waiting for request capacity and rate limits. The request uses the shared limits and failure rules of this namespace. By default one client admits four REST and upload requests per local shard, up to 64, plus four independent attachment downloads, and both pools share at most 256 pending requests or 4 MiB of pending JSON. The rest client option changes these limits. Only confirmed rate-limit rejections can retry automatically, and sends with unknown outcomes never retry. With inline multipart uploads, a confirmed HTTP 429 can replay copied data bytes only, while file and stream inputs fail with rateLimit instead of being read again

The nonce input can be a 1–32 character string or a nonnegative safe integer. If omitted, the SDK creates one nonce per send execution, and the same nonce is reused for confirmed rate-limit retries. Fluxer tries to suppress duplicate sends for five minutes after saving a message. This does not guarantee that a repeated or concurrent send posts only one message. A lost response or cancellation after dispatch can leave a message posted, and the SDK neither retries nor rolls it back. Check MessageError.outcome before sending again

Parameters

channelId
string
input
string | MessageInput
options optional
RequestOptions
Returns
ResultAsync<M, ConfigurationError | SendError | CancelledError>ResultAsync<
  M,
  | ConfigurationError | SendError
  | CancelledError
>

typing#

Show this bot's temporary typing indicator in a channel

Pass a decimal channel ID. Success follows HTTP 204, without waiting for another client to see it. No gateway connection, cache entry, local typing state or presence change is made. Fluxer decides delivery and when the indicator expires. This uses the client's request limits, a dedicated per-channel typing rate limit and the client's default deadline (rest.defaultTimeoutMs, 30,000 ms unless configured). Only confirmed rate-limit rejection retries. A lost response, timeout or cancellation can leave the indicator shown. Input, capacity and HTTP failures use MessageOperationError operation typing, and client closure fails with ClientClosedError. Cancellation waits for request cleanup

typing(channelId: string, options?: RequestOptions): ResultAsync<
    void,
    ConfigurationError | MessageOperationFailure | CancelledError
>typing(
  channelId: string,
  options?: RequestOptions
): ResultAsync<
  void,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Parameters

channelId
string
options optional
RequestOptions

unpin#

Remove a pin without deleting the message or its pin-created system message

Supply a decimal message id and channelId. Fluxer checks the same permissions as pin. Success follows HTTP 204, including when the message is already unpinned. The last-pin timestamp is not reset. The auditReason option supplies an optional community audit-log explanation. The pin method's request limits, deadline, rate-limit retries, cancellation and cache removal also apply. Expected failures identify operation unpin, and client closure fails with ClientClosedError. No gateway connection, confirmation fetch, event synthesis or automatic rollback is performed

unpin(
    message: MessageReference,
    options?: AuditedRequestOptions
): ResultAsync<
    void,
    ConfigurationError | MessageOperationFailure | CancelledError
>unpin(
  message: MessageReference,
  options?: AuditedRequestOptions
): ResultAsync<
  void,
  | ConfigurationError
  | MessageOperationFailure
  | CancelledError
>

Parameters

options optional
AuditedRequestOptions

PaginateOptions#

Choose who may turn reaction pages and how long they listen

The bot adds ◀ and ▶ reactions, and each click on one shows the previous or next page, wrapping around at the ends. By default, adding or removing an arrow counts as one click, so the bot needs only Add Reactions and Read Message History. Registration needs a connected gateway, like messages.collectReactions

interface PaginateOptions extends OperationOptionsinterface PaginateOptions
  extends OperationOptions

Aborting the signal stops listening, removes the bot's arrows and returns CancelledError, leaving the current page shown

idleMs optional#

Stop after this many milliseconds without an accepted click

Integer 1 through 2,147,483,647, default 60,000

number
removeClicks optional#

Count only added arrows, and remove the clicker's arrow after each turn so the next click is another addition

The bot then needs Manage Messages. Default false, where adding and removing an arrow both turn the page

boolean
timeoutMs optional#

Stop after this many milliseconds from registration, regardless of clicks

Integer 1 through 2,147,483,647, default 300,000

number
users optional#

Who may turn pages

Required by messages.paginate, while a command context defaults to the command's author

PageTurners

Inherited from OperationOptions: signal

PaginateResult#

How reaction pages ended after listening normally

Failures, cancellation and interruption are returned in the failure channel instead

interface PaginateResult<M extends MessageCore = Message>interface PaginateResult<
  M extends MessageCore = Message
>
message#

Latest snapshot of the page message, as sent or as returned by the last page change

M
page#

Position of the page shown at the end, with 0 identifying the first page

number
reason#

The reason idle means idleMs passed without a click, timeout means timeoutMs passed and singlePage means only one page was sent, without arrows or listening

"idle" | "timeout" | "singlePage"

PinIterationQuery#

Limits and starting point for messages.iteratePins, reading newest pin times first

Each message ID is delivered at most once per consumption. Its first observed pin wins, even if it is later repinned. Timestamp ties or concurrent changes can prevent complete enumeration. If the next timestamp does not become older, traversal fails with cursorStalled after delivering newly observed IDs from that page

interface PinIterationQuery extends PaginationQueryinterface PinIterationQuery
  extends PaginationQuery
before optional#

Start with older pin times than this ISO 8601 timestamp with a timezone

Omit to use Fluxer's current-time default

string

Inherited from PaginationQuery: maxItems, maxPages, pageSize

ReactionEmoji#

Emoji identity supplied in a reaction event

This frozen value records the name and any custom ID or animation flag supplied by Fluxer

interface ReactionEmoji
animated optional#

Whether a custom emoji is animated, when supplied

Absence means unknown and Unicode emoji omit this field

boolean
id optional#

Custom emoji ID as a decimal string

Absent for Unicode emoji

string
name#

Literal Unicode emoji text, or the custom emoji name at event time

string

ReactionTarget#

Message address carried by a reaction event, with optional community context

The id field is the message ID. Gateway reconnection can miss events. An event does not show current counts or everyone who reacted. Additional provider data, such as session identifiers, is not retained. The acting member of an addition or removal is available only as MessageReaction.member

interface ReactionTarget extends MessageReferenceinterface ReactionTarget
  extends MessageReference
guildId optional#

Owning community ID when supplied

Absence alone does not establish private-channel scope

string

Inherited from MessageReference: channelId, id

ReactionUser#

Account identity returned in a reaction-user page

This frozen snapshot has no account methods, community membership details or automatically refreshed data

interface ReactionUser
id#

Account ID as a decimal string, not a JavaScript number

string
isBot#

True if Fluxer marked the account as a bot, otherwise false

boolean
username#

Username at the time Fluxer returned this page

string

ReactionUsersPage#

One frozen page of users who reacted with the requested emoji

Users are ordered by ascending ID. Concurrent reaction changes can affect later pages. Several pages do not represent one fixed list of people who reacted

interface ReactionUsersPage
hasMore#

True when Fluxer reported more users after this page

boolean
items#

Users ordered by ascending decimal ID, with no more than the requested limit

readonly ReactionUser[]
nextAfter#

Cursor to pass as after for the next request

The last returned user ID when hasMore is true, otherwise null

string | null

ReactionUsersQuery#

Choose one page of users who reacted with a particular emoji

Pass to messages.fetchReactionUsers. Use iterateReactionUsers to traverse bounded multiple pages. Fields are captured once. Unknown properties and invalid limits or IDs are rejected before the request

interface ReactionUsersQuery
after optional#

Return user IDs greater than this decimal ID, excluding the cursor user

Omit to start at the first page

string
limit optional#

Maximum users requested in this page, an integer from 1 through 100, default 25

number

RefreshedAttachmentUrl#

One result from an explicit attachment URL refresh

Fluxer returns these frozen entries in the same order as the requested URLs

interface RefreshedAttachmentUrl
original#

Requested string exactly as supplied to attachments.refreshUrls

string
refreshed#

Newly signed URL, or the original string when it is not an attachment URL of the selected instance

string

Type Aliases#

AttachmentInput#

A file to send with a message, using exactly one source: Data bytes, a sized file, or a finite stream with its exact size

All forms also require a display filename. A filesystem path or URL alone is not accepted

type AttachmentInput =
    | AttachmentBytesInput | AttachmentFileInput
    | AttachmentStreamInputtype AttachmentInput =
    | AttachmentBytesInput
    | AttachmentFileInput
    | AttachmentStreamInput

Title and description limits are measured after U+000C and U+202E removal and surrounding-whitespace trimming. This normalization is validation-only, and the original metadata strings are sent unchanged

The SDK copies data bytes when the operation starts. It reads file and stream sources after upload planning. Default API calls start immediately. Effect API calls prepare separately each time they run

Files upload before the SDK creates or edits the message. Fluxer may provide presigned upload URLs, or require a direct multipart upload when preuploads are disabled. Byte PUTs to presigned URLs carry no bot credential. Planning, completion and message requests use the client's API authentication

Failed operations may leave temporary remote files, with no rollback or crash recovery

One deadline covers endpoint discovery, planning, PUTs, completion and the message request. Failed PUTs are not retried automatically. After a confirmed inline-message HTTP 429, the SDK retries only copied byte inputs. File and stream sources report rateLimit instead of being read again

export const attachmentExample = {
    data: new Uint8Array([72, 105]),
    filename: "greeting.txt",
    contentType: "text/plain",
    title: "Greeting",
    description: "A short greeting",
    spoiler: false,
}
import type { AttachmentInput } from "@neontechspace/fluxerly"
export const attachmentExample: AttachmentInput = {
    data: new Uint8Array([72, 105]),
    filename: "greeting.txt",
    contentType: "text/plain",
    title: "Greeting",
    description: "A short greeting",
    spoiler: false,
}
// Pass a Blob/File, such as the result of Node's fs.openAsBlob, and a finite byte stream
export function sizedAttachmentExamples(file, stream, size) {
    return [
        { file, filename: "report.csv", contentType: "text/csv" },
        { stream, size, filename: "generated.bin" },
    ]
}
import type { AttachmentFileSource, AttachmentInput, AttachmentStreamSource } from "@neontechspace/fluxerly"
// Pass a Blob/File, such as the result of Node's fs.openAsBlob, and a finite byte stream
export function sizedAttachmentExamples(file: AttachmentFileSource, stream: AttachmentStreamSource, size: number): readonly AttachmentInput[] {
    return [
        { file, filename: "report.csv", contentType: "text/csv" },
        { stream, size, filename: "generated.bin" },
    ]
}

AttachmentStreamReadResult#

The result of reading an attachment stream: A byte chunk, or done true when the stream ends

This type accepts Node's native ReadableStream without requiring browser types. When done is false or omitted, value must be a Uint8Array. When done is true, the SDK stops reading and value may be omitted

type AttachmentStreamReadResult =
    | { readonly done?: false; readonly value: Uint8Array }
    | {
          readonly done: true
          readonly value: Uint8Array | undefined
      }
    | { readonly done: true; readonly value?: Uint8Array }type AttachmentStreamReadResult =
    | {
        readonly done?: false
        readonly value: Uint8Array
      }
    | {
        readonly done: true
        readonly value:
          | Uint8Array | undefined
      }
    | {
        readonly done: true
        readonly value?: Uint8Array
      }

EditMessageInput#

Input for changing an existing message without fetching or merging its old data

Omitted body properties are left unchanged. Each supplied array replaces its corresponding collection. To keep existing files alongside new uploads, include their attachment IDs in attachments. To clear files, supply attachments: [] together with nonempty text or embeds. To clear embeds, supply embeds: [] together with nonempty text. Empty content asks Fluxer to clear text. Fluxer may regenerate link previews when text changes. A flags-only edit is accepted. An empty edit and unknown properties are rejected. Each field is read at most once, so the value validated is the value sent. Mention notifications default off for this edit, including notification of the reply author

type EditMessageInput =
    | MessageContent<AttachmentInput | AttachmentReference>
      & EditMessageOptions
    | EditMessageOptions
      & {
            readonly attachments?: never
            readonly content?: never
            readonly embeds?: never
            readonly flags: number
        }type EditMessageInput =
    | MessageContent<
          | AttachmentInput
          | AttachmentReference
        >
      & EditMessageOptions
    | EditMessageOptions
      & {
          readonly attachments?:
            never
          readonly content?: never
          readonly embeds?: never
          readonly flags: number
        }

EditMessageOptions#

Delivery settings that an edit can change alongside or instead of its body

type EditMessageOptions = { … }
allowedMentions optional#

Mentions permitted to notify during this edit, defaulting to none, including the reply author

AllowedMentions
flags optional#

Replacement writable flags containing only MessageFlags.SuppressEmbeds and MessageFlags.SuppressNotifications

Omit to preserve flags, or use 0 to clear both writable bits. Server-managed and unsupported bits fail locally before dispatch

number

MessageBody#

Content for a new message: Text, embeds, file uploads, stickers, or a combination

At least one of these must be nonempty when the operation runs, even if TypeScript accepts an empty value. Stickers can be sent by bots and webhooks, but cannot be replaced in message edits

type MessageBody =
    & (
          | MessageContent<AttachmentInput>
          | {
                readonly attachments?: readonly AttachmentInput[]
                readonly content?: string
                readonly embeds?:
                    readonly (EmbedInput | EmbedBuilder)[]
                readonly stickerIds: readonly string[]
            })
    & { readonly stickerIds?: readonly string[] }type MessageBody =
    & (
        | MessageContent<
            AttachmentInput
          >
        | {
            readonly attachments?: readonly AttachmentInput[]
            readonly content?:
              string
            readonly embeds?: readonly (
              | EmbedInput
              | EmbedBuilder)[]
            readonly stickerIds:
              readonly string[]
          })
    & {
        readonly stickerIds?:
          readonly string[]
      }
export function stickerExample(client, channelId, stickerId) {
    return client.messages.send(channelId, { stickerIds: [stickerId] })
}
import type { Client } from "@neontechspace/fluxerly"
export function stickerExample(client: Client, channelId: string, stickerId: string) {
    return client.messages.send(channelId, { stickerIds: [stickerId] })
}

MessageCleanupOutcome#

What is known about the failed stage's request

The outcome notDispatched means no request was sent, rejected means confirmed rejection, and unknown means Fluxer may have acted. An unknown outcome does not mean it is safe to repeat the request

type MessageCleanupOutcome =
    "notDispatched" | "rejected" | "unknown"type MessageCleanupOutcome =
    | "notDispatched" | "rejected"
    | "unknown"

MessageCleanupProgress#

Progress notification for a cleanup batch, not durable evidence of individual deletions

The onProgress callback runs synchronously and cleanup continues after it fails. A throw, a rejected asynchronous return or a returned or resolved Err result reaches the client-level onError as a progress FailureReport, or is logged at Error. A returned Effect is not run and is reported the same way as misuse. An application that needs the notification for reconciliation should persist it synchronously. Cancellation or interruption can leave a submitting batch uncertain without a terminal failed notification

type MessageCleanupProgress =
    | {
          readonly batch: MessageCleanupBatch
          readonly state: "submitting"
      }
    | {
          readonly batch: MessageCleanupBatch
          readonly state: "submitted"
      }
    | {
          readonly batch: MessageCleanupBatch
          readonly failure: MessageCleanupFailureMetadata
          readonly state: "failed"
      }type MessageCleanupProgress =
    | {
        readonly batch:
          MessageCleanupBatch
        readonly state:
          "submitting"
      }
    | {
        readonly batch:
          MessageCleanupBatch
        readonly state: "submitted"
      }
    | {
        readonly batch:
          MessageCleanupBatch
        readonly failure: MessageCleanupFailureMetadata
        readonly state: "failed"
      }

MessageCleanupStopReason#

Why preview stopped: An empty history page, the scan cap, or the selected-message cap

The scanLimit and selectionLimit reasons do not mean that the channel's history was exhausted

type MessageCleanupStopReason =
    "historyExhausted" | "scanLimit" | "selectionLimit"type MessageCleanupStopReason =
    | "historyExhausted"
    | "scanLimit"
    | "selectionLimit"

MessageContent#

Text, embeds and files of a message body, where at least one of content, embeds or attachments is required

A is the accepted attachment type: New uploads when sending, or uploads and references to kept files when editing

type MessageContent<A> =
    | {
          readonly attachments?: readonly A[]
          readonly content: string
          readonly embeds?: readonly (EmbedInput | EmbedBuilder)[]
      }
    | {
          readonly attachments?: readonly A[]
          readonly content?: string
          readonly embeds: readonly (EmbedInput | EmbedBuilder)[]
      }
    | {
          readonly attachments: readonly A[]
          readonly content?: string
          readonly embeds?: readonly (EmbedInput | EmbedBuilder)[]
      }type MessageContent<A> =
    | {
        readonly attachments?:
          readonly A[]
        readonly content: string
        readonly embeds?: readonly (
          | EmbedInput
          | EmbedBuilder)[]
      }
    | {
        readonly attachments?:
          readonly A[]
        readonly content?: string
        readonly embeds: readonly (
          | EmbedInput
          | EmbedBuilder)[]
      }
    | {
        readonly attachments:
          readonly A[]
        readonly content?: string
        readonly embeds?: readonly (
          | EmbedInput
          | EmbedBuilder)[]
      }

MessageCore#

Message fields available even when messageFields is an empty array

IDs, text, author and type remain available for message operations, commands and collectors. Prefix commands read the type to run only for messages a person typed. The type and guildId are retained when supplied, but remain optional

type MessageCore =
    Pick<
        Message,
        | "id" | "channelId" | "content" | "author" | "type"
        | "guildId"
    >type MessageCore =
    Pick<
      Message,
      | "id" | "channelId"
      | "content" | "author"
      | "type" | "guildId"
    >

MessageField#

Name of a Message property accepted by the client's messageFields option

Selecting a MessageCore property, which is always kept, does not change the result. The member field appears only on messageCreate and messageUpdate events, as Message.member describes. The mentionedHere, channelType and nicknames fields appear only on messageCreate events, as their own comments describe

type MessageField = keyof Message

MessageFields#

Message property names to retain in this client's request results, events, cache and collectors

Omit messageFields to keep the full Message shape, or use [] to keep only MessageCore. The client copies the list at creation, so later edits to the supplied array do not change its selection. A selected property includes its complete nested value, including media metadata inside messageSnapshots. Excluded data is still validated when received, so selection does not hide malformed responses

type MessageFields = readonly MessageField[]type MessageFields =
    readonly MessageField[]

MessageFlag#

One known bit from MessageFlags, including server-managed bits observed in received messages

Only SuppressEmbeds and SuppressNotifications can be combined for send or edit input

type MessageFlag = typeof MessageFlags[keyof typeof MessageFlags]type MessageFlag =
    typeof MessageFlags[
      keyof typeof MessageFlags
    ]

MessageHistoryQuery#

Choose one page for messages.fetchHistory

Omit cursors for the latest visible messages, or choose exactly one of before, after and around. Results are returned newest first, including pages selected with after. Combined cursor modes and unknown properties are rejected locally

type MessageHistoryQuery =
    & { readonly limit?: number }
    & (
          | {
                readonly after?: never
                readonly around?: never
                readonly before?: string
            }
          | {
                readonly after?: string
                readonly around?: never
                readonly before?: never
            }
          | {
                readonly after?: never
                readonly around?: string
                readonly before?: never
            })type MessageHistoryQuery =
    & { readonly limit?: number }
    & (
        | {
            readonly after?: never
            readonly around?: never
            readonly before?:
              string
          }
        | {
            readonly after?: string
            readonly around?: never
            readonly before?: never
          }
        | {
            readonly after?: never
            readonly around?:
              string
            readonly before?: never
          })

MessageInput#

Input for messages.send, including content and optional delivery settings

Supply nonempty text, embeds, new files or sticker IDs. Unknown properties are rejected locally. Notifications are off by default. Use allowedMentions to permit specific existing mentions to notify. An attachment:// embed image or thumbnail must name one matching new image or video upload in this request. Each field, including an attachment or allowedMentions field, is read at most once, so the value validated is the value sent. Use messages.forward to copy a source message into an immutable forward

type MessageInput =
    & MessageBody
    & {
          readonly allowedMentions?: AllowedMentions
          readonly flags?: number
          readonly messageReference?: MessageReference
          readonly nonce?: MessageNonce
          readonly tts?: boolean
      }type MessageInput =
    & MessageBody
    & {
        readonly allowedMentions?:
          AllowedMentions
        readonly flags?: number
        readonly messageReference?:
          MessageReference
        readonly nonce?:
          MessageNonce
        readonly tts?: boolean
      }

MessageNonce#

Correlation identifier attached to a send, reply or forward

Use a string of 1 through 32 UTF-16 code units, or a nonnegative safe integer encoded as a decimal string. This is not the message ID returned after creation

type MessageNonce = string | number

MessageSearchAuthorType#

Author category used by Fluxer's message search: A user, bot or webhook sender

type MessageSearchAuthorType = "user" | "bot" | "webhook"type MessageSearchAuthorType =
    "user" | "bot" | "webhook"

MessageSearchContentType#

Kind of content to require or exclude in Fluxer's message search

The kind snapshot identifies copied content in a forwarded message

type MessageSearchContentType =
    | "image" | "sound" | "video" | "file" | "sticker" | "embed"
    | "link" | "poll" | "snapshot"type MessageSearchContentType =
    | "image" | "sound" | "video"
    | "file" | "sticker" | "embed"
    | "link" | "poll" | "snapshot"

MessageSearchContext#

Community or channel in which to search messages visible to the bot

Supply at least guildId or channelId, as decimal strings, or both. Search uses the bot's current access permissions, not another account's permissions or access the bot had earlier. The SDK captures the supplied IDs once when the request or traversal starts

type MessageSearchContext =
    | { readonly channelId?: string; readonly guildId: string }
    | { readonly channelId: string; readonly guildId?: string }type MessageSearchContext =
    | {
        readonly channelId?: string
        readonly guildId: string
      }
    | {
        readonly channelId: string
        readonly guildId?: string
      }

MessageSearchEmbedType#

Embed category to require or exclude in Fluxer's message search

type MessageSearchEmbedType =
    "image" | "video" | "sound" | "article"type MessageSearchEmbedType =
    | "image" | "video" | "sound"
    | "article"

PageInput#

One page shown by reaction pages, such as "Page 1" or { embeds: [embed] }

A string is the page's text. An object supplies text, embeds or both, and must not be empty. Showing a page replaces the message's text and embeds, so text from one page never stays on an embed-only page. Files, stickers and mentions are not supported on pages, and mention notifications stay off. Fluxer validates each page when it is sent or shown, so an invalid later page fails only when someone turns to it

type PageInput =
    | string
    | {
          readonly content?: string
          readonly embeds?: readonly (EmbedInput | EmbedBuilder)[]
      }type PageInput =
    | string
    | {
        readonly content?: string
        readonly embeds?: readonly (
          | EmbedInput
          | EmbedBuilder)[]
      }

PageTurners#

Who may turn pages: A list of account IDs, or a synchronous check that returns true to accept a click

The check receives the reaction addition, or the removal in the default toggle mode, after the arrow is matched. Return true for anyone, as in users: () => true. Reactions by the bot itself are never clicks. A throw or a non-boolean return ends the pages with CollectorError reason filter, and is reported to the client-level onError with kind filter, or logged at Error

type PageTurners =
    readonly string[] | ((reaction: MessageReaction) => boolean)type PageTurners =
    | readonly string[]
    | ((reaction: MessageReaction)
        => boolean)

ReactionEmojiInput#

Emoji accepted by reaction operations and reaction collector selection

Pass literal Unicode such as "👍", custom markup such as "<:party:123>" or "<a:party:123>", a { name, id, animated? } value, or a GuildEmoji returned by client.emojis. Values returned by format.parseCustomEmoji, emojis.fetchMetadata and reaction events can be reused directly

type ReactionEmojiInput = string | ReactionEmoji | GuildEmojitype ReactionEmojiInput =
    | string | ReactionEmoji
    | GuildEmoji

Custom names use 1 through 32 ASCII letters, digits, underscores or hyphens. IDs are decimal strings. Markup must occupy the whole string. Shortcodes such as :wave: and URL-encoded text are rejected. Custom animation flags are optional and do not change the request identity or collector match

Unicode input is limited to 128 UTF-16 code units and rejects spaces, control characters and reserved markup characters. Fluxer checks that the emoji is supported and that the bot may use it. The SDK does not fetch the emoji or decide whether the bot has permission to use it

ReferencedMessage#

One resolved reply supplied inline with a message

This is a frozen Message snapshot without another resolved reply or member, keeping nesting finite and avoiding hidden fetches

type ReferencedMessage =
    Omit<
        Message,
        | "referencedMessage" | "member" | "mentionedHere"
        | "channelType" | "nicknames"
    >type ReferencedMessage =
    Omit<
      Message,
      | "referencedMessage"
      | "member" | "mentionedHere"
      | "channelType" | "nicknames"
    >

ReplyInput#

Content and delivery settings for messages.reply

The target argument supplies the reply reference, so do not add messageReference here

type ReplyInput =
    & MessageBody
    & Pick<
          MessageInput,
          "allowedMentions" | "flags" | "nonce" | "tts"
      >type ReplyInput =
    & MessageBody
    & Pick<
        MessageInput,
        | "allowedMentions"
        | "flags" | "nonce" | "tts"
      >

SelectedMessage#

Type of message returned for a client's messageFields selection

With no selection, this is Message. With a fixed list, it includes MessageCore and the named properties. Properties optional in Message remain optional, even when selected. If the list is built dynamically, TypeScript cannot know which fields it contains, so selectable fields remain optional. Alternative fixed lists produce alternative message shapes, not a shape promising properties from both lists

type SelectedMessage<
    F extends MessageFields | undefined = undefined
> = F extends undefined
    ? Message
    : F extends MessageFields
    ? number extends F["length"]
          ? MessageCore & Partial<Pick<Message, F[number]>>
          : Pick<Message, keyof MessageCore | F[number]>
    : nevertype SelectedMessage<
  F extends
    | MessageFields | undefined
    = undefined
> = F extends undefined
  ? Message
  : F extends MessageFields
  ? number extends F["length"]
      ?
          & MessageCore
          & Partial<
              Pick<
                Message, F[number]
              >
            >
      : Pick<
          Message,
          | keyof MessageCore
          | F[number]
        >
  : never