|
|
|
@ -1,49 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
use poise::serenity_prelude as serenity;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mod commands;
|
|
|
|
mod commands;
|
|
|
|
mod data_loader;
|
|
|
|
mod data_loader;
|
|
|
|
|
|
|
|
|
|
|
|
pub struct Data {} // User data, which is stored and accessible in all command invocations
|
|
|
|
use serenity::async_trait;
|
|
|
|
type Error = Box<dyn std::error::Error + Send + Sync>;
|
|
|
|
use serenity::model::channel::Message;
|
|
|
|
type Context<'a> = poise::Context<'a, Data, Error>;
|
|
|
|
use serenity::model::gateway::Ready;
|
|
|
|
|
|
|
|
use serenity::prelude::*;
|
|
|
|
|
|
|
|
|
|
|
|
/// Displays your or another user's account creation date
|
|
|
|
struct Handler;
|
|
|
|
#[poise::command(slash_command, prefix_command)]
|
|
|
|
|
|
|
|
async fn age(ctx: Context<'_>, #[description = "Selected user"] user: Option<serenity::User>) -> Result<(), Error>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
let u = user.as_ref().unwrap_or_else(|| ctx.author());
|
|
|
|
|
|
|
|
let response = format!("{}'s account was created at {}", u.name, u.created_at());
|
|
|
|
|
|
|
|
ctx.say(response).await?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// A command with two subcommands: `child1` and `child2`
|
|
|
|
#[async_trait]
|
|
|
|
///
|
|
|
|
impl EventHandler for Handler {
|
|
|
|
/// Running this function directly, without any subcommand, is only supported in prefix commands.
|
|
|
|
// Set a handler for the `message` event - so that whenever a new message
|
|
|
|
/// Discord doesn't permit invoking the root command of a slash command if it has subcommands.
|
|
|
|
// is received - the closure (or function) passed will be called.
|
|
|
|
#[poise::command(prefix_command, slash_command, subcommands("child1", "child2"))]
|
|
|
|
//
|
|
|
|
pub async fn parent(ctx: Context<'_>) -> Result<(), Error>
|
|
|
|
// Event handlers are dispatched through a threadpool, and so multiple
|
|
|
|
{
|
|
|
|
// events can be dispatched simultaneously.
|
|
|
|
ctx.say("Hello there!").await?;
|
|
|
|
async fn message(&self, ctx: Context, msg: Message) {
|
|
|
|
Ok(())
|
|
|
|
if msg.content == "!ping" {
|
|
|
|
|
|
|
|
// Sending a message can fail, due to a network error, an
|
|
|
|
|
|
|
|
// authentication error, or lack of permissions to post in the
|
|
|
|
|
|
|
|
// channel, so log to stdout when some error happens, with a
|
|
|
|
|
|
|
|
// description of it.
|
|
|
|
|
|
|
|
if let Err(why) = msg.channel_id.say(&ctx.http, "Pong!").await {
|
|
|
|
|
|
|
|
println!("Error sending message: {:?}", why);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// A subcommand of `parent`
|
|
|
|
|
|
|
|
#[poise::command(prefix_command, slash_command)]
|
|
|
|
|
|
|
|
pub async fn child1(ctx: Context<'_>) -> Result<(), Error>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
ctx.say("You invoked the first child command!").await?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Another subcommand of `parent`
|
|
|
|
// Set a handler to be called on the `ready` event. This is called when a
|
|
|
|
#[poise::command(prefix_command, slash_command)]
|
|
|
|
// shard is booted, and a READY payload is sent by Discord. This payload
|
|
|
|
pub async fn child2(ctx: Context<'_>) -> Result<(), Error>
|
|
|
|
// contains data like the current user's guild Ids, current user data,
|
|
|
|
{
|
|
|
|
// private channels, and more.
|
|
|
|
ctx.say("You invoked the second child command!").await?;
|
|
|
|
//
|
|
|
|
Ok(())
|
|
|
|
// In this case, just print what the current user's username is.
|
|
|
|
|
|
|
|
async fn ready(&self, _: Context, ready: Ready) {
|
|
|
|
|
|
|
|
println!("{} is connected!", ready.user.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
#[tokio::main]
|
|
|
|
async fn main()
|
|
|
|
async fn main()
|
|
|
|
@ -56,21 +52,22 @@ async fn main()
|
|
|
|
|
|
|
|
|
|
|
|
println!("Connecting...");
|
|
|
|
println!("Connecting...");
|
|
|
|
|
|
|
|
|
|
|
|
let framework = poise::Framework::builder()
|
|
|
|
let intents = GatewayIntents::GUILD_MESSAGES
|
|
|
|
.options(poise::FrameworkOptions {
|
|
|
|
| GatewayIntents::DIRECT_MESSAGES
|
|
|
|
commands: vec![age(), parent()],
|
|
|
|
| GatewayIntents::MESSAGE_CONTENT;
|
|
|
|
..Default::default()
|
|
|
|
|
|
|
|
})
|
|
|
|
// Create a new instance of the Client, logging in as a bot. This will
|
|
|
|
.token(token)
|
|
|
|
// automatically prepend your bot token with "Bot ", which is a requirement
|
|
|
|
.intents(serenity::GatewayIntents::non_privileged())
|
|
|
|
// by Discord for bot users.
|
|
|
|
.setup(|ctx, _ready, framework|
|
|
|
|
let mut client = Client::builder(&token, intents).event_handler(Handler).await.expect("Err creating client");
|
|
|
|
{
|
|
|
|
|
|
|
|
Box::pin(async move
|
|
|
|
// Finally, start a single shard, and start listening to events.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Shards will automatically attempt to reconnect, and will perform
|
|
|
|
|
|
|
|
// exponential backoff until it reconnects.
|
|
|
|
|
|
|
|
if let Err(why) = client.start().await
|
|
|
|
{
|
|
|
|
{
|
|
|
|
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
|
|
|
|
println!("Client error: {:?}", why);
|
|
|
|
Ok(Data {})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
framework.run().await.unwrap();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|