/servers.rkt

http://github.com/elibarzilay/rudybot · Shell · 285 lines · 257 code · 21 blank · 7 comment · 5 complexity · 3cdc4d53fc478d9a98001f09dc3caa54 MD5 · raw file

  1. #! /bin/sh
  2. #| Hey Emacs, this is -*-scheme-*- code!
  3. if [ "x$BOTDEBUG" != "xno" ]; then
  4. exec racket -l errortrace --require $0 --main -- ${1+"$@"}
  5. else
  6. exec racket --require $0 --main -- ${1+"$@"}
  7. fi
  8. |#
  9. #lang racket
  10. (require "loop.rkt"
  11. (except-in "vars.rkt" log)
  12. "git-version.rkt"
  13. (except-in "quotes.rkt" main)
  14. (except-in "clearenv.rkt" main)
  15. (only-in "incubot.rkt" make-test-corpus)
  16. (only-in "iserver.rkt" make-incubot-server)
  17. scheme/port)
  18. (define (real-server)
  19. (let-values ([(ip op) (tcp-connect (*irc-server-hostname*)
  20. (*irc-server-port*))])
  21. (file-stream-buffer-mode op 'line)
  22. (values ip op)))
  23. (define (make-preloaded-server op)
  24. (lambda ()
  25. (values (let-values ([(ip op) (make-pipe)])
  26. (thread
  27. (lambda ()
  28. (define (meh str)
  29. (format ":n!n@n PRIVMSG #c :~a"
  30. str))
  31. (define (c str)
  32. (format ":n!n@n PRIVMSG #c :~a: ~a"
  33. (unbox *my-nick*)
  34. str))
  35. (define (p str)
  36. (format ":n!n@n PRIVMSG ~a :~a"
  37. (unbox *my-nick*)
  38. str))
  39. (for-each
  40. (lambda (line)
  41. (display line op)
  42. (display "\r\n" op))
  43. (cond
  44. (#f
  45. (list
  46. (meh "Hey everyone! What's happening?")
  47. (c "uptime")
  48. (c "settle")
  49. (meh "frotz: plotz.")
  50. (c "everyone")
  51. (c "plotz")
  52. (meh "\1ACTION fred eats salami\1")
  53. (c "salami")))
  54. (#f
  55. ;; Typical stuff from ircd-seven
  56. `(":bartol.freenode.net NOTICE * :*** No Ident response"
  57. ":notice!NickServ@services. NOTICE rudybot :This nickname is registered. Please choose a different nickname, or identify via \u0002/msg NickServ identify <password>\u0002.")
  58. )
  59. (#f
  60. `(
  61. ":t8!n=foo@bar PRIVMSG #ch :,t8"
  62. ":t8!n=foo@bar PRIVMSG #ch :,t8 fr"
  63. ":t8!n=foo@bar PRIVMSG #ch :,t8 fr de"
  64. ,(format ":t8!n=foo@bar PRIVMSG #ch :~a: t8 en it kits, cats, sacks, wives: how many were going to St Ives?" (unbox *my-nick*))
  65. ":t8!n=foo@bar PRIVMSG #ch :,t8 en hu I will not buy this record, it is scratched"
  66. ":t8!n=foo@bar PRIVMSG #ch : ,t8 en hu I will not buy this translation; it contains leading whitespace"))
  67. (else
  68. `(
  69. ,(c (format "eval (error \"foo\\r\\nQUIT bar\")"))
  70. ":freenode-connect!freenode@freenode/bot/connect PRIVMSG upstartbot :\u0001VERSION\u0001"
  71. "foO!"
  72. "PING :localhost."
  73. ":sykopomp!n=user@host-70-45-40-165.onelinkpr.net PRIVMSG #emacs :\u0001ACTION is wondering if it's easy to save any logs from bitlbee to a different folder than all the irc logs.\u0001"
  74. ":arcfide!n=arcfide@VPNBG165-7.umsl.edu PRIVMSG #scheme :\u0001ACTION sighs. \u0001"
  75. ":action!n=No@unaffiliated/clue PRIVMSG #ch :\u0001ACTION does an action!\u0001"
  76. ":invite!n=No@unaffiliated/clue INVITE upstartbot :##mircscripts"
  77. ":join!n=Aaron@b415.adsl.ecomtel.com.au JOIN :#scheme"
  78. ":duncanm!n=duncanm@b415.adsl.ecomtel.com.au JOIN :#scheme"
  79. ":kick!n=chandler@opendarwin/developer/chandler KICK #scheme lumon :http://www.penny-arcade.com/comic/2003/11/07/"
  80. ":kick2!n=asc@pdpc/supporter/active/kensanata KICK #emacs jordanb :you too"
  81. ":mode!ChanServ@services. MODE #emacs +o alephnull "
  82. ":nick!n=Aaron@b415.adsl.ecomtel.com.au NICK :AshyIsMe"
  83. ":nick2!n=Aaron@b415.adsl.ecomtel.com.au NICK :AshyIsMe"
  84. ":notice!NickServ@services. NOTICE rudybot :This nickname is registered. Please choose a different nickname, or identify via \u0002/msg NickServ identify <password>\u0002."
  85. ":notice2!i=christel@freenode/staff/exherbo.christel NOTICE $* :[Global Notice] Aaaaand we make contact! A small step for manki..oh wai-! Sorry about the delay there and thank you for your patience. Services are now back up!"
  86. ":part!n=Akaleb@bl6-112-187.dsl.telepac.pt PART #emacs :\"Changed major mode\""
  87. ":quit!n=adam@yax.org.uk PRIVMSG #ch :This is my last utterance before quitting."
  88. ":quit!n=adam@yax.org.uk QUIT :Client Quit"
  89. ":topic!n=javachat@cpe-74-71-143-65.twcny.res.rr.com TOPIC #emacs :-=[ www.WHAK.com ]=- Make Free/Fun Graphics Online At http://www.ImageGenerator.org =)"
  90. ,(c "version")
  91. ,(c "SOURCE")
  92. ,(c "quote")
  93. ,(format ":t8!n=foo@bar PRIVMSG #ch :~a: t8 en it kits, cats, sacks, wives: how many were going to St Ives?" (unbox *my-nick*))
  94. ":t8!n=foo@bar PRIVMSG #ch :,t8 en hu I will not buy this record, it is scratched"
  95. ":t8!n=foo@bar PRIVMSG #ch : ,t8 en hu I will not buy this translation; it contains leading whitespace"
  96. ,(format ":t8!n=foo@bar PRIVMSG #ch :~a: t8 snord horde" (unbox *my-nick*))
  97. ,(format ":jordanb!n@n PRIVMSG #c :~a: quote" (unbox *my-nick*))
  98. ,(format ":jordanb!n@n PRIVMSG #c :Let's say something memorable")
  99. ,(format ":n!n@n PRIVMSG #emacs :,...")
  100. ,(format ":n!n@n PRIVMSG #not-emacs :,...")
  101. ,(format ":n!n@n PRIVMSG #c :~a:~a" (unbox *my-nick*) "lookboynospaces")
  102. ,(format ":n!n@n PRIVMSG #c :~a:" (unbox *my-nick*) )
  103. ,@(for/list ([action (in-list (list "action" "invite" "join" "kick" "kick2" "mode" "nick" "nick2" "notice" "notice2" "part" "quit" "topic"))])
  104. (c (format "seen ~a" action)))
  105. ":niven.freenode.net 001 rudybot :Welcome to the freenode IRC Network rudybot"
  106. ,(format
  107. ":NickServ!NickServ@services. NOTICE ~a :If this is your nickname, type /msg NickServ \0002IDENTIFY\0002 <password>"
  108. (unbox *my-nick*))
  109. ,@(apply
  110. append
  111. (for/list ([expr (in-list '((+ 2 1)
  112. (begin (display (+ 2 1)) (newline))
  113. (let loop ()
  114. (printf "Yaa!!")
  115. (loop))
  116. (require srfi/1)
  117. (make-list 100000)
  118. (apply values (make-list 100000))))])
  119. (list
  120. (c (format "eval ~s" expr))
  121. (p (format "eval ~s" expr)))))
  122. ,@(map c (list "quote" "uptime"))
  123. ,@(map p (list "This is a private utterance, and I certainly hope you don't divulge it!!"))
  124. ,(c "seen n")
  125. ;; This should work, if you set BOTMASTER in the
  126. ;; environment before running this test.
  127. ,(c "system ls /")
  128. ;; This should yield an empty string.
  129. ,(c "eval (getenv \"PATH\")")
  130. ;; This should simply not blow up.
  131. ,(p "eval (number->string #d10000000000000000000000000000000000000000000000000000000000 16)")
  132. ))))
  133. (close-output-port op)))
  134. ip)
  135. op)))
  136. (define (make-log-replaying-ip-port log-file-name (max-lines 'all))
  137. (let-values ([(ip op) (make-pipe)])
  138. (thread
  139. (lambda ()
  140. (call-with-input-file log-file-name
  141. (lambda (ip)
  142. (let/ec return
  143. (for ([line (in-lines ip)]
  144. [lines-handled (in-naturals)])
  145. (when (equal? lines-handled max-lines)
  146. (return))
  147. (match line
  148. [(regexp #px"<= (\".*\")" (list _ datum))
  149. (display (read (open-input-string datum)) op)
  150. (display #\return op)
  151. (newline op)]
  152. [_ #f])))
  153. (close-output-port op)))))
  154. ip))
  155. (define (make-flaky-server log-file-name)
  156. (lambda ()
  157. (when (zero? (random 3))
  158. (raise (make-exn:fail:network
  159. "de network, she be broke"
  160. (current-continuation-marks))))
  161. (values (make-log-replaying-ip-port log-file-name 20)
  162. (open-output-nowhere))))
  163. (define (make-log-replaying-server log-file-name)
  164. (lambda ()
  165. (values (make-log-replaying-ip-port log-file-name)
  166. (relocate-output-port
  167. (current-output-port)
  168. #f #f 1 #f))))
  169. (define (make-random-server)
  170. (define (random-bytes [length 200])
  171. (let ([r (make-bytes length)])
  172. (for ([i (in-range length)])
  173. (let new-byte ()
  174. (let ([b (random 256)])
  175. (case b
  176. [(10 13) (new-byte)]
  177. [else (bytes-set! r i b)]))))
  178. r))
  179. (let-values ([(ip op) (make-pipe)])
  180. (thread
  181. (lambda ()
  182. (let loop ([lines-emitted 0])
  183. (when (< lines-emitted 200)
  184. (display #":ow!ow@ow PRIVMSG #ow :" op)
  185. (display (random-bytes) op)
  186. (display #"\r\n" op)
  187. (loop (add1 lines-emitted))))
  188. (close-output-port op)))
  189. (values ip (open-output-nowhere))))
  190. (define (make-hanging-up-server)
  191. (lambda ()
  192. (let-values ([(ip op) (make-pipe)])
  193. (thread
  194. (lambda ()
  195. (for ([line (in-list '("NOTICE AUTH :*** Looking up your hostname..."
  196. "NOTICE AUTH :*** Found your hostname, welcome back"
  197. "NOTICE AUTH :*** Checking ident"
  198. "NOTICE AUTH :*** No identd (auth) response"
  199. "ERROR :Closing Link: 127.0.0.1 (Connection Timed Out)"))])
  200. (fprintf op "~a\r~%" line))
  201. (sleep 1)
  202. (close-output-port op)))
  203. (values ip (open-output-nowhere)))))
  204. (define (replay-main . args)
  205. (parameterize ([*bot-gives-up-after-this-many-silent-seconds* 1/4]
  206. [*log-ports* (list (current-error-port))])
  207. (log "Main starting.")
  208. (connect-and-run
  209. (make-log-replaying-server "big-log")
  210. #:retry-on-hangup? #f)))
  211. (define (preload-main . args)
  212. (log "Main starting.")
  213. (parameterize ([*bot-gives-up-after-this-many-silent-seconds* 1/4]
  214. [*log-ports* (list (current-error-port))]
  215. [*incubot-server* (make-incubot-server (make-test-corpus))]
  216. [*incubot-logger* log])
  217. (connect-and-run
  218. (make-preloaded-server (open-output-nowhere))
  219. #:retry-on-hangup? #f)))
  220. (define (localhost-main . args)
  221. (log "Main starting: ~a" (git-version))
  222. (parameterize ([*irc-server-hostname* "localhost"])
  223. (connect-and-run real-server)))
  224. (define (flaky-main . args)
  225. (parameterize ([*bot-gives-up-after-this-many-silent-seconds* 1/4]
  226. [*log-ports* (list (current-error-port))])
  227. (random-seed 0)
  228. (connect-and-run
  229. (make-flaky-server "big-log")
  230. #:retry-on-hangup? #t)))
  231. (define (random-main . args)
  232. (parameterize ([*bot-gives-up-after-this-many-silent-seconds* 1/4]
  233. [*log-ports* (list (current-error-port))])
  234. (random-seed 0)
  235. (connect-and-run
  236. make-random-server
  237. #:retry-on-hangup? #f)))
  238. (define (hanging-up-main . args)
  239. (parameterize ([*log-ports* (list (current-error-port))])
  240. (connect-and-run
  241. (make-hanging-up-server))))
  242. (define (main . args)
  243. (fprintf (current-error-port) "Say goodbye to your environment ...")
  244. (clearenv)
  245. (fprintf (current-error-port) " poof~%")
  246. ;; flaky-main
  247. ;;; hanging-up-main
  248. ;;; (localhost-main)
  249. (preload-main)
  250. ;;; random-main
  251. ;;; replay-main
  252. )
  253. (provide (all-defined-out))