~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

[PATCH v2] Implement trick-local storage

Details
Message ID
<20210330164328.855329-1-wenming.yi@gmail.com>
DKIM signature
pass
Download raw message
Patch: +67 -6
From: Alwinfy <20421383+Alwinfy@users.noreply.github.com>

---
Same as last time, but rebased and formatted.
 main.rkt              | 41 +++++++++++++++++++++++++++++++++++++++--
 scribblings/r16.scrbl | 32 ++++++++++++++++++++++++++++----
 2 files changed, 67 insertions(+), 6 deletions(-)

diff --git a/main.rkt b/main.rkt
index 302c66a..3bed30e 100755
--- a/main.rkt
+++ b/main.rkt
@@ -32,6 +32,7 @@
  (author
   body
   created
   [storage #:mutable]
   [invocations #:mutable]))

(define (can-modify? message trick)
@@ -100,12 +101,13 @@
  (trick (if parent (trick-author parent) (message-author-id message))
         (strip-backticks body)
         (if parent (trick-created parent) (rc:message-timestamp message))
         (if parent (trick-storage parent) (make-hash))
         (if parent (trick-invocations parent) 0)))

(define (run-snippet client db message code)
  (let ([code (strip-backticks code)])
    (with-typing-indicator client message
      (thunk (ev:run code (evaluation-ctx client message db (context-id message) "" #f))))))
      (thunk (ev:run code (evaluation-ctx #f client message db (context-id message) "" #f))))))

(define (register-trick client db message text)
  (check-trick-prereqs
@@ -131,6 +133,7 @@
             (thunk (ev:run
                     (trick-body trick)
                     (evaluation-ctx
                      trick
                      client
                      message
                      db
@@ -255,6 +258,7 @@
               (thunk (ev:run
                       (trick-body trick)
                       (evaluation-ctx
                        trick
                        client
                        message
                        db
@@ -267,6 +271,35 @@
          (apply values vals))
        (raise (make-exn:fail:contract (~a "Trick " name " doesn't exist!"))))))

(define (storage-info message type)
  (match type
    ['guild   (cons 65536 'global)]
    ['channel (cons 8192  (rc:message-channel-id message))]
    ['user    (cons 2048  (message-author-id message))]
    [_        (cons 0     #f)]))

(define/contract (read-storage trick message type)
  (-> (or/c trick? #f) rc:message? (or/c 'guild 'channel 'user) any/c)
  (let ([datum (and~> trick
                 trick-storage
                 (hash-ref (cdr (storage-info message type)) #f)
                 (with-input-from-bytes read)
                 (with-handlers ([exn:fail:read? (const #f)]) _))])
    (and (not (eof-object? datum)) datum)))
(define/contract (write-storage trick message type data)
  (-> (or/c trick? #f) rc:message? (or/c 'guild 'channel 'user) any/c boolean?)
  (and
    trick
    (match-let ([(cons limit key) (storage-info message type)])
      (and
        key
        (let ([data (with-output-to-bytes (curry write data))])
          (and
            (<= (bytes-length data) limit)
            (begin
              (hash-set! (trick-storage trick) key data)
              #t)))))))

; client -> (emote name -> emote id)
(define emote-lookup-cache (make-hash))

@@ -309,7 +342,7 @@
         ; If empty byte string returned, return #f
         (and data (positive? (bytes-length data)) data)))))))

(define (evaluation-ctx client message db context-id args parent-ctx)
(define (evaluation-ctx trick client message db context-id args parent-ctx)
  (let* ([placeholder (make-placeholder #f)]
         [ctx
          `((message-contents . ,(rc:message-content message))
@@ -328,6 +361,9 @@
            (delete-caller    . ,(thunk (thread-send deleter-thread (cons client message))))
            (make-attachment  . ,make-attachment)
            (call-trick       . ,(call-subtrick client db context-id message placeholder))
            (message-author   . ,(message-author-id message))
            (read-storage     . ,(curry read-storage trick message))
            (write-storage    . ,(curry write-storage trick message))
            (parent-context   . ,parent-ctx))])
    (placeholder-set! placeholder (make-hash ctx))
    (cons (make-reader-graph ctx) '(threading))))
@@ -343,6 +379,7 @@
   (hash-ref json 'author)
   (hash-ref json 'body)
   (hash-ref json 'created)
   (make-hash) ; We purposefully don't save the trick storage due to space limits
   (hash-ref json 'invocations)))

(define command-table
diff --git a/scribblings/r16.scrbl b/scribblings/r16.scrbl
index 2052f3c..7d90487 100644
--- a/scribblings/r16.scrbl
+++ b/scribblings/r16.scrbl
@@ -19,8 +19,8 @@ All symbols from the @racket[threading-lib] package are available for convenienc
                          [mime (or/c symbol? string? bytes?)]) any/c]{
Creates an attachment with payload @racket[payload], filename @racket[name], and MIME-type @racket[mime].
This opaque object must be returned from the trick to be sent to Discord.
If more than one attachment is returned, an unspecified one is sent.                      
} 
If more than one attachment is returned, an unspecified one is sent.
}

@defproc[(call-trick [name (or/c symbol? string?)]
                     [argument any/c]) any/c]{
@@ -48,10 +48,34 @@ Function that returns the ID for emote with name @racket[name], or @racket[#f] i
Function that returns the PNG data of the emote with ID @racket[id], or @racket[#f] if it doesn't exist.
}

@defproc[(read-storage [type (or/c 'guild 'channel 'user)]) any/c]{
Reads "trick-local storage" @racket[name] and return its result, or @racket[#f] if the result is uninitialized.

A trick's "trick-local storage" can be per-guild, per-channel, or per-user.

This will always return @racket[#f] for the eval command.
}

@defproc[(write-storage [type (or/c 'guild 'channel 'user)]
                        [data any/c]) boolean?]{
Writes @racket[data] to the trick's "trick-local storage," overwriting any existing value, and returns whether the write succeeded. All data supported by @racket[write] can be written.

Note that "trick-local storage" is transient and does not currently persist across bot restarts.

A trick's "trick-local storage" can be per-guild, per-channel, or per-user; each type of storage has its own limitation on size:
@tabular[#:sep @hspace[1]
  `(,(list @bold{Type} @bold{Size Limit})
          ("guild"     "64kb")
          ("channel"   "8kb")
          ("user"      "2kb"))]
}

This will always be a no-op when invoked from the eval command.

@defproc[(delete-caller) void?]{
Thunk that deletes the message that invoked this sandbox.
} 
}

@defthing[parent-context (or/c (hash/c symbol? any/c) #f)]{
Mapping of all the above symbols for the trick calling this one, or @racket[#f] if this trick is the top level invocation.
} 
}
-- 
2.25.1
Reply to thread Export thread (mbox)