This egg may still work with a more recent version of the spec, but it's not guaranteed. An example of a change in the spec that doesn't require any change in the API is this:
17 | 3.01 | yes | torrent-get | new arg "file-count" 17 | 3.01 | yes | torrent-get | new arg "primary-mime-type"
This is because the library doesn't check if the fields are valid (this is intentional).
These changes, however:
16 | 3.00 | yes | session-get | new request arg "fields" 16 | 3.00 | yes | torrent-get | new request arg "format" 16 | 3.00 | yes | torrent-set | new arg "labels"
Require API changes, because otherwise the fields and format arguments can't be used.
NOTE: This egg uses medea to read and write JSON, which by default reads object keys as symbols. This isn't great, so don't use this library with untrusted Transmission clients if you can avoid it. In the future the reader will be changed to read the keys as strings instead.
The following eggs are required for using this egg:
The following eggs are required for testing this egg:
Every method of the spec is defined, and naming is followed almost directly. In the spec, all methods and most arguments follow the kebab-case convention. The exceptions are a few arguments in camelCase -- these are converted to kebab-case in this egg: e.g., the key argument for queuePosition is called queue-position. Note, however, that the messages are left untouched: a message to/from the server will still use queuePosition as the key, NOT queue-position.
Almost all required parameters are positional arguments in the library -- the only exception is the ids argument, which is always a key argument, even for methods with required ids, because it defaults to no IDs to avoid acting on torrents by accident.
All optional arguments in the spec are key arguments in the library.
Create a torrent source to use with torrent-add. A torrent can be added from a magnet URL; from a torrent file, given its path, which must be readable by the Transmission daemon; or the contents of the torrent file, encoded in Base64.
Every API procedure returns a result, which is a SRFI-189 Either object. The most useful and most commonly used procedures for handling results are renamed and exported. On top of these, some others are defined.
- true #!rest _procedure
- false #!rest _procedure
- result/error obj ...procedure
- result/error? objprocedure
- result/ok obj ...procedure
- result/ok? objprocedure
- result? objprocedure
- result-bind result mproc1 mproc2 ...procedure
- result-ref result failure #!optional successprocedure
- exception->result pred thunkprocedure
- result/error-ref result #!optional (fail false)procedure
- result/ok-ref result #!optional (fail false)procedure
- result-ref* resultprocedure
- default-error-proc result/con #!optional tag req respprocedure
- with-transmission-result result success-proc #!optional (error-proc default-error-proc)procedure
Convenient way to handle a single RPC call's result.
with-transmission-result is similar to result-ref (either-ref from SRFI-189), except that the order of the success and failure procedures is swapped. The failure procedure defaults to default-error-proc, which calls error with a generic error message.
success-proc should be a procedure of 4 parameters: the arguments and tag fields of a reply message, the uri-common request object, and the intarweb response object.
failure-proc should be a procedure of 4 parameters, 3 of them optional: result/con, tag, req, and resp. result and tag are the fields of a reply message, req is the uri-common request object, and resp is the intarweb response object. tag, req, and resp are either all false or none false. If they're false, result/con is a condition object thrown during the API call; if they're not false, then result/con is a result string.
- (make-rpc-call (method (required required-handler) ...) (key default key-handler) ...)syntax
- (make-rpc-call method (key default key-handler) ...)syntax
- (define-rpc-call (method required ...) key ...)syntax
- (define-rpc-call method key ...)syntax
- (export-rpc-call (method required ...) key ...)syntax
- (export-rpc-call method key ...)syntax
- (export-3.1/4.6 method)syntax
make-rpc-call creates a procedure to represent an RPC method.
export-3.1/4.6 exports RPC procedures of sections 3.1 and 4.6 of the spec, which have a single optional ids argument.
required is the name of a required argument. It will not be used in messages.
key is the name of an optional (key) argument. It will be used as the key name in the created procedure, but not in messages.
required-handler and key-handler are functions that will process a given value, to assure it has the right type/format, and return an entry ready to be inserted into the arguments object of a message, i.e., they must return a (key . value) pair that will later be converted to JSON.
default is the default value of an optional (key) argument.
- rpc-call method #!key (arguments #f) (tag #f)procedure
Make an RPC call. method is the name of the RPC method, and arguments is the arguments object, containing both required and optional arguments.
- handle-409 condition request messageprocedure
- http-call request messageprocedure
- (update-request-session-id request #!optional (session-id (*session-id*)))procedure
- make-serialized-message method arguments tagprocedure
- make-message method arguments tagprocedure
- (make-rpc-request host url port username password #!optional (session-id (*session-id*)))procedure
- (alist-let alist (formal ...) body ...)syntax
- (alist-let/and alist (formal ...) body ...)syntax
- (alist-let/nor alist (formal ...) body ...)syntax
Where formal is either key, which will be used both as the key name and the variable, or (var key), which will be the variable name and key respectively.
(let ((var (alist-ref 'key alist)) ...) body ...)
(alist-let/and '((ant . 3) (bunny . 5) (Cat . 3)) (ant bunny (cat Cat)) (list ant bunny cat))
Expands to something like this:
(let ((%alist '((ant . 3) (bunny . 5) (Cat . 3)))) (let ((ant (alist-ref 'ant %alist)) (bunny (alist-ref 'bunny %alist)) (cat (alist-ref 'Cat %alist))) (list ant bunny cat)))
- unique-tag! #!optional (new-n #f)procedure
Return an unique tag, that starts at 0 and is incremented by 1 on each call. If new-n is given and is a fixnum?, set the internal variable to new-n for future use.
The torrent status constants.
The priority constants -- for bandwidth-priority.
The following example lists all the torrents that satisfy a certain predicate: they must be seeding, have an upload ratio greater than 1, and the download path must be /some/path/ (note that, to Transmission, /some/path and /some/path/ are not the same).
(import srfi-1 transmission transmission.utils) (parameterize ((*host* "hostname") (*username* "username") (*password* "password")) (let ((tag (unique-tag!))) (with-transmission-result (torrent-get '("downloadDir" "id" "name" "status" "uploadRatio") #:ids #f #:tag tag) (lambda (arguments tag req resp) (define (want-torrent? tor) (alist-let/and tor (downloadDir status uploadRatio) (and (= status status/seed) (> uploadRatio 1) (string=? downloadDir "/some/path/")))) (alist-let/and arguments (torrents) (let ((wanted-tors (filter want-torrent? (vector->list torrents)))) (for-each print wanted-tors)))) ; NOTE: The error case handling procedure doesn't have to accept ; #!optional arguments -- the "missing" arguments will be #f. (lambda (result tag req resp) (error 'here "torrent-get call failed with the following error" result)))))
For more examples take a look at https://git.sr.ht/~siiky/trmote (no longer in this egg's download directory). The example above is similar to transmission-filter from that repo.
This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to <http://unlicense.org>
- Add *scheme* parameter to support HTTPS as well.
- default-error-proc now supports the case where the result was just a condition;
- Add (hopefully) useful example programs to the examples directory -- you can get these from the repo or the chicken-install cache directory;
- Export alist-let from transmission.utils.
- Return a more functional result object from API calls instead of a more C-like reply for easier error handling. There's no chance to mistake an error for a good result now;
- Improve alist-let/and and alist-let/nor to support optional variable names, and save the value resulting of evaluating the alist expression;
- Add priority constants;
- Rename unique-tag to unique-tag!;
- Replace vector-lib with r7rs because srfi-189 depends on it anyway.
Add with-transmission-reply and update the documentation accordingly.
Initial release with all methods defined, and almost all tested.