viddl/src/YTDL.hs

89 lines
2.8 KiB
Haskell
Raw Normal View History

2021-07-04 17:04:39 +02:00
module YTDL (Resolution(..), ytdl) where
2021-07-02 14:45:20 +02:00
2021-07-06 16:25:55 +02:00
import Config
import Control.Monad.Trans.Reader
2021-07-04 17:04:39 +02:00
import Control.Concurrent (forkIO, threadDelay)
import Data.Digest.Pure.MD5
import qualified Data.ByteString.Lazy.UTF8 as BCU
2021-07-02 14:45:20 +02:00
import System.Directory
import System.Exit
import System.Process
import System.IO
data Resolution
= P144
| P240
| P360
| P480
| P720
| P1080
| PMAX
| Audio
deriving (Eq, Show)
wrapResString :: String -> [String]
wrapResString str = ["-f", concat ["bestvideo[ext=mp4,height<=", str,
"]+bestaudio[ext=m4a]/mp4[height<=", str, "]"], "--merge-output-format", "mp4"]
2021-07-02 14:45:20 +02:00
resToArgs :: Resolution -> [String]
resToArgs (P144) = wrapResString "144"
resToArgs (P240) = wrapResString "240"
resToArgs (P360) = wrapResString "360"
resToArgs (P480) = wrapResString "480"
resToArgs (P720) = wrapResString "720"
resToArgs (P1080) = wrapResString "1080"
resToArgs (PMAX) = ["-f", "bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4", "--merge-output-format", "mp4"]
2021-07-02 14:45:20 +02:00
resToArgs (Audio) = ["-x", "--audio-format", "mp3"]
extraYtdlArgs :: [String]
extraYtdlArgs = ["--no-playlist"]
2021-07-06 16:25:55 +02:00
ytdl :: String -> Resolution -> ReaderT ViddlConfig IO (Either String FilePath)
2021-07-09 18:16:55 +02:00
ytdl url res = ReaderT $ \cfg -> do
2021-07-06 16:25:55 +02:00
2021-07-04 17:04:39 +02:00
let ext = case res of { Audio -> ".mp3"; _ -> ".mp4" }
2021-07-02 14:45:20 +02:00
2021-07-04 17:04:39 +02:00
let ident = show . md5 . BCU.fromString $ url <> show res
2021-07-02 14:45:20 +02:00
2021-07-06 16:25:55 +02:00
let dir = concat [dlDir cfg, "/", ident]
2021-07-04 17:04:39 +02:00
let fileName = concat [dir, "/", ident, ext]
processed <- doesFileExist fileName
if processed
then do
putStrLn $ "Returning existing ident " <> ident
pure (Right fileName)
else do
putStrLn $ "Processing new ident " <> ident
createDirectoryIfMissing True dir
2021-07-02 14:45:20 +02:00
2021-07-09 18:16:55 +02:00
print (resToArgs res <> ["-o", fileName, url])
ytdlProc <- createProcess (proc "youtube-dl" (resToArgs res <> ["-o", fileName, url] <> extraYtdlArgs))
2021-07-04 17:04:39 +02:00
{ std_out = CreatePipe
, std_err = CreatePipe }
2021-07-02 14:45:20 +02:00
2021-07-04 17:04:39 +02:00
case ytdlProc of
2021-07-12 17:14:21 +02:00
(_, Just hout, Just herr, ph) -> do
2021-07-04 17:04:39 +02:00
err <- hGetContents herr
2021-07-12 17:14:21 +02:00
out <- hGetContents hout
2021-07-04 17:04:39 +02:00
exitCode <- waitForProcess ph
case exitCode of
ExitSuccess -> do
exists <- doesFileExist fileName
if exists
then do
-- wait 5 minutes and then delete the directory
_ <- forkIO $ threadDelay 300000000 >> removeDirectoryRecursive dir
pure (Right fileName)
else do
removeDirectoryRecursive dir
2022-03-14 10:52:32 +01:00
(pure . Left) "An unknown error prevented the output file from being created"
2021-07-02 14:45:20 +02:00
2022-03-14 10:52:32 +01:00
(ExitFailure status) ->
pure . Left $ "execution failed with status " ++ show status ++ ": " ++ out ++ ", " ++ err
2021-07-02 14:45:20 +02:00
2022-03-14 10:52:32 +01:00
_ -> (pure . Left) "Unable to create ytdlProcess for downloading video"