Files
drracket-discord/discord-ipc.rkt
2026-01-17 19:16:55 +01:00

68 lines
2.1 KiB
Racket

#lang racket/base
(require racket/unix-socket
json
racket/list
racket/os)
(provide connect-discord update-presence)
(define ipc-out #f)
(define (get-socket-path)
(define base-dirs
(list (getenv "XDG_RUNTIME_DIR")
(getenv "TMPDIR")
"/tmp"
(build-path "/run/user" (number->string (getpid)))))
(for/first ([dir base-dirs]
#:when dir
[i (in-range 10)]
#:do [(define p (build-path dir (format "discord-ipc-~a" i)))]
#:when (file-exists? p))
p))
(define (write-packet opcode payload)
(when ipc-out
(define json-bytes (string->bytes/utf-8 (jsexpr->string payload)))
(define len (bytes-length json-bytes))
(write-bytes (integer->integer-bytes opcode 4 #f #f) ipc-out) ; Opcode
(write-bytes (integer->integer-bytes len 4 #f #f) ipc-out) ; Length
(write-bytes json-bytes ipc-out)
(flush-output ipc-out)))
(define (connect-discord client-id)
(define path (get-socket-path))
(if path
(with-handlers ([exn:fail? (lambda (e) (printf "Discord connection failed.\n"))])
(define-values (in out) (unix-socket-connect path))
(set! ipc-out out)
(write-packet 0 (hash 'v 1 'client_id client-id))
(printf "Connected to Discord at ~a\n" path))
(printf "Discord not found.\n")))
(define (update-presence details state
#:start [start-timestamp #f]
#:small-text [small-text #f])
(define activity
(hash 'details details
'state state
'assets (hash
'large_image "racket-logo-ezgif_com-svg-to-png-converter"
'large_text "DrRacket"
'small_image (if small-text "lambda" #f)
'small_text small-text)
'timestamps (if start-timestamp
(hash 'start start-timestamp)
#f)))
(write-packet 1
(hash 'cmd "SET_ACTIVITY"
'nonce (number->string (current-milliseconds))
'args (hash 'pid (getpid)
'activity activity))))