Initial Commit
This commit is contained in:
+178
@@ -0,0 +1,178 @@
|
||||
use modules::*;
|
||||
use serenity::all::ChannelId;
|
||||
use serenity::async_trait;
|
||||
use serenity::model::channel::Message;
|
||||
use serenity::model::gateway::Ready;
|
||||
use serenity::prelude::*;
|
||||
use songbird::SerenityInit;
|
||||
use songbird::get;
|
||||
use songbird::input::HlsRequest;
|
||||
use songbird::input::Input;
|
||||
use songbird::tracks::TrackHandle;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
use std::process::Stdio;
|
||||
use std::sync::Arc;
|
||||
pub mod modules;
|
||||
|
||||
type TrackMap = Arc<Mutex<HashMap<u64, TrackHandle>>>;
|
||||
struct Handler {
|
||||
track_map: TrackMap,
|
||||
}
|
||||
fn get_user_voice_channel(ctx: &Context, msg: &Message) -> Option<ChannelId> {
|
||||
let guild_id = msg.guild_id?;
|
||||
let guild = ctx.cache.guild(guild_id)?;
|
||||
guild
|
||||
.voice_states
|
||||
.get(&msg.author.id)
|
||||
.and_then(|vs| vs.channel_id)
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for Handler {
|
||||
async fn message(&self, ctx: Context, msg: Message) {
|
||||
if msg.content == "!ping"
|
||||
&& let Err(why) = msg.channel_id.say(&ctx.http, "Pong!").await
|
||||
{
|
||||
println!("Error sending message: {why:?}");
|
||||
}
|
||||
if msg.content == "!join" {
|
||||
let guild_id = match msg.guild_id {
|
||||
Some(g) => g,
|
||||
None => return,
|
||||
};
|
||||
let channel_id = match get_user_voice_channel(&ctx, &msg) {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
let _ = msg
|
||||
.channel_id
|
||||
.say(&ctx.http, "You must be in a voice channel")
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let manager = get(&ctx).await.expect("Songbird not initialized").clone();
|
||||
|
||||
let _ = manager.join(guild_id, channel_id).await;
|
||||
|
||||
let _ = msg
|
||||
.channel_id
|
||||
.say(&ctx.http, "Joined your voice channel!")
|
||||
.await;
|
||||
}
|
||||
if msg.content == "!leave" {
|
||||
let guild_id = match msg.guild_id {
|
||||
Some(g) => g,
|
||||
None => return,
|
||||
};
|
||||
let manager = songbird::get(&ctx).await.unwrap();
|
||||
if manager.get(guild_id).is_some() {
|
||||
let _ = manager.remove(guild_id).await;
|
||||
let _ = msg
|
||||
.channel_id
|
||||
.say(&ctx.http, "Left the voice channel")
|
||||
.await;
|
||||
}
|
||||
}
|
||||
if msg.content.starts_with("!play") {
|
||||
let url = msg
|
||||
.content
|
||||
.strip_prefix("!play ")
|
||||
.unwrap_or("")
|
||||
.trim()
|
||||
.to_string();
|
||||
|
||||
if url.is_empty() {
|
||||
let _ = msg.reply(&ctx, "Please provide a YouTube URL.").await;
|
||||
return;
|
||||
}
|
||||
let guild_id = msg.guild_id.unwrap();
|
||||
let manager = songbird::get(&ctx)
|
||||
.await
|
||||
.expect("Songbird Voice client placed in at initialisation.")
|
||||
.clone();
|
||||
let handler_lock = if let Some(handler) = manager.get(guild_id) {
|
||||
handler
|
||||
} else {
|
||||
let channel_id = get_user_voice_channel(&ctx, &msg);
|
||||
match channel_id {
|
||||
Some(c) => manager.join(guild_id, c).await.unwrap(),
|
||||
None => {
|
||||
let _ = msg.reply(&ctx, "Join a voice channel first!").await;
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
let output = Command::new("yt-dlp")
|
||||
.args(["-f", "bestaudio", "-g", &url])
|
||||
.stdout(Stdio::piped())
|
||||
.output()
|
||||
.expect("Failed");
|
||||
let url_bytes = output.stdout;
|
||||
let url = String::from_utf8(url_bytes).expect("Failed");
|
||||
let mut handler = handler_lock.lock().await;
|
||||
let input = Input::from(HlsRequest::new(reqwest::Client::new(), url.to_string()));
|
||||
let track_handle = handler.play_input(input);
|
||||
let _ = track_handle.play();
|
||||
self.track_map
|
||||
.lock()
|
||||
.await
|
||||
.insert(guild_id.into(), track_handle);
|
||||
let _ = msg.channel_id.say(&ctx.http, "🎶 Playing...").await;
|
||||
}
|
||||
if msg.content == "!pause" {
|
||||
let guild_id = match msg.guild_id {
|
||||
Some(g) => g,
|
||||
None => return,
|
||||
};
|
||||
if let Some(handle) = self.track_map.lock().await.get(&guild_id.into()) {
|
||||
let _ = handle.pause();
|
||||
}
|
||||
}
|
||||
if msg.content == "!resume" {
|
||||
let guild_id = match msg.guild_id {
|
||||
Some(g) => g,
|
||||
None => return,
|
||||
};
|
||||
if let Some(handle) = self.track_map.lock().await.get(&guild_id.into()) {
|
||||
let _ = handle.play();
|
||||
}
|
||||
}
|
||||
if msg.content == "!stop" {
|
||||
let guild_id = match msg.guild_id {
|
||||
Some(g) => g,
|
||||
None => return,
|
||||
};
|
||||
if let Some(handle) = self.track_map.lock().await.get(&guild_id.into()) {
|
||||
let _ = handle.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
async fn ready(&self, _: Context, ready: Ready) {
|
||||
println!("{} is connected!", ready.user.name);
|
||||
}
|
||||
}
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
println!("RhythmWorks Copyright (C) 2025 James Brotosky\n
|
||||
This program comes with ABSOLUTELY NO WARRANTY\n
|
||||
This is free software, and you are welcome to redistribute it under certain conditions.");
|
||||
updator::update().await;
|
||||
let token = env::var("DISCORD_TOKEN").expect("Expected a token in the environment");
|
||||
let intents = GatewayIntents::GUILD_MESSAGES
|
||||
| GatewayIntents::GUILDS
|
||||
| GatewayIntents::DIRECT_MESSAGES
|
||||
| GatewayIntents::MESSAGE_CONTENT
|
||||
| GatewayIntents::GUILD_VOICE_STATES;
|
||||
let track_map: TrackMap = Arc::new(Mutex::new(HashMap::new()));
|
||||
let mut client = Client::builder(&token, intents)
|
||||
.event_handler(Handler { track_map })
|
||||
.register_songbird()
|
||||
.await
|
||||
.expect("Err creating client");
|
||||
if let Err(why) = client.start().await {
|
||||
println!("Client error: {why:?}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod updator;
|
||||
pub mod downloadyt;
|
||||
@@ -0,0 +1,20 @@
|
||||
use serde::Deserialize;
|
||||
use semver::Version;
|
||||
use reqwest;
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Release {
|
||||
tag_name: String,
|
||||
}
|
||||
|
||||
pub async fn update() {
|
||||
let body = reqwest::get("https://git.racooncity.org/api/v1/repos/brotoskyj/RhythmWorks/releases/latest").await.unwrap().text().await.unwrap();
|
||||
let release_info: Release = serde_json::from_str(&body).unwrap();
|
||||
let latest_version = Version::parse(&release_info.tag_name).unwrap();
|
||||
let current_version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||
if latest_version > current_version {
|
||||
println!("Update Available")
|
||||
}
|
||||
else {
|
||||
println!("Already on current version");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user