aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Ángel Moreno <mail@migalmoreno.com>2023-02-17 12:59:57 +0100
committerMiguel Ángel Moreno <mail@migalmoreno.com>2023-02-17 13:06:58 +0100
commitcbfdef3a130b76a4e848e6275a6f4c63db82583b (patch)
tree33282c85c696099d6998f64c5060229984141464
parentbc2d78de31a596cde37e4a31088be7ba55fcf6a8 (diff)
feat: Refactor how instances are passed to routes
The ability to compute instances via arbitrary functions is removed, since arbitrary instances should be provided in triggers anyway. Now, the only way to add instances to a route is via an instances-builder object.
-rw-r--r--instances.lisp117
-rw-r--r--nx-router.asd1
-rw-r--r--router.lisp17
3 files changed, 127 insertions, 8 deletions
diff --git a/instances.lisp b/instances.lisp
new file mode 100644
index 0000000..b765038
--- /dev/null
+++ b/instances.lisp
@@ -0,0 +1,117 @@
+(in-package #:nx-router)
+(nyxt:use-nyxt-package-nicknames)
+
+(define-class instances-builder ()
+ ((source
+ nil
+ :type (or quri:uri string null))
+ (builder
+ nil
+ :type (or function symbol null)))
+ (:export-class-name-p t)
+ (:export-slot-names-p t)
+ (:export-accessor-names-p t)
+ (:accessor-name-transformer (class*:make-name-transformer name))
+ (:documentation "An instances builder for an alternative front-end."))
+
+(export-always 'libredirect-instances-source)
+(defvar libredirect-instances-source
+ "https://raw.githubusercontent.com/libredirect/instances/main/data.json")
+
+(export-always 'libredirect-instances-builder)
+(defun libredirect-instances-builder (service)
+ "Return an instances builder for SERVICE in Libredirect's generated list
+of instances."
+ (lambda (instances)
+ (rest (alex:assoc-value
+ (alex:assoc-value
+ (json:with-decoder-simple-list-semantics
+ (json:decode-json-from-string instances))
+ service)
+ :clearnet))))
+
+(export-always 'proxitok-instances-builder)
+(defvar proxitok-instances-builder
+ (make-instance
+ 'instances-builder
+ :source libredirect-instances-source
+ :builder (libredirect-instances-builder :proxi-tok)))
+
+(export-always 'whoogle-instances-builder)
+(defvar whoogle-instances-builder
+ (make-instance
+ 'instances-builder
+ :source libredirect-instances-source
+ :builder (libredirect-instances-builder :whoogle)))
+
+(export-always 'breezewiki-instances-builder)
+(defvar breezewiki-instances-builder
+ (make-instance
+ 'instances-builder
+ :source libredirect-instances-source
+ :builder (libredirect-instances-builder :breeze-wiki)))
+
+(export-always 'invidious-instances-builder)
+(defvar invidious-instances-builder
+ (make-instance
+ 'instances-builder
+ :source "https://api.invidious.io/instances.json"
+ :builder
+ (lambda (instances)
+ (mapcar 'first
+ (json:with-decoder-simple-list-semantics
+ (json:decode-json-from-string instances))))))
+
+(export-always 'scribe-instances-builder)
+(defvar scribe-instances-builder
+ (make-instance
+ 'instances-builder
+ :source
+ "https://git.sr.ht/~edwardloveall/scribe/blob/main/docs/instances.json"
+ :builder
+ (lambda (instances)
+ (json:decode-json-from-string instances))))
+
+(export-always 'teddit-instances-builder)
+(defvar teddit-instances-builder
+ (make-instance
+ 'instances-builder
+ :source
+ "https://codeberg.org/teddit/teddit/raw/branch/main/instances.json"
+ :builder
+ (lambda (instances)
+ (mapcar (lambda (instance)
+ (unless (str:emptyp (alex:assoc-value instance :url))
+ (alex:assoc-value instance :url)))
+ (json:with-decoder-simple-list-semantics
+ (json:decode-json-from-string instances))))))
+
+(export-always 'libreddit-instances-builder)
+(defvar libreddit-instances-builder
+ (make-instance
+ 'instances-builder
+ :source
+ "https://raw.githubusercontent.com/libreddit/libreddit-instances/master/instances.json"
+ :builder
+ (lambda (instances)
+ (mapcar (lambda (instance)
+ (unless (str:emptyp (alex:assoc-value instance :url))
+ (alex:assoc-value instance :url)))
+ (alex:assoc-value
+ (json:with-decoder-simple-list-semantics
+ (json:decode-json-from-string instances))
+ :instances)))))
+
+(defun fetch-instances (url)
+ (handler-case (dex:get url)
+ (usocket:ns-host-not-found-error ()
+ (nyxt:echo-warning
+ "There's no Internet connection to retrieve instances")
+ nil)))
+
+(defgeneric build-instances (instances-builder)
+ (:documentation "Build a list of instances from INSTANCES-BUILDER."))
+
+(defmethod build-instances ((instances-builder instances-builder))
+ (alex:when-let ((instances (fetch-instances (source instances-builder))))
+ (delete nil (funcall (builder instances-builder) instances))))
diff --git a/nx-router.asd b/nx-router.asd
index 9711bf1..79f2b3a 100644
--- a/nx-router.asd
+++ b/nx-router.asd
@@ -6,6 +6,7 @@
:serial t
:depends-on ("nyxt")
:components ((:file "package")
+ (:file "instances")
(:file "router"))
:in-order-to ((test-op (test-op "nx-router/tests"))))
diff --git a/router.lisp b/router.lisp
index 0efdf93..46b5c62 100644
--- a/router.lisp
+++ b/router.lisp
@@ -11,12 +11,13 @@
((trigger
'()
:type (or string list function)
- :documentation "Trigger(s) to determine if this `route' is to be activated.")
- (instances
+ :documentation "Trigger(s) to determine if `route' is to be activated.")
+ (instances-builder
nil
- :type (or null function)
- :documentation "A function to compute a list of instances to add to `:trigger',
-useful if a service provides an official endpoint where these are stored.")
+ :type (maybe (list-of instances-builder))
+ :documentation "An `instances-builder' object that holds the necessary setup
+to build a list of instances for a service provider. These will be added to
+the route's `:trigger'.")
(toplevel-p
t
:type boolean
@@ -152,8 +153,8 @@ want to modify in a web buffer."))
'handle-routing))
(defmethod initialize-instance :after ((route route) &key)
- (with-slots (instances trigger) route
- (nyxt:run-thread "Set up trigger"
+ (with-slots (instances-builder trigger) route
+ (nyxt:run-thread "nx-router trigger build"
(flet ((construct-predicates (sources)
(mapcar (lambda (instance)
`(nyxt:match-host
@@ -213,7 +214,7 @@ want to modify in a web buffer."))
((list-of-lists-p trigger)
(triggers-match-p trigger))
((listp trigger)
- (if (instances route)
+ (if (instances-builder route)
(triggers-match-p trigger)
(funcall (eval trigger) url)))
((functionp trigger)