Guest User

Untitled

a guest
May 26th, 2018
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.97 KB | None | 0 0
  1. (defpackage #:simple-usocket-irc-bot
  2. (:use :cl :usocket :split-sequence))
  3. (in-package :simple-usocket-irc-bot)
  4.  
  5. (defvar *bot-socket* nil
  6. "Global socket for a single bot connection.")
  7.  
  8. (defun connect! (host &key (port 6667))
  9. (setq *bot-socket* (socket-connect host port)))
  10.  
  11. (defun format-irc-message (&rest args)
  12. "Format ARGS into a valid irc message sans the newlines at the end."
  13. (let ((result-string "")
  14. (last-arg (apply #'concatenate 'string ":" (last args)))
  15. (arg-list-but-last (append (butlast args))))
  16. (concatenate 'string
  17. (dolist (arg arg-list-but-last result-string)
  18. (setq result-string (concatenate 'string result-string arg " ")))
  19. last-arg)))
  20. (defun send-irc-message (&rest args)
  21. (prog1
  22. (write-sequence (apply #'format-irc-message args) (socket-stream *bot-socket*))
  23. (terpri (socket-stream *bot-socket*))
  24. (force-output (socket-stream *bot-socket*))))
  25.  
  26. ;;; Minimal sequence to write a bot that joins and quits immediately
  27. ;;; closing the socket while doing so.
  28. ;;;
  29. ;;; To run this and other code snippets, remove the #+ () line in front
  30. ;;; and hit C-c C-c in emacs.
  31.  
  32. (defun handle-irc-message (line)
  33. (let* ((words (split-sequence #\Space line)))
  34. (cond
  35. ; PING/PONG
  36. ((equal (first words) "PING")
  37. (send-irc-message "PONG"
  38. (string-trim ":" (second words))))
  39. ((equal (second words) "001")
  40. (send-irc-message "JOIN #programming")))))
  41.  
  42. (defun run ()
  43. (progn
  44. (connect! "onyx.ninthbit.net")
  45. (send-irc-message "NICK" "lispbot-d")
  46. (send-irc-message "USER" "lisp" "0" "*" "hi from nixeagle!")
  47. (loop
  48. (wait-for-input *bot-socket*)
  49. (handle-irc-message (read-line (socket-stream *bot-socket*))))))
  50.  
  51.  
  52. #+ () (
  53. (send-irc-message "JOIN" "#offtopic")
  54. (send-irc-message "PRIVMSG" "#offtopic" "Hi from nixeagle's simple lisp bot!")
  55. (send-irc-message "QUIT" "bye now!")
  56. (socket-close *bot-socket*))
  57.  
  58. ;;; listen to the socket, don't hang if there is nothing to hear, but if
  59. ;;; there is, print it to #sonicircd
  60. #+ ()
  61. (when (listen (socket-stream *bot-socket*))
  62. (send-irc-message "PRIVMSG" "#sonicircd" (read-line (socket-stream *bot-socket*))))
  63.  
  64. ;;; This will loop forever waiting for input and doing something (again
  65. ;;; just printing to #sonicircd) when the bot hears something
  66. #+ ()
  67. (loop
  68. (wait-for-input *bot-socket*
  69. (send-irc-message "PRIVMSG" "#sonicircd"
  70. (read-line (socket-stream *bot-socket*)))))
  71.  
  72. ;;; Ask me about threading when you get tired of stopping the loop just to
  73. ;;; modify the bot's behavior, but you need to know how to put the bot's
  74. ;;; behavior in a function and so on so that the modifications to the
  75. ;;; function can be seen by the threaded bot (this is not difficult, just
  76. ;;; put (defun i-got-input-from-server! (&optional (socket *bot-socket*))
  77. ;;; <some code here>) and call that instead of directly printing in the
  78. ;;; loop.
  79.  
  80. ;;; Close a socket with
  81. #+ ()
  82. (socket-close *bot-socket*)
Add Comment
Please, Sign In to add comment