gaato/discord/app does not have a README file
type Spawner = async (async () -> Unit) -> Unitpub(all) suberror AppConfigError {
EmptyToken
DuplicateCommand(name~ : String, first~ : SourceLoc, second~ : SourceLoc)
DuplicateCommandPath(command~ : String, path~ : String)
NestedSubcommandGroup(command~ : String, path~ : String)
ChoicesWithAutocomplete(command~ : String, path~ : String)
RequiredOptionAfterOptional(command~ : String, path~ : String)
DuplicateComponentRoute(custom_id~ : String, first~ : SourceLoc, second~ : SourceLoc)
DuplicateModalRoute(custom_id~ : String, first~ : SourceLoc, second~ : SourceLoc)
EmptyComponentRoute
EmptyModalRoute
InvalidRouteId(custom_id~ : String, reason~ : String)
InvalidModalFieldCount(custom_id~ : String, count~ : Int)
DuplicateModalTextInput(custom_id~ : String, field~ : String)
ModalOutsideLimits(custom_id~ : String, violation~ : LimitViolation)
InvalidFileTypes(owner~ : String, reason~ : String)
CommandOutsideLimits(command~ : String, violation~ : LimitViolation)
InvalidCooldown(command~ : String, seconds~ : Int)
InvalidMaxInFlight(value~ : Int)
InvalidMaxPending(value~ : Int)
} derive(Debug)pub(all) suberror CustomIdError {
TooLong(custom_id~ : String, length~ : Int)
SeparatorInSegment(segment~ : String)
} derive(Debug)pub(all) suberror HandlerError {
UserMessage(message~ : String, ephemeral~ : Bool)
GuildOnly
DmOnly
CheckFailed
MissingPermission(Permissions)
OnCooldown(retry_after_ms~ : Int64)
InvalidInput(name~ : String?, message~ : String)
Malformed(reason~ : String)
UnsupportedResponse(reason~ : String)
Busy
} derive(Debug)test "guard a handler with a permission requirement" {
fn require_send_messages(permissions : @model.Permissions) -> Unit raise {
let required = @model.Permissions::send_messages()
if !permissions.contains(required) {
raise @app.HandlerError::MissingPermission(required)
}
}
try require_send_messages(@model.Permissions::none()) catch {
@app.HandlerError::MissingPermission(_) => ()
other => raise other
} noraise {
_ => fail("expected MissingPermission")
}
}pub(all) suberror ModalShowError {
InvalidCustomId(CustomIdError)
UnknownCustomId(custom_id~ : String)
NonTextInput(custom_id~ : String)
ValueTooLong(custom_id~ : String, length~ : Int, max~ : Int)
} derive(Debug)pub struct App {
// private fields
}fn App::attach(self : App, framework : Framework, client~ : Client, application_id~ : Id[ApplicationMarker], waiter? : async (String, Id[UserMarker]?, Int?) -> ComponentCtx?, latency_ms? : () -> Int64?, intake? : HandlerIntake) -> AppCtxasync fn App::plan_commands(self : App, client : Client, application_id : Id[ApplicationMarker], scope~ : CommandScope, unowned? : UnownedCommands) -> CommandPlanasync fn App::serve(self : App, group : TaskGroup[Unit], access~ : RestAccess, application_id? : Id[ApplicationMarker], clock? : &Clock) -> InteractionEndpointfn App::spawner(self : App, group : TaskGroup[Unit], intake? : HandlerIntake) -> (async (async () -> Unit) -> Unit)async fn App::sync_commands(self : App, client : Client, application_id : Id[ApplicationMarker], scope~ : CommandScope, unowned? : UnownedCommands) -> SyncReportpub struct AppBuilder {
// private fields
}fn AppBuilder::AppBuilder(max_in_flight? : Int, max_pending? : Int, cooldown_store? : &CooldownStore, cooldown_outage? : CooldownOutage) -> AppBuilderfn AppBuilder::autocomplete(self : AppBuilder, name : String, handler : async (AutocompleteCtx) -> Unit) -> Unit#callsite(autofill(loc))
fn[A] AppBuilder::command(self : AppBuilder, command : Command[A], loc~ : SourceLoc) -> Unitfn AppBuilder::middleware(self : AppBuilder, middleware : async (InteractionCtx, async () -> Unit) -> Unit) -> Unit#callsite(autofill(loc))
fn[A] AppBuilder::on_component(self : AppBuilder, route : ComponentRoute[A], handler : ComponentHandler[A], loc~ : SourceLoc) -> Unit#callsite(autofill(loc))
fn AppBuilder::on_component_raw(self : AppBuilder, prefix~ : String, handler : async (ComponentCtx) -> Unit, loc~ : SourceLoc) -> Unit#callsite(autofill(loc))
fn[S, A] AppBuilder::on_modal(self : AppBuilder, modal : Modal[S, A], handler : ModalSubmitHandler[S, A], loc~ : SourceLoc) -> Unit#callsite(autofill(loc))
fn AppBuilder::on_modal_raw(self : AppBuilder, prefix~ : String, handler : async (ModalCtx) -> Unit, loc~ : SourceLoc) -> Unit#callsite(autofill(loc))
fn AppBuilder::register(self : AppBuilder, command : RegisteredCommand, loc~ : SourceLoc) -> Unitpub struct AppCtx {
// private fields
}pub(all) enum AppWarning {
AutoDeferFailed(target~ : String, error~ : Error)
InteractionDropped(target~ : String)
DeferredInteractionExpired(target~ : String)
InteractionDroppedWhileStopping(target~ : String)
ErrorResponseWithoutInteraction(summary~ : String)
ErrorResponseExpired(summary~ : String)
MalformedInteraction(origin~ : FailureOrigin, reason~ : String)
UnhandledFailure(origin~ : FailureOrigin, error~ : Error)
ErrorPolicyFailed(error~ : Error)
AutocompleteTruncated(command_path~ : String, option~ : String, count~ : Int)
HandlerFailed(target~ : String, error~ : Error)
WaiterUnavailable
InteractionProcessingFailed(error~ : Error)
Executor(source~ : String, message~ : String)
DeferredInteractionsRefused(max_pending~ : Int)
CooldownUnavailable(reason~ : String, outage~ : CooldownOutage)
} derive(Debug)impl Show for AppWarningpub struct CheckCtx {
// private fields
}pub struct Command[A] {
// private fields
}fn CommandReply::message(content? : String, embeds? : Array[Embed], components? : Array[Component], files? : Array[FileUpload], allowed_mentions? : AllowedMentions, poll? : PollCreateRequest, ephemeral? : Bool) -> CommandReplypub(all) enum CommandScope {
Global
Guild(Id[GuildMarker])
Guilds(Array[Id[GuildMarker]])
} derive(Debug)pub struct ComponentDeferredCtx {
// private fields
}async fn ComponentDeferredCtx::delete_followup(self : ComponentDeferredCtx, message_id : Id[MessageMarker]) -> Unitasync fn ComponentDeferredCtx::edit_followup(self : ComponentDeferredCtx, message_id : Id[MessageMarker], content? : String, clear_content? : Bool, embeds? : Array[Embed], components? : Array[Component], allowed_mentions? : AllowedMentions, files? : Array[FileUpload], keep_attachments? : Array[AttachmentRequest]) -> Messageasync fn ComponentDeferredCtx::edit_original(self : ComponentDeferredCtx, content? : String, clear_content? : Bool, embeds? : Array[Embed], components? : Array[Component], allowed_mentions? : AllowedMentions, files? : Array[FileUpload], keep_attachments? : Array[AttachmentRequest], poll? : PollCreateRequest) -> Messageasync fn ComponentDeferredCtx::followup(self : ComponentDeferredCtx, content? : String, embeds? : Array[Embed], components? : Array[Component], files? : Array[FileUpload], allowed_mentions? : AllowedMentions, poll? : PollCreateRequest, ephemeral? : Bool) -> Messageasync fn ComponentDeferredCtx::get_followup(self : ComponentDeferredCtx, message_id : Id[MessageMarker]) -> Messagefn ComponentDeferredCtx::guild_scope(self : ComponentDeferredCtx) -> GuildInvocation raise HandlerErrorasync fn[A] ComponentDeferredCtx::wait_for_component(self : ComponentDeferredCtx, route : ComponentRoute[A], state : A, from? : WaitFrom, timeout_ms? : Int) -> ComponentCtx?pub(all) enum ComponentHandler[A] {
Immediate(async (ComponentImmediateCtx, A) -> ComponentReply)
DeferredUpdate(async (ComponentDeferredCtx, A) -> Unit)
DeferredMessage(ephemeral~ : Bool, async (ComponentDeferredCtx, A) -> Unit)
Raw(async (ComponentCtx) -> Unit)
}pub struct ComponentImmediateCtx {
// private fields
}fn ComponentImmediateCtx::guild_scope(self : ComponentImmediateCtx) -> GuildInvocation raise HandlerErrorpub(all) enum ComponentReply {
UpdateMessage(MessageUpdate)
Message(InitialResponse)
ShowModal(ModalHandle)
}fn ComponentReply::message(content? : String, embeds? : Array[Embed], components? : Array[Component], files? : Array[FileUpload], allowed_mentions? : AllowedMentions, poll? : PollCreateRequest, ephemeral? : Bool) -> ComponentReplyfn ComponentReply::update_message(content? : String, clear_content? : Bool, embeds? : Array[Embed], components? : Array[Component], allowed_mentions? : AllowedMentions, files? : Array[FileUpload], keep_attachments? : Array[AttachmentRequest], poll? : PollCreateRequest) -> ComponentReplypub struct ComponentRoute[A] {
// private fields
}test {
let route = @app.component_route(
id="ticket-close",
state=@app.CustomIdCodec::int(),
)
assert_eq(route.decode(route.custom_id(42)), 42)
}pub struct CustomIdCodec[A] {
// private fields
}fn[A] CustomIdCodec::custom(encode~ : (A) -> String, decode~ : (String) -> A raise) -> CustomIdCodec[A]fn[A, B] CustomIdCodec::imap(self : CustomIdCodec[A], to~ : (A) -> B raise, from~ : (B) -> A) -> CustomIdCodec[B]fn[A, B] CustomIdCodec::zip(self : CustomIdCodec[A], other : CustomIdCodec[B]) -> CustomIdCodec[(A, B)]pub struct DeferredCtx {
// private fields
}async fn DeferredCtx::edit_followup(self : DeferredCtx, message_id : Id[MessageMarker], content? : String, clear_content? : Bool, embeds? : Array[Embed], components? : Array[Component], allowed_mentions? : AllowedMentions, files? : Array[FileUpload], keep_attachments? : Array[AttachmentRequest]) -> Messageasync fn DeferredCtx::edit_original(self : DeferredCtx, content? : String, clear_content? : Bool, embeds? : Array[Embed], components? : Array[Component], allowed_mentions? : AllowedMentions, files? : Array[FileUpload], keep_attachments? : Array[AttachmentRequest], poll? : PollCreateRequest) -> Messageasync fn DeferredCtx::followup(self : DeferredCtx, content? : String, embeds? : Array[Embed], components? : Array[Component], files? : Array[FileUpload], allowed_mentions? : AllowedMentions, poll? : PollCreateRequest, ephemeral? : Bool) -> Messageasync fn[A] DeferredCtx::wait_for_component(self : DeferredCtx, route : ComponentRoute[A], state : A, from? : WaitFrom, timeout_ms? : Int) -> ComponentCtx?pub struct FailureCtx {
// private fields
}async fn FailureCtx::respond_error(self : FailureCtx, content? : String, embeds? : Array[Embed], components? : Array[Component], files? : Array[FileUpload], allowed_mentions? : AllowedMentions, ephemeral? : Bool) -> Unitpub struct HandlerIntake {
// private fields
}pub struct ImmediateCtx {
// private fields
}pub struct InitialResponse {
// private fields
}pub struct InteractionCtx {
// private fields
}async fn InteractionCtx::respond(self : InteractionCtx, message : String, ephemeral? : Bool) -> Unitpub struct InteractionEndpoint {
// private fields
}async fn InteractionEndpoint::handle(self : InteractionEndpoint, body : Json, deadline_ms? : Int) -> Json?async fn InteractionEndpoint::handle_interaction(self : InteractionEndpoint, interaction : Interaction, deadline_ms? : Int) -> InteractionOutcomeasync fn InteractionEndpoint::handle_signed_http(self : InteractionEndpoint, request : InteractionHttpRequest, verifier : InteractionVerifier, deadline_ms? : Int) -> InteractionHttpResponsepub(all) enum InteractionHandler[A] {
Immediate(async (ImmediateCtx, A) -> CommandReply)
Deferred(ephemeral~ : Bool, async (DeferredCtx, A) -> Unit)
Raw(async (CommandCtx) -> Unit)
}pub(all) struct InteractionHttpRequest {
http_method : String
signature : String?
timestamp : String?
body : Bytes
}pub(all) struct InteractionHttpResponse {
status : Int
content_type : String?
body : InteractionHttpBody
}pub(all) enum InteractionOutcome {
Reply(response~ : InteractionResponse, files~ : Array[FileUpload]?)
NoRoute
NoResponse
TimedOut
} derive(Debug)pub(all) enum InteractionTarget {
Command(name~ : String)
Component(custom_id~ : String)
Modal(custom_id~ : String)
} derive(Debug)pub struct MessageUpdate {
// private fields
}fn MessageUpdate::MessageUpdate(content? : String, clear_content? : Bool, embeds? : Array[Embed], components? : Array[Component], allowed_mentions? : AllowedMentions, files? : Array[FileUpload], keep_attachments? : Array[AttachmentRequest], poll? : PollCreateRequest) -> MessageUpdatepub struct Modal[S, A] {
// private fields
}fn[S, A] Modal::show(self : Modal[S, A], state : S, values? : Map[String, String]) -> ModalHandle raise ModalShowErrorpub struct ModalDeferredCtx {
// private fields
}async fn ModalDeferredCtx::delete_followup(self : ModalDeferredCtx, message_id : Id[MessageMarker]) -> Unitasync fn ModalDeferredCtx::edit_followup(self : ModalDeferredCtx, message_id : Id[MessageMarker], content? : String, clear_content? : Bool, embeds? : Array[Embed], components? : Array[Component], allowed_mentions? : AllowedMentions, files? : Array[FileUpload], keep_attachments? : Array[AttachmentRequest]) -> Messageasync fn ModalDeferredCtx::edit_original(self : ModalDeferredCtx, content? : String, clear_content? : Bool, embeds? : Array[Embed], components? : Array[Component], allowed_mentions? : AllowedMentions, files? : Array[FileUpload], keep_attachments? : Array[AttachmentRequest], poll? : PollCreateRequest) -> Messageasync fn ModalDeferredCtx::followup(self : ModalDeferredCtx, content? : String, embeds? : Array[Embed], components? : Array[Component], files? : Array[FileUpload], allowed_mentions? : AllowedMentions, poll? : PollCreateRequest, ephemeral? : Bool) -> Messageasync fn ModalDeferredCtx::get_followup(self : ModalDeferredCtx, message_id : Id[MessageMarker]) -> Messageasync fn[A] ModalDeferredCtx::wait_for_component(self : ModalDeferredCtx, route : ComponentRoute[A], state : A, from? : WaitFrom, timeout_ms? : Int) -> ComponentCtx?pub struct ModalField[A] {
// private fields
}pub struct ModalFields[A] {
// private fields
}fn[A, B, Z] ModalFields::map2(a : ModalField[A], b : ModalField[B], f : (A, B) -> Z) -> ModalFields[Z]fn[A, B, C, Z] ModalFields::map3(a : ModalField[A], b : ModalField[B], c : ModalField[C], f : (A, B, C) -> Z) -> ModalFields[Z]fn[A, B, C, D, Z] ModalFields::map4(a : ModalField[A], b : ModalField[B], c : ModalField[C], d : ModalField[D], f : (A, B, C, D) -> Z) -> ModalFields[Z]fn[A, B, C, D, E, Z] ModalFields::map5(a : ModalField[A], b : ModalField[B], c : ModalField[C], d : ModalField[D], e : ModalField[E], f : (A, B, C, D, E) -> Z) -> ModalFields[Z]pub struct ModalHandle {
// private fields
}pub struct ModalImmediateCtx {
// private fields
}fn ModalReply::message(content? : String, embeds? : Array[Embed], components? : Array[Component], files? : Array[FileUpload], allowed_mentions? : AllowedMentions, poll? : PollCreateRequest, ephemeral? : Bool) -> ModalReplyfn ModalReply::update_message(content? : String, clear_content? : Bool, embeds? : Array[Embed], components? : Array[Component], allowed_mentions? : AllowedMentions, files? : Array[FileUpload], keep_attachments? : Array[AttachmentRequest], poll? : PollCreateRequest) -> ModalReplypub(all) enum ModalSubmitHandler[S, A] {
Immediate(async (ModalImmediateCtx, S, A) -> ModalReply)
DeferredMessage(ephemeral~ : Bool, async (ModalDeferredCtx, S, A) -> Unit)
DeferredUpdate(async (ModalDeferredCtx, S, A) -> Unit)
Raw(async (ModalCtx) -> Unit)
}pub struct RegisteredCommand {
// private fields
}pub struct SlashChild {
// private fields
}test "build a component from its route" {
let route = @app.component_route(id="page", state=@app.CustomIdCodec::int())
let app = @app.AppBuilder()
app.on_component(
route,
Immediate((_, page) => @app.ComponentReply::message(content="Page \{page}")),
)
let _ = @interaction.button(custom_id=route.custom_id(2), label="Next")
assert_eq(route.custom_id(2), "page:2")
app.build() |> ignore
}fn file_field(custom_id~ : String, label~ : String, description? : String, min_values? : Int, max_values? : Int, file_types? : Array[FileTypeFilter]) -> ModalField[Array[Attachment]]fn message_command(name~ : String, handler~ : InteractionHandler[Message], default_member_permissions? : Permissions, nsfw? : Bool, integration_types? : Array[ApplicationIntegrationType], contexts? : Array[InteractionContextType], name_localizations? : Map[String, String]) -> Command[Message]fn[S, A] modal(custom_id~ : String, title~ : String, state~ : CustomIdCodec[S], fields~ : ModalFields[A]) -> Modal[S, A]test "construct and validate a typed modal" {
let feedback = @app.modal(
custom_id="feedback",
title="Feedback",
state=@app.CustomIdCodec::int(),
fields=@app.ModalFields::of(
@app.text_field(custom_id="details", label="Details").optional(),
),
)
let app = @app.AppBuilder()
app.on_modal(feedback, Raw(_ => ()))
app.build() |> ignore
let _ : @app.ModalHandle = feedback.show(42)
}fn select_field(custom_id~ : String, label~ : String, options~ : Array[SelectOption], description? : String, placeholder? : String, min_values? : Int, max_values? : Int) -> ModalField[Array[String]]fn[A] slash(name~ : String, description~ : String, args~ : Args[A], handler~ : InteractionHandler[A], default_member_permissions? : Permissions, nsfw? : Bool, integration_types? : Array[ApplicationIntegrationType], contexts? : Array[InteractionContextType], name_localizations? : Map[String, String], description_localizations? : Map[String, String]) -> Command[A]test "inspect a slash-command registration spec" {
let command = @app.slash(
name="echo",
description="Echo text",
args=@interaction.Args::of(
@interaction.arg_string(name="text", description="Text to echo"),
),
handler=Raw(_ => ()),
)
json_inspect(command.spec().to_json(), content={
"name": "echo",
"description": "Echo text",
"options": [
{
"type": 3,
"name": "text",
"description": "Text to echo",
"required": true,
},
],
})
}fn slash_group(name~ : String, description~ : String, children~ : Array[SlashChild], default_member_permissions? : Permissions, nsfw? : Bool, integration_types? : Array[ApplicationIntegrationType], contexts? : Array[InteractionContextType], name_localizations? : Map[String, String], description_localizations? : Map[String, String]) -> Command[Unit]fn[A] subcommand(name~ : String, description~ : String, args~ : Args[A], handler~ : InteractionHandler[A], name_localizations? : Map[String, String], description_localizations? : Map[String, String]) -> SlashChildfn subcommand_group(name~ : String, description~ : String, children~ : Array[SlashChild], name_localizations? : Map[String, String], description_localizations? : Map[String, String]) -> SlashChildfn text_field(custom_id~ : String, label~ : String, style? : TextInputStyle, description? : String, placeholder? : String, min_length? : Int, max_length? : Int, value? : String) -> ModalField[String]fn user_command(name~ : String, handler~ : InteractionHandler[TargetUser], default_member_permissions? : Permissions, nsfw? : Bool, integration_types? : Array[ApplicationIntegrationType], contexts? : Array[InteractionContextType], name_localizations? : Map[String, String]) -> Command[TargetUser]test "inspect context-menu command kinds" {
let user = @app.user_command(name="Inspect user", handler=Raw(_ => ()))
let message = @app.message_command(
name="Inspect message",
handler=Raw(_ => ()),
)
json_inspect(user.spec().to_json(), content={
"name": "Inspect user",
"description": "",
"type": 2,
})
json_inspect(message.spec().to_json(), content={
"name": "Inspect message",
"description": "",
"type": 3,
})
}Install
Download zipAn experimental Discord library for MoonBit: native/JS/Wasm REST, interactions, and gateway bots. Voice is in gaato/discord_voice.
Dependencies