booru 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/dist/Constants.d.ts +1 -0
- package/dist/Constants.d.ts.map +1 -1
- package/dist/Constants.js +11 -5
- package/dist/Constants.js.map +1 -1
- package/dist/Utils.d.ts +10 -2
- package/dist/Utils.d.ts.map +1 -1
- package/dist/Utils.js +38 -4
- package/dist/Utils.js.map +1 -1
- package/dist/boorus/Booru.d.ts +29 -0
- package/dist/boorus/Booru.d.ts.map +1 -1
- package/dist/boorus/Booru.js +84 -3
- package/dist/boorus/Booru.js.map +1 -1
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -2
- package/dist/index.js.map +1 -1
- package/dist/sites.json +24 -12
- package/dist/structures/SearchResults.d.ts.map +1 -1
- package/dist/structures/SearchResults.js.map +1 -1
- package/dist/structures/SiteApi.d.ts +2 -0
- package/dist/structures/SiteApi.d.ts.map +1 -1
- package/dist/structures/SiteApi.js.map +1 -1
- package/dist/structures/Tag.d.ts +42 -0
- package/dist/structures/Tag.d.ts.map +1 -0
- package/dist/structures/Tag.js +52 -0
- package/dist/structures/Tag.js.map +1 -0
- package/dist/structures/TagListParameters.d.ts +14 -0
- package/dist/structures/TagListParameters.d.ts.map +1 -0
- package/dist/structures/TagListParameters.js +7 -0
- package/dist/structures/TagListParameters.js.map +1 -0
- package/dist/structures/TagListResults.d.ts +53 -0
- package/dist/structures/TagListResults.d.ts.map +1 -0
- package/dist/structures/TagListResults.js +73 -0
- package/dist/structures/TagListResults.js.map +1 -0
- package/package.json +14 -15
- package/readme.md +22 -5
package/LICENSE.md
CHANGED
package/dist/Constants.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ export declare const USER_AGENT: string;
|
|
|
36
36
|
* @param {BooryCredentials} [credentials] The credentials to use for the search, appended to the querystring
|
|
37
37
|
*/
|
|
38
38
|
export declare function searchURI(site: Site, tags?: string[], limit?: number, page?: number, credentials?: BooruCredentials): string;
|
|
39
|
+
export declare function tagListURI(site: Site, limit?: number, page?: number, credentials?: BooruCredentials): string;
|
|
39
40
|
/**
|
|
40
41
|
* The default options to use for requests
|
|
41
42
|
* <p>I could document this better but meh
|
package/dist/Constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Constants.d.ts","sourceRoot":"","sources":["../src/Constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"Constants.d.ts","sourceRoot":"","sources":["../src/Constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AACzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,KAAK,IAAI,MAAM,mBAAmB,CAAA;AACzC,OAAO,KAAK,QAAQ,MAAM,uBAAuB,CAAA;AAMjD,MAAM,MAAM,OAAO,GACf,UAAU,GACV,UAAU,GACV,cAAc,GACd,oBAAoB,GACpB,cAAc,GACd,cAAc,GACd,UAAU,GACV,cAAc,GACd,YAAY,GACZ,eAAe,GACf,UAAU,GACV,YAAY,GACZ,mBAAmB,GACnB,gBAAgB,GAChB,eAAe,CAAA;AAgBnB;;GAEG;AACH,eAAO,MAAM,KAAK,EAAe,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AAE1D;;;;GAIG;AACH,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM,GAAG,KAAK;CAWpC;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,QAAyE,CAAA;AAYhG;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,IAAI,EACV,IAAI,GAAE,MAAM,EAAO,EACnB,KAAK,SAAM,EACX,IAAI,SAAI,EACR,WAAW,GAAE,gBAAqB,GACjC,MAAM,CAcR;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,IAAI,EACV,KAAK,SAAM,EACX,IAAI,SAAI,EACR,WAAW,GAAE,gBAAqB,GACjC,MAAM,CAQR;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,WAK5B,CAAA"}
|
package/dist/Constants.js
CHANGED
|
@@ -3,14 +3,12 @@
|
|
|
3
3
|
* @packageDocumentation
|
|
4
4
|
* @module Constants
|
|
5
5
|
*/
|
|
6
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
-
};
|
|
9
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
7
|
exports.defaultOptions = exports.USER_AGENT = exports.BooruError = exports.sites = void 0;
|
|
11
8
|
exports.searchURI = searchURI;
|
|
9
|
+
exports.tagListURI = tagListURI;
|
|
12
10
|
const Utils_1 = require("./Utils");
|
|
13
|
-
const
|
|
11
|
+
const siteJson = require('./sites.json');
|
|
14
12
|
const packageJson = require('../package.json');
|
|
15
13
|
const expandedTags = {
|
|
16
14
|
'rating:e': 'rating:explicit',
|
|
@@ -20,7 +18,7 @@ const expandedTags = {
|
|
|
20
18
|
/**
|
|
21
19
|
* A map of site url/{@link SiteInfo}
|
|
22
20
|
*/
|
|
23
|
-
exports.sites =
|
|
21
|
+
exports.sites = siteJson;
|
|
24
22
|
/**
|
|
25
23
|
* Custom error type for when the boorus error or for user-side error, not my code (probably)
|
|
26
24
|
* <p>The name of the error is 'BooruError'
|
|
@@ -75,6 +73,14 @@ function searchURI(site, tags = [], limit = 100, page = 0, credentials = {}) {
|
|
|
75
73
|
});
|
|
76
74
|
return `http${site.insecure ? '' : 's'}://${site.domain}${site.api.search}${query}`;
|
|
77
75
|
}
|
|
76
|
+
function tagListURI(site, limit = 100, page = 0, credentials = {}) {
|
|
77
|
+
const query = (0, Utils_1.querystring)({
|
|
78
|
+
limit,
|
|
79
|
+
[site.paginate]: page,
|
|
80
|
+
...credentials,
|
|
81
|
+
});
|
|
82
|
+
return `http${site.insecure ? '' : 's'}://${site.domain}${site.api.tagList}${query}`;
|
|
83
|
+
}
|
|
78
84
|
/**
|
|
79
85
|
* The default options to use for requests
|
|
80
86
|
* <p>I could document this better but meh
|
package/dist/Constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Constants.js","sourceRoot":"","sources":["../src/Constants.ts"],"names":[],"mappings":";AAAA;;;GAGG
|
|
1
|
+
{"version":3,"file":"Constants.js","sourceRoot":"","sources":["../src/Constants.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AA6FH,8BAoBC;AAED,gCAaC;AA1HD,mCAAqC;AAErC,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;AACxC,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;AA2B9C,MAAM,YAAY,GAAY;IAC5B,UAAU,EAAE,iBAAiB;IAC7B,UAAU,EAAE,qBAAqB;IACjC,UAAU,EAAE,aAAa;CAC1B,CAAA;AAED;;GAEG;AACU,QAAA,KAAK,GAAG,QAAqC,CAAA;AAE1D;;;;GAIG;AACH,MAAa,UAAW,SAAQ,KAAK;IACnC,YAAY,OAAuB;QACjC,KAAK,CAAC,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;QAE3D,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;YAC7B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,YAAY,CAAA;QAC5C,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;QAC3C,CAAC;QAED,IAAI,CAAC,IAAI,GAAG,YAAY,CAAA;IAC1B,CAAC;CACF;AAZD,gCAYC;AAED;;;GAGG;AACU,QAAA,UAAU,GAAG,SAAS,WAAW,CAAC,OAAO,0CAA0C,CAAA;AAEhG;;;;;GAKG;AACH,SAAS,UAAU,CAAC,IAAc;IAChC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AAC5D,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,SAAS,CACvB,IAAU,EACV,OAAiB,EAAE,EACnB,KAAK,GAAG,GAAG,EACX,IAAI,GAAG,CAAC,EACR,cAAgC,EAAE;IAElC,MAAM,KAAK,GAAG,IAAA,mBAAW,EACvB;QACE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC;QACjC,KAAK;QACL,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI;QACrB,GAAG,WAAW;KACf,EACD;QACE,SAAS,EAAE,IAAI,CAAC,OAAO;KACxB,CACF,CAAA;IAED,OAAO,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,EAAE,CAAA;AACrF,CAAC;AAED,SAAgB,UAAU,CACxB,IAAU,EACV,KAAK,GAAG,GAAG,EACX,IAAI,GAAG,CAAC,EACR,cAAgC,EAAE;IAElC,MAAM,KAAK,GAAG,IAAA,mBAAW,EAAC;QACxB,KAAK;QACL,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI;QACrB,GAAG,WAAW;KACf,CAAC,CAAA;IAEF,OAAO,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,KAAK,EAAE,CAAA;AACtF,CAAC;AAED;;;;;GAKG;AACU,QAAA,cAAc,GAAgB;IACzC,OAAO,EAAE;QACP,MAAM,EAAE,oDAAoD;QAC5D,YAAY,EAAE,kBAAU;KACzB;CACF,CAAA","sourcesContent":["/**\n * @packageDocumentation\n * @module Constants\n */\n\nimport type { RequestInit } from 'undici'\nimport type { BooruCredentials } from './boorus/Booru'\nimport type Site from './structures/Site'\nimport type SiteInfo from './structures/SiteInfo'\nimport { querystring } from './Utils'\n\nconst siteJson = require('./sites.json')\nconst packageJson = require('../package.json')\n\nexport type AnySite =\n | 'e621.net'\n | 'e926.net'\n | 'hypnohub.net'\n | 'danbooru.donmai.us'\n | 'konachan.com'\n | 'konachan.net'\n | 'yande.re'\n | 'gelbooru.com'\n | 'rule34.xxx'\n | 'safebooru.org'\n | 'tbib.org'\n | 'xbooru.com'\n | 'rule34.paheal.net'\n | 'derpibooru.org'\n | 'realbooru.com'\n\ntype gelTags = {\n 'rating:e': 'rating:explicit'\n 'rating:q': 'rating:questionable'\n 'rating:s': 'rating:safe'\n\n [key: string]: string\n}\n\nconst expandedTags: gelTags = {\n 'rating:e': 'rating:explicit',\n 'rating:q': 'rating:questionable',\n 'rating:s': 'rating:safe',\n}\n\n/**\n * A map of site url/{@link SiteInfo}\n */\nexport const sites = siteJson as Record<AnySite, SiteInfo>\n\n/**\n * Custom error type for when the boorus error or for user-side error, not my code (probably)\n * <p>The name of the error is 'BooruError'\n * @type {Error}\n */\nexport class BooruError extends Error {\n constructor(message: string | Error) {\n super(message instanceof Error ? message.message : message)\n\n if (message instanceof Error) {\n this.stack = message.stack ?? '<No Stack>'\n } else {\n Error.captureStackTrace(this, BooruError)\n }\n\n this.name = 'BooruError'\n }\n}\n\n/**\n * The user-agent to use for searches\n * @private\n */\nexport const USER_AGENT = `booru/${packageJson.version} (+https://github.com/AtoraSuunva/booru)`\n\n/**\n * Expands tags based on a simple map, used for gelbooru/safebooru/etc compat :(\n *\n * @private\n * @param {String[]} tags The tags to expand\n */\nfunction expandTags(tags: string[]): string[] {\n return tags.map((v) => expandedTags[v.toLowerCase()] ?? v)\n}\n\n/**\n * Create a full uri to search with\n *\n * @private\n * @param {string} domain The domain to search\n * @param {Site} site The site to search\n * @param {string[]} [tags=[]] The tags to search for\n * @param {number} [limit=100] The limit for images to return\n * @param {number} [page=0] The page to get\n * @param {BooryCredentials} [credentials] The credentials to use for the search, appended to the querystring\n */\nexport function searchURI(\n site: Site,\n tags: string[] = [],\n limit = 100,\n page = 0,\n credentials: BooruCredentials = {},\n): string {\n const query = querystring(\n {\n [site.tagQuery]: expandTags(tags),\n limit,\n [site.paginate]: page,\n ...credentials,\n },\n {\n arrayJoin: site.tagJoin,\n },\n )\n\n return `http${site.insecure ? '' : 's'}://${site.domain}${site.api.search}${query}`\n}\n\nexport function tagListURI(\n site: Site,\n limit = 100,\n page = 0,\n credentials: BooruCredentials = {},\n): string {\n const query = querystring({\n limit,\n [site.paginate]: page,\n ...credentials,\n })\n\n return `http${site.insecure ? '' : 's'}://${site.domain}${site.api.tagList}${query}`\n}\n\n/**\n * The default options to use for requests\n * <p>I could document this better but meh\n *\n * @private\n */\nexport const defaultOptions: RequestInit = {\n headers: {\n Accept: 'application/json, application/xml;q=0.9, */*;q=0.8',\n 'User-Agent': USER_AGENT,\n },\n}\n"]}
|
package/dist/Utils.d.ts
CHANGED
|
@@ -11,13 +11,21 @@ import { type AnySite } from './Constants';
|
|
|
11
11
|
*/
|
|
12
12
|
export declare function resolveSite(domain: string): AnySite | null;
|
|
13
13
|
/**
|
|
14
|
-
* Parses xml to json, which can be used with js
|
|
14
|
+
* Parses posts xml to json, which can be used with js
|
|
15
15
|
*
|
|
16
16
|
* @private
|
|
17
17
|
* @param {String} xml The xml to convert to json
|
|
18
18
|
* @return {Object[]} A Promise with an array of objects created from the xml
|
|
19
19
|
*/
|
|
20
|
-
export declare function
|
|
20
|
+
export declare function jsonifyPosts(xml: string): object[];
|
|
21
|
+
/**
|
|
22
|
+
* Parses tags xml to json, which can be used with js
|
|
23
|
+
*
|
|
24
|
+
* @private
|
|
25
|
+
* @param {String} xml The xml to convert to json
|
|
26
|
+
* @return {Object[]} A Promise with an array of objects created from the xml
|
|
27
|
+
*/
|
|
28
|
+
export declare function jsonifyTags(xml: string): object[];
|
|
21
29
|
/**
|
|
22
30
|
* Try to parse JSON, and then return an empty array if data is an empty string, or the parsed JSON
|
|
23
31
|
*
|
package/dist/Utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../src/Utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../src/Utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,KAAK,OAAO,EAAqB,MAAM,aAAa,CAAA;AAE7D;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAkB1D;AAiCD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAgClD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA+BjD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAMpE;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAe1C;AAGD;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GAAG,MAAM,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAejC;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAItE;AAED,KAAK,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAC7C,KAAK,UAAU,GAAG,YAAY,GAAG,YAAY,EAAE,CAAA;AAE/C,UAAU,kBAAkB;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,UAAU,0BAA0B;IAClC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EACjC,EAAE,SAAe,EAAE,GAAE,kBAAuB,GAC3C,MAAM,CASR;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,UAAU,EACjB,EAAE,SAAe,EAAE,GAAE,0BAA+B,GACnD,MAAM,CAMR"}
|
package/dist/Utils.js
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.resolveSite = resolveSite;
|
|
8
|
-
exports.
|
|
8
|
+
exports.jsonifyPosts = jsonifyPosts;
|
|
9
|
+
exports.jsonifyTags = jsonifyTags;
|
|
9
10
|
exports.tryParseJSON = tryParseJSON;
|
|
10
11
|
exports.shuffle = shuffle;
|
|
11
12
|
exports.randInt = randInt;
|
|
@@ -13,8 +14,8 @@ exports.validateSearchParams = validateSearchParams;
|
|
|
13
14
|
exports.compareArrays = compareArrays;
|
|
14
15
|
exports.querystring = querystring;
|
|
15
16
|
exports.encodeURIQueryValue = encodeURIQueryValue;
|
|
16
|
-
const Constants_1 = require("./Constants");
|
|
17
17
|
const fast_xml_parser_1 = require("fast-xml-parser");
|
|
18
|
+
const Constants_1 = require("./Constants");
|
|
18
19
|
/**
|
|
19
20
|
* Check if `site` is a supported site (and check if it's an alias and return the sites's true name)
|
|
20
21
|
*
|
|
@@ -40,13 +41,13 @@ const xmlParser = new fast_xml_parser_1.XMLParser({
|
|
|
40
41
|
attributeNamePrefix: '',
|
|
41
42
|
});
|
|
42
43
|
/**
|
|
43
|
-
* Parses xml to json, which can be used with js
|
|
44
|
+
* Parses posts xml to json, which can be used with js
|
|
44
45
|
*
|
|
45
46
|
* @private
|
|
46
47
|
* @param {String} xml The xml to convert to json
|
|
47
48
|
* @return {Object[]} A Promise with an array of objects created from the xml
|
|
48
49
|
*/
|
|
49
|
-
function
|
|
50
|
+
function jsonifyPosts(xml) {
|
|
50
51
|
if (typeof xml === 'object')
|
|
51
52
|
return xml;
|
|
52
53
|
const data = xmlParser.parse(xml);
|
|
@@ -71,6 +72,39 @@ function jsonfy(xml) {
|
|
|
71
72
|
}
|
|
72
73
|
return [];
|
|
73
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Parses tags xml to json, which can be used with js
|
|
77
|
+
*
|
|
78
|
+
* @private
|
|
79
|
+
* @param {String} xml The xml to convert to json
|
|
80
|
+
* @return {Object[]} A Promise with an array of objects created from the xml
|
|
81
|
+
*/
|
|
82
|
+
function jsonifyTags(xml) {
|
|
83
|
+
if (typeof xml === 'object')
|
|
84
|
+
return xml;
|
|
85
|
+
const data = xmlParser.parse(xml);
|
|
86
|
+
if (data.html || data['!doctype']) {
|
|
87
|
+
// Some boorus return HTML error pages instead of JSON responses on errors
|
|
88
|
+
// So try scraping off what we can in that case
|
|
89
|
+
const page = data.html ?? data['!doctype']?.html;
|
|
90
|
+
const message = [];
|
|
91
|
+
if (page.body.h1) {
|
|
92
|
+
message.push(page.body.h1);
|
|
93
|
+
}
|
|
94
|
+
if (page.body.p) {
|
|
95
|
+
message.push(page.body.p['#text']);
|
|
96
|
+
}
|
|
97
|
+
throw new Constants_1.BooruError(`The Booru sent back an error: '${message.join(': ')}'`);
|
|
98
|
+
}
|
|
99
|
+
if (data.tags.tag) {
|
|
100
|
+
return data.tags.tag
|
|
101
|
+
? Array.isArray(data.tags.tag)
|
|
102
|
+
? data.tags.tag
|
|
103
|
+
: [data.tags.tag]
|
|
104
|
+
: [];
|
|
105
|
+
}
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
74
108
|
/**
|
|
75
109
|
* Try to parse JSON, and then return an empty array if data is an empty string, or the parsed JSON
|
|
76
110
|
*
|
package/dist/Utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Utils.js","sourceRoot":"","sources":["../src/Utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @packageDocumentation\n * @module Utils\n */\n\nimport { type AnySite, BooruError, sites } from './Constants'\n\nimport { XMLParser } from 'fast-xml-parser'\n\n/**\n * Check if `site` is a supported site (and check if it's an alias and return the sites's true name)\n *\n * @param {String} domain The site to resolveSite\n * @return {String?} null if site is not supported, the site otherwise\n */\nexport function resolveSite(domain: string): AnySite | null {\n if (typeof domain !== 'string') {\n return null\n }\n\n const lowerDomain = domain.toLowerCase()\n\n for (const [site, info] of Object.entries(sites)) {\n if (\n site === lowerDomain ||\n info.domain === lowerDomain ||\n info.aliases.includes(lowerDomain)\n ) {\n return site as AnySite\n }\n }\n\n return null\n}\n\ninterface XMLPage {\n html: any\n}\n\ninterface XMLPosts {\n post?: any[]\n tag?: any\n}\n\ninterface BooruXML {\n html?: XMLPage\n '!doctype'?: XMLPage\n posts: XMLPosts\n}\n\nconst xmlParser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: '',\n})\n\n/**\n * Parses xml to json, which can be used with js\n *\n * @private\n * @param {String} xml The xml to convert to json\n * @return {Object[]} A Promise with an array of objects created from the xml\n */\nexport function jsonfy(xml: string): object[] {\n if (typeof xml === 'object') return xml\n\n const data = xmlParser.parse(xml) as BooruXML\n\n if (data.html || data['!doctype']) {\n // Some boorus return HTML error pages instead of JSON responses on errors\n // So try scraping off what we can in that case\n const page = data.html ?? data['!doctype']?.html\n const message = []\n if (page.body.h1) {\n message.push(page.body.h1)\n }\n\n if (page.body.p) {\n message.push(page.body.p['#text'])\n }\n\n throw new BooruError(\n `The Booru sent back an error: '${message.join(': ')}'`,\n )\n }\n\n if (data.posts.post) {\n return data.posts.post\n }\n\n if (data.posts.tag) {\n return Array.isArray(data.posts.tag) ? data.posts.tag : [data.posts.tag]\n }\n\n return []\n}\n\n/**\n * Try to parse JSON, and then return an empty array if data is an empty string, or the parsed JSON\n *\n * Blame rule34.xxx for returning literally an empty response with HTTP 200 for this\n * @param data The data to try and parse\n * @returns Either the parsed data, or an empty array\n */\nexport function tryParseJSON(data: string): Record<string, unknown>[] {\n if (data === '') {\n return []\n }\n\n return JSON.parse(data)\n}\n\n/**\n * Yay fisher-bates\n * Taken from http://stackoverflow.com/a/2450976\n *\n * @private\n * @param {Array} array Array of something\n * @return {Array} Shuffled array of something\n */\nexport function shuffle<T>(array: T[]): T[] {\n let currentIndex: number = array.length\n let temporaryValue: T\n let randomIndex: number\n\n while (currentIndex !== 0) {\n randomIndex = Math.floor(Math.random() * currentIndex)\n currentIndex -= 1\n\n temporaryValue = array[currentIndex]\n array[currentIndex] = array[randomIndex]\n array[randomIndex] = temporaryValue\n }\n\n return array\n}\n\n// Thanks mdn and damnit derpibooru\n/**\n * Generate a random int between [min, max]\n *\n * @private\n * @param {Number} min The minimum (inclusive)\n * @param {Number} max The maximum (inclusive)\n */\nexport function randInt(min: number, max: number): number {\n const nmin = Math.ceil(min)\n const nmax = Math.floor(max)\n return Math.floor(Math.random() * (nmax - nmin + 1)) + nmin\n}\n\n/**\n * Performs some basic search validation\n *\n * @private\n * @param {String} site The site to resolve\n * @param {Number|String} limit The limit for the amount of images to fetch\n */\nexport function validateSearchParams(\n site: string,\n limit: number | string,\n): { site: string; limit: number } {\n const resolvedSite = resolveSite(site)\n\n const resolvedLimit =\n typeof limit !== 'number' ? Number.parseInt(limit, 10) : limit\n\n if (resolvedSite === null) {\n throw new BooruError('Site not supported')\n }\n\n if (typeof limit !== 'number' || Number.isNaN(limit)) {\n throw new BooruError('`limit` should be an int')\n }\n\n return { site: resolvedSite, limit: resolvedLimit }\n}\n\n/**\n * Finds the matching strings between two arrays\n *\n * @private\n * @param {String[]} arr1 The first array\n * @param {String[]} arr2 The second array\n * @return {String[]} The shared strings between the arrays\n */\nexport function compareArrays(arr1: string[], arr2: string[]): string[] {\n return arr1.filter((e1) =>\n arr2.some((e2) => e1.toLowerCase() === e2.toLowerCase()),\n )\n}\n\ntype URIEncodable = string | number | boolean\ntype QueryValue = URIEncodable | URIEncodable[]\n\ninterface QuerystringOptions {\n arrayJoin?: string\n}\n\ninterface EncodeURIQueryValueOptions {\n arrayJoin?: string\n}\n\n/**\n * Turns an object into a query string, correctly encoding uri components\n *\n * @example\n * const options = { page: 10, limit: 100 }\n * const query = querystring(options) // 'page=10&limit=100'\n * console.log(`https://example.com?${query}`)\n *\n * @param query An object with key/value pairs that will be turned into a string\n * @returns A string that can be appended to a url (after `?`)\n */\nexport function querystring(\n query: Record<string, QueryValue>,\n { arrayJoin = '+' }: QuerystringOptions = {},\n): string {\n return Object.entries(query)\n .map(\n ([key, value]) =>\n `${encodeURIComponent(key)}=${encodeURIQueryValue(value, {\n arrayJoin,\n })}`,\n )\n .join('&')\n}\n\n/**\n * Encodes a single value or an array of values to be usable in as a URI component,\n * joining array elements with '+'\n * @param value The value to encode\n * @returns An encoded value that can be passed to a querystring\n */\nexport function encodeURIQueryValue(\n value: QueryValue,\n { arrayJoin = '+' }: EncodeURIQueryValueOptions = {},\n): string {\n if (Array.isArray(value)) {\n return value.map(encodeURIComponent).join(arrayJoin)\n }\n\n return encodeURIComponent(value)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Utils.js","sourceRoot":"","sources":["../src/Utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @packageDocumentation\n * @module Utils\n */\n\nimport { XMLParser } from 'fast-xml-parser'\nimport { type AnySite, BooruError, sites } from './Constants'\n\n/**\n * Check if `site` is a supported site (and check if it's an alias and return the sites's true name)\n *\n * @param {String} domain The site to resolveSite\n * @return {String?} null if site is not supported, the site otherwise\n */\nexport function resolveSite(domain: string): AnySite | null {\n if (typeof domain !== 'string') {\n return null\n }\n\n const lowerDomain = domain.toLowerCase()\n\n for (const [site, info] of Object.entries(sites)) {\n if (\n site === lowerDomain ||\n info.domain === lowerDomain ||\n info.aliases.includes(lowerDomain)\n ) {\n return site as AnySite\n }\n }\n\n return null\n}\n\ninterface XMLPage {\n html: any\n}\n\ninterface XMLPosts {\n post?: any[]\n tag?: any\n}\n\ninterface XMLTags {\n tag?: any[]\n}\n\ninterface BooruXML {\n html?: XMLPage\n '!doctype'?: XMLPage\n}\n\ninterface BooruXMLPosts extends BooruXML {\n posts: XMLPosts\n}\n\ninterface BooruXMLTags extends BooruXML {\n tags: XMLTags\n}\n\nconst xmlParser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: '',\n})\n\n/**\n * Parses posts xml to json, which can be used with js\n *\n * @private\n * @param {String} xml The xml to convert to json\n * @return {Object[]} A Promise with an array of objects created from the xml\n */\nexport function jsonifyPosts(xml: string): object[] {\n if (typeof xml === 'object') return xml\n\n const data = xmlParser.parse(xml) as BooruXMLPosts\n\n if (data.html || data['!doctype']) {\n // Some boorus return HTML error pages instead of JSON responses on errors\n // So try scraping off what we can in that case\n const page = data.html ?? data['!doctype']?.html\n const message = []\n if (page.body.h1) {\n message.push(page.body.h1)\n }\n\n if (page.body.p) {\n message.push(page.body.p['#text'])\n }\n\n throw new BooruError(\n `The Booru sent back an error: '${message.join(': ')}'`,\n )\n }\n\n if (data.posts.post) {\n return data.posts.post\n }\n\n if (data.posts.tag) {\n return Array.isArray(data.posts.tag) ? data.posts.tag : [data.posts.tag]\n }\n\n return []\n}\n\n/**\n * Parses tags xml to json, which can be used with js\n *\n * @private\n * @param {String} xml The xml to convert to json\n * @return {Object[]} A Promise with an array of objects created from the xml\n */\nexport function jsonifyTags(xml: string): object[] {\n if (typeof xml === 'object') return xml\n\n const data = xmlParser.parse(xml) as BooruXMLTags\n\n if (data.html || data['!doctype']) {\n // Some boorus return HTML error pages instead of JSON responses on errors\n // So try scraping off what we can in that case\n const page = data.html ?? data['!doctype']?.html\n const message = []\n if (page.body.h1) {\n message.push(page.body.h1)\n }\n\n if (page.body.p) {\n message.push(page.body.p['#text'])\n }\n\n throw new BooruError(\n `The Booru sent back an error: '${message.join(': ')}'`,\n )\n }\n\n if (data.tags.tag) {\n return data.tags.tag\n ? Array.isArray(data.tags.tag)\n ? data.tags.tag\n : [data.tags.tag]\n : []\n }\n return []\n}\n\n/**\n * Try to parse JSON, and then return an empty array if data is an empty string, or the parsed JSON\n *\n * Blame rule34.xxx for returning literally an empty response with HTTP 200 for this\n * @param data The data to try and parse\n * @returns Either the parsed data, or an empty array\n */\nexport function tryParseJSON(data: string): Record<string, unknown>[] {\n if (data === '') {\n return []\n }\n\n return JSON.parse(data)\n}\n\n/**\n * Yay fisher-bates\n * Taken from http://stackoverflow.com/a/2450976\n *\n * @private\n * @param {Array} array Array of something\n * @return {Array} Shuffled array of something\n */\nexport function shuffle<T>(array: T[]): T[] {\n let currentIndex: number = array.length\n let temporaryValue: T\n let randomIndex: number\n\n while (currentIndex !== 0) {\n randomIndex = Math.floor(Math.random() * currentIndex)\n currentIndex -= 1\n\n temporaryValue = array[currentIndex]\n array[currentIndex] = array[randomIndex]\n array[randomIndex] = temporaryValue\n }\n\n return array\n}\n\n// Thanks mdn and damnit derpibooru\n/**\n * Generate a random int between [min, max]\n *\n * @private\n * @param {Number} min The minimum (inclusive)\n * @param {Number} max The maximum (inclusive)\n */\nexport function randInt(min: number, max: number): number {\n const nmin = Math.ceil(min)\n const nmax = Math.floor(max)\n return Math.floor(Math.random() * (nmax - nmin + 1)) + nmin\n}\n\n/**\n * Performs some basic search validation\n *\n * @private\n * @param {String} site The site to resolve\n * @param {Number|String} limit The limit for the amount of images to fetch\n */\nexport function validateSearchParams(\n site: string,\n limit: number | string,\n): { site: string; limit: number } {\n const resolvedSite = resolveSite(site)\n\n const resolvedLimit =\n typeof limit !== 'number' ? Number.parseInt(limit, 10) : limit\n\n if (resolvedSite === null) {\n throw new BooruError('Site not supported')\n }\n\n if (typeof limit !== 'number' || Number.isNaN(limit)) {\n throw new BooruError('`limit` should be an int')\n }\n\n return { site: resolvedSite, limit: resolvedLimit }\n}\n\n/**\n * Finds the matching strings between two arrays\n *\n * @private\n * @param {String[]} arr1 The first array\n * @param {String[]} arr2 The second array\n * @return {String[]} The shared strings between the arrays\n */\nexport function compareArrays(arr1: string[], arr2: string[]): string[] {\n return arr1.filter((e1) =>\n arr2.some((e2) => e1.toLowerCase() === e2.toLowerCase()),\n )\n}\n\ntype URIEncodable = string | number | boolean\ntype QueryValue = URIEncodable | URIEncodable[]\n\ninterface QuerystringOptions {\n arrayJoin?: string\n}\n\ninterface EncodeURIQueryValueOptions {\n arrayJoin?: string\n}\n\n/**\n * Turns an object into a query string, correctly encoding uri components\n *\n * @example\n * const options = { page: 10, limit: 100 }\n * const query = querystring(options) // 'page=10&limit=100'\n * console.log(`https://example.com?${query}`)\n *\n * @param query An object with key/value pairs that will be turned into a string\n * @returns A string that can be appended to a url (after `?`)\n */\nexport function querystring(\n query: Record<string, QueryValue>,\n { arrayJoin = '+' }: QuerystringOptions = {},\n): string {\n return Object.entries(query)\n .map(\n ([key, value]) =>\n `${encodeURIComponent(key)}=${encodeURIQueryValue(value, {\n arrayJoin,\n })}`,\n )\n .join('&')\n}\n\n/**\n * Encodes a single value or an array of values to be usable in as a URI component,\n * joining array elements with '+'\n * @param value The value to encode\n * @returns An encoded value that can be passed to a querystring\n */\nexport function encodeURIQueryValue(\n value: QueryValue,\n { arrayJoin = '+' }: EncodeURIQueryValueOptions = {},\n): string {\n if (Array.isArray(value)) {\n return value.map(encodeURIComponent).join(arrayJoin)\n }\n\n return encodeURIComponent(value)\n}\n"]}
|
package/dist/boorus/Booru.d.ts
CHANGED
|
@@ -6,12 +6,17 @@ import type InternalSearchParameters from '../structures/InternalSearchParameter
|
|
|
6
6
|
import type SearchParameters from '../structures/SearchParameters';
|
|
7
7
|
import SearchResults from '../structures/SearchResults';
|
|
8
8
|
import type Site from '../structures/Site';
|
|
9
|
+
import TagListResults from '../structures/TagListResults';
|
|
9
10
|
export type BooruCredentials = Record<string, string>;
|
|
10
11
|
interface SearchUrlParams {
|
|
11
12
|
tags: string[];
|
|
12
13
|
limit: number;
|
|
13
14
|
page: number;
|
|
14
15
|
}
|
|
16
|
+
interface TagsURLParams {
|
|
17
|
+
limit?: number | undefined;
|
|
18
|
+
page?: number | undefined;
|
|
19
|
+
}
|
|
15
20
|
/**
|
|
16
21
|
* A basic, JSON booru
|
|
17
22
|
* @example
|
|
@@ -60,6 +65,14 @@ export declare class Booru {
|
|
|
60
65
|
* @return {String} The url to the post
|
|
61
66
|
*/
|
|
62
67
|
postView(id: string | number): string;
|
|
68
|
+
/**
|
|
69
|
+
* Gets a list of tags from the booru
|
|
70
|
+
* @param {Partial<TagsURLParams>} [params] The parameters for the tags list
|
|
71
|
+
* @param {number} [params.limit=100] The limit of tags to return
|
|
72
|
+
* @param {number} [params.page=1] The page of tags to return
|
|
73
|
+
* @return {Promise<any[]>} A promise with the tags as an array
|
|
74
|
+
*/
|
|
75
|
+
tagList({ limit, page, }?: Partial<TagsURLParams>): Promise<TagListResults>;
|
|
63
76
|
/**
|
|
64
77
|
* The internal & common searching logic, pls dont use this use .search instead
|
|
65
78
|
*
|
|
@@ -78,6 +91,14 @@ export declare class Booru {
|
|
|
78
91
|
* @returns A URL to search the booru
|
|
79
92
|
*/
|
|
80
93
|
getSearchUrl({ tags, limit, page, }?: Partial<SearchUrlParams>): string;
|
|
94
|
+
/**
|
|
95
|
+
* Generates a URL to get a list of tags from the booru
|
|
96
|
+
* @param opt
|
|
97
|
+
* @param {number} [opt.limit] The limit of tags to return
|
|
98
|
+
* @param {number} [opt.page] The page of tags to return
|
|
99
|
+
* @returns {string} A URL to get the tags list
|
|
100
|
+
*/
|
|
101
|
+
getTagListUrl({ limit, page, }?: Partial<TagsURLParams>): string;
|
|
81
102
|
/**
|
|
82
103
|
* Parse the response from the booru
|
|
83
104
|
*
|
|
@@ -87,6 +108,14 @@ export declare class Booru {
|
|
|
87
108
|
* @return {SearchResults} The results of this search
|
|
88
109
|
*/
|
|
89
110
|
protected parseSearchResult(result: any, { fakeLimit, tags, limit, random, page, showUnavailable, }: InternalSearchParameters): SearchResults;
|
|
111
|
+
/**
|
|
112
|
+
* Parse the response from the booru for a tag list
|
|
113
|
+
*
|
|
114
|
+
* @param result
|
|
115
|
+
* @param param1
|
|
116
|
+
* @returns
|
|
117
|
+
*/
|
|
118
|
+
protected parseTagListResult(result: any, { limit, page }?: Partial<TagsURLParams>): TagListResults;
|
|
90
119
|
}
|
|
91
120
|
export default Booru;
|
|
92
121
|
//# sourceMappingURL=Booru.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Booru.d.ts","sourceRoot":"","sources":["../../src/boorus/Booru.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"Booru.d.ts","sourceRoot":"","sources":["../../src/boorus/Booru.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,wBAAwB,MAAM,wCAAwC,CAAA;AAElF,OAAO,KAAK,gBAAgB,MAAM,gCAAgC,CAAA;AAClE,OAAO,aAAa,MAAM,6BAA6B,CAAA;AACvD,OAAO,KAAK,IAAI,MAAM,oBAAoB,CAAA;AAE1C,OAAO,cAAc,MAAM,8BAA8B,CAAA;AAgBzD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAErD,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACb;AAED,UAAU,aAAa;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC1B;AAUD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,KAAK;IAChB,8BAA8B;IACvB,MAAM,EAAE,MAAM,CAAA;IACrB,8CAA8C;IACvC,IAAI,EAAE,IAAI,CAAA;IACjB,4CAA4C;IACrC,WAAW,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAA;IAEjD;;;;;;OAMG;gBACS,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,gBAAgB;IAYtD,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE;IAQ1D;;;;;OAKG;IACU,MAAM,CACjB,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,EACE,KAAS,EACT,MAAc,EACd,IAAQ,EACR,eAAuB,GACxB,GAAE,gBAAqB,GACvB,OAAO,CAAC,aAAa,CAAC;IA4BzB;;;;;OAKG;IACI,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAU5C;;;;;;OAMG;IACU,OAAO,CAAC,EACnB,KAAW,EACX,IAAQ,GACT,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA6CxD;;;;;;;OAOG;cACa,eAAe,CAC7B,IAAI,EAAE,MAAM,EAAE,EACd,EACE,GAAU,EACV,KAAS,EACT,MAAc,EACd,IAAQ,GACT,GAAE,wBAA6B,GAC/B,OAAO,CAAC,GAAG,CAAC;IA2Df;;;;;;;OAOG;IACH,YAAY,CAAC,EACX,IAAS,EACT,KAAW,EACX,IAAQ,GACT,GAAE,OAAO,CAAC,eAAe,CAAM,GAAG,MAAM;IAIzC;;;;;;OAMG;IACH,aAAa,CAAC,EACZ,KAAW,EACX,IAAQ,GACT,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,MAAM;IASvC;;;;;;;OAOG;IACH,SAAS,CAAC,iBAAiB,CACzB,MAAM,EAAE,GAAG,EACX,EACE,SAAS,EACT,IAAI,EACJ,KAAK,EACL,MAAM,EACN,IAAI,EACJ,eAAe,GAChB,EAAE,wBAAwB,GAC1B,aAAa;IAuDhB;;;;;;OAMG;IACH,SAAS,CAAC,kBAAkB,CAC1B,MAAM,EAAE,GAAG,EACX,EAAE,KAAW,EAAE,IAAQ,EAAE,GAAE,OAAO,CAAC,aAAa,CAAM,GACrD,cAAc;CAiBlB;AAED,eAAe,KAAK,CAAA"}
|
package/dist/boorus/Booru.js
CHANGED
|
@@ -8,11 +8,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
8
8
|
};
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.Booru = void 0;
|
|
11
|
-
const Constants_1 = require("../Constants");
|
|
12
|
-
const Utils_1 = require("../Utils");
|
|
13
11
|
const undici_1 = require("undici");
|
|
12
|
+
const Constants_1 = require("../Constants");
|
|
14
13
|
const Post_1 = __importDefault(require("../structures/Post"));
|
|
15
14
|
const SearchResults_1 = __importDefault(require("../structures/SearchResults"));
|
|
15
|
+
const Tag_1 = __importDefault(require("../structures/Tag"));
|
|
16
|
+
const TagListResults_1 = __importDefault(require("../structures/TagListResults"));
|
|
17
|
+
const Utils_1 = require("../Utils");
|
|
16
18
|
const resolvedFetch = typeof window !== 'undefined' ? window.fetch.bind(window) : undici_1.fetch;
|
|
17
19
|
/*
|
|
18
20
|
- new Booru
|
|
@@ -112,6 +114,50 @@ class Booru {
|
|
|
112
114
|
}
|
|
113
115
|
return `http${this.site.insecure ? '' : 's'}://${this.domain}${this.site.api.postView}${id}`;
|
|
114
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Gets a list of tags from the booru
|
|
119
|
+
* @param {Partial<TagsURLParams>} [params] The parameters for the tags list
|
|
120
|
+
* @param {number} [params.limit=100] The limit of tags to return
|
|
121
|
+
* @param {number} [params.page=1] The page of tags to return
|
|
122
|
+
* @return {Promise<any[]>} A promise with the tags as an array
|
|
123
|
+
*/
|
|
124
|
+
async tagList({ limit = 100, page = 1, } = {}) {
|
|
125
|
+
const url = this.getTagListUrl({ limit, page });
|
|
126
|
+
const options = Constants_1.defaultOptions;
|
|
127
|
+
try {
|
|
128
|
+
const response = await resolvedFetch(url, options);
|
|
129
|
+
// Check for CloudFlare ratelimiting
|
|
130
|
+
if (response.status === 503) {
|
|
131
|
+
const body = await response.clone().text();
|
|
132
|
+
if (body.includes('cf-browser-verification')) {
|
|
133
|
+
throw new Constants_1.BooruError("Received a CloudFlare browser verification request. Can't proceed.");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (!response.ok) {
|
|
137
|
+
throw new Constants_1.BooruError(`Received HTTP ${response.status} from booru: '${await response.text()}'`);
|
|
138
|
+
}
|
|
139
|
+
const data = await response.text();
|
|
140
|
+
/**
|
|
141
|
+
* Many boorus don't support JSON parameter for tag listing
|
|
142
|
+
* So attempt JSON parsing, but if it fails default to XML parsing
|
|
143
|
+
**/
|
|
144
|
+
let tags = [];
|
|
145
|
+
try {
|
|
146
|
+
tags = (0, Utils_1.tryParseJSON)(data);
|
|
147
|
+
}
|
|
148
|
+
catch (_e) {
|
|
149
|
+
tags = (0, Utils_1.jsonifyTags)(data);
|
|
150
|
+
}
|
|
151
|
+
return this.parseTagListResult(tags, { limit, page });
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
if (err.type === 'invalid-json')
|
|
155
|
+
if (err instanceof Error) {
|
|
156
|
+
throw new Constants_1.BooruError(err);
|
|
157
|
+
}
|
|
158
|
+
throw err;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
115
161
|
/**
|
|
116
162
|
* The internal & common searching logic, pls dont use this use .search instead
|
|
117
163
|
*
|
|
@@ -149,7 +195,7 @@ class Booru {
|
|
|
149
195
|
}
|
|
150
196
|
}
|
|
151
197
|
const data = await response.text();
|
|
152
|
-
const posts = xml ? (0, Utils_1.
|
|
198
|
+
const posts = xml ? (0, Utils_1.jsonifyPosts)(data) : (0, Utils_1.tryParseJSON)(data);
|
|
153
199
|
if (!response.ok) {
|
|
154
200
|
throw new Constants_1.BooruError(`Received HTTP ${response.status} ` +
|
|
155
201
|
`from booru: '${posts.error ??
|
|
@@ -175,6 +221,19 @@ class Booru {
|
|
|
175
221
|
getSearchUrl({ tags = [], limit = 100, page = 1, } = {}) {
|
|
176
222
|
return (0, Constants_1.searchURI)(this.site, tags, limit, page, this.credentials);
|
|
177
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Generates a URL to get a list of tags from the booru
|
|
226
|
+
* @param opt
|
|
227
|
+
* @param {number} [opt.limit] The limit of tags to return
|
|
228
|
+
* @param {number} [opt.page] The page of tags to return
|
|
229
|
+
* @returns {string} A URL to get the tags list
|
|
230
|
+
*/
|
|
231
|
+
getTagListUrl({ limit = 100, page = 1, } = {}) {
|
|
232
|
+
if (!this.site.api.tagList) {
|
|
233
|
+
throw new Constants_1.BooruError(`This booru does not support tag listing: ${this.site.domain}`);
|
|
234
|
+
}
|
|
235
|
+
return (0, Constants_1.tagListURI)(this.site, limit, page, this.credentials);
|
|
236
|
+
}
|
|
178
237
|
/**
|
|
179
238
|
* Parse the response from the booru
|
|
180
239
|
*
|
|
@@ -231,6 +290,28 @@ class Booru {
|
|
|
231
290
|
}
|
|
232
291
|
return new SearchResults_1.default(posts, tags, options, this);
|
|
233
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Parse the response from the booru for a tag list
|
|
295
|
+
*
|
|
296
|
+
* @param result
|
|
297
|
+
* @param param1
|
|
298
|
+
* @returns
|
|
299
|
+
*/
|
|
300
|
+
parseTagListResult(result, { limit = 100, page = 1 } = {}) {
|
|
301
|
+
if (result.success === false) {
|
|
302
|
+
throw new Constants_1.BooruError(result.message ?? result.reason);
|
|
303
|
+
}
|
|
304
|
+
let tags = [];
|
|
305
|
+
if (result) {
|
|
306
|
+
if (Array.isArray(result)) {
|
|
307
|
+
tags = result.map((v) => new Tag_1.default(v, this));
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
tags = [new Tag_1.default(result, this)];
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return new TagListResults_1.default(tags, { limit, page }, this);
|
|
314
|
+
}
|
|
234
315
|
}
|
|
235
316
|
exports.Booru = Booru;
|
|
236
317
|
exports.default = Booru;
|
package/dist/boorus/Booru.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Booru.js","sourceRoot":"","sources":["../../src/boorus/Booru.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @packageDocumentation\n * @module Boorus\n */\n\nimport { BooruError, defaultOptions, searchURI } from '../Constants'\nimport { jsonfy, resolveSite, shuffle, tryParseJSON } from '../Utils'\n\nimport { fetch } from 'undici'\nimport type InternalSearchParameters from '../structures/InternalSearchParameters'\nimport Post from '../structures/Post'\nimport type SearchParameters from '../structures/SearchParameters'\nimport SearchResults from '../structures/SearchResults'\nimport type Site from '../structures/Site'\n\n// Shut up the compiler\n// This attempts to find and use the native browser fetch, if possible\n// Fixes https://github.com/AtoraSuunva/booru/issues/51\ndeclare const window: any\nconst resolvedFetch: typeof fetch =\n typeof window !== 'undefined' ? window.fetch.bind(window) : fetch\n\nexport type BooruCredentials = Record<string, string>\n\ninterface SearchUrlParams {\n tags: string[]\n limit: number\n page: number\n}\n\n/*\n - new Booru\n => Constructor, params {name, {nsfw, {search, postView, ...}, random}, {apiTokens...}}\n => .search([tags...], {limit, random})\n => .postView(id)\n => .site\n */\n\n/**\n * A basic, JSON booru\n * @example\n * ```\n * const Booru = require('booru')\n * // Aliases are supported\n * const e9 = Booru('e9')\n *\n * // You can then search the site\n * const imgs = await e9.search(['cat', 'cute'], {limit: 3})\n *\n * // And use the images\n * imgs.forEach(i => console.log(i.fileUrl))\n *\n * // Or access other methods on the Booru\n * e9.postView(imgs[0].id)\n * ```\n */\nexport class Booru {\n /** The domain of the booru */\n public domain: string\n /** The site object representing this booru */\n public site: Site\n /** The credentials to use for this booru */\n public credentials?: BooruCredentials | undefined\n\n /**\n * Create a new booru from a site\n *\n * @private\n * @param site The site to use\n * @param credentials Credentials for the API (Currently not used)\n */\n constructor(site: Site, credentials?: BooruCredentials) {\n const domain = resolveSite(site.domain)\n\n if (domain === null) {\n throw new Error(`Invalid site passed: ${site.domain}`)\n }\n\n this.domain = domain\n this.site = site\n this.credentials = credentials\n }\n\n protected normalizeTags(tags: string | string[]): string[] {\n if (!Array.isArray(tags)) {\n return [tags]\n }\n\n return tags.slice()\n }\n\n /**\n * Search for images on this booru\n * @param {String|String[]} tags The tag(s) to search for\n * @param {SearchParameters} searchArgs The arguments for the search\n * @return {Promise<SearchResults>} The results as an array of Posts\n */\n public async search(\n tags: string | string[],\n {\n limit = 1,\n random = false,\n page = 0,\n showUnavailable = false,\n }: SearchParameters = {},\n ): Promise<SearchResults> {\n const fakeLimit: number = random && !this.site.random ? 100 : 0\n const tagArray = this.normalizeTags(tags)\n\n try {\n const searchResult = await this.doSearchRequest(tagArray, {\n limit,\n random,\n page,\n showUnavailable,\n })\n return this.parseSearchResult(searchResult, {\n fakeLimit,\n tags: tagArray,\n limit,\n random,\n page,\n showUnavailable,\n })\n } catch (err) {\n if (err instanceof Error) {\n throw new BooruError(err)\n }\n\n throw err\n }\n }\n\n /**\n * Gets the url you'd see in your browser from a post id for this booru\n *\n * @param {String} id The id to get the postView for\n * @return {String} The url to the post\n */\n public postView(id: string | number): string {\n if (typeof id === 'string' && Number.isNaN(Number.parseInt(id, 10))) {\n throw new BooruError(`Not a valid id for postView: ${id}`)\n }\n\n return `http${this.site.insecure ? '' : 's'}://${this.domain}${\n this.site.api.postView\n }${id}`\n }\n\n /**\n * The internal & common searching logic, pls dont use this use .search instead\n *\n * @protected\n * @param {String[]|String} tags The tags to search with\n * @param {InternalSearchParameters} searchArgs The arguments for the search\n * @return {Promise<Object>}\n */\n protected async doSearchRequest(\n tags: string[],\n {\n uri = null,\n limit = 1,\n random = false,\n page = 0,\n }: InternalSearchParameters = {},\n ): Promise<any> {\n // Used for random on sites without order:random\n let fakeLimit: number | undefined\n let searchTags = tags.slice()\n\n if (random) {\n if (this.site.random) {\n searchTags.push('order:random')\n } else {\n fakeLimit = 100\n }\n }\n\n if (this.site.defaultTags) {\n searchTags = searchTags.concat(\n this.site.defaultTags.filter((v) => !searchTags.includes(v)),\n )\n }\n\n const fetchuri =\n uri ??\n this.getSearchUrl({ tags: searchTags, limit: fakeLimit ?? limit, page })\n const options = defaultOptions\n const xml = this.site.type === 'xml'\n\n try {\n const response = await resolvedFetch(fetchuri, options)\n\n // Check for CloudFlare ratelimiting\n if (response.status === 503) {\n const body = await response.clone().text()\n if (body.includes('cf-browser-verification')) {\n throw new BooruError(\n \"Received a CloudFlare browser verification request. Can't proceed.\",\n )\n }\n }\n\n const data = await response.text()\n const posts = xml ? jsonfy(data) : tryParseJSON(data)\n\n if (!response.ok) {\n throw new BooruError(\n `Received HTTP ${response.status} ` +\n `from booru: '${\n (posts as any).error ??\n (posts as any).message ??\n JSON.stringify(posts)\n }'`,\n )\n }\n\n return posts\n } catch (err) {\n if ((err as any).type === 'invalid-json') return ''\n throw err\n }\n }\n\n /**\n * Generates a URL to search the booru with, mostly for debugging purposes\n * @param opt\n * @param {string[]} [opt.tags] The tags to search for\n * @param {number} [opt.limit] The limit of results to return\n * @param {number} [opt.page] The page of results to return\n * @returns A URL to search the booru\n */\n getSearchUrl({\n tags = [],\n limit = 100,\n page = 1,\n }: Partial<SearchUrlParams> = {}): string {\n return searchURI(this.site, tags, limit, page, this.credentials)\n }\n\n /**\n * Parse the response from the booru\n *\n * @protected\n * @param {Object} result The response of the booru\n * @param {InternalSearchParameters} searchArgs The arguments used for the search\n * @return {SearchResults} The results of this search\n */\n protected parseSearchResult(\n result: any,\n {\n fakeLimit,\n tags,\n limit,\n random,\n page,\n showUnavailable,\n }: InternalSearchParameters,\n ): SearchResults {\n let outResult = result\n\n if (outResult.success === false) {\n throw new BooruError(outResult.message ?? outResult.reason)\n }\n\n // Gelbooru\n if (outResult['@attributes']) {\n const attributes = outResult['@attributes']\n\n if (attributes.count === '0' || !outResult.post) {\n outResult = []\n } else if (Array.isArray(outResult.post)) {\n outResult = outResult.post\n } else {\n outResult = [outResult.post]\n }\n }\n\n if (outResult.posts) {\n outResult = outResult.posts\n }\n\n if (outResult.images) {\n outResult = outResult.images\n }\n\n let r: string[] | undefined\n // If gelbooru/other booru decides to return *nothing* instead of an empty array\n if (outResult === '') {\n r = []\n } else if (fakeLimit) {\n r = shuffle(outResult)\n } else if (outResult.constructor === Object) {\n // For XML based sites\n r = [outResult]\n }\n\n let posts: Post[] = (r ?? outResult)\n .slice(0, limit)\n .map((v: any) => new Post(v, this))\n const options = { limit, random, page, showUnavailable }\n\n if (tags === undefined) {\n tags = []\n }\n\n if (!showUnavailable) {\n posts = posts.filter((p) => p.available)\n }\n\n return new SearchResults(posts, tags, options, this)\n }\n}\n\nexport default Booru\n"]}
|
|
1
|
+
{"version":3,"file":"Booru.js","sourceRoot":"","sources":["../../src/boorus/Booru.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @packageDocumentation\n * @module Boorus\n */\n\nimport { fetch } from 'undici'\nimport { BooruError, defaultOptions, searchURI, tagListURI } from '../Constants'\nimport type InternalSearchParameters from '../structures/InternalSearchParameters'\nimport Post from '../structures/Post'\nimport type SearchParameters from '../structures/SearchParameters'\nimport SearchResults from '../structures/SearchResults'\nimport type Site from '../structures/Site'\nimport Tag from '../structures/Tag'\nimport TagListResults from '../structures/TagListResults'\nimport {\n jsonifyPosts,\n jsonifyTags,\n resolveSite,\n shuffle,\n tryParseJSON,\n} from '../Utils'\n\n// Shut up the compiler\n// This attempts to find and use the native browser fetch, if possible\n// Fixes https://github.com/AtoraSuunva/booru/issues/51\ndeclare const window: any\nconst resolvedFetch: typeof fetch =\n typeof window !== 'undefined' ? window.fetch.bind(window) : fetch\n\nexport type BooruCredentials = Record<string, string>\n\ninterface SearchUrlParams {\n tags: string[]\n limit: number\n page: number\n}\n\ninterface TagsURLParams {\n limit?: number | undefined\n page?: number | undefined\n}\n\n/*\n - new Booru\n => Constructor, params {name, {nsfw, {search, postView, ...}, random}, {apiTokens...}}\n => .search([tags...], {limit, random})\n => .postView(id)\n => .site\n */\n\n/**\n * A basic, JSON booru\n * @example\n * ```\n * const Booru = require('booru')\n * // Aliases are supported\n * const e9 = Booru('e9')\n *\n * // You can then search the site\n * const imgs = await e9.search(['cat', 'cute'], {limit: 3})\n *\n * // And use the images\n * imgs.forEach(i => console.log(i.fileUrl))\n *\n * // Or access other methods on the Booru\n * e9.postView(imgs[0].id)\n * ```\n */\nexport class Booru {\n /** The domain of the booru */\n public domain: string\n /** The site object representing this booru */\n public site: Site\n /** The credentials to use for this booru */\n public credentials?: BooruCredentials | undefined\n\n /**\n * Create a new booru from a site\n *\n * @private\n * @param site The site to use\n * @param credentials Credentials for the API (Currently not used)\n */\n constructor(site: Site, credentials?: BooruCredentials) {\n const domain = resolveSite(site.domain)\n\n if (domain === null) {\n throw new Error(`Invalid site passed: ${site.domain}`)\n }\n\n this.domain = domain\n this.site = site\n this.credentials = credentials\n }\n\n protected normalizeTags(tags: string | string[]): string[] {\n if (!Array.isArray(tags)) {\n return [tags]\n }\n\n return tags.slice()\n }\n\n /**\n * Search for images on this booru\n * @param {String|String[]} tags The tag(s) to search for\n * @param {SearchParameters} searchArgs The arguments for the search\n * @return {Promise<SearchResults>} The results as an array of Posts\n */\n public async search(\n tags: string | string[],\n {\n limit = 1,\n random = false,\n page = 0,\n showUnavailable = false,\n }: SearchParameters = {},\n ): Promise<SearchResults> {\n const fakeLimit: number = random && !this.site.random ? 100 : 0\n const tagArray = this.normalizeTags(tags)\n\n try {\n const searchResult = await this.doSearchRequest(tagArray, {\n limit,\n random,\n page,\n showUnavailable,\n })\n return this.parseSearchResult(searchResult, {\n fakeLimit,\n tags: tagArray,\n limit,\n random,\n page,\n showUnavailable,\n })\n } catch (err) {\n if (err instanceof Error) {\n throw new BooruError(err)\n }\n\n throw err\n }\n }\n\n /**\n * Gets the url you'd see in your browser from a post id for this booru\n *\n * @param {String} id The id to get the postView for\n * @return {String} The url to the post\n */\n public postView(id: string | number): string {\n if (typeof id === 'string' && Number.isNaN(Number.parseInt(id, 10))) {\n throw new BooruError(`Not a valid id for postView: ${id}`)\n }\n\n return `http${this.site.insecure ? '' : 's'}://${this.domain}${\n this.site.api.postView\n }${id}`\n }\n\n /**\n * Gets a list of tags from the booru\n * @param {Partial<TagsURLParams>} [params] The parameters for the tags list\n * @param {number} [params.limit=100] The limit of tags to return\n * @param {number} [params.page=1] The page of tags to return\n * @return {Promise<any[]>} A promise with the tags as an array\n */\n public async tagList({\n limit = 100,\n page = 1,\n }: Partial<TagsURLParams> = {}): Promise<TagListResults> {\n const url = this.getTagListUrl({ limit, page })\n const options = defaultOptions\n try {\n const response = await resolvedFetch(url, options)\n\n // Check for CloudFlare ratelimiting\n if (response.status === 503) {\n const body = await response.clone().text()\n if (body.includes('cf-browser-verification')) {\n throw new BooruError(\n \"Received a CloudFlare browser verification request. Can't proceed.\",\n )\n }\n }\n\n if (!response.ok) {\n throw new BooruError(\n `Received HTTP ${response.status} from booru: '${await response.text()}'`,\n )\n }\n\n const data = await response.text()\n /**\n * Many boorus don't support JSON parameter for tag listing\n * So attempt JSON parsing, but if it fails default to XML parsing\n **/\n let tags = []\n try {\n tags = tryParseJSON(data)\n } catch (_e) {\n tags = jsonifyTags(data)\n }\n\n return this.parseTagListResult(tags, { limit, page })\n } catch (err) {\n if ((err as any).type === 'invalid-json')\n if (err instanceof Error) {\n throw new BooruError(err)\n }\n\n throw err\n }\n }\n\n /**\n * The internal & common searching logic, pls dont use this use .search instead\n *\n * @protected\n * @param {String[]|String} tags The tags to search with\n * @param {InternalSearchParameters} searchArgs The arguments for the search\n * @return {Promise<Object>}\n */\n protected async doSearchRequest(\n tags: string[],\n {\n uri = null,\n limit = 1,\n random = false,\n page = 0,\n }: InternalSearchParameters = {},\n ): Promise<any> {\n // Used for random on sites without order:random\n let fakeLimit: number | undefined\n let searchTags = tags.slice()\n\n if (random) {\n if (this.site.random) {\n searchTags.push('order:random')\n } else {\n fakeLimit = 100\n }\n }\n\n if (this.site.defaultTags) {\n searchTags = searchTags.concat(\n this.site.defaultTags.filter((v) => !searchTags.includes(v)),\n )\n }\n\n const fetchuri =\n uri ??\n this.getSearchUrl({ tags: searchTags, limit: fakeLimit ?? limit, page })\n const options = defaultOptions\n const xml = this.site.type === 'xml'\n\n try {\n const response = await resolvedFetch(fetchuri, options)\n\n // Check for CloudFlare ratelimiting\n if (response.status === 503) {\n const body = await response.clone().text()\n if (body.includes('cf-browser-verification')) {\n throw new BooruError(\n \"Received a CloudFlare browser verification request. Can't proceed.\",\n )\n }\n }\n\n const data = await response.text()\n const posts = xml ? jsonifyPosts(data) : tryParseJSON(data)\n\n if (!response.ok) {\n throw new BooruError(\n `Received HTTP ${response.status} ` +\n `from booru: '${\n (posts as any).error ??\n (posts as any).message ??\n JSON.stringify(posts)\n }'`,\n )\n }\n\n return posts\n } catch (err) {\n if ((err as any).type === 'invalid-json') return ''\n throw err\n }\n }\n\n /**\n * Generates a URL to search the booru with, mostly for debugging purposes\n * @param opt\n * @param {string[]} [opt.tags] The tags to search for\n * @param {number} [opt.limit] The limit of results to return\n * @param {number} [opt.page] The page of results to return\n * @returns A URL to search the booru\n */\n getSearchUrl({\n tags = [],\n limit = 100,\n page = 1,\n }: Partial<SearchUrlParams> = {}): string {\n return searchURI(this.site, tags, limit, page, this.credentials)\n }\n\n /**\n * Generates a URL to get a list of tags from the booru\n * @param opt\n * @param {number} [opt.limit] The limit of tags to return\n * @param {number} [opt.page] The page of tags to return\n * @returns {string} A URL to get the tags list\n */\n getTagListUrl({\n limit = 100,\n page = 1,\n }: Partial<TagsURLParams> = {}): string {\n if (!this.site.api.tagList) {\n throw new BooruError(\n `This booru does not support tag listing: ${this.site.domain}`,\n )\n }\n return tagListURI(this.site, limit, page, this.credentials)\n }\n\n /**\n * Parse the response from the booru\n *\n * @protected\n * @param {Object} result The response of the booru\n * @param {InternalSearchParameters} searchArgs The arguments used for the search\n * @return {SearchResults} The results of this search\n */\n protected parseSearchResult(\n result: any,\n {\n fakeLimit,\n tags,\n limit,\n random,\n page,\n showUnavailable,\n }: InternalSearchParameters,\n ): SearchResults {\n let outResult = result\n\n if (outResult.success === false) {\n throw new BooruError(outResult.message ?? outResult.reason)\n }\n\n // Gelbooru\n if (outResult['@attributes']) {\n const attributes = outResult['@attributes']\n\n if (attributes.count === '0' || !outResult.post) {\n outResult = []\n } else if (Array.isArray(outResult.post)) {\n outResult = outResult.post\n } else {\n outResult = [outResult.post]\n }\n }\n\n if (outResult.posts) {\n outResult = outResult.posts\n }\n\n if (outResult.images) {\n outResult = outResult.images\n }\n\n let r: string[] | undefined\n // If gelbooru/other booru decides to return *nothing* instead of an empty array\n if (outResult === '') {\n r = []\n } else if (fakeLimit) {\n r = shuffle(outResult)\n } else if (outResult.constructor === Object) {\n // For XML based sites\n r = [outResult]\n }\n\n let posts: Post[] = (r ?? outResult)\n .slice(0, limit)\n .map((v: any) => new Post(v, this))\n const options = { limit, random, page, showUnavailable }\n\n if (tags === undefined) {\n tags = []\n }\n\n if (!showUnavailable) {\n posts = posts.filter((p) => p.available)\n }\n\n return new SearchResults(posts, tags, options, this)\n }\n\n /**\n * Parse the response from the booru for a tag list\n *\n * @param result\n * @param param1\n * @returns\n */\n protected parseTagListResult(\n result: any,\n { limit = 100, page = 1 }: Partial<TagsURLParams> = {},\n ): TagListResults {\n if (result.success === false) {\n throw new BooruError(result.message ?? result.reason)\n }\n\n let tags: any[] = []\n\n if (result) {\n if (Array.isArray(result)) {\n tags = result.map((v) => new Tag(v, this))\n } else {\n tags = [new Tag(result, this)]\n }\n }\n\n return new TagListResults(tags, { limit, page }, this)\n }\n}\n\nexport default Booru\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ import Post from './structures/Post';
|
|
|
9
9
|
import type SearchParameters from './structures/SearchParameters';
|
|
10
10
|
import SearchResults from './structures/SearchResults';
|
|
11
11
|
import Site from './structures/Site';
|
|
12
|
+
import type TagListParameters from './structures/TagListParameters';
|
|
13
|
+
import type TagListResults from './structures/TagListResults';
|
|
12
14
|
/**
|
|
13
15
|
* Create a new booru to search with
|
|
14
16
|
*
|
|
@@ -23,6 +25,9 @@ export default booruForSite;
|
|
|
23
25
|
export interface BooruSearch extends SearchParameters {
|
|
24
26
|
credentials?: BooruCredentials;
|
|
25
27
|
}
|
|
28
|
+
export interface BooruTagList extends TagListParameters {
|
|
29
|
+
credentials?: BooruCredentials;
|
|
30
|
+
}
|
|
26
31
|
/**
|
|
27
32
|
* Searches a site for images with tags and returns the results
|
|
28
33
|
* @param {String} site The site to search
|
|
@@ -39,6 +44,20 @@ export interface BooruSearch extends SearchParameters {
|
|
|
39
44
|
* ```
|
|
40
45
|
*/
|
|
41
46
|
export declare function search(site: string, tags?: string[] | string, { limit, random, page, credentials }?: BooruSearch): Promise<SearchResults>;
|
|
47
|
+
/**
|
|
48
|
+
* Get a list of tags from a site
|
|
49
|
+
* @param {String} site The site to get the tags from
|
|
50
|
+
* @param {TagListParameters} [options={}] The options for the tag list
|
|
51
|
+
* @return {Promise<TagListResults>} A promise with the tags as an array of objects
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```
|
|
55
|
+
* const Booru = require('booru')
|
|
56
|
+
* // Returns a promise with the first 100 tags from e926
|
|
57
|
+
* Booru.tagList('e926')
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function tagList(site: string, { limit, page, credentials }?: BooruTagList): Promise<TagListResults>;
|
|
42
61
|
/**
|
|
43
62
|
* Deprecated, now a noop
|
|
44
63
|
* <p>This will be removed *soon* please stop using it</p>
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAC7D,OAAO,UAAU,MAAM,qBAAqB,CAAA;AAC5C,OAAO,QAAQ,MAAM,mBAAmB,CAAA;AAExC,OAAO,IAAI,MAAM,mBAAmB,CAAA;AACpC,OAAO,KAAK,gBAAgB,MAAM,+BAA+B,CAAA;AACjE,OAAO,aAAa,MAAM,4BAA4B,CAAA;AACtD,OAAO,IAAI,MAAM,mBAAmB,CAAA;AACpC,OAAO,KAAK,iBAAiB,MAAM,gCAAgC,CAAA;AACnE,OAAO,KAAK,cAAc,MAAM,6BAA6B,CAAA;AAyB7D;;;;;;;GAOG;AACH,iBAAS,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,gBAAgB,GAAG,KAAK,CASzE;AAED,OAAO,EAAE,YAAY,IAAI,OAAO,EAAE,CAAA;AAClC,eAAe,YAAY,CAAA;AAE3B,MAAM,WAAW,WAAY,SAAQ,gBAAgB;IACnD,WAAW,CAAC,EAAE,gBAAgB,CAAA;CAC/B;AAED,MAAM,WAAW,YAAa,SAAQ,iBAAiB;IACrD,WAAW,CAAC,EAAE,gBAAgB,CAAA;CAC/B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,MAAM,EAAE,GAAG,MAAW,EAC5B,EAAE,KAAS,EAAE,MAAc,EAAE,IAAQ,EAAE,WAAgB,EAAE,GAAE,WAAgB,GAC1E,OAAO,CAAC,aAAa,CAAC,CA4BxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,EAAE,KAAS,EAAE,IAAQ,EAAE,WAAgB,EAAE,GAAE,YAAiB,GAC3D,OAAO,CAAC,cAAc,CAAC,CAezB;AAOD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAGxD;AAED,OAAO,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;AAC1D,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAA"}
|