Closes #1
This commit is contained in:
Generated
+1
-1
@@ -4,7 +4,7 @@ version = 4
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "RhythmWorks"
|
name = "RhythmWorks"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"semver",
|
"semver",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "RhythmWorks"
|
name = "RhythmWorks"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
+65
-46
@@ -8,18 +8,12 @@ use songbird::SerenityInit;
|
|||||||
use songbird::get;
|
use songbird::get;
|
||||||
use songbird::input::HlsRequest;
|
use songbird::input::HlsRequest;
|
||||||
use songbird::input::Input;
|
use songbird::input::Input;
|
||||||
use songbird::tracks::TrackHandle;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
use std::sync::Arc;
|
|
||||||
pub mod modules;
|
pub mod modules;
|
||||||
|
|
||||||
type TrackMap = Arc<Mutex<HashMap<u64, TrackHandle>>>;
|
struct Handler;
|
||||||
struct Handler {
|
|
||||||
track_map: TrackMap,
|
|
||||||
}
|
|
||||||
fn get_user_voice_channel(ctx: &Context, msg: &Message) -> Option<ChannelId> {
|
fn get_user_voice_channel(ctx: &Context, msg: &Message) -> Option<ChannelId> {
|
||||||
let guild_id = msg.guild_id?;
|
let guild_id = msg.guild_id?;
|
||||||
let guild = ctx.cache.guild(guild_id)?;
|
let guild = ctx.cache.guild(guild_id)?;
|
||||||
@@ -77,61 +71,78 @@ impl EventHandler for Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if msg.content.starts_with("!play") {
|
if msg.content.starts_with("!play") {
|
||||||
let mut url = msg
|
let mut yt_url = msg
|
||||||
.content
|
.content
|
||||||
.strip_prefix("!play ")
|
.strip_prefix("!play ")
|
||||||
.unwrap_or("")
|
.unwrap_or("")
|
||||||
.trim()
|
.trim()
|
||||||
.to_string();
|
.to_string();
|
||||||
let separator = "&";
|
if let Some(offset) = yt_url.find('&') {
|
||||||
if let Some(offset) = url.find(separator) {
|
yt_url.truncate(offset);
|
||||||
url.truncate(offset);
|
|
||||||
}
|
}
|
||||||
if url.is_empty() {
|
if yt_url.is_empty() {
|
||||||
let _ = msg.reply(&ctx, "Please provide a YouTube URL.").await;
|
let _ = msg.reply(&ctx, "Please provide a YouTube URL.").await;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let guild_id = msg.guild_id.unwrap();
|
let guild_id = msg.guild_id.unwrap();
|
||||||
let manager = songbird::get(&ctx)
|
let manager = songbird::get(&ctx).await.unwrap().clone();
|
||||||
.await
|
let handler_lock = if let Some(call) = manager.get(guild_id) {
|
||||||
.expect("Songbird Voice client placed in at initialisation.")
|
call
|
||||||
.clone();
|
|
||||||
let handler_lock = if let Some(handler) = manager.get(guild_id) {
|
|
||||||
handler
|
|
||||||
} else {
|
} else {
|
||||||
let channel_id = get_user_voice_channel(&ctx, &msg);
|
let channel_id = match get_user_voice_channel(&ctx, &msg) {
|
||||||
match channel_id {
|
Some(c) => c,
|
||||||
Some(c) => manager.join(guild_id, c).await.unwrap(),
|
|
||||||
None => {
|
None => {
|
||||||
let _ = msg.reply(&ctx, "Join a voice channel first!").await;
|
let _ = msg.reply(&ctx, "Join a voice channel first!").await;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
manager.join(guild_id, channel_id).await.unwrap()
|
||||||
};
|
};
|
||||||
let output = Command::new("./yt-dlp")
|
let output = Command::new("./yt-dlp")
|
||||||
.args(["-f", "bestaudio", "-g", &url])
|
.args(["-f", "bestaudio", "-g", &yt_url])
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.output()
|
.output()
|
||||||
.expect("Failed");
|
.expect("yt-dlp failed");
|
||||||
let url_bytes = output.stdout;
|
if !output.status.success() {
|
||||||
let url = String::from_utf8(url_bytes).expect("Failed");
|
let _ = msg.reply(&ctx, "Failed to fetch audio stream.").await;
|
||||||
let mut handler = handler_lock.lock().await;
|
return;
|
||||||
let input = Input::from(HlsRequest::new(reqwest::Client::new(), url.to_string()));
|
}
|
||||||
let track_handle = handler.play_input(input);
|
let stream_url = String::from_utf8(output.stdout)
|
||||||
let _ = track_handle.play();
|
.expect("Invalid UTF-8")
|
||||||
self.track_map
|
.trim()
|
||||||
.lock()
|
.to_string();
|
||||||
.await
|
let mut call = handler_lock.lock().await;
|
||||||
.insert(guild_id.into(), track_handle);
|
let input = Input::from(HlsRequest::new(reqwest::Client::new(), stream_url));
|
||||||
let _ = msg.channel_id.say(&ctx.http, "🎶 Playing...").await;
|
let _ = call.enqueue_input(input).await;
|
||||||
|
let position = call.queue().len();
|
||||||
|
let response = if position == 1 {
|
||||||
|
"🎶 Now playing!".to_string()
|
||||||
|
} else {
|
||||||
|
format!("🎶 Added Song to Queue: #{}", position)
|
||||||
|
};
|
||||||
|
let _ = msg.channel_id.say(&ctx.http, response).await;
|
||||||
|
}
|
||||||
|
if msg.content == "!skip" {
|
||||||
|
let guild_id = match msg.guild_id {
|
||||||
|
Some(g) => g,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
let manager = songbird::get(&ctx).await.unwrap();
|
||||||
|
if let Some(call) = manager.get(guild_id) {
|
||||||
|
let call = call.lock().await;
|
||||||
|
let _ = call.queue().skip();
|
||||||
|
let _ = msg.channel_id.say(&ctx.http, "Skipped").await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if msg.content == "!pause" {
|
if msg.content == "!pause" {
|
||||||
let guild_id = match msg.guild_id {
|
let guild_id = match msg.guild_id {
|
||||||
Some(g) => g,
|
Some(g) => g,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
if let Some(handle) = self.track_map.lock().await.get(&guild_id.into()) {
|
let manager = songbird::get(&ctx).await.unwrap();
|
||||||
let _ = handle.pause();
|
if let Some(call) = manager.get(guild_id) {
|
||||||
|
let call = call.lock().await;
|
||||||
|
let _ = call.queue().pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if msg.content == "!resume" {
|
if msg.content == "!resume" {
|
||||||
@@ -139,8 +150,10 @@ impl EventHandler for Handler {
|
|||||||
Some(g) => g,
|
Some(g) => g,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
if let Some(handle) = self.track_map.lock().await.get(&guild_id.into()) {
|
let manager = songbird::get(&ctx).await.unwrap();
|
||||||
let _ = handle.play();
|
if let Some(call) = manager.get(guild_id) {
|
||||||
|
let call = call.lock().await;
|
||||||
|
let _ = call.queue().resume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if msg.content == "!stop" {
|
if msg.content == "!stop" {
|
||||||
@@ -148,8 +161,10 @@ impl EventHandler for Handler {
|
|||||||
Some(g) => g,
|
Some(g) => g,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
if let Some(handle) = self.track_map.lock().await.get(&guild_id.into()) {
|
let manager = songbird::get(&ctx).await.unwrap();
|
||||||
let _ = handle.stop();
|
if let Some(call) = manager.get(guild_id) {
|
||||||
|
let call = call.lock().await;
|
||||||
|
let _ = call.queue().stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,24 +172,28 @@ impl EventHandler for Handler {
|
|||||||
println!("{} is connected!", ready.user.name);
|
println!("{} is connected!", ready.user.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
println!("RhythmWorks Copyright (C) 2025 James Brotosky\n
|
println!(
|
||||||
|
"RhythmWorks Copyright (C) 2025 James Brotosky\n
|
||||||
This program comes with ABSOLUTELY NO WARRANTY\n
|
This program comes with ABSOLUTELY NO WARRANTY\n
|
||||||
This is free software, and you are welcome to redistribute it under certain conditions.");
|
This is free software, and you are welcome to redistribute it under certain conditions."
|
||||||
|
);
|
||||||
updator::update().await;
|
updator::update().await;
|
||||||
println!("Please paste in your bot token");
|
println!("Please paste in your bot token");
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
io::stdin().read_line(&mut input).expect("Failed to read line");
|
io::stdin()
|
||||||
|
.read_line(&mut input)
|
||||||
|
.expect("Failed to read line");
|
||||||
let token = input.trim();
|
let token = input.trim();
|
||||||
let intents = GatewayIntents::GUILD_MESSAGES
|
let intents = GatewayIntents::GUILD_MESSAGES
|
||||||
| GatewayIntents::GUILDS
|
| GatewayIntents::GUILDS
|
||||||
| GatewayIntents::DIRECT_MESSAGES
|
| GatewayIntents::DIRECT_MESSAGES
|
||||||
| GatewayIntents::MESSAGE_CONTENT
|
| GatewayIntents::MESSAGE_CONTENT
|
||||||
| GatewayIntents::GUILD_VOICE_STATES;
|
| GatewayIntents::GUILD_VOICE_STATES;
|
||||||
let track_map: TrackMap = Arc::new(Mutex::new(HashMap::new()));
|
|
||||||
let mut client = Client::builder(&token, intents)
|
let mut client = Client::builder(&token, intents)
|
||||||
.event_handler(Handler { track_map })
|
.event_handler(Handler)
|
||||||
.register_songbird()
|
.register_songbird()
|
||||||
.await
|
.await
|
||||||
.expect("Err creating client");
|
.expect("Err creating client");
|
||||||
|
|||||||
+12
-8
@@ -1,15 +1,22 @@
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
use serde::Deserialize;
|
|
||||||
use semver::Version;
|
|
||||||
use reqwest;
|
use reqwest;
|
||||||
|
use semver::Version;
|
||||||
|
use serde::Deserialize;
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
struct Release {
|
struct Release {
|
||||||
tag_name: String,
|
tag_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update() {
|
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 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 release_info: Release = serde_json::from_str(&body).unwrap();
|
||||||
let latest_version = Version::parse(&release_info.tag_name).unwrap();
|
let latest_version = Version::parse(&release_info.tag_name).unwrap();
|
||||||
let current_version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
let current_version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
|
||||||
@@ -18,9 +25,6 @@ pub async fn update() {
|
|||||||
println!("URL: https://git.racooncity.org/brotoskyj/RhythmWorks/releases");
|
println!("URL: https://git.racooncity.org/brotoskyj/RhythmWorks/releases");
|
||||||
thread::sleep(std::time::Duration::from_secs(10));
|
thread::sleep(std::time::Duration::from_secs(10));
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
|
} else {
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user