Comparing version 1.4.8 to 2.0.0
{ | ||
"name": "danbooru", | ||
"version": "1.4.8", | ||
"version": "2.0.0", | ||
"description": "danbooru api wrapper", | ||
"main": "lib/index.js", | ||
"main": "index.js", | ||
"directories": { | ||
"test": "test" | ||
}, | ||
"scripts": { | ||
"build": "lsc -o lib src", | ||
"doctoc": "doctoc --notitle README.md", | ||
"clean": "rm -rf lib", | ||
"test": "lsc test", | ||
"prepublish": "npm run build", | ||
"postpublish": "npm run clean" | ||
"test": "tape test/*" | ||
}, | ||
@@ -19,20 +17,9 @@ "repository": { | ||
"keywords": [ | ||
"wrapper", | ||
"tags", | ||
"tag", | ||
"search", | ||
"posts", | ||
"post", | ||
"manga", | ||
"images", | ||
"image", | ||
"gallery", | ||
"favorites", | ||
"favorite", | ||
"danbooru", | ||
"booru", | ||
"api", | ||
"anime" | ||
"image", | ||
"anime", | ||
"manga" | ||
], | ||
"author": "Pudding <aideen@aideen.pw> (https://aideen.pw)", | ||
"license": "ISC", | ||
@@ -43,13 +30,7 @@ "bugs": { | ||
"homepage": "https://github.com/stawberri/danbooru-node#readme", | ||
"author": "Pudding <aideen@aideen.pw> (https://aideen.pw/)", | ||
"devDependencies": { | ||
"doctoc": "^1.0.0", | ||
"livescript": "^1.4.0", | ||
"nock": "^7.2.2", | ||
"tape": "^4.5.1" | ||
}, | ||
"dependencies": { | ||
"args-js": "^0.10.11", | ||
"extend": "^3.0.0", | ||
"request": "^2.69.0" | ||
"nock": "^9.0.13", | ||
"tape": "^4.6.3" | ||
} | ||
} |
329
README.md
@@ -7,194 +7,223 @@ # danbooru-node | ||
My api wrapper is super simple! You just require it, then refer to [Danbooru's lovely api documentation](https://danbooru.donmai.us/wiki_pages/43568) and make requests! | ||
```javascript | ||
Danbooru = require('danbooru'); | ||
This package is an api wrapper intended to make [Danbooru's api](https://danbooru.donmai.us/wiki_pages/43568) even easier to work with. | ||
Danbooru.search('rating:s order:rank', function(err, data) { | ||
data.random() | ||
.getLarge() | ||
.pipe(require('fs').createWriteStream('random.jpg')); | ||
}); | ||
```js | ||
const Danbooru = require('danbooru') | ||
let booru = new Danbooru() | ||
booru.posts('fox_ears smile').then(async posts => { | ||
let file = posts[0].file | ||
let data = await file.download() | ||
require('fs').writeFile(file.name, data)) | ||
}) | ||
``` | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
This module has been updated to require Node.js 7. You can still install version 1 with `npm install danbooru@1` and [read its documentation on Github](https://github.com/stawberri/danbooru-node/tree/v1.4.8). | ||
- [Making requests](#making-requests) | ||
- [Danbooru.method([path], [params], [callback])](#danboorumethodpath-params-callback) | ||
- [Danbooru.request([options], [callback])](#danboorurequestoptions-callback) | ||
- [Authentication](#authentication) | ||
- [[new] Danbooru([object], [api_key])](#new-danbooruobject-api_key) | ||
- [Searching](#searching) | ||
- [Danbooru.search([tags], [params], [callback])](#danboorusearchtags-params-callback) | ||
- [searchData](#searchdata) | ||
- [searchData.page](#searchdatapage) | ||
- [searchData.load([page], [callback])](#searchdataloadpage-callback) | ||
- [searchData.next([modifier], [callback])](#searchdatanextmodifier-callback) | ||
- [searchData.prev([modifier], [callback])](#searchdataprevmodifier-callback) | ||
- [searchData.tags](#searchdatatags) | ||
- [searchData.add([tagMod], [callback])](#searchdataaddtagmod-callback) | ||
- [searchData.add([tagMod], [callback])](#searchdataaddtagmod-callback-1) | ||
- [searchData.random()](#searchdatarandom) | ||
- [post](#post) | ||
- [post.get([callback])](#postgetcallback) | ||
- [post.getLarge([callback])](#postgetlargecallback) | ||
- [post.getPreview([callback])](#postgetpreviewcallback) | ||
- [post.favorite([yes], [callback])](#postfavoriteyes-callback) | ||
- [post.url](#posturl) | ||
## Danbooru class | ||
This module exposes the `Danbooru` class. Instantiating it with no arguments creates an unauthenticated session, while passing it parameters allows you to log in. You can also specify an alternate base url. Your `api_key` is not your password, and you can find it on your profile page. | ||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
```js | ||
// Unauthenticated session | ||
let booru = new Danbooru() | ||
## Making requests | ||
// Login to your account with your username and api_key | ||
let booru = new Danbooru('login', 'api_key') | ||
```javascript | ||
Danbooru.get('posts', {limit: 5, tags: 'cat_ears'}, function(err, data) { | ||
if(err) throw err; | ||
console.log(data); // All of your cute kittehgirls! | ||
}); | ||
// Optionally provide a base url to use a different server | ||
let booru = new Danbooru({ | ||
login: 'login', | ||
api_key: 'api_key', | ||
base: 'http://sonohara.donmai.us' | ||
}) | ||
// Specify all three in one string | ||
let booru = new Danbooru(`http://login:api_key@sonohara.donmai.us`) | ||
``` | ||
You can also use `Danbooru.post()`, `Danbooru.put()`, and `Danbooru.delete()`. They all have the same parameters and give you the same callback! | ||
### Safebooru subclass | ||
### Danbooru.method([path], [params], [callback]) | ||
Perform a http request on Danbooru's api! | ||
* `method` _property_. One of `get`, `post`, `put`, or `delete`, depending on what type of request you would like to make. | ||
* `path` _string_. The API documentation mentions a base URL. You put that here! The slash and `.json` are optional. In fact, the entire thing is optional, but you won't get anything useful from omitting path. | ||
* `params` _object_. Just provide your parameters as an object! | ||
* `callback` _function(err, data)_. What do you wannya do after you get your api request? | ||
- `err` _Error_. Node.js callbacks always give you an error for some reason. Here you go! | ||
- `data` _object_. Parsing JSON output is an extra step, so you don't hafta do it! Here's an already-parsed object for you! | ||
A `Safebooru` subclass is available that locks the base url to `https://safebooru.donmai.us`. This alternate server only serves "safe" images. Please refer to [Danbooru's definition of safe](https://danbooru.donmai.us/wiki_pages/10920), and remember that ratings for most posts can be changed by anyone. | ||
### Danbooru.request([options], [callback]) | ||
A simple wrapper function for [request](https://www.npmjs.com/package/request), with `baseUrl` always set to Danbooru. Refer to [their documentation](https://www.npmjs.com/package/request#requestoptions-callback) for details. | ||
* `options` _string_. _object_. A url or options for your request. | ||
* `callback` _function(err, response, body)_. Callback function. `response` is a usual node HTTP response, while `body` is the body of that response, ready for using. | ||
* **returns** _request_. Request object. | ||
```js | ||
// Unauthenticated safe images session | ||
let booru = new Danbooru.Safebooru() | ||
I'm providing this to give you an easy way to download images and make custom requests without having to type Danbooru's url: | ||
// Login, but still only see safe posts | ||
let booru = new Danbooru.Safebooru('login', 'api_key') | ||
``` | ||
```javascript | ||
Danbooru.request('/data/9b5d16968321eff393fea8d735d69de3.jpg') | ||
.pipe(fs.create-write-stream('cutiefox.jpg')); | ||
## Image posts | ||
Images on Danbooru come with a bunch of tags and other metadata. These are bundled into packages called posts. There are two functions available to you to find them. | ||
### Searching for posts | ||
You can search for a tag string, or choose to use the full set of post listing parameters Danbooru makes available through its api. You may wish to refer to [Danbooru's search cheat sheet](https://danbooru.donmai.us/wiki_pages/43049) to decide on your search query. | ||
This function returns a promise that resolves to an array of posts. | ||
```js | ||
// Perform a simple search for a tag string or array of tags | ||
let postArray = await booru.posts('fox_ears smile') | ||
let postArray = await booru.posts(['fox_ears', 'smile']) | ||
// Specify parameters | ||
let postArray = await booru.posts({ | ||
limit: 100, | ||
page: 1, | ||
tags: 'fox_ears smile', | ||
random: true | ||
}) | ||
``` | ||
## Authentication | ||
You know what's a pain? Having to type the same stuff over and over again. You know what you hafta do if you want to be authenticated on Danbooru? Send your `login` and `api_key` over and over again. | ||
### Fetching a post | ||
If you know the numerical ID of a post, you can fetch it directly. This function returns a promise that resolves to a single post. | ||
```javascript | ||
authedBooru = new Danbooru({login: 'topsecret', api_key: 'evenmoresecret'}); | ||
authedBooru.post('favorites', {post_id: 2288637}, function(err, data) { | ||
if(err) throw err; | ||
console.log('Successfully favorited!'); // Wow, you do like kittehgirls! | ||
}); | ||
```js | ||
// Fetch a single post | ||
let post = await booru.posts.get(2689871) | ||
``` | ||
If that's still too much typing for you, you can use a shortcut! | ||
```javascript | ||
shortBooru = Danbooru('topsecret', 'evenmoresecret'); | ||
### Post object | ||
This module parses posts and restructures them into an instance of `Post`. | ||
```js | ||
// Get the id of a post as an integer or a string | ||
let id = post.id | ||
let id = +post | ||
let id = String(post) | ||
// Get a post's raw data, as received from the server | ||
let data = post.raw | ||
// Look up a post's tags | ||
let tags = post.tags | ||
// Break up a post's tags into categories | ||
let artists = post.tags.artist | ||
let characters = post.tags.character | ||
let copyrights = post.tags.copyright | ||
let otherTags = post.tags.general | ||
// Get a post's rating as a boolean | ||
let isSafe = post.rating.s | ||
let isSafe = post.rating.safe | ||
let isQuestionable = post.rating.q | ||
let isQuestionable = post.rating.questionable | ||
let isExplicit = post.rating.e | ||
let isExplicit = post.rating.explicit | ||
// Or get it as a string | ||
String(post.rating) === 's' | ||
``` | ||
### [new] Danbooru([object], [api_key]) | ||
Save parameters for later. Returns a new Danbooru object that you can use to make requests with those saved parameters. | ||
* `object` _object_. _string_. If you provide an object, it'll be used as default parameters for all requests you make! If you provide a string, it'll set your default `login` parameter to whatever you provide! If you provide neither, you'll create a new, empty `Danbooru` object. | ||
* `api_key` _string_. If (and only if) you provided a string for `object`, this will be used as your default `api_key` parameter! | ||
### Download object | ||
Posts have a download object meant to make downloading files easier. You can access it with `post.file`. | ||
## Searching | ||
Note that you may occasionally encounter posts that have been deleted or marked as unavailable due to their tags. In this case, `post.file` will still return an object, but it will be missing most of its properties. | ||
"But wait," you say, "APIs are supposed to help make my life easier! Why do I still have to type so much?" Well, I made a helper function called `.search()` for you, and as a bonus, its data object even gives you extra helper functions to get around more easily! The helper functions are also returned by `.search()`, so you can chain more nicely! | ||
```js | ||
// Fetch a post's file object | ||
let file = post.file | ||
// Check if it's actually available first | ||
if(!('request' in file)) return | ||
```javascript | ||
Danbooru.search('1girl fox_ears', function(err, page1) { | ||
if(err) throw err; | ||
console.log(page1); // Foxgirls! | ||
}).next(function(err, page2) { | ||
if(err) throw err; | ||
console.log(page2); // More foxgirls! | ||
page2.next(function(err, page3) { | ||
if(err) throw err; | ||
console.log(page3); // So many foxgirls~ ♥ | ||
}); | ||
}); | ||
// Get some details about the file | ||
let filename = file.name | ||
let fileExtension = file.ext | ||
let width = file.width | ||
let height = file.height | ||
let md5 = file.md5 | ||
let size = file.size | ||
// Start a http request for the file | ||
// let httpResponse = file.request() | ||
// Or just get its data in a promise! | ||
let dataPromise = file.download() | ||
// Keep track of its download progress | ||
dataPromise.data((bytesDownloaded, bytesTotal) => { | ||
let percent = 100 * bytesDownloaded/bytesTotal | ||
console.log(`Currently downloaded ${percent}%`) | ||
}) | ||
// then() or await the promise to get a buffer of your image | ||
let dataBuffer = await dataPromise | ||
// You can also cancel a download | ||
// dataPromise.abort() | ||
``` | ||
### Danbooru.search([tags], [params], [callback]) | ||
Perform a search on Danbooru. A shortcut for `Danbooru.get('posts', {tags: tags, limit: 100, ...params}, callback)`, but also adds on extra methods to the data object you get. Visit [an api result](https://danbooru.donmai.us/posts.json?tags=fox_ears&limit=2) in your browser to inspect the data object provided. | ||
* `tags` _string_. A space separated list of tags, and basically your Danbooru search query. You can try out your query visually on [Danbooru](https://danbooru.donmai.us/) or look up their [searching reference](https://danbooru.donmai.us/wiki_pages/43049) if you're not sure what to type. | ||
* `params` _object_. These are just parameters that will be directly passed to Danbooru's API. It will contain `limit: 100` | ||
by default, but you can change the number of posts you want by specifying it. Trying to specify `tags` won't do anything, because the `tags` parameter always overwrites the value of `tags` here, even if `tags` is empty or missing (which makes it default to empty). | ||
* `callback` _function(err, searchData)_ Do something after your request comes back. | ||
- `err` _Error_. Like always, an error object if there was one. | ||
- `searchData` _object_. Whatever Danbooru's API returns, but with some extra methods and properties. More details below! | ||
* **returns** _object_. Contains only my extra helper methods and properties from `searchData`. Also details below~ | ||
Posts also have a `preview` thumbnail image, and a `large` preview image that is used on post pages if the actual image is too large. | ||
### searchData | ||
Like I've said probably three times already, this data object is the one that Danbooru's api gives you, but with some nice helper functions! You can see sample API output by [visiting Danbooru](https://danbooru.donmai.us/posts.json?tags=fox_ears&limit=2). I haven't told you what the methods are yet, so~ | ||
```js | ||
// Get thumbnail image | ||
let preview = post.file.preview | ||
// Preview images have less data associated with them | ||
// This set of data is also available to large preview images | ||
let name = preview.name | ||
let extension = preview.ext | ||
let response = preview.request() | ||
let data = preview.download() | ||
#### searchData.page | ||
This is a property that tells you what your current page number is. You can't change it. | ||
// Large preview images do not always exist, so check if they exist first. | ||
if('large' in post.file) { | ||
let largePreview = post.file.large | ||
let largeBuffer = await largePreview.download() | ||
} | ||
``` | ||
#### searchData.load([page], [callback]) | ||
Calls `Danbooru.search()` again with the same tags and parameters as last time, but with the page of results you want! Trying to load a page number less than 1 will just set it to 1. | ||
* `page` _number_. What page of results would you like? Defaults to your current page, so you can actually use `searchData.load(callback)` to refresh your data. | ||
* `callback` _function(err, searchData)_. This literally gives you the same type of object as the `searchData` you're currently looking at. | ||
#### searchData.next([modifier], [callback]) | ||
Calls `searchData.load(this.page + modifier, callback)`, which basically increases your page number by your specified modifier. This will usually give you older posts (unless you specify a negative modifier for some reason). | ||
* `modifier` _number_. What number would you like to increment your page number by? | ||
* `callback` _function(err, searchData)_. Same as above. | ||
## Favorites | ||
The `Danbooru` object exposes a function for fetching and setting favorites. | ||
#### searchData.prev([modifier], [callback]) | ||
Calls `searchData.load(this.page - modifier, callback)`, which basically decreases your page number by your specified modifier. This will usually give you newer posts (unless you specify a negative modifier for some reason). | ||
* `modifier` _number_. What number would you like to decrement your page number by? | ||
* `callback` _function(err, searchData)_. Same as above. | ||
This will throw an error with an unauthenticated session. | ||
#### searchData.tags | ||
This is a property that tells you what tags your search is currently for. You can't change it. | ||
```js | ||
// Get a post array of your favorites | ||
let favoriteArray = await booru.favorites() | ||
#### searchData.add([tagMod], [callback]) | ||
Calls `Danbooru.search()` again with the same parameters as last time, but with your `tagMod` added to the end of your `tags` and `page` set back to 1. | ||
* `tagMod` _string_. This basically just takes your current tags and then adds these tags to it. In other words, effectively `Danbooru.search(searchData.tags + " " + tagMod, params, callback)`. | ||
* `callback` _function(err, searchData)_. Meow. | ||
// Add a favorite | ||
// Returns a promise that resolves true on success, throws on error | ||
let success = await booru.favorites.add(2689871) | ||
let success = await booru.favorites.add(post) // Or use a post object | ||
#### searchData.add([tagMod], [callback]) | ||
Calls `Danbooru.search()` again with the same parameters as last time, removing the tags in your `tagMod` from `tags` and `page` set back to 1. | ||
* `tagMod` _string_. This list of tags is separated by spaces, and then any tags here are removed from your tags for your new search. | ||
* `callback` _function(err, searchData)_. Nyaa. | ||
// Remove a favorite | ||
let success = await booru.favorites.delete(2689871, false) | ||
let success = await booru.favorites.delete(post, false) | ||
``` | ||
#### searchData.random() | ||
Gives you a random post from the set of posts you've found. Doesn't return anything when you don't have any posts. | ||
* **returns** _object_. A random post from `searchData`. | ||
### post | ||
When you're searching, you're probably looking for posts. When you're looking for posts, you probably wannya make get requests to their image URLs to be able to use them. Rather than make you write `Danbooru.request(post.file_url)` over and over again, how about we make things simpler for you? This example uses `random`, but you could also just go to any valid index and it would still work. | ||
## Custom requests | ||
This api wrapper is still missing a lot of things, so you can use its request method directly to access endpoints that haven't been wrapped yet. | ||
```javascript | ||
authBooru = new Danbooru('maidlover', 'maidsarecute'); | ||
authBooru.search('maid', function(err, data) { | ||
if(err) throw err; | ||
data.random().favorite(); // Favoriting a random maid~ H-how bold! | ||
}); | ||
This function call returns a promise that resolves to a parsed json object. Any error encountered while trying to generate this object will be rejected. | ||
```js | ||
let objectPromise = booru.requestJson('METHOD path', {parameters}) | ||
``` | ||
#### post.get([callback]) | ||
This does a get request to your post's `file_url`, which is usually your post's full size image. This also uses [request](https://www.npmjs.com/package/request), just like `Danbooru.request()`. | ||
* `callback` _function(err, response, body)_. Callback function. `response` is a usual node HTTP response, while `body` is your image data. | ||
* **returns** _request_. Request object. | ||
* objectPromise: A promise of the results of your api call | ||
* method: `GET`, `POST`, `PUT`, or `DELETE`. If you leave this out, it'll be a `GET` request. | ||
* path: Your api endpoint. The beginning slash and `.json` are optional. | ||
* parameters: If this is a get request, this will be added to your querystring. It supports nested objects and arrays. If this is another type of request, it'll be sent as a json body. | ||
#### post.getLarge([callback]) | ||
This does a get request to your post's `large_file_url`, which is a large image appropriate for browsers, but not original size. It's sometimes the same image as `file_url`. This also uses [request](https://www.npmjs.com/package/request), just like `Danbooru.request()`. | ||
* `callback` _function(err, response, body)_. Callback function. `response` is a usual node HTTP response, while `body` is your image data. | ||
* **returns** _request_. Request object. | ||
```js | ||
// GET /posts.json | ||
let data = await booru.requestJson('posts') | ||
#### post.getPreview([callback]) | ||
This does a get request to your post's `preview_file_url`, which is usually your post's tiny preview image, useful for thumbnails. This also uses [request](https://www.npmjs.com/package/request), just like `Danbooru.request()`. | ||
* `callback` _function(err, response, body)_. Callback function. `response` is a usual node HTTP response, while `body` is your image data. | ||
* **returns** _request_. Request object. | ||
// GET /posts.json?limit=5&tags=1girl | ||
let data = await booru.requestJson('posts', {limit: 5, tags: '1girl'}) | ||
#### post.favorite([yes], [callback]) | ||
This function only really works with an authenticated Danbooru object, but you can use it to quickly favorite or unfavorite a post! | ||
* `yes` _boolean_. Defaults to yes. Pass `false` to perform an unfavorite instead. | ||
* `callback` _function(err, data)_. It's a callback. | ||
// GET /artists.json?search[id]=135024&search[is_active]=true | ||
let data = await booru.requestJson('artists', { | ||
search: { | ||
id: 135024, | ||
is_active: true | ||
} | ||
}) | ||
#### post.url | ||
This property contains a human friendly post url. This is where you would find this post if you were manually browsing Danbooru in a browser. | ||
// POST /favorites.json | ||
// body: {"post_id": 2689871} | ||
let data = await booru.requestJson('POST favorites', {post_id: 2689871}) | ||
// DELETE /favorites/2689871.json | ||
let data = await booru.requestJson('DELETE favorites/2689871') | ||
``` |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
0
2
10
538
229
25551
3
- Removedargs-js@^0.10.11
- Removedextend@^3.0.0
- Removedrequest@^2.69.0
- Removedajv@6.12.6(transitive)
- Removedargs-js@0.10.12(transitive)
- Removedasn1@0.2.6(transitive)
- Removedassert-plus@1.0.0(transitive)
- Removedasynckit@0.4.0(transitive)
- Removedaws-sign2@0.7.0(transitive)
- Removedaws4@1.13.2(transitive)
- Removedbcrypt-pbkdf@1.0.2(transitive)
- Removedcaseless@0.12.0(transitive)
- Removedcombined-stream@1.0.8(transitive)
- Removedcore-util-is@1.0.2(transitive)
- Removeddashdash@1.14.1(transitive)
- Removeddelayed-stream@1.0.0(transitive)
- Removedecc-jsbn@0.1.2(transitive)
- Removedextend@3.0.2(transitive)
- Removedextsprintf@1.3.0(transitive)
- Removedfast-deep-equal@3.1.3(transitive)
- Removedfast-json-stable-stringify@2.1.0(transitive)
- Removedforever-agent@0.6.1(transitive)
- Removedform-data@2.3.3(transitive)
- Removedgetpass@0.1.7(transitive)
- Removedhar-schema@2.0.0(transitive)
- Removedhar-validator@5.1.5(transitive)
- Removedhttp-signature@1.2.0(transitive)
- Removedis-typedarray@1.0.0(transitive)
- Removedisstream@0.1.2(transitive)
- Removedjsbn@0.1.1(transitive)
- Removedjson-schema@0.4.0(transitive)
- Removedjson-schema-traverse@0.4.1(transitive)
- Removedjson-stringify-safe@5.0.1(transitive)
- Removedjsprim@1.4.2(transitive)
- Removedmime-db@1.52.0(transitive)
- Removedmime-types@2.1.35(transitive)
- Removedoauth-sign@0.9.0(transitive)
- Removedperformance-now@2.1.0(transitive)
- Removedpsl@1.15.0(transitive)
- Removedpunycode@2.3.1(transitive)
- Removedqs@6.5.3(transitive)
- Removedrequest@2.88.2(transitive)
- Removedsafe-buffer@5.2.1(transitive)
- Removedsafer-buffer@2.1.2(transitive)
- Removedsshpk@1.18.0(transitive)
- Removedtough-cookie@2.5.0(transitive)
- Removedtunnel-agent@0.6.0(transitive)
- Removedtweetnacl@0.14.5(transitive)
- Removeduri-js@4.4.1(transitive)
- Removeduuid@3.4.0(transitive)
- Removedverror@1.10.0(transitive)