summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fig-frontend/src/Fig/Frontend.hs17
-rw-r--r--fig-frontend/src/Fig/Frontend/DB.hs20
-rw-r--r--fig-monitor-discord/src/Fig/Monitor/Discord.hs1
-rw-r--r--fig-monitor-twitch/src/Fig/Monitor/Twitch.hs30
-rw-r--r--fig-utils/src/Fig/Prelude.hs4
5 files changed, 71 insertions, 1 deletions
diff --git a/fig-frontend/src/Fig/Frontend.hs b/fig-frontend/src/Fig/Frontend.hs
index 3cab953..b1c6aed 100644
--- a/fig-frontend/src/Fig/Frontend.hs
+++ b/fig-frontend/src/Fig/Frontend.hs
@@ -65,4 +65,21 @@ app cfg = do
DB.hget db "songnotes" hash >>= \case
Nothing -> Tw.send . Tw.status Tw.status404 $ Tw.text "song not found"
Just val -> Tw.send . Tw.text $ decodeUtf8 val
+ , Tw.get "/api/poke/:name" do
+ target <- encodeUtf8 . toLower <$> Tw.param "name"
+ inbox <- fromMaybe [] <$> DB.smembers db ("pokeinbox:" <> target)
+ Tw.send . Tw.text . pretty . SExprList @Void $ SExprString . decodeUtf8 <$> inbox
+ , Tw.post "/api/poke/:name" do
+ me <- encodeUtf8 . toLower <$> Tw.param "ayem"
+ target <- encodeUtf8 . toLower <$> Tw.param "name"
+ DB.sismember db ("pokeinbox:" <> me) target >>= \case
+ True -> do
+ log . tshow $ "handshake between " <> me <> " and " <> target <> " complete!"
+ DB.srem db ("pokeinbox:" <> target) [me]
+ DB.srem db ("pokeinbox:" <> me) [target]
+ Tw.send $ Tw.text "complete"
+ False -> do
+ log . tshow $ "partial handshake from " <> me <> " to " <> target
+ DB.sadd db ("pokeinbox:" <> target) [me]
+ Tw.send $ Tw.text "partial"
]
diff --git a/fig-frontend/src/Fig/Frontend/DB.hs b/fig-frontend/src/Fig/Frontend/DB.hs
index d0641de..5ca8772 100644
--- a/fig-frontend/src/Fig/Frontend/DB.hs
+++ b/fig-frontend/src/Fig/Frontend/DB.hs
@@ -24,3 +24,23 @@ hget c key hkey = liftIO $ Redis.runRedis c do
hvals :: MonadIO m => Redis.Connection -> ByteString -> m (Maybe [ByteString])
hvals c key = liftIO $ Redis.runRedis c do
hush <$> Redis.hvals key
+
+sadd :: MonadIO m => Redis.Connection -> ByteString -> [ByteString] -> m ()
+sadd c key skeys = liftIO $ Redis.runRedis c do
+ _ <- Redis.sadd key skeys
+ pure ()
+
+srem :: MonadIO m => Redis.Connection -> ByteString -> [ByteString] -> m ()
+srem c key skeys = liftIO $ Redis.runRedis c do
+ _ <- Redis.srem key skeys
+ pure ()
+
+smembers :: MonadIO m => Redis.Connection -> ByteString -> m (Maybe [ByteString])
+smembers c key = liftIO $ Redis.runRedis c do
+ hush <$> Redis.smembers key
+
+sismember :: MonadIO m => Redis.Connection -> ByteString -> ByteString -> m Bool
+sismember c key skey = liftIO $ Redis.runRedis c do
+ Redis.sismember key skey >>= hush >>> \case
+ Just x -> pure x
+ Nothing -> pure False
diff --git a/fig-monitor-discord/src/Fig/Monitor/Discord.hs b/fig-monitor-discord/src/Fig/Monitor/Discord.hs
index a0c1b16..d5b09f3 100644
--- a/fig-monitor-discord/src/Fig/Monitor/Discord.hs
+++ b/fig-monitor-discord/src/Fig/Monitor/Discord.hs
@@ -6,7 +6,6 @@ import Fig.Prelude
import GHC.Real (fromIntegral)
-import Control.Arrow ((>>>))
import Control.Monad (unless)
import Control.Monad.Reader (runReaderT)
import qualified Control.Concurrent.Async as Async
diff --git a/fig-monitor-twitch/src/Fig/Monitor/Twitch.hs b/fig-monitor-twitch/src/Fig/Monitor/Twitch.hs
index 360e9c8..1889545 100644
--- a/fig-monitor-twitch/src/Fig/Monitor/Twitch.hs
+++ b/fig-monitor-twitch/src/Fig/Monitor/Twitch.hs
@@ -210,6 +210,29 @@ removeVIP vipuser user = do
unless (HTTP.statusIsSuccessful $ HTTP.responseStatus response) $ do
log $ "Failed to remove VIP: error " <> tshow (HTTP.statusCode $ HTTP.responseStatus response)
+shoutout :: Text -> Text -> Authed ()
+shoutout souser user = do
+ log $ "Shoutout to: \"" <> souser <> "\""
+ let body = Aeson.encode $ Aeson.object
+ [ "from_broadcaster_id" .= user
+ , "moderator_id" .= user
+ , "to_broadcaster_id" .= souser
+ ]
+ rc <- ask
+ initialRequest <- liftIO . HTTP.parseRequest $ unpack "https://api.twitch.tv/helix/chat/shoutouts"
+ let request = initialRequest
+ { method = encodeUtf8 "POST"
+ , requestBody = RequestBodyLBS body
+ , requestHeaders =
+ [ ("Authorization", encodeUtf8 $ "Bearer " <> rc.config.userToken)
+ , ("Client-Id", encodeUtf8 rc.config.clientId)
+ , ("Content-Type", "application/json")
+ ]
+ }
+ response <- liftIO $ HTTP.httpLbs request rc.manager
+ unless (HTTP.statusIsSuccessful $ HTTP.responseStatus response) $ do
+ log $ "Failed to shoutout: error " <> tshow (HTTP.statusCode $ HTTP.responseStatus response)
+
twitchEventClient :: Config -> (Text, Text) -> IO ()
twitchEventClient cfg busAddr = do
WS.runSecureClient "eventsub.wss.twitch.tv" 443 "/ws" \conn -> do
@@ -241,6 +264,7 @@ twitchEventClient cfg busAddr = do
cmds.subscribe [sexp|(monitor twitch prediction finish)|]
cmds.subscribe [sexp|(monitor twitch vip add)|]
cmds.subscribe [sexp|(monitor twitch vip remove)|]
+ cmds.subscribe [sexp|(monitor twitch shoutout)|]
forever do
resp <- WS.receiveData conn
case Aeson.eitherDecodeStrict resp of
@@ -404,6 +428,12 @@ twitchEventClient cfg busAddr = do
loginToMaybeUserId u >>= \case
Nothing -> pure ()
Just vipuser -> removeVIP vipuser user
+ | ev == [sexp|(monitor twitch shoutout)|] -> do
+ runAuthed cfg do
+ user <- loginToUserId cfg.userLogin
+ loginToMaybeUserId u >>= \case
+ Nothing -> pure ()
+ Just souser -> shoutout souser user
_ -> log $ "Invalid incoming message: " <> tshow d
)
(pure ())
diff --git a/fig-utils/src/Fig/Prelude.hs b/fig-utils/src/Fig/Prelude.hs
index 80e5829..060f197 100644
--- a/fig-utils/src/Fig/Prelude.hs
+++ b/fig-utils/src/Fig/Prelude.hs
@@ -46,6 +46,7 @@ module Fig.Prelude
, headMay, atMay
, throwLeft
, log
+ , (>>>)
, Pretty(..)
, Fix(..), unFix
@@ -113,6 +114,9 @@ throwLeft :: (Exception e, MonadThrow m) => (b -> e) -> Either b a -> m a
throwLeft f (Left x) = throwM $ f x
throwLeft _ (Right x) = pure x
+(>>>) :: (a -> b) -> (b -> c) -> a -> c
+(>>>) = flip (.)
+
log :: MonadIO m => Text -> m ()
log msg = do
t <- liftIO Time.getCurrentTime