You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
4.2 KiB
130 lines
4.2 KiB
/**
|
|
* Szurubooru api client
|
|
*/
|
|
|
|
let axios = require('axios');
|
|
let { logger } = require('../../logging');
|
|
|
|
function getRandomInt(min, max) {
|
|
min = Math.ceil(min);
|
|
max = Math.floor(max);
|
|
return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
|
|
}
|
|
|
|
class SzurubooruClient {
|
|
|
|
_randomSearchQueryValues = "type:image,animated,video sort:random";
|
|
_randomSearchUrlTemplate = "%s/posts/?offset=%s&limit=%d&query=%s";
|
|
|
|
constructor(url, username, token) {
|
|
this.url = url;
|
|
this.baseUrl = url.replace('/api', '');
|
|
this.username = username;
|
|
this.token = token;
|
|
this.updateRandomScope();
|
|
}
|
|
|
|
getRandomSearchUrl(offset, limit, tags = []) {
|
|
var searchQuery = this._randomSearchQueryValues;
|
|
if (tags !== null && tags.length > 0) {
|
|
searchQuery = this._randomSearchQueryValues + tags.join(" ");
|
|
}
|
|
return this.url + '/posts/?offset=' + offset + '&limit=' + limit + '&query=' + searchQuery;
|
|
}
|
|
|
|
/**
|
|
* Determine a sane range of offset values
|
|
*
|
|
* @param {*} limit The content limit of a single page
|
|
* @param {*} total The number of objects to search through
|
|
*/
|
|
getValidOffsetRange(limit, total) {
|
|
let offsetOverflow = total % limit;
|
|
var offsetCeiling = (Math.round(total / limit));
|
|
if (offsetOverflow === 0) {
|
|
offsetCeiling -= 1;
|
|
}
|
|
return [0, offsetCeiling];
|
|
}
|
|
|
|
|
|
/**
|
|
* Determine a random offset based on the potential random search size
|
|
*
|
|
* Because Szurubooru doesn't randomize each sort:random search request, we must
|
|
* manually calculate a random offset for each request to simulate randomness in the
|
|
* posts returned.
|
|
*
|
|
* @param {*} self
|
|
* @param {*} imageCount
|
|
*/
|
|
getRandomSearchParameters(imageCount = null) {
|
|
let resultLimit = 10;
|
|
var offsetRange = [0, 1];
|
|
if (imageCount === null) {
|
|
offsetRange = this.getValidOffsetRange(resultLimit, this.randomImageCount);
|
|
} else {
|
|
offsetRange = this.getValidOffsetRange(resultLimit, imageCount);
|
|
}
|
|
return [resultLimit, getRandomInt(offsetRange[0], offsetRange[1])];
|
|
}
|
|
|
|
|
|
async updateRandomScope() {
|
|
let client = this;
|
|
let target = this.getRandomSearchUrl(0, 1);
|
|
await this.makeGetRequest(target).then((result) => {
|
|
client.randomImageCount = result.total;
|
|
});
|
|
|
|
}
|
|
|
|
makeGetRequest(url) {
|
|
logger.debug("Making get request to %s", url);
|
|
return axios.get(url, {
|
|
headers: {
|
|
"Authorization": "Token " + Buffer.from(this.username + ':' + this.token).toString('base64'),
|
|
"Accept": "application/json"
|
|
}
|
|
}).then((response) => {
|
|
logger.debug("Recieved: %o", response.data);
|
|
return response.data;
|
|
}, (err) => {
|
|
logger.error("Unexpected client error: %o", err);
|
|
return null;
|
|
});
|
|
return self._handle_response("GET", url, None, response)
|
|
}
|
|
|
|
/**
|
|
* Return a random post matching the optionally provided tags.
|
|
*
|
|
* @param {*} self
|
|
* @param {*} tags
|
|
*/
|
|
getRandomPost(tags = []) {
|
|
let client = this;
|
|
var resultLimit = 0;
|
|
var randomSearchOffset = 0;
|
|
if (tags.length === 0) {
|
|
let randomSearchParameters = this.getRandomSearchParameters();
|
|
resultLimit = randomSearchParameters[0];
|
|
randomSearchOffset = randomSearchParameters[1];
|
|
}
|
|
let searchUrl = this.getRandomSearchUrl(randomSearchOffset, resultLimit, tags);
|
|
return this.makeGetRequest(searchUrl)
|
|
.then((data) => {
|
|
if (data !== null) {
|
|
let limitSpace = Math.min(resultLimit, data.results.length - 1);
|
|
let randomPost = data.results[getRandomInt(0, limitSpace)];
|
|
return client.baseUrl + '/' + randomPost.contentUrl;
|
|
} else {
|
|
return null
|
|
}
|
|
}, (err) => {
|
|
|
|
})
|
|
}
|
|
}
|
|
|
|
exports.Client = SzurubooruClient;
|