exh-1.0.0: src/Language/JavaScript/Extraction.hs
{-# LANGUAGE StrictData #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}
-- | Internal module. Extract values from mpv script
module Language.JavaScript.Extraction where
import Data.Aeson
import Data.ByteString.Lazy.Char8 (pack)
import Data.Maybe
import Data.Text (Text)
import Language.JavaScript.Parser.AST
import Optics.TH
import Text.Read
import Web.Exhentai.Utils hiding (div)
import Prelude hiding ((!!))
data MpvImage = MpvImage
{ name :: {-# UNPACK #-} Text,
key :: {-# UNPACK #-} Text,
thumbnail :: {-# UNPACK #-} Text
}
deriving (Show, Eq)
instance FromJSON MpvImage where
parseJSON = withObject "mpv image" $ \o ->
MpvImage
<$> o .: "n"
<*> o .: "k"
<*> o .: "t"
-- | All the variables defined in the scripts that came with the MPV
data Vars = Vars
{ gid :: {-# UNPACK #-} Int,
mpvkey :: {-# UNPACK #-} Text,
pageCount :: {-# UNPACK #-} Int,
imageList :: [MpvImage]
}
deriving (Show, Eq)
class As a b where
as :: a -> Maybe b
instance As JSExpression Int where
as (JSDecimal _ s) = decode (pack s)
as (JSExpressionBinary expr1 op expr2) = do
i1 <- as expr1
i2 <- as expr2
case op of
JSBinOpPlus {} -> pure $ i1 + i2
JSBinOpMinus {} -> pure $ i1 - i2
JSBinOpTimes {} -> pure $ i1 * i2
JSBinOpDivide {} -> pure $ i1 `div` i2
_ -> Nothing
as (JSUnaryExpression op expr) = do
i <- as expr
case op of
JSUnaryOpIncr {} -> pure $ i + 1
JSUnaryOpDecr {} -> pure $ i - 1
JSUnaryOpMinus {} -> pure $ - i
JSUnaryOpPlus {} -> pure i
_ -> Nothing
as (JSVarInitExpression _ initializer) = as initializer
as _ = Nothing
instance As JSExpression a => As JSVarInitializer a where
as (JSVarInit _ expr) = as expr
as _ = Nothing
instance As (JSCommaList JSExpression) a => As JSStatement a where
as (JSVariable _ l _) = as l
as _ = Nothing
instance {-# OVERLAPPABLE #-} As a b => As (JSCommaList a) b where
as (JSLOne x) = as x
as (JSLCons _ _ x) = as x
as _ = Nothing
instance As JSExpression Text where
as (JSStringLiteral _ s) = decode (pack s)
as (JSVarInitExpression _ initializer) = as initializer
as _ = Nothing
instance As JSPropertyName Text where
as (JSPropertyString _ s) = readMaybe s
as _ = Nothing
instance As JSArrayElement a => As JSExpression [a] where
as (JSArrayLiteral _ l _) = Just $ mapMaybe as l
as (JSVarInitExpression _ initializer) = as initializer
as _ = Nothing
instance As JSExpression a => As JSArrayElement a where
as (JSArrayElement expr) = as expr
as (JSArrayComma _) = Nothing
class AsPair a where
asPair :: a -> Maybe (Text, Text)
instance AsPair JSObjectProperty where
asPair (JSPropertyNameandValue n _ [expr]) = (,) <$> as n <*> as expr
asPair _ = Nothing
instance As (JSCommaList JSObjectProperty) [(Text, Text)] where
as (JSLCons xs _ p) = (:) <$> asPair p <*> as xs
as (JSLOne p) = pure <$> asPair p
as JSLNil = pure []
instance {-# OVERLAPPABLE #-} As (JSCommaList a) b => As (JSCommaTrailingList a) b where
as (JSCTLComma l _) = as l
as (JSCTLNone l) = as l
instance As JSObjectPropertyList MpvImage where
as l = do
mapping <- (as l :: Maybe [(Text, Text)])
thumbnail <- lookup "t" mapping
key <- lookup "k" mapping
name <- lookup "n" mapping
pure MpvImage {..}
instance As JSExpression MpvImage where
as (JSObjectLiteral _ l _) = as l
as _ = Nothing
instance As JSAST Vars where
as (JSAstProgram stmts _) = do
gidStmt <- stmts !! 1
gid <- as gidStmt
imgStmt <- stmts !! 3
imageList <- as imgStmt
keyStmt <- stmts !! 2
mpvkey <- as keyStmt
pgCountStmt <- stmts !! 9
pageCount <- as pgCountStmt
pure Vars {..}
as _ = Nothing
makeFieldLabelsWith noPrefixFieldLabels ''Vars
makeFieldLabelsWith noPrefixFieldLabels ''MpvImage
{-
extractEnv :: Text -> IO (Result Vars)
extractEnv script = quickjs $ do
eval_ $ encodeUtf8 script
gid' <- eval "gid"
mpvkey' <- eval "mpvkey"
imageList' <- eval "imagelist"
pageCount' <- eval "pagecount"
pure $ do
gid <- fromJSON gid'
mpvkey <- fromJSON mpvkey'
imageList <- fromJSON imageList'
pageCount <- fromJSON pageCount'
pure Vars {..}
-}