Skip to content

Instantly share code, notes, and snippets.

@saolsen
Last active December 14, 2015 09:29
Show Gist options
  • Save saolsen/5065547 to your computer and use it in GitHub Desktop.
Save saolsen/5065547 to your computer and use it in GitHub Desktop.
markerbot
(ns markerbot.core
(:require [taoensso.timbre :as log]
[clojure.data.json :as json]
[clojure.string :as s]
[clj-http.client :as client])
(:import (java.net Socket)
(java.io PrintWriter InputStreamReader BufferedReader))
(:gen-class))
;; marksy
(defn payload [from to text]
(json/write-str {:input from, :output to, :text text}))
(defn transmarksify [from to text]
(let [req (client/post "http://marksy.arc90.com/convert"
{:headers {"x-marksy" "markerbot"}
:content-type :json
:accept :json
:body (payload from to text)})]
(-> req
(:body)
(json/read-str :key-fn keyword)
(:payload))))
;; irc
(defn get-connection [server port]
(let [socket (Socket. server port)
in (BufferedReader. (InputStreamReader. (.getInputStream socket)))
out (PrintWriter. (.getOutputStream socket))]
{:in in :out out}))
;; types that contain and manage the state
(defprotocol PIrcConnection
"A connection to irc"
(readline [this] "read a line from irc")
(writeline [this command] "writes a command to irc"))
(defrecord IrcConnection [in out]
PIrcConnection
(readline [_] (.readLine in))
(writeline [_ command] (doto out
(.println (str command "\r"))
(.flush))))
(defprotocol PManagedChannel
"A managed irc channel"
(register-handler [this handler] "register a function to be called")
(setup [this] "sets everything up"))
(defrecord ManagedChannel [connection channel user
reads writes msg-handler]
PManagedChannel
(register-handler [_ handler] (reset! msg-handler handler))
(setup [_]
;; watcher to log to console
(add-watch reads :log
(fn [_ _ _ msg]
(log/info "received: " msg)))
;; watcher to publish messages to irc
(add-watch writes :publish
(fn [_ _ _ msg]
(log/info "replied: " msg)
(writeline connection msg)))
;; watcher to check for pings
(add-watch reads :pingback
(fn [_ _ _ msg]
(when (re-find #"^PING" msg)
(reset! writes (str "PONG " (re-find #":.*" msg))))))
;; watcher to call handler
(add-watch reads :handler
(fn [_ _ _ msg]
(future
(when-let [reply (@msg-handler msg)]
(doseq [m (s/split reply #"\n")]
(reset! writes
(str "PRIVMSG " channel " :" m)))))))
;; sign in and join channel
(reset! writes (str "NICK " user))
(reset! writes (str "USER " user " 0 * :" user))
(reset! writes (str "JOIN " channel))
;; thread to read from the channel and publish notifications
(future
(while true
(let [next-message (readline connection)]
(reset! reads next-message))))
nil
))
(defn connect
"connects to an irc channel and returns an IrcConnection"
[server port]
(let [conn (get-connection server port)
irc (IrcConnection. (:in conn) (:out conn))]
irc))
;; marksy coms
(defn marksinator [msg]
(when-let [match (re-find #"(\[)([A-z]*)(->)([A-z]*)(\])(.*)" msg)]
(transmarksify (nth match 2) (nth match 4) (nth match 6))))
;; main
(defn -main [& args]
(let [conn (connect "irc.freenode.net" 6667)
channel (ManagedChannel. conn "#marksy" "markerbot"
(atom nil) (atom nil) (atom nil))]
(register-handler channel marksinator)
(setup channel)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment