hydrus/help/client_api.html

506 lines
22 KiB
HTML
Raw Normal View History

2019-02-06 22:41:35 +00:00
<html>
<head>
<title>client api</title>
<link href="hydrus.ico" rel="shortcut icon" />
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="content">
<p class="warning">This is all currently under construction!</p>
<h3>client api</h3>
2019-02-13 22:26:43 +00:00
<p>The hydrus client now supports a very simple API so you can access it with external programs.</p>
<p>By default, the Client API is not turned on. Go to <i>services->manage services</i> and give it a port to get it started. I recommend you not allow non-local connections (i.e. only requests from the same computer will work) to start with.</p>
<p>The Client API should start immediately. It will only be active while the client is open. To test it is running all correct (and assuming you used the default port of 45869), try loading this:</p>
2019-02-06 22:41:35 +00:00
<a href="http://127.0.0.1:45869"><pre>http://127.0.0.1:45869</pre></a>
2019-02-13 22:26:43 +00:00
<p>You should get a welcome page. For now, the Client API is http only.</p>
<p>Then go to its entry in <i>services->review services</i>. Each external program trying to access the API will need its own access key, which is the familiar 64-character hexadecimal used in many places in hydrus. You can enter the details manually from the review services panel and then copy/paste the key to your external program, or you can have the program request its own access while a mini-dialog launched from the review services panel waits to catch the request.</p>
<h3>Support created by hydrus users:</h3>
<ul>
<li><a href="https://gitgud.io/prkc/hydrus-companion">https://gitgud.io/prkc/hydrus-companion</a> - Hydrus Companion, a browser extension for hydrus.</li>
<li><a href="https://gitlab.com/cryzed/hydrus-api">https://gitlab.com/cryzed/hydrus-api</a> - A python module that talks to the API.</li>
</ul>
<h3>API</h3>
2019-02-27 23:03:30 +00:00
<p>If the API returns anything on 200, it should always return JSON. Otherwise, assume it will return plain text, sometimes a raw traceback. You'll typically get 400 for a missing parameter, 401 or 403 for missing/insufficient access, and 500 for a real deal serverside error.</p>
<h3>Contents</h3>
<ul>
<li>
<h4>Access Management</h4>
<ul>
<li><a href="#api_version">GET /api_version</a></li>
<li><a href="#request_new_permissions">GET /request_new_permissions</a></li>
<li><a href="#verify_access_key">GET /verify_access_key</a></li>
</ul>
<h4>Adding Files</h4>
<ul>
<li><a href="#add_files_add_file">POST /add_files/add_file</a></li>
</ul>
<h4>Adding Tags</h4>
<ul>
<li><a href="#add_tags_clean_tags">GET /add_tags/clean_tags</a></li>
<li><a href="#add_tags_get_tag_services">GET /add_tags/get_tag_services</a></li>
<li><a href="#add_tags_add_tags">POST /add_tags/add_tags</a></li>
</ul>
<h4>Adding URLs</h4>
<ul>
<li><a href="#add_urls_get_url_files">GET /add_urls/get_url_files</a></li>
<li><a href="#add_urls_get_url_info">GET /add_urls/get_url_info</a></li>
<li><a href="#add_urls_add_url">POST /add_urls/add_url</a></li>
<li><a href="#add_urls_associate_url">POST /add_urls/associate_url</a></li>
</ul>
</ul>
2019-02-06 22:41:35 +00:00
<h3>Access Management</h3>
2019-02-27 23:03:30 +00:00
<div class="apiborder" id="api_version">
2019-02-06 22:41:35 +00:00
<h3><b>GET /api_version</b></h3>
2019-02-13 22:26:43 +00:00
<p><i>Gets the current API version. I will increment this every time I alter the API.</i></p>
2019-02-06 22:41:35 +00:00
<ul>
<li><p>Headers: n/a</p></li>
<li><p>Arguments: n/a</p></li>
2019-02-13 22:26:43 +00:00
<li><p>Response description: Some simple JSON describing the current version.</p></li>
2019-02-06 22:41:35 +00:00
<li>
<p>Example response:</p>
<ul>
2019-02-13 22:26:43 +00:00
<li><pre>{"version": 1}</pre></li>
2019-02-06 22:41:35 +00:00
</ul>
</li>
</ul>
</div>
2019-02-27 23:03:30 +00:00
<div class="apiborder" id="request_new_permissions">
2019-02-06 22:41:35 +00:00
<h3><b>GET /request_new_permissions</b></h3>
<p><i>Register a new external program with the client. This requires the 'add from api request' mini-dialog under </i>services->review services<i> to be open, otherwise it will 403.</i></p>
<ul>
<li><p>Headers: n/a</p></li>
<li>
<p>Arguments:</p>
<ul>
<li>name : (descriptive name of your access)</li>
2019-02-13 22:26:43 +00:00
<li>basic_permissions : A JSON-encoded list of numerical permission identifiers you want to request.</li>
2019-02-06 22:41:35 +00:00
</ul>
</li>
<li>
<p>The permissions are currently:</p>
<ul>
2019-02-13 22:26:43 +00:00
<li>0 - Import URLs</li>
<li>1 - Import Files</li>
<li>2 - Add Tags</li>
2019-02-06 22:41:35 +00:00
<li>3 - Search for files</li>
</ul>
</li>
<li>
<p>Example request:</p>
<ul>
<li><p>/request_access_permissions?name=my%20import%20script&basic_permissions=[0,1]</p></li>
</ul>
</li>
2019-02-13 22:26:43 +00:00
<li><p>Response description: Some JSON with your access key, which is 64 characters of hex. This will not be valid until the user approves the request in the client ui.</p></li>
2019-02-06 22:41:35 +00:00
<li>
<p>Example response:</p>
<ul>
2019-02-13 22:26:43 +00:00
<li><pre>{"access_key": "73c9ab12751dcf3368f028d3abbe1d8e2a3a48d0de25e64f3a8f00f3a1424c57"}</pre></li>
2019-02-06 22:41:35 +00:00
</ul>
</li>
</ul>
</div>
2019-02-27 23:03:30 +00:00
<div class="apiborder" id="verify_access_key">
2019-02-06 22:41:35 +00:00
<h3><b>GET /verify_access_key</b></h3>
<p><i>Check your access key is valid.</i></p>
<ul>
<li>
<p>Headers:</p>
<ul>
<li>Hydrus-Client-API-Access-Key : (Your hexadecimal access key)</li>
</ul>
</li>
<li><p>Arguments: n/a</p></li>
<li><p>Response description: 403 and some error text if the access key is invalid, otherwise some JSON with basic permission info.</p></li>
<li>
<p>Example response:</p>
<ul>
2019-02-13 22:26:43 +00:00
<li>
<pre>{
"basic_permissions": [0, 1, 3],
"human_description": "API Permissions (autotagger): add tags to files, import files, search for files: Can search: only autotag this"
}</pre>
</li>
2019-02-06 22:41:35 +00:00
</ul>
</li>
</ul>
</div>
<h3>Adding Files</h3>
2019-02-27 23:03:30 +00:00
<div class="apiborder" id="add_files_add_file">
2019-02-13 22:26:43 +00:00
<h3><b>POST /add_files/add_file</b></h3>
<p><i>Tell the client to import a file.</i></p>
<ul>
<li>
<p>Headers:</p>
<ul>
<li>Hydrus-Client-API-Access-Key : (Your hexadecimal access key)</li>
<li>Content-Type : application/json (if sending path), application/octet-stream (if sending file)</li>
</ul>
</li>
<li><p>Arguments (in JSON):</p></li>
<blockquote>path : (the path you want to import)</blockquote>
<li>
<p>Example request body:</p>
<blockquote><pre>{"path": "E:\\to_import\\ayanami.jpg"}</pre></blockquote>
</li>
<li><p>Arguments (as bytes): You can alternately just send the file's bytes as the POST body.</p></li>
<li><p>Response description: Some JSON with the import result. Please note that file imports for large files may take several seconds, and longer if the client is busy doing other db work, so make sure your request is willing to wait that long for the response.</p></li>
<li>
<p>Example response:</p>
<pre>{
"status": 1,
"hash": "29a15ad0c035c0a0e86e2591660207db64b10777ced76565a695102a481c3dd1",
"note": ""
}</pre>
<p>'status' is:</p>
<ul>
<li>1 - File was successfully imported</li>
<li>2 - File already in database</li>
<li>3 - File previously deleted</li>
<li>4 - File failed to import</li>
<li>7 - File vetoed</li>
</ul>
<p>A file 'veto' is caused by the file import options (which in this case is the 'quiet' set under the client's <i>options->importing</i>) stopping the file due to its resolution or minimum file size rules, etc...</p>
<p>'hash' is the file's SHA256 hash in hexadecimal, and 'note' is some occasional additional human-readable text appropriate to the file status that you may recognise from hydrus's normal import workflow. For an import error, it will always be the full traceback.</p>
</li>
</ul>
2019-02-06 22:41:35 +00:00
</div>
<h3>Adding Tags</h3>
2019-02-27 23:03:30 +00:00
<div class="apiborder" id="add_tags_clean_tags">
<h3><b>GET /add_tags/clean_tags</b></h3>
<p><i>Ask the client about how it will see certain tags.</i></p>
<ul>
<li>
<p>Headers:</p>
<ul>
<li>Hydrus-Client-API-Access-Key : (Your hexadecimal access key)</li>
</ul>
</li>
<li><p>Arguments (in percent-encoded JSON):</p></li>
<ul>
<li>tags : (a list of the tags you want cleaned)</li>
</ul>
<li>
<p>Example request:</p>
<pre>Given tags [ " bikini ", "blue eyes", " character : samus aran ", ":)", " ", "", "10", "11", "9", "system:wew", "-flower" ]:</pre>
<ul>
<li><p>/add_tags/clean_tags?tags=%5B%22%20bikini%20%22%2C%20%22blue%20%20%20%20eyes%22%2C%20%22%20character%20%3A%20samus%20aran%20%22%2C%20%22%3A%29%22%2C%20%22%20%20%20%22%2C%20%22%22%2C%20%2210%22%2C%20%2211%22%2C%20%229%22%2C%20%22system%3Awew%22%2C%20%22-flower%22%5D</p></li>
</ul>
</li>
<li>
<p>Response description: The tags cleaned according to hydrus rules. They will also be in hydrus human-friendly sorting order.</p>
</li>
<li>
<p>Example response:</p>
<ul>
<li>
<pre>{
"tags": [ "9", "10", "11", "::)", "bikini", "blue eyes", "character:samus aran", "flower", "wew" ]
}</pre>
</li>
</ul>
<p>Mostly, hydrus simply trims excess whitespace, but the other examples are rare issues you might run into. 'system' is an invalid namespace, tags cannot be prefixed with hyphens, and any tag starting with ':' is secretly dealt with internally as "[no namespace]:[colon-prefixed-subtag]". Again, you probably won't run into these, but if you see a mismatch somewhere and want to figure it out, or just want to sort some numbered tags, you might like to try this.</p>
</li>
</ul>
</div>
<div class="apiborder" id="add_tags_get_tag_services">
2019-02-13 22:26:43 +00:00
<h3><b>GET /add_tags/get_tag_services</b></h3>
<p><i>Ask the client about its tag services.</i></p>
<ul>
<li>
<p>Headers:</p>
<ul>
<li>Hydrus-Client-API-Access-Key : (Your hexadecimal access key)</li>
</ul>
</li>
<li><p>Arguments: n/a</p></li>
<li>
<p>Response description: Some JSON listing the client's 'local tags' and tag repository services by name.</p>
</li>
<li>
<p>Example response:</p>
<ul>
<li>
<pre>{
"local_tags": [ "local tags" ]
"tag_repositories": [ "public tag repository", "mlp fanfic tagging server" ]
}</pre>
</li>
</ul>
<p>Note that a user can rename their services. Don't assume the client's local tags service will be "local tags".</p>
</li>
</ul>
</div>
2019-02-27 23:03:30 +00:00
<div class="apiborder" id="add_tags_add_tags">
2019-02-13 22:26:43 +00:00
<h3><b>POST /add_tags/add_tags</b></h3>
2019-02-27 23:03:30 +00:00
<p><i>Make changes to the tags that files have.</i></p>
<ul>
<li>
<p>Headers:</p>
<ul>
<li>Hydrus-Client-API-Access-Key : (Your hexadecimal access key)</li>
</ul>
</li>
<li><p>Arguments (in JSON):</p></li>
<ul>
<li>hash : (an SHA256 hash for a file in 64 characters of hexadecimal)</li>
<li>hashes : (a list of SHA256 hashes)</li>
<li>service_names_to_tags : (an Object of service names to lists of tags to be 'added' to the files)</li>
<li>service_names_to_actions_to_tags : (an Object of service names to content update actions to lists of tags)</li>
</ul>
<p>You can use either 'hash' or 'hashes', and you can use either the simple add-only 'service_names_to_tags' or the advanced 'service_names_to_actions_to_tags'.</p>
<p>The service names are as in the <i>/add_tags/get_tag_services</i> call.</p>
<p>The permitted 'actions' are:</p>
<ul>
<li>0 - Add to a local tag service.</li>
<li>1 - Delete from a local tag service.</li>
<li>2 - Pend to a tag repository.</li>
<li>3 - Rescind a pend from a tag repository.</li>
<li>4 - Petition from a tag repository. (This is special)</li>
<li>5 - Rescind a petition from a tag repository.</li>
</ul>
<p>When you petition a tag from a repository, a 'reason' for the petition is typically needed. If you send a normal list of tags here, a default reason of "Petitioned from API" will be given. If you want to set your own reason, you can instead give a list of [ tag, reason ] pairs.</p>
<p>Some example requests:</p>
<p>Adding some tags to a file:</p>
<pre>{
"hash" : "df2a7b286d21329fc496e3aa8b8a08b67bb1747ca32749acb3f5d544cbfc0f56",
"service_names_to_tags" : {
"local tags" : [ "character:supergirl", "rating:safe" ]
}
}</pre>
<p>Adding more tags to two files:</p>
<pre>{
"hashes" : [ "df2a7b286d21329fc496e3aa8b8a08b67bb1747ca32749acb3f5d544cbfc0f56", "f2b022214e711e9a11e2fcec71bfd524f10f0be40c250737a7861a5ddd3faebf" ],
"service_names_to_tags" : {
"local tags" : [ "process this" ],
"public tag repository" : [ "creator:dandon fuga" ]
}
}</pre>
<p>A complicated transaction with all possible actions:</p>
<pre>{
"hash" : "df2a7b286d21329fc496e3aa8b8a08b67bb1747ca32749acb3f5d544cbfc0f56",
"service_names_to_actions_to_tags" : {
"local tags" : {
0 : [ "character:supergirl", "rating:safe" ],
1 : [ "character:superman" ]
},
"public tag repository" : {
2 : [ "character:supergirl", "rating:safe" ],
3 : [ "filename:image.jpg" ],
4 : [ [ "creator:danban faga", "typo" ], [ "character:super_girl", "underscore" ] ]
5 : [ "skirt" ]
}
}
}</pre>
<p>This last example is far more complicated than you will usually see. Pend rescinds and petition rescinds are not common. Petitions are also quite rare, and gathering a good petition reason for each tag is often a pain.</p>
<p>Response description: 200 and no content.</p>
<p>Note also that hydrus tag actions are safely idempotent. You can pend a tag that is already pended and not worry about an error--it will be discarded. The same for other reasonable logical scenarios: deleting a tag that does not exist will silently make no change, pending a tag that is already 'current' will again be passed over. It is fine to just throw 'process this' tags at every file import you add and not have to worry about checking which files you already added it to.</p>
</ul>
2019-02-06 22:41:35 +00:00
</div>
<h3>Adding URLs</h3>
2019-02-27 23:03:30 +00:00
<div class="apiborder" id="add_urls_get_url_files">
2019-02-13 22:26:43 +00:00
<h3><b>GET /add_urls/get_url_files</b></h3>
<p><i>Ask the client about an URL's files.</i></p>
<ul>
<li>
<p>Headers:</p>
<ul>
<li>Hydrus-Client-API-Access-Key : (Your hexadecimal access key)</li>
</ul>
</li>
<li>
<p>Arguments:</p>
<ul>
<li>url : (the url you want to ask about)</li>
</ul>
</li>
<li>
<p>Example request (for URL http://safebooru.org/index.php?page=post&s=view&id=2753608):</p>
<ul>
<li><p>/add_urls/get_url_files?url=http%3A%2F%2Fsafebooru.org%2Findex.php%3Fpage%3Dpost%26s%3Dview%26id%3D2753608</p></li>
</ul>
</li>
<li>
<p>Response description: Some JSON which files are known to be mapped to that URL. Note this needs a database hit, so it may be delayed if the client is otherwise busy. Don't rely on this to always be fast.</p>
</li>
<li>
<p>Example response:</p>
<ul>
<li>
<pre>{
"normalised_url": "https://safebooru.org/index.php?id=2753608&page=post&s=view"
"url_file_statuses": [
{
"status": 2
"hash": "20e9002824e5e7ffc240b91b6e4a6af552b3143993c1778fd523c30d9fdde02c",
"note": "url recognised: Imported at 2015/10/18 10:58:01, which was 3 years 4 months ago (before this check)."
}
]
}</pre>
</li>
</ul>
<p>The 'url_file_statuses' is a list of zero-to-n JSON Objects, each representing a file match the client found in its database for the URL. Typically, it will be of length 0 (for as-yet-unvisited URLs or Gallery/Watchable URLs that are not attached to files) or 1, but sometimes multiple files are given the same URL (sometimes by mistaken misattribution, sometimes by design, such as pixiv manga pages). Handling n files per URL is a pain but an unavoidable issue you should account for.</p>
<p>'status' is the same as for /add_files/add_file:</p>
<ul>
<li>0 - File not in database, ready for import (you will only see this very rarely--usually in this case you will just get no matches)</li>
<li>2 - File already in database</li>
<li>3 - File previously deleted</li>
</ul>
<p>'hash' is the file's SHA256 hash in hexadecimal, and 'note' is some occasional additional human-readable text you may recognise from hydrus's normal import workflow.</p>
</li>
</ul>
</div>
2019-02-27 23:03:30 +00:00
<div class="apiborder" id="add_urls_get_url_info">
2019-02-06 22:41:35 +00:00
<h3><b>GET /add_urls/get_url_info</b></h3>
<p><i>Ask the client for information about a URL.</i></p>
<ul>
<li>
<p>Headers:</p>
<ul>
<li>Hydrus-Client-API-Access-Key : (Your hexadecimal access key)</li>
</ul>
</li>
<li>
<p>Arguments:</p>
<ul>
<li>url : (the url you want to ask about)</li>
</ul>
</li>
<li>
<p>Example request (for URL https://8ch.net/tv/res/1846574.html):</p>
<ul>
<li><p>/add_urls/get_url_info?url=https%3A%2F%2F8ch.net%2Ftv%2Fres%2F1846574.html</p></li>
</ul>
</li>
<li>
<p>Response description: Some JSON describing what the client thinks of the URL.</p>
2019-02-13 22:26:43 +00:00
</li>
<li>
<p>Example response:</p>
<ul>
<li>
<pre>{
"normalised_url": "https://8ch.net/tv/res/1846574.html",
"url_type": 4,
"url_type_string": "watchable url",
"match_name": "8chan thread",
"can_parse": true,
}</pre>
</li>
</ul>
2019-02-06 22:41:35 +00:00
<p>The url types are currently:</p>
<ul>
<li>0 - Post URL</li>
<li>2 - File URL</li>
<li>3 - Gallery URL</li>
<li>4 - Watchable URL</li>
<li>5 - Unknown URL (i.e. no matching URL Class)</li>
</ul>
2019-02-13 22:26:43 +00:00
<p>'Unknown' URLs are treated in the client as direct File URLs. Even though the 'File URL' type is available, most file urls do not have a URL Class, so they will appear as Unknown. Adding them to the client will pass them to the URL Downloader as a raw file for download and import.</p>
2019-02-06 22:41:35 +00:00
</li>
</ul>
</div>
2019-02-27 23:03:30 +00:00
<div class="apiborder" id="add_urls_add_url">
2019-02-06 22:41:35 +00:00
<h3><b>POST /add_urls/add_url</b></h3>
<p><i>Tell the client to 'import' a URL. This triggers the exact same routine as drag-and-dropping a text URL onto the main client window.</i></p>
<ul>
<li>
<p>Headers:</p>
<ul>
<li>Hydrus-Client-API-Access-Key : (Your hexadecimal access key)</li>
<li>Content-Type : application/json</li>
</ul>
</li>
<li>
<p>Arguments (in JSON):</p>
<ul>
<li>url : (the url you want to add)</li>
2019-02-27 23:03:30 +00:00
<li>destination_page_name : (optional page name to receive the url)</li>
<li>service_names_to_tags : (optional tags to give to any files imported from this url)</li>
2019-02-06 22:41:35 +00:00
</ul>
</li>
2019-02-27 23:03:30 +00:00
<p>If you specify a destination_page_name and an appropriate importer page already exists with that name, that page will be used. Otherwise, a new page with that name will be recreated (and used by subsequent calls with that name). Make sure it that page name is unique (e.g. '/b/ threads', not 'watcher') in your client, or it may not be found.</p>
<p>The service_names_to_tags uses the same system as for /add_tags/add_tags. You will need 'add tags' permission, or this will 403.</p>
2019-02-06 22:41:35 +00:00
<li>
<p>Example request body:</p>
<ul>
2019-02-27 23:03:30 +00:00
<li>
<pre>{
"url": "https://8ch.net/tv/res/1846574.html",
"destination_page_name": "kino zone",
"service_names_to_tags": {
"local tags" : [ "as seen on /tv/" ]
}
}</pre>
</li>
2019-02-06 22:41:35 +00:00
</ul>
</li>
2019-02-13 22:26:43 +00:00
<li><p>Response description: Some JSON with info on the URL added.</p></li>
<li>
<p>Example response:</p>
<ul>
<li>
<pre>{
"human_result_text": "\"https://8ch.net/tv/res/1846574.html\" URL added successfully.",
"normalised_url": "https://8ch.net/tv/res/1846574.html"
}</pre>
</li>
</ul>
</li>
2019-02-06 22:41:35 +00:00
</ul>
</div>
2019-02-27 23:03:30 +00:00
<div class="apiborder" id="add_urls_associate_url">
2019-02-13 22:26:43 +00:00
<h3><b>POST /add_urls/associate_url</b></h3>
2019-02-27 23:03:30 +00:00
<p><i>Manage which URLs the client considers to be associated with which files.</i></p>
<ul>
<li>
<p>Headers:</p>
<ul>
<li>Hydrus-Client-API-Access-Key : (Your hexadecimal access key)</li>
<li>Content-Type : application/json</li>
</ul>
</li>
<li>
<p>Arguments (in JSON):</p>
<ul>
<li>url_to_add : (an url you want to associate with the file(s))</li>
<li>urls_to_add : (a list of urls you want to associate with the file(s))</li>
<li>url_to_delete : (an url you want to disassociate from the file(s))</li>
<li>urls_to_delete : (a list of urls you want to disassociate from the file(s))</li>
<li>hash : (an SHA256 hash for a file in 64 characters of hexadecimal)</li>
<li>hashes : (a list of SHA256 hashes)</li>
</ul>
</li>
<p>All of these are optional, but you obviously need to have at least one of 'url' arguments and one of the 'hash' arguments. Unless you really know what you are doing with URL Classes, I strongly recommend you stick to associating URLs with just one single 'hash' at a time. Multiple hashes pointing to the same URL is unusual and frequently unhelpful.</p>
<li>
<p>Example request body:</p>
<ul>
<li>
<pre>{
"url_to_add": "https://rule34.xxx/index.php?id=2588418&page=post&s=view",
"hash": "3b820114f658d768550e4e3d4f1dced3ff8db77443472b5ad93700647ad2d3ba"
}
}</pre>
</li>
</ul>
</li>
<li><p>Response description: 200 with no content. Like when adding tags, this is safely idempotent--do not worry about re-adding URLs associations that already exist or accidentally trying to delete ones that don't.</p></li>
</ul>
2019-02-13 22:26:43 +00:00
</div>
2019-02-06 22:41:35 +00:00
<h3>Searching Files</h3>
<div class="apiborder">
<h3><b>GET file search</b></h3>
</div>
<div class="apiborder">
<h3><b>GET file metadata</b></h3>
</div>
<div class="apiborder">
<h3><b>GET file</b></h3>
</div>
<div class="apiborder">
<h3><b>GET thumbnail</b></h3>
</div>
</div>
</body>
</html>