On This Page

Roles and Permissions

23 symbols from @neontechspace/fluxerly/effect

Variables#

hierarchy#

Compare roles and members by Fluxer's role hierarchy from snapshots already held, returning plain values rather than Effects

Invalid snapshots throw GuildOperationError with reason input, and such a throw inside Effect code becomes a defect, because inconsistent snapshots are a programming mistake

const hierarchy: HierarchyHelpers
TypeScript
import { Effect } from "effect"
import { hierarchy, type Client } from "@neontechspace/fluxerly/effect"
export function hierarchyExample(client: Client, guildId: string, actorUserId: string, targetUserId: string) {
    return Effect.gen(function* () {
        const [guild, actor, target, roles] = yield* Effect.all([
            client.guilds.fetch(guildId),
            client.members.fetch({ guildId, userId: actorUserId }),
            client.members.fetch({ guildId, userId: targetUserId }),
            client.roles.fetchAll(guildId),
        ])
        return hierarchy.canManage({ guild, actor, target, roles })
    })
}

permissionBits#

Build and inspect permission bitfields from named Fluxer permissions

A bitfield stores permission flags in a bigint. Methods return plain values immediately, the same as in the default API, without fetching resources or deciding whether an action is allowed. Unknown names or bits outside the unsigned 64-bit range throw HelperError, and such a throw inside Effect code becomes a defect

const permissionBits: PermissionBitHelpers

Interfaces#

PermissionHelpers#

Calculate permission bits from supplied snapshots or freshly fetched resources

These results do not account for timeouts or role hierarchy and do not prove an action will succeed

interface PermissionHelpers

calculate#

Calculate permission flags from supplied guild, member, role and optional channel data

No request or cache read is made, and connection state is irrelevant, including after client shutdown. The bigint result ranges from 0n through 18_446_744_073_709_551_615n and preserves unknown flags. Community owner or base Administrator gets all flags. Otherwise the calculation applies everyone, combined roles, then member overwrites. Only the target channel's stored overwrites are used, not its parent category's. A thread uses the overwrites of the parentChannel supplied with it, then grants SendMessages exactly when SendMessagesInThreads is granted, as Fluxer does. A thread without its parentChannel, or with any other channel as parentChannel, is rejected. Missing or inconsistent input is misuse and throws GuildOperationError for permissions.calculate with reason input in both APIs. A timed-out member keeps its permission bits, but Fluxer blocks sending messages, editing and publishing the member's own messages, reacting, uploading, typing, changing the member's own nickname, writing in threads and joining voice, so check members.timeoutState as well

calculate(input: PermissionInput): bigintcalculate(
  input: PermissionInput
): bigint

Parameters

Returns
bigint

Returns the value synchronously, as in the default API, because the calculation is pure

fetch#

Fetch guild, member, role and optional channel data, then calculate their permission flags

Use fetchChannels for every channel of a community. No gateway connection is needed, and by default every observation is read fresh without consulting a cache. Set preferCache to take each observation from an enabled cache when it is there and fetch only what is missing. A cached channel without its overwrite list is fetched, and so are all roles when any needed role is not cached. Cached observations reflect the last applied gateway events, which can differ from Fluxer, and they can come from different moments. Cached entries stay while a shard can resume and are cleared when a new session starts, after which they are fetched. Use the default right before an action where a stale grant matters. With caches disabled, preferCache behaves as the default. A thread channel adds a read of its parent channel, and the result follows Fluxer's thread rule as in calculate. Underlying fetches can enter enabled caches, but the calculated result is not cached. The sequential reads are separate observations, so the result does not guarantee a later action will succeed. The default deadline, rest.defaultTimeoutMs (30,000 ms unless configured), covers the whole helper with shared read retries and awaited cancellation cleanup. Only fetches count toward it, so reads served by a cache need no time. Invalid target, deadline or a preferCache that is not a boolean fails with permissions.fetch reason input. Resource errors keep their GuildOperationError or ChannelOperationError. A channel from another community fails instead of mixing guild data, and so does a channel other than a thread that Fluxer sends without its permission overwrite list, with permissions.fetch reason response, outcome unknown, details.read and details.channelId. Client closure fails with ClientClosedError. Its outcome is notDispatched when the client closes before a read is sent or during a cache lookup, including when every observation is cached, rejected while a read waits out a 429 before its retry, and unknown with details.read while a read is in flight

fetch(
    target: PermissionTarget,
    options?: PermissionFetchOptions
): Effect<
    bigint,
    ClientClosedError | ChannelOperationError | GuildOperationError
>fetch(
  target: PermissionTarget,
  options?: PermissionFetchOptions
): Effect<
  bigint,
  | ClientClosedError
  | ChannelOperationError
  | GuildOperationError
>

Parameters

options optional
PermissionFetchOptions

fetchChannels#

Fetch one member's permission flags in every channel of a community, such as to see what the bot can do in each channel

Pass the bot's own ID as userId, which client.users.getSelf() returns once the bot has connected. It reads the guild, the member, the role list and the channel list once each, always fresh, then calculates each channel locally the same way as calculate and fetch, so the community owner and an Administrator get every flag. That is four reads for the whole community, where fetch with a channelId takes up to four per channel. Returns a frozen array of frozen { channel, permissions } entries, in the order Fluxer lists the channels. Fluxer lists only the channels the bot can view, so a channel that only the member can view is missing. Threads and forum posts are not listed, so call fetch with a thread's ID for one. The reads happen at different moments, so the result does not guarantee that a later action will succeed. It ignores timeouts and role hierarchy, and a channel's bits do not prove that the member can view it. The reads can fill enabled caches, but the result itself is not cached. Unlike fetch, it has no preferCache, because no cache holds a complete channel list. The default deadline, rest.defaultTimeoutMs (30,000 ms unless configured), covers the whole call, including read retries and awaited cancellation cleanup. An invalid target or deadline fails with permissions.fetchChannels reason input. Errors from the reads keep their GuildOperationError or ChannelOperationError. A listed channel that Fluxer sends without its permission overwrites fails with permissions.fetchChannels reason response, outcome unknown, details.read and details.channelId, as in fetch. Client closure fails with ClientClosedError. Its outcome is notDispatched when the client closes before a read is sent, rejected while a read waits out a 429 before its retry, and unknown with details.read while a read is in flight

fetchChannels(
    target: MemberReference,
    options?: RequestOptions
): Effect<
    readonly ChannelPermissions[],
    ClientClosedError | ChannelOperationError | GuildOperationError
>fetchChannels(
  target: MemberReference,
  options?: RequestOptions
): Effect<
  readonly ChannelPermissions[],
  | ClientClosedError
  | ChannelOperationError
  | GuildOperationError
>

Parameters

options optional
RequestOptions
TypeScript
import { Effect } from "effect"
import { permissionBits, type Client } from "@neontechspace/fluxerly/effect"

export const sendableChannels = (client: Client, guildId: string) =>
    Effect.gen(function* () {
        const botId = (yield* client.users.getSelf())?.id
        if (botId === undefined) return []
        const entries = yield* client.permissions.fetchChannels({ guildId, userId: botId })
        return entries
            .filter(({ permissions }) => permissionBits.hasAll(permissions, ["ViewChannel", "SendMessages"]))
            .map(({ channel }) => channel.id)
    })

Roles#

Read or change community roles, their permission bits and their ordering

Methods return Effects and share Guilds' HTTP concurrency limits, deadlines and read retries. Writes retry only confirmed 429 rejections. Fluxer enforces permissions and hierarchy, and the SDK does not predict permissions locally. Interruption waits for owned cleanup but cannot undo write requests already sent. Success is not a gateway acknowledgement. Expected failures use GuildOperationError or ClientClosedError. Defects and interruption retain Cause. Inputs are copied on execution, not Effect construction. Returned roles contain bigint permissions and require explicit JSON conversion. Every remote role mutation accepts AuditedRequestOptions. The fetchAll method rejects auditReason

interface Roles

create#

Create a role with a name, optional color and permission flags

The permissions input defaults to 0n, rather than copying the everyone role's grants. Supplied permissions must be from 0n through 9_223_372_036_854_775_807n. Explicit permissions use Fluxer's feature opt-in for ViewChannelMembers. The result reports the actual server grants, which can differ from the request. Use a separate edit to change hoist or mentionable settings. The application manages the created role afterward. After an unknown outcome, use fetchAll before deciding whether to create again

create(
    guildId: string,
    input: RoleCreate,
    options?: AuditedRequestOptions
): Effect<GuildRole, GuildOperationFailure>create(
  guildId: string,
  input: RoleCreate,
  options?: AuditedRequestOptions
): Effect<
  GuildRole,
  GuildOperationFailure
>

Parameters

guildId
string
options optional
AuditedRequestOptions
TypeScript
import { Permissions, type Client } from "@neontechspace/fluxerly/effect"
export const createRoleExample = (client: Client, guildId: string) =>
    client.roles.create(guildId, {
        name: "Readers",
        permissions: Permissions.ViewChannel | Permissions.ReadMessageHistory,
    })

delete#

Delete a role and remove its member assignments in Fluxer

The everyone role cannot be deleted. Fluxer removes the role from each member in separate writes before it deletes the role, and does not roll them back. A failure can leave the role in place after some members already lost it, so fetch the role and the affected members again before retrying. HTTP 204 succeeds with no value, without proving member-event delivery. Snapshots already returned to the caller remain unchanged

delete(
    role: RoleReference,
    options?: AuditedRequestOptions
): Effect<void, GuildOperationFailure>delete(
  role: RoleReference,
  options?: AuditedRequestOptions
): Effect<
  void,
  GuildOperationFailure
>

Parameters

options optional
AuditedRequestOptions

edit#

Change only supplied role fields and return the server's snapshot

Empty inputs and unknown fields fail locally. The permissions input replaces all raw grants rather than adding flags, and can set or clear ViewChannelMembers. The replacement must be from 0n through 9_223_372_036_854_775_807n, and larger received masks cannot be written unchanged. The everyone role accepts only color and permissions. Other supplied fields fail, even in a mixed input

edit(
    role: RoleReference,
    input: RoleEdit,
    options?: AuditedRequestOptions
): Effect<GuildRole, GuildOperationFailure>edit(
  role: RoleReference,
  input: RoleEdit,
  options?: AuditedRequestOptions
): Effect<
  GuildRole,
  GuildOperationFailure
>

Parameters

input
RoleEdit
options optional
AuditedRequestOptions

fetchAll#

Fetch the community's current role list, including everyone, in server order

This always reads remotely, without pagination or background refresh

fetchAll(
    guildId: string,
    options?: RequestOptions
): Effect<readonly GuildRole[], GuildOperationFailure>fetchAll(
  guildId: string,
  options?: RequestOptions
): Effect<
  readonly GuildRole[],
  GuildOperationFailure
>

Parameters

guildId
string
options optional
RequestOptions

get#

Look up a role by decimal guildId and id in the enabled cache, including the everyone role

No request is made. The cache misses, stale-snapshot warnings, misuse and recency rules of guilds.get apply

get(role: RoleReference): Effect<GuildRole | undefined>get(
  role: RoleReference
): Effect<GuildRole | undefined>

Parameters

Returns
Effect<GuildRole | undefined>

getAll#

Look up every role of a community by decimal guildId in the enabled cache, including the everyone role

No request is made. The frozen list is ordered as roles.fetchAll orders it, highest in the hierarchy first: Larger positions first, and the smaller numeric ID first between equal positions. The result is undefined unless the cache holds the complete list. A guildCreate event makes the list complete, as does a full role read, such as roles.fetchAll, that finishes while the community's shard is connected, when no role event, role write or lost connection overlapped it. Only role events keep the list current, so a read while that shard is not connected, such as before connect, leaves it unknown. Later role create and update events keep it complete. Removing any of the community's roles makes it unknown again, whether by a role deletion event, expiry, capacity eviction, cache.delete or cache.clear, as does a role the cache does not keep because of its limits or maxAgeMs. So does every role write by the bot that succeeds or has an unknown outcome, including create, edit and reorder. A shard's new session, including its first, makes it unknown until the next guildCreate, while a resumed session keeps it. The roles limit, 1,000 entries unless configured, counts roles of every community together, so a bot in many communities needs a larger limit to keep complete lists. An invalid ID is misuse: The default API throws GuildOperationError with reason input and the native API dies with it. A closing or closed client has no cache, so the result is undefined

getAll(guildId: string): Effect<readonly GuildRole[] | undefined>getAll(guildId: string): Effect<
  readonly GuildRole[] | undefined
>

Parameters

guildId
string
Returns
Effect<readonly GuildRole[] | undefined>Effect<
  readonly GuildRole[] | undefined
>
TypeScript
import { Effect } from "effect"
import type { Client } from "@neontechspace/fluxerly/effect"
export const roleNamesExample = (client: Client, guildId: string) =>
    client.roles.getAll(guildId).pipe(
        Effect.flatMap((cached) => (cached ? Effect.succeed(cached) : client.roles.fetchAll(guildId))),
        Effect.map((roles) => roles.map((role) => role.name)),
    )

reorder#

Change role hierarchy positions using distinct role IDs and nonnegative safe-integer positions

The everyone role cannot move. HTTP 204 succeeds with no value and no new role list. Fluxer normalizes manageable positions, so use fetchAll if final order matters. This is not a transaction. A failure can leave partial changes, requiring a fresh read before recovery

reorder(
    guildId: string,
    positions: readonly RolePosition[],
    options?: AuditedRequestOptions
): Effect<void, GuildOperationFailure>reorder(
  guildId: string,
  positions:
    readonly RolePosition[],
  options?: AuditedRequestOptions
): Effect<
  void,
  GuildOperationFailure
>

Parameters

guildId
string
positions
readonly RolePosition[]
options optional
AuditedRequestOptions

resetHoistPositions#

Clear display-position assignments across the community, including roles above the bot

Fluxer requires ManageRoles. Permission hierarchy and hoist flags remain unchanged. HTTP 204 succeeds with no value, not a role list. Changes are not transactional and a failure can be partial. Successful writes and writes with unknown outcomes invalidate cached guild roles. Refetch to resolve an unknown outcome

resetHoistPositions(
    guildId: string,
    options?: AuditedRequestOptions
): Effect<void, GuildOperationFailure>resetHoistPositions(
  guildId: string,
  options?: AuditedRequestOptions
): Effect<
  void,
  GuildOperationFailure
>

Parameters

guildId
string
options optional
AuditedRequestOptions

setHoistPositions#

Set roles' display positions without changing their permission hierarchy or enabling hoist

Pass a nonempty list of distinct role IDs with integer hoistPosition values from -2,147,483,648 through 2,147,483,647. The everyone role is excluded. Fluxer checks ManageRoles and hierarchy. HTTP 204 succeeds with no value, not a role list. Successful writes and writes with unknown outcomes invalidate cached guild roles and conflicting pending reads. Failure or cancellation can leave partial changes. Refetch before deciding to replay

setHoistPositions(
    guildId: string,
    positions: readonly RoleHoistPosition[],
    options?: AuditedRequestOptions
): Effect<void, GuildOperationFailure>setHoistPositions(
  guildId: string,
  positions:
    readonly RoleHoistPosition[],
  options?: AuditedRequestOptions
): Effect<
  void,
  GuildOperationFailure
>

Parameters

guildId
string
positions
readonly RoleHoistPosition[]
options optional
AuditedRequestOptions
TypeScript
import { type Client } from "@neontechspace/fluxerly/effect"
export function orderRoleDisplay(client: Client, guildId: string, roleId: string) {
    return client.roles.setHoistPositions(guildId, [{ id: roleId, hoistPosition: 0 }])
}

Re-Exports#

Declared in JavaScript & TypeScript and documented there. Import them from @neontechspace/fluxerly/effect as well

Permissions#
Named permission grants for role inputs, channel overwrites and raw permission checks
ChannelPermissions#
One entry of the permissions.fetchChannels result: A member's raw permission bits in one community channel
GuildRole#
A community role that groups members and supplies permission grants, hierarchy rank and display settings
GuildRoleUpdateBulk#
One bulk role update, not individual update events or a complete role list
OverwritePatch#
Changes for permissionBits.patchOverwrite: Which permissions to allow, deny or return to inheritance
PermissionBitInspection#
Known permission names and any unnamed bits found by permissionBits.inspect
PermissionInput#
Calculate a member's community or channel permission bits from supplied guild, member, role and channel data
PermissionOverwrite#
Give or deny channel permissions to one role or member
PermissionTarget#
Choose whose permission bits permissions.fetch should calculate, by default from fresh REST reads
RoleCreate#
Create a named community role with an optional color and permission grants
RoleEdit#
Change the name, grants or display settings of an existing role
RoleHierarchyInput#
Check whether one community member outranks another using guild, member and role snapshots already held by the caller
RoleHoistPosition#
One display-order assignment, independent of permission hierarchy and the role's hoist flag
RoleManagementInput#
Check whether a community member's rank allows managing one role using guild, member and role snapshots already held by the caller
RolePosition#
One requested hierarchy position, not an absolute final-position guarantee
RoleReference#
Address one role inside its owning community for role reads and changes, without fetching it or retaining a client
HierarchyHelpers#
Compare roles and members by Fluxer's role hierarchy using snapshots the caller already holds
PermissionBitHelpers#
Methods of the permissionBits helper, which builds and inspects raw bigint permission flags
PermissionName#
A key of Permissions, such as "ManageMessages", accepted by the named permissionBits helpers