-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from mizunashi-mana/initial-structing
Initial working
- Loading branch information
Showing
9 changed files
with
459 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,39 @@ | ||
{-# LANGUAGE OverloadedStrings #-} | ||
|
||
module Main where | ||
|
||
import Lib | ||
import Control.Concurrent | ||
import Control.Concurrent.STM | ||
import Control.Monad | ||
import Data.Maybe (isNothing) | ||
import qualified Data.Text as T | ||
import System.Cron | ||
|
||
import Bot.Config | ||
import Bot.Message | ||
import Bot.Run | ||
import Bot.Slack | ||
|
||
waiting :: Int -> IO () | ||
waiting n = forever $ threadDelay n | ||
|
||
main :: IO () | ||
main = someFunc | ||
main = do | ||
opts <- getBotOptions | ||
url <- T.pack <$> case optsWebhookUrl opts of | ||
Just v -> return v | ||
_ -> fail "Must be set webhook url" | ||
snaps <- getLtsSnapshots_ $ head defaultSnapshotsURLs | ||
let stmsnaps = newTVar snaps | ||
tids <- execSchedule $ | ||
addJob (updateSlackCronJob stmsnaps $ sendMsg url) "* * * * *" | ||
waiting 1000000 | ||
where | ||
slackConf = SlackConfig | ||
slackInfo = SlackPostInfo "haskell" "ltshaskell-bot" | ||
slackMessage = SlackMessage ":haskell:" | ||
|
||
sendMsg url info = sendSlackMessage | ||
(slackConf url) | ||
slackInfo | ||
(slackMessage $ defaultMessage info) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
{-# LANGUAGE OverloadedStrings #-} | ||
{-# LANGUAGE RecordWildCards #-} | ||
{-# LANGUAGE TupleSections #-} | ||
|
||
module Bot.Message where | ||
|
||
import Data.IntMap (IntMap) | ||
import qualified Data.IntMap as IntMap | ||
import Data.Semigroup | ||
import Data.Text (Text) | ||
import qualified Data.Text as T | ||
|
||
import Bot.Types | ||
|
||
data MessageLang | ||
= LanguageEnUs | ||
| LanguageJaJp | ||
deriving (Show, Eq, Ord, Enum) | ||
|
||
data MessageTheme | ||
= NormalTheme | ||
| DetailTheme | ||
| PrettyTheme | ||
deriving (Show, Eq, Ord, Enum) | ||
|
||
data LtsHaskellType | ||
= LtsHaskell Int | ||
| LatestLtsHaskell | ||
| NightlyLtsHaskell | ||
deriving (Show, Eq, Ord) | ||
|
||
data LtsHaskellUpdateInfo = LtsHaskellUpdateInfo | ||
{ getLtsHaskellType :: !LtsHaskellType | ||
, getBeforeVersion :: !Text | ||
, getAfterVersion :: !Text | ||
, getDetailUrl :: !Text | ||
} | ||
|
||
toLatestInfo :: LtsHaskellUpdates -> Maybe LtsHaskellUpdateInfo | ||
toLatestInfo updates = do | ||
info <- getLatestUpdate updates | ||
let befver = T.pack . show $ getBeforeLtsVersion info | ||
let aftver = T.pack . show $ getAfterLtsVersion info | ||
return $ LtsHaskellUpdateInfo | ||
LatestLtsHaskell | ||
befver aftver | ||
$ "https://www.stackage.org/" <> aftver | ||
|
||
toNightlyInfo :: LtsHaskellUpdates -> Maybe LtsHaskellUpdateInfo | ||
toNightlyInfo updates = do | ||
info <- getNightlyUpdate updates | ||
let befver = "nightly-" <> T.pack (show $ getBeforeNightlyDay info) | ||
let aftver = "nightly-" <> T.pack (show $ getAfterNightlyDay info) | ||
return $ LtsHaskellUpdateInfo | ||
NightlyLtsHaskell | ||
befver aftver | ||
$ "https://www.stackage.org/" <> aftver | ||
|
||
toLtsInfos :: LtsHaskellUpdates -> IntMap LtsHaskellUpdateInfo | ||
toLtsInfos updates = IntMap.fromList $ do | ||
(v, info) <- IntMap.toList $ getEachLtsUpdates updates | ||
let befver = T.pack . show $ getBeforeLtsVersion info | ||
let aftver = T.pack . show $ getAfterLtsVersion info | ||
return . (v,) $ LtsHaskellUpdateInfo | ||
(LtsHaskell v) | ||
befver aftver | ||
$ "https://www.stackage.org/" <> aftver | ||
|
||
defaultMessage :: LtsHaskellUpdateInfo -> Text | ||
defaultMessage LtsHaskellUpdateInfo{..} = | ||
"LTS Haskell updated! :tada: " | ||
<> "(" <> getBeforeVersion <> " -> " <> getAfterVersion <> ")\n" | ||
<> "For more information, see " <> getDetailUrl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,44 @@ | ||
module Bot.Run where | ||
module Bot.Run | ||
( getLtsSnapshots | ||
, getLtsSnapshots_ | ||
, checkLtsHaskellUpdates | ||
, updateSlackCronJob | ||
) where | ||
|
||
import Control.Concurrent.STM | ||
import Control.Monad | ||
import Control.Monad.Trans | ||
import Data.Aeson | ||
import Data.Maybe (fromMaybe) | ||
import Data.Text (Text) | ||
import qualified Data.Text as T | ||
import Network.HTTP.Conduit | ||
|
||
import Bot.Config | ||
import Bot.Message | ||
import Bot.Types | ||
|
||
getLtsSnapshots :: MonadIO m => Text -> m (Maybe Snapshots) | ||
getLtsSnapshots url = decode <$> simpleHttp (T.unpack url) | ||
|
||
getLtsSnapshots_ :: MonadIO m => Text -> m Snapshots | ||
getLtsSnapshots_ url = do | ||
msnaps <- getLtsSnapshots url | ||
case msnaps of | ||
Just snaps -> return snaps | ||
_ -> fail "Failed to get snapshots" | ||
|
||
checkLtsHaskellUpdates :: MonadIO m => Snapshots -> m (Snapshots, LtsHaskellUpdates) | ||
checkLtsHaskellUpdates snaps = do | ||
nsnaps <- getLtsSnapshots_ $ head defaultSnapshotsURLs | ||
return (nsnaps, checkUpdates snaps nsnaps) | ||
|
||
updateSlackCronJob :: MonadIO m => STM (TVar Snapshots) -> (LtsHaskellUpdateInfo -> m ()) -> m () | ||
updateSlackCronJob stmsnaps sendMsg = do | ||
snaps <- liftIO $ atomically $ stmsnaps >>= readTVar | ||
(newsnaps, updates) <- checkLtsHaskellUpdates snaps | ||
liftIO $ putStrLn $ "trace: " ++ show newsnaps | ||
liftIO $ atomically $ stmsnaps >>= flip writeTVar newsnaps | ||
fromMaybe (return ()) $ do | ||
info <- toLatestInfo updates | ||
return $ liftIO (putStrLn "trace: sending to slack...") >> sendMsg info |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
{-# LANGUAGE OverloadedStrings #-} | ||
{-# LANGUAGE RecordWildCards #-} | ||
|
||
module Bot.Slack | ||
( SlackMessage (..) | ||
, SlackPostInfo (..) | ||
, SlackPostData (..) | ||
, SlackConfig (..) | ||
, postToSlack | ||
, sendSlackMessage | ||
) where | ||
|
||
import Control.Monad | ||
import Control.Monad.Catch | ||
import Control.Monad.Trans | ||
import Control.Monad.Trans.Resource | ||
import Data.Aeson | ||
import qualified Data.ByteString as BS | ||
import qualified Data.ByteString.Lazy as BSL | ||
import Data.Text (Text) | ||
import qualified Data.Text as T | ||
import Network.HTTP.Conduit | ||
|
||
data SlackMessage = SlackMessage | ||
{ getIcon :: !Text | ||
, getText :: !Text | ||
} deriving (Show, Eq) | ||
|
||
data SlackPostInfo = SlackPostInfo | ||
{ getChannel :: !Text | ||
, getUserName :: !Text | ||
} deriving (Show, Eq) | ||
|
||
data SlackPostData = SlackPostData | ||
{ getInfo :: !SlackPostInfo | ||
, getMessage :: !SlackMessage | ||
} deriving (Show, Eq) | ||
|
||
instance ToJSON SlackPostData where | ||
toJSON SlackPostData{..} = object | ||
[ "channel" .= getChannel getInfo | ||
, "username" .= getUserName getInfo | ||
, "text" .= getText getMessage | ||
, "icon_emoji" .= getIcon getMessage | ||
] | ||
|
||
data SlackConfig = SlackConfig | ||
{ webhookUrl :: !Text | ||
} deriving (Show, Eq) | ||
|
||
getPostRequest :: | ||
MonadThrow m => [(BS.ByteString, BS.ByteString)] -> Text -> m Request | ||
getPostRequest pdata = return . urlEncodedBody pdata <=< parseUrl . T.unpack | ||
|
||
postToSlack :: SlackConfig -> SlackPostData -> IO BSL.ByteString | ||
postToSlack c d = runResourceT $ do | ||
req <- getPostRequest | ||
[("payload", BSL.toStrict . encode $ d)] | ||
$ webhookUrl c | ||
manager <- liftIO $ newManager tlsManagerSettings | ||
res <- httpLbs req manager | ||
return $ responseBody res | ||
|
||
sendSlackMessage :: MonadIO m => SlackConfig -> SlackPostInfo -> SlackMessage -> m () | ||
sendSlackMessage c i m = void $ liftIO $ postToSlack c $ SlackPostData i m |
Oops, something went wrong.