133 lines
4.5 KiB
Clojure
133 lines
4.5 KiB
Clojure
(ns irc-search-bot.core
|
|
(:import [java.util.concurrent Executors TimeUnit]
|
|
[java.util Date]
|
|
[org.pircbotx PircBotX Channel]
|
|
[org.pircbotx.hooks Event])
|
|
(:use [irc-search-bot.bot]
|
|
[irc-search-bot.lucene]
|
|
[irc-search-bot.util]
|
|
[clojure.string :only (trim join)]
|
|
[clojure.java.io :only (reader as-file)]
|
|
[clojure.contrib.math :only (floor)]))
|
|
|
|
(defn index-dir [bot] (fs-directory (str "index-" (.getNick bot))))
|
|
|
|
(def *chat-log* (atom []))
|
|
|
|
(def *analyzer*
|
|
(selective-analyzer
|
|
(stemmer-analyzer (standard-analyzer))
|
|
#{"message"}))
|
|
|
|
(def *msg-max-hits* 3)
|
|
|
|
(def *prv-msg-max-hits* 5)
|
|
|
|
(def *ignored-users*
|
|
(if (.exists (as-file "ignored_users"))
|
|
(with-open [rdr (reader "ignored_users")]
|
|
(into (hash-set) (line-seq rdr)))
|
|
#{}))
|
|
|
|
(defn index-chat-log [index-writer chat-log]
|
|
(doseq [[^Long timestamp user message] chat-log]
|
|
(do
|
|
(println (format "[%tr] %s: %s" (Date. timestamp) user message))
|
|
(add-document
|
|
index-writer
|
|
(document
|
|
(field :timestamp (str timestamp) :index :not-analyzed)
|
|
(field :user user :index :not-analyzed)
|
|
(field :message message))))))
|
|
|
|
(defn search-chat-log [index-searcher query-str max-hits analyzer]
|
|
(let [qp (query-parser :message analyzer)
|
|
raw-query (parse-query qp query-str)
|
|
[query filter] (filterify-query raw-query #{"user"})
|
|
[total hits] (search index-searcher query filter max-hits "timestamp")]
|
|
(println "Query:" query)
|
|
(println "Filter:" filter)
|
|
(println ">>" total "hits for query:" query-str)
|
|
(vector
|
|
total
|
|
(map
|
|
#(let [timestamp (-> % :doc :timestamp (Long/parseLong))
|
|
delta (floor (/ (- (System/currentTimeMillis) timestamp) 1000))]
|
|
(format
|
|
"[%s] %s: %s"
|
|
(fuzzy-relative-time delta)
|
|
(-> % :doc :user)
|
|
(-> % :doc :message)))
|
|
hits))))
|
|
|
|
(defn schedule-index-chat-log [bot]
|
|
(let [executor (Executors/newSingleThreadScheduledExecutor)]
|
|
(.scheduleWithFixedDelay
|
|
executor
|
|
(fn []
|
|
(try
|
|
(with-open [iw (index-writer (index-dir bot) *analyzer*)]
|
|
(let [chat-log @*chat-log*]
|
|
(do
|
|
(reset! *chat-log* [])
|
|
(index-chat-log iw chat-log))))
|
|
(catch Exception e
|
|
(.printStackTrace e))))
|
|
10 10 TimeUnit/SECONDS)))
|
|
|
|
(defmethod event-listener :disconnect [^PircBotX bot ^Event ev]
|
|
(do
|
|
(.connect bot (.getServer bot))
|
|
(doseq [channel (.getChannelNames bot)]
|
|
(.joinChannel bot channel))))
|
|
|
|
(defmethod event-listener :kick [^PircBotX bot ^Event ev]
|
|
(join-channel bot (.getChannel ev)))
|
|
|
|
(defmethod event-listener :message [^PircBotX bot ^Event ev]
|
|
(let [msg (trim (.getMessage ev))
|
|
user (.. ev getUser getNick)
|
|
timestamp (.getTimestamp ev)
|
|
channel (.getChannel ev)
|
|
query (trim (subs msg 2))]
|
|
(if (.startsWith msg "!q")
|
|
(with-open [is (index-searcher (index-dir bot))]
|
|
(let [[total results]
|
|
(search-chat-log is query *msg-max-hits* *analyzer*)]
|
|
(if (zero? total)
|
|
(send-message bot channel (format "No results found for \"%s\"" query))
|
|
(do
|
|
(send-message
|
|
bot channel
|
|
(format "%s results found for \"%s\". Top %s results:"
|
|
total query (count results)))
|
|
(doseq [result results]
|
|
(send-message bot channel result))))))
|
|
(when (and (not (.startsWith msg "!")) (not (*ignored-users* user)))
|
|
(swap! *chat-log* conj [timestamp user msg])))))
|
|
|
|
(defmethod event-listener :private-message [^PircBotX bot ^Event ev]
|
|
(let [msg (trim (.getMessage ev))
|
|
user (.. ev getUser getNick)
|
|
timestamp (.getTimestamp ev)
|
|
query (trim (subs msg 2))]
|
|
(when (.startsWith msg "!q")
|
|
(with-open [is (index-searcher (index-dir bot))]
|
|
(let [[total results]
|
|
(search-chat-log is query *prv-msg-max-hits* *analyzer*)]
|
|
(if (zero? total)
|
|
(send-prv-message bot user (format "No results found for \"%s\"" query))
|
|
(do
|
|
(send-prv-message
|
|
bot user
|
|
(format "%s results found for \"%s\". Top %s results:"
|
|
total query (count results)))
|
|
(doseq [result results]
|
|
(send-prv-message bot user result)))))))))
|
|
|
|
(defn run-bot [bot-name server channel]
|
|
(let [bot (make-bot bot-name)]
|
|
(connect-bot bot server channel)
|
|
(schedule-index-chat-log bot)
|
|
bot))
|