Gelbooru API in JSON

node v8.17.0
version: 8.0.0
endpointsharetweet
# Gelbooru API in JSON ## Usage ### https://runkit.io/pronow/gelbooru/8.0.0/ > Retuns "up" ### https://runkit.io/pronow/gelbooru/8.0.0/posts > Returns a list of posts Query - page : The page number (pid). - limit : How many posts you want to retrieve. There is a hard limit of 100 posts per request. - tags : The tags to search for. Any tag combination that works on the web site will work here. This includes all the meta-tags. See cheatsheet for more information. ### https://runkit.io/pronow/gelbooru/8.0.0/posts/:id > Returns one post by id Param - id : the id of the post ### https://runkit.io/pronow/gelbooru/8.0.0/tags/:name > Returns a list of matching tags with the stat Param - name: the name of the tag. Use * as a wildcard. Query - sort : can be 'asc' or 'desc'. - order : can be - updated : by date - tag : by alphabetic order for tag names - type : by alphabetic order for type names - index_count : by post count number ### https://runkit.io/pronow/gelbooru/8.0.0/macro/characters/:name > Returns character oriented full description The full description has : - the name - an extract of each ratings (s,q,e) Param - name: the tag of the character.
// var express = require('@runkit/runkit/express-endpoint/1.0.0') var app = express(exports) const assert = require('assert') const bodyParser = require('body-parser') const statuses = require('statuses') const cors = require('cors') const Promise = require('bluebird') const cheerio = require('cheerio') const _debug = require('debug') _debug.enable('*') const debug = _debug('gelbooru') const superagent = require("superagent"); // _debug.log = console.log.bind(console) Promise.config({ longStackTraces: true }) const BASE_URL = 'http://gelbooru.com/index.php' function TooMutchResultError() {} TooMutchResultError.prototype = Object.create(Error.prototype); function NotFoundError() {} TooMutchResultError.prototype = Object.create(Error.prototype); // app.use(cors()) // http://gelbooru.com/index.php?page=dapi&s=post&q=index app.get('/', (req, res) => res.send('up')) // http://gelbooru.com/index.php?page=dapi&s=post&q=index app.get('/posts', getLatestPosts) app.get('/posts/:id', getPostById) // http://gelbooru.com/index.php?page=tags&s=list&tags=nami_*&sort=desc&order_by=index_count app.get('/tags/:name', getTagsStats) app.get('/macro/characters/:name', getMacroOfCharacter) app.use(errorHandler) // function getLatestPosts (req, res, next) { debug('getLatestPosts') const page = Math.max(0, Number(req.query.page) || 0) const limit = Math.max(0, Number(req.query.limit) || 100) const tags = false || typeof req.query.tags === 'string' ? [req.query.tags] : req.query.tags || [] return Promise.resolve() .then(() => queryGelbooruPosts({ limit, page, tags })) .then((result) => res.send(result)) .catch(next) } function getPostById (req, res, next) { debug('getPostById') const id = Math.max(0, Number(req.params.id) || 0) return Promise.resolve() .then(() => asyncRequest(`${BASE_URL}?page=dapi&s=post&q=index&id=${id}`)) .then((xml) => cheerio.load(xml, { normalizeWhitespace: true, xmlMode: true })) .then(format$ToPostData) .then((result) => res.send(result)) .catch(next) } function getTagsStats (req, res, next) { debug('getTagsStats') const name = req.params.name const {order, sort} = req.query return Promise.resolve() .then(() => queryGelbooruTags( name, { order, sort } )) .catch(TooMutchResultError, () => { return Promise.reject({ status: 413 }) }) .then((result) => res.send(result)) .catch(next) } function getMacroOfCharacter (req, res, next) { debug('getMacroOfCharacter') const name = req.params.name return Promise.resolve() .then(() => macroCharacterQuery(name)) .catch(() => { return Promise.reject({ status: 404 }) }) .then((result) => res.send(result)) .catch(next) } // // BUISNESS // function queryGelbooruPosts (options) { debug('queryGelbooruPosts options=%j', options) const { limit, page, tags } = options return Promise.resolve() .then(() => asyncRequest(`${BASE_URL}?page=dapi&s=post&q=index&pid=${page}&tags=${tags.join('+')}&limit=${limit}`)) .then((xml) => cheerio.load(xml, { normalizeWhitespace: true, xmlMode: true })) .then(format$ToPostList) .then((result) => Object.assign(result, {page: page})) } function queryGelbooruTags (name, options) { debug('queryGelbooruTags name=%s options=%j', name, options) const {order, sort} = options return Promise.resolve() .then(() => asyncRequest(`${BASE_URL}?page=tags&s=list&tags=${name}&sort=${sort}&order_by=${order}`)) .then((rawHtml) => cheerio.load(rawHtml, {})) .then(format$ToTagList) .then((resultTaglList) => { let hasError = resultTaglList.length === 1 hasError &= !resultTaglList[0].type hasError &= !resultTaglList[0].posts if (hasError) { const msg = resultTaglList[0].name if (/No results found/i.test(msg)) { return [] } throw new TooMutchResultError() } return resultTaglList }) } function macroCharacterQuery (name) { debug('macroCharacterQuery name=%s', name) return Promise.resolve() .then(() => queryGelbooruTags( name, {order: 'asc', sort: 'tag'} )) .then((resultTagList) => resultTagList.filter((tag) => tag.type === 'character') ) .then((characterTagList) => { if (characterTagList.length != 1) { throw new NotFoundError() } return characterTagList[0] }) .then(({name, posts}) => Promise.props({ name, posts, ratings: Promise.props({ safe: queryGelbooruPosts({tags: [name, 'rating:safe']}), questionable: queryGelbooruPosts({tags: [name, 'rating:questionable']}), explicit: queryGelbooruPosts({tags: [name, 'rating:explicit']}) }) }) ) } // // SERVICES // function asyncRequest (uri) { debug('asyncRequest uri=%s', uri) return new Promise ((resolve, reject) => { superagent .get(uri) .end(function (err, response) { if (err) { return reject(err) } return resolve(response.text) }) }) } // // FORMATTERS // function format$ToPostList ($) { debug('format$ToPostList') return { total: +$('posts').attr('count'), count: $('posts').children().length, posts: $('posts').children().map(function () { const attrs = $(this).attr(); // https://simg3.gelbooru.com/ urls have to be replaced by https://simg3.gelbooru.com// // so gelbooru doesn't 403 us. const override = Object.entries(attrs) .reduce((memo, [key, value]) => Object.assign({}, memo, { [key]: value.replace('https://simg3.gelbooru.com/', 'https://simg3.gelbooru.com//') }), {}) return Object.assign({}, attrs, override) }).toArray() }; } function format$ToPostData ($) { debug('format$ToPostData') return $('posts').children().first().attr() } function format$ToTagList ($) { debug('format$ToTagList') const $tagTable = $('table.highlightable', '#content') return $tagTable.children('tr') .slice(1) // Remove first header line .map((i, el) => { const $td = $(el).children('td') let posts = $td.eq(0).text() let name = $td.eq(1).text() let type = $td.eq(2).text() type = (type || '').replace(' (edit)', '') posts = Number(posts) return {name, posts, type} }) .toArray() } // function errorHandler (err, req, res, next) { debug('errorHandler') const status = err.status || err.statusCode || 500 const body = { status: status, message: statuses[status] } if (err.stack) body.stack = err.stack if (err.code) body.code = err.code if (err.name) body.name = err.name if (err.type) body.type = err.type res.status(status).json(body) } debug('listening') 'started'
Loading…

no comments

    sign in to comment