#![allow(non_snake_case)] extern crate serenity; extern crate parking_lot; extern crate serde_json; extern crate typemap; mod player; use serenity::{ framework::standard::{ help_commands, macros::{check, command, group, help}, Args, CheckResult, CommandGroup, CommandOptions, CommandResult, DispatchError, HelpOptions, StandardFramework, }, model::{ channel::{Channel, Message}, gateway::Ready, id::UserId, }, utils::{content_safe, ContentSafeOptions}, }; // This imports `typemap`'s `Key` as `TypeMapKey`. use serenity::prelude::*; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; use player::prelude::*; use std::collections::HashSet; use utilities::prelude::*; struct Config { token: String, prefix: String, volume: f32, } impl Default for Config { fn default() -> Self { Self { token: String::new(), prefix: String::new(), volume: 1.0, } } } group!({ name: "general", options: {}, commands: [ip, list, pause, play, remove, skip, stop] }); #[help] fn my_help( context: &mut Context, msg: &Message, args: Args, help_options: &'static HelpOptions, groups: &[&'static CommandGroup], owners: HashSet, ) -> CommandResult { help_commands::with_embeds(context, msg, args, &help_options, groups, owners) } fn main() -> VerboseResult<()> { // read config file let config_file = ConfigHandler::read_config("bot.conf")?; let mut config = Config::default(); match config_file.get("Meta") { Some(info) => { match info.get("token") { Some(token_pair) => { token_pair.set_value(&mut config.token)?; } None => { create_error!("couldn't find token inside meta section"); } } match info.get("prefix") { Some(prefix_pair) => { prefix_pair.set_value(&mut config.prefix)?; } None => { create_error!("couldn't find prefix inside meta section"); } } if let Some(volume) = info.get("volume") { volume.set_value(&mut config.volume)?; } } None => { create_error!("couldn't find Meta section in config file"); } }; let mut client = Client::new(&config.token, Handler).expect("Err creating client"); let media_data = Arc::new(Mutex::new( MediaData::new("Penis1", Arc::clone(&client.voice_manager), config.volume) .expect("failed to create media data handle"), )); // Obtain a lock to the data owned by the client, and insert the client's // voice manager into it. This allows the voice manager to be accessible by // event handlers and framework commands. { let mut data = client.data.write(); data.insert::(media_data.clone()); } // We will fetch your bot's owners and id let (owners, bot_id) = match client.cache_and_http.http.get_current_application_info() { Ok(info) => { let mut owners = HashSet::new(); owners.insert(info.owner.id); (owners, info.id) } Err(why) => panic!("Could not access application info: {:?}", why), }; client.with_framework( // Configures the client, allowing for options to mutate how the // framework functions. // // Refer to the documentation for // `serenity::ext::framework::Configuration` for all available // configurations. StandardFramework::new() .configure(|c| { c.with_whitespace(true) .on_mention(Some(bot_id)) .prefix(&config.prefix) .owners(owners) }) .group(&GENERAL_GROUP) .help(&MY_HELP), ); thread::spawn(move || loop { { let mut media_lock = media_data.lock().unwrap(); // check if there is a song currently being played let mut is_playing = false; if let Some(song) = media_lock.song() { let song_lock = song.lock(); if !song_lock.finished { is_playing = true; } } if !is_playing { MediaData::next_song(&mut media_lock).unwrap(); } } thread::sleep(Duration::from_millis(1500)); }); let _ = client .start() .map_err(|why| println!("Client ended: {:?}", why)); Ok(()) }