-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathmain.rkt
125 lines (115 loc) · 4.25 KB
/
main.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#lang racket
(require scribble/srcdoc
(for-doc scribble/base scribble/manual)
(for-label "private/data.rkt"))
(require "private/constants.rkt"
"private/data.rkt"
"private/events.rkt"
(only-in "private/gateway.rkt" new-ws-client send-status-update start-shard stop-shard)
"private/logger.rkt"
(prefix-in http: "http.rkt"))
(provide on-event
(all-from-out "private/constants.rkt")
(all-from-out "http.rkt")
client?
client-user
client-intents
client-events
discord-logger)
(define (format-token token type)
(case type
[(bot) (string-append "Bot " token)]
[(bearer) (string-append "Bearer " token)]
[(client) token]
[else (raise-user-error 'format-token "~a is not a valid token type" type)]))
(provide
(proc-doc/names
make-client (->* (string?)
(#:intents (listof integer?) ; todo narrow to just known intents?
#:token-type (or/c 'bot 'bearer 'client)
#:auto-shard boolean?
#:shard-count integer?)
client?)
((token) ((intents null) (token-type 'bot) (auto-shard #f) (shard-count 1)))
("Constructs a client with the passed token."
(linebreak)
(linebreak)
(racket #:auto-shard) ": If " (racket #t) ", ask Discord what the number of shards should be. Only applies if "
(racket #:token-type) " is " (racket 'bot) "."
(linebreak)
(linebreak)
(racket #:shard-count) ": If " (racket #:auto-shard) " is " (racket #f)
", the number of shards to use.")))
(define (make-client token
#:intents [intents null]
#:token-type [token-type 'bot]
#:auto-shard [auto-shard #f]
#:shard-count [shard-count 1])
(let* ([fmt-token (format-token token token-type)]
[http-client (http:make-http-client fmt-token)])
(let-values ([(ws-url shards)
(if auto-shard
(http:get-ws-url-bot http-client)
(values (http:get-ws-url http-client)
shard-count))])
(new-client ws-url shards http-client fmt-token intents))))
(define (new-client ws-url shard-count http-client token intents)
(let ([clnt
(client
null ; shard ws-clients
null ; shard-threads
#hash() ; user
#hash() ; event handlers
http-client
token
intents
(make-semaphore 0))])
(set-client-shards!
clnt
(map (lambda (n) (new-ws-client clnt n ws-url))
(range shard-count)))
(add-events clnt)
clnt))
(provide
(proc-doc/names
start-client (-> client? void?) (client)
("Starts a client and begins handling events."
(linebreak)
"This function blocks until the client is stopped through " (racket stop-client) ".")))
(define (start-client client)
(start-client-no-wait client)
(semaphore-wait (client-running client)))
(provide
(proc-doc/names
start-client-no-wait (-> client? void?) (client)
("Same as " (racket start-client) " but does not block the calling thread.")))
(define (start-client-no-wait client)
(set-client-shard-threads!
client
(map start-shard (client-shards client))))
(provide
(proc-doc/names
stop-client (-> client? void?) (client)
("Stops a client")))
(define (stop-client client)
(for ([shard (client-shard-threads client)])
(stop-shard shard))
(semaphore-post (client-running client)))
(provide
(proc-doc/names
update-status (->* (client?)
(#:since (or/c integer? #f)
#:activities (listof hash?)
#:status (or/c "online" "dnd" "idle" "invisible" "offline") ; TODO: make it use symbols?
#:afk boolean?)
void?)
((client) ((since #f) (activities null) (status "online") (afk #f)))
("Updates the client's status.")))
(define (update-status client
#:since [since #f]
#:activities [activities null]
#:status [status "online"]
#:afk [afk #f])
; XXX not quite right?
(for ([shard (client-shards client)])
(send-status-update shard status afk activities since)))