Helpers
Ekztazy.STYLES — ConstantRegex expressions for split_message to not break Discord formatting.
Ekztazy.Permission — TypeBitwise permission flags. More details here.
Ekztazy.has_permission — Functionhas_permission(perms::Integer, perm::Permission) -> BoolDetermine whether a bitwise OR of permissions contains one Permission.
Examples
julia> has_permission(0x0420, PERM_VIEW_CHANNEL)
true
julia> has_permission(0x0420, PERM_ADMINISTRATOR)
false
julia> has_permission(0x0008, PERM_MANAGE_ROLES)
trueEkztazy.permissions_in — Functionpermissions_in(m::Member, g::Guild, ch::DiscordChannel) -> Int64Compute a Member's Permissions in a DiscordChannel.
Ekztazy.reply — Functionreply(
c::Client
context;
kwargs...
)Replies to a Context, an Interaction or a Message.
Ekztazy.filter_ranges — Functionfilter_ranges(u::Vector{UnitRange{Int}})Filter a list of ranges, discarding ranges included in other ranges from the list.
Example
julia> Ekztazy.filter_ranges([1:5, 3:8, 1:20, 2:16, 10:70, 25:60, 5:35, 50:90, 10:70])
4-element Vector{UnitRange{Int64}}:
1:20
5:35
50:90
10:70Ekztazy.split_message — Functionsplit_message(text::AbstractString; chunk_limit::UInt=2000,
extrastyles::Vector{Regex}=Vector{Regex}(),
forcesplit::Bool = true) -> Vector{String}Split a message into chunks with at most chunk_limit length, preserving formatting.
The chunk_limit has as default the 2000 character limit of Discord's messages, but can be changed to any nonnegative integer.
Formatting is specified by STYLES) and can be aggregated with the extrastyles argument.
Discord limits messages to 2000, so the code forces split if format breaking cannot be avoided. If desired, however, this behavior can be lifter by setting forcesplit to false.
Examples
julia> split_message("foo")
1-element Vector{String}:
"foo"
julia> split_message(repeat('.', 1995) * "**hello, world**")[2]
"**hello, world**"
julia> split_message("**hello**, *world*", chunk_limit=10)
2-element Vector{String}:
"**hello**,"
"*world*"
julia> split_message("**hello**, _*beautiful* world_", chunk_limit=15)
┌ Warning: message was forced-split to fit the desired chunk length limit 15
└ @ Main REPL[66]:28
3-element Vector{String}:
"**hello**,"
"_*beautiful* wo"
"rld_"
julia> split_message("**hello**, _*beautiful* world_", chunk_limit=15, forcesplit=false)
┌ Warning: message could not be split into chunks smaller than the length limit 15
└ @ Main REPL[66]:32
2-element Vector{String}:
"**hello**,"
"_*beautiful* world_"
julia> split_message("**hello**\n=====\n", chunk_limit=12)
2-element Vector{String}:
"**hello**\n=="
"==="
julia> split_message("**hello**\n≡≡≡≡≡\n", chunk_limit=12, extrastyles = [r"\n≡+\n"])
2-element Vector{String}:
"**hello**"
"≡≡≡≡≡"Ekztazy.plaintext — Functionplaintext(m::Message) -> String
plaintext(c::Client, m::Message) -> StringGet the Message contents with any User mentions replaced with their plaintext. If a Client is provided, DiscordChannels Role are also replaced. However, only channels and roles stored in state are replaced; no API requests are made.
Ekztazy.upload_file — Functionupload_file(c::Client, ch::DiscordChannel, path::AbstractString; kwargs...) -> MessageSend a Message with a file Attachment. Any keywords are passed on to create_message.
Ekztazy.set_game — Functionset_game(
c::Client,
game::AbstractString;
type::Int=AT.GAME,
since::Nullable{Int}=c.presence["since"],
status::Union{PresenceStatus, AbstractString}=c.presence["status"],
afk::Bool=c.presence["afk"],
kwargs...,
) -> BoolShortcut for update_status to set the Client's Activity. Any additional keywords are passed into the activity section.
Ekztazy.opt — FunctionDeprecated, use Option instead
opt(ctx::Context)Helper function that is equivalent to calling extops(ctx.interaction.data.options)
Ekztazy.Option — FunctionOption(; kwargs...) -> ApplicationCommandOptionHelper function that creates an ApplicationCommandOption`
Ekztazy.extops — Functionextops(ops::Vector)Creates a Dict of option name -> option value for the given vector of ApplicationCommandOption. If the option is of Subcommand type, creates a dict for all its subcommands.
Return an empty Dict if the list of options used is missing.
Ekztazy.isme — Functionisme(c::Client, ctx::Context) -> BoolReturns whether the context is a Message Context sent by the bot user.
Ekztazy.method_args — Functionmethod_args(m::Method) -> Vector{Tuple{Symbol, Type}}Ekztazy.add_handler! — Functionadd_handler!(c::Client, handler::Handler)Adds a handler to the client.
add_handler!(c::Client, handler::Handler)Bulk adds handlers to the client.
Ekztazy.Options — FunctionOptions(args...) -> Vector{ApplicationCommandOption}Calls Option on each Vector in the args.
Ekztazy.mention — Functionmention(
o::DiscordObject
)Generates the plaintext mention for a User, a Member, a DiscordChannel, a Role, or a Context
Ekztazy.@fetch — Macro@fetch [functions...] blockWrap all calls to the specified CRUD functions (create, retrieve, update, and delete) with fetch inside a block. If no functions are specified, all CRUD functions are wrapped.
Examples
Wrapping all CRUD functions:
@fetch begin
guild_resp = create(c, Guild; name="foo")
guild_resp.ok || error("Request for new guild failed")
channel_resp = retrieve(c, DiscordChannel, guild_resp.val)
endWrapping only calls to retrieve:
@fetch retrieve begin
resp = retrieve(c, DiscordChannel, 123)
future = create(c, Message, resp.val; content="foo") # Behaves normally.
endEkztazy.@fetchval — MacroEkztazy.@deferred_fetch — Macro@deferred_fetch [functions...] blockIdentical to @fetch, but Futures are not fetched until the end of the block. This is more efficient, but only works when there are no data dependencies in the block.
Examples
This will work:
@deferred_fetch begin
guild_resp = create(c, Guild; name="foo")
channel_resp = retrieve(c, DiscordChannel, 123)
endThis will not, because the second call is dependent on the first value:
@deferred_fetch begin
guild_resp = create(c, Guild; name="foo")
channels_resp = retrieve(c, DiscordChannel, guild_resp.val)
endEkztazy.@deferred_fetchval — Macro@deferred_fetchval [functions...] blockIdentical to @deferred_fetch, but Futures have fetchval called on them instead of fetch.