-
Notifications
You must be signed in to change notification settings - Fork 0
Providers & Plugins
Note: Data here only applies to v3.0.0. Plugins are not supported on previous versions of aphrodite.
This application supports plugins for other boorus hosted with DanBooru or Philomena. This page should give a basic rundown on developing a plugin. The system is designed to make the program do all of the work to make developing providers quick and easy, not to say it requires no knowledge -- you should still know the basics.
While plugin support is very initial, it may change per release. If any changes to the provider interfaces occur, the creator of the provider should be responsible for updating the provider.
Providers also have the option to create their own userscript for the booru of their choice. All arguments outlined in the arguments page will apply.
All providers are required to have a valid GUID associated with it, and that it is a unique GUID. GUIDs are used to identify providers, and if the GUID is invalid or not present, the provider will not be loaded.
The following GUIDs are not allowed to be used:
| GUID | Reason, optional other remarks |
|---|---|
0fb5a737-ea09-4615-8048-0dc2bacede18 |
aphrodites GUID. It will reference the internal e621 provider. |
00000000-0000-0000-0000-000000000000 |
The default GUID. Defers to the default provider selected by the user. |
00000000-0000-0000-0000-000000000001 |
The internal InkBunny GUID. |
00000000-0000-0000-0000-000000000002 |
The internal Pixiv GUID. |
Although the internal e621 providers can be used as a reference for what you should do, do NOT use it as a copy/paste for your own provider. Each booru may be unique or require different things.
I tried to make developing a provider as easy as possible, and hopefully it's as simple as possible.
Aphrodite is built on C# 11 and .NET Framework 4.7.2. It's recommended to use Visual Studio 2022 17.4, a higher version, or any IDE that supports C# 11 and .NET Framework 4.7.2 to build for the compiler flags and runtime additions to work properly. All in all, that will be all that is required to develop a provider. To debug your provider, you can use the debug configuration of aphrodite.
Currently, json.net is used for serializing and deserializing. Your classes may use DataContract and DataMember attributes instead of json.net specific attributes, but you may reference json.net if you wish to use json.net specific attributes. In addition to JSON-based attributes, you will need to specify attributes for Pool and Post derived classes used by the parse and the provider system.
Most objects you use may support pre-serializing and post-deserialized methods.
| Abstract class | Supported methods |
|---|---|
Post |
PostDeserialized(), PostSerializing()
|
Pool |
PoolDeserialized(), PoolSeriaizling()
|
PostParent, PoolParent
|
ParentDeserialized() |
Post objects have additional and HIGHLY recommended overrides you should take advantage of:
OVERRIDE_EQUALS_AND_GETHASHCODE_METHOD_FOR_MOST_COMPATIBILITY() is an abstract void that does nothing internally but warns the developer that Equals(object) and GetHashCode() methods should be overridden for highest compatibility with the program.
Equals(object) |
You should check if the object is your Post object and that the PostProperty.PostId is equal-to the current posts' PostId. |
GetHashCode() |
You should return the PostId of the current post as a hashcode. A simple (int)PostId cast is sufficient enough. |
Your provider class must include this attribute for it to load. It lets you define specific values in regards to the API.
| Constructor | Required | Remarks |
|---|---|---|
ApiFormat Value
|
Yes | The format of the API. It can be either ApiFormat.JSON or ApiFormat.XML. |
Type PostType
|
Conditional | The typeof the class that inherits aphrodite.Post which contains API data tied to your booru. Only required if you do not have a generic IProvider. |
Type PostParentType
|
Conditional | The typeof the class that inherits aphrodite.PostParent which contains a property pointing to an instance of the PostType. Only required if you do not have a generic IProvider. |
It includes the following optional parameters:
| Parameter | Description |
|---|---|
ApiHashType HashType
|
The type of hash used by the provider, which may be used to scan files after download. (May not be used) |
int StartingPageIndex
|
The page index number that the first page of your booru starts with. It can be 0, 1, or a number affected by PageIndexOffset. |
int PageIndexOffset
|
The offset for the page numbers. For most boorus, this value is 1, but for boorus that have a weird way of using pages, this will alleviate those troubles. |
int PostsPerPage
|
The amount of posts that are on each page. This value helps determine how many posts are expected per page so the parser knows when to stop parsing. This value is set to 50 by default, but you will need to set a proper value. |
bool AllowPreQueueDownloads
|
Whether the pre-queue downloads setting is allowed to be used with your booru. Some boorus may close connections that do not get used for a period of time. This is set to false by default, and the value is not respected if the user does not enable pre-queue downloads. |
string? DateTimeFormat
|
The Date/Time format used by the booru. You can leave it as null to allow json.net to handle any DateTime(Offset) values. |
The PostPropertyAttribute is used to find Properties within your Post class. This attribute is first-come first-serve, whichever property that has a PostProperty first will be the property that is for that value. There are some require properties for this attribute or the provider will not function. Any value marked with a ! is required, any value marked with ? is a conditional requirement.
| Value | Type | Required | Description |
|---|---|---|---|
ArtistTagsArray |
string[] |
No | Contains string-values of artist(s) for that post. |
Author |
string |
No | The ID or Username of the person who uploaded the post. |
FavoriteCount |
int |
No | The amount of favorites on the post. |
FileExtension |
string |
Yes | The extension of the file. This will be trimmed before being used. |
FileHash |
string |
No | The hash of the file, MD5, SHA1, etc... |
FileSize |
long |
No | The size of the file (in bytes). If your booru does not support it, you can just return 0. |
FileUrl |
string |
Conditional | The URL to download the file. This is required if CanBeDownloaded is true. |
PostId |
uint |
Yes | The ID of the post. |
Rating |
string |
Yes | The rating of the post. This should follow suit for the booru provided. DanBooru providers return "e" or "explicit", "q" or "questionable", and "s" or "safe". Philomena providers return "e" or "explicit", "m" or "mature", "q" or "questionable", "su" or "suggestive", and "s" or "safe". Any booru that breaks tradition must be handled in it's own provider class to correct the changes. |
Score |
int |
No | The total score for the post. |
ScoreUp |
int |
No | The total positive score for the post. |
ScoreDown |
int |
No | The total negative score for the post. |
UpdateTime |
object (DateTime[Offset] recommended) |
No | The last update time for the post. This is used for updating post information locally. If this value does not exist, the information will always be updated. |
AllTagsArray |
string[] |
Conditional, highly recommended | All of the tags for the post. This is required for PostScanner providers, and is optional for other providers, but it is HIGHLY recommended to have. |
CanBeDownloaded |
bool |
Yes | Whether a post is downloadable or not. If a booru has a deleted flag or similar, you may point to that -- but if a booru "fake" deletes (marks as deleted but the file is still accessible), then you may choose to circumvent the flag. |
Post |
aphrodite.Post or aphrodite.Post[]
|
Conditional | The post object or array within a post parent object. See #PostParent for information on when to use this. |
This object can be used for ITagProvider, IPoolProvider, and IImageProvider` as your provider is expected to only provider service to one booru.
IPoolProvider classes require a class-specific attribute PoolFormatAttribute which will determine if the pool requires multiple API downloads to parse.
| Constructor | Required | Remarks |
|---|---|---|
PoolFormat Value
|
Yes | What format the pool is designated as, see the next list for values. |
Type PoolType
|
Conditional | The typeof the class that inherits aphrodite.Pool which contains API data tied to your booru. Only required if you do not have a generic IProvider. |
Type PoolParentType
|
Conditional | The typeof the class that inherits aphrodite.PoolParent which contains a property pointing to an instance of the PoolType. Only required if you do not have a generic IProvider. |
| PoolFormat value | Explanation |
|---|---|
PoolFormat.SingleParse |
The pool has all required post data within the pool API data. |
PoolFormat.MultiParse |
The pool needs to download more API pages to parse the posts within the pool. |
The PoolPropertyAttribute is for Properties in the Pool class, akin to the PostPropertyAttribute.
| Value | Type | Required | Description |
|---|---|---|---|
Name |
string |
Yes | The string name of the pool. |
Posts |
aphrodite.Post[] |
Conditional | The Post[] of all the posts within the pool. Required if PoolFormatAttribute.Value is set to PoolFormat.SingleParse. |
Deleted |
bool |
Yes | Whether the pool was deleted. Some boorus may delete pools but not the files, so this should be used per-booru. Do your research. |
OrderedPostIds |
uint[] |
Yes | The post IDs in chronological order. If your booru does not have this, then Posts may already be ordered, in which case, just create a uint[] when the post is deserialized. |
PageCount |
int |
Yes | The amount of posts within the pool, in total. If this is wrong, it may affect PoolFormat.MultiParse boorus. |
| `UpdateTime |
object (DateTime[Offset] recommended) |
No | An object that represents the last update time for the pool. This is used for updating pool information locally. If this value does not exist, the information will always be updated. |
Some boorus may have a "special" way of returning API data, in which it gives you an object of an array of posts instead of just an array of posts. This is annoying but easily handled.
Let's say, for example, your booru API returns like this:
{
"post(s)": [
...
]
}You would have to implement a class that can handle that object itself, since it's the object that holds that value. If the posts are within a sub-object (or sub-sub object, or even more layered), you can add a getter property for the nested post object or array, since the attribute only scans the object itself and not sub-objects.
Your post root class would need to inherit the PostParent class for it to catch on properly, and then implement a Post array or object property. For example:
public sealed class BooruPostData : PostParent {
[PostProperty(PostProperty.Post)]
public Post[] PostData { get; }
}But, if for some ungodly reason it's even farther nested like this:
{
"data": {
"post(s)": {
...
}
}
}You can have the parent class return the sub-objects array, and it can be as deep as required as long as the root parent has the array to return.
public sealed class BooruPostData : PostParent {
public SubObject Data { get; }
[PostProperty(PostProperty.Post)]
public Post[] Posts => Data.PostData;
}
public sealed class SubObject {
public Post[] PostData { get; }
}PostPropertyAttribute and PoolPropertyAttribute both support Parent values in the case either of them need it.
The default provider interface. It is not used generally for much, but every provider (aside from ICustomProvider) implement this interface.
| Property signature | Description |
|---|---|
string Name |
The name of the provider. This will appear in the log and the drop-down buttons on the main form. |
string SiteAccessName |
The short and sweet URL to access the booru. An example would be e621.net. There is no https or subdomains, just the sub domain (if required), domain name, and TLD. |
System.Drawing.Image Icon |
The System.Drawing.Image object to represent the booru. This can be the favicon. If this value is NULL, it will use a grayed-out application icon. |
| Method signature | Description |
|---|---|
void GenerateDownloadClientData(HttpClientHeaders) |
Occurs when the provider is created on startup. This will generate the base request the downloader will use when downloading data from the booru. |
void Dispose |
Occurs when the provider gets reloaded when the library file gets replaced while the application is running. You should dispose of anything your provider may use, other than the Icon property which will be disposed of by the application. |
The provider that is used for downloading files using tags.
ITagProvider isn't used as the main provider interface, instead there are sub-providers to differentiate them and pass them to their proper provider. Currently supported sub-providers are IDanBooruTagProvider and IPhilomenaTagProvider. No unique methods are used for them since they're both the same, just identified differently.
When selecting an IDanBooruTagProvider or IPhilomenaTagProvider, you'll notice some extra interfaces you can select: IDanBooruTagProvider<TPost>, IDanBooruTagProvider<TPost, TParent> (and the same for IPhilomenaTagProvider). These are generic types that are used as a cleaner way of identifying Post-derived and PostParent-derived objects within your provider.
-
TPostgeneric type must inheritaphrodite.Post. -
TParentgeneric type must inheritaphrodite.PostParent.
-
string FolderName
The name of the output folder that the downloader will save the files to. I usually use acronyms for boorus that have words, likefurbooruwould becomefb, but you can choose whatever. -
string BaseApiUrl
The base URL that will be used to connect to the API, with format parameters following-
{0}must be the tags. -
{1}must be the page number. -
{2}must be the max amount of posts displayed per-page.
-
-
string BaseFrontendUrl
The base URL that will be used to connect to the frontend of the booru, with the format parameters followed-
{0}must be the tags. -
{1}must be the page number.
-
-
string BaseTagsPageApiUrl
The base url for the API page for a page that the user usually sees. This should not have a changed posts-per-page query string. The following format parameters are required:-
{0}-> The requested page number. -
{1}-> The tags that are included with the page.
-
-
string BasePageApiUrl
The This is the same as above, but it does not include the tags format parameter. The flag for the downloader to display a total download size, if the API contains a value for the file size for each file. -
bool SupportsPageDownload
Whether the provider supports downloading single pages from the API. In general, mosttagproviders do have support for this, but the program does extra logic for page downloads to ensure it's successful.
-
bool ValidPageLink(string)
Returnstrueif the inputstringis a valid page URL for the provider; otherwise,false. This is used for page downloading. -
bool ValidPageWithTagsLink(string)
Returnstrueif the inputstringis a valid page URL that contains tags; otherwise,false. This is used for extracting tags from page urls. -
string GetTags(UrlData)
Returns the tags extracted from the input UrlData. This will only be called ifValidPageLinkWithTags(string)istrue, so you can expect theUrlDatato contain the broken down url (see #UrlData) -
int GetPageNumber(UrlData)
Returns the current page number extracted from the input string. It should be whatever the URL has, and it must align withPageIndexOffsetsince the program will mathematically work on the value returned. -
void BuildTags(string, out string, out string)
Allows the provider to manually format the tags forUrlTagsandIdentifier. Since boorus often differ, it's done this way so no variances will need to be accounted for. You may also use this as a way to 'serialize' your data, if searching can be varied. The inputstringwill be saved and sent to the provider on re-downloads.
The provider that is used for downloading pools from boorus.
IPoolProvider isn't used as the main provider interface, instead there are sub-providers to differentiate them and pass them to their proper provider. Currently supported sub-providers are IDanBooruPoolProvider and IPhilomenaPoolProvider. No unique methods are currently used.
When selecting an IDanBooruPoolProvider or IPhilomenaPoolProvider, you'll notice some extra interfaces you can select: IDanBooruPoolProvider<TPool, TPost>, IDanBooruPoolProvider<TPool, TPost, TParent>, IDanBooruPoolProviderP<TPool, TPoolParent, TPost>, IDanBooruPoolProvider<TPool, TPoolParent, TPost, TPostParent> (and the same for IPhilomenaPoolProvider). These are generic types that are used as a cleaner way of identifying Post-derived and PostParent-derived objects within your provider.
-
TPoolgeneric type must inheritaphrodite.Pool. -
TPoolParentgeneric type must inheritaphrodite.PoolParent. -
TPostgeneric type must inheritaphrodite.Post. -
TParentgeneric type must inheritaphrodite.PostParent.
IPoolProviderP<TPool, TPoolParent, TPost> is specifically named that way as a means for the pool to have a parent object, but the posts do not. There's no other way to handle this.
-
string FolderName
The name of the output folder that the downloader will save the files to. I usually use acronyms for boorus that have words, likefurbooruwould becomefb, but you can choose whatever. -
string BaseApiUrl
The base URL that will be used to connect to the API to get the initial pool information, with format parameters following-
{0}must be the pool id.
-
-
string BaseFrontendUrl
The base URL that will be used to connect to the frontend of the booru, with the format parameters followed-
{0}must be the pool id.
-
-
string BasePoolSearchApiUrl
The base URL for Multi-Parse pools that will download additional information from APIs, like the tag downloader. This 3 format parameters:-
{0}must be the pool id search value (ie:pool:222). -
{1}must be the page number. -
{2}must be the max amount of posts displayed per-page. If your provider does not require Multi-Parsing then this property will not be accessed.
-
-
bool ValidId(string)
Returnstrueif the inputstringis a valid pool ID for the provider; otherwise,false. -
bool ValidPoolLink(string)
Returnstrueif the inputstringis a valid pool URL for the provider; otherwise,false. -
string GetPoolId(UrlData)
Returns the pool id that is extracted from the pool url in thestringparameter. This will only be called ifValidPoolLink(string)istrue, so you can expect theUrlDatato contain the broken down url (see #UrlData)
The provider for downloading single images. This is a very simple provider and is 100% ambiguous when it comes to data. All of it is basically handled by the provider, which means any site is technically supported, if implemented properly.
When selecting IImageProvider, you'll notice some extra interfaces you can select: IImageProvider<TPost>, IImageProvider<TPost, TParent>. These are generic types that are used as a cleaner way of identifying Post-derived and PostParent-derived objects within your provider.
Obviously, The TPost generic type must inherit aphrodite.Post, and the TParent generic type must inherit aphrodite.PostParent.
-
string FolderName
The name of the output folder that the downloader will save the files to. I usually use acronyms for boorus that have words, likefurbooruwould becomefb, but you can choose whatever. -
string BaseApiUrl
The base URL that will be used to connect to the API, with format parameters following-
{0}must be the post id.
-
-
string BaseFrontendUrl
The base URL that will be used to connect to the frontend of the booru, with the format parameters followed-
{0}must be the post id.
-
-
bool ValidId(string)
Returnstrueif the inputstringvalue is a valid post ID for the provider; otherwise,false. -
bool ValidImageLink(string)
Returnstrueif the inputstringvalue is a valid post link for the provider; otherwise,false. -
string GetImageId(UrlData)
Returns the image ID that gets extracted from the inputstringvalue. This will only be called ifValidImageLink(string)istrue, so you can expect theUrlDatato contain the broken down url (see #UrlData)
This provider was created for a simple way to check individual posts that may have been filtered that the user wishes to NOT have lost. It doesn't overwrite the tag filters and it doesn't download the images, only the API data. While it requires the PostApiValue.AllTagsArray to be defined, it also may include support for post comments in the future.
This may be unused in the future, if IImageProvider is chosen over IPostScannerProvider objects.
-
string BaseApiUrl
The base URL that will be used to connect to the API, with format parameters following-
{0}must be the post id.
-
-
string BaseFrontendUrl
The base URL that will be used to connect to the frontend of the booru, with the format parameters followed-
{0}must be the post id.
-
-
string BaseFrontendTagSearchUrl
The base URL that will be used to connect to a tag search for the booru, with the format parameters followed-
{0}must be the tag selected by the user.
-
(For any comment values, you can ignore them as they are in indefinitely not supported until a time comes where I feel like implementing it.)
-
bool ValidId(string)
Returnstrueif the inputstringvalue is a valid post ID for the provider; otherwise,false. -
bool ValidPostLink(string)
Returnstrueif the inputstringvalue is a valid post link for the provider; otherwise,false. -
string GetPostId(UrlData)
Returns the image ID that gets extracted from the inputstringvalue. This will only be called ifValidImageLink(string)istrue, so you can expect theUrlDatato contain the broken down url (see #UrlData)
This will help debug your provider by offering a few tools that may be used during downloads. It also optionally allows your provider to run its own function to help you with debugging. Any debugging providers will load during startup.
Release builds will not load any debugger providers.
Custom providers are providers that do their own thing.
-
string Name
The name of the custom provider. This will allow your provider to be identified easily. -
Image Icon
TheSystem.Drawing.Imageobject to represent your provider. This can be the favicon. If this value is NULL, it will use a grayed-out application icon. -
ISubCustomProvider[]? SubProviders
An array ofISubCustomProviderobjects that your provider additionally supports. See below forISubCustomProviderinformation. -
bool IncludeWithSubProviders
Whether theICustomProviderinstance is to be included with theSubProviderswhere accessible. This can befalseif theICustomProviderinstance does not do anything.
-
void DisplayProvider()
Runs the custom provider, such as open a form or run another program.
This is sub custom provider that the ICustomProvider can handle, if you desire. It's basically the same as ICustomProvider, but the only available properties and methods are string Name, System.Drawing.Image Icon, and void DisplaySubProvider().
When using a custom provider, you have access to a few helpful tools aphrodite provides:
This will give you a few options for sending notifications to the user. These notifications always appear on the bottom-right of the users' primary screen and are logged when sent to the user. Notifications should only be displayed for when actions start, error, or finish, and should not be used frequently. You can also send an image along to be displayed in a 32x32 picture box, if you desire to show the image of your provider. The header can be customized, but it's best to leave it alone. It has the following methods available:
void ShowNotification(string)void ShowNotification(string, string)void ShowNotification(string, Image?)void ShowNotification(string, string, image?)
This is a IDisposable class that allows you to access the HttpClient that aphrodite uses, with proxy, throttling, and other tooling that aphrodite uses. Please ALWAYS dispose of the aphrodite.HttpClient when you are not using it (opposed to System.Net.Http.HttpClient; I know, confusing because System.Net.Http.HttpClient should live as long as the application, but HttpClient can't make major changes without it being re-created. And also, it allows downloads that requires the HttpClient to remain alive until unneeded. I actually prefer it this way.), as not disposing it will not properly destroy the handle to the internal HttpClient making it live indefinitely.
When using a user-agent, you can set your own (if your provider needs to spoof user-agents), but by default uses aphrodite-custom-provider/{Version} (CLR Version).
It's NOT a complete drop-in replacement to System.Net.Http.HttpClient, but it does make doing certain things easier. It has the following methods available:
Task<string> DownloadStringAsnyc(string/Uri/HttpRequestMessage/HttpResponseMessage, CancellationToken)Task DownloadFileAsync(string/Uri/HttpRequestMessage/HttpResponseMessage, string/FileInfo, CancellationToken)Task<byte[]> DownloadDataAsync(string/Uri/HttpRequestMessage/HttpResponseMessage, CancellationToken)Task<System.Drawing.Image> DownloadImageAsync(string/Uri/HttpRequestMessage/HttpResponseMessage, CancellationToken)Task<HttpResponseMessage> SendAsync(HttpRequestMessage, [HttpCompletionOption], [CancellationToken])void LaunchUrl(string)void LaunchUri(Uri)
It also includes a couple events:
DownloadProgressChangedDownloadFinished
The events are tailored specifically to WinForms, so DownloadProgressChanged won't absolutely destroy the UI thread when called, but it will stress it a little bit.
This is a form that allows the user to modify the cookies your provider may require. A lot of sites require some cookies for authentication, or for bypassing cloudflare (if the network connection through aphrodite is the same for your browser, ie proxy, ip, etc). The form is very basic, with simple editing for cookies.
You have 2 ctor methods of using the form; frmCookies(System.Drawing.Image) and frmCookies(System.Drawing.Image, System.Net.Cookie[]). The first one requires just an image to display on the provider box. The second one requires the image as well as an array of cookies to present to the user, either saved or as a placeholder. The user will require the name, value, and domain values to be written.
This will allow you to access the aphrodite.ini file associated with aphrodite.
If a section is null, empty, whitespace, or used internally; it will throw a ProviderException. You should only have 1 section for your provider, preferably the name of your provider.
The following methods are available to the developer:
-
string? ReadKey(string Key, string Section)-> Reads a key from a section in the ini. -
string WriteKey(string Key, string Value, string Section)-> Writes a key/value to a section in the ini. It returns what is written to the ini. -
void DeleteKey(string Key, string Section)-> Deletes a key from a section in the ini. -
IEnumerable<KeyValuePair<string, string>> ReadSection(string)-> Reads a section from the ini. - void DeleteSection(string)` -> Deletes a section from the ini.
There's not much else to it. Very simple.
aphrodite has a special class to convert a url string into a readable object for methods that require it.
The UrlData objects passed to providers allow you to see urls in a simple manor. BasUri is the uri sent to the UrlData class if you want full granular control of the uri. Scheme is the scheme used by the uri (such as http://). SubDomain is the subdomain of the url. Host is the main host (such as google.com). Paths is an array of UrlPath objects that contain data relating to the path. LastPath is the last path of the url, most likely the thing most boorus are looking for.
UrlPath contains path-specific values. Path is the name (so, "example.com/path1", path1 would be the name of the path. Subsequent paths contain their own UrlPath objects). Fragment is a value that appears after a # character, most providers may not require that value. QueryStrings is where most of your information may lie; they are the values that appear after ? and & charachters ("&value=123" would make a query string keyvaluepair Value, 123).
UrlPath also contains some help methods:
-
bool TryFindQuery(string, out KeyValuePair<string, string>, [StringComparison])-> Returnstrueif aKeyis found within theQueryStringsof the path.out queryis the key/value pair it found.compareris how the keys are compared. -
bool TryGetQuery(string, out string, [StringComparison])-> Returnstrueif aKeyis found within theQueryStringsof the path.out queryis the value of the query it found.compareris how the keys are compared. -
string GetQuery(string, [StringComparison])-> Returns the value of thekeywithin theQueryStrings.compareris how the keys are compared. If the key is not found, it will throw aKeyNotFoundException.
This is one of the powerful sides of aphrodite, allowing easy access to url data when the user sends it to aphrodite. It helps alleviate url decoding problems.
aphrodite will forward any arguments to your provider if the GUID is to the right of the argument id. Currently, tags, pages, pools, and image are supported for forwarding, while poolwishlist will continue to be handled by aphrodite.
When using arguments with providers, make sure users can access them by following the schema for the argument system: -<argument>:<your GUID> .... An example of this would e -tags:1234... "checkmark".
The pool wishlist is supported by using -poolwl:<your GUID> <pool url> [pool name]. The pool URL is required, while the pool name is optional. If no pool name is given, the name will be saved as empty pool name.
Finally, arguments with spaces should be "in double-quotes". If you require using double-quotes, you can \"escape\" them or use the internal double-quote marker {{%DQ%}}. If you require that marker for other purposes, it is up to you to work around it.
aphrodite will host the provider, if you wish to push it to the repo. However, issues opened regarding your provider will be marked as invalid. If you wish to handle issues, you can open your own repo and either open a new issue asking to be added to the wiki, or if it's supported, open a wiki edit pull request to add yours to the list.
No providers are available at this time.