diff --git a/.gitignore b/.gitignore index 9da9ba1..496341d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ erl_crash.dump /config/config.exs .elixir_ls/ /tmp/ + +/bin \ No newline at end of file diff --git a/lib/HahaCommands/download.ex b/lib/HahaCommands/download.ex index bf5b76e..25d7990 100644 --- a/lib/HahaCommands/download.ex +++ b/lib/HahaCommands/download.ex @@ -5,6 +5,8 @@ defmodule HahaYes.Commands.Download do import Nostrum.Struct.Embed alias Nostrum.Api + alias HahaYes.Utility + @doc """ Download the video sent by the user with yt-dlp. @@ -33,29 +35,27 @@ defmodule HahaYes.Commands.Download do """ def execute(msg, _ws_state, args) do url = Enum.at(args, 0) - {:ok, loading} = Api.create_message(msg.channel_id, "Downloading...") + {:ok, loading} = Api.create_message(msg.channel_id, "⚙️ Processing...") - with {:ok, output} <- HahaYes.Utility.download(url, "#{System.tmp_dir}/#{msg.id}") do - {:ok, file} = File.stat(output) - file_size = - file.size / 1000000.0 - |> Decimal.from_float() - |> Decimal.round(2) - |> Decimal.to_float() + with {:ok, output} <- Utility.do_download(url, "#{System.tmp_dir()}/#{msg.id}", loading), + {:ok, output} <- Utility.do_compression(output, loading), + {:ok, file_size} <- Utility.validate_filesize(output) do + embed = + %Nostrum.Struct.Embed{} + |> put_color(431_948) + |> put_author( + "Downloaded by #{msg.author.username} (#{file_size} MB)", + url, + "https://cdn.discordapp.com/avatars/#{msg.author.id}/#{msg.author.avatar}.webp" + ) + |> put_footer( + "You can get the original video by clicking on the \"Downloaded by #{msg.author.username}\" message!" + ) + Api.create_message(msg.channel_id, files: [output], embeds: [embed]) + # Delete original message and loading message Api.delete_message(loading.channel_id, loading.id) Api.delete_message(msg) - - if file_size >= 25 do - Api.create_message(msg.channel_id, "File size is too big! (#{file_size})") - else - embed = - %Nostrum.Struct.Embed{} - |> put_color(431_948) - |> put_author("Downloaded by #{msg.author.username} (#{file_size} MB)", url, "https://cdn.discordapp.com/avatars/#{msg.author.id}/#{msg.author.avatar}.webp") - |> put_footer("You can get the original video by clicking on the \"Downloaded by #{msg.author.username}\" message!") - Api.create_message(msg.channel_id, files: [output], embeds: [embed]) - end else {:error, error} -> Api.create_message(msg.channel_id, "`#{error}`") end diff --git a/lib/events/messages.ex b/lib/events/messages.ex index 0763075..aea8a3c 100644 --- a/lib/events/messages.ex +++ b/lib/events/messages.ex @@ -15,13 +15,13 @@ defmodule HahaYes.Events.MessagesConsumer do def handle_event({:MESSAGE_CREATE, msg, ws_state}) when msg.author.bot != true do prefix = Application.get_env(:nostrum, :prefix) if String.starts_with?(msg.content, prefix) do - msg.content - |> String.replace(prefix, "") - |> String.split(" ") - |> Enum.at(0) - |> String.downcase() - |> String.capitalize() - |> then(& Module.safe_concat(HahaYes.Commands, &1).execute(msg, ws_state, String.split(String.replace(String.downcase(msg.content), "#{prefix}#{String.downcase(&1)} ", "")))) + msg.content + |> String.replace(prefix, "") + |> String.split(" ") + |> Enum.at(0) + |> String.downcase() + |> String.capitalize() + |> then(& Module.safe_concat(HahaYes.Commands, &1).execute(msg, ws_state, String.split(String.replace(String.downcase(msg.content), "#{prefix}#{String.downcase(&1)} ", "")))) end end end diff --git a/lib/haha_yes/utils.ex b/lib/haha_yes/utils.ex index 358a0dc..a701ba3 100644 --- a/lib/haha_yes/utils.ex +++ b/lib/haha_yes/utils.ex @@ -2,6 +2,8 @@ defmodule HahaYes.Utility do @moduledoc """ Various utilities to be reused in commands """ + require Logger + alias Nostrum.Api @doc """ Download utility with the format at 480p by default. @@ -9,24 +11,104 @@ defmodule HahaYes.Utility do ## Example ``` - iex> HahaYes.Utility.download("https://x.com/i/status/1844841048603783249", "#{System.tmp_dir}/test") - {:ok, "#{System.tmp_dir}/test.mp4"} + iex> HahaYes.Utility.download("https://x.com/i/status/1844841048603783249", "#{System.tmp_dir()}/test") + {:ok, "#{System.tmp_dir()}/test.mp4"} ``` ``` - iex> HahaYes.Utility.download("http://example.com", "#{System.tmp_dir}/test") + iex> HahaYes.Utility.download("http://example.com", "#{System.tmp_dir()}/test") {:error,"[generic] Extracting URL: http://example.com\\n[generic] example: Downloading webpage\\n[generic] example: Extracting information\\nERROR: Unsupported URL: http://example.com\\n"} ``` """ def download(url, output, format \\ "bestvideo[height<=?480]+bestaudio/best") do - opt = ["-f", format, url, "-o", "#{output}.%(ext)s", "--force-overwrites", "--playlist-reverse", "--no-playlist", "--remux-video=mp4/webm/mov", "--no-warnings"]; + opt = [ + "-f", + format, + url, + "-o", + "#{output}.%(ext)s", + "--force-overwrites", + "--playlist-reverse", + "--no-playlist", + "--remux-video=mp4/webm/mov", + "--no-warnings" + ] + + {error_output, status} = System.cmd("#{File.cwd!()}/bin/yt-dlp", opt, stderr_to_stdout: true) - {error_output, status} = System.cmd("yt-dlp", opt, [stderr_to_stdout: true]) if status !== 0 do {:error, error_output} else {:ok, Enum.at(Path.wildcard("#{output}.*"), 0)} end end + + @doc """ + Compression utility with the format at 540p60 by default. + + ## Example + + ``` + iex> HahaYes.Utility.compress("input.mp4", "#{System.tmp_dir()}/test") + {:ok, "#{System.tmp_dir()}/test.mp4"} + ``` + """ + def compress(input, output) do + opt = [ + "-i", + input, + "-Z", + "Social 25 MB 2 Minutes 540p60", + "-q", + "30", + "--turbo", + "--optimize", + "-o", + output + ] + + {error_output, status} = + System.cmd("#{File.cwd!()}/bin/HandBrakeCLI", opt, stderr_to_stdout: true) + + if status !== 0 do + {:error, error_output} + else + {:ok, output} + end + end + + def validate_filesize(input) do + {:ok, file} = File.stat(input) + + file_size = + (file.size / 1_000_000.0) + |> Decimal.from_float() + |> Decimal.round(2) + |> Decimal.to_float() + + if file_size <= 10.0 do + {:ok, file_size} + else + {:error, "File is too big! (#{file_size})"} + end + end + + def do_compression(input, message) do + message + |> Api.edit_message!("🗜 Compressing...") + + with {:error, _} <- validate_filesize(input) do + compress(input, "#{input}compressed.mp4") + else + _ -> {:ok, input} + end + end + + def do_download(input, output, message) do + message + |> Api.edit_message!("💾 Downloading...") + + download(input, output) + end end