initial commit

This commit is contained in:
Gabriel Fontes
2022-01-27 22:57:11 -03:00
commit c8c2b86ea6
16 changed files with 3720 additions and 0 deletions

72
src/client.rs Normal file
View File

@@ -0,0 +1,72 @@
use anyhow::Result;
use serenity::{
client::Client as DiscordClient, framework::standard::StandardFramework, prelude::TypeMapKey,
};
use songbird::SerenityInit;
use sunk::Client as SubsonicClient;
use std::{env, fs, io};
use crate::discord::{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> {
Ok(DiscordClient::builder(&self.discord_token)
.event_handler(Handler)
.framework(
StandardFramework::new()
.configure(|c| c.prefix("~"))
.group(&GENERAL_GROUP),
)
.type_map_insert::<MusicClient>(ss)
.register_songbird()
.await?)
}
pub async fn subsonic(&self) -> Result<SubsonicClient> {
Ok(SubsonicClient::new(
&self.ss_url,
&self.ss_user,
&self.ss_password,
)?)
}
}
pub struct MusicClient;
impl TypeMapKey for MusicClient {
type Value = SubsonicClient;
}

95
src/discord/mod.rs Normal file
View File

@@ -0,0 +1,95 @@
use serenity::{
async_trait,
client::{Context, EventHandler},
framework::standard::{
macros::{command, group},
Args, CommandResult,
},
model::channel::Message,
utils::MessageBuilder,
};
use sunk::{
search::{self, SearchPage},
Streamable,
};
use crate::MusicClient;
#[group]
#[commands(play)]
pub struct General;
pub struct Handler;
#[async_trait]
impl EventHandler for Handler {}
#[command]
#[only_in(guilds)]
#[aliases(p, queue, song)]
#[example("~play Down Under")]
#[description("Tocar uma música")]
async fn play(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
let data = ctx.data.read().await;
let music_client = data
.get::<MusicClient>()
.expect("Couldn't retrieve music client");
let search_size = SearchPage::new().with_size(1);
let ignore = search::NONE;
let result = music_client
.search(args.rest(), ignore, ignore, search_size)
.await?
.songs;
match result.first() {
Some(song) => {
let guild = msg.guild(&ctx.cache).await.unwrap();
let guild_id = guild.id;
let caller_channel = guild
.voice_states
.get(&msg.author.id)
.and_then(|voice_state| voice_state.channel_id);
let connect_to = match caller_channel {
Some(channel) => channel,
None => {
msg.reply(ctx, "Você não está em um canal de voz").await?;
return Ok(());
}
};
let manager = songbird::get(ctx).await.unwrap();
let handler = manager.join(guild_id, connect_to).await;
let mut channel_handler = handler.0.lock().await;
let url = song.stream_url(&music_client)?;
let input = songbird::ffmpeg(url).await.unwrap();
channel_handler.play_only_source(input);
let message = MessageBuilder::new()
.push("Agora tocando ")
.push_bold_safe(format!(
"{} - {} ({})",
song.artist.clone().unwrap_or_default(),
song.title,
song.album.clone().unwrap_or_default(),
))
.build();
msg.channel_id.say(&ctx.http, &message).await?;
Ok(())
}
None => {
msg.channel_id
.say(&ctx.http, "Nenhuma música encontrada")
.await?;
Ok(())
}
}
}

4
src/lib.rs Normal file
View File

@@ -0,0 +1,4 @@
pub mod client;
pub use client::{MusicClient, Client};
pub mod discord;

16
src/main.rs Normal file
View File

@@ -0,0 +1,16 @@
use anyhow::Result;
use disconic::Client;
#[tokio::main]
async fn main() -> Result<()> {
dotenv::dotenv().ok();
let client = Client::from_env().await?;
let subsonic = client.subsonic().await?;
let mut discord = client.discord(subsonic).await?;
discord.start().await?;
Ok(())
}