1
0
Disbranĉigi 0

Support for TOPIC/TOPICWHOTIME, and IRCv3 message tags

This commit is contained in:
Jaidyn Ann 2023-01-04 13:39:28 -06:00
parent fe77077c68
commit 4a3914cb1b

129
ircc.scm
View File

@ -113,6 +113,16 @@
(cond [(eq? reply RPL_WELCOME) (cond [(eq? reply RPL_WELCOME)
(hash-table-set! conn 'registered #t) (hash-table-set! conn 'registered #t)
(hash-table-set! conn 'nick (car params))] (hash-table-set! conn 'nick (car params))]
[(eq? reply RPL_TOPIC)
(let ([channel (second params)]
[topic (last params)])
(irc:channel-set! conn channel 'topic topic))]
[(eq? reply RPL_TOPICWHOTIME)
(let ([channel (second params)]
[setter-nick (third params)]
[time (time-unix->time-utc (string->number (last params)))])
(irc:channel-set! conn channel 'topic-set
(time->date time)))]
[(eq? reply RPL_NAMREPLY) [(eq? reply RPL_NAMREPLY)
(let ([channel (third params)] (let ([channel (third params)]
[chan-symbol (second params)] [chan-symbol (second params)]
@ -225,23 +235,100 @@
;; Convert a string to a `msg` alist, with keys 'command', 'reply', 'params', ;; Convert a string to a `msg` alist, with keys 'command', 'reply', 'params',
;; and 'sender'. ;; and 'sender'.
(define (irc:line->alist str) (define (irc:line->alist str)
(let* ([colon-split (string-split str " :")] (let* ([space-split (string-split str " ")]
[last-column (reduce string-append #f (cdr colon-split))] ;; for post-colon colons [tags (irc:line-tags str space-split)]
[other-columns (string-split (car colon-split) " ")] [sender (irc:line-sender str space-split)]
[sender (if (eq? #\: [verb (irc:line-verb str space-split)]
(car (string->list (car other-columns)))) [command (car verb)]
(string-drop (car other-columns) 1) [reply (string->number (car verb))]
#f)] [params (irc:line-verb-params verb)])
[command (if sender
(cadr other-columns)
(car other-columns))]
[reply (string->number command)]
[params (append (if sender (cddr other-columns) (cdr other-columns))
(list last-column))])
`((command ,(if (not reply) command #f)) `((command ,(if (not reply) command #f))
(reply ,reply) (reply ,reply)
,(append '(params) params) ,(append '(params) params)
(sender ,sender)))) (sender ,sender)
,(append '(tags) tags))))
;; Parses out all tags from the given line of IRC output
(define (irc:line-tags str space-split)
(if (not (string=? (string-take str 1) "@"))
#f
(let*
([first-column (car space-split)]
[tag-strs (string-split (string-drop first-column 1) ";")]
[tag-pairs (map
(lambda (tag-str)
(string-split tag-str "="))
tag-strs)]
[no-empty-pairs (map
(lambda (tag-pair)
(if (eq? (length tag-pair) 1)
(append tag-pair '(""))
tag-pair))
tag-pairs)]
[escaped-pairs
(map
(lambda (tag-pair)
(list (car tag-pair)
(string-translate* (cadr tag-pair)
'(("\\s" . " ")
("\\\\" . "\\")
("\\r" . "\r")
("\\n" . "\n")))))
no-empty-pairs)])
escaped-pairs)))
;; Parse the sender of an IRC output line, if there is any
(define (irc:line-sender str space-split)
(let ([first-char (string-take str 1)])
(cond
[(and (string=? first-char "@")
(string=? (string-take (cadr space-split) 1) ":"))
(string-drop (cadr space-split) 1)]
[(string=? first-char ":")
(string-drop (car space-split) 1)]
[#t
#f])))
;; Parse out the verb (command or reply) with subsequent words into a list
(define (irc:line-verb str space-split)
(let ([first-char (string-take str 1)])
(cond
[(and (string=? first-char "@")
(string=? (string-take (cadr space-split) 1) ":"))
(cddr space-split)]
[(or (string=? first-char "@")
(string=? first-char ":"))
(cdr space-split)]
[#t
space-split])))
;; Returns a list of parameters from the parsed-out verb section of a line
(define (irc:line-verb-params verb)
(let* ([params (cdr verb)]
[other-params '()]
[last-param '()])
(map (lambda (param)
(cond
[(and (string=? (string-take param 1) ":")
(null? last-param))
(set! last-param
(append last-param `(,(string-drop param 1))))]
[(not (null? last-param))
(set! last-param (append last-param `(,param)))]
[#t
(set! other-params (append other-params `(,param)))]))
params)
(append
other-params
`(,(reduce-right
(lambda (a b)
(string-append a " " b))
#f
last-param)))))
;; ————————————————————————————————————————————————————————————————————————————— ;; —————————————————————————————————————————————————————————————————————————————
@ -256,6 +343,20 @@
#f))) #f)))
;; By Göran Weinholt, from the Scheme Cookbook
;; https://cookbook.scheme.org/format-unix-timestamp/
(define (time-unix->time-utc seconds)
(add-duration (date->time-utc (make-date 0 0 0 0 1 1 1970 0))
(make-time time-duration 0 seconds)))
;; By Göran Weinholt, from the Scheme Cookbook
;; https://cookbook.scheme.org/format-unix-timestamp/
(define (time-unix->string seconds . maybe-format)
(apply date->string (time-utc->date (time-unix->time-utc seconds))
maybe-format))
;; ————————————————————————————————————————————————————————————————————————————— ;; —————————————————————————————————————————————————————————————————————————————
;; IRC constants ;; IRC constants
;; ————————————————————————————————————————————————————————————————————————————— ;; —————————————————————————————————————————————————————————————————————————————