Browse Source

Leave channel if nothing is playing

There is no reason for the bot to remain in a channel when it has
finished playing.

Make it leave when there is no next song in the queue.
Frans Bergman 3 years ago
parent
commit
5bc51291cf
2 changed files with 37 additions and 41 deletions
  1. 33 25
      src/audio/audio_state.rs
  2. 4 16
      src/audio/song_queue.rs

+ 33 - 25
src/audio/audio_state.rs

@@ -12,8 +12,10 @@ use songbird::{
     tracks::{TrackCommand, TrackHandle},
     Call, Event, EventContext, EventHandler as VoiceEventHandler, TrackEvent,
 };
+use std::time::Duration;
 use std::{mem::drop, sync::Arc};
 use tokio::sync::Mutex;
+use tokio::time::sleep;
 
 pub struct AudioState {
     queue: SongQueue,
@@ -39,12 +41,18 @@ impl AudioState {
             http: Mutex::new(ctx.http.clone()),
         };
         let audio_state = Arc::new(audio_state);
-        {
-            let audio_state = audio_state.clone();
-            tokio::spawn(async {
-                AudioState::play_audio(audio_state).await;
-            });
-        }
+        let my_audio_state = audio_state.clone();
+        tokio::spawn(async move {
+            // Leave if no music is playing within 1 minute
+            sleep(Duration::from_secs(60)).await;
+            let current_song = my_audio_state.current_song.lock().await;
+            if current_song.is_none() {
+                let mut handler = my_audio_state.handler.lock().await;
+                if let Err(e) = handler.leave().await {
+                    println!("Automatic leave failed: {:?}", e);
+                }
+            }
+        });
         audio_state
     }
 
@@ -63,14 +71,23 @@ impl AudioState {
         let is_looping = audio_state.is_looping.lock().await;
         let song = if *is_looping {
             let mut current_song = audio_state.current_song.lock().await;
-            current_song
-                .take()
-                .expect("logical error: expected current_song to be non-empty")
+            current_song.take()
         } else {
             audio_state.queue.pop().await
         };
         drop(is_looping);
 
+        let song = match song {
+            Some(song) => song,
+            None => {
+                let mut handler = audio_state.handler.lock().await;
+                if let Err(e) = handler.leave().await {
+                    println!("Error leaving channel: {:?}", e);
+                }
+                return;
+            }
+        };
+
         let source = ffmpeg_pcm(&song.url).await;
         let source = match source {
             Ok(source) => source,
@@ -120,6 +137,13 @@ impl AudioState {
             }
         };
         audio_state.queue.push(vec![song]).await;
+        let current_song = audio_state.current_song.lock().await;
+        if current_song.is_none() {
+            let audio_state = audio_state.clone();
+            tokio::spawn(async {
+                AudioState::play_audio(audio_state).await;
+            });
+        }
     }
 
     pub async fn send_track_command(
@@ -155,22 +179,6 @@ impl AudioState {
         let mut is_looping = audio_state.is_looping.lock().await;
         *is_looping = !*is_looping;
         Ok(*is_looping)
-        /*
-        if looping{
-            if *is_looping{
-                Err("already looping".to_string())
-            }else{
-                *is_looping = true;
-                Ok(())
-            }
-        }else{
-            if !*is_looping{
-                Err("not looping at the moment".to_string())
-            }else{
-                *is_looping = false;
-                Ok(())
-            }
-        }*/
     }
 
     pub async fn get_string(audio_state: Arc<AudioState>) -> String {

+ 4 - 16
src/audio/song_queue.rs

@@ -1,38 +1,26 @@
 use super::song::Song;
 use rand::seq::SliceRandom;
-use std::{cmp::min, collections::VecDeque, mem::drop, sync::Arc};
-use tokio::sync::{Mutex, Semaphore};
+use std::{cmp::min, collections::VecDeque, sync::Arc};
+use tokio::sync::Mutex;
 pub struct SongQueue {
     queue: Arc<Mutex<VecDeque<Song>>>,
-    queue_sem: Semaphore,
 }
 
 impl SongQueue {
     pub fn new() -> SongQueue {
         SongQueue {
             queue: Arc::new(Mutex::new(VecDeque::new())),
-            queue_sem: Semaphore::new(0),
         }
     }
     pub async fn push(&self, songs: Vec<Song>) {
         let mut queue = self.queue.lock().await;
-        let count = songs.len();
         for item in songs.into_iter() {
             queue.push_back(item);
         }
-        drop(queue);
-        self.queue_sem.add_permits(count);
     }
-    pub async fn pop(&self) -> Song {
-        self.queue_sem
-            .acquire()
-            .await
-            .expect("Error SongQueue.pop: semaphore acquire() failed")
-            .forget();
+    pub async fn pop(&self) -> Option<Song> {
         let mut queue = self.queue.lock().await;
-        queue
-            .pop_front()
-            .expect("Error SongQueue.pop: semaphore sync failure")
+        queue.pop_front()
     }
     pub async fn shuffle(&self) -> Result<(), String> {
         let mut queue = self.queue.lock().await;