remove whitespace
Add a utilities file for helpful utilities and wrappers.
add auto method for calling an api endpoint
This repository implements bindings to the Lemmy API for Common Lisp.
Lemmy API interfaces, API endpoints, enums, and types are defined according to the unofficial openapi specification.
The main project page is available at https://sr.ht/~yana/cl-lemmy-api/. Bugs may be reported at https://todo.sr.ht/~yana/cl-lemmy-api/. The mailing list is used for patches and general discussion. The mailing list archives can be browsed at https://lists.sr.ht/~yana/cl-lemmy-api/.
Start by loading the ASDF system :LEMMY-API
. This will load the most recent
version of the api bindings (v0.19.5 at time of writing).The API can now be
interacted with by using the generic function CALL-API-ENDPOINT
with an
endpoint and an instance of a lemmy interface class, such as GET-POSTS
. The
instances of lemmy interface objects can be validated with the function
VALIDATE-LEMMY-INTERFACE
.
As an example of this, lets take a look at what logging in might look like:
CL-USER> (ql:quickload :lemmy-api)
To load "lemmy-api":
Load 1 ASDF system:
lemmy-api
; Loading "lemmy-api"
..................................................
[package lemmy-api/0.19.5]........................
..................................................
[package lemmy-api].
(:LEMMY-API)
CL-USER> (lemmy-api:call-api-endpoint 'lemmy-api:/user/login
(make-instance 'lemmy-api:login
:username-or-email
"USERNAME"
:password
"PASSWORD")
:server "https://SERVER.com"
:validate-inbound t)
WARNING: Received HTTP response code 200. Expected one of the following:
400, 201
#<LEMMY-INTERFACE "LoginResponse" {1005020BE3}>
200 (8 bits, #xC8, #o310, #b11001000)
CL-USER> (setf lemmy-api:*jwt* (lemmy-api:jwt *))
"long-token"
CL-USER> (lemmy-api:call-api-endpoint 'lemmy-api:/user/list_logins
nil
:server "https://SERVER.com")
(#<LEMMY-INTERFACE "LoginToken" {1005829293}>
#<LEMMY-INTERFACE "LoginToken" {1005829333}>
#<LEMMY-INTERFACE "LoginToken" {10058293D3}>
#<LEMMY-INTERFACE "LoginToken" {1005829473}>
#<LEMMY-INTERFACE "LoginToken" {1005829513}>
#<LEMMY-INTERFACE "LoginToken" {10058295B3}>)
200 (8 bits, #xC8, #o310, #b11001000)
Most api endpoints return a lemmy interface object, however this one (/user/list_logins) returns an array of lemmy interface objects.
Since version 0.19.5 the way the API is interacted with has changed. Prior to
this API calls were made with the function LEMMY-API-OPERATE
. This is
considered deprecated and is not implemented for version 0.19.5 or later, but
the generic function is still present.
As of version 0.18.3: Some slots are specified as required but are not given by
the server. These should be specified when calling VALIDATE-LEMMY-INTERFACE
,
or added to the dynamic variable *SLOTS-TO-IGNORE*
. A non-comprehensive list
is given at the end of this document. If you become aware of such errors, please
submit a patch updating this list.
When parsing a lemmy interface object without being given an explicit type, a
object of type EMPTY-LEMMY-INTERFACE
will be instantiated instead, with its
slot UNKNOWN-SLOTS
propogated with whatever the JSON parsed out to. An example
of this can be found in the api endpoint /USER/VALIDATE_AUTH
in version
0.19.5, which does not expect a JSON response from the server but gets one
anyway.
This system does not bind slots that dont have a value when generating them from
a JSON response. As such, it may be helpful in certain circumstances to define
custom accessors for specific slots, or alternatively to establish a handler for
unbound slot errors that returns NIL
when invoked with a lemmy-interface
object. E.g.
(handler-bind ((unbound-slot
(lambda (c)
(when (typep (unbound-slot-instance c) 'lemmy-interface)
(let ((r (find-restart 'use-value c)))
(when r
(invoke-restart r nil)))))))
(code body))
As of version 0.18.3: This system does not provide complete bindings. The current system of parsing bindings from the javascript sources is error prone; not all interfaces and methods parse correctly. The solution to this would be to generate an api specification from the rust sources using rust macros. While this is currently under consideration at time of writing, it appears there are numerous issues standing in the way of this. If you are interested in contributing to this endeavor, please see this issue as a starting point: https://github.com/LemmyNet/lemmy/issues/2937.
As of version 0.19.5: The unofficial lemmy openapi specification is used to generate the bindings. This eliminates the error prone parsing of javascript sources. However this system should not be assumed to provide all bindings. If you find a binding that is not present or has not been parsed correctly, please open an issue.
This project is broken up into three strata. The base system, LEMMY-API/BASE
,
defines the framework that allows interface objects to be implemented. This
includes, among other things, the macros DEFINE-INTERFACE-CLASS
and
DEFINE-API-ENDPOINT
. The top level system LEMMY-API
provides a common
package to expose symbols from specific lemmy api versions. These versioned
packages, such as LEMMY-API/0.18.3
, are USE
d by, and have their symbols
re-exported from, LEMMY-API
.
The system LEMMY-API
loads the latest version of the API bindings (at the time
of writing this is v0.19.5), however alternate versions can be loaded by asdf by
specifying the version number, e.g. LEMMY-API/0.18.3
. The LEMMY-API
package
does not define or export any additional symbols, it is provided simply for ease
of use, and the underlying versioned packages can be used in its stead.
The specific definition files for individual versions lie in the
version/x.y.z/
folders. In addition, the specific version of the lemmy api
currently loaded is pushed to the *FEATURES*
list, and multiple versions of
the api bindings can be loaded, as they reside in separate packages.
USE
-ing This PackageDo not use the System LEMMY-API
, unless providing a vendored version; the
LEMMY-API
package tracks the latest api version, and its exported symbols are
subject to change. However, LEMMY-API/MAJ.MIN.PAT
packages should be
considered stable and not subject to change.
New api versions can be defined by running the shell script
generate-bindings.sh
. This shell script takes a single .yaml
specification
file as its only argument. This will place the result of the specification into
its own version folder. It will not generate the asd file entry for the
generated version, this must be manually added to the file lemmy-api.asd
using
the macro define-lemmy-version
.
This file defines the metaobject used for lemmy interface classes. The MOP is used to add additional parameters to slot definitions, which eases the conversion of slot values into and out of the JSON format, and allows for easier validation.
This file provides the interface definition macro and the validation function for interface objects.
This file defines conditions used in the lemmy api system.
This file defines how interface objects will be parsed from JSON.
This file provides the inverse of json-to-interface.lisp
.
This file provides the plumbing for sending and receiving information to and
from a server. It defines the macro DEFINE-API-ENDPOINT
, as well as the
deprecated DEFINE-LEMMY-API-METHOD
. It also defines a host of auxillary
functions for making the actual api calls.
This file defines the specific versioned package, and registers the feature
:LEMMY-API/MAJOR.MINOR.PATCH
.
As of version 0.19.5: This file is generated automatically in two stages from
the unofficial openapi specification. First the specification (a .yaml
file)
is parsed into memory, and then used to generate a lispy specification
file. That specification file is used to generate a definitions file containing
all the type, class, and method definitions.
As of version 0.18.3: This file is generated automatically in two stages from the lemmy javascript client sources. First the javascript client sources are parsed into a specification file. These specifications are then used to generate the types, classes, and methods which reside in this file. In addition all types, class names, and accessors are exported.
GPLv3
INBOX-URL