Merge pull request #1 from larzeitlin/refactor-suggestions
Refactor suggestions
This commit is contained in:
commit
cd8dabc61d
|
@ -1,81 +1,126 @@
|
|||
(ns irc-bot.core
|
||||
(:require [clojure.java.io :as io])
|
||||
(:import (javax.net.ssl SSLSocketFactory)
|
||||
(java.net Socket SocketException)
|
||||
(java.io PrintWriter InputStreamReader BufferedReader)))
|
||||
(java.net Socket SocketException)))
|
||||
|
||||
|
||||
(def servers [{:name "irc.hashbang.sh" :port 6697 :tls true
|
||||
(def servers [{:hostname "irc.hashbang.sh"
|
||||
:port 6697
|
||||
:tls true
|
||||
:channels ["#!" "#bots"]}
|
||||
{:name "testnet.ergo.chat" :port 6667 :tls false
|
||||
{:hostname "testnet.ergo.chat"
|
||||
:port 6667
|
||||
:tls false
|
||||
:channels ["#bots" "#0"]}
|
||||
{:name "irc.tilde.chat" :port 6697 :tls true
|
||||
{:hostname "irc.tilde.chat"
|
||||
:port 6697
|
||||
:tls true
|
||||
:channels ["#bots" "#meta"]}
|
||||
{:name "irc.libera.chat" :port 6667 :tls false
|
||||
{:hostname "irc.libera.chat"
|
||||
:port 6667
|
||||
:tls false
|
||||
:channels ["#bots" "#clojure"]}])
|
||||
|
||||
(def user {:name "Clojure Bot" :nick "cljpt"})
|
||||
(def user {:username "Clojure Bot"
|
||||
:nick "cljpt"})
|
||||
|
||||
(declare conn-handler)
|
||||
(defn socket->ssl-socket
|
||||
[socket hostname port]
|
||||
(.createSocket
|
||||
(SSLSocketFactory/getDefault)
|
||||
socket
|
||||
hostname port true))
|
||||
|
||||
(defn connect [server]
|
||||
(let [socket (if (true? (:tls server))
|
||||
(.createSocket (SSLSocketFactory/getDefault)
|
||||
(Socket. (:name server) (:port server))
|
||||
(:name server) (:port server) true)
|
||||
(Socket. (:name server) (:port server)))
|
||||
channels (:channels server)
|
||||
in (BufferedReader. (InputStreamReader. (.getInputStream socket)))
|
||||
out (PrintWriter. (.getOutputStream socket))
|
||||
conn (atom {:in in :out out :socket socket :channels channels})]
|
||||
(doto (Thread. #(try (conn-handler conn)
|
||||
(catch SocketException se
|
||||
(println (str "Caught exception: " (.getMessage se))))))
|
||||
(.start))
|
||||
conn))
|
||||
(defn conn->address-str [conn]
|
||||
(-> conn
|
||||
:socket
|
||||
.getRemoteSocketAddress
|
||||
.toString))
|
||||
|
||||
(defn write [conn msg]
|
||||
(doto (:out @conn)
|
||||
(.println (str msg "\r"))
|
||||
(.flush)))
|
||||
(defn disconnect [connection-atoms]
|
||||
(doseq [conn* connection-atoms]
|
||||
(if (-> @conn* :socket .isClosed)
|
||||
(println "No established connection to:"
|
||||
(conn->address-str @conn*))
|
||||
(do
|
||||
(println "Closing TCP socket connection:"
|
||||
(conn->address-str @conn*))
|
||||
(-> @conn* :socket .close)))))
|
||||
|
||||
|
||||
(defn write [{:keys [writer] :as _conn} msg]
|
||||
(.write writer (str msg "\n"))
|
||||
(.flush writer))
|
||||
|
||||
(defn join [conn chan]
|
||||
(write conn (str "JOIN " chan)))
|
||||
|
||||
(defn login [conn user]
|
||||
(write conn (str "NICK " (:nick user)))
|
||||
(write conn (str "USER " (:nick user) " 0 * :" (:name user))))
|
||||
(defn join-all-channels [connection-atoms]
|
||||
(doseq [conn* connection-atoms
|
||||
ch (:channels @conn*)]
|
||||
(join @conn* ch))
|
||||
connection-atoms)
|
||||
|
||||
(defn connected? [conn] (.isConnected conn))
|
||||
(defn login [conn*
|
||||
{:keys [nick username]
|
||||
:as _user}]
|
||||
(println "logging " username " into "
|
||||
(conn->address-str @conn*))
|
||||
(write @conn* (str "NICK " nick))
|
||||
(write @conn* (str "USER " nick " 0 * :" username))
|
||||
conn*)
|
||||
|
||||
(defn conn-handler [conn]
|
||||
(println "Connecting to:" (.toString (.getRemoteSocketAddress (:socket @conn))))
|
||||
(login conn user)
|
||||
(while (and (connected? (:socket @conn)) (nil? (:exit @conn)))
|
||||
(let [msg (.readLine (:in @conn))]
|
||||
(println msg)
|
||||
(cond
|
||||
(re-find #"^ERROR :Closing Link:" msg)
|
||||
(swap! conn merge {:exit true})
|
||||
(re-find #"^PING" msg)
|
||||
(write conn (str "PONG " (re-find #":.*" msg)))))))
|
||||
(defn read-messages [conn*]
|
||||
(with-open [socket (:socket @conn*)
|
||||
reader (io/reader socket)]
|
||||
(swap! conn* assoc :reader reader)
|
||||
(doseq [line (line-seq reader)]
|
||||
(cond
|
||||
(re-find #"^ERROR :Closing Link:" line)
|
||||
(swap! conn* merge {:exit true})
|
||||
|
||||
(defn disconnected? [conn] (.isClosed conn))
|
||||
(re-find #"^PING" line)
|
||||
(write conn* (str "PONG " (re-find #":.*" line))))
|
||||
|
||||
(def connections (doall (map connect servers)))
|
||||
;else
|
||||
(println line))))
|
||||
|
||||
(defn spawn-message-reader [conn*]
|
||||
(future
|
||||
(try
|
||||
(read-messages conn*)
|
||||
(catch SocketException e
|
||||
(println "Exception : "
|
||||
(conn->address-str conn*)
|
||||
" : " e))))
|
||||
conn*)
|
||||
|
||||
(defn server->connection
|
||||
[{:keys [port tls hostname]
|
||||
:as server}]
|
||||
(let [socket (cond-> (Socket. hostname port)
|
||||
tls
|
||||
(socket->ssl-socket hostname port))]
|
||||
(atom
|
||||
(merge server
|
||||
{:socket socket
|
||||
:writer (io/writer socket :append true)}))))
|
||||
|
||||
(defn connect-and-login-all-servers []
|
||||
(let [connection-atoms (map server->connection servers)]
|
||||
(doseq [c connection-atoms]
|
||||
(-> c
|
||||
(login user)
|
||||
spawn-message-reader))
|
||||
connection-atoms))
|
||||
|
||||
(comment
|
||||
(defn disconnect-servers [conn]
|
||||
(doseq [s conn]
|
||||
(if (not (disconnected? (:socket @s)))
|
||||
(do
|
||||
(println "Closing TCP socket connection:" (.toString (.getRemoteSocketAddress (:socket @s))))
|
||||
(.close (:socket @s)))
|
||||
(println "No established connection to:" (.toString (.getRemoteSocketAddress (:socket @s)))))))
|
||||
|
||||
(defn join-all-channels [conns]
|
||||
(for [c conns
|
||||
ch (:channels @c)]
|
||||
(join c ch)))
|
||||
(def connections-atoms
|
||||
(connect-and-login-all-servers))
|
||||
|
||||
(disconnect connections-atoms)
|
||||
|
||||
(disconnect-servers connections)
|
||||
(join-all-channels connections))
|
||||
(join-all-channels connections-atoms)
|
||||
|
||||
,)
|
||||
|
|
Loading…
Reference in New Issue