~jojo/stalin-bot

5bb29f7c12c22699b911b07bac084aba84fb5621 — JoJo a month ago 3440e63
Add cmds playnext, skip, pause, resume, queue, move, clear
2 files changed, 231 insertions(+), 26 deletions(-)

M Cargo.toml
M src/main.rs
M Cargo.toml => Cargo.toml +1 -1
@@ 9,6 9,6 @@ edition = "2021"
tracing = "0.1"
tracing-subscriber = "0.2"
tracing-futures = "0.2"
songbird = "0.2"
songbird = { version = "0.2", features = ["builtin-queue"] }
serenity = { version = "0.10", features = ["client", "standard_framework", "voice", "rustls_backend"] }
tokio = { version = "1.0", features = ["macros", "rt-multi-thread", "signal"] }
\ No newline at end of file

M src/main.rs => src/main.rs +230 -25
@@ 40,7 40,10 @@ impl EventHandler for Handler {
}

#[group]
#[commands(help, deafen, join, leave, mute, play, stop, ping, undeafen, unmute)]
#[commands(
    help, deafen, join, leave, mute, play, playnext, skip, pause, resume, queue, move_, clear,
    stop, ping, undeafen, unmute
)]
struct General;

#[tokio::main]


@@ 68,13 71,13 @@ async fn main() {
            .map_err(|why| println!("Client ended: {:?}", why));
    });

    tokio::signal::ctrl_c().await;
    tokio::signal::ctrl_c().await.ok();
    println!("Received Ctrl-C, shutting down.");
}

#[command]
async fn help(context: &Context, msg: &Message) -> CommandResult {
    check_msg(msg.channel_id.say(&context.http, "jag kan 'help', 'deafen', 'join', 'leave', 'mute', 'play <url>', 'stop', 'ping', 'undeafen', och 'unmute'").await);
    check_msg(msg.channel_id.say(&context.http, "jag kan 'help', 'deafen', 'join', 'leave', 'mute', 'play <url>', 'playnext', 'skip', 'pause', 'resume', 'queue', 'move <from> <to>', 'clear', 'stop', 'ping', 'undeafen', och 'unmute'").await);
    Ok(())
}



@@ 226,11 229,8 @@ async fn ping(context: &Context, msg: &Message) -> CommandResult {
    Ok(())
}

#[command]
#[only_in(guilds)]
async fn play(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
    join_(ctx, msg).await?;
    let query = match args.rest() {
async fn play_query(ctx: &Context, msg: &Message, args: Args) -> Option<String> {
    match args.rest() {
        "" => {
            check_msg(
                msg.channel_id


@@ 240,40 240,98 @@ async fn play(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
                    )
                    .await,
            );

            return Ok(());
            None
        }
        q if q.starts_with("http") => q.to_string(),
        q => "ytsearch:".to_string() + &q,
    };
        q if q.starts_with("http") => Some(q.to_string()),
        q => Some("ytsearch:".to_string() + &q),
    }
}

#[command]
#[only_in(guilds)]
async fn play(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
    join_(ctx, msg).await?;
    let query = if let Some(q) = play_query(ctx, msg, args).await {
        q
    } else {
        return Ok(());
    };
    println!("play {}", query);

    let guild = msg.guild(&ctx.cache).await.unwrap();
    let guild_id = guild.id;

    let manager = songbird::get(ctx)
        .await
        .expect("Songbird Voice client placed in at initialisation.")
        .clone();

    if let Some(handler_lock) = manager.get(guild_id) {
        let mut handler = handler_lock.lock().await;

        let source = match songbird::ytdl(&query).await {
            Ok(source) => source,
            Err(why) => {
                println!("Err starting source: {:?}", why);

                check_msg(msg.channel_id.say(&ctx.http, "Error sourcing ffmpeg").await);

                return Ok(());
            }
        };
        check_msg(
            msg.channel_id
                .say(
                    &ctx.http,
                    if !handler.queue().is_empty() {
                        "Queueing song"
                    } else {
                        "Playing song"
                    },
                )
                .await,
        );
        handler.enqueue_source(source);
        handler.queue().resume()?;
    } else {
        check_msg(
            msg.channel_id
                .say(&ctx.http, "Not in a voice channel to play in")
                .await,
        );
    }
    Ok(())
}

        handler.play_only_source(source);

        check_msg(msg.channel_id.say(&ctx.http, "Playing song").await);
#[command]
#[only_in(guilds)]
async fn playnext(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
    join_(ctx, msg).await?;
    let query = if let Some(q) = play_query(ctx, msg, args).await {
        q
    } else {
        return Ok(());
    };
    println!("playnext {}", query);
    let guild = msg.guild(&ctx.cache).await.unwrap();
    let guild_id = guild.id;
    let manager = songbird::get(ctx)
        .await
        .expect("Songbird Voice client placed in at initialisation.")
        .clone();
    if let Some(handler_lock) = manager.get(guild_id) {
        let mut handler = handler_lock.lock().await;
        let source = match songbird::ytdl(&query).await {
            Ok(source) => source,
            Err(why) => {
                println!("Err starting source: {:?}", why);
                check_msg(msg.channel_id.say(&ctx.http, "Error sourcing ffmpeg").await);
                return Ok(());
            }
        };
        check_msg(msg.channel_id.say(&ctx.http, "Playing song next").await);
        handler.enqueue_source(source);
        if handler.queue().len() > 2 {
            handler.queue().modify_queue(|q| {
                let x = q.pop_back().unwrap();
                q.insert(1, x);
            });
        }
        handler.queue().resume()?;
    } else {
        check_msg(
            msg.channel_id


@@ 281,24 339,171 @@ async fn play(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
                .await,
        );
    }
    Ok(())
}

#[command]
#[only_in(guilds)]
async fn skip(ctx: &Context, msg: &Message) -> CommandResult {
    join_(ctx, msg).await?;
    let guild = msg.guild(&ctx.cache).await.unwrap();
    let guild_id = guild.id;
    let manager = songbird::get(ctx)
        .await
        .expect("Songbird Voice client placed in at initialisation.")
        .clone();
    if let Some(handler_lock) = manager.get(guild_id) {
        let handler = handler_lock.lock().await;
        handler.queue().skip()?;
        check_msg(msg.channel_id.say(&ctx.http, "Skipping").await);
    }
    Ok(())
}

#[command]
#[only_in(guilds)]
async fn stop(ctx: &Context, msg: &Message) -> CommandResult {
async fn clear(ctx: &Context, msg: &Message) -> CommandResult {
    join_(ctx, msg).await?;
    let guild = msg.guild(&ctx.cache).await.unwrap();
    let guild_id = guild.id;
    let manager = songbird::get(ctx)
        .await
        .expect("Songbird Voice client placed in at initialisation.")
        .clone();
    if let Some(handler_lock) = manager.get(guild_id) {
        let handler = handler_lock.lock().await;
        handler
            .queue()
            .modify_queue::<_, songbird::error::TrackResult<()>>(|q| {
                for t in q.drain(1..) {
                    t.stop()?
                }
                Ok(())
            })?;
        check_msg(msg.channel_id.say(&ctx.http, "Clearing queue").await);
    }
    Ok(())
}

#[command]
#[only_in(guilds)]
async fn pause(ctx: &Context, msg: &Message) -> CommandResult {
    join_(ctx, msg).await?;
    let guild = msg.guild(&ctx.cache).await.unwrap();
    let guild_id = guild.id;
    let manager = songbird::get(ctx)
        .await
        .expect("Songbird Voice client placed in at initialisation.")
        .clone();
    if let Some(handler_lock) = manager.get(guild_id) {
        let handler = handler_lock.lock().await;
        handler.queue().pause()?;
        check_msg(msg.channel_id.say(&ctx.http, "Pausing").await);
    }
    Ok(())
}

#[command]
#[only_in(guilds)]
async fn resume(ctx: &Context, msg: &Message) -> CommandResult {
    join_(ctx, msg).await?;
    let guild = msg.guild(&ctx.cache).await.unwrap();
    let guild_id = guild.id;
    let manager = songbird::get(ctx)
        .await
        .expect("Songbird Voice client placed in at initialisation.")
        .clone();
    if let Some(handler_lock) = manager.get(guild_id) {
        let mut handler = handler_lock.lock().await;
        handler.stop();
        let handler = handler_lock.lock().await;
        handler.queue().resume()?;
        check_msg(msg.channel_id.say(&ctx.http, "Resuming").await);
    }
    Ok(())
}

#[command]
#[only_in(guilds)]
async fn queue(ctx: &Context, msg: &Message) -> CommandResult {
    join_(ctx, msg).await?;
    let guild = msg.guild(&ctx.cache).await.unwrap();
    let guild_id = guild.id;
    let manager = songbird::get(ctx)
        .await
        .expect("Songbird Voice client placed in at initialisation.")
        .clone();
    if let Some(handler_lock) = manager.get(guild_id) {
        let handler = handler_lock.lock().await;
        let s = handler
            .queue()
            .current_queue()
            .iter()
            .enumerate()
            .map(|(i, t)| {
                format!(
                    "{}. {}",
                    i,
                    t.metadata()
                        .title
                        .clone()
                        .or(t.metadata().source_url.clone())
                        .unwrap_or("???".to_string()),
                )
            })
            .intersperse("\n".to_string())
            .collect::<String>();
        check_msg(
            msg.channel_id
                .say(&ctx.http, format!("== Queue ==\n{}", s))
                .await,
        );
    }
    Ok(())
}

#[command("move")]
#[only_in(guilds)]
async fn move_(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
    join_(ctx, msg).await?;
    let from = args.single::<usize>()?;
    let to = args.single::<usize>()?;
    let guild = msg.guild(&ctx.cache).await.unwrap();
    let guild_id = guild.id;
    let manager = songbird::get(ctx)
        .await
        .expect("Songbird Voice client placed in at initialisation.")
        .clone();
    if let Some(handler_lock) = manager.get(guild_id) {
        let handler = handler_lock.lock().await;
        check_msg(msg.channel_id.say(&ctx.http, "Moving song in queue").await);
        handler.queue().modify_queue(|q| {
            q.remove(from).map(|x| {
                x.pause().ok();
                if to <= q.len() {
                    q.insert(to, x)
                } else {
                    q.push_back(x)
                }
            })
        });
        handler.queue().resume()?;
    }
    Ok(())
}

#[command]
#[only_in(guilds)]
async fn stop(ctx: &Context, msg: &Message) -> CommandResult {
    join_(ctx, msg).await?;
    let guild = msg.guild(&ctx.cache).await.unwrap();
    let guild_id = guild.id;
    let manager = songbird::get(ctx)
        .await
        .expect("Songbird Voice client placed in at initialisation.")
        .clone();
    println!("stop");
    if let Some(handler_lock) = manager.get(guild_id) {
        let handler = handler_lock.lock().await;
        handler.queue().stop();
        check_msg(msg.channel_id.say(&ctx.http, "Stopped playing").await);
    } else {
        check_msg(msg.channel_id.say(&ctx.http, "??? idiot").await);