diff options
| -rw-r--r-- | Makefile.am | 10 | ||||
| -rw-r--r-- | toot.scm | 233 | ||||
| -rw-r--r-- | toot/accounts.scm | 58 | ||||
| -rw-r--r-- | toot/attachments.scm | 39 | ||||
| -rw-r--r-- | toot/emojis.scm | 55 | ||||
| -rw-r--r-- | toot/notifications.scm | 59 | ||||
| -rw-r--r-- | toot/statuses.scm | 107 | ||||
| -rw-r--r-- | toot/utils.scm | 48 | 
8 files changed, 391 insertions, 218 deletions
diff --git a/Makefile.am b/Makefile.am index 722d422..b879c58 100644 --- a/Makefile.am +++ b/Makefile.am @@ -41,8 +41,14 @@ godir=$(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/site-ccache  bin_SCRIPTS = -SOURCES =        \ -  toot.scm +SOURCES =                \ +  toot.scm               \ +  toot/accounts.scm      \ +  toot/attachments.scm   \ +  toot/emojis.scm        \ +  toot/notifications.scm \ +  toot/statuses.scm      \ +  toot/utils.scm  TESTS = @@ -17,6 +17,13 @@  ;;; along with Toot.  If not, see <http://www.gnu.org/licenses/>.  (define-module (toot) +  #:use-module (toot utils) +  #:use-module (toot statuses) +  #:use-module (toot accounts) +  #:use-module (toot notifications) +  #:use-module (toot emojis) +  #:use-module (toot attachments) +  #:use-module (toot config)    #:use-module (ice-9 format)    #:use-module (web response)    #:use-module (web client) @@ -60,51 +67,10 @@              ;; streaming              streaming-user              streaming-public -             -            ;; status -            status? -            status-id -            status-emojis -            status-reblog -            status-account -            status-content -            status-public? -            status-sensitive? -            status-visibility -            status-spoiler-text -            status-creation-time -            status-in-reply-to-id -            status-in-reply-to-account-id -            display-status - -            ;; notification -            notification? -            notification-id -            notification-type -            notification-status -            notification-account -            notification-creation-time -            display-notification - -            ;; emoji -            emoji? -            emoji-shortcode -            emoji-static-url -            emoji-visible-in-picker? -            ;; account -            account? -            account-id -            account-acct -            account-emojis -            account-display-name -            account-avatar-static -            )) - -(define-syntax-rule (and/nil test expr) -  (if test -      expr -      '())) +            ;; display +            display-status +            display-notification))  (define mastodon-host    (make-parameter (getenv "MASTODON_HOST"))) @@ -115,14 +81,6 @@  (define display-image?    (make-parameter #f)) -(define (created-at-string->date str) -  (time-utc->date -   (date->time-utc -    (string->date str "~Y-~m-~dT~H:~M:~S.~N~z")))) - -(define (creation-time->string date) -  (date->string date "~4")) -  (define* (post text                 #:key                 spoiler-text @@ -172,57 +130,6 @@                  `((media_ids . ,(list->vector (map number->string media-ids))))))     #:authorization? #t)) -(define-record-type <status> -  (make-status json) -  status? -  (json status-json)) - -(set-record-type-printer! <status> -  (lambda (status port) -    (format port -            "#<status id: ~s ...>" -            (status-id status)))) - -(define-record-type <account> -  (make-account json) -  account? -  (json account-json)) - -(set-record-type-printer! <account> -  (lambda (account port) -    (format port "#<account id: ~s acct: ~s ...>" -            (account-id account) -            (account-acct account)))) - -(define-record-type <notification> -  (make-notification json) -  notification? -  (json notification-json)) - -(define (notification-id notification) -  (assoc-ref (notification-json notification) -             "id")) - -(define (notification-status notification) -  (make-status -   (assoc-ref (notification-json notification) -              "status"))) - -(define (notification-account notification) -  (make-account -   (assoc-ref (notification-json notification) -              "account"))) - -(define (notification-type notification) -  (string->symbol -   (assoc-ref (notification-json notification) -              "type"))) - -(define (notification-creation-time notification) -  (created-at-string->date -   (assoc-ref (notification-json notification) -              "created_at"))) -  (define* (display-notification notification #:key (port (current-output-port)))    (let ((account (notification-account notification))          (status (notification-status notification)) @@ -237,9 +144,6 @@              (creation-time->string time))      (display-status (notification-status notification)))) -(define (status-public? status) -  (eq? 'public (status-visibility status))) -  (define (account-to-string account)    (format #f "~{~a~} <~a> (account-id: ~s)"            (insert-emoji-picts (account-emojis account) @@ -318,24 +222,6 @@             (scale status-pict 0.5)))))       (else status-pict)))) -(define (status-id status) -  (assoc-ref (status-json status) "id")) - -(define (status-account status) -  (make-account (assoc-ref (status-json status) "account"))) - -(define (status-reblog status) -  (let ((reblog/json (assoc-ref (status-json status) "reblog"))) -    (if (eq? reblog/json 'null) -        #f -        (make-status reblog/json)))) - -(define (status-sensitive? status) -  (assoc-ref (status-json status) "sensitive")) - -(define (status-content status) -  (assoc-ref (status-json status) "content")) -  (define (sanitize x)    (string-delete (char-set #\x202d #\x202e) x)) @@ -373,43 +259,6 @@      (append-map flatten x))     (else (list x)))) -(define (status-visibility status) -  (string->symbol (assoc-ref (status-json status) "visibility"))) - -(define (status-spoiler-text status) -  (let ((s (assoc-ref (status-json status) "spoiler_text"))) -    (if (zero? (string-length s)) -        #f -        s))) - -(define-record-type <emoji> -  (make-emoji json) -  emoji? -  (json emoji-json)) - -(define (emojis->regexp emojis) -  (string-append ":(" -                 (string-join (map (compose regexp-quote emoji-shortcode) emojis) -                              "|") -                 "):")) - -(define (status-emojis status) -  (map make-emoji (vector->list (assoc-ref (status-json status) "emojis")))) - -(define-record-type <attachment> -  (make-attachment json) -  attachment? -  (json attachment-json)) - -(define (attachment-type attachment) -  (string->symbol (assoc-ref (attachment-json attachment) "type"))) - -(define (attachment-preview-url attachment) -  (assoc-ref (attachment-json attachment) "preview_url")) - -(define (attachment-url attachment) -  (assoc-ref (attachment-json attachment) "url")) -  (define (fetch-attachment-preview-pict attachment)    (fetch-pict (attachment-preview-url attachment)                #:height> 128)) @@ -417,35 +266,6 @@  (define (fetch-attachment-pict attachment)    (fetch-pict (attachment-url attachment))) -(define (status-media-attachments status) -  (let ((v (assoc-ref (status-json status) "media_attachments"))) -    (map make-attachment (vector->list v)))) - -(define (status-in-reply-to-id status) -  (let ((id (assoc-ref (status-json status) "in_reply_to_id"))) -    (if (eq? 'null id) -        #f -        id))) - -(define (status-in-reply-to-account-id status) -  (let ((id (assoc-ref (status-json status) "in_reply_to_account_id"))) -    (if (eq? 'null id) -        #f -        id))) - -(define (status-creation-time status) -  (created-at-string->date (assoc-ref (status-json status) -                                      "created_at"))) - -(define (emoji-static-url emoji) -  (assoc-ref (emoji-json emoji) "static_url")) - -(define (emoji-shortcode emoji) -  (assoc-ref (emoji-json emoji) "shortcode")) - -(define (emoji-visible-in-picker? emoji) -  (assoc-ref (emoji-json emoji) "visible_in_picker")) -  (define emoji-cache (make-hash-table))  (define (fetch-emoji-pict emoji) @@ -470,7 +290,7 @@                     (let ((shortcode (match:substring mat 1)))                       (cons* (match:prefix mat)                              (cond -                             ((emojis-ref emojis shortcode) +                             ((emoji-find emojis shortcode)                                =>                                (lambda (emoji)                                  (or (and (display-image?) @@ -481,25 +301,6 @@                   (list s))))          (list x)))) -(define (emojis-ref emojis shortcode) -  (find (lambda (emoji) (equal? shortcode (emoji-shortcode emoji))) -        emojis)) - -(define (account-id account) -  (assoc-ref (account-json account) "id")) - -(define (account-avatar-static account) -  (assoc-ref (account-json account) "avatar_static")) - -(define (account-acct account) -  (assoc-ref (account-json account) "acct")) - -(define (account-display-name account) -  (assoc-ref (account-json account) "display_name")) - -(define (account-emojis account) -  (map make-emoji (vector->list (assoc-ref (account-json account) "emojis")))) -  (define avatar-static-cache (make-hash-table))  (define* (fetch-pict url #:key resize height>) @@ -553,7 +354,7 @@    (receive (res body)        (get-/api/v1/statuses/:id id #:authorization? authorization?)      (case (response-code res) -      ((200) (make-status body)) +      ((200) (status-from-json body))        (else         (error "fetch-status: failed" res body))))) @@ -572,7 +373,7 @@                                    #:local? local?)      (case (response-code res)        ((200) -       (map make-status (vector->list body))) +       (map status-from-json (vector->list body)))        ((206)         (error "fetch-home-timeline: Home feed is regenerating"))        (else @@ -589,7 +390,7 @@                                      #:only-media? only-media?)      (case (response-code res)        ((200) -       (map make-status (vector->list body))) +       (map status-from-json (vector->list body)))        (else         (error "fetch-public-timeline: failed" res body))))) @@ -713,7 +514,7 @@    (receive (res body)        (get-/api/v1/accounts/:id id)      (case (response-code res) -      ((200) (make-account body)) +      ((200) (account-from-json body))        ((401)         (error "fetch-account: Unauthorized" id))        ((404) @@ -827,7 +628,7 @@                   (case event                     ((update)                      (handler event -                             (make-status +                             (status-from-json                                (json-string->scm data)))                      (loop #f))                     ((delete) @@ -835,7 +636,7 @@                      (loop #f))                     ((notification)                      (handler event -                             (make-notification +                             (notification-from-json                                (json-string->scm data)))                      (loop #f))                     (else diff --git a/toot/accounts.scm b/toot/accounts.scm new file mode 100644 index 0000000..79eedb6 --- /dev/null +++ b/toot/accounts.scm @@ -0,0 +1,58 @@ +;;; Toot --- Mastodon client. +;;; Copyright © 2020 Masaya Tojo <masaya@tojo.tokyo> +;;; +;;; This file is part of Toot. +;;; +;;; Toot is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; Toot is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with Toot.  If not, see <http://www.gnu.org/licenses/>. + +(define-module (toot accounts) +  #:use-module (toot emojis) +  #:use-module (srfi srfi-9) +  #:use-module (srfi srfi-9 gnu) +  #:use-module (ice-9 format) +  #:export (account-from-json +            account? +            account-id +            account-display-name +            account-avatar-static +            account-acct +            account-emojis +            )) + +(define-record-type <account> +  (account-from-json json) +  account? +  (json account-json)) + +(set-record-type-printer! <account> +  (lambda (account port) +    (format port "#<account id: ~s acct: ~s ...>" +            (account-id account) +            (account-acct account)))) + +(define (account-id account) +  (assoc-ref (account-json account) "id")) + +(define (account-display-name account) +  (assoc-ref (account-json account) "display_name")) + +(define (account-avatar-static account) +  (assoc-ref (account-json account) "avatar_static")) + +(define (account-acct account) +  (assoc-ref (account-json account) "acct")) + +(define (account-emojis account) +  (map emoji-from-json +       (vector->list (assoc-ref (account-json account) "emojis")))) diff --git a/toot/attachments.scm b/toot/attachments.scm new file mode 100644 index 0000000..259036e --- /dev/null +++ b/toot/attachments.scm @@ -0,0 +1,39 @@ +;;; Toot --- Mastodon client. +;;; Copyright © 2020 Masaya Tojo <masaya@tojo.tokyo> +;;; +;;; This file is part of Toot. +;;; +;;; Toot is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; Toot is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with Toot.  If not, see <http://www.gnu.org/licenses/>. + +(define-module (toot attachments) +  #:use-module (srfi srfi-9) +  #:export (attachment-from-json +            attachment? +            attachment-type +            attachment-preview-url +            attachment-url)) + +(define-record-type <attachment> +  (attachment-from-json json) +  attachment? +  (json attachment-json)) + +(define (attachment-type attachment) +  (string->symbol (assoc-ref (attachment-json attachment) "type"))) + +(define (attachment-preview-url attachment) +  (assoc-ref (attachment-json attachment) "preview_url")) + +(define (attachment-url attachment) +  (assoc-ref (attachment-json attachment) "url")) diff --git a/toot/emojis.scm b/toot/emojis.scm new file mode 100644 index 0000000..9252911 --- /dev/null +++ b/toot/emojis.scm @@ -0,0 +1,55 @@ +;;; Toot --- Mastodon client. +;;; Copyright © 2020 Masaya Tojo <masaya@tojo.tokyo> +;;; +;;; This file is part of Toot. +;;; +;;; Toot is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; Toot is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with Toot.  If not, see <http://www.gnu.org/licenses/>. + +(define-module (toot emojis) +  #:use-module (srfi srfi-9) +  #:use-module (srfi srfi-9 gnu) +  #:use-module (srfi srfi-1) +  #:use-module (ice-9 regex) +  #:export (emoji-from-json +            emoji? +            emoji-static-url +            emoji-shortcode +            emoji-visible-in-picker? +            emojis->regexp +            emoji-find)) + +(define-record-type <emoji> +  (emoji-from-json json) +  emoji? +  (json emoji-json)) + +(define (emoji-static-url emoji) +  (assoc-ref (emoji-json emoji) "static_url")) + +(define (emoji-shortcode emoji) +  (assoc-ref (emoji-json emoji) "shortcode")) + +(define (emoji-visible-in-picker? emoji) +  (assoc-ref (emoji-json emoji) "visible_in_picker")) + +(define (emojis->regexp emojis) +  (string-append ":(" +                 (string-join (map (compose regexp-quote emoji-shortcode) +                                   emojis) +                              "|") +                 ":)")) + +(define (emoji-find emojis shortcode) +  (find (lambda (emoji) (equal? shortcode (emoji-shortcode emoji))) +        emojis)) diff --git a/toot/notifications.scm b/toot/notifications.scm new file mode 100644 index 0000000..a171183 --- /dev/null +++ b/toot/notifications.scm @@ -0,0 +1,59 @@ +;;; Toot --- Mastodon client. +;;; Copyright © 2020 Masaya Tojo <masaya@tojo.tokyo> +;;; +;;; This file is part of Toot. +;;; +;;; Toot is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; Toot is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with Toot.  If not, see <http://www.gnu.org/licenses/>. + +(define-module (toot notifications) +  #:use-module (toot statuses) +  #:use-module (toot accounts) +  #:use-module (toot utils) +  #:use-module (srfi srfi-9) +  #:export (notification-from-json +            notification? +            notification-id +            notification-status +            notification-account +            notification-type +            notification-creation-time)) + +(define-record-type <notification> +  (notification-from-json json) +  notification? +  (json notification-json)) + +(define (notification-id notification) +  (assoc-ref (notification-json notification) +             "id")) + +(define (notification-status notification) +  (status-from-json +   (assoc-ref (notification-json notification) +              "status"))) + +(define (notification-account notification) +  (account-from-json +   (assoc-ref (notification-json notification) +              "account"))) + +(define (notification-type notification) +  (string->symbol +   (assoc-ref (notification-json notification) +              "type"))) + +(define (notification-creation-time notification) +  (created-at->creation-time +   (assoc-ref (notification-json notification) +              "created_at"))) diff --git a/toot/statuses.scm b/toot/statuses.scm new file mode 100644 index 0000000..48e73ca --- /dev/null +++ b/toot/statuses.scm @@ -0,0 +1,107 @@ +;;; Toot --- Mastodon client. +;;; Copyright © 2020 Masaya Tojo <masaya@tojo.tokyo> +;;; +;;; This file is part of Toot. +;;; +;;; Toot is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; Toot is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with Toot.  If not, see <http://www.gnu.org/licenses/>. + +(define-module (toot statuses) +  #:use-module (toot emojis) +  #:use-module (toot accounts) +  #:use-module (toot attachments) +  #:use-module (srfi srfi-9) +  #:use-module (srfi srfi-9 gnu) +  #:use-module (ice-9 format) +  #:use-module (srfi srfi-19) +  #:use-module (toot utils) +  #:export (status-from-json +            status? +            status-public? +            status-sensitive? +            status-id +            status-account +            status-reblog +            status-visibility +            status-spoiler-text +            status-content +            status-emojis +            status-media-attachments +            status-in-reply-to-id +            status-in-reply-to-account-id +            status-creation-time)) + +(define-record-type <status> +  (status-from-json json) +  status? +  (json status-json)) + +(set-record-type-printer! <status> +  (lambda (status port) +    (format port +            "#<status id: ~s ...>" +            (status-id status)))) + +(define (status-public? status) +  (eq? 'public (status-visibility status))) + +(define (status-sensitive? status) +  (assoc-ref (status-json status) "sensitive")) + +(define (status-id status) +  (assoc-ref (status-json status) "id")) + +(define (status-account status) +  (account-from-json (assoc-ref (status-json status) "account"))) + +(define (status-reblog status) +  (let ((reblog/json (assoc-ref (status-json status) "reblog"))) +    (if (eq? reblog/json 'null) +        #f +        (status-from-json reblog/json)))) + +(define (status-visibility status) +  (string->symbol (assoc-ref (status-json status) "visibility"))) + +(define (status-spoiler-text status) +  (let ((s (assoc-ref (status-json status) "spoiler_text"))) +    (if (zero? (string-length s)) +        #f +        s))) + +(define (status-content status) +  (assoc-ref (status-json status) "content")) + +(define (status-emojis status) +  (map emoji-from-json +       (vector->list (assoc-ref (status-json status) "emojis")))) + +(define (status-media-attachments status) +  (let ((v (assoc-ref (status-json status) "media_attachments"))) +    (map attachment-from-json (vector->list v)))) + +(define (status-in-reply-to-id status) +  (let ((id (assoc-ref (status-json status) "in_reply_to_id"))) +    (if (eq? 'null id) +        #f +        id))) + +(define (status-in-reply-to-account-id status) +  (let ((id (assoc-ref (status-json status) "in_reply_to_account_id"))) +    (if (eq? 'null id) +        #f +        id))) + +(define (status-creation-time status) +  (created-at->creation-time (assoc-ref (status-json status) +                                        "created_at"))) diff --git a/toot/utils.scm b/toot/utils.scm new file mode 100644 index 0000000..5e9c73f --- /dev/null +++ b/toot/utils.scm @@ -0,0 +1,48 @@ +;;; Toot --- Mastodon client. +;;; Copyright © 2020 Masaya Tojo <masaya@tojo.tokyo> +;;; +;;; This file is part of Toot. +;;; +;;; Toot is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; Toot is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +;;; General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with Toot.  If not, see <http://www.gnu.org/licenses/>. + +(define-module (toot utils) +  #:use-module (ice-9 format) +  #:use-module (srfi srfi-19) +  #:export (and/nil + +            created-at->creation-time +            creation-time->string)) + + +;;; +;;; Macros. +;;; + +(define-syntax-rule (and/nil test expr) +  (if test +      expr +      '())) + + +;;; +;;; Date +;;; + +(define (created-at->creation-time str) +  (time-utc->date +   (date->time-utc +    (string->date str "~Y-~m-~dT~H:~M:~S.~N~z")))) + +(define (creation-time->string date) +  (date->string date "~4"))  | 
