Removed hardcoded URL in /join

main
DaXcess 2023-09-26 09:46:15 +02:00
parent 1201e44313
commit b5999fe718
No known key found for this signature in database
GPG Key ID: CF78CC72F0FD5EAD
8 changed files with 147 additions and 146 deletions

View File

@ -8,6 +8,7 @@ In this section of the change log all current changes that have been made since
* Added aarch64 support * Added aarch64 support
* Added cross compilation to Github Actions * Added cross compilation to Github Actions
* Added `dev` branch to Github Actions * Added `dev` branch to Github Actions
* Removed hardcoded URL in the /join command
## 2.1.1 | September 23rd 2023 ## 2.1.1 | September 23rd 2023
Reduced the amount of CPU that the bot uses from ~15%-25% per user to 1%-2% per user (percentage per core, benched on an AMD Ryzen 9 5950X). Reduced the amount of CPU that the bot uses from ~15%-25% per user to 1%-2% per user (percentage per core, benched on an AMD Ryzen 9 5950X).

2
Cargo.lock generated
View File

@ -2269,6 +2269,7 @@ dependencies = [
"dotenv", "dotenv",
"env_logger 0.10.0", "env_logger 0.10.0",
"hex", "hex",
"lazy_static",
"librespot", "librespot",
"log", "log",
"protobuf", "protobuf",
@ -2280,7 +2281,6 @@ dependencies = [
"serenity", "serenity",
"songbird", "songbird",
"thiserror", "thiserror",
"time",
"tokio", "tokio",
"zerocopy 0.7.5", "zerocopy 0.7.5",
] ]

View File

@ -16,6 +16,7 @@ anyhow = "1.0.75"
dotenv = "0.15.0" dotenv = "0.15.0"
env_logger = "0.10.0" env_logger = "0.10.0"
hex = "0.4.3" hex = "0.4.3"
lazy_static = "1.4.0"
librespot = { version = "0.4.2", default-features = false } librespot = { version = "0.4.2", default-features = false }
log = "0.4.20" log = "0.4.20"
protobuf = "2.28.0" protobuf = "2.28.0"
@ -27,7 +28,6 @@ serde_json = "1.0.107"
serenity = { version = "0.11.6", features = ["framework", "cache", "standard_framework"], default-features = false } serenity = { version = "0.11.6", features = ["framework", "cache", "standard_framework"], default-features = false }
songbird = "0.3.2" songbird = "0.3.2"
thiserror = "1.0.48" thiserror = "1.0.48"
time = "0.3.28"
tokio = { version = "1.32.0", features = ["rt", "full"] } tokio = { version = "1.32.0", features = ["rt", "full"] }
zerocopy = "0.7.5" zerocopy = "0.7.5"

View File

@ -8,6 +8,7 @@ use serenity::{
use crate::{ use crate::{
bot::commands::{respond_message, CommandOutput}, bot::commands::{respond_message, CommandOutput},
consts::SPOTICORD_ACCOUNTS_URL,
database::{Database, DatabaseError}, database::{Database, DatabaseError},
utils::embed::{EmbedBuilder, Status}, utils::embed::{EmbedBuilder, Status},
}; };
@ -39,8 +40,11 @@ pub fn command(ctx: Context, command: ApplicationCommandInteraction) -> CommandO
} }
if let Ok(request) = database.get_user_request(command.user.id.to_string()).await { if let Ok(request) = database.get_user_request(command.user.id.to_string()).await {
let base = std::env::var("SPOTICORD_ACCOUNTS_URL").expect("to be present"); let link = format!(
let link = format!("{}/spotify/{}", base, request.token); "{}/spotify/{}",
SPOTICORD_ACCOUNTS_URL.as_str(),
request.token
);
respond_message( respond_message(
&ctx, &ctx,
@ -106,8 +110,11 @@ pub fn command(ctx: Context, command: ApplicationCommandInteraction) -> CommandO
.await .await
{ {
Ok(request) => { Ok(request) => {
let base = std::env::var("SPOTICORD_ACCOUNTS_URL").expect("to be present"); let link = format!(
let link = format!("{}/spotify/{}", base, request.token); "{}/spotify/{}",
SPOTICORD_ACCOUNTS_URL.as_str(),
request.token
);
respond_message( respond_message(
&ctx, &ctx,

View File

@ -7,6 +7,7 @@ use serenity::{
use crate::{ use crate::{
bot::commands::{defer_message, respond_message, update_message, CommandOutput}, bot::commands::{defer_message, respond_message, update_message, CommandOutput},
consts::SPOTICORD_ACCOUNTS_URL,
session::manager::{SessionCreateError, SessionManager}, session::manager::{SessionCreateError, SessionManager},
utils::embed::{EmbedBuilder, Status}, utils::embed::{EmbedBuilder, Status},
}; };
@ -241,7 +242,7 @@ pub fn command(ctx: Context, command: ApplicationCommandInteraction) -> CommandO
&command, &command,
EmbedBuilder::new() EmbedBuilder::new()
.title("Cannot join voice channel") .title("Cannot join voice channel")
.description("You need to link your Spotify account. Use </link:1036714850367320136> or go to [the accounts website](https://account.spoticord.com/) to get started.") .description(format!("You need to link your Spotify account. Use </link:1036714850367320136> or go to [the accounts website]({}) to get started.", SPOTICORD_ACCOUNTS_URL.as_str()))
.status(Status::Error) .status(Status::Error)
.build(), .build(),
) )
@ -255,7 +256,7 @@ pub fn command(ctx: Context, command: ApplicationCommandInteraction) -> CommandO
&command, &command,
EmbedBuilder::new() EmbedBuilder::new()
.title("Cannot join voice channel") .title("Cannot join voice channel")
.description("Spoticord no longer has access to your Spotify account. Use </link:1036714850367320136> or go to [the accounts website](https://account.spoticord.com/) to relink your Spotify account.") .description(format!("Spoticord no longer has access to your Spotify account. Use </link:1036714850367320136> or go to [the accounts website]({}) to relink your Spotify account.", SPOTICORD_ACCOUNTS_URL.as_str()))
.status(Status::Error) .status(Status::Error)
.build(), .build(),
).await; ).await;

View File

@ -30,20 +30,22 @@ pub const NAME: &str = "playing";
pub fn command(ctx: Context, command: ApplicationCommandInteraction) -> CommandOutput { pub fn command(ctx: Context, command: ApplicationCommandInteraction) -> CommandOutput {
Box::pin(async move { Box::pin(async move {
let not_playing = async { macro_rules! not_playing {
respond_message( () => {
&ctx, respond_message(
&command, &ctx,
EmbedBuilder::new() &command,
.title("Cannot get track info") EmbedBuilder::new()
.icon_url("https://spoticord.com/forbidden.png") .title("Cannot get track info")
.description("I'm currently not playing any music in this server") .icon_url("https://spoticord.com/forbidden.png")
.status(Status::Error) .description("I'm currently not playing any music in this server")
.build(), .status(Status::Error)
true, .build(),
) true,
.await; )
}; .await;
};
}
let data = ctx.data.read().await; let data = ctx.data.read().await;
let session_manager = data let session_manager = data
@ -51,62 +53,50 @@ pub fn command(ctx: Context, command: ApplicationCommandInteraction) -> CommandO
.expect("to contain a value") .expect("to contain a value")
.clone(); .clone();
let session = match session_manager let Some(session) = session_manager
.get_session(command.guild_id.expect("to contain a value")) .get_session(command.guild_id.expect("to contain a value"))
.await .await
{ else {
Some(session) => session, not_playing!();
None => {
not_playing.await;
return; return;
}
}; };
let owner = match session.owner().await { let Some(owner) = session.owner().await else {
Some(owner) => owner, not_playing!();
None => {
not_playing.await;
return; return;
}
}; };
// Get Playback Info from session // Get Playback Info from session
let pbi = match session.playback_info().await { let Some(pbi) = session.playback_info().await else {
Some(pbi) => pbi, not_playing!();
None => {
not_playing.await;
return; return;
}
}; };
// Get owner of session // Get owner of session
let owner = match utils::discord::get_user(&ctx, owner).await { let Some(owner) = utils::discord::get_user(&ctx, owner).await else {
Some(user) => user, // This shouldn't happen
None => {
// This shouldn't happen
error!("Could not find user with ID: {owner}"); error!("Could not find user with ID: {owner}");
respond_message( respond_message(
&ctx, &ctx,
&command, &command,
EmbedBuilder::new() EmbedBuilder::new()
.title("[INTERNAL ERROR] Cannot get track info") .title("[INTERNAL ERROR] Cannot get track info")
.description(format!( .description(format!(
"Could not find user with ID `{}`\nThis is an issue with the bot!", "Could not find user with ID `{}`\nThis is an issue with the bot!",
owner owner
)) ))
.status(Status::Error) .status(Status::Error)
.build(), .build(),
true, true,
) )
.await; .await;
return; return;
}
}; };
// Get metadata // Get metadata
@ -188,48 +178,39 @@ pub fn component(ctx: Context, mut interaction: MessageComponentInteraction) ->
.clone(); .clone();
// Check if session still exists // Check if session still exists
let mut session = match session_manager let Some(mut session) = session_manager
.get_session(interaction.guild_id.expect("to contain a value")) .get_session(interaction.guild_id.expect("to contain a value"))
.await .await
{ else {
Some(session) => session, error_edit(
None => { "Cannot perform action",
error_edit( "I'm currently not playing any music in this server",
"Cannot perform action", )
"I'm currently not playing any music in this server", .await;
)
.await;
return; return;
}
}; };
// Check if the session contains an owner // Check if the session contains an owner
let owner = match session.owner().await { let Some(owner) = session.owner().await else {
Some(owner) => owner, error_edit(
None => { "Cannot change playback state",
error_edit( "I'm currently not playing any music in this server",
"Cannot change playback state", )
"I'm currently not playing any music in this server", .await;
)
.await;
return; return;
}
}; };
// Get Playback Info from session // Get Playback Info from session
let pbi = match session.playback_info().await { let Some(pbi) = session.playback_info().await else {
Some(pbi) => pbi, error_edit(
None => { "Cannot change playback state",
error_edit( "I'm currently not playing any music in this server",
"Cannot change playback state", )
"I'm currently not playing any music in this server", .await;
)
.await;
return; return;
}
}; };
// Check if the user is the owner of the session // Check if the user is the owner of the session
@ -244,30 +225,27 @@ pub fn component(ctx: Context, mut interaction: MessageComponentInteraction) ->
} }
// Get owner of session // Get owner of session
let owner = match utils::discord::get_user(&ctx, owner).await { let Some(owner) = utils::discord::get_user(&ctx, owner).await else {
Some(user) => user, // This shouldn't happen
None => {
// This shouldn't happen
error!("Could not find user with ID: {owner}"); error!("Could not find user with ID: {owner}");
respond_component_message( respond_component_message(
&ctx, &ctx,
&interaction, &interaction,
EmbedBuilder::new() EmbedBuilder::new()
.title("[INTERNAL ERROR] Cannot get track info") .title("[INTERNAL ERROR] Cannot get track info")
.description(format!( .description(format!(
"Could not find user with ID `{}`\nThis is an issue with the bot!", "Could not find user with ID `{}`\nThis is an issue with the bot!",
owner owner
)) ))
.status(Status::Error) .status(Status::Error)
.build(), .build(),
true, true,
) )
.await; .await;
return; return;
}
}; };
// Send the desired command to the session // Send the desired command to the session
@ -370,34 +348,28 @@ async fn update_embed(interaction: &mut MessageComponentInteraction, ctx: &Conte
.clone(); .clone();
// Check if session still exists // Check if session still exists
let session = match session_manager let Some(session) = session_manager
.get_session(interaction.guild_id.expect("to contain a value")) .get_session(interaction.guild_id.expect("to contain a value"))
.await .await
{ else {
Some(session) => session, error_edit(
None => { "Cannot perform action",
error_edit( "I'm currently not playing any music in this server",
"Cannot perform action", )
"I'm currently not playing any music in this server", .await;
)
.await;
return; return;
}
}; };
// Get Playback Info from session // Get Playback Info from session
let pbi = match session.playback_info().await { let Some(pbi) = session.playback_info().await else {
Some(pbi) => pbi, error_edit(
None => { "Cannot change playback state",
error_edit( "I'm currently not playing any music in this server",
"Cannot change playback state", )
"I'm currently not playing any music in this server", .await;
)
.await;
return; return;
}
}; };
let (title, description, thumbnail) = get_metadata(&pbi); let (title, description, thumbnail) = get_metadata(&pbi);

View File

@ -1,3 +1,5 @@
use lazy_static::lazy_static;
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const VERSION: &str = env!("CARGO_PKG_VERSION");
@ -8,3 +10,18 @@ pub const MOTD: &str = "some good 'ol music";
/// The time it takes for Spoticord to disconnect when no music is being played /// The time it takes for Spoticord to disconnect when no music is being played
pub const DISCONNECT_TIME: u64 = 5 * 60; pub const DISCONNECT_TIME: u64 = 5 * 60;
lazy_static! {
pub static ref DISCORD_TOKEN: String =
std::env::var("DISCORD_TOKEN").expect("missing DISCORD_TOKEN environment variable");
pub static ref DATABASE_URL: String =
std::env::var("DATABASE_URL").expect("missing DATABASE_URL environment variable");
pub static ref SPOTICORD_ACCOUNTS_URL: String = std::env::var("SPOTICORD_ACCOUNTS_URL")
.expect("missing SPOTICORD_ACCOUNTS_URL environment variable");
}
#[cfg(feature = "stats")]
lazy_static! {
pub static ref KV_URL: String =
std::env::var("KV_URL").expect("missing KV_URL environment variable");
}

View File

@ -1,10 +1,18 @@
use dotenv::dotenv; use dotenv::dotenv;
use crate::{bot::commands::CommandManager, database::Database, session::manager::SessionManager}; #[cfg(feature = "stats")]
use crate::consts::KV_URL;
use crate::{
bot::commands::CommandManager,
consts::{DATABASE_URL, DISCORD_TOKEN, MOTD},
database::Database,
session::manager::SessionManager,
};
use log::*; use log::*;
use serenity::{framework::StandardFramework, prelude::GatewayIntents, Client}; use serenity::{framework::StandardFramework, prelude::GatewayIntents, Client};
use songbird::SerenityInit; use songbird::SerenityInit;
use std::{any::Any, env, process::exit}; use std::{any::Any, process::exit};
#[cfg(unix)] #[cfg(unix)]
use tokio::signal::unix::SignalKind; use tokio::signal::unix::SignalKind;
@ -41,7 +49,7 @@ async fn main() {
env_logger::init(); env_logger::init();
info!("It's a good day"); info!("It's a good day");
info!(" - Spoticord {}", time::OffsetDateTime::now_utc().year()); info!(" - Spoticord, {}", MOTD);
let result = dotenv(); let result = dotenv();
@ -54,19 +62,14 @@ async fn main() {
warn!("No .env file found, expecting all necessary environment variables"); warn!("No .env file found, expecting all necessary environment variables");
} }
let token = env::var("DISCORD_TOKEN").expect("a token in the environment");
let db_url = env::var("DATABASE_URL").expect("a database URL in the environment");
#[cfg(feature = "stats")] #[cfg(feature = "stats")]
let stats_manager = let stats_manager = StatsManager::new(KV_URL.as_str()).expect("Failed to connect to redis");
StatsManager::new(env::var("KV_URL").expect("a redis URL in the environment"))
.expect("Failed to connect to redis");
let session_manager = SessionManager::new(); let session_manager = SessionManager::new();
// Create client // Create client
let mut client = Client::builder( let mut client = Client::builder(
token, DISCORD_TOKEN.as_str(),
GatewayIntents::GUILDS | GatewayIntents::GUILD_VOICE_STATES, GatewayIntents::GUILDS | GatewayIntents::GUILD_VOICE_STATES,
) )
.event_handler(crate::bot::events::Handler) .event_handler(crate::bot::events::Handler)
@ -78,7 +81,7 @@ async fn main() {
{ {
let mut data = client.data.write().await; let mut data = client.data.write().await;
data.insert::<Database>(Database::new(db_url, None)); data.insert::<Database>(Database::new(DATABASE_URL.as_str(), None));
data.insert::<CommandManager>(CommandManager::new()); data.insert::<CommandManager>(CommandManager::new());
data.insert::<SessionManager>(session_manager.clone()); data.insert::<SessionManager>(session_manager.clone());
} }