Sources
Introduction¶
If your site is not based on Danbooru, Gelbooru, Shimmie, or another already-included source file, it gets more complicated to add it.
Warning
You must have knowledge of JavaScript to make your own JavaScript source.
Note
All examples below are using TypeScript.
Note
All types described in here are documented in depth in types.d.ts. Make sure to check it out if you're confused about the usage of a given type.
This page is more about providing actual examples and explaining the flow of creating a source in a more "natural" way, rather than being an exhaustive documentation on types.
To have a tutorial following the step-by-step creation of a real source as an example, see Source example.
Structure¶
Sources can be found in your settings folder. On Windows, by default, it is C:\Users\%USERNAME%\AppData\Local\Bionus\Grabber\sites
.
A source is defined by a folder containing three files:
icon.png
: a PNG icon, usually the favicon of the source (recommended size: 16x16, it will be resized if larger)model.js
: the JS script that decides which URLs to load and how to parse the results into images (usually compiled from amodel.ts
TypeScript file)supported.txt
: the list of supported sites based on this source, separated by a new linesites.txt
: the list of default sites to add when installing this source, separated by a new line. This file can be ignored and will be created when adding a new site using this source in Grabber
Utils¶
The JS environment used by Grabber is not fully fledged. Therefore, there is a helper to help do a few things that are not easily possible otherwise: JavaScript model helper.
Also, note that you can use the console
commands as in JavaScript to generate logs in Grabber's console. Supported methods:
console.debug
(debug level, not shown by default)console.info
(info level)console.log
(info level)console.warn
(warning level)console.error
(error level)
Basics¶
A basic source file simply exports a source
object, defined by the ISource
type. It must have a name and at least one API. All other fields are optional.
Example
export const source: ISource = {
name: "New source",
apis: {
api_id: api,
},
};
API¶
A source can have one or more APIs, defined by the IApi
type. It must have a name, an auth
array (which can be empty), and the search
endpoint description.
Most sources have only one API. Examples are API types are "JSON", "XML", "RSS", or even "HTML". HTML is harder to parse and prone to breaking, but it's sometimes the only option for sources that don't provide a public API.
Example
const api = {
name: "JSON", // The name of the API
auth: [], // The ID of the auth required to use this API, multiple values means OR
search: {
url: search_url_function,
parse: parse_url_function,
},
}
Search "url" function¶
The goal of this function is to return the URL that lists the images for a given search on that source.
The main parameter, query
, contains a search
string containing the user's input, as well as a page
number containing the page number the user wants to see.
From this, the function must return a string representing the URL to load. Note that you shouldn't include the base URL / domain in that link. It's recommended to use an absolute path instead.
Example
function(query) {
return "/posts.json?page=" + query.page + "&tags=" + encodeURIComponent(query.search);
}
Search "parse" function¶
Parameters:
- src (
string
)
Returns: { images: {}[], tags?: { id?: number, name: string, count?: number, type?: string, typeId?: number }[], error?: string }
Tags "url" function¶
Parameters:
- query (
{ search: string, page: number }
) - opts (
{ limit: number, auth: {} }
)
Returns: (either)
string
: an URL{ url: string, headers?: { [key: string]: string }
: a URL and headers{ error?: string }
: an error
Description¶
Builds a tag listing API url from a search query.
Example¶
function(query, opts) {
return "/tags.json?limit=" + opts.limit + "&page=" + query.page;
}
Tags "parse" function¶
Parameters:
- src (
string
)
Returns: { tags?: { id?: number, name: string, count?: number, type?: string, typeId?: number }[], error?: string }
Auth¶
URL auth¶
The credentials are passed directly in the URL of each request.
Example¶
{
type: "url",
fields: [
{
key: "login",
type: "username",
},
{
key: "password_hash",
type: "hash",
hash: "sha1",
salt: "choujin-steiner--%value%--",
},
],
}
GET and POST auth¶
The credentials are sent to a given URL on the website to login before doing any request.
Example¶
{
type: "post", // Either "get" or "post"
url: "/session",
fields: [
{
key: "name",
type: "username",
},
{
key: "password",
type: "password",
},
],
check: {
type: "cookie",
key: "password_hash",
},
}
OAuth 2 auth¶
Example¶
{
type: "oauth2",
authType: "password", // Either "password", "client_credentials", or "header_basic"
tokenUrl: "/auth/token",
requestUrl: "/auth/request", // Optional
refreshTokenUrl: "/auth/refresh", // Optional
scope: ["user"], // Optional
}
Tag format¶
A tag format is defined by two fields:
case
: the word casing:lower
: some tagupper_first
: Some tagupper
: Some Tagcaps
: SOME TAG
wordSeparator
: the separator to add between each word
Example¶
{
case: "lower",
wordSeparator: "_",
}
Search format¶
A search format must define at least a and
operator. An operator is either:
- A string such as
&&
- An object of type
{ separator: string, prefix?: string }
, where the separator is what should be added between both operands, and the prefix what should be added before each operand
If the search also support the OR operator, you must then define or
, parenthesis
, and precedence
:
or
: same asand
, either a string or an objectparenthesis
: a boolean to say whether this source supports parenthesisprecedence
: which operator has precedence over the other, eitheror
orand
Example¶
{
and: " ",
or: {
separator: " ",
prefix: "~",
},
parenthesis: false,
precedence: "or",
}
(A | B) & C
into the text "~A ~B C".