diff --git a/README.md b/README.md index e0b09cb..a911135 100644 --- a/README.md +++ b/README.md @@ -209,6 +209,13 @@ for evaluation (e.g. `expected.tsv` files for the challenge or given when a challenge is created or a submission is done and the Gonito server must have access to such a special remote. +Integration with Slack/Discord +------------------------------ + +Gonito can send announcements to Slack or Discord via web hooks, e.g. +when new best result is achieved. Simply set the `ANNOUNCEMENT_HOOK` +environment variable to a Slack/Discord webhook. + Authors ------- diff --git a/Web/Announcements.hs b/Web/Announcements.hs index 0564864..56f84e0 100644 --- a/Web/Announcements.hs +++ b/Web/Announcements.hs @@ -16,19 +16,24 @@ import Prelude import Data.Aeson import Data.Default -data AnnouncementHook = SlackWebHook Text +data AnnouncementHook = SlackWebHook Text | DiscordWebHook Text toAnnouncementHook :: Text -> AnnouncementHook toAnnouncementHook url | ".slack." `isInfixOf` url = SlackWebHook url - | otherwise = error $ "unknown hook type" + | "discord.com" `isInfixOf` url = DiscordWebHook url + | otherwise = error $ unpack $ "unknown hook type '" <> url <> "'" sendAnnouncement :: AnnouncementHook -> Text -> IO () -sendAnnouncement (SlackWebHook hook) message = do +sendAnnouncement (SlackWebHook hook) message = sendAnnouncementViaJson hook "text" message +sendAnnouncement (DiscordWebHook hook) message = sendAnnouncementViaJson hook "content" message + +sendAnnouncementViaJson :: Text -> Text -> Text -> IO () +sendAnnouncementViaJson hook fieldName message = do let (Just (hookUrl, _)) = parseUrlHttps $ DTE.encodeUtf8 hook R.runReq def $ do - let payload = object [ "text" .= message ] + let payload = object [ fieldName .= message ] (_ :: IgnoreResponse) <- R.req R.POST hookUrl (R.ReqBodyJson payload) @@ -38,4 +43,8 @@ sendAnnouncement (SlackWebHook hook) message = do formatLink :: Maybe AnnouncementHook -> Text -> Text -> Text formatLink (Just (SlackWebHook _)) url title = "<" <> url <> "|" <> title <> ">" -formatLink Nothing url title = title <> "<" <> url <> ">" +formatLink (Just (DiscordWebHook _)) url title = formatLinkWithAngleBrackets url title +formatLink Nothing url title = formatLinkWithAngleBrackets url title + +formatLinkWithAngleBrackets :: Text -> Text -> Text +formatLinkWithAngleBrackets url title = title <> " <" <> url <> ">" diff --git a/docker-compose-simple.yml b/docker-compose-simple.yml index 8363a6c..c3427a4 100644 --- a/docker-compose-simple.yml +++ b/docker-compose-simple.yml @@ -16,6 +16,7 @@ services: - AUTO_OPENING=${GONITO_AUTO_OPENING:-false} - IS_PUBLIC=${GONITO_IS_PUBLIC:-true} - JSON_WEB_KEY=${JSON_WEB_KEY} + - ANNOUNCEMENT_HOOK=${GONITO_ANNOUNCEMENT_HOOK} ports: - 3000:3000 volumes: diff --git a/docker-compose.yml b/docker-compose.yml index 49a4a7d..10f6b50 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,6 +29,7 @@ services: - VIEWING_PROGRESS_STYLE=${GONITO_VIEWING_PROGRESS_STYLE:-with-web-sockets} - AUTO_TEAM=${GONITO_AUTO_TEAM:-false} - TEAM_FIELD=$GONITO_TEAM_FIELD + - ANNOUNCEMENT_HOOK=${GONITO_ANNOUNCEMENT_HOOK} expose: - "3000" volumes: diff --git a/sample.env b/sample.env index 2389027..44fa227 100644 --- a/sample.env +++ b/sample.env @@ -26,3 +26,6 @@ GONITO_TEAM_FIELD=given_name # # Note: at the moment, only RS256 is handled. JSON_WEB_KEY={"kty":"RSA", "alg":"RS256", "use":"sig", "kid":"h01jmt_bD-1Di8i_GYbEV2a4NxhptzySHO-R8VuNHVA", "e":"AQAB", "n": "qG1elE6KPW3BYMxNpgK73MoksvbrUSfpRY4z9hU5iMsJREyD5Ar6XpjM1xAr6G7xglnOoumPC9o6FqhDHihm6QdJ5s5MA9ZyGkbi--kvy9Qc2d_VIGU-UR4vwyk3hAwXOFLhoknpQrJBJmMQvGFdas1Yr-m9EIWwT1zN7neHZkRUYZSVyQw_XghtMIWAUsLnhr6mM7nstHLafgxe5Qamzuc4K5EC_qipFXu4ugYkMDnaknlhkT43m7tcduVDnv5GV_4dBesF7FRII8tgUQWyw3Ty_FIoq43SInUPU_9cxA-qPGQz5C50th2aJl1z1snpLWS_1Zfsa8lnFsMj8_oh6w"} + +# Announcements can be sent to Slack or Discord via a given web hook +GONITO_ANNOUNCEMENT_HOOK=https://discord.com/api/webhooks/123456789/abcdefghijklmnopqrstuvwxz123456789