update how configuring works
This commit is contained in:
@@ -1,83 +0,0 @@
|
||||
use anyhow::{Context as ErrContext, Result};
|
||||
use serenity::{
|
||||
client::Client as DiscordClient,
|
||||
framework::standard::StandardFramework,
|
||||
prelude::{GatewayIntents, TypeMapKey},
|
||||
};
|
||||
use songbird::SerenityInit;
|
||||
use sunk::Client as SubsonicClient;
|
||||
|
||||
use std::{env, fs, io};
|
||||
|
||||
use crate::discord::{after_hook, Handler, GENERAL_GROUP};
|
||||
|
||||
pub struct Client {
|
||||
ss_url: String,
|
||||
ss_user: String,
|
||||
ss_password: String,
|
||||
discord_token: String,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub async fn from_env() -> Result<Self> {
|
||||
// Convert to std::io::Error, allowing usage of and_then
|
||||
let convert_err = |e| io::Error::new(io::ErrorKind::Other, e);
|
||||
|
||||
let ss_url = env::var("SUBSONIC_URL")?;
|
||||
let ss_user = env::var("SUBSONIC_USER")?;
|
||||
let ss_password = env::var("SUBSONIC_PASSWORD").or_else(|_| {
|
||||
env::var("SUBSONIC_PASSWORD_FILE")
|
||||
.map_err(convert_err)
|
||||
.and_then(fs::read_to_string)
|
||||
.map(|s| s.trim().to_owned())
|
||||
})?;
|
||||
let discord_token = env::var("DISCORD_TOKEN").or_else(|_| {
|
||||
env::var("DISCORD_TOKEN_FILE")
|
||||
.map_err(convert_err)
|
||||
.and_then(fs::read_to_string)
|
||||
.map(|s| s.trim().to_owned())
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
ss_url,
|
||||
ss_user,
|
||||
ss_password,
|
||||
discord_token,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn discord(&self, ss: SubsonicClient) -> Result<DiscordClient> {
|
||||
let intents = GatewayIntents::non_privileged() | GatewayIntents::MESSAGE_CONTENT;
|
||||
let framework = StandardFramework::new()
|
||||
.group(&GENERAL_GROUP)
|
||||
.after(after_hook);
|
||||
|
||||
framework.configure(|c| c.prefix("~"));
|
||||
|
||||
let client = DiscordClient::builder(&self.discord_token, intents)
|
||||
.event_handler(Handler)
|
||||
.framework(framework)
|
||||
.type_map_insert::<MusicClient>(ss)
|
||||
.register_songbird()
|
||||
.await?;
|
||||
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
pub async fn subsonic(&self) -> Result<SubsonicClient> {
|
||||
let client = SubsonicClient::new(&self.ss_url, &self.ss_user, &self.ss_password)?;
|
||||
log::info!("Created subsonic client: {client:?}");
|
||||
// Check that connection works
|
||||
client
|
||||
.ping()
|
||||
.await
|
||||
.with_context(|| "Could not connect to subsonic server.")?;
|
||||
|
||||
Ok(client)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MusicClient;
|
||||
impl TypeMapKey for MusicClient {
|
||||
type Value = SubsonicClient;
|
||||
}
|
||||
67
src/config.rs
Normal file
67
src/config.rs
Normal file
@@ -0,0 +1,67 @@
|
||||
use crate::handles::SubsonicClientHandle;
|
||||
use anyhow::{Context as ErrContext, Result};
|
||||
use clap::Parser;
|
||||
use log::LevelFilter;
|
||||
use serenity::{
|
||||
client::Client as DiscordClient, framework::standard::StandardFramework,
|
||||
prelude::GatewayIntents,
|
||||
};
|
||||
use simple_logger::SimpleLogger;
|
||||
use songbird::SerenityInit;
|
||||
use sunk::Client as SubsonicClient;
|
||||
|
||||
use crate::discord::{after_hook, Handler, GENERAL_GROUP};
|
||||
|
||||
#[derive(Parser, Clone)]
|
||||
pub struct Config {
|
||||
#[clap(long, env = "DISCONIC_SUBSONIC_URL")]
|
||||
subsonic_url: String,
|
||||
#[clap(long, env = "DISCONIC_SUBSONIC_USER")]
|
||||
subsonic_user: String,
|
||||
#[clap(long, env = "DISCONIC_SUBSONIC_PASSWORD")]
|
||||
subsonic_password: String,
|
||||
#[clap(long, env = "DISCONIC_DISCORD_TOKEN")]
|
||||
discord_token: String,
|
||||
#[clap(long, env = "DISCONIC_LOG_LEVEL", default_value = "warn")]
|
||||
log_level: LevelFilter,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub async fn discord(&self, ss: SubsonicClient) -> Result<DiscordClient> {
|
||||
let intents = GatewayIntents::non_privileged() | GatewayIntents::MESSAGE_CONTENT;
|
||||
let framework = StandardFramework::new()
|
||||
.group(&GENERAL_GROUP)
|
||||
.after(after_hook);
|
||||
|
||||
framework.configure(|c| c.prefix("~"));
|
||||
|
||||
let client = DiscordClient::builder(&self.discord_token, intents)
|
||||
.event_handler(Handler)
|
||||
.framework(framework)
|
||||
.type_map_insert::<SubsonicClientHandle>(ss)
|
||||
.register_songbird()
|
||||
.await?;
|
||||
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
pub async fn subsonic(&self) -> Result<SubsonicClient> {
|
||||
let client = SubsonicClient::new(
|
||||
&self.subsonic_url,
|
||||
&self.subsonic_user,
|
||||
&self.subsonic_password,
|
||||
)?;
|
||||
log::info!("Created subsonic client: {client:?}");
|
||||
// Check that connection works
|
||||
client
|
||||
.ping()
|
||||
.await
|
||||
.with_context(|| "Could not connect to subsonic server.")?;
|
||||
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
pub fn logger(&self) -> SimpleLogger {
|
||||
SimpleLogger::new().with_level(self.log_level)
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ use serenity::{
|
||||
Args, CommandResult,
|
||||
},
|
||||
model::{channel::Message, gateway::Ready},
|
||||
prelude::TypeMapKey,
|
||||
utils::MessageBuilder,
|
||||
};
|
||||
use songbird::{
|
||||
@@ -25,7 +24,7 @@ use tokio::sync::Mutex;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::MusicClient;
|
||||
use crate::handles::{SubsonicClientHandle, SubsonicSongHandle};
|
||||
|
||||
#[group]
|
||||
#[commands(
|
||||
@@ -38,7 +37,7 @@ pub struct Handler;
|
||||
#[async_trait]
|
||||
impl EventHandler for Handler {
|
||||
async fn ready(&self, _: Context, ready: Ready) {
|
||||
println!("{} is connected!", ready.user.name);
|
||||
log::info!("{} is connected!", ready.user.name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +75,7 @@ async fn join(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
async fn song(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
let data = ctx.data.read().await;
|
||||
let music_client = data
|
||||
.get::<MusicClient>()
|
||||
.get::<SubsonicClientHandle>()
|
||||
.expect("Couldn't retrieve music client");
|
||||
|
||||
let search_size = SearchPage::new().with_size(1);
|
||||
@@ -114,7 +113,7 @@ async fn song(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
async fn album(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
let data = ctx.data.read().await;
|
||||
let music_client = data
|
||||
.get::<MusicClient>()
|
||||
.get::<SubsonicClientHandle>()
|
||||
.expect("Couldn't retrieve music client");
|
||||
|
||||
let search_size = SearchPage::new().with_size(1);
|
||||
@@ -153,7 +152,7 @@ async fn album(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||
async fn random(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
let data = ctx.data.read().await;
|
||||
let music_client = data
|
||||
.get::<MusicClient>()
|
||||
.get::<SubsonicClientHandle>()
|
||||
.expect("Couldn't retrieve music client");
|
||||
|
||||
let result = Song::random(music_client, 1).await?;
|
||||
@@ -334,11 +333,6 @@ async fn remove(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||
// ==========================
|
||||
// ==========================
|
||||
|
||||
struct SongHandler;
|
||||
impl TypeMapKey for SongHandler {
|
||||
type Value = Song;
|
||||
}
|
||||
|
||||
async fn queue_song(
|
||||
ctx: &Context,
|
||||
msg: &Message,
|
||||
@@ -351,7 +345,7 @@ async fn queue_song(
|
||||
let track = load_song(song, client).await?;
|
||||
let track_handle = handler.enqueue(track).await;
|
||||
let mut type_map = track_handle.typemap().write().await;
|
||||
type_map.insert::<SongHandler>(song.clone());
|
||||
type_map.insert::<SubsonicSongHandle>(song.clone());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -394,7 +388,7 @@ async fn get_song(track: &TrackHandle) -> Result<Song> {
|
||||
.typemap()
|
||||
.read()
|
||||
.await
|
||||
.get::<SongHandler>()
|
||||
.get::<SubsonicSongHandle>()
|
||||
.map(ToOwned::to_owned)
|
||||
.ok_or_else(|| anyhow!("Sound information not found"))?;
|
||||
Ok(song)
|
||||
|
||||
12
src/handles.rs
Normal file
12
src/handles.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use serenity::prelude::TypeMapKey;
|
||||
use sunk::{song::Song as SubsonicSong, Client as SubsonicClient};
|
||||
|
||||
pub struct SubsonicClientHandle;
|
||||
impl TypeMapKey for SubsonicClientHandle {
|
||||
type Value = SubsonicClient;
|
||||
}
|
||||
|
||||
pub struct SubsonicSongHandle;
|
||||
impl TypeMapKey for SubsonicSongHandle {
|
||||
type Value = SubsonicSong;
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
pub mod client;
|
||||
pub use client::{Client, MusicClient};
|
||||
|
||||
pub mod config;
|
||||
pub mod discord;
|
||||
pub mod handles;
|
||||
|
||||
12
src/main.rs
12
src/main.rs
@@ -1,16 +1,18 @@
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
|
||||
use disconic::Client;
|
||||
use disconic::config::Config;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
dotenv::dotenv().ok();
|
||||
env_logger::init();
|
||||
|
||||
let client = Client::from_env().await?;
|
||||
let subsonic = client.subsonic().await?;
|
||||
let mut discord = client.discord(subsonic).await?;
|
||||
let config = Config::parse();
|
||||
let logger = config.logger();
|
||||
let subsonic = config.subsonic().await?;
|
||||
let mut discord = config.discord(subsonic).await?;
|
||||
|
||||
logger.init()?;
|
||||
discord.start().await?;
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user