fix: several improvements
This commit is contained in:
parent
50202dfdf5
commit
2c82dbb019
10 changed files with 384 additions and 269 deletions
|
@ -1,20 +1,21 @@
|
|||
use chrono::Local;
|
||||
use serenity::all::{CommandInteraction, Context};
|
||||
use serenity::builder::{CreateCommand, CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter};
|
||||
use serenity::builder::{CreateCommand, CreateEmbed};
|
||||
|
||||
use crate::util::embed::Embed;
|
||||
|
||||
pub async fn run(_ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
||||
let username = command.user.name.as_str();
|
||||
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
||||
CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.description("Botendo v7\ndeveloped by [moonleay](https://moonleay.net)\n\nCheck out the repository: https://git.moonleay.net/DiscordBots/Rustendo")
|
||||
.footer(CreateEmbedFooter::new(format!(">{} | {}", current_time, username)))
|
||||
}
|
||||
|
||||
Embed::create(
|
||||
username,
|
||||
"",
|
||||
"Botendo v7\ndeveloped by [moonleay](https://moonleay.net)\n\nCheck out the repository: https://git.moonleay.net/DiscordBots/Rustendo",
|
||||
)
|
||||
}
|
||||
|
||||
pub fn register() -> CreateCommand {
|
||||
CreateCommand::new("info").description("Infos about the bot")
|
||||
}
|
||||
|
||||
// >18/02/2024 @ 19:01:59 - bartlo
|
||||
// >2024-02-19 17:58:39 | moonleay
|
||||
// >2024-02-19 17:58:39 | moonleay
|
||||
|
|
|
@ -1,93 +1,104 @@
|
|||
use chrono::Local;
|
||||
use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction, Context, ResolvedOption, ResolvedValue};
|
||||
use serenity::builder::{CreateCommand, CreateCommandOption, CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter};
|
||||
use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction, Context};
|
||||
use serenity::builder::{CreateCommand, CreateCommandOption, CreateEmbed};
|
||||
use serenity::model::application::CommandOptionType;
|
||||
|
||||
use crate::util::user_util;
|
||||
use crate::util::embed::Embed;
|
||||
use crate::util::user_util::{self, get_guild};
|
||||
|
||||
pub async fn run(ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
||||
let username = command.user.name.as_str();
|
||||
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
||||
let options = &command.data.options;
|
||||
|
||||
let query = if let Some(CommandDataOption {
|
||||
value: CommandDataOptionValue::String(query), ..
|
||||
}) = &options.first()
|
||||
{
|
||||
query
|
||||
} else {
|
||||
return CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("Error 400")
|
||||
.description("There is no query provied.")
|
||||
.footer(CreateEmbedFooter::new(format!(">{} | {}", current_time, username)))
|
||||
};
|
||||
let query = command.data.options.first().and_then(|option| {
|
||||
if let CommandDataOptionValue::String(query) = &option.value {
|
||||
Some(query)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
if query.is_none() {
|
||||
return Embed::create(username, "Error 400", "There is no query provided");
|
||||
}
|
||||
|
||||
let guild_id = match &command.guild_id {
|
||||
Some(guild_id) => guild_id,
|
||||
None => {
|
||||
return CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("GuildId not found")
|
||||
.description("Could not find guild id.")
|
||||
.footer(CreateEmbedFooter::new(format!("> {} | {}", current_time, username)));
|
||||
return Embed::create(username, "GuildId not found", "Could not find guild id.");
|
||||
}
|
||||
};
|
||||
|
||||
let (guild_id, channel_id) = {
|
||||
let guild = &ctx.cache.guild(guild_id).unwrap(); // TODO: This unwrap throws errors.
|
||||
// This may be unsafe, idk not sure yet
|
||||
let channel_id = guild
|
||||
.voice_states
|
||||
.get(&command.user.id)
|
||||
.and_then(|voice_state| voice_state.channel_id);
|
||||
(guild.id, channel_id)
|
||||
let guild = get_guild(ctx, guild_id);
|
||||
|
||||
match guild {
|
||||
Some(guild) => {
|
||||
let channel_id = guild
|
||||
.voice_states
|
||||
.get(&command.user.id)
|
||||
.and_then(|voice_state| voice_state.channel_id);
|
||||
|
||||
(guild.id, channel_id)
|
||||
}
|
||||
None => {
|
||||
return Embed::create(username, "Guild not found", "Could not find guild.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let connect_to = match channel_id {
|
||||
Some(channel) => channel,
|
||||
None => {
|
||||
return CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("You are not in a VC.")
|
||||
.description("Join one to start playing music.")
|
||||
.footer(CreateEmbedFooter::new(format!("> {} | {}", current_time, username)));
|
||||
},
|
||||
return Embed::create(
|
||||
username,
|
||||
"You are not in a VC.",
|
||||
"Join one to start playing music.",
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let manager = &songbird::get(ctx)
|
||||
.await
|
||||
.expect("Cannot get Songbird.")
|
||||
.clone();
|
||||
|
||||
if !user_util::is_self_connected_to_vc(&ctx, &guild_id) {
|
||||
if !user_util::is_self_connected_to_vc(ctx, &guild_id) {
|
||||
// self is connected to vc, check if user is in same vc
|
||||
let self_channel = user_util::get_self_vc_id(&ctx, &guild_id);
|
||||
let self_channel = user_util::get_self_vc_id(ctx, &guild_id);
|
||||
|
||||
if self_channel.is_none() {
|
||||
return Embed::create(
|
||||
username,
|
||||
"I am not in a VC.",
|
||||
"Connect me to a VC to start playing music.",
|
||||
);
|
||||
}
|
||||
|
||||
let self_channel = self_channel.unwrap();
|
||||
|
||||
// Check if user is in the same VC as the bot
|
||||
if self_channel != connect_to {
|
||||
return CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("You are not in my VC.")
|
||||
.description("Connect to my VC to control the music.")
|
||||
.footer(CreateEmbedFooter::new(format!("> {} | {}", current_time, username)));
|
||||
return Embed::create(
|
||||
username,
|
||||
"You are not in my VC.",
|
||||
"Connect to my VC to control the music.",
|
||||
);
|
||||
}
|
||||
// Connect to VC
|
||||
manager.join(guild_id, connect_to).await.expect("Cannot connect>...");
|
||||
manager
|
||||
.join(guild_id, connect_to)
|
||||
.await
|
||||
.expect("Cannot connect>...");
|
||||
}
|
||||
|
||||
CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("Searching...")
|
||||
.description(format!("Looking for {}", query))
|
||||
.footer(CreateEmbedFooter::new(format!(">{} | {}", current_time, username)))
|
||||
}
|
||||
|
||||
Embed::create(username, "Searching...", format!("Looking for {}", query))
|
||||
}
|
||||
|
||||
pub fn register() -> CreateCommand {
|
||||
CreateCommand::new("play")
|
||||
.description("Play music")
|
||||
.add_option(
|
||||
CreateCommandOption::new(CommandOptionType::String, "query", "Link or search term")
|
||||
.required(true)
|
||||
.required(true),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,60 +1,52 @@
|
|||
use chrono::Local;
|
||||
use serenity::all::{CommandInteraction, Context};
|
||||
use serenity::builder::{CreateCommand, CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter};
|
||||
use serenity::builder::{CreateCommand, CreateEmbed};
|
||||
|
||||
use crate::util::embed::Embed;
|
||||
use crate::util::user_util;
|
||||
|
||||
pub async fn run(ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
||||
let username = command.user.name.as_str();
|
||||
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
||||
|
||||
let guild_id = match &command.guild_id {
|
||||
Some(guild_id) => guild_id,
|
||||
None => {
|
||||
return CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("GuildId not found")
|
||||
.description("Could not find guild id.")
|
||||
.footer(CreateEmbedFooter::new(format!("> {} | {}", current_time, username)));
|
||||
return Embed::create(username, "GuildId not found", "Could not find guild id.");
|
||||
}
|
||||
};
|
||||
|
||||
if !user_util::is_self_connected_to_vc(&ctx, guild_id) {
|
||||
if !user_util::is_self_connected_to_vc(ctx, guild_id) {
|
||||
// Bot is not connectd to vc; no need to dc
|
||||
return CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("Bot is not connected")
|
||||
.description("And therefore I cannot stop playing.")
|
||||
.footer(CreateEmbedFooter::new(format!("> {} | {}", current_time, username)));
|
||||
return Embed::create(
|
||||
username,
|
||||
"Bot is not connected",
|
||||
"And therefore I cannot stop playing.",
|
||||
);
|
||||
}
|
||||
|
||||
let manager = songbird::get(&ctx)
|
||||
let manager = songbird::get(ctx)
|
||||
.await
|
||||
.expect("Cannot get Songbird")
|
||||
.clone();
|
||||
|
||||
let has_handler = manager.get(guild_id.clone()).is_some();
|
||||
let has_handler = manager.get(*guild_id).is_some();
|
||||
|
||||
if has_handler {
|
||||
if let Err(e) = manager.remove(guild_id.clone()).await {
|
||||
return CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("There was an error")
|
||||
.description(format!("Failed: {:?}", e))
|
||||
.footer(CreateEmbedFooter::new(format!("> {} | {}", current_time, username)));
|
||||
if let Err(e) = manager.remove(*guild_id).await {
|
||||
return Embed::create(username, "There was an error", format!("Failed: {:?}", e));
|
||||
}
|
||||
return CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("I stopped and left\nJust like your girlfriend.")
|
||||
.footer(CreateEmbedFooter::new(format!(">{} | {}", current_time, username)))
|
||||
return Embed::create(
|
||||
username,
|
||||
"I stopped and left\nJust like your girlfriend.",
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("Bot is not connected")
|
||||
.description("And therefore I cannot stop playing.\nSomething happend, which shouldn't have.")
|
||||
.footer(CreateEmbedFooter::new(format!("> {} | {}", current_time, username)))
|
||||
}
|
||||
|
||||
Embed::create(
|
||||
username,
|
||||
"Bot is not connected",
|
||||
"And therefore I cannot stop playing.\nSomething happend, which shouldn't have.",
|
||||
)
|
||||
}
|
||||
|
||||
pub fn register() -> CreateCommand {
|
||||
CreateCommand::new("stop").description("Stop playing and start leavin'")
|
||||
|
|
24
src/main.rs
24
src/main.rs
|
@ -2,18 +2,14 @@ mod commands;
|
|||
mod handler;
|
||||
mod util;
|
||||
|
||||
use chrono::Local;
|
||||
use serenity::all::{CommandInteraction, OnlineStatus};
|
||||
use serenity::async_trait;
|
||||
use serenity::builder::{
|
||||
CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter, CreateInteractionResponse,
|
||||
CreateInteractionResponseMessage,
|
||||
};
|
||||
use serenity::builder::{CreateEmbed, CreateInteractionResponse, CreateInteractionResponseMessage};
|
||||
use serenity::gateway::ActivityData;
|
||||
use serenity::model::application::{Command, Interaction};
|
||||
use serenity::model::gateway::Ready;
|
||||
use serenity::prelude::*;
|
||||
use util::config;
|
||||
use util::{config, error::Embed};
|
||||
|
||||
// This trait adds the `register_songbird` and `register_songbird_with` methods
|
||||
// to the client builder below, making it easy to install this voice client.
|
||||
|
@ -63,17 +59,11 @@ impl EventHandler for Handler {
|
|||
}
|
||||
|
||||
pub async fn respond_with_error(_ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
||||
let username = &command.user.name.as_str();
|
||||
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
||||
|
||||
CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new("Rustendo"))
|
||||
.title("Command not found")
|
||||
.description("Cannot find the executed command")
|
||||
.footer(CreateEmbedFooter::new(format!(
|
||||
"> {} | {}",
|
||||
current_time, username
|
||||
)))
|
||||
Embed::create(
|
||||
command.user.name.to_owned(),
|
||||
"Command not found",
|
||||
"Cannot find the executed command",
|
||||
)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
|
|
|
@ -8,7 +8,7 @@ pub struct Config {
|
|||
pub discord_token: String,
|
||||
pub lavalink_address: String,
|
||||
pub lavalink_password: String,
|
||||
pub user_id: u64
|
||||
pub user_id: u64,
|
||||
}
|
||||
|
||||
const CONFIG_FILE: &str = "./data/config.json";
|
||||
|
@ -17,23 +17,23 @@ pub fn load() -> Result<Config, Box<dyn Error>> {
|
|||
// TODO: load config, create empty config if there is no config, stop if there is no complete config
|
||||
let config_file = match fs::File::open(CONFIG_FILE) {
|
||||
Ok(file) => file,
|
||||
Err(_) => create_empty()
|
||||
Err(_) => create_empty(),
|
||||
};
|
||||
let config_file = serde_json::from_reader(config_file).unwrap();
|
||||
Ok(config_file)
|
||||
}
|
||||
|
||||
fn create_empty() -> fs::File{
|
||||
fn create_empty() -> fs::File {
|
||||
let example_config = Config {
|
||||
discord_token: "paste_your_token".to_string(),
|
||||
lavalink_address: "paste_your_lavalink_address".to_string(),
|
||||
lavalink_password: "paste_your_lavalink_password".to_string(),
|
||||
user_id: 1
|
||||
user_id: 1,
|
||||
};
|
||||
|
||||
let mut config_file = fs::File::create(CONFIG_FILE).unwrap();
|
||||
let file_content = serde_json::to_string(&example_config).unwrap();
|
||||
config_file.write_all(&file_content.as_bytes()).unwrap();
|
||||
config_file.write_all(file_content.as_bytes()).unwrap();
|
||||
|
||||
panic!("There is no config. But now there is a template.")
|
||||
}
|
||||
}
|
||||
|
|
29
src/util/embed.rs
Normal file
29
src/util/embed.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use chrono::Local;
|
||||
use serenity::all::{CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter};
|
||||
|
||||
pub struct Embed;
|
||||
|
||||
impl Embed {
|
||||
pub fn create<
|
||||
S: Into<String> + Display,
|
||||
T: Into<String> + Display,
|
||||
U: Into<String> + Display,
|
||||
>(
|
||||
username: S,
|
||||
title: T,
|
||||
message: U,
|
||||
) -> CreateEmbed {
|
||||
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
||||
|
||||
CreateEmbed::new()
|
||||
.author(CreateEmbedAuthor::new(username.to_string()))
|
||||
.title(title)
|
||||
.description(message)
|
||||
.footer(CreateEmbedFooter::new(format!(
|
||||
"> {} | {}",
|
||||
current_time, username
|
||||
)))
|
||||
}
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
pub mod config;
|
||||
pub mod user_util;
|
||||
pub mod embed;
|
||||
pub mod user_util;
|
||||
|
|
|
@ -1,42 +1,38 @@
|
|||
use serenity::all::{ChannelId, Context, CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter, GuildId};
|
||||
use serenity::all::{ChannelId, Context, Guild, GuildId};
|
||||
|
||||
/// Get a guild by id
|
||||
pub fn get_guild(ctx: &Context, guild_id: &GuildId) -> Option<Guild> {
|
||||
let guild = ctx.cache.guild(guild_id)?;
|
||||
|
||||
Some(guild.clone())
|
||||
}
|
||||
|
||||
/// Get the current channel id of the bot
|
||||
pub fn get_channel_id(ctx: &Context, guild_id: &GuildId) -> Option<ChannelId> {
|
||||
let guild = get_guild(ctx, guild_id)?;
|
||||
|
||||
let channel_id = guild
|
||||
.voice_states
|
||||
.get(&ctx.cache.current_user().id)
|
||||
.and_then(|voice_state| voice_state.channel_id);
|
||||
|
||||
Some(channel_id.unwrap())
|
||||
}
|
||||
|
||||
pub fn is_self_connected_to_vc(ctx: &Context, guild_id: &GuildId) -> bool {
|
||||
let self_id = &ctx.cache.current_user().id;
|
||||
|
||||
let (_guild_id, channel_id) = {
|
||||
let guild = &ctx.cache.guild(guild_id).unwrap();
|
||||
// This may be unsafe, idk not sure yet
|
||||
let channel_id = guild
|
||||
.voice_states
|
||||
.get(self_id)
|
||||
.and_then(|voice_state| voice_state.channel_id);
|
||||
(guild.id, channel_id)
|
||||
};
|
||||
let channel_id = get_channel_id(ctx, guild_id);
|
||||
|
||||
// TODO: There has to be a way to improve this. This is bad code and it should be optimized.
|
||||
let connect_to = match channel_id {
|
||||
Some(channel) => channel,
|
||||
None => {
|
||||
return false
|
||||
},
|
||||
};
|
||||
|
||||
true
|
||||
if channel_id.is_none() {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
// This whole file is jank. I have to rewrite this once I know Rust better
|
||||
|
||||
pub fn get_self_vc_id(ctx: &Context, guild_id: &GuildId) -> ChannelId {
|
||||
let self_id = &ctx.cache.current_user().id;
|
||||
let (guild_id, channel_id) = {
|
||||
let guild = &ctx.cache.guild(guild_id).unwrap();
|
||||
// This may be unsafe, idk not sure yet
|
||||
let channel_id = guild
|
||||
.voice_states
|
||||
.get(&self_id)
|
||||
.and_then(|voice_state| voice_state.channel_id);
|
||||
(guild.id, channel_id)
|
||||
};
|
||||
|
||||
channel_id.unwrap()
|
||||
|
||||
pub fn get_self_vc_id(ctx: &Context, guild_id: &GuildId) -> Option<ChannelId> {
|
||||
let channel_id = get_channel_id(ctx, guild_id)?;
|
||||
|
||||
Some(channel_id)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue