Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
wip Racket Bot
#lang racket/base
(require net/url)
; define consts, structs and params at top level
; constants used to access the thread vector
(define DB 0)
(define WEB 1)
(define BOT 2)
(define WEBHOOK-PREFIX "https://discordapp.com/api/webhooks/")
(define TEST-WEBHOOK "")
; create log messages to use with a LOG-LEVEL parameter
(define LOG-LEVEL (make-parameter 0))
(LOG-LEVEL 5)
(define (log-wrapper name num-filter)
(λ (msg)
(when (<= num-filter (LOG-LEVEL))
(displayln (format "[~a] ~a" name msg)))))
(define log (log-wrapper "LOG" 1))
(define info (log-wrapper "INFO" 2))
(define debug (log-wrapper "DEBUG" 3))
(define warn (log-wrapper "WARN" 4))
(define err (log-wrapper "ERROR" 5))
; Convert a symbol to an integer used for accessing a vector
; ie: (symbol->index 'bot) => 2
; (yes it's silly, but i prefer symbols over all-caps constants)
(define (symbol->index sym)
(cond
[(eqv? sym 'db) DB]
[(eqv? sym 'web) WEB]
[(eqv? sym 'bot) BOT]
[else (error "Unsupported index")]))
(define (thread-send-wrapper thread-vector)
(λ (sym datum)
(define requested-thread (vector-ref thread-vector (symbol->index sym)))
(if (not (thread? requested-thread))
(err "main" (format "Index ~a is not a thread" sym))
(thread-send requested-thread datum))))
; A database thread which acts as the add/remove/mutation thread
; Messages can be sent to this thread using message structs
(struct db-message (command args))
; Commands are as follows:
; 'add symbol means to add a user record (or add an additional WebHook)
; 'del symbol means to remove the user from the database entirely
; 'list symbol will display all entries in db hash
;
; Deleting a user should delete all attached webhooks in order to make
; it easier to unhook a user from this system
;
; The Hash association looks like:
; Key{User ID} => Value{Last Match ID, (Listof WebHook URLs)}
; If a match was played that's more recent than the Last Match ID,
; Send a JSON blob to all WebHook URLs associated
;
; The Database thread should be connected to two other threads:
; the web thread and the bot thread
; The web thread needs to know when things are added/removed
; The bot thread needs to fetch a list of all records in the hash
(define (database-thread send-t)
(displayln "Spinning up Database thread")
(define database (make-hash))
; add record method
; looks up the key; if it exists, append the url string to the list
; else, create a new hash entry and use the url string as the first member
(define (add-record key url-string)
(hash-set! database key url-string))
; del record method
; looks up a key; if it exists, wipe it from the hash
(define (del-record key)
(void))
; active running thread
(thread
(λ ()
(define (loop)
(define input-data (thread-receive))
(log "Received database command")
(define com (db-message-command input-data))
(cond
[(eqv? com 'add) (displayln "ADDED")]
[(eqv? com 'del) (displayln "DELETED")]
[(eqv? com 'list) (send-t 'bot '(1 2 3))]
[else (warn "Unsupported operation")])
(loop))
(loop))))
; Webserver thread
(define (webserver-thread send-t port)
(displayln "Spinning up Webserver thread")
(thread
(λ ()
(define (loop)
(sleep 1)
(loop))
(loop))))
; Botloop thread
(define (botloop-thread send-t)
(displayln "Spinning up Botloop thread")
(thread
(λ ()
(define (loop)
; receive data list here
(define data-list (thread-receive))
(log "Received and printing data")
; iterate through the data and send requests
(for-each displayln data-list)
; repeat and await the next batch of data
(loop))
(loop))))
; Example webhook:
; https://discordapp.com/api/webhooks/(.*[0-9])/(.*[a-zA-Z0-9_])
; We only accept the two IDs: ^from here til the EOL
(define (main)
; define the thread vector and the send-thread function
(define thread-vec (make-vector 3))
(define send-thread (thread-send-wrapper thread-vec))
; set our threads in place
(vector-set! thread-vec DB (database-thread send-thread))
(vector-set! thread-vec WEB (webserver-thread send-thread 8080))
(vector-set! thread-vec BOT (botloop-thread send-thread))
(define (loop)
(send-thread 'db (db-message 'list '()))
(sleep 5)
(loop))
(loop))
(main)
; end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment