Index
Introduction
Welcome to Ekztazy.jl
Ekztazy.jl is the spiritual successor to Discord.jl. It is a maintained Julia Pkg for creating simple yet efficient Discord bots.
- Strong, expressive type system: No fast-and-loose JSON objects here.
- Non-blocking: API calls return immediately and can be awaited when necessary.
- Simple: Multiple dispatch allows for a small, elegant core API.
- Fast: Julia is fast like C but still easy like Python.
- Robust: Resistant to bad event handlers and/or requests. Errors are introspectible for debugging.
- Lightweight: Cache what is important but shed dead weight with TTL.
- Gateway independent: Ability to interact with Discord's API without establishing a gateway connection.
- Distributed: Process-based sharding requires next to no intervention and you can even run shards on separate machines.
Getting Started
You can add Ekztazy.jl from Git using the following command in the REPL:
] add https://github.com/Humans-of-Julia/Ekztazy.jl
The most important type when working with Ekztazy.jl is the Client
. Most applications will start in a similar fashion to this:
using Ekztazy
client = Client()
This will create a Client
using default parameters. This expects two environment variables:
- APPLICATION_ID, the bot's application id
- DISCORD_TOKEN, the bot's secret token
These can also be specified.
using Ekztazy
client = Client(
discord_token,
application_id,
intents(GUILDS, GUILD_MESSAGES)
)
(Assuming discord_token is a String and applicaton_id is an Int). For a more complete list of parameters for creating a Client
. Check the Client documentation.
Usually when working with Ekztazy, we will either want to handle messages or commands. Let's start with messages.
# ...
on_message_create!(client) do (ctx)
if ctx.message.author.id != me(client).id
reply(client, ctx, content="I received the following message: $(ctx.message.content).")
end
end
start(client)
Let's look this code. First we are using the on_message_create!
function which generates a Handler
. (For more information on this, check the events documentation). Then in the handling function we start by checking if the the message author's id isn't the same as the the bot's. This is sensible, as we wouldn't want the bot to indefinitely respond to itself. Finally, we use the reply
function to reply to the message! Under the hood, the reply function appraises the context, and finds a way to reply to it, the kwargs
passed to it are then made into the request body. Here, in the message we use interpolation to send the message's content. We finish by calling start
on the client.
Next, commands.
# ...
g = ENV["MY_TESTING_GUILD"]
command!(client, g, "double", "Doubles a number!", options=[opt(name="number", description="The number to double!")]) do (ctx)
Ekztazy.reply(client, ctx, content="$(parse(Int, opt(ctx)["number"])*2)")
end
start(client)
Let's look at this code again. First we are using the command!
function. This creates a command with the specified parameters. We are also using the helper opt
method, to generate and get options. Calling opt with a name and description will create an option, using it on a context will get the values the user provided for each option in a Dict. Like in the previous example we are using the magic reply
function that creates a followup message for the interaction. (This does not strictly reply to the interaction. Interactions instantly get ACKd by Ekztazy.jl to prevent your handling implementation from exceeding the interaction's 3s reply time limit.)
Here is the equivalent using the new system. The old system is deprecated and will be removed in the next major version.
# ...
g = ENV["MY_TESTING_GUILD"]
command!(client, g, "double", "Doubles a number!", legacy=false, options=Options(
[Int, "num", "The number to double!"]
) do ctx, num::Int
reply(client, ctx, content="$(num*2)")
end
start(client)
The option num
will magically be passed to the handler to be used directly, no need to use [opt
] anywhere anymore. The value for num is also automatically converted to an Int.
Sometimes we may also want to do things without waiting for user input. However putting such code in the top scope would never be executed as start
is blocking. This is where on_ready!
comes in.
# ...
CHID = 776251117616234509 # Testing channel ID
on_ready!(client) do (ctx)
button = component!(client, "ar00"; type=2, style=1, label="Really??") do (ctx)
Ekztazy.reply(client, ctx, content="Yes!")
end
create(client, Message, CHID, content="I am ready!", components=[button])
end
Here, we first are using the on_ready!
. This is called as soon as the bot is ready (see the events documentation). We are then creating a Component
and a handler for it. The component's handler simply replies with "Yes!", as usual using the reply
function. Next we have a new function, create
. This simply sends message to the specificed channel id (See the REST API documentation for more info). Here the message content is simply "I am ready". It also has a component.
The component we created previously is of type 2, it's a button. It cannot be sent directly and needs to be wrapped in an action row of type 1, however Ekztazy is very nice so it'll do that for you.
This is all you should need for most Discord bot projects! For any question please join the Humans of Julia Discord, and look for me @Kyando#0001!
Ekztazy.ActionType
Ekztazy.ActivityFlags
Ekztazy.ActivityType
Ekztazy.ExplicitContentFilterLevel
Ekztazy.MFALevel
Ekztazy.MessageActivityType
Ekztazy.MessageNotificationLevel
Ekztazy.MessageType
Ekztazy.VerificationLevel
Ekztazy.STYLES
Ekztazy.AbstractGuild
Ekztazy.Activity
Ekztazy.ActivityAssets
Ekztazy.ActivityParty
Ekztazy.ActivitySecrets
Ekztazy.ActivityTimestamps
Ekztazy.ApplicationCommand
Ekztazy.ApplicationCommandChoice
Ekztazy.ApplicationCommandOption
Ekztazy.Attachment
Ekztazy.AuditLog
Ekztazy.AuditLogChange
Ekztazy.AuditLogEntry
Ekztazy.AuditLogOptions
Ekztazy.Ban
Ekztazy.CacheFilter
Ekztazy.CacheForever
Ekztazy.CacheLRU
Ekztazy.CacheNever
Ekztazy.CacheStrategy
Ekztazy.CacheTTL
Ekztazy.Client
Ekztazy.Component
Ekztazy.Connection
Ekztazy.Context
Ekztazy.DiscordChannel
Ekztazy.Embed
Ekztazy.EmbedAuthor
Ekztazy.EmbedField
Ekztazy.EmbedFooter
Ekztazy.EmbedImage
Ekztazy.EmbedProvider
Ekztazy.EmbedThumbnail
Ekztazy.EmbedVideo
Ekztazy.Emoji
Ekztazy.Guild
Ekztazy.GuildEmbed
Ekztazy.Handler
Ekztazy.Integration
Ekztazy.IntegrationAccount
Ekztazy.Interaction
Ekztazy.InteractionData
Ekztazy.Invite
Ekztazy.InviteMetadata
Ekztazy.Member
Ekztazy.Message
Ekztazy.MessageActivity
Ekztazy.MessageApplication
Ekztazy.Overwrite
Ekztazy.Permission
Ekztazy.Presence
Ekztazy.Reaction
Ekztazy.Response
Ekztazy.Role
Ekztazy.SelectOption
Ekztazy.UnavailableGuild
Ekztazy.User
Ekztazy.VoiceRegion
Ekztazy.VoiceState
Ekztazy.Webhook
Base.close
Base.isopen
Base.open
Base.wait
Ekztazy.Option
Ekztazy.Options
Ekztazy.ack_interaction
Ekztazy.add_guild_member
Ekztazy.add_guild_member_role
Ekztazy.add_handler!
Ekztazy.add_pinned_channel_message
Ekztazy.begin_guild_prune
Ekztazy.bulk_delete_messages
Ekztazy.bulk_overwrite_application_commands
Ekztazy.command!
Ekztazy.component!
Ekztazy.create
Ekztazy.create_application_command
Ekztazy.create_channel_invite
Ekztazy.create_dm
Ekztazy.create_followup_message
Ekztazy.create_guild
Ekztazy.create_guild_ban
Ekztazy.create_guild_channel
Ekztazy.create_guild_emoji
Ekztazy.create_guild_integration
Ekztazy.create_guild_role
Ekztazy.create_message
Ekztazy.create_reaction
Ekztazy.create_webhook
Ekztazy.delete
Ekztazy.delete_all_reactions
Ekztazy.delete_channel
Ekztazy.delete_channel_permission
Ekztazy.delete_guild
Ekztazy.delete_guild_emoji
Ekztazy.delete_guild_integration
Ekztazy.delete_guild_role
Ekztazy.delete_invite
Ekztazy.delete_message
Ekztazy.delete_own_reaction
Ekztazy.delete_pinned_channel_message
Ekztazy.delete_user_reaction
Ekztazy.delete_webhook
Ekztazy.delete_webhook_with_token
Ekztazy.disable_cache!
Ekztazy.edit_channel_permissions
Ekztazy.edit_interaction
Ekztazy.edit_message
Ekztazy.enable_cache!
Ekztazy.execute_github_compatible_webhook
Ekztazy.execute_slack_compatible_webhook
Ekztazy.execute_webhook
Ekztazy.extops
Ekztazy.fetchval
Ekztazy.filter_ranges
Ekztazy.get_application_commands
Ekztazy.get_channel
Ekztazy.get_channel_invites
Ekztazy.get_channel_message
Ekztazy.get_channel_messages
Ekztazy.get_channel_webhooks
Ekztazy.get_current_user
Ekztazy.get_current_user_guilds
Ekztazy.get_guild
Ekztazy.get_guild_audit_log
Ekztazy.get_guild_ban
Ekztazy.get_guild_bans
Ekztazy.get_guild_channels
Ekztazy.get_guild_embed
Ekztazy.get_guild_emoji
Ekztazy.get_guild_integrations
Ekztazy.get_guild_invites
Ekztazy.get_guild_member
Ekztazy.get_guild_prune_count
Ekztazy.get_guild_roles
Ekztazy.get_guild_voice_regions
Ekztazy.get_guild_webhooks
Ekztazy.get_guild_widget_image
Ekztazy.get_invite
Ekztazy.get_pinned_messages
Ekztazy.get_reactions
Ekztazy.get_user
Ekztazy.get_vanity_url
Ekztazy.get_webhook
Ekztazy.get_webhook_with_token
Ekztazy.has_permission
Ekztazy.heartbeat_ping
Ekztazy.isme
Ekztazy.leave_guild
Ekztazy.list_guild_emojis
Ekztazy.list_guild_members
Ekztazy.list_voice_regions
Ekztazy.me
Ekztazy.mention
Ekztazy.method_args
Ekztazy.modify_channel
Ekztazy.modify_current_user
Ekztazy.modify_current_user_nick
Ekztazy.modify_guild
Ekztazy.modify_guild_channel_positions
Ekztazy.modify_guild_embed
Ekztazy.modify_guild_emoji
Ekztazy.modify_guild_integration
Ekztazy.modify_guild_member
Ekztazy.modify_guild_role
Ekztazy.modify_guild_role_positions
Ekztazy.modify_webhook
Ekztazy.modify_webhook_with_token
Ekztazy.obtain
Ekztazy.on_channel_create!
Ekztazy.on_channel_delete!
Ekztazy.on_channel_pins_update!
Ekztazy.on_channel_update!
Ekztazy.on_guild_ban_add!
Ekztazy.on_guild_ban_remove!
Ekztazy.on_guild_create!
Ekztazy.on_guild_delete!
Ekztazy.on_guild_emojis_update!
Ekztazy.on_guild_integrations_update!
Ekztazy.on_guild_member_add!
Ekztazy.on_guild_member_remove!
Ekztazy.on_guild_member_update!
Ekztazy.on_guild_members_chunk!
Ekztazy.on_guild_role_create!
Ekztazy.on_guild_role_delete!
Ekztazy.on_guild_role_update!
Ekztazy.on_guild_update!
Ekztazy.on_interaction_create!
Ekztazy.on_message_create!
Ekztazy.on_message_delete!
Ekztazy.on_message_delete_bulk!
Ekztazy.on_message_reaction_add!
Ekztazy.on_message_reaction_remove!
Ekztazy.on_message_reaction_remove_all!
Ekztazy.on_message_update!
Ekztazy.on_presence_update!
Ekztazy.on_ready!
Ekztazy.on_resumed!
Ekztazy.on_typing_start!
Ekztazy.on_user_update!
Ekztazy.on_voice_server_update!
Ekztazy.on_voice_state_update!
Ekztazy.on_webhooks_update!
Ekztazy.opt
Ekztazy.permissions_in
Ekztazy.plaintext
Ekztazy.remove_guild_ban
Ekztazy.remove_guild_member
Ekztazy.remove_guild_member_role
Ekztazy.reply
Ekztazy.request_guild_members
Ekztazy.respond_to_interaction
Ekztazy.retrieve
Ekztazy.set_game
Ekztazy.split_message
Ekztazy.start
Ekztazy.sync_guild_integration
Ekztazy.trigger_typing_indicator
Ekztazy.update
Ekztazy.update_ack_interaction
Ekztazy.update_message_int
Ekztazy.update_status
Ekztazy.update_voice_state
Ekztazy.upload_file
Ekztazy.@deferred_fetch
Ekztazy.@deferred_fetchval
Ekztazy.@fetch
Ekztazy.@fetchval