Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add toml config #5

Merged
merged 12 commits into from Jun 22, 2022
1 change: 1 addition & 0 deletions .gitignore
@@ -1,2 +1,3 @@
/target
/cache
config.toml
103 changes: 103 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Expand Up @@ -11,8 +11,13 @@ tracing = "0.1"
tracing-subscriber = "0.2"
tracing-futures = "0.2"
tokio = { version = "1.5.0", features = ["full"] }
toml = "0.5"
futures = "0.3.14"
byteorder = "1.4.3"
samplerate = "0.2.4"
oleggtro marked this conversation as resolved.
Show resolved Hide resolved
serde = "1.0"
envy = "0.4"
figment = { version = "0.10", features = ["toml", "env"] }
rubato = "0.10.0"

[dependencies.serenity]
Expand Down
18 changes: 10 additions & 8 deletions README.md
Expand Up @@ -29,10 +29,10 @@ services:
volumes:
- ./aoede:/data
environment:
- DISCORD_TOKEN=
- SPOTIFY_USERNAME=
- SPOTIFY_PASSWORD=
- DISCORD_USER_ID= # Discord user ID of the user you want Aoede to follow
- AOEDE_DISCORD_TOKEN=
- AOEDE_SPOTIFY_USERNAME=
- AOEDE_SPOTIFY_PASSWORD=
- AOEDE_DISCORD_USER_ID= # Discord user ID of the user you want Aoede to follow
```

**Docker**:
Expand All @@ -52,10 +52,12 @@ docker run --rm -d --env-file .env codetheweb/aoede

Prebuilt binaries are available on the [releases page](https://github.com/codetheweb/aoede/releases). Download the binary for your platform, then inside a terminal session:

1. Set the required environment variables (see the Docker Compose section)
- On Windows, you can use `setx DISCORD_TOKEN my-token`
- On Linux / macOS, you can use `export DISCORD_TOKEN=my-token`
3. Run the binary:
1. There are two options to make configuration values available to Aoede:
1. Rename the `config.sample.toml` file to `config.toml` and update the config values
oleggtro marked this conversation as resolved.
Show resolved Hide resolved
2. Use environment variables (see the Docker Compose section above):
- On Windows, you can use `setx AOEDE_DISCORD_TOKEN my-token`
- On Linux / macOS, you can use `export AOEDE_DISCORD_TOKEN=my-token`
2. Run the binary:
- For Linux / macOS, `./platform-latest-aoede` after navigating to the correct directory
- For Windows, execute `windows-latest-aoede.exe` after navigating to the correct directory

Expand Down
4 changes: 4 additions & 0 deletions config.sample.toml
@@ -0,0 +1,4 @@
DISCORD_TOKEN="the discord bot token"
SPOTIFY_USERNAME="your spotify email"
SPOTIFY_PASSWORD="your spotify password"
DISCORD_USER_ID="your discord id here"
24 changes: 24 additions & 0 deletions src/lib/config.rs
@@ -0,0 +1,24 @@
use figment::{
providers::{Env, Format, Toml},
Error, Figment,
};
use serde::Deserialize;
use serenity::model::id;

#[derive(Deserialize, Clone)]
pub struct Config {
pub discord_token: String,
pub spotify_username: String,
pub spotify_password: String,
pub discord_user_id: id::UserId,
}

impl Config {
pub fn new() -> Result<Self, Error> {
let config: Config = Figment::new()
.merge(Toml::file("config.toml"))
.merge(Env::prefixed("AOEDE_").map(|v| v.to_string().to_lowercase().into()))
oleggtro marked this conversation as resolved.
Show resolved Hide resolved
.extract()?;
Ok(config)
}
}
oleggtro marked this conversation as resolved.
Show resolved Hide resolved
58 changes: 35 additions & 23 deletions src/main.rs
@@ -1,11 +1,13 @@
use std::env;
use std::process::exit;

use lib::config::Config;
use songbird::input;
use songbird::SerenityInit;

mod lib {
pub mod config;
pub mod player;
// pub mod forward_mpsc;
}
use lib::player::{SpotifyPlayer, SpotifyPlayerKey};
use librespot::core::mercury::MercuryError;
Expand All @@ -14,6 +16,7 @@ use librespot::playback::player::PlayerEvent;
use std::sync::Arc;
use tokio::sync::Mutex;
use tokio::time::{sleep, Duration};
use figment::error::Kind::MissingField;

use serenity::client::Context;

Expand All @@ -28,9 +31,9 @@ use serenity::{

struct Handler;

pub struct UserIdKey;
impl TypeMapKey for UserIdKey {
type Value = id::UserId;
pub struct ConfigKey;
impl TypeMapKey for ConfigKey {
type Value = Config;
}

#[async_trait]
Expand All @@ -53,9 +56,7 @@ impl EventHandler for Handler {
let data = ctx.data.read().await;

let player = data.get::<SpotifyPlayerKey>().unwrap().clone();
let user_id = *data
.get::<UserIdKey>()
.expect("User ID placed in at initialisation.");
let config = data.get::<ConfigKey>().unwrap().clone();

// Handle case when user is in VC when bot starts
let guild = ctx
Expand All @@ -66,7 +67,7 @@ impl EventHandler for Handler {

let channel_id = guild
.voice_states
.get(&user_id)
.get(&config.discord_user_id)
.and_then(|voice_state| voice_state.channel_id);
drop(guild);

Expand Down Expand Up @@ -118,7 +119,7 @@ impl EventHandler for Handler {

let channel_id = match guild
.voice_states
.get(&user_id)
.get(&config.discord_user_id)
.and_then(|voice_state| voice_state.channel_id)
{
Some(channel_id) => channel_id,
Expand Down Expand Up @@ -201,9 +202,9 @@ impl EventHandler for Handler {
) {
let data = ctx.data.read().await;

let user_id = data.get::<UserIdKey>();
let config = data.get::<ConfigKey>().unwrap();

if new.user_id.to_string() != user_id.unwrap().to_string() {
if new.user_id.to_string() != config.discord_user_id.to_string() {
return;
}

Expand Down Expand Up @@ -269,16 +270,21 @@ impl EventHandler for Handler {
async fn main() {
tracing_subscriber::fmt::init();

// Configure the client with your Discord bot token in the environment.
let token = env::var("DISCORD_TOKEN").expect("Expected a token in the environment");

let framework = StandardFramework::new();
let username =
env::var("SPOTIFY_USERNAME").expect("Expected a Spotify username in the environment");
let password =
env::var("SPOTIFY_PASSWORD").expect("Expected a Spotify password in the environment");
let user_id =
env::var("DISCORD_USER_ID").expect("Expected a Discord user ID in the environment");

let config = match Config::new() {
Ok(config) => config,
Err(error) => {
println!("Couldn't read config");
if let MissingField(f) = error.kind {
println!("Missing field: 'AOEDE_{}'", f.to_uppercase());
oleggtro marked this conversation as resolved.
Show resolved Hide resolved
} else {
println!("Error: {:?}", error);
exit(2)
}
exit(1)
}
};

let mut cache_dir = None;

Expand All @@ -287,14 +293,20 @@ async fn main() {
}

let player = Arc::new(Mutex::new(
SpotifyPlayer::new(username, password, Bitrate::Bitrate320, cache_dir).await,
SpotifyPlayer::new(
config.spotify_username.clone(),
config.spotify_password.clone(),
Bitrate::Bitrate320,
cache_dir,
)
.await,
));

let mut client = Client::builder(&token)
let mut client = Client::builder(&config.discord_token)
.event_handler(Handler)
.framework(framework)
.type_map_insert::<SpotifyPlayerKey>(player)
.type_map_insert::<UserIdKey>(id::UserId::from(user_id.parse::<u64>().unwrap()))
.type_map_insert::<ConfigKey>(config)
.register_songbird()
.await
.expect("Err creating client");
Expand Down