Add Main.hs
This commit is contained in:
parent
a90da3de6f
commit
82e49a4701
1 changed files with 66 additions and 0 deletions
66
Main.hs
Normal file
66
Main.hs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
{-# LANGUAGE OverloadedStrings #-}
|
||||
import Conduit
|
||||
import qualified Data.Conduit.Combinators as CC
|
||||
import System.Environment (getArgs)
|
||||
import System.FilePath (takeExtension, takeBaseName)
|
||||
import Data.Char (toLower)
|
||||
import qualified Data.Map.Strict as Map
|
||||
import System.Random (randomRIO)
|
||||
import Control.Monad (forM_)
|
||||
import Data.Foldable (toList)
|
||||
import System.Process (callProcess)
|
||||
|
||||
-- | Check if a file extension denotes a video.
|
||||
isVideoFile :: FilePath -> Bool
|
||||
isVideoFile path =
|
||||
let ext = map toLower (takeExtension path)
|
||||
in ext `elem` [".mp4", ".mkv", ".avi", ".mov", ".webm"]
|
||||
|
||||
-- | Split a filename (base name) into tokens by delimiters (-, _, ., space).
|
||||
splitTokens :: String -> [String]
|
||||
splitTokens "" = []
|
||||
splitTokens s =
|
||||
let (tok, rest) = break (`elem` ("-_. " :: String)) s
|
||||
in case tok of
|
||||
"" -> splitTokens (dropWhile (`elem` ("-_. " :: String)) rest)
|
||||
_ -> tok : splitTokens rest
|
||||
|
||||
-- | Compute prefix1 (first token) and prefix2 (first two tokens) for grouping.
|
||||
makePrefixes :: FilePath -> (String, Maybe String)
|
||||
makePrefixes fp =
|
||||
let name = map toLower (takeBaseName fp) -- base name without extension
|
||||
tokens = splitTokens name
|
||||
in case tokens of
|
||||
[] -> ("", Nothing)
|
||||
(x:[]) -> (x, Nothing)
|
||||
(x:y:_) -> (x, Just (x ++ " " ++ y))
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
args <- getArgs
|
||||
let dirs = if null args then ["."]
|
||||
else args
|
||||
|
||||
filePaths <- runConduitRes $
|
||||
yieldMany dirs
|
||||
.| concatMapMC (\dir -> runConduitRes $ sourceDirectoryDeep False dir .| sinkList)
|
||||
.| CC.filter isVideoFile
|
||||
.| sinkList
|
||||
|
||||
let prefixes = map makePrefixes filePaths
|
||||
countMap1 = Map.fromListWith (+) [ (p1, 1 :: Int) | (p1, _) <- prefixes, p1 /= "" ]
|
||||
countMap2 = Map.fromListWith (+) [ (p2, 1 :: Int) | (_, Just p2) <- prefixes ]
|
||||
isStandalone fp =
|
||||
let (p1, mp2) = makePrefixes fp
|
||||
c1 = Map.findWithDefault 0 p1 countMap1
|
||||
c2 = maybe 0 (\p2 -> Map.findWithDefault 0 p2 countMap2) mp2
|
||||
in c1 == 1 && c2 == 1
|
||||
candidates = filter isStandalone filePaths
|
||||
|
||||
if null candidates
|
||||
then putStrLn "No standalone movie found."
|
||||
else do
|
||||
idx <- randomRIO (0, length candidates - 1)
|
||||
let choice = candidates !! idx
|
||||
putStrLn $ "🎬 Playing movie: " ++ choice
|
||||
callProcess "mpv" [choice]
|
||||
Loading…
Reference in a new issue