Rust serenity框架下如何从Discord语音频道获取成员列表?
从Discord语音频道获取成员列表的Rust(serenity框架)实现方案
背景说明
你此前使用Python的discord.py库实现了从Discord语音频道拉取成员的功能,原Python实现代码如下:
# Python def getDiscordUsers(): json = {name: [] for name in names} for i in range(0, 3): channel = bot.get_channel(channels[i]) members = channel.members for member in members: # selfMuted = member.voice.self_mute if member.bot: continue if member.nick == None: json[names[i]].append(member.name) else: json[names[i]].append(member.nick) return json
现在需要在Rust的serenity框架中实现同等功能,以下是完整实现方案:
实现逻辑
和discord.py的逻辑对应,serenity中实现的核心步骤如下:
- 接收上下文
Context和指定的语音频道ID作为入参 - 校验频道类型,确认传入ID对应频道是公会语音频道
- 从频道所属公会中拉取所有语音状态,筛选出当前在目标语音频道的用户
- 过滤机器人账号,优先返回用户公会昵称,无昵称则返回全局用户名
完整可运行代码
use serenity::model::prelude::*; use serenity::prelude::*; use std::error::Error; // 核心方法:传入ctx和语音频道ID,返回该频道内非机器人用户的展示名列表(优先返回昵称) pub async fn get_users_from_voice(ctx: &Context, channel_id: u64) -> Result<Vec<String>, Box<dyn Error>> { let channel = ctx.http.get_channel(channel_id).await?; // 校验频道类型是否为公会语音频道 let guild_channel = match channel { Channel::Guild(chan) => chan, _ => return Err("指定ID不属于公会频道".into()) }; if guild_channel.kind != ChannelType::Voice { return Err("指定频道不是语音频道".into()) } let guild_id = guild_channel.guild_id; // 从缓存拉取公会内所有用户的语音状态 let voice_states = guild_id.voice_states(&ctx.cache).await?; let mut user_names = Vec::new(); for state in voice_states { // 筛选当前在目标语音频道的用户 if state.channel_id != Some(ChannelId::new(channel_id)) { continue; } // 获取成员完整信息 let member = guild_id.member(&ctx.http, state.user_id).await?; // 过滤机器人账号 if member.user.bot { continue; } // 优先取昵称,没有昵称则取用户名 let display_name = member.nick.unwrap_or(member.user.name); user_names.push(display_name); } Ok(user_names) } // 调用示例 pub async fn call_me(ctx: &Context) -> Result<Vec<String>, Box<dyn Error>> { // 替换为你实际的语音频道ID let members = get_users_from_voice(ctx, 123456789012345).await?; // 遍历打印成员名示例 for name in &members { println!("{}", name); } Ok(members) } // 序列化返回JSON示例 async fn some(ctx: &Context) -> Result<serde_json::Value, Box<dyn Error>> { let members = call_me(ctx).await?; Ok(serde_json::json!(members)) }
注意事项
- 必须在Bot初始化时开启
GUILD_VOICE_STATES和GUILD_MEMBERS网关意图,否则无法获取语音状态和成员信息,意图开启示例:
let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_VOICE_STATES | GatewayIntents::GUILD_MEMBERS; let mut client = Client::builder("你的Bot Token", intents) .event_handler(Handler) .await .expect("客户端创建失败");
- 生产环境建议替换所有直接
unwrap()的逻辑为自定义错误处理,避免Bot意外崩溃 - 如果需要实现原Python代码的多频道批量获取功能,只需要传入频道ID和对应名称的列表,循环调用
get_users_from_voice拼接结果即可
内容的提问来源于stack exchange,提问作者alfex4936
相关产品推荐
相关产品推荐

