~williewillus/public-inbox

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
1

[PATCH r16] Make the emote name to id lookup more robust

Details
Message ID
<20220314023631.184285-1-vincent@vincent-lee.net>
DKIM signature
missing
Download raw message
Patch: +50 -15
1. Search the local guild's emotes first, then the other guilds after
2. Listen for the guild delete and guild emojis update events so
   the set of known emotes updates live. Before the bot would not
   see emote changes without a restart.
---
Sending this for review if anyone has opinions. It's a pretty
straightforward diff, so I'm going to commit it in a day or two if
there's no objections.

 frontends/discord.rkt | 63 ++++++++++++++++++++++++++++++++-----------
 scribblings/r16.scrbl |  2 ++
 2 files changed, 50 insertions(+), 15 deletions(-)

diff --git a/frontends/discord.rkt b/frontends/discord.rkt
index 0e55438..fb2fefe 100644
--- a/frontends/discord.rkt
+++ b/frontends/discord.rkt
@@ -147,11 +147,11 @@
              (bitwise-and perms)
              ((negate zero?)))))

    ;; emote name -> emote id
    (define emote-lookup-cache (make-hash))
    ;; context/guild id -> (emote name -> emote id)
    (define emote-name-lookup (make-hash))

    ;; set of emote ids known by the bot
    (define known-emotes (mutable-set))
    ;; flattened set of all the leaf emote id's in emote-name-lookup, for fast contains
    (define known-emotes (box (set)))

    (define emote-image-cache
      (make-expiring-cache
@@ -173,9 +173,23 @@
      (define message-author (message-author-id message))
      (define channel-id (hash-ref message 'channel_id))

      (define/contract (emote-lookup name)
        (-> string? (or/c string? #f))
        (or
         ;; Check our own guild's emotes first
         (~> (context-id message)
             (hash-ref emote-name-lookup _ #hash())
             (hash-ref _ name #f))
         ;; Then try other guilds the bot is a member of (in arbitrary order)
         (for/or ([map (in-hash-values emote-name-lookup)])
           (hash-ref map name #f))))

      (define/contract (emote-image id)
        (-> string? (or/c bytes? #f))
        (and (set-member? known-emotes id)
        ;; Check if the emote is known to any of the guilds we're in.
        ;; This is to prevent tricks from abusing the bot to download unrelated emotes
        ;; from other servers it's not in.
        (and (set-member? (unbox known-emotes) id)
             (let ([data (expiring-cache-get emote-image-cache id)])
               (and (positive? (bytes-length data))
                    data))))
@@ -244,7 +258,7 @@
      (lambda (base trick-obj _args _parent-context)
        `(((message-contents       . ,message-contents)
           (message-author         . ,message-author)
           (emote-lookup           . ,(curry hash-ref emote-lookup-cache))
           (emote-lookup           . ,emote-lookup)
           (emote-image            . ,emote-image)
           (delete-caller          . ,delete-caller)
           (make-attachment        . ,make-attachment)
@@ -271,17 +285,36 @@
          (loop))))
      (rc:on-event 'raw-message-create client message-received)
      (rc:on-event 'raw-guild-create client guild-create)
      (rc:on-event 'raw-guild-delete client guild-delete)
      (rc:on-event 'raw-guild-emojis-update client guild-emojis-update)
      (rc:start-client client))

    (define (extract-emojis data)
      (for/hash ([emote (in-list (hash-ref data 'emojis null))])
        (values (hash-ref emote 'name) (hash-ref emote 'id))))

    (define (recompute-known-emotes)
      (define new (for*/set ([name-to-id (in-hash-values emote-name-lookup)]
                             [id (in-hash-values name-to-id)])
                    id))
      (log-r16-debug "Know of ~a emotes" (set-count new))
      (set-box! known-emotes new))

    (define (guild-create _ws-client _client guild)
      ;; eagerly fill all the emote mappings for each guild, so we don't need to touch the
      ;; network when tricks call emote-id
      (let ([known (mutable-set)])
        (for ([emote (in-list (hash-ref guild 'emojis null))])
          (hash-set! emote-lookup-cache (hash-ref emote 'name) (hash-ref emote 'id))
          (set-add! known (hash-ref emote 'id)))
        (set-union! known-emotes known)
        (log-r16-debug "Preloaded ~a emote ID's" (set-count known))))
      (hash-set! emote-name-lookup
                 (hash-ref guild 'id)
                 (extract-emojis guild))
      (recompute-known-emotes))

    (define (guild-delete _ws-client _client guild)
      (hash-remove! emote-name-lookup (hash-ref guild 'id))
      (recompute-known-emotes))

    (define (guild-emojis-update _ws-client _client payload)
      (hash-set! emote-name-lookup
                 (hash-ref payload 'guild_id)
                 (extract-emojis payload))
      (recompute-known-emotes))

    (define (message-received _ws-client _client message)
      (parameterize ([current-message message]
@@ -554,7 +587,7 @@
    (rc:make-client
     token
     #:auto-shard #t
     #:intents (list rc:intent-guilds rc:intent-guild-messages)))
     #:intents (list rc:intent-guilds rc:intent-guild-messages rc:intent-guild-emojis)))
  (new discord-frontend%
       [client client]
       [bot-prefix bot-prefix]
diff --git a/scribblings/r16.scrbl b/scribblings/r16.scrbl
index 1ee9217..b1eb861 100644
--- a/scribblings/r16.scrbl
+++ b/scribblings/r16.scrbl
@@ -104,6 +104,8 @@ Delete the message that invoked this sandbox.

@defproc[(emote-lookup [name string?]) (or/c string? #f)]{
Function that returns the ID for emote with name @racket[name], or @racket[#f] if it doesn't exist.
The emotes of the guild that the triggering message was sent in are searched first,
then the emotes of other guilds the bot is part of are searched in unspecified order.
}

@defproc[(emote-image [id string?]) (or/c bytes? #f)]{
-- 
2.35.1

[r16/patches/linux_buildtest.yml] build success

builds.sr.ht <builds@sr.ht>
Details
Message ID
<CIJ8PG5KIT05.34075HODCSRVK@cirno>
In-Reply-To
<20220314023631.184285-1-vincent@vincent-lee.net> (view parent)
DKIM signature
missing
Download raw message
r16/patches/linux_buildtest.yml: SUCCESS in 1m44s

[Make the emote name to id lookup more robust][0] from [Vincent Lee][1]

[0]: https://lists.sr.ht/~williewillus/public-inbox/patches/30210
[1]: vincent@vincent-lee.net

✓ #714361 SUCCESS r16/patches/linux_buildtest.yml https://builds.sr.ht/~williewillus/job/714361
Reply to thread Export thread (mbox)