fatherjack.hs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. -- the comments are all outta wack too.
  2. --important, reminder, Digit ! This is stage4 type, not stage 3 type.
  3. -- therefor, mind your pastes from type 3 to type 4 need the " h" taken out of equations
  4. -- This is the Father Jack version of daskeb (digit's haskell bot).
  5. -- in this version
  6. -- its sole feature is to answer any question with:
  7. -- "Yes."
  8. -- or ...
  9. -- "That would be an ecumenical matter."
  10. import Data.List
  11. import Network
  12. import System.IO
  13. import System.Exit
  14. import Control.Arrow
  15. import Control.Monad.Reader
  16. import Control.Exception
  17. import Text.Printf
  18. import System.Random -- import random, it said, surely they meant import Random, trying System.Random
  19. --server = "irc.freenode.org"
  20. server = "irc.libera.chat"
  21. port = 6667
  22. --chan = "#fatherjack"
  23. --chan = "#ss-nsfw"
  24. --chan = "#systemcrafters"
  25. --chan = "#gentoo-weed"
  26. --chan = "#akashicwhatever"
  27. chan = "##?"
  28. --chan = "#cow"
  29. --chan = "#botwar"
  30. --chan = "#librespeech" -- :strontium.libera.chat 480 FatherJack #librespeech :Cannot join channel (+S) - SSL/TLS required
  31. --chan = "##spiritscience"
  32. --chan = "##philosophy" --blocked
  33. --chan = "##"
  34. ----------------------------chan = "#dbtfc"
  35. --chan = "#muhcows"
  36. --chan = "#twocows"
  37. nick = "FatherJack"
  38. -- The 'Net' monad, a wrapper over IO, carrying the bot's immutable state.
  39. type Net = ReaderT Bot IO
  40. data Bot = Bot { socket :: Handle }
  41. -- Set up actions to run on start and end, and run the main loop
  42. main :: IO ()
  43. main = bracket connect disconnect loop
  44. where
  45. disconnect = hClose . socket
  46. loop st = runReaderT run st
  47. -- Connect to the server and return the initial bot state
  48. connect :: IO Bot
  49. connect = notify $ do
  50. h <- connectTo server (PortNumber (fromIntegral port))
  51. hSetBuffering h NoBuffering
  52. return (Bot h)
  53. where
  54. notify a = bracket_
  55. (printf "Connecting to %s ... " server >> hFlush stdout)
  56. (putStrLn "done.")
  57. a
  58. -- We're in the Net monad now, so we've connected successfully
  59. -- Join a channel, and start processing commands
  60. run :: Net ()
  61. run = do
  62. write "NICK" nick
  63. write "USER" (nick++" 0 * :DigitsHaskellBot")
  64. write "JOIN" chan
  65. asks socket >>= listen
  66. -- Process each line from the server
  67. listen :: Handle -> Net ()
  68. listen h = forever $ do
  69. s <- init `fmap` io (hGetLine h)
  70. io (putStrLn s)
  71. if ping s then pong s else eval (clean s)
  72. where
  73. forever a = a >> forever a
  74. clean = drop 1 . dropWhile (/= ':') . drop 1
  75. ping x = "PING :" `isPrefixOf` x
  76. pong x = write "PONG" (':' : drop 6 x)
  77. ---- this is/was/willbe another way of doing it, with the randomised either answer.
  78. --let ecumenical = ["yes","that would be an ecumenical matter."]
  79. --let ecumenical = [("yes"),("that would be an ecumenical matter.")]
  80. --ecumenical = [("yes"),("that would be an ecumenical matter.")]
  81. -- oh oh array! lets try that!
  82. --ecumenical = array (1, 3) [(1, "yes"),(2, "that would be an ecumenical matter."),(3, "drink!")]
  83. -- Dispatch a command
  84. eval :: String -> Net ()
  85. ---- fatherjackbot:
  86. -- /THE/ FEATURE:
  87. ----iwishthisworkedsosomplesomethinglikesthis----eval x | "?" `isSuffixOf` x = privmsg (if "what""who""how""why""where""when" `isInfixOf` x then "that would be an ecumenical matter" else "yes")
  88. -- with a little help: https://stackoverflow.com/questions/56944717/how-can-i-make-the-target-of-a-conditional-be-any-of-many-search-for-any-of-a-l/56944826#56944826
  89. --interrogatives = ["what", "who", "how", "why", "where", "when"]
  90. --eval x | "?" `isSuffixOf` x = privmsg (if any (`isInfixOf` x) interrogatives then "that would be an ecumenical matter" else "yes")
  91. --
  92. --riddances = ["stfu", "shut up", "go away", "be quiet", "stop that", "enough", "!", "rage", "please stop", "Hush", "hush", "HUSH", "quiet you", "Quiet you", "QUIET", "please segfault", "segfault please", "fuckoff", "feckoff", "fuck off", "feck off", "fek off", "fekoff", "gtf", "please leave"] --standard
  93. riddances = ["stfu", "shut up", "go away", "be quiet", "stop that", "enough", "!!!", "rage", "please stop", "Hush", "hush", "HUSH", "quiet you", "Quiet you", "QUIET", "please segfault", "segfault please", "fuckoff", "feckoff", "fuck off", "feck off", "fek off", "fekoff", "gtf", "please leave"] --hardcore
  94. -----
  95. -------------
  96. ------------------------
  97. -----------------------------------
  98. --------------------------------------------------------------
  99. --interrogatives = ["what", "who", "how", "why", "where", "when", "which", " or ", "What", "Who", "How", "Why", "Where", "When", "Which", "Or ", "WHAT", "WHO", "HOW", "WHY", "WHERE", "WHEN", "WHICH", " OR "]
  100. interrogatives = ["wat", "what", "who", "how", "why", "where", "when", "which", " or ", "wtf", "What", "Who", "How", "Why", "Where", "When", "Which", "Or ", "WHAT", "WHO", "HOW", "WHY", "WHERE", "WHEN", "WHICH", " OR ", "WTF"]
  101. --
  102. -- suffix (use me, i worked fine!)
  103. eval x | "?" `isSuffixOf` x = privmsg (if any (`isInfixOf` x) interrogatives then "that would be an ecumenical matter" else "yes")
  104. --
  105. -- infix (testing) ... dangerously irritating, triggered by many urls.
  106. --eval x | "?" `isInfixOf` x = privmsg (if any (`isInfixOf` x) interrogatives then "that would be an ecumenical matter" else "yes")
  107. --
  108. --eval x | "?" `isSuffixOf` x = privmsg (if any (`isInfixOf` x) interrogatives then "that would be an ecumenical matter" else "yes")
  109. --
  110. ---------------------------------------------
  111. -------------------------------------------
  112. -----------------------------------
  113. ---------------------------
  114. -------------------
  115. -------------
  116. -----
  117. -- old prior scraps, kept here for elucidation of simpler forms
  118. --eval x | "?" `isSuffixOf` x = privmsg (if "FatherJackBot:" `isPrefixOf` x then "that would be an ecumenical matter" else "yes") -- well at least this one works.
  119. --eval x | "?" `isInfixOf` x = privmsg (if "FatherJackBot:" `isPrefixOf` x then "That would be an ecumenical matter." else "Yes.") -- well at least this one works.
  120. -- THE /ANTI/-FEATURE:
  121. eval x | "drink" `isInfixOf` x = privmsg (if "FatherJack:" `isPrefixOf` x then "glug glug glug" else "DRINK!")
  122. eval x | "Drink" `isInfixOf` x = privmsg (if "FatherJack:" `isPrefixOf` x then "glug glug glug" else "DRINK!")
  123. eval x | "drink" `isInfixOf` x = privmsg (if "gives FatherJack" `isInfixOf` x then "glug glug glug" else "DRINK!")
  124. eval x | "Drink" `isInfixOf` x = privmsg (if "givevs FatherJack" `isPrefixOf` x then "glug glug glug" else "DRINK!")
  125. -- ( THE OTHER /ANTI/-FEATURES: ) e.g.
  126. eval x | "Gerls!" `isInfixOf` x = privmsg (if "Fek!" `isInfixOf` x then "glug glug glug" else "DRINK!")
  127. -- but make these several arrays. gerls|Gerls|GERLS|girls|Girls|GIRLS etc and fek|Fek|FEK|feck|Feck|FECK etc etc.
  128. -- SAFETY DE-ANNOYANCE FEATURE
  129. --courtesy extra features: stfu & leave (/gtfo).
  130. -- the stfu feature is still in development
  131. -- current form, leaves if told to stfu directly.
  132. -- next intended dev goal: have gtfo > leave, and stfu > unresponsive mode
  133. -- (considering simply having gives drink be what makes fatherted go into stfu mode)
  134. -- (also considering having stfu include an optional timer, rather than toggle.)
  135. --eval x | "stfu" `isInfixOf` x = (if "FatherJackBot:" `isPrefixOf` x then write "QUIT" ":Exiting" >> io (exitWith ExitSuccess) else privmsg "hrm")
  136. --
  137. -- this version works great ----- or did i break it again, doh.
  138. --
  139. --eval x | "STFU!" `isInfixOf` x = (if "FatherJackBot:" `isPrefixOf` x then write "QUIT" ":Exiting" >> io (exitWith ExitSuccess) else return())
  140. --
  141. -- but i'm going to have a go putting in an aray like before.
  142. --
  143. --riddances = ["stfu", "shut up", "go away", "be quiet", "stop that", "enough", "!", "rage", "please stop"]
  144. --eval x | "!!!" `isInfixOf` x = privmsg (if any (`isInfixOf` x) riddances then write "QUIT" ":Exiting" >> io (exitWith ExitSuccess) else return())
  145. --desperate stab in the dark...
  146. --works but multiple declarations of eval... hrmmm
  147. eval x | "FatherJack" `isInfixOf` x = (if any (`isInfixOf` x) riddances then write "QUIT" ":Exiting" >> io (exitWith ExitSuccess) else return())
  148. --"that would be an ecumenical matter" else "yes")
  149. --
  150. -- TEMPORARY, For Morlog:
  151. eval ".seen wal" = privmsg ("no morlog, we've not seen em yet. keep looking.")
  152. --tbd: also, "i'm SO, SO sorry. :E :E :E" said before quitting...? it does take jack out of the well trained mode of that episode with the cardinals. twas sarcastic sorry to bishop brennan when he did that.
  153. --old basic leave, straight n clean, for reference:
  154. eval "!leave" = write "QUIT" ":Exiting" >> io (exitWith ExitSuccess)
  155. -- WEBSEARCH FEATURE
  156. eval x | "!search " `isPrefixOf` x = privmsg ("https://lmddgtfy.net/?q=" ++ (drop 8 x) ++ " ok?") -- added this back in to be useful.
  157. -- PARROT FEATURE
  158. eval x | "!repeat " `isPrefixOf` x = privmsg (drop 8 x) -- commented this out to minimise abuse
  159. eval _ = return () -- ignore everything else
  160. -- Send a privmsg to the current chan + server
  161. privmsg :: String -> Net ()
  162. privmsg s = write "PRIVMSG" (chan ++ " :" ++ s)
  163. -- Send a message out to the server we're currently connected to
  164. write :: String -> String -> Net ()
  165. write s t = do
  166. h <- asks socket
  167. io $ hPrintf h "%s %s\r\n" s t
  168. io $ printf "> %s %s\n" s t
  169. -- Convenience.
  170. io :: IO a -> Net a
  171. io = liftIO