chore: restructurize the whole source
This commit is contained in:
parent
e32e632c7c
commit
9d920421b7
31 changed files with 1031 additions and 183 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -11,3 +11,5 @@
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
mooverdb.db*
|
mooverdb.db*
|
||||||
|
|
||||||
|
*.txt
|
879
Cargo.lock
generated
879
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -7,21 +7,22 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
anyhow = "1.0.89"
|
anyhow = "1.0.95"
|
||||||
tokio-cron-scheduler = "0.13.0"
|
tokio-cron-scheduler = "0.13.0"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
poise = "0.6.1"
|
poise = "0.6.1"
|
||||||
serenity = { version = "0.12.4", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "http", "cache"] }
|
serenity = { version = "0.12.4", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "http", "cache"] }
|
||||||
# serenity_utils = "0.7.0"
|
# serenity_utils = "0.7.0"
|
||||||
tokio = { version = "1.42.0", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] }
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
chrono = "0.4.38"
|
chrono = "0.4.39"
|
||||||
sqlx = {version="0.8.2", features=["runtime-tokio", "sqlite"]}
|
sqlx = {version="0.8.3", features=["runtime-tokio", "sqlite"]}
|
||||||
form_urlencoded = "1.2.1"
|
form_urlencoded = "1.2.1"
|
||||||
tenorv2 = { path = "./tenor-v2/tenorv2" }
|
tenorv2 = { path = "./tenor-v2/tenorv2" }
|
||||||
# librespot = { version = "0.6.0", default-features = false, features = ["rodio-backend"] }
|
# librespot = { version = "0.6.0", default-features = false, features = ["rodio-backend"] }
|
||||||
songbird = { version = "0.4.6", features = ["driver", "builtin-queue"] }
|
songbird = { version = "0.4.6", features = ["driver", "builtin-queue"] }
|
||||||
reqwest = "0.11.27" # songbird depends on ^0.11
|
reqwest = "0.11.27" # songbird depends on ^0.11
|
||||||
|
radiobrowser = "0.6.1"
|
||||||
|
|
||||||
[dependencies.symphonia]
|
[dependencies.symphonia]
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
pub use moover::*;
|
pub use moover::*;
|
||||||
pub use notice::*;
|
pub use notice::*;
|
||||||
pub use user_interactions::*;
|
pub use user_interactions::*;
|
||||||
pub use other::*;
|
// pub use other::*;
|
||||||
pub use voice::*;
|
pub use voice::*;
|
||||||
|
// pub use command_utils::*;
|
||||||
|
|
||||||
pub mod moover;
|
pub mod moover;
|
||||||
pub mod notice;
|
pub mod notice;
|
||||||
pub mod user_interactions;
|
pub mod user_interactions;
|
||||||
pub mod other;
|
// pub mod other;
|
||||||
pub mod voice;
|
pub mod voice;
|
||||||
|
// mod command_utils;
|
|
@ -1,7 +1,7 @@
|
||||||
pub use moove::*;
|
pub use moove::*;
|
||||||
|
pub use gif::*;
|
||||||
pub use say::*;
|
pub use say::*;
|
||||||
// pub use gif::*;
|
|
||||||
|
|
||||||
pub mod moove;
|
pub mod moove;
|
||||||
|
pub mod gif;
|
||||||
pub mod say;
|
pub mod say;
|
||||||
// pub mod gif;
|
|
20
src/commands/moover/gif.rs
Normal file
20
src/commands/moover/gif.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
use poise;
|
||||||
|
use serenity::all::{Embed, User};
|
||||||
|
|
||||||
|
use crate::types::{Error, Context};
|
||||||
|
|
||||||
|
#[poise::command(
|
||||||
|
slash_command,
|
||||||
|
description_localized("en-US", "Send a gif from Tenor")
|
||||||
|
)]
|
||||||
|
pub async fn gif(ctx: Context<'_>,
|
||||||
|
#[description = "What should I search?"]
|
||||||
|
what: String,
|
||||||
|
#[description = "Should the gif be R-rated?"]
|
||||||
|
contentfilter: String
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
// let embed;
|
||||||
|
// send_with_embed(ctx, "hug", &title, &desc).await?;
|
||||||
|
ctx.reply("Done!").await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ use anyhow::anyhow;
|
||||||
use serenity::all::{Colour, CreateEmbed, CreateMessage};
|
use serenity::all::{Colour, CreateEmbed, CreateMessage};
|
||||||
use tenorv2::tenor_builder::Tenor;
|
use tenorv2::tenor_builder::Tenor;
|
||||||
|
|
||||||
use crate::{types::Context, util::{gifs::get_random_tenor_gif, utilities}};
|
use crate::{types::Context, utils::{gifs::get_random_tenor_gif, utilities}};
|
||||||
|
|
||||||
/// Sends embed with random tenor gif from searched query
|
/// Sends embed with random tenor gif from searched query
|
||||||
/// title and desc are used in the embed
|
/// title and desc are used in the embed
|
||||||
|
|
11
src/commands/voice.rs
Normal file
11
src/commands/voice.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
use voice_utils::*;
|
||||||
|
|
||||||
|
mod voice_utils;
|
||||||
|
pub mod player_common;
|
||||||
|
pub mod radio;
|
||||||
|
pub mod general_player;
|
||||||
|
|
||||||
|
// ! not working
|
||||||
|
// pub mod yt;
|
||||||
|
// TODO implement
|
||||||
|
// pub mod spotify;
|
|
@ -1,3 +0,0 @@
|
||||||
pub use general_player::*;
|
|
||||||
|
|
||||||
pub mod general_player;
|
|
|
@ -2,10 +2,11 @@ use std::vec;
|
||||||
|
|
||||||
use songbird::input::YoutubeDl;
|
use songbird::input::YoutubeDl;
|
||||||
|
|
||||||
use crate::commands::util::connect;
|
use crate::utils::poise_context_extension::ContextExt;
|
||||||
use crate::util::poise_context_extension::ContextExt;
|
|
||||||
use crate::types::{Context, Error};
|
use crate::types::{Context, Error};
|
||||||
use crate::commands::voice::util::autocomplete_channel;
|
use crate::commands::voice::voice_utils::autocomplete_channel;
|
||||||
|
|
||||||
|
use super::connect;
|
||||||
|
|
||||||
// TODO: search, queue
|
// TODO: search, queue
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
|
@ -38,14 +39,11 @@ pub async fn play(ctx: Context<'_>,
|
||||||
let http_client = &ctx.data().http_client;
|
let http_client = &ctx.data().http_client;
|
||||||
|
|
||||||
if manager.get(guild_id).is_none() {
|
if manager.get(guild_id).is_none() {
|
||||||
match connect(&ctx, guild_id, channel).await {
|
if let Err(e) = connect(&ctx, guild_id, channel).await {
|
||||||
Ok(_) => (),
|
|
||||||
Err(e) => {
|
|
||||||
ctx.reply_ephemeral(&e.to_string()).await?;
|
ctx.reply_ephemeral(&e.to_string()).await?;
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(handler_lock) = manager.get(guild_id) {
|
if let Some(handler_lock) = manager.get(guild_id) {
|
||||||
let mut handler = handler_lock.lock().await;
|
let mut handler = handler_lock.lock().await;
|
|
@ -1,6 +0,0 @@
|
||||||
pub mod util;
|
|
||||||
pub mod player_common;
|
|
||||||
pub mod radio;
|
|
||||||
// pub mod spotify;
|
|
||||||
pub mod general;
|
|
||||||
pub mod yt;
|
|
|
@ -2,12 +2,12 @@ use std::vec;
|
||||||
|
|
||||||
use songbird::input::{File, Input};
|
use songbird::input::{File, Input};
|
||||||
|
|
||||||
use crate::util::debug::send_error;
|
use crate::utils::debug::send_error;
|
||||||
use crate::util::poise_context_extension::ContextExt;
|
use crate::utils::poise_context_extension::ContextExt;
|
||||||
use crate::util::utilities::get_local_songs;
|
use crate::utils::utilities::get_local_songs;
|
||||||
use crate::types::{Context, Error};
|
use crate::types::{Context, Error};
|
||||||
|
|
||||||
use super::util::{connect, autocomplete_channel};
|
use super::voice_utils::{connect, autocomplete_channel};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common commands that are the same for every implementation
|
* Common commands that are the same for every implementation
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
pub use radio_player::*;
|
pub use radio_player::*;
|
||||||
|
use radio_utils::*;
|
||||||
|
|
||||||
pub mod radio_player;
|
pub mod radio_player;
|
||||||
|
|
||||||
|
mod radio_utils;
|
|
@ -1,26 +1,41 @@
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
|
use radiobrowser::RadioBrowserAPI;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
|
|
||||||
use songbird::input::Input;
|
use songbird::input::Input;
|
||||||
use songbird::input::HttpRequest;
|
use songbird::input::HttpRequest;
|
||||||
|
|
||||||
use crate::commands::util::connect;
|
use super::super::connect;
|
||||||
use crate::util::poise_context_extension::ContextExt;
|
use crate::utils::poise_context_extension::ContextExt;
|
||||||
use crate::types::{Context, Error};
|
use crate::types::{Context, Error};
|
||||||
use crate::commands::voice::util::autocomplete_channel;
|
use crate::commands::voice::voice_utils::autocomplete_channel;
|
||||||
|
|
||||||
|
use super::radio_utils::paginate_search;
|
||||||
|
|
||||||
|
use super::super::voice_utils::MAX_ENTRIES;
|
||||||
|
|
||||||
|
#[poise::command(
|
||||||
|
slash_command,
|
||||||
|
description_localized("en-US", "Plays music from URL source"),
|
||||||
|
subcommands("search", "play")
|
||||||
|
)]
|
||||||
|
pub async fn radio(_ctx: Context<'_>) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: autocomplete radio stream URLs
|
// TODO: autocomplete radio stream URLs
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
slash_command,
|
slash_command,
|
||||||
description_localized("en-US", "Plays music from URL source")
|
description_localized("en-US", "Plays music from URL source")
|
||||||
)]
|
)]
|
||||||
pub async fn radio(ctx: Context<'_>,
|
pub async fn play(ctx: Context<'_>,
|
||||||
#[autocomplete = "autocomplete_channel"]
|
#[autocomplete = "autocomplete_channel"]
|
||||||
#[description = "Voice channel name: "]
|
#[description = "Voice channel name: "]
|
||||||
channel: Option<String>,
|
channel: Option<String>,
|
||||||
#[description = "Source URL: "]
|
#[autocomplete = "autocomplete_radio"]
|
||||||
url: String,
|
#[description = "Radio station: "]
|
||||||
|
name: String,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
|
||||||
if ctx.guild().is_none() {
|
if ctx.guild().is_none() {
|
||||||
|
@ -39,20 +54,17 @@ pub async fn radio(ctx: Context<'_>,
|
||||||
};
|
};
|
||||||
|
|
||||||
if manager.get(guild_id).is_none() {
|
if manager.get(guild_id).is_none() {
|
||||||
match connect(&ctx, guild_id, channel).await {
|
if let Err(e) = connect(&ctx, guild_id, channel).await {
|
||||||
Ok(_) => (),
|
|
||||||
Err(e) => {
|
|
||||||
ctx.reply_ephemeral(&e.to_string()).await?;
|
ctx.reply_ephemeral(&e.to_string()).await?;
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(handler_lock) = manager.get(guild_id) {
|
if let Some(handler_lock) = manager.get(guild_id) {
|
||||||
let mut handler = handler_lock.lock().await;
|
let mut handler = handler_lock.lock().await;
|
||||||
|
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
let request = HttpRequest::new(client, url);
|
let request = HttpRequest::new(client, name);
|
||||||
let input = Input::from(request);
|
let input = Input::from(request);
|
||||||
handler.play_only_input(input);
|
handler.play_only_input(input);
|
||||||
}
|
}
|
||||||
|
@ -64,3 +76,80 @@ pub async fn radio(ctx: Context<'_>,
|
||||||
ctx.reply_ephemeral("Done!").await?;
|
ctx.reply_ephemeral("Done!").await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn autocomplete_radio(
|
||||||
|
ctx: Context<'_>,
|
||||||
|
partial: &str
|
||||||
|
) -> Vec<String> {
|
||||||
|
|
||||||
|
let api = {
|
||||||
|
match &ctx.data().radio_browser {
|
||||||
|
Some(v) => v.clone(),
|
||||||
|
None => {
|
||||||
|
let Ok(radio_browser) = RadioBrowserAPI::new().await else {
|
||||||
|
return vec!["There was an error with radio API!".to_owned()]
|
||||||
|
};
|
||||||
|
radio_browser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let stations: Vec<String> = match api.get_stations()
|
||||||
|
.limit(MAX_ENTRIES)
|
||||||
|
.name(partial)
|
||||||
|
.hidebroken(true)
|
||||||
|
.send().await {
|
||||||
|
Ok(stations) => {
|
||||||
|
stations.iter().map(|station|
|
||||||
|
format!("Name: {} Language: {} Bitrate: {}", station.name, station.countrycode, station.bitrate)
|
||||||
|
).collect()
|
||||||
|
},
|
||||||
|
Err(_) => return vec!["".to_owned()]
|
||||||
|
};
|
||||||
|
|
||||||
|
dbg!(&stations);
|
||||||
|
|
||||||
|
return stations
|
||||||
|
// return vec![];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// autocomplete
|
||||||
|
// search with buttons and list in embed with direct links to stream
|
||||||
|
// embed showing currently playing song
|
||||||
|
|
||||||
|
// TODO: autocomplete radio stream URLs
|
||||||
|
#[poise::command(
|
||||||
|
slash_command,
|
||||||
|
description_localized("en-US", "Search for a radio")
|
||||||
|
)]
|
||||||
|
pub async fn search(ctx: Context<'_>,
|
||||||
|
#[description = "Radio station: "]
|
||||||
|
name: String,
|
||||||
|
#[description = "Country: "]
|
||||||
|
country: Option<String>,
|
||||||
|
#[description = "Tag: "]
|
||||||
|
tag: Option<String>
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
|
||||||
|
let api = match &ctx.data().radio_browser {
|
||||||
|
Some(v) => v.clone(),
|
||||||
|
None => {
|
||||||
|
let Ok(radio_browser) = RadioBrowserAPI::new().await else {
|
||||||
|
let _ = ctx.reply_ephemeral("There was an error with radio API!").await;
|
||||||
|
return Ok(())
|
||||||
|
};
|
||||||
|
radio_browser
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let station_search_builder = api.get_stations()
|
||||||
|
.name(name)
|
||||||
|
.tag(tag.unwrap_or("".to_owned()))
|
||||||
|
.country(country.unwrap_or("".to_owned()))
|
||||||
|
.hidebroken(true);
|
||||||
|
|
||||||
|
paginate_search(ctx, station_search_builder);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
83
src/commands/voice/radio/radio_utils.rs
Normal file
83
src/commands/voice/radio/radio_utils.rs
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
use poise::{ChoiceParameter, CreateReply};
|
||||||
|
use radiobrowser::StationSearchBuilder;
|
||||||
|
use serenity::{all::{CreateActionRow, CreateButton, CreateEmbed, CreateInteractionResponse, CreateInteractionResponseMessage}, futures::SinkExt};
|
||||||
|
|
||||||
|
use crate::types::Context;
|
||||||
|
|
||||||
|
#[derive(ChoiceParameter)]
|
||||||
|
pub enum WelcomeChoice {
|
||||||
|
#[name = "5"]
|
||||||
|
A,
|
||||||
|
#[name = "10"]
|
||||||
|
B,
|
||||||
|
#[name = "15"]
|
||||||
|
C
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn paginate_search(
|
||||||
|
ctx: Context<'_>,
|
||||||
|
search_builder: StationSearchBuilder,
|
||||||
|
) -> Result<(), serenity::Error> {
|
||||||
|
// Define some unique identifiers for the navigation buttons
|
||||||
|
let ctx_id = ctx.id();
|
||||||
|
let prev_button_id = format!("{}prev", ctx_id);
|
||||||
|
let next_button_id = format!("{}next", ctx_id);
|
||||||
|
|
||||||
|
let Ok(stations) = search_builder.send().await else {
|
||||||
|
let _ = ctx.reply("Something went wrong, try searching again").await;
|
||||||
|
return Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send the embed with the first page as content
|
||||||
|
let reply = {
|
||||||
|
let components = CreateActionRow::Buttons(vec![
|
||||||
|
CreateButton::new(&prev_button_id).emoji('◀'),
|
||||||
|
CreateButton::new(&next_button_id).emoji('▶'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
CreateReply::default()
|
||||||
|
.embed(CreateEmbed::new())
|
||||||
|
.components(vec![components])
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.send(reply).await?;
|
||||||
|
|
||||||
|
// Loop through incoming interactions with the navigation buttons
|
||||||
|
let mut current_page = 0;
|
||||||
|
while let Some(press) = serenity::collector::ComponentInteractionCollector::new(ctx)
|
||||||
|
// We defined our button IDs to start with `ctx_id`. If they don't, some other command's
|
||||||
|
// button was pressed
|
||||||
|
.filter(move |press| press.data.custom_id.starts_with(&ctx_id.to_string()))
|
||||||
|
// Timeout when no navigation button has been pressed for 24 hours
|
||||||
|
.timeout(std::time::Duration::from_secs(3600 * 24))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
// Depending on which button was pressed, go to next or previous page
|
||||||
|
if press.data.custom_id == next_button_id {
|
||||||
|
current_page += 1;
|
||||||
|
// TODO find a way to check end
|
||||||
|
// if current_page >= pages.len() {
|
||||||
|
// current_page = 0;
|
||||||
|
// }
|
||||||
|
} else if press.data.custom_id == prev_button_id {
|
||||||
|
// TODO find a way to get pages len
|
||||||
|
// current_page = current_page.checked_sub(1).unwrap_or(pages.len() - 1);
|
||||||
|
} else {
|
||||||
|
// This is an unrelated button interaction
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the message with the new page contents
|
||||||
|
press
|
||||||
|
.create_response(
|
||||||
|
ctx.serenity_context(),
|
||||||
|
CreateInteractionResponse::UpdateMessage(
|
||||||
|
CreateInteractionResponseMessage::new()
|
||||||
|
.embed(CreateEmbed::new()),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
use serenity::all::{ChannelId, GuildId};
|
use poise::{CreateReply};
|
||||||
|
use serenity::all::{ChannelId, CreateActionRow, CreateButton, CreateEmbed, CreateInteractionResponse, CreateInteractionResponseMessage, Embed, GuildId};
|
||||||
use serenity::async_trait;
|
use serenity::async_trait;
|
||||||
|
|
||||||
use songbird::events::{Event, EventContext, EventHandler as VoiceEventHandler};
|
use songbird::events::{Event, EventContext, EventHandler as VoiceEventHandler};
|
||||||
use songbird::TrackEvent;
|
use songbird::TrackEvent;
|
||||||
|
|
||||||
use crate::{types::{Context, Error}, util::utilities::get_channel_by_name};
|
use crate::{types::{Context, Error}, utils::utilities::get_channel_by_name};
|
||||||
|
|
||||||
|
pub const MAX_ENTRIES: &str = "15";
|
||||||
|
|
||||||
/// Returns either voice channel to which the user is currently connected to or the one passed via name
|
/// Returns either voice channel to which the user is currently connected to or the one passed via name
|
||||||
async fn get_voice_channel(ctx: &Context<'_>, name: Option<String>) -> Result<ChannelId, String> {
|
async fn get_voice_channel(ctx: &Context<'_>, name: Option<String>) -> Result<ChannelId, String> {
|
||||||
|
@ -68,7 +71,7 @@ pub async fn autocomplete_channel(
|
||||||
_partial: &str,
|
_partial: &str,
|
||||||
) -> Vec<String> {
|
) -> Vec<String> {
|
||||||
|
|
||||||
use crate::util::utilities::get_vc_names;
|
use crate::utils::utilities::get_vc_names;
|
||||||
match ctx.guild() {
|
match ctx.guild() {
|
||||||
Some(guild) => get_vc_names(guild),
|
Some(guild) => get_vc_names(guild),
|
||||||
None => [].to_vec()
|
None => [].to_vec()
|
13
src/main.rs
13
src/main.rs
|
@ -23,7 +23,7 @@ mod message_handler;
|
||||||
use message_handler::handle;
|
use message_handler::handle;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
mod util;
|
mod utils;
|
||||||
|
|
||||||
mod other;
|
mod other;
|
||||||
use other::notice;
|
use other::notice;
|
||||||
|
@ -57,7 +57,7 @@ impl EventHandler for Handler {
|
||||||
println!("{} v3.3.1 is connected!", ready.user.name);
|
println!("{} v3.3.1 is connected!", ready.user.name);
|
||||||
|
|
||||||
#[cfg(feature="RELEASE")] {
|
#[cfg(feature="RELEASE")] {
|
||||||
use util::debug::hello;
|
use utils::debug::hello;
|
||||||
let _ = hello(ctx.http.clone()).await;
|
let _ = hello(ctx.http.clone()).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,10 +87,9 @@ async fn main() -> anyhow::Result<()> {
|
||||||
commands::say(),
|
commands::say(),
|
||||||
commands::hug(),
|
commands::hug(),
|
||||||
// commands::player::play_local(),
|
// commands::player::play_local(),
|
||||||
commands::player_common::disconnect(),
|
|
||||||
commands::radio::radio(),
|
commands::radio::radio(),
|
||||||
commands::general::play(),
|
commands::general_player::play(),
|
||||||
commands::yt::play_yt()
|
commands::player_common::disconnect(),
|
||||||
],
|
],
|
||||||
prefix_options: poise::PrefixFrameworkOptions {
|
prefix_options: poise::PrefixFrameworkOptions {
|
||||||
prefix: Some("/".into()),
|
prefix: Some("/".into()),
|
||||||
|
@ -129,8 +128,10 @@ async fn main() -> anyhow::Result<()> {
|
||||||
register_globally(ctx, &framework.options().commands).await?;
|
register_globally(ctx, &framework.options().commands).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Ok(Data {
|
Ok(Data {
|
||||||
http_client: HttpClient::new()
|
http_client: HttpClient::new(),
|
||||||
|
radio_browser: RadioBrowserAPI::new().await.ok()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,8 +5,8 @@ use serenity::model::channel::Message;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::util::debug::send_error;
|
use crate::utils::debug::send_error;
|
||||||
use crate::util::utilities;
|
use crate::utils::utilities;
|
||||||
|
|
||||||
use crate::commands::moover::moove::{moove, moove_check};
|
use crate::commands::moover::moove::{moove, moove_check};
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ use serenity::{all::{GuildId, UserId}, builder::{CreateEmbed, CreateMessage}, cl
|
||||||
|
|
||||||
use sqlx::{Connection, FromRow, SqliteConnection};
|
use sqlx::{Connection, FromRow, SqliteConnection};
|
||||||
|
|
||||||
use crate::util::debug::send_error;
|
use crate::utils::debug::send_error;
|
||||||
use crate::util::utilities;
|
use crate::utils::utilities;
|
||||||
|
|
||||||
use std::{env, sync::Arc};
|
use std::{env, sync::Arc};
|
||||||
|
|
||||||
|
|
|
@ -2,20 +2,15 @@
|
||||||
|
|
||||||
use std::{ffi::OsString, path::PathBuf};
|
use std::{ffi::OsString, path::PathBuf};
|
||||||
|
|
||||||
use serenity::prelude::TypeMapKey;
|
use radiobrowser::RadioBrowserAPI;
|
||||||
|
|
||||||
use reqwest::Client as HttpClient;
|
use reqwest::Client as HttpClient;
|
||||||
|
|
||||||
// TODO: this should be probably expanded also to be used by multiple servers and commands
|
// TODO: this should be probably expanded also to be used by multiple servers and commands
|
||||||
// radio and spotify commands always create new HttpClient
|
// radio and spotify commands always create new HttpClient
|
||||||
pub struct HttpKey;
|
|
||||||
|
|
||||||
impl TypeMapKey for HttpKey {
|
|
||||||
type Value = HttpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
pub http_client: HttpClient,
|
pub http_client: HttpClient,
|
||||||
|
pub radio_browser: Option<RadioBrowserAPI>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Error = Box<dyn std::error::Error + Send + Sync>;
|
pub type Error = Box<dyn std::error::Error + Send + Sync>;
|
||||||
|
|
Loading…
Reference in a new issue