Last active
December 29, 2015 19:19
-
-
Save 4poc/7716437 to your computer and use it in GitHub Desktop.
Simple Example IRC Bot, my first clojure program!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns cljbot | |
(:use [clojure.string :only (split join)] | |
[clojure.pprint :only (pprint)]) | |
(:import (javax.net.ssl SSLSocketFactory X509TrustManager SSLContext TrustManager) | |
(java.io BufferedReader PrintWriter InputStreamReader) | |
(java.security SecureRandom) | |
(java.util.regex Pattern))) | |
(def HOST "irc.teranetworks.de") | |
(def PORT 6697) | |
(def CHANNEL "#test") | |
(def IDENT | |
{:nick "conjurer" | |
:username "cljbot" | |
:realname "Clojure"} | |
) | |
(def PREFIX "!") | |
(defn trust-invalid-manager [] | |
"This allows the ssl socket to connect with invalid/self-signed SSL certs." | |
(reify X509TrustManager | |
(getAcceptedIssuers [this] nil) | |
(checkClientTrusted [this certs authType]) | |
(checkServerTrusted [this certs authType]) | |
) | |
) | |
(defn get-irc-conn [host port] | |
"Connects to host and port and returns input and output streams." | |
(def ssl-context (SSLContext/getInstance "SSL")) | |
(.init ssl-context nil (into-array TrustManager [(trust-invalid-manager)]) | |
(new SecureRandom)) | |
(let [socket (.createSocket (.getSocketFactory ssl-context) host port)] | |
{:in (new BufferedReader (new InputStreamReader (.getInputStream socket))) | |
:out (new PrintWriter (.getOutputStream socket))} | |
) | |
) | |
(defn parse-raw [line] | |
"Parses the messages sent from the server into a descriptive hash map." | |
(let [[_ source command args message] (re-matches | |
#"^(?:[:](\S+) )?(\S+)(?: (?!:)(.+?))?(?: [:](.+))?$" line)] | |
{:source source | |
:command command | |
:args args | |
:message message} | |
) | |
) | |
(defn parse-privmsg [params] | |
"Parses privmsg using a simple command syntax, similar to other irc bots." | |
(def pattern (re-pattern (str "^(" (Pattern/quote PREFIX) "|" | |
(Pattern/quote (:nick IDENT)) "[:|,] ?)?([^ ]+) ?(.*)?$")) | |
) | |
(if-let [[_ prefix action args] (re-matches pattern (:message params))] | |
(if (or prefix (and (not prefix) (.equals (:args params) (:nick IDENT)))) | |
{:prefix prefix :action action :args (split args #" ")} | |
) | |
) | |
) | |
(defn action-ping [sendline reply args params] | |
(reply "pong") | |
) | |
(defn action-version [sendline reply args params] | |
(reply "clojure irc bot!") | |
) | |
(defn action-quit [sendline reply args params] | |
(sendline (str "QUIT :" (join " " args))) | |
) | |
(defn handle-privmsg [params sendline] | |
(defn reply [message] | |
(if (= (.indexOf (:args params) "#") 0) | |
(def dest (:args params)) | |
(def dest (:source params)) | |
) | |
(sendline (str "PRIVMSG " dest " :" message)) | |
) | |
(if-let [{action :action args :args} (parse-privmsg params)] | |
(let [fnk (ns-resolve 'cljbot (symbol (str "action-" action)))] | |
(if fnk (fnk sendline reply args params)) | |
) | |
) | |
) | |
(defn handle-raw [params sendline] | |
(when (.equals (:command params) "PING") | |
(sendline (str "PONG :" (:message params))) | |
) | |
(when (.equals (:command params) "376") | |
(sendline (str "JOIN " CHANNEL)) | |
) | |
(when (.equals (:command params) "PRIVMSG") | |
(handle-privmsg params sendline) | |
) | |
) | |
(defn mainloop [in sendline] | |
(doseq [line (line-seq in)] | |
(handle-raw (parse-raw line) sendline) | |
) | |
) | |
(defn -main [& args] | |
(let [{in :in out :out} (get-irc-conn HOST PORT)] | |
(defn sendline [line] | |
"Sends a single line to the irc server." | |
(println "<" line) | |
(doto out | |
(.print (str line "\r\n")) | |
(.flush) | |
) | |
) | |
(println "bot connected, sending nick/user...") | |
(sendline (str "NICK " (:nick IDENT))) | |
(sendline (str "USER " (:username IDENT) " 0 * :" (:realname IDENT))) | |
(mainloop in sendline) | |
) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment