module MusicScroll.LyricsPipeline
( SongByOrigin (..),
SearchResult (..),
ErrorCause (..),
noRepeatedSongs,
getLyricsFromAnywhere,
getLyricsOnlyFromWeb,
saveOnDb,
)
where
import Control.Applicative (Alternative (..))
import Control.Concurrent.MVar
import Control.Monad.Trans.Reader (ReaderT, runReaderT)
import Database.SQLite.Simple
import MusicScroll.DatabaseUtils
import MusicScroll.Providers.AZLyrics (azLyricsInstance)
import MusicScroll.Providers.MusiXMatch (musiXMatchInstance)
import MusicScroll.Providers.Utils (Lyrics (..))
import MusicScroll.TrackInfo
import MusicScroll.Web
import Pipes
import qualified Pipes.Prelude as PP
data SongByOrigin = DB | Web deriving (Int -> SongByOrigin -> ShowS
[SongByOrigin] -> ShowS
SongByOrigin -> String
(Int -> SongByOrigin -> ShowS)
-> (SongByOrigin -> String)
-> ([SongByOrigin] -> ShowS)
-> Show SongByOrigin
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SongByOrigin -> ShowS
showsPrec :: Int -> SongByOrigin -> ShowS
$cshow :: SongByOrigin -> String
show :: SongByOrigin -> String
$cshowList :: [SongByOrigin] -> ShowS
showList :: [SongByOrigin] -> ShowS
Show)
data SearchResult
= GotLyric SongByOrigin TrackInfo Lyrics
| ErrorOn ErrorCause
deriving (Int -> SearchResult -> ShowS
[SearchResult] -> ShowS
SearchResult -> String
(Int -> SearchResult -> ShowS)
-> (SearchResult -> String)
-> ([SearchResult] -> ShowS)
-> Show SearchResult
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SearchResult -> ShowS
showsPrec :: Int -> SearchResult -> ShowS
$cshow :: SearchResult -> String
show :: SearchResult -> String
$cshowList :: [SearchResult] -> ShowS
showList :: [SearchResult] -> ShowS
Show)
data ErrorCause = NotOnDB TrackByPath | NoLyricsOnWeb TrackInfo | ENoSong
deriving (Int -> ErrorCause -> ShowS
[ErrorCause] -> ShowS
ErrorCause -> String
(Int -> ErrorCause -> ShowS)
-> (ErrorCause -> String)
-> ([ErrorCause] -> ShowS)
-> Show ErrorCause
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ErrorCause -> ShowS
showsPrec :: Int -> ErrorCause -> ShowS
$cshow :: ErrorCause -> String
show :: ErrorCause -> String
$cshowList :: [ErrorCause] -> ShowS
showList :: [ErrorCause] -> ShowS
Show)
noRepeatedSongs :: Functor m => Pipe TrackIdentifier TrackIdentifier m a
noRepeatedSongs :: forall (m :: * -> *) a.
Functor m =>
Pipe TrackIdentifier TrackIdentifier m a
noRepeatedSongs = do
TrackIdentifier
firstSong <- Proxy () TrackIdentifier () TrackIdentifier m TrackIdentifier
Consumer' TrackIdentifier m TrackIdentifier
forall (m :: * -> *) a. Functor m => Consumer' a m a
await
TrackIdentifier -> Proxy () TrackIdentifier () TrackIdentifier m ()
forall (m :: * -> *) a x' x. Functor m => a -> Proxy x' x () a m ()
yield TrackIdentifier
firstSong
TrackIdentifier -> Pipe TrackIdentifier TrackIdentifier m a
forall {m :: * -> *} {b}.
Functor m =>
TrackIdentifier -> Proxy () TrackIdentifier () TrackIdentifier m b
loop TrackIdentifier
firstSong
where
loop :: TrackIdentifier -> Proxy () TrackIdentifier () TrackIdentifier m b
loop TrackIdentifier
prevSong = do
TrackIdentifier
newSong <- Proxy () TrackIdentifier () TrackIdentifier m TrackIdentifier
Consumer' TrackIdentifier m TrackIdentifier
forall (m :: * -> *) a. Functor m => Consumer' a m a
await
if (TrackIdentifier -> TrackIdentifierWithEq
TIWE TrackIdentifier
newSong) TrackIdentifierWithEq -> TrackIdentifierWithEq -> Bool
forall a. Eq a => a -> a -> Bool
/= (TrackIdentifier -> TrackIdentifierWithEq
TIWE TrackIdentifier
prevSong)
then TrackIdentifier -> Proxy () TrackIdentifier () TrackIdentifier m ()
forall (m :: * -> *) a x' x. Functor m => a -> Proxy x' x () a m ()
yield TrackIdentifier
newSong Proxy () TrackIdentifier () TrackIdentifier m ()
-> Proxy () TrackIdentifier () TrackIdentifier m b
-> Proxy () TrackIdentifier () TrackIdentifier m b
forall a b.
Proxy () TrackIdentifier () TrackIdentifier m a
-> Proxy () TrackIdentifier () TrackIdentifier m b
-> Proxy () TrackIdentifier () TrackIdentifier m b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> TrackIdentifier -> Proxy () TrackIdentifier () TrackIdentifier m b
loop TrackIdentifier
newSong
else TrackIdentifier -> Proxy () TrackIdentifier () TrackIdentifier m b
loop TrackIdentifier
prevSong
getLyricsFromAnywhere :: MVar Connection -> Pipe TrackIdentifier SearchResult IO a
getLyricsFromAnywhere :: forall a. MVar Connection -> Pipe TrackIdentifier SearchResult IO a
getLyricsFromAnywhere MVar Connection
connMvar = (TrackIdentifier -> IO SearchResult)
-> Pipe TrackIdentifier SearchResult IO a
forall (m :: * -> *) a b r. Monad m => (a -> m b) -> Pipe a b m r
PP.mapM TrackIdentifier -> IO SearchResult
go
where
go :: TrackIdentifier -> IO SearchResult
go :: TrackIdentifier -> IO SearchResult
go TrackIdentifier
ident = ReaderT (MVar Connection) IO SearchResult
-> MVar Connection -> IO SearchResult
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ((TrackByPath -> ReaderT (MVar Connection) IO SearchResult)
-> (TrackInfo -> ReaderT (MVar Connection) IO SearchResult)
-> TrackIdentifier
-> ReaderT (MVar Connection) IO SearchResult
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either TrackByPath -> ReaderT (MVar Connection) IO SearchResult
caseByPath TrackInfo -> ReaderT (MVar Connection) IO SearchResult
caseByInfoGeneral TrackIdentifier
ident) MVar Connection
connMvar
getLyricsOnlyFromWeb :: Pipe TrackInfo SearchResult IO a
getLyricsOnlyFromWeb :: forall a. Pipe TrackInfo SearchResult IO a
getLyricsOnlyFromWeb = (TrackInfo -> IO SearchResult) -> Pipe TrackInfo SearchResult IO a
forall (m :: * -> *) a b r. Monad m => (a -> m b) -> Pipe a b m r
PP.mapM TrackInfo -> IO SearchResult
forall (m :: * -> *).
(MonadIO m, Alternative m) =>
TrackInfo -> m SearchResult
caseByInfoWeb
caseByInfoGeneral :: TrackInfo -> ReaderT (MVar Connection) IO SearchResult
caseByInfoGeneral :: TrackInfo -> ReaderT (MVar Connection) IO SearchResult
caseByInfoGeneral TrackInfo
track =
let local :: ReaderT (MVar Connection) IO SearchResult
local = (TrackInfo -> Lyrics -> SearchResult)
-> (TrackInfo, Lyrics) -> SearchResult
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (SongByOrigin -> TrackInfo -> Lyrics -> SearchResult
GotLyric SongByOrigin
DB) ((TrackInfo, Lyrics) -> SearchResult)
-> ReaderT (MVar Connection) IO (TrackInfo, Lyrics)
-> ReaderT (MVar Connection) IO SearchResult
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> ReaderT (MVar Connection) IO (TrackInfo, Lyrics)
getDBSong (TrackInfo -> String
tUrl TrackInfo
track)
web :: ReaderT (MVar Connection) IO SearchResult
web = TrackInfo -> ReaderT (MVar Connection) IO SearchResult
forall (m :: * -> *).
(MonadIO m, Alternative m) =>
TrackInfo -> m SearchResult
caseByInfoWeb TrackInfo
track
err :: ReaderT (MVar Connection) IO SearchResult
err = SearchResult -> ReaderT (MVar Connection) IO SearchResult
forall a. a -> ReaderT (MVar Connection) IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ErrorCause -> SearchResult
ErrorOn (TrackInfo -> ErrorCause
NoLyricsOnWeb TrackInfo
track))
in ReaderT (MVar Connection) IO SearchResult
local ReaderT (MVar Connection) IO SearchResult
-> ReaderT (MVar Connection) IO SearchResult
-> ReaderT (MVar Connection) IO SearchResult
forall a.
ReaderT (MVar Connection) IO a
-> ReaderT (MVar Connection) IO a -> ReaderT (MVar Connection) IO a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ReaderT (MVar Connection) IO SearchResult
web ReaderT (MVar Connection) IO SearchResult
-> ReaderT (MVar Connection) IO SearchResult
-> ReaderT (MVar Connection) IO SearchResult
forall a.
ReaderT (MVar Connection) IO a
-> ReaderT (MVar Connection) IO a -> ReaderT (MVar Connection) IO a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ReaderT (MVar Connection) IO SearchResult
err
caseByInfoWeb :: (MonadIO m, Alternative m) => TrackInfo -> m SearchResult
caseByInfoWeb :: forall (m :: * -> *).
(MonadIO m, Alternative m) =>
TrackInfo -> m SearchResult
caseByInfoWeb TrackInfo
track =
SongByOrigin -> TrackInfo -> Lyrics -> SearchResult
GotLyric SongByOrigin
Web TrackInfo
track
(Lyrics -> SearchResult) -> m Lyrics -> m SearchResult
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ( Provider -> TrackInfo -> m Lyrics
forall (m :: * -> *).
(MonadIO m, Alternative m) =>
Provider -> TrackInfo -> m Lyrics
getLyricsFromWeb Provider
azLyricsInstance TrackInfo
track
m Lyrics -> m Lyrics -> m Lyrics
forall a. m a -> m a -> m a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Provider -> TrackInfo -> m Lyrics
forall (m :: * -> *).
(MonadIO m, Alternative m) =>
Provider -> TrackInfo -> m Lyrics
getLyricsFromWeb Provider
musiXMatchInstance TrackInfo
track
)
caseByPath :: TrackByPath -> ReaderT (MVar Connection) IO SearchResult
caseByPath :: TrackByPath -> ReaderT (MVar Connection) IO SearchResult
caseByPath TrackByPath
track =
(((TrackInfo -> Lyrics -> SearchResult)
-> (TrackInfo, Lyrics) -> SearchResult
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (SongByOrigin -> TrackInfo -> Lyrics -> SearchResult
GotLyric SongByOrigin
DB)) ((TrackInfo, Lyrics) -> SearchResult)
-> ReaderT (MVar Connection) IO (TrackInfo, Lyrics)
-> ReaderT (MVar Connection) IO SearchResult
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> ReaderT (MVar Connection) IO (TrackInfo, Lyrics)
getDBSong (TrackByPath -> String
tpPath TrackByPath
track))
ReaderT (MVar Connection) IO SearchResult
-> ReaderT (MVar Connection) IO SearchResult
-> ReaderT (MVar Connection) IO SearchResult
forall a.
ReaderT (MVar Connection) IO a
-> ReaderT (MVar Connection) IO a -> ReaderT (MVar Connection) IO a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> SearchResult -> ReaderT (MVar Connection) IO SearchResult
forall a. a -> ReaderT (MVar Connection) IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ErrorCause -> SearchResult
ErrorOn (TrackByPath -> ErrorCause
NotOnDB TrackByPath
track))
saveOnDb :: MVar Connection -> InsertStategy -> Pipe SearchResult SearchResult IO a
saveOnDb :: forall a.
MVar Connection
-> InsertStategy -> Pipe SearchResult SearchResult IO a
saveOnDb MVar Connection
mconn InsertStategy
strat = (SearchResult -> IO ()) -> Pipe SearchResult SearchResult IO a
forall (m :: * -> *) a r. Monad m => (a -> m ()) -> Pipe a a m r
PP.chain SearchResult -> IO ()
go
where
go :: SearchResult -> IO ()
go :: SearchResult -> IO ()
go (GotLyric SongByOrigin
Web TrackInfo
info Lyrics
lyr) = ReaderT (MVar Connection) IO () -> MVar Connection -> IO ()
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (InsertStategy
strat TrackInfo
info Lyrics
lyr) MVar Connection
mconn
go SearchResult
_otherwise = () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()