{-# LANGUAGE OverloadedStrings #-}
module Review where
import Control.Applicative ((<$>))
import qualified Data.ByteString.Lazy as LBS
import qualified Data.List as List
import Data.Text (Text)
import qualified Data.Text as Text
import Data.Text.Encoding (decodeUtf8)
import qualified GitHub
import Network.HTTP.Client (Manager, httpLbs, parseRequest,
responseBody)
import Text.HTML.TagSoup (parseTags)
import Text.HTML.TagSoup.Tree (TagTree (..), tagTree)
data Approval
= Approved
| Rejected
| Unknown
deriving (Show)
data Status = Status
{ _reviewerStatus :: Approval
, reviewerName :: Text
}
instance Show Status where
show (Status Approved name) = '+' : read (show name)
show (Status Rejected name) = '-' : read (show name)
show (Status Unknown name) = read (show name)
fetchHtml :: Manager -> GitHub.SimplePullRequest -> IO Text
fetchHtml mgr pr = do
let url = Text.unpack $ GitHub.getUrl $ GitHub.simplePullRequestHtmlUrl pr
-- hPutStrLn stderr $ "fetching " ++ url
req <- parseRequest url
decodeUtf8 . LBS.toStrict . responseBody <$> httpLbs req mgr
collectDiscussionItems :: TagTree Text -> [(Text, Text)]
collectDiscussionItems = reverse . go []
where
go acc TagLeaf {} = acc
go acc (TagBranch "div" [("class", cls)] (_ : TagBranch "div" _ (_ : TagBranch "a" [("href", name)] _ : _) : _))
| Text.isInfixOf "discussion-item-review" cls = (cls, Text.tail name) : acc
go acc (TagBranch _ _ body) =
foldl go acc body
extractApprovals :: [Status] -> [(Text, Text)] -> [Status]
extractApprovals = foldl extract
where
extract acc (cls, name)
| Text.isInfixOf "is-rejected" cls = Status Rejected name : acc
| Text.isInfixOf "is-approved" cls = Status Approved name : acc
| otherwise = acc
approvalsFromHtml :: [Status] -> Text -> [Status]
approvalsFromHtml statuses =
nubWith reviewerName
. extractApprovals statuses
. collectDiscussionItems
. TagBranch "xml" []
. tagTree
. parseTags
where
nubWith f = List.nubBy (\x y -> f x == f y)