serenity-rs / poise

Discord bot command framework for serenity, with advanced features like edit tracking and flexible argument parsing

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Context doesn't have Guild but command can only be run in Guild

Rushmore75 opened this issue · comments

Using this command code:

#[poise::command(slash_command, rename = "index", guild_only)]
pub async fn index(ctx: Context<'_>) -> Result<(), Error> {
    if let Some(guild) = ctx.guild() {
        guild.channels.iter().for_each(|(_id, channel)| {
            println!("{} {:?} {:?}",
                channel.name,
                channel.kind,
                channel.message_count,
            );
        });
    }
    Ok(())
}

But when this code is executed it just jumps at the if let Some statement to the end of the function meaning that ctx.guild() is empty?

Probably user error but it's confusing with the ctx.guild() documentation saying

Return the guild of this context, if we are inside a guild

And with the macro having guild_only I would assume that I would have access to the guild in this function's context 🤷

I wrote some more "testing" code inside the function:

println!("ID {:?}", ctx.guild_id().is_some());
println!("Channel {:?}", ctx.guild_channel().await.is_some());
println!("Guild {:?}", ctx.guild().is_some());

Which returns:

ID true
Channel true
Guild false

But all the documentation is the same:

Return the X of this context, if we are in a guild.

Looks as though it looks in the cache then never makes an http request if there is a miss

#[cfg(feature = "cache")]
    (guild self)
    (pub fn guild(self) -> Option<serenity::GuildRef<'a>>) {
        self.guild_id()?.to_guild_cached(self.serenity_context())
    }

Whereas, something like partial guild makes a request on cache miss:

    #[inline]
    pub async fn to_partial_guild(self, cache_http: impl CacheHttp) -> Result<PartialGuild> {
        #[cfg(feature = "cache")]
        {
            if let Some(cache) = cache_http.cache() {
                if let Some(guild) = cache.guild(self) {
                    return Ok(guild.clone().into());
                }
            }
        }

        cache_http.http().get_guild(self).await
    }
    ```

You cannot receive a Guild object over Http, only over the gateway.

If the guild is not present in your cache its because of one of these reasons:

  • The bot has just started and the guild is not cached yet, this can take a while depending on how many guilds and shards you have.
  • You do not have the GUILDS intent enabled, and thus do not receive the guild over the gateway.
  • The guild is unavailable or has not been sent for other reasons to do with Discord's api.

noted