Git Product home page Git Product logo

poise's People

Contributors

arqunis avatar bloectasy avatar buymymojo avatar c-git avatar chargedbyte avatar emilyyyylime avatar ev3nvy avatar fee1-dead avatar gnomeddev avatar jamesbt365 avatar jellywx avatar kangalio avatar keiveulbugs avatar mattfbacon avatar mrnossiom avatar nickelc avatar nilstrieb avatar noituri avatar notnorom avatar overzealouslotus avatar peanutbother avatar s0lst1ce avatar sadorowo avatar seraxis avatar snowsee avatar spacerulerwill avatar vicky5124 avatar vidhanio avatar whitbur avatar wilt00 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

poise's Issues

ThreadUpdate event?

I used to use serenity's thread_update function in the event handler struct for this purpose. I tried using the ChannelUpdate event for this, but it seems to not be called for threads.

Unexpected token `include_str`

Hey so I just updated my packages and poise updated as well. However, now that I've done that, whenever I try and run the bot the following error comes up and stops it from running...

error: unexpected token: `include_str`
 --> /Users/user/.cargo/git/checkouts/poise-2ca7e75d46548da7/435cf20/src/lib.rs:1:10
  |
1 | #![doc = include_str!("../README.md")]
  |          ^^^^^^^^^^^

error: aborting due to previous error

error: could not compile `poise`

Any help would be greatly appreciated. Thanks!

Only prefix commands show up in help menu

If a context menu command is registered, it will not show up in help, even if it's also allowed to run as a slash or prefix command, though, that should probably not matter and show up anyway.

/// Test
#[poise::command(context_menu_command = "Test", slash_command, prefix_command)]
pub async fn test(
    ctx: Context<'_>,
    #[description = "test"] _user: User,
) -> CommandResult {
    Ok(())
}
Commands:
  /help        Show this menu
  
Test bottom text

Running /help test doesn't work either, saying "No such command test"

`defer_response` causes chained methods of `CreateReply` to be ignored.

Current behaviour: When the command has defer_response enabled, chained methods such as .components(), ephemeral(true), etc get ignored when using slash commands but work fine when using prefix commands.

Expected behaviour: Chained methods of CreateReply such as .components() and .ephemeral() should not be ignored and work as they do when defer_response is disabled.

Example code

poise::send_reply(ctx, |message| {
    message
        .embed(|embed| {
            // ... create the embed
            embed
        })
        .components(|components| { // components are not shown with defer_response enabled
            debug!("Creating components..."); // this does get executed
            // ... create components
        })
        .ephemeral(true) // this gets ignored when defer_response is enabled
})
.await?;

Demonstration

Adding a License

Because of the situation I'm working in, a library not having a LICENSE generally stokes concerns over whether or not it's fair game to use (since we're developing in a professional context).

So adding a LICENSE file would probably be helpful.

Slash commands only available to administrators

It seems like the slash commands I created are only available on users who have the administrator permission. For someone with no special permissions, the command list appears empty when starting to type the slash commands with /. The prefix based commands work fine though. It is also not a permissioning problem regarding slash commands in general, as another bot's slash commands are still accessible. Context menu commands also seem to work.

Prefix commands aren't recognised at all

After updating Poise and Serenity to their latest versions (using #60 for now, but I doubt that's the culprit) I've found that the bot doesn't recognise any prefix commands.

The prefix is set using the PrefixFrameworkOptions, and is set to -. I'm testing it on Linux x64. If you need any more information please let me know, but I'm hoping this will be easily reproducible.

I'm raising this issue here instead of with Serenity because if I'm not mistaken, Poise is doing the parsing. If I'm wrong or it's my fault in some way, please let me know.

How to create long-standing component interactions?

Is there a pattern for creating long-standing component interactions that will persist across instances of the bot?

The only example I can find of component interactions is this one. Unless I'm quite mistaken, because it awaits interactions in the command handler, if the bot is subsequently restarted the buttons will stop doing anything.

Please add documentation on how subcommands work

It appears that subcommands (specifically for slash commands, using the command macro in my case) are somehow implemented, but the only times I can see them mentioned in the documentation (on the page for the command macro and the page for the Command struct, and not how to use them.

I can infer from compiler error messages that when specified in the command macro, subcommands should be the name of another function, and have worked out that:

  • As far as I can tell, it doesn't matter what you put into the parent command function, as long as it accepts the required Context parameter and returns the Result that is expected by the macro. It doesn't appear the parent command ever gets run by running a subcommand, it seems to just be there as a placeholder.
  • Only the parent command should be in the list of commands to be registered, but the parent command function itself is not registered.
  • The subcommand function must also be annotated with slash_command.

Assuming these are accurate (which it's entirely possible that they're not), having these things shown in documentation, or even an example, would be great.

Or, is there a more idiomatic way to do this? Documenting that would also be really nice to have.

Here's my code that seems to work as expected:

#[poise::command(
    slash_command,
    subcommands("create"),
)]
async fn class(
    context: Context<'_>,
) -> Result<(), Error> {
    println!("parent command");
    Ok(())
}

#[poise::command(slash_command)]
async fn create(
    context: Context<'_>,
    text: String,
) -> Result<(), Error> {
    println!("test");
    Ok(())
}

Edit: I just found examples/framework_usage/commands/subcommand.rs. Still, a link to this example on the command macro doc page would be greatly appreciated, as well as links to the other similar examples by their relevant documentation. (You always seem to figure stuff out right after you ask for help, don't you?)

owners including users not specified in options is surprising (and feature request to be able to change behavior)

The docs on owners i can find are

https://kangalioo.github.io/poise/master/poise/attr.command.html
owners_only: Restricts command callers to the list of owners specified in framework options

https://kangalioo.github.io/poise/master/poise/struct.FrameworkOptions.html#structfield.owners
User IDs which are allowed to use owners_only commands

I think in both of these places it would probably be good to mention it adds the user that created the bot if it's not in owners already.

It would also be nice to have the option to disable that functionality.
https://kangalioo.github.io/poise/master/src/poise/framework/builder.rs.html#164

Message command context

Hello, I was scheduled these days and something came to my mind that I believe would be a good addition

A way to have a struct that is initially defined in the before command and goes through all the states, the command check, the command itself and the after command

Something similar to how the bot's global data is set

https://github.com/kangalioo/poise/blob/0fc5d548e32fc7e3c8ea490afe95db00ec17ec24/examples/framework_usage/main.rs#L142-L148

So something like that would be in place of the current pre command

https://github.com/kangalioo/poise/blob/0fc5d548e32fc7e3c8ea490afe95db00ec17ec24/examples/framework_usage/main.rs#L117-L121

I believe that there would have to be a change in how the command context is currently defined, to have the definition of the type that would transit between the command states

https://github.com/kangalioo/poise/blob/0fc5d548e32fc7e3c8ea490afe95db00ec17ec24/examples/framework_usage/main.rs#L13

Allow automatic registration of guild-specific commands

This is a pretty useful thing to have for developing a bot. If it exists in this library, I haven't found it. The main crate doc page mentions the differences between local and global commands, but I haven't found a way to register guild-specific commands other than manually going through the register_application_commands_buttons() dialog.

Please let me know if I'm missing something or misunderstanding this.

Thanks!

Allow commands to have multiple checks

Currently the checks field accepts a string with the name of the function to act as a check. This does not presently allow for multiple checks to be implemented.

None of the commands specified work, `Ready` shows the server I am testing in is "Unavailable"

That is about it, the Ready value in user_data_setup which I presume could be used for a ready function to report that the bot has logged in, has the guild I am testing in reported as unavailable like this:

guilds: [UnavailableGuild { id: GuildId(<The id for the guild>), unavailable: true }]

With the serenity standard framework this worked fine. Also it is not only slash commands that do not work, I can not use the register provided by examples or help.

`FrameworkBuilder` can't return the built `Framework` without starting it

What
The current builder for the framework doesn't provide a method to get the framework without running it.
I believe a finish() (or another name like framework()) method would be useful.

Why
The example from the README proposes (more or less) this code:

#[tokio::main]
async fn main() {
    poise::Framework::build()
        .token(std::env::var("DISCORD_BOT_TOKEN").unwrap())
        .user_data_setup(move |_ctx, _ready, _framework| {
            Box::pin(async move {
                Ok(())
            })
        })
        .options(poise::FrameworkOptions {
            // configure framework here
            prefix_options: PrefixFrameworkOptions {
                prefix: Some(":t".into()),
                ..Default::default()
            },
            ..Default::default()
        })
        .run()
        .await
        .unwrap();
}

This works fine but provides no control over the Framework instance which can't even be accessed within main. This becomes an issue when you want to have some external control on the state of the framework (running or not). For example if you want to gracefully shutdown the shards when quitting by reacting to an INTERRUPT signal. For the intent of making this example clearer the following is code I'd like to be able to write:

#[tokio::main]
async fn main() {
    let framework = poise::build()
    .token(std::env::var("DISCORD_BOT_TOKEN").unwrap())
    .user_data_setup(move |_ctx, _ready, _framework| {
        Box::pin(async move {
            Ok(())
        })
    })
    .options(poise::FrameworkOptions {
        // configure framework here
        prefix_options: PrefixFrameworkOptions {
            prefix: Some(":t".into()),
            ..Default::default()
        },
        ..Default::default()
    })
    .finish(); // <-- the method I'd like

    tokio::spawn(async move {
        tokio::signal::ctrl_c()
            .await
            .expect("Could not register ctrl+c handler");
        framework.shard_manager().lock().await.shutdown_all().await; // uses framework
    });

    if let Err(why) = framework.start().await { // uses framework
        error!("Client error: {:?}", why);
    }
}

Hopefully this clarifies the case for such a method. If I missed something and this can already be done please point me to it. Otherwise I can try to whip a PR for this.

Porting serenity's command framework example

The serenity repo has a very extensive example for their command framework. The later not only makes use of many of the framework's features but also gives many hints as to what is what and how to use the features.

I know poise is still far from done but I'm thinking trying to port this example may help drive it forward and improve user adoption. This would also alleviate the sometimes lacking documentation.

Accessing message attachments from a command

Is it possible to access message attachments from within a command (using PoiseContext)?

I took a look through the available API and didn't see anything, but perhaps I missed something.

Event handler mutable

Hello good night, could you help me? I'm trying to use the event handler but for some functions for example add role I need the new member to be mutable, but from what I noticed the event cannot be mutable, would you have any solution?

temporary solution:

Event::GuildMemberAddition { new_member } => {
    let roles = new_member.guild_id.roles(ctx).await.map_app_err()?;

    let role = roles.iter().find(|x| x.1.name == "alguma coisa");
    let role = role.unwrap();

    let mut member = new_member.clone();

    member.add_role(ctx, role.0).await.map_app_err()?;
}

`once_cell` Build Error

In updating my bot to the latest versions of dependencies, I encountered a build error with Poise:

error[E0433]: failed to resolve: could not find `sync` in `once_cell`
  --> C:\Users\Zacc\.cargo\git\checkouts\poise-2ca7e75d46548da7\e94eb68\src\framework\mod.rs:14:27
   |
14 |     user_data: once_cell::sync::OnceCell<U>,
   |                           ^^^^ could not find `sync` in `once_cell`

error[E0433]: failed to resolve: could not find `sync` in `once_cell`
  --> C:\Users\Zacc\.cargo\git\checkouts\poise-2ca7e75d46548da7\e94eb68\src\framework\mod.rs:76:41
   |
76 |             user_data: once_cell::sync::OnceCell::new(),
   |                                         ^^^^^^^^ not found in `once_cell::sync`
   |
help: consider importing one of these items
   |
6  | use core::lazy::OnceCell;
   |
6  | use once_cell::unsync::OnceCell;
   |
6  | use std::lazy::OnceCell;
   |
6  | use tokio::sync::OnceCell;
   |

I'm almost certain it's because of commit 9243918, which removed the default features for dependencies and therefore removed the std feature in once_cell.

I've tested this in a blank new project and the sync module is not available without the std feature.

Thank you for your work on this framework.

Allow autocompletion callback for whole command

First of, the existing API for auto completion is incredible, thank you so much for that ❤️. While implementing a command with a parameter that can be auto-filled either with values based on the current user or filled with values based on a member supplied in an extra parameter, I thought it would be great if I could access this member parameter in the auto complete function.
As far as I understand the discord documentation, in the auto complete event, everything is sent, not just the current/focused parameter. It would be great if the framework could take advantage of that maybe with an autocomplete function for the whole command instead of functions for each parameter.

Required feature flags for example are badly documented

Running the example seems to fail:

error[E0433]: failed to resolve: could not find `CollectComponentInteraction` in `serenity`
   --> examples/framework_usage/commands.rs:113:37
    |
113 |     while let Some(mci) = serenity::CollectComponentInteraction::new(ctx.discord())
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ could not find `CollectComponentInteraction` in `serenity`

For more information about this error, try `rustc --explain E0433`.
error: could not compile `poise` due to previous error```

Using custom event handling

Adding the custom event handler itself seems to work fine, but the problem arises when I need to use some of the values in the Data struct. Namely a connection to a database. I need the connection to the database to be available for both commands and said interactions, and with using serenity's TypeMap for storing it would mean I would need to store it 2 times. Is there any other way to do this?

[Feature Request] bot_required_permissions in `poise::command`

Summary

This would allow definition of the permissions the bot user must have for a command to execute, if not met, pass an error to on_error.

Usecase

In order to reduce 403s in the command body, or repeated code to handle checking permissions and displaying friendly errors, it would allow the user to centralize it in on_error. I personally use discord.py's @commands.bot_required_permissions extensively to define basic permissions such as send_messages, embed_links, or similar.

macro to quickly add commands as-is

What do you think about introducing a macro like the following:

macro_rules! add_commands {
    ($framework_builder:ident, $($command:path),*) => {{
        $($framework_builder = $framework_builder.command($command(), |f| f);)*
        $framework_builder
    }};
}

This would allow one to do:

let mut framework_builder = poise::Framework::build();
framework_builder =  add_commands!(
        framework_builder,
        help,
        register,
        command1,
        command2
    );
let framework = framework_builder.build().await.unwrap();

This is what I currently do with my bot to cut down on the number of .command(command1, |f| f) calls. This would fit well alongside the already existing builtins I think.

Quickstart crashes on runtime / cannot use commands

I get this error when I try to run the Quickstart (I've already setted the env variable)

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Gateway(DisallowedGatewayIntents)', src\main.rs:43:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\learn_rust.exe` (exit code: 101)

Re-think command storage to associate different implementations of same command with each other

This issue is a continuation of the discussion in #19.

Problem

Poise currently generates multiple command objects per function, corresponding to each command type (prefix, slash, context menu). These command objects are stored completely separate from each other in PrefixFrameworkOptions and ApplicationFrameworkOptions respectively.

This makes it hard to tell which command invocations belong to the same command at runtime, which is needed for many things:

  • a dashboard for the bot to enable or disable commands: you need to know which command entry in the dashboard a command invocation belongs to (this was the motivator for #19)
  • help command: to display both slash commands and prefix commands in the help menu (#13), there needs to be a way to avoid displaying commands twice if they have both a prefix and a slash implementation
  • command cooldowns (#1): cooldowns should apply across invocation types

In #19 we discussed several ideas to redesign how commands are stored in order to fix the issues. But after thinking about each of them and starting to implement a couple in feature branches, none of them seemed great.

I'm currently relatively demotivated to work on this issue because to me it feels like no good solution is in sight. This issue functions as a reminder/placeholder for now, or as a place of discussion for ideas for solutions

Clippy lint `clippy::str_to_string` fails on generated commands with `String` arguments

I run a fairly extensive set of lints on my projects. Since updating Poise from 2746481 to 6010651, I've found that the lint clippy::str_to_string warns for commands that have String arguments.

#![warn(clippy::str_to_string)]

#[command(prefix_command)]
pub async fn some_command(
	ctx: PoiseContext<'_>,
	#[rest]
	#[description = "Some description."]
	command: String,
) -> Result<(), Error> {
	Ok(())
}

Warns with the following error:

warning: `to_string()` called on a `&str`
  --> src\commands\mod.rs:40:1
   |
40 | #[command(prefix_command)]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = help: consider using `.to_owned()`
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string
   = note: this warning originates in the macro `$crate::_parse_prefix` (in Nightly builds, run with -Z macro-backtrace for more info)

It seems to only be with prefix_command, not slash_command. Not a huge deal at all, but I thought I'd mention it.

Add serenity crash course to docs

I'm trying to send a DM to a user provided in a command but user.create_dm_channel(); and user.direct_message(); both require a CacheHttp object. Looking through the docs and the examples I don't see any mention of this.

Could you add some examples on how to use those functions in the docs and in this issue for me too please.

Add `CreateReply::set_embed` API

Serenity's CreateMessage struct has the set_embed(embed: CreateEmbed) API when poise only has embed(embed: &mut CreateEmbed). While taking a mutable reference can be useful it also causes some lifetime issues. Consider the following code:

pub type Context<'a> = poise::Context<'a, GlobalData, BotError>;
fn some_func(ctx: Context<'_>) {
   //embed is bound to the scope of the function
    let mut embed = CreateEmbed::default();
    // but we make a ref out of it
    ctx.send(|r| r.embed(|e| &mut embed)).await;
    //then we want to send it again
    ctx.send(|r| r.embed(|e| &mut embed)).await;

As you can see this doesn't work because embed doesn't live long enough since it's bound to the scope's lifetime (not sure about the wording, I'm still pretty new to lifetimes ^^). Of course I could just move the entire embed creation process within the closure but that can be hard to follow and more importantly it means I can't just clone() the CreateEmbed if I want to send it again!
If I'm not just missing something I'd like there to be a set_embed API that takes an owned CreateEmbed.

custom_data field for Commands

Currently, Commands are relatively limited in the amount of metadata you can provide to them.
There's the help-fields and the category, but both of those have specific usecases and are limited in what they can and should store.
It would be useful to be able to store arbitrary additional information together with the command declaration, thus allowing users of poise to implement their own system for keeping track of things such as specific permission requirements, additional help-data (i.e. usage examples, etc) and many other things.

After a short discussion of this in the serenity discord server, we came to the conclusion that it'd make sense to provide a custom_data field in the poise::command macro, which could store any user-provided struct together with the command, via a Box<dyn Any>.

I.e.:

#[poise::command(
  slash_command,
  custom_data=r#"CmdData { perm_level: PermissionLevel::Helpers, example: "/mute someguy 10m" }"#
)]
pub async fn mute(...) -> Result<()> {
...
}

Allow specifying subcommands via the poise::command macro

Currently, specifying subcommands requires you to manually insert them into the Command struct, commonly done via

Command {
  subcommands: vec![a(), b(), c()],
  ..foo()
}

which is quite cumbersome, especially if you're splitting up your commands into separate modules.

To improve this, I'd propose adding a subcommands attribute to the poise::command macro, which would allow specifying subcommands on the parent command like this:

#[poise::command(
  slash_command,
  subcommands(a, b, c)
]
pub fn foo(_: Context<'_>) -> Result<(), Error> {
  Ok(())
}

Help needed/Problem with registering songbird as VoiceGatewayManager

I'm certain that this problem is because of my lack of understanding rust that's why I'm sry for being so impudent to open an issue.

I wanted to use Songbird alongside poise to handle voice for discord, but Songbird needs to be registered at startup as VoiceGatewayManager which is done with ClientBuilder#voice_manager_arc. The method expects a struct with poise::serenity_prelude::VoiceGatewayManager implemented but Songbird doesn't use the re-exports and implements serenity::client::bridge::voice::VoiceGatewayManager. I also had to enable the feature voice for serenity in poise to be able to use ClientBuilder#voice_manager_arc.

Is there a simple way to tell the compiler that poise::serenity_prelude::VoiceGatewayManager and serenity::client::bridge::voice::VoiceGatewayManager are the same?

Provide some way to set default values for modals

According to the docs, discord allows you to set a default value for modal interaction fields.
It would be nice if these where supported dynamically in some way -- although I'm not sure how that'd look.
I think one way to structure that API would be to make the Modal derive-macro generate a second struct <name>DefaultValues,
which could contain fields for each field in the original modal that has been annotated with #[has_default]. Then you could provide an instance of that DefaultValues-struct when executing the modal interaction.

Alternatively, the macro could generate a builder struct that requires the defaults to be provided via functions, I guess

Has `add_string_choice` support been implemented?

Looking through the code, it doesn't seem like support for add_string_choice has been implemented. Is this correct or have I missed it? I'd like to give users choices when entering slash commands.

Use `log` or `tracing` crate instead of `println!` and `eprintln!`

I've noticed that poise uses println! as well as eprintln!.
This is bad, because this can't make use of a log backend like env_logger which formats logs in a nice way. This might lead to cases where a warning is missed, because it is just plain text and can't be distinguished from other (non warning) logs. E.g. I've just had a hard time finding this warning: https://github.com/kangalioo/poise/blob/3ad61d4d1c51334b33a6bc362b129fb0e70ea514/src/framework/mod.rs#L287

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.