Skip to content

Commit

Permalink
the schpinkly
Browse files Browse the repository at this point in the history
  • Loading branch information
Dissssy committed May 14, 2024
1 parent 28cfddf commit 92a6491
Show file tree
Hide file tree
Showing 13 changed files with 347 additions and 140 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ shitgpt.json
whitelist.json
ex.html
src/commands/emulate.rs.old
sam
alerts.json
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ base64 = "0.21.0"
async-recursion = "1.0.0"
image = "0.24.5"
lazy_static = "1.4.0"
human_format = "1.0.3"
chrono = "0.4.31"
linkify = "0.10.0"
env_logger = "0.10.0"
Expand Down
6 changes: 5 additions & 1 deletion alerts.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
{
"main": "neon circle",
"aliases": [
"neon circles",
"beyond circle",
"beyond circles",
"neoncircle",
"me uncircled",
"me on circle",
"the uncircled"
"me on circles",
"the uncircled",
"the uncircle"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion runloop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ while true; do
# yt-dlp --update-to nightly
python -m pip install --upgrade yt-dlp
# run the application
cargo run --release --features experimental --features misogyny
cargo run --release --features experimental # --features misogyny

# save the return code
ret=$?
Expand Down
10 changes: 8 additions & 2 deletions src/commands/music/mainloop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ pub async fn the_lüüp(rawcall: Arc<Mutex<Call>>, rawrx: mpsc::UnboundedReceive
let transcribe = crate::voice_events::VoiceDataManager::new(Arc::clone(&rawcall), Arc::clone(&http), rawtx).await;
let (killtranscribe, transcribereturn) = tokio::sync::mpsc::channel::<()>(1);
let (transsender, transcribed) = mpsc::unbounded::<(String, UserId)>();
let trans = tokio::task::spawn(crate::voice_events::transcription_thread(transcribe, transcribereturn, transsender));
let trans = {
let call = Arc::clone(&rawcall);
tokio::task::spawn(crate::voice_events::transcription_thread(transcribe, transcribereturn, transsender, call))
};

(trans, killtranscribe, transcribed)
};
Expand Down Expand Up @@ -247,12 +250,15 @@ pub async fn the_lüüp(rawcall: Arc<Mutex<Call>>, rawrx: mpsc::UnboundedReceive
log.log(&format!("Error sending play: {}\n", e)).await;
}
}
AudioPromiseCommand::Stop => {
AudioPromiseCommand::Stop(delay) => {
let r = snd.send(String::from("Stopped"));
if let Err(e) = r {
log.log(&format!("Error sending stop: {}\n", e)).await;
}
control.brk = true;
if let Some(delay) = delay {
tokio::time::sleep(delay).await;
}
}
AudioPromiseCommand::Paused(paused) => {
let val = paused.get_val(control.settings.pause);
Expand Down
14 changes: 9 additions & 5 deletions src/commands/music/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ pub enum AudioPromiseCommand {
Play(Vec<MetaVideo>),

Paused(OrToggle),
Stop,
// contains an optional delay to wait before leaving the channel
Stop(Option<tokio::time::Duration>),
Loop(OrToggle),
Repeat(OrToggle),
Shuffle(OrToggle),
Expand Down Expand Up @@ -275,6 +276,12 @@ impl VideoType {
VideoType::Url(v) => v.title.clone(),
}
}
pub async fn delete(&self) -> Result<(), Error> {
if let VideoType::Disk(v) = self {
v.delete()?;
}
Ok(())
}
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -347,10 +354,7 @@ pub struct MetaVideo {

impl MetaVideo {
pub async fn delete(&mut self) -> Result<(), Error> {
match self.video {
VideoType::Disk(ref mut video) => video.delete(),
_ => Ok(()),
}?;
self.video.delete().await?;
#[cfg(feature = "tts")]
if let Some(ref mut ttsmsg) = self.ttsmsg {
if let Ok(vid) = ttsmsg.wait_for().await {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/music/stop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ impl crate::CommandTrait for Stop {

if let Some(tx) = audio_command_handler.get_mut(&guild_id.to_string()) {
let (rtx, rrx) = serenity::futures::channel::oneshot::channel::<String>();
if tx.unbounded_send((rtx, AudioPromiseCommand::Stop)).is_err() {
if tx.unbounded_send((rtx, AudioPromiseCommand::Stop(None))).is_err() {
if let Err(e) = interaction.edit_original_interaction_response(&ctx.http, |response| response.content("Failed to send stop command")).await {
eprintln!("Failed to edit original interaction response: {:?}", e);
}
Expand Down
14 changes: 7 additions & 7 deletions src/commands/music/transcribe.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rand::seq::SliceRandom;

use serenity::model::prelude::interaction::autocomplete::AutocompleteInteraction;
use serenity::model::prelude::{ChannelId, GuildId, Message, UserId};
use serenity::model::prelude::{ChannelId, GuildId, Message};
use songbird::tracks::TrackHandle;
use songbird::{ffmpeg, Call};
use tokio::sync::Mutex;
Expand Down Expand Up @@ -232,7 +232,7 @@ impl Handler {
if self.current_handle.is_none() {
let mut call = self.call.lock().await;
let handle = call.play_source(ffmpeg(v.get_video().path.clone()).await.expect("Error creating ffmpeg source"));
let _ = handle.set_volume(1.5);
let _ = handle.set_volume(2.0);
self.current_handle = Some((handle, v.clone()));
// println!("Prepared next is done");
self.prepared_next = None;
Expand Down Expand Up @@ -368,7 +368,7 @@ pub struct TranscribeChannelHandler {
channels: Amh<ChannelId, Sender<RawMessage>>,
sender: Sender<RawMessage>,
receiver: Option<Receiver<RawMessage>>,
assigned_voice: Amh<UserId, crate::youtube::TTSVoice>,
assigned_voice: Amh<String, crate::youtube::TTSVoice>,
voice_cycle: Vec<crate::youtube::TTSVoice>,
}

Expand Down Expand Up @@ -420,11 +420,11 @@ impl TranscribeChannelHandler {
// attempt to get voice
let voice = {
let mut assigned_voice = self.assigned_voice.lock().await;
match assigned_voice.get(&msg.author.id) {
match assigned_voice.get(&msg.author.name) {
Some(v) => *v,
None => {
let v = self.voice_cycle.remove(0);
assigned_voice.insert(msg.author.id, v);
assigned_voice.insert(msg.author.name.clone(), v);
self.voice_cycle.push(v);
messages.push(RawMessage::announcement(msg, format!("{} is now using this voice to speak", msg.author.name), &v));
v
Expand All @@ -444,7 +444,7 @@ impl TranscribeChannelHandler {
messages
}
pub async fn send_tts(&mut self, ctx: &Context, msg: &Message) {
let undo_voice = { self.assigned_voice.lock().await.get(&msg.author.id).is_none() };
let undo_voice = { self.assigned_voice.lock().await.get(&msg.author.name).is_none() };
let messages = self.get_tts(ctx, msg).await;

let mut errored = false;
Expand All @@ -457,7 +457,7 @@ impl TranscribeChannelHandler {
}
}
if errored && undo_voice {
self.assigned_voice.lock().await.remove(&msg.author.id);
self.assigned_voice.lock().await.remove(&msg.author.name);
}
}
}
21 changes: 15 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
mod commands;

mod radio;
mod sam;
mod video;
mod youtube;
use std::collections::HashMap;
Expand Down Expand Up @@ -160,7 +161,7 @@ impl EventHandler for Handler {
match original_command {
"pause" => AudioPromiseCommand::Paused(OrToggle::Toggle),
"skip" => AudioPromiseCommand::Skip,
"stop" => AudioPromiseCommand::Stop,
"stop" => AudioPromiseCommand::Stop(None),
"looped" => AudioPromiseCommand::Loop(OrToggle::Toggle),
"shuffle" => AudioPromiseCommand::Shuffle(OrToggle::Toggle),
"repeat" => AudioPromiseCommand::Repeat(OrToggle::Toggle),
Expand Down Expand Up @@ -1051,7 +1052,7 @@ impl EventHandler for Handler {

if let Some(tx) = audio_command_handler.get_mut(&guild_id.to_string()) {
let (rtx, rrx) = serenity::futures::channel::oneshot::channel::<String>();
if let Err(e) = tx.unbounded_send((rtx, AudioPromiseCommand::Stop)) {
if let Err(e) = tx.unbounded_send((rtx, AudioPromiseCommand::Stop(None))) {
eprintln!("Failed to send stop command: {}", e);
};

Expand All @@ -1072,9 +1073,10 @@ impl EventHandler for Handler {
}

async fn message(&self, ctx: Context, new_message: Message) {
if new_message.author.bot {
return;
}
// println!("Message: {:?}", new_message);
// if new_message.author.bot {
// return;
// }
if new_message.content.trim().is_empty() {
return;
}
Expand Down Expand Up @@ -1402,7 +1404,7 @@ async fn main() {
println!("Sending stop command {}", i);
let (tx, rx) = serenity::futures::channel::oneshot::channel::<String>();

if let Err(e) = x.unbounded_send((tx, commands::music::AudioPromiseCommand::Stop)) {
if let Err(e) = x.unbounded_send((tx, commands::music::AudioPromiseCommand::Stop(None))) {
println!("Failed to send stop command: {}", e);
};

Expand Down Expand Up @@ -1466,6 +1468,8 @@ struct Config {
transcribe_token: String,
#[cfg(feature = "transcribe")]
alert_phrases_path: PathBuf,
#[cfg(feature = "transcribe")]
sam_path: PathBuf,
}

impl Config {
Expand Down Expand Up @@ -1509,6 +1513,8 @@ impl Config {
transcribe_token: if let Some(transcribe_token) = rec.transcribe_token { transcribe_token } else { Self::safe_read("\nPlease enter your transcribe token:") },
#[cfg(feature = "transcribe")]
alert_phrases_path: if let Some(alert_phrase_path) = rec.alert_phrase_path { alert_phrase_path } else { Self::safe_read("\nPlease enter your alert phrase path:") },
#[cfg(feature = "transcribe")]
sam_path: if let Some(sam_path) = rec.sam_path { sam_path } else { Self::safe_read("\nPlease enter your sam path:") },
}
} else {
println!("Welcome to my shitty Rust Music Bot!");
Expand Down Expand Up @@ -1540,6 +1546,7 @@ impl Config {
transcribe_token: Self::safe_read("\nPlease enter your transcribe token:"),
transcribe_url: Self::safe_read("\nPlease enter your transcribe url:"),
alert_phrases_path: Self::safe_read("\nPlease enter your alert phrase path:"),
sam_path: Self::safe_read("\nPlease enter your sam path:"),
}
};
std::fs::write(config_path.clone(), serde_json::to_string_pretty(&config).unwrap_or_else(|_| panic!("Failed to write\n{:?}", config_path))).expect("Failed to write config.json");
Expand Down Expand Up @@ -1611,4 +1618,6 @@ struct RecoverConfig {
transcribe_token: Option<String>,
#[cfg(feature = "transcribe")]
alert_phrase_path: Option<PathBuf>,
#[cfg(feature = "transcribe")]
sam_path: Option<PathBuf>,
}
24 changes: 24 additions & 0 deletions src/sam.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// all we have to do is run the command "node {config.sam_path} {text}" and stdout will be a wav file with the speech

use crate::video::Video;
use anyhow::Result;

pub fn get_speech(text: &str) -> Result<Video> {
let config = crate::Config::get();
let output = std::process::Command::new("node").arg(config.sam_path).arg(text).output()?;

if !output.status.success() {
return Err(anyhow::anyhow!("Failed to run command: {}", String::from_utf8_lossy(&output.stderr)));
}

// we're gonna write this wav file to a temp file
let mut path = config.data_path.clone();
path.push("tmp");
let id = nanoid::nanoid!(10);
let name = format!("{}-tts.wav", id);
path.push(&name);

std::fs::write(&path, output.stdout)?;

Video::from_path(path, "n/a".to_owned(), true, id)
}
39 changes: 30 additions & 9 deletions src/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

use std::path::PathBuf;

use anyhow::Error;
use anyhow::Result;
// use async_recursion::async_recursion;
use serde::Deserialize;
use serenity::async_trait;
use ytd_rs::Arg;

#[cfg(feature = "spotify")]
Expand All @@ -31,7 +32,7 @@ pub struct RawVideo {
pub duration: u32,
}

async fn get_videos(url: &str, allow_search: bool) -> Result<Vec<RawVideo>, anyhow::Error> {
async fn get_videos(url: &str, allow_search: bool) -> Result<Vec<RawVideo>> {
let mut bot_path = crate::Config::get().data_path.clone();
bot_path.push("cookies.txt");
let url = if !(url.starts_with("http://") || url.starts_with("https://")) {
Expand Down Expand Up @@ -94,7 +95,7 @@ impl Video {
// audio_only: bool,
allow_playlist: bool,
allow_search: bool,
) -> Result<Vec<VideoType>, anyhow::Error> {
) -> Result<Vec<VideoType>> {
let now = std::time::Instant::now();
let mut v = get_videos(url, allow_search).await?;
println!("Took {}ms to get videos", now.elapsed().as_millis());
Expand All @@ -106,7 +107,7 @@ impl Video {
}
Ok(v.iter().map(|v| VideoType::Url(VideoInfo { title: v.title.clone(), url: v.url.clone(), duration: Some(v.duration as u64) })).collect::<Vec<VideoType>>())
}
pub async fn download_video(url: &str, audio_only: bool, spoiler: bool, max_filesize: &str) -> Result<VideoType, anyhow::Error> {
pub async fn download_video(url: &str, audio_only: bool, spoiler: bool, max_filesize: &str) -> Result<VideoType> {
let v = Self::get_video(url, false, false).await?;
let v = v.first().ok_or(anyhow::anyhow!("No videos found"))?;
// convert to downloaded video type
Expand Down Expand Up @@ -189,7 +190,7 @@ impl Video {
// url: String,
// audio_only: bool,
// allow_playlist: bool,
// ) -> Result<Vec<VideoType>, anyhow::Error> {
// ) -> Result<Vec<VideoType>> {
// // if url is empty
// if url.is_empty() {
// return Self::get_video(crate::Config::get().bumper_url, audio_only, allow_playlist)
Expand Down Expand Up @@ -260,11 +261,11 @@ impl Video {
// Ok(videos.iter().map(|v| VideoType::Disk(v.clone())).collect())
// }
// }
pub fn delete(&self) -> Result<(), anyhow::Error> {
pub fn delete(&self) -> Result<()> {
std::fs::remove_file(self.path.clone())?;
Ok(())
}
pub fn from_path(path: PathBuf, url: String, audio_only: bool, id: String) -> Result<Self, Error> {
pub fn from_path(path: PathBuf, url: String, audio_only: bool, id: String) -> Result<Self> {
let file_name = match path.file_name().and_then(|f| f.to_str()) {
Some(f) => f,
None => return Err(anyhow::anyhow!("No file name")),
Expand All @@ -278,10 +279,30 @@ impl Video {
let playlist_index = file_name.split('_').nth(1).and_then(|s| s.split('.').next().and_then(|s| s.parse::<usize>().ok())).unwrap_or(0);
Ok(Self { url, path: path.clone(), title: title.to_string(), duration, video, playlist_index })
}
pub async fn delete_when_finished(self, handle: songbird::tracks::TrackHandle) -> Result<()> {
handle.add_event(songbird::events::Event::Track(songbird::events::TrackEvent::End), self)?;
Ok(())
}
}

#[async_trait]
impl songbird::EventHandler for Video {
async fn act(&self, ctx: &songbird::EventContext<'_>) -> Option<songbird::Event> {
if let songbird::EventContext::Track(track) = ctx {
for (state, _handle) in *track {
if state.playing.is_done() {
if let Err(e) = self.delete() {
println!("Failed to delete file: {}", e);
}
}
}
}
None
}
}

#[cfg(feature = "spotify")]
pub async fn get_spotify_shiz(url: String) -> Result<Vec<VideoType>, Error> {
pub async fn get_spotify_shiz(url: String) -> Result<Vec<VideoType>> {
let id = url.split('/').last().ok_or_else(|| anyhow::anyhow!("Invalid spotify URL"))?.split('?').next().ok_or_else(|| anyhow::anyhow!("Invalid spotify URL"))?.to_string();
let videos = get_spotify_song_title(id).await?;
if videos.is_empty() {
Expand All @@ -302,7 +323,7 @@ pub async fn get_spotify_shiz(url: String) -> Result<Vec<VideoType>, Error> {
}
}

async fn run_preprocessor(filepath: &PathBuf) -> Result<(), Error> {
async fn run_preprocessor(filepath: &PathBuf) -> Result<()> {
// run the preprocessor script located in the data folder if it exists and is executable
let mut path = crate::Config::get().data_path.clone();
path.push("preprocessor.sh");
Expand Down
Loading

0 comments on commit 92a6491

Please sign in to comment.