git.iko.soy/rowtype-yoga/royo
on main help sign in
Rework code [re]execution flow
commit2584d0628d3c4206e6adb0c088af07021881b515 authorPureFunctor <purefunctor@gmail.com> dateTue 27 Jul 2021, 15:43 (5 years ago) parentf625445
4 files changed+62−24
spago.dhall+1 src/Discord/DiscordJS.js+5 src/Discord/DiscordJS.purs+6−1 src/Royo/Discord/Bot.purs+50−23
spago.dhall+1
@@ -21,6 +21,7 @@ You can edit this file as you like.
2121 , "node-process"
2222 , "prelude"
2323 , "psci-support"
24+ , "refs"
2425 , "strings"
2526 , "stringutils"
2627 ]
src/Discord/DiscordJS.js+5
@@ -17,6 +17,11 @@ exports.onMessageUpdate = (callback) => (client) => () => {
1717 client.on("messageUpdate", (oldMsg, newMsg) => callback(oldMsg)(newMsg)())
1818}
1919
20+exports.offMessageUpdate = (client) => () => {
21+ // TODO: use removeListener?
22+ client.removeAllListeners("messageUpdate");
23+}
24+
2025exports.loginImpl = token => client => () => {
2126 return client.login(token).then(() => client)
2227}
src/Discord/DiscordJS.purs+6−1
@@ -8,7 +8,7 @@ import Effect.Aff (Aff)
88import Effect.Class (liftEffect)
99import Prim.Row (class Lacks)
1010
11−foreign import data Client ∷ #Type -> Type
11+foreign import data Client ∷ Row Type -> Type
1212
1313foreign import newClient ∷ Effect (Client ())
1414
@@ -40,6 +40,7 @@ type Message =
4040 { channel ∷ Channel
4141 , content ∷ String {- not really... -}
4242 , author ∷ User
43+ , id ∷ String {- Snowflake ~ String -}
4344 }
4445
4546foreign import removeAllReactionsImpl ∷ Message -> Effect (Promise Unit)
@@ -79,6 +80,10 @@ foreign import onMessage ∷
7980foreign import onMessageUpdate ∷
8081 ∀ r. (Message -> Message -> Effect Unit) -> Client ( loggedIn ∷ Void | r ) -> Effect Unit
8182
83+foreign import offMessageUpdate ::
84+ ∀ r. Client ( loggedIn :: Void | r ) -> Effect Unit
85+
86+
8287foreign import sendStringImpl ∷ NonEmptyString -> Channel -> Effect (Promise Unit)
8388
8489sendString ∷ NonEmptyString -> Channel -> Aff Unit
src/Royo/Discord/Bot.purs+50−23
@@ -9,23 +9,24 @@ import Data.Foldable (intercalate)
99import Data.Interpolate (i)
1010import Data.Maybe (Maybe(..))
1111import Data.String (Pattern(..), contains, drop, length, stripPrefix, stripSuffix, trim)
12+import Data.String.NonEmpty as NES
1213import Data.String.NonEmpty.Internal (NonEmptyString(..))
13−import Data.String.NonEmpty.Internal as NES
1414import Data.String.Utils (startsWith)
15−import Discord.DiscordJS (ChannelType(..), DiscordToken, Message, createDMChannel, getChannelType, login, newClient, onMessage, onMessageUpdate, react, removeAllReactions, sendString)
16−import Effect.Aff (Aff, attempt, launchAff_, message)
15+import Discord.DiscordJS (DiscordToken, Message, createDMChannel, login, newClient, offMessageUpdate, onMessage, onMessageUpdate, react, sendString)
16+import Effect.Aff (Aff, Milliseconds(..), attempt, delay, error, forkAff, killFiber, launchAff_, message)
1717import Effect.Class (liftEffect)
1818import Effect.Class.Console (log)
19+import Effect.Ref as Effect
1920import Yoga.APIClient (CompileResult, YogaToken, compileAndRun)
2021
2122_BOT_USER_ID ∷ String
22−_BOT_USER_ID = "741940687263760475"
23+_BOT_USER_ID = "625255925627748363"
2324
2425mentionPrefix1 ∷ String
2526mentionPrefix1 = i "<@!" _BOT_USER_ID ">"
2627
2728_OTHER_BOT_USER_ID ∷ String
28−_OTHER_BOT_USER_ID = "741945029056135179"
29+_OTHER_BOT_USER_ID = "625255925627748363"
2930
3031mentionPrefix2 ∷ String
3132mentionPrefix2 = i "<@&" _OTHER_BOT_USER_ID ">"
@@ -41,32 +42,58 @@ runBot ∷ YogaToken -> DiscordToken -> Aff Unit
4142runBot yogaToken discordToken = do
4243 newClient <- newClient # liftEffect
4344 client <- newClient # login discordToken
44− client # onMessage (launchAff_ <$> messageHandler) # liftEffect
45− client # onMessageUpdate (launchAff_ `map map map` messageUpdatedHandler) # liftEffect
45+ client # onMessage (launchAff_ <$> messageHandler client) # liftEffect
4646 where
47− messageUpdatedHandler _ msg = printErrors msg do
48− when (getChannelType msg.channel == TextChannel) $ removeAllReactions msg
49− msg # react rewindEmoji
50− messageHandler msg
51−
52− messageHandler msg@{ content, channel } = printErrors msg do
47+ messageHandler client msg@{ content } = printErrors msg do
5348 when (isMention content) do
54− case parseCodeBlock content of
55− Nothing -> do
56− sendBasicInstructions msg
57− Just code -> do
58− res <- compileAndRun yogaToken { code: prepareCode code }
59− case res of
60− Left cr -> sendCompileProblem msg code cr
61− Right rr -> case NES.fromString rr.stdout, NES.fromString rr.stderr of
62− Just stdout, _ -> do
49+ parseAndRun msg
50+
51+ -- Create a countdown
52+ stopFR <- do
53+ stopF <- forkAff stopSession
54+ Effect.new stopF # liftEffect
55+
56+ let recvMessage old new =
57+ when (msg.id == old.id && msg.id == new.id) do
58+ -- Kill countdown
59+ stopF_ <- Effect.read stopFR # liftEffect
60+ killFiber (error "messageHandler: reset timer") stopF_
61+
62+ -- Renew countdown
63+ stopF <- forkAff stopSession
64+ Effect.write stopF stopFR # liftEffect
65+
66+ parseAndRun new
67+
68+ -- Register to messageUpdate
69+ client # onMessageUpdate (launchAff_ `map map map` recvMessage) # liftEffect
70+
71+ where
72+ -- Unregister from messageUpdate
73+ stopSession = do
74+ delay (Milliseconds 10_000.0)
75+ client # offMessageUpdate # liftEffect
76+
77+ parseAndRun msg@{ channel, content } = do
78+ case parseCodeBlock content of
79+ Nothing -> do
80+ sendBasicInstructions msg
81+ Just code -> do
82+ res <- compileAndRun yogaToken { code: prepareCode code }
83+ case res of
84+ Left cr ->
85+ sendCompileProblem msg code cr
86+ Right rr ->
87+ case NES.fromString rr.stdout, NES.fromString rr.stderr of
88+ Just _, _ -> do
6389 msg # react robotMuscleEmoji
6490 channel # sendString (NonEmptyString (prepareOutput rr.stdout))
65− Nothing, Just stderr -> do
91+ Nothing, Just _ -> do
6692 msg # react sirenEmoji
6793 sendRunProblem msg code rr.stderr
6894 _, _ -> channel # sendString (NonEmptyString "Something is weird")
6995
96+
7097sendBasicInstructions :: Message -> Aff Unit
7198sendBasicInstructions msg = do
7299 msg # react thinkingEmoji