| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- module LinkedIn.JobsUnifiedTopCard where
- import Control.Alt
- import Prelude
- import Data.Either (Either(..), hush)
- import Data.Foldable (class Foldable, foldMap, foldlDefault, foldrDefault)
- import Data.Generic.Rep (class Generic)
- import Data.List.Types (NonEmptyList)
- import Data.Maybe (Maybe(..))
- import Data.Show.Generic (genericShow)
- import Data.Traversable (class Traversable, sequence, traverseDefault)
- import LinkedIn (DetachedNode(..))
- import LinkedIn.Types (ParseError(..), Parser)
- import LinkedIn.Utils (detachNonEmptyTextChild, parseDetachedNode, queryAndDetachMany, queryAndDetachOne, queryManyAndParse, queryOneAndParse)
- data JobsUnifiedTopCardElement a = JobsUnifiedTopCardElement {
- header :: a,
- primaryDescription :: TopCardPrimaryDescription a,
- insights :: Maybe (NonEmptyList (TopCardInsight a)),
- actions :: Maybe (NonEmptyList (TopCardAction a))
- }
- data TopCardPrimaryDescription a = TopCardPrimaryDescription {
- link :: a,
- text :: a,
- tvmText :: Maybe (NonEmptyList a)
- }
- data TopCardInsight a = TopCardInsight {
- icon :: a,
- content :: TopCardInsightContent a
- }
- data TopCardInsightContent a =
- TopCardInsightContentSingle a
- | TopCardInsightContentSecondary {primary :: a, secondary :: NonEmptyList (TopCardSecondaryInsight a)}
- | TopCardInsightContentButton a
- data TopCardSecondaryInsight a =
- TopCardSecondaryInsightNested a
- | TopCardSecondaryInsightPlain a
- -- External application : <button id="ember74" class="jobs-apply-button artdeco-button artdeco-button--3 artdeco-button--primary ember-view artdeco-button--icon-right" role="link">
- -- LinkedIn Applcation : <button id="ember115" class="jobs-apply-button artdeco-button artdeco-button--3 artdeco-button--primary ember-view" data-job-id="3786945580">
- data TopCardAction a = TopCardActionApplyButton a
- derive instance Generic (JobsUnifiedTopCardElement a) _
- derive instance Eq a => Eq (JobsUnifiedTopCardElement a)
- instance Show a => Show (JobsUnifiedTopCardElement a) where
- show = genericShow
- derive instance Functor JobsUnifiedTopCardElement
- instance Foldable JobsUnifiedTopCardElement where
- foldMap f (JobsUnifiedTopCardElement {header, primaryDescription, insights, actions}) =
- f header
- <> foldMap f primaryDescription
- <> foldMap (foldMap (foldMap f)) insights
- <> foldMap (foldMap (foldMap f)) actions
- foldl = \x -> foldlDefault x
- foldr = \x -> foldrDefault x
- instance Traversable JobsUnifiedTopCardElement where
- sequence (JobsUnifiedTopCardElement {header, primaryDescription, insights, actions}) = ado
- h <- header
- pd <- sequence primaryDescription
- i <- traverseMayNel insights
- a <- traverseMayNel actions
- in JobsUnifiedTopCardElement {header: h, primaryDescription: pd, insights: i, actions: a}
- traverse = \x -> traverseDefault x
- traverseMayNel :: forall m t a. Traversable t => Applicative m => Maybe(NonEmptyList (t (m a))) -> m (Maybe (NonEmptyList (t a)))
- traverseMayNel (Just o) = map pure (sequence (map sequence o))
- traverseMayNel Nothing = pure Nothing
- derive instance Generic (TopCardPrimaryDescription a) _
- derive instance Eq a => Eq (TopCardPrimaryDescription a)
- instance Show a => Show (TopCardPrimaryDescription a) where
- show = genericShow
- derive instance Functor TopCardPrimaryDescription
- instance Foldable TopCardPrimaryDescription where
- foldMap f (TopCardPrimaryDescription {link, text, tvmText}) = f link <> f text <> foldMap (foldMap f) tvmText
- foldl = \x -> foldlDefault x
- foldr = \x -> foldrDefault x
- instance Traversable TopCardPrimaryDescription where
- sequence (TopCardPrimaryDescription {link, text, tvmText}) = ado
- l <- link
- t <- text
- tvm <- sequence (map sequence tvmText)
- in TopCardPrimaryDescription {link: l, text: t, tvmText: tvm}
- traverse = \x -> traverseDefault x
- derive instance Generic (TopCardInsight a) _
- derive instance Eq a => Eq (TopCardInsight a)
- instance Show a => Show (TopCardInsight a) where
- show = genericShow
- derive instance Functor TopCardInsight
- instance Foldable TopCardInsight where
- foldMap f (TopCardInsight {icon, content}) = f icon <> foldMap f content
- foldl = \x -> foldlDefault x
- foldr = \x -> foldrDefault x
- instance Traversable TopCardInsight where
- sequence (TopCardInsight {icon, content}) = ado
- i <- icon
- c <- sequence content
- in TopCardInsight {icon: i, content: c}
- traverse = \x -> traverseDefault x
- derive instance Generic (TopCardInsightContent a) _
- derive instance Eq a => Eq (TopCardInsightContent a)
- instance Show a => Show (TopCardInsightContent a) where
- show = genericShow
- derive instance Functor TopCardInsightContent
- instance Foldable TopCardInsightContent where
- foldMap f (TopCardInsightContentSingle a) = f a
- foldMap f (TopCardInsightContentButton a) = f a
- foldMap f (TopCardInsightContentSecondary {primary, secondary}) = f primary <> foldMap (foldMap f) secondary
- foldl = \x -> foldlDefault x
- foldr = \x -> foldrDefault x
- instance Traversable TopCardInsightContent where
- sequence (TopCardInsightContentSingle ins) = TopCardInsightContentSingle <$> ins
- sequence (TopCardInsightContentButton ins) = TopCardInsightContentButton <$> ins
- sequence (TopCardInsightContentSecondary {primary, secondary}) = ado
- p <- primary
- s <- sequence (map sequence secondary)
- in TopCardInsightContentSecondary {primary: p, secondary: s}
- traverse = \x -> traverseDefault x
- derive instance Generic (TopCardSecondaryInsight a) _
- derive instance Eq a => Eq (TopCardSecondaryInsight a)
- instance Show a => Show (TopCardSecondaryInsight a) where
- show = genericShow
- derive instance Functor TopCardSecondaryInsight
- instance Foldable TopCardSecondaryInsight where
- foldMap f (TopCardSecondaryInsightNested a) = f a
- foldMap f (TopCardSecondaryInsightPlain a) = f a
- foldl = \x -> foldlDefault x
- foldr = \x -> foldrDefault x
- instance Traversable TopCardSecondaryInsight where
- sequence (TopCardSecondaryInsightNested ins) = TopCardSecondaryInsightNested <$> ins
- sequence (TopCardSecondaryInsightPlain ins) = TopCardSecondaryInsightPlain <$> ins
- traverse = \x -> traverseDefault x
- derive instance Generic (TopCardAction a) _
- derive instance Eq a => Eq (TopCardAction a)
- instance Show a => Show (TopCardAction a) where
- show = genericShow
- derive instance Functor TopCardAction
- instance Foldable TopCardAction where
- foldMap f (TopCardActionApplyButton a) = f a
- foldl = \x -> foldlDefault x
- foldr = \x -> foldrDefault x
- instance Traversable TopCardAction where
- sequence (TopCardActionApplyButton app) = ado
- a <- app
- in TopCardActionApplyButton a
- traverse = \x -> traverseDefault x
- parseTopCardAction :: Parser (TopCardAction DetachedNode)
- parseTopCardAction n = do
- self <- parseDetachedNode n
- pure $ ado
- s <- self
- in TopCardActionApplyButton s
- parseTopCardSecondaryInsight :: Parser (TopCardSecondaryInsight DetachedNode)
- parseTopCardSecondaryInsight n = do
- nested <- queryAndDetachOne ":scope span[aria-hidden=true]" n
- plain <- parseDetachedNode n
- pure $ case nested, plain of
- Right p@(DetachedElement _), _ -> Right $ TopCardSecondaryInsightNested p
- _, Right p@(DetachedElement _) -> Right $ TopCardSecondaryInsightPlain p
- _, _ -> Left TextNotFoundError
- parseTopCardInsightContent :: Parser (TopCardInsightContent DetachedNode)
- parseTopCardInsightContent n = do
- primary <- queryAndDetachOne ":scope > span:first-child span[aria-hidden=true]" n
- secondary <- queryManyAndParse
- ":scope > span.job-details-jobs-unified-top-card__job-insight-view-model-secondary"
- parseTopCardSecondaryInsight
- n
- self <- parseDetachedNode n
- pure $ case primary, secondary, self of
- _, _, Right b@(DetachedElement {tag: "BUTTON"}) -> Right $ TopCardInsightContentButton b
- Right p@(DetachedElement _), Right s, _ -> Right $ TopCardInsightContentSecondary {primary: p, secondary: s}
- _, _, Right el@(DetachedElement _) -> Right $ TopCardInsightContentSingle el
- _, _, _ -> Left TextNotFoundError
- parseTopCardInsight :: Parser (TopCardInsight DetachedNode)
- parseTopCardInsight n = do
- icon <- queryAndDetachOne ":scope li-icon" n
- svg <- queryAndDetachOne ":scope svg" n
- content <- queryOneAndParse ":scope > span" parseTopCardInsightContent n
- actionButton <- queryOneAndParse ":scope > button" parseTopCardInsightContent n
- pure $ ado
- i <- icon <|> svg
- c <- content <|> actionButton
- in TopCardInsight {icon: i, content: c}
- parseTopCardPrimaryDescription :: Parser (TopCardPrimaryDescription DetachedNode)
- parseTopCardPrimaryDescription n = do
- link <- queryAndDetachOne ":scope > a" n
- text <- detachNonEmptyTextChild n
- tvmText <- queryAndDetachMany "span.tvm__text" n
- pure $ ado
- l <- link
- t <- text
- in TopCardPrimaryDescription {link: l, text: t, tvmText: hush tvmText}
- parseJobsUnifiedTopCardElement :: Parser (JobsUnifiedTopCardElement DetachedNode)
- parseJobsUnifiedTopCardElement n = do
- h1 <- queryAndDetachOne "h1.job-details-jobs-unified-top-card__job-title" n
- primary <- queryOneAndParse
- "div.job-details-jobs-unified-top-card__primary-description-container > div"
- parseTopCardPrimaryDescription
- n
- insights <- queryManyAndParse
- "li.job-details-jobs-unified-top-card__job-insight"
- parseTopCardInsight
- n
- actions <- queryManyAndParse
- ".mt5 button"
- parseTopCardAction
- n
- pure $ ado
- h <- h1
- p <- primary
- in JobsUnifiedTopCardElement {
- header: h,
- primaryDescription: p,
- insights: hush insights,
- actions: hush actions
- }
- toHeader ∷ forall a. JobsUnifiedTopCardElement a → a
- toHeader (JobsUnifiedTopCardElement {header}) = header
- toPrimaryDescriptionLink ∷ forall a. JobsUnifiedTopCardElement a → a
- toPrimaryDescriptionLink (JobsUnifiedTopCardElement {
- primaryDescription: TopCardPrimaryDescription {link}
- }) = link
- toPrimaryDescriptionText ∷ forall a. JobsUnifiedTopCardElement a → a
- toPrimaryDescriptionText (JobsUnifiedTopCardElement {
- primaryDescription: TopCardPrimaryDescription {text}
- }) = text
|