Browse Source

fixed a bunch of bugs and changed the responses

master
wes 12 years ago
parent
commit
d56ab5f081
  1. 10
      botcore.rkt
  2. 33
      commands.rkt
  3. 43
      database.rkt
  4. 61
      redis.rkt

10
botcore.rkt

@ -12,7 +12,7 @@
;; CALLBACK FUNCTIONS ;; CALLBACK FUNCTIONS
(define (privmsg-handler send userinfo content join part) (define (privmsg-handler send userinfo content join part)
(match (parse-exclamation content) (match (parse-at content)
['nil 'nil] ['nil 'nil]
; joining a channel ; joining a channel
@ -29,7 +29,13 @@
[_ 'nil])] [_ 'nil])]
[_ 'nil])] [_ 'nil])]
[result (send (format "~a is ~a" (first result) (dispatch userinfo content)))])) [result
(let ([result (dispatch userinfo content)])
(display result)
(match result
['nil 'nil]
[(? hash?) (send "OK")]
[_ (send (format "~a" result))]))]))
;; Callback for join messages ;; Callback for join messages
(define (join-handler privmsg userinfo) (define (join-handler privmsg userinfo)

33
commands.rkt

@ -8,13 +8,19 @@
;; Command Parsing ;; Command Parsing
(define (string-head str) (define (string-head str)
(substring str 0 1)) (match (string-length str)
[(? ((curry <) 0)) (substring str 0 1)]
[_ #f]))
(define (string-tail str) (define (string-tail str)
(substring str 1 (string-length str))) (match (string-length str)
[(? ((curry eq?) 0)) 'nil]
[len (substring str 1 len)]))
(define (cmd? cmdchar cmd) (define (cmd? cmdchar cmd)
(string=? cmdchar (string-head cmd))) (match (string-head cmd)
[#f #f]
[content (string=? cmdchar content)]))
(define split-whitespace (define split-whitespace
((curry regexp-split) #rx" ")) ((curry regexp-split) #rx" "))
@ -29,24 +35,23 @@
split-whitespace)) split-whitespace))
(define parse-exclamation (define parse-exclamation
(cmdparse "!")) (cmdparse "?"))
(define parse-at (define parse-at
(cmdparse "@")) (cmdparse "?"))
;; Command Dispatcher ;; Command Dispatcher
(define (dispatch nick command) (define (dispatch nick command)
(match (allowed?) (match (allowed?)
[#f "Please try again in a few minutes"] [#f 'nil]
[_ (match (parse-exclamation command) [_ (match (parse-at command) ; if we are allowed, proceed
[(list-rest "set" args) (match args [(list-rest "set" args) (match (car args)
; this part checks if the right number of arguments are there ; this part checks if the right number of arguments are there
[(list (list name) (list-rest _ text)) [(list-rest name text)
(submit-question name (string-join text " ")) (submit-question name (string-join text " "))]
"Done!"] ; if for some reason this did not work, return nil
[_ 'nil])] [_ 'nil])]
[(list-rest "alias" (list args)) (make-alias (first args) (second args))] [(list-rest "alias" (list (list new old))) (make-alias new old)]
[(list-rest name _) (get-question name)] [(list-rest name _) (get-question name)])]))
[_ 'nil])]))
(provide (all-defined-out)) (provide (all-defined-out))

43
database.rkt

@ -10,6 +10,9 @@
; Couch Database operations ; Couch Database operations
; object used to connect to the database ; object used to connect to the database
(define reserved-words (set "counter" "alias" "set"))
(define (database-connection database-name) (define (database-connection database-name)
(couchdb-db (couchdb-db
(couchdb-connect (couchdb-connect
@ -39,12 +42,23 @@
(strip-newlines (strip-newlines
(second question)))))) (second question))))))
; trys to get a question from couchdb
(define (try-couchdb-get database id)
(with-handlers ([exn:couchdb:not-found?
(lambda (_)
'nil)])
(couchdb-get database id)))
; gets a question ; gets a question
(define couchdb-retrieve (define couchdb-retrieve
(compose (compose
(lambda (result) (lambda (result)
(hash-ref result 'text)) (match result
((curry couchdb-get) ['nil 'nil]
[_ (hash-ref result 'text)]))
((curry try-couchdb-get)
(database-connection "faqbot")))) (database-connection "faqbot"))))
; strips all newlines ; strips all newlines
@ -56,11 +70,11 @@
; Redis Database Operations ; Redis Database Operations
; make a command ; make a command
(define make-cmd set) (define make-cmd redis-set)
; gets a specified command ID from redis ; gets a specified command ID from redis
(define (get-id cmd) (define (get-id cmd)
(match (get cmd) (match (redis-get cmd)
['nil 'nil] ['nil 'nil]
[result (match (bytes->string/utf-8 result) [result (match (bytes->string/utf-8 result)
['nil 'nil] ['nil 'nil]
@ -78,17 +92,22 @@
; associates a name with an id in Redis, then puts the question in couchdb ; associates a name with an id in Redis, then puts the question in couchdb
(define (submit-question name content) (define (submit-question name content)
(let* ([id (caar (hash-values [get-uuid]))]) (match name
[(? ((curry set-member?) reserved-words)) "reserved word"]
[_ (let* ([id (caar (hash-values [get-uuid]))])
(make-cmd name id) (make-cmd name id)
(couchdb-submit (list id content)))) (couchdb-submit (list id content)))]))
; gets an id associated with a name from Redis, then gets the question from couchdb ; gets an id associated with a name from Redis, then gets the question from couchdb
(define (get-question name) (define (get-question name)
(let* ([id (get-id name)]) (let* ([id (get-id name)])
(match id (match id
['nil "No question found"] ['nil 'nil]
[_ (couchdb-retrieve id)]))) [_ (match (couchdb-retrieve id)
['nil (redis-del! name) ; if there is nothing in the database
'nil] ; then remove it
[result result])])))
;; Rate Limiting ;; Rate Limiting
; if |hC Current| > k, then set hC to Current, and hN to 0, and allow ; if |hC Current| > k, then set hC to Current, and hN to 0, and allow
@ -106,13 +125,13 @@
(let ([hN (bytes->number hN)]) (let ([hN (bytes->number hN)])
(cond (cond
[(and (> k mag) (eq? hN n)) #f] [(and (> k mag) (eq? hN n)) #f]
[(and (< mag k) (< hN n)) (hincrby "counter" "n" "1") #t] [(and (< mag k) (< hN n)) (redis-hincrby "counter" "n" "1") #t]
[else (hset "counter" "n" "0") [else (redis-hset "counter" "n" "0")
(hset "counter" "current" (number->string (current-inexact-milliseconds))) (redis-hset "counter" "current" (number->string (current-inexact-milliseconds)))
#t]))) #t])))
(define ((rate-check n k)) (define ((rate-check n k))
(let* ([counter (hvals "counter")] (let* ([counter (redis-hvals "counter")]
[current-time (current-inexact-milliseconds)]) [current-time (current-inexact-milliseconds)])
(let* ([hC-Current (time-magnitude (second counter) current-time)]) (let* ([hC-Current (time-magnitude (second counter) current-time)])
(rate-check-helper hC-Current (first counter) n k)))) (rate-check-helper hC-Current (first counter) n k))))

61
redis.rkt

@ -68,136 +68,135 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; COMMANDS ;; COMMANDS
(define (ping) (define (redis-ping)
(send-command "PING") (send-command "PING")
(read-reply)) (read-reply))
;; Connection handling ;; Connection handling
(define (quit) (define (redis-quit)
(send-command "QUIT") (send-command "QUIT")
(disconnect!)) (disconnect!))
(define (auth) (define (redis-auth)
(send-command "AUTH") (send-command "AUTH")
(read-reply)) (read-reply))
;; Commands operating on all value types ;; Commands operating on all value types
(define (exists? key) (define (redis-exists? key)
(send-command "EXISTS" key) (send-command "EXISTS" key)
(match (read-reply) (match (read-reply)
[1 #t] [1 #t]
[0 #f])) [0 #f]))
(define del! (define redis-del!
(lambda keys (lambda keys
(apply send-command `("DEL" ,@keys)) (apply send-command `("DEL" ,@keys))
(read-reply))) (read-reply)))
(define (type key) (define (redis-type key)
(send-command "TYPE" key) (send-command "TYPE" key)
(string->symbol (read-reply))) (string->symbol (read-reply)))
(define (keys pattern) (define (redis-keys pattern)
(send-command "KEYS" pattern) (send-command "KEYS" pattern)
(read-reply)) (read-reply))
(define (randomkey) (define (redis-randomkey)
(send-command "RANDOMKEY") (send-command "RANDOMKEY")
(read-reply)) (read-reply))
(define (redis-rename! oldkey newkey)
(define (rename! oldkey newkey)
(send-command "RENAME" oldkey newkey) (send-command "RENAME" oldkey newkey)
(read-reply)) (read-reply))
(define (renamenx! oldkey newkey) (define (redis-renamenx! oldkey newkey)
(send-command "RENAME" oldkey newkey) (send-command "RENAME" oldkey newkey)
(match (read-reply) (match (read-reply)
[1 #t] [1 #t]
[0 #f])) [0 #f]))
(define (dbsize) (define (redis-dbsize)
(send-command "DBSIZE") (send-command "DBSIZE")
(read-reply)) (read-reply))
(define (expire! key seconds) (define (redis-expire! key seconds)
(send-command "EXPIRE" key seconds) (send-command "EXPIRE" key seconds)
(read-reply)) (read-reply))
(define (expireat! key date) (define (redis-expireat! key date)
(send-command "EXPIREAT" key (date->seconds date)) (send-command "EXPIREAT" key (date->seconds date))
(read-reply)) (read-reply))
(define (ttl key) (define (redis-ttl key)
(send-command "TTL" key) (send-command "TTL" key)
(read-reply)) (read-reply))
(define (select key) (define (redis-select key)
(send-command "SELECT" key) (send-command "SELECT" key)
(read-reply)) (read-reply))
(define (move key dbindex) (define (redis-move key dbindex)
(send-command "MOVE" key dbindex) (send-command "MOVE" key dbindex)
(read-reply)) (read-reply))
(define (flushdb) (define (redis-flushdb)
(send-command "FLUSHDB") (send-command "FLUSHDB")
(read-reply)) (read-reply))
(define (flushall) (define (redis-flushall)
(send-command "FLUSHALL") (send-command "FLUSHALL")
(read-reply)) (read-reply))
(define (set key value) (define (redis-set key value)
(send-command "SET" key value) (send-command "SET" key value)
(read-reply)) (read-reply))
(define (get key) (define (redis-get key)
(send-command "GET" key) (send-command "GET" key)
(read-reply)) (read-reply))
(define (getset key value) (define (redis-getset key value)
(send-command "GETSET" key value) (send-command "GETSET" key value)
(read-reply)) (read-reply))
(define mget (define redis-mget
(lambda keys (lambda keys
(apply send-command `("MGET" ,@keys) (apply send-command `("MGET" ,@keys)
(read-reply)))) (read-reply))))
(define (incrby key n) (define (redis-incrby key n)
(send-command "INCRBY" key n) (send-command "INCRBY" key n)
(read-reply)) (read-reply))
;; Hash commands ;; Hash commands
(define (hset key field value) (define (redis-hset key field value)
(send-command "HSET" key field value) (send-command "HSET" key field value)
(read-reply)) (read-reply))
(define (hget key field) (define (redis-hget key field)
(send-command "HGET" key field) (send-command "HGET" key field)
(read-reply)) (read-reply))
(define (hgetall key) (define (redis-hgetall key)
(send-command "HGETALL" key) (send-command "HGETALL" key)
(read-reply)) (read-reply))
(define (hincrby key field num) (define (redis-hincrby key field num)
(send-command "HINCRBY" key field num) (send-command "HINCRBY" key field num)
(read-reply)) (read-reply))
(define (hincrbyfloat key field num) (define (redis-hincrbyfloat key field num)
(send-command "HINCRBYFLOAT" key field num) (send-command "HINCRBYFLOAT" key field num)
(read-reply)) (read-reply))
(define (hkeys key) (define (redis-hkeys key)
(send-command "HKEYS" key) (send-command "HKEYS" key)
(read-reply)) (read-reply))
(define (hvals key) (define (redis-hvals key)
(send-command "HVALS" key) (send-command "HVALS" key)
(read-reply)) (read-reply))

Loading…
Cancel
Save