add simple mux command
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
target/
 | 
			
		||||
result
 | 
			
		||||
@@ -20,9 +20,10 @@
 | 
			
		||||
          devShells = with pkgs; {
 | 
			
		||||
            default = mkShell
 | 
			
		||||
              {
 | 
			
		||||
                buildInputs = [
 | 
			
		||||
                buildInputs = with gst_all_1; [
 | 
			
		||||
                  rust-bin.nightly.latest.default
 | 
			
		||||
                  rust-analyzer
 | 
			
		||||
                  ffmpeg
 | 
			
		||||
                ];
 | 
			
		||||
              };
 | 
			
		||||
            bare = mkShell
 | 
			
		||||
@@ -47,6 +48,9 @@
 | 
			
		||||
            nativeBuildInputs = with pkgs; [
 | 
			
		||||
              rust-bin.nightly.latest.default
 | 
			
		||||
            ];
 | 
			
		||||
            buildInputs = with pkgs; [
 | 
			
		||||
              ffmpeg
 | 
			
		||||
            ];
 | 
			
		||||
            cargoSha256 = "sha256-DhWWUNDpDsao6lOogoM5UfUgrUfEmZvCpY0pxmr4/mI=";
 | 
			
		||||
          };
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								general.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								general.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
use serenity::framework::standard::{macros::command, CommandResult};
 | 
			
		||||
use serenity::model::prelude::*;
 | 
			
		||||
use serenity::prelude::*;
 | 
			
		||||
 | 
			
		||||
#[command]
 | 
			
		||||
pub async fn ping(ctx: &Context, msg: &Message) -> CommandResult {
 | 
			
		||||
    msg.reply(ctx, "Pong!").await?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								src/commands/general.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/commands/general.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
use serenity::framework::standard::{macros::command, CommandResult};
 | 
			
		||||
use serenity::model::prelude::*;
 | 
			
		||||
use serenity::prelude::*;
 | 
			
		||||
 | 
			
		||||
#[command]
 | 
			
		||||
pub async fn ping(ctx: &Context, msg: &Message) -> CommandResult {
 | 
			
		||||
    msg.reply(ctx, "Pong!").await?;
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								src/commands/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								src/commands/mod.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
pub mod general;
 | 
			
		||||
pub mod transcode;
 | 
			
		||||
							
								
								
									
										71
									
								
								src/commands/transcode.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/commands/transcode.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
use crate::lib::ffmpeg::FfmpegTranscode;
 | 
			
		||||
use serenity::{
 | 
			
		||||
    framework::standard::{macros::command, Args, CommandResult},
 | 
			
		||||
    http::AttachmentType,
 | 
			
		||||
    model::prelude::*,
 | 
			
		||||
    prelude::*,
 | 
			
		||||
};
 | 
			
		||||
use std::{fs::remove_file, path::Path, process::ExitStatus};
 | 
			
		||||
use tokio::fs::File;
 | 
			
		||||
 | 
			
		||||
#[command]
 | 
			
		||||
#[aliases("mux")]
 | 
			
		||||
pub async fn remux(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
 | 
			
		||||
    let q: Vec<&str> = args.raw().collect::<Vec<&str>>();
 | 
			
		||||
    if q.len() < 2 || q.len() > 4 {
 | 
			
		||||
        msg.reply(
 | 
			
		||||
            ctx,
 | 
			
		||||
            "Please use the proper syntax: `xxremux <audio> <video> [audio_codec] [video_codec]` or attach something",
 | 
			
		||||
        )
 | 
			
		||||
        .await?;
 | 
			
		||||
        return Ok(());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let mut trans = FfmpegTranscode::default();
 | 
			
		||||
 | 
			
		||||
    trans.add_input(q[0]).add_input(q[1]);
 | 
			
		||||
 | 
			
		||||
    if q.len() > 2 {
 | 
			
		||||
        trans.set_acodec(q[2]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if q.len() > 3 {
 | 
			
		||||
        trans.set_vcodec(q[3]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let ext = Path::new(&q[1]).extension().unwrap().to_str().unwrap();
 | 
			
		||||
    let output = format!("/tmp/{}{}.{}", "singh4-", msg.id, ext);
 | 
			
		||||
 | 
			
		||||
    trans
 | 
			
		||||
        .add_flag("shortest")
 | 
			
		||||
        .set_output(&output)
 | 
			
		||||
        .add_arg("map", "0:a:0")
 | 
			
		||||
        .add_arg("map", "1:v:0");
 | 
			
		||||
 | 
			
		||||
    let mut m = msg.reply_ping(ctx, "Working").await?;
 | 
			
		||||
    let exit_code: ExitStatus = trans.run();
 | 
			
		||||
    let file: File = File::open(&output).await?;
 | 
			
		||||
 | 
			
		||||
    if !exit_code.success() {
 | 
			
		||||
        msg.reply(ctx, "Some error occurred, please check the inputs")
 | 
			
		||||
            .await?;
 | 
			
		||||
    } else if file.metadata().await.unwrap().len() > 8 * 1024 * 1024 {
 | 
			
		||||
        msg.reply(ctx, "Output file larger than 8 MB").await?;
 | 
			
		||||
    } else {
 | 
			
		||||
        m.edit(ctx, |m| m.content("Uploading")).await?;
 | 
			
		||||
        msg.channel_id
 | 
			
		||||
            .send_message(ctx, |m| {
 | 
			
		||||
                m.add_file(AttachmentType::File {
 | 
			
		||||
                    file: &file,
 | 
			
		||||
                    filename: format!("{}.{}", msg.id, ext),
 | 
			
		||||
                })
 | 
			
		||||
                .content(msg.author.mention())
 | 
			
		||||
            })
 | 
			
		||||
            .await?;
 | 
			
		||||
        m.delete(ctx).await?;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    remove_file(output)?;
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										84
									
								
								src/lib/ffmpeg.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/lib/ffmpeg.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
use std::process::{Command, ExitStatus};
 | 
			
		||||
 | 
			
		||||
//Helper lib for running ffmpeg using std::process::Command
 | 
			
		||||
 | 
			
		||||
fn sanitize_arg<V: Into<String>>(value: V) -> String {
 | 
			
		||||
    let v: String = value.into();
 | 
			
		||||
    if v.starts_with('-') {
 | 
			
		||||
        v
 | 
			
		||||
    } else {
 | 
			
		||||
        format!("-{}", v)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct FfmpegTranscode {
 | 
			
		||||
    args: Vec<String>,
 | 
			
		||||
    out: String,
 | 
			
		||||
    acodec: String,
 | 
			
		||||
    vcodec: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for FfmpegTranscode {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        FfmpegTranscode {
 | 
			
		||||
            args: vec![],
 | 
			
		||||
            out: String::from("/tmp/ffmpeg"),
 | 
			
		||||
            acodec: String::from("copy"),
 | 
			
		||||
            vcodec: String::from("copy"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl FfmpegTranscode {
 | 
			
		||||
    pub fn add_flag<V: Into<String>>(&mut self, value: V) -> &mut Self {
 | 
			
		||||
        self.args.push(sanitize_arg(value));
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn add_flags<T: Into<String>, V: IntoIterator<Item = T>>(&mut self, value: V) -> &mut Self {
 | 
			
		||||
        for v in value {
 | 
			
		||||
            self.add_flag(v);
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn add_arg<K: Into<String>, V: ToString>(&mut self, key: K, value: V) -> &mut Self {
 | 
			
		||||
        self.args.push(sanitize_arg(key));
 | 
			
		||||
        self.args.push(value.to_string());
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn add_input<V: ToString>(&mut self, input: V) -> &mut Self {
 | 
			
		||||
        self.add_arg('i', input)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn set_output<V: ToString>(&mut self, output: V) -> &mut Self {
 | 
			
		||||
        self.out = output.to_string();
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn set_acodec<V: ToString>(&mut self, acodec: V) -> &mut Self {
 | 
			
		||||
        self.acodec = acodec.to_string();
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn set_vcodec<V: ToString>(&mut self, vcodec: V) -> &mut Self {
 | 
			
		||||
        self.vcodec = vcodec.to_string();
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn add_map(&mut self, inp: i32, s: char, out: i32) -> &mut Self {
 | 
			
		||||
        self.add_arg("map", format!("{}:{}:{}", inp, s, out))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn run(&self) -> ExitStatus {
 | 
			
		||||
        Command::new("ffmpeg")
 | 
			
		||||
            .args(&self.args)
 | 
			
		||||
            .args(vec!["-c:a", &self.acodec])
 | 
			
		||||
            .args(vec!["-c:v", &self.vcodec])
 | 
			
		||||
            .arg(&self.out)
 | 
			
		||||
            .status()
 | 
			
		||||
            .expect("FFmpeg failed to run")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								src/lib/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/lib/mod.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
pub mod ffmpeg;
 | 
			
		||||
							
								
								
									
										20
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -1,11 +1,15 @@
 | 
			
		||||
mod commands;
 | 
			
		||||
mod handler;
 | 
			
		||||
mod lib;
 | 
			
		||||
use commands::general::*;
 | 
			
		||||
use commands::transcode::*;
 | 
			
		||||
use handler::Handler;
 | 
			
		||||
use serenity::{
 | 
			
		||||
    client::bridge::gateway::ShardManager,
 | 
			
		||||
    framework::{
 | 
			
		||||
        standard::{
 | 
			
		||||
            help_commands,
 | 
			
		||||
            macros::help,
 | 
			
		||||
            macros::{group, help},
 | 
			
		||||
            Args, CommandGroup, CommandResult, HelpOptions,
 | 
			
		||||
        },
 | 
			
		||||
        StandardFramework,
 | 
			
		||||
@@ -22,6 +26,14 @@ impl TypeMapKey for ShardManagerContainer {
 | 
			
		||||
    type Value = Arc<Mutex<ShardManager>>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[group]
 | 
			
		||||
#[commands(remux)]
 | 
			
		||||
struct Transcode;
 | 
			
		||||
 | 
			
		||||
#[group]
 | 
			
		||||
#[commands(ping)]
 | 
			
		||||
struct General;
 | 
			
		||||
 | 
			
		||||
#[help]
 | 
			
		||||
#[max_levenshtein_distance(2)]
 | 
			
		||||
#[indention_prefix = "+"]
 | 
			
		||||
@@ -56,8 +68,10 @@ async fn main() {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let framework = StandardFramework::new()
 | 
			
		||||
        .configure(|c| c.owners(owners).prefix(","))
 | 
			
		||||
        .help(&MY_HELP);
 | 
			
		||||
        .configure(|c| c.owners(owners).prefix("xx"))
 | 
			
		||||
        .help(&MY_HELP)
 | 
			
		||||
        .group(&GENERAL_GROUP)
 | 
			
		||||
        .group(&TRANSCODE_GROUP);
 | 
			
		||||
 | 
			
		||||
    let mut client = Client::builder(&token)
 | 
			
		||||
        .framework(framework)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user