viddl/src/YTDL.hs

82 lines
2.6 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
import Control.Monad.Trans.Class
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
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"]
2021-07-06 16:25:55 +02:00
ytdl :: String -> Resolution -> ReaderT ViddlConfig IO (Either String FilePath)
2021-07-04 17:04:39 +02:00
ytdl url res = do
2021-07-06 16:25:55 +02:00
cfg <- ask
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]
2021-07-06 16:25:55 +02:00
processed <- lift $ doesFileExist fileName
2021-07-04 17:04:39 +02:00
if processed
then do
2021-07-06 16:25:55 +02:00
lift $ putStrLn $ "Returning existing ident " <> ident
2021-07-04 17:04:39 +02:00
pure (Right fileName)
else do
2021-07-06 16:25:55 +02:00
lift $ putStrLn $ "Processing new ident " <> ident
2021-07-04 17:04:39 +02:00
2021-07-06 16:25:55 +02:00
lift $ createDirectoryIfMissing True dir
2021-07-02 14:45:20 +02:00
2021-07-06 16:25:55 +02:00
lift $ print (resToArgs res <> ["-o", fileName, url])
2021-07-06 16:25:55 +02:00
ytdlProc <- lift $ createProcess (proc "youtube-dl" (resToArgs res <> ["-o", fileName, url]))
2021-07-02 14:45:20 +02:00
2021-07-04 17:04:39 +02:00
case ytdlProc of
(_, _, _, ph) -> do
2021-07-06 16:25:55 +02:00
exitCode <- lift $ waitForProcess ph
2021-07-04 17:04:39 +02:00
case exitCode of
ExitSuccess -> do
2021-07-06 16:25:55 +02:00
exists <- lift $ doesFileExist fileName
2021-07-04 17:04:39 +02:00
if exists
then do
-- wait 5 minutes and then delete the directory
2021-07-06 16:25:55 +02:00
_ <- lift $ forkIO $ threadDelay 300000000 >> removeDirectoryRecursive dir
2021-07-04 17:04:39 +02:00
pure (Right fileName)
else do
-- removeDirectoryRecursive dir
2021-07-04 17:04:39 +02:00
pure (Left "An unknown error prevented the output file from being created")
2021-07-02 14:45:20 +02:00
(ExitFailure status) -> pure (Left ("execution failed with status " <> show status))
2021-07-02 14:45:20 +02:00
2021-07-04 17:04:39 +02:00
_ -> pure (Left "Unable to create ytdlProcess for downloading video")