The Arcology Garden

Extracting Wallabag metadata from my Read it Later files on koreader

  • use lua-http's http.request and lua-http's http.headers to construct an oauth2 client for wallabag

  • load credentials from a fennel file in homedir and generate an access_token on startup

    • see https://bag.fontkeming.fail/developer/howto/first-app for getting the access_token

  • render-one-book should notice that the file name has a [w-id_XXXX] in the filename extract that filename

  • load up the crappy oauth2 client

  • query the API for the GET /api/entries/:id.json endpoint, extract url from the JSON body

  • use that in the page template

Dead Simple Wallabag Fennel client

References

This does the bare-minimum and is probably not super re-usable without API modification?

Make a .wallabag file containing a lua expression:

lua
return {
   [ "client_id" ] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
   [ "client_secret" ] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
   [ "username" ] = "XXXX",
   [ "password" ] = "XXXX"
}

That will be read by wallabag.fnl:

fennel:tangle ~/Code/koreader-to-org/wallabag.fnl
(local hr (require :http.request))
(local tablex (require :pl.tablex))
(local pretty (require :pl.pretty))
(local rj (require :rapidjson))

(var api-prefix "https://bag.fontkeming.fail")

(fn load-client-credentials [path]
  ((loadfile path)))

That table can get fed directly to get-token:

fennel:tangle ~/Code/koreader-to-org/wallabag.fnl
(fn get-token [token-endpoint credentials]
  (let [req (hr.new_from_uri token-endpoint)
        body (tablex.copy credentials)]
    (set body.grant_type "password")
    (req:set_body (rj.encode body))
    (: (. req :headers) :upsert ":method" "POST")
    (: (. req :headers) :append "content-type" "application/json")
    (match (req:go)
      (headers stream) (let [{ :access_token at }
                             (rj.decode (stream:get_body_as_string 2))]
                         at))))

get-token returns an oauth token which will be valid for 1 hour. we don't cache that across invocations of the koreader-to-org command, sorry but Personal Software Can Be Shitty. api-req can consume one, and will return the headers and decoded JSON response.

fennel:tangle ~/Code/koreader-to-org/wallabag.fnl
(fn api-req [cred method uri body]
  (let [req (hr.new_from_uri uri)]
    (req:set_body (rj.encode body))
    (: (. req :headers) :upsert ":method" method)
    (: (. req :headers) :upsert "content-type" "application/json")
    (: (. req :headers) :upsert "authorization" (.. "Bearer " cred))
    (match (req:go)
      {:_data [{:name ":status" :value "404"}]} (print 404)
      {:_data [{:name ":status" :value "503"}]} (print 404)
      (headers stream) (values headers (rj.decode (stream:get_body_as_string 2)))
      _ (print "req failed"))))

{ :api-req api-req
  :get-token get-token
  :api-prefix api-prefix
  :load-client-credentials load-client-credentials }