151 lines
5.0 KiB
JavaScript
151 lines
5.0 KiB
JavaScript
import Service from 'resource:///com/github/Aylur/ags/service.js';
|
|
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
|
|
|
// Note: this service is made mainly for waifu.im. Others might work but not as properly
|
|
const APISERVICES = {
|
|
'im': {
|
|
'endpoint': 'https://api.waifu.im/search',
|
|
'headers': { 'Accept-Version': 'v5' },
|
|
},
|
|
'nekos': {
|
|
'endpoint': 'https://nekos.life/api/neko',
|
|
'headers': {},
|
|
},
|
|
'pics': {
|
|
'endpoint': 'https://api.waifu.pics/sfw/',
|
|
'headers': {},
|
|
},
|
|
};
|
|
|
|
function paramStringFromObj(params) {
|
|
return Object.entries(params)
|
|
.map(([key, value]) => {
|
|
if (Array.isArray(value)) { // If it's an array, repeat
|
|
if (value.length == 0) return '';
|
|
let thisKey = `${encodeURIComponent(key)}=${encodeURIComponent(value[0])}`
|
|
for (let i = 1; i < value.length; i++) {
|
|
thisKey += `&${encodeURIComponent(key)}=${encodeURIComponent(value[i])}`;
|
|
}
|
|
return thisKey;
|
|
}
|
|
return `${key}=${value}`;
|
|
})
|
|
.join('&');
|
|
}
|
|
|
|
class WaifuService extends Service {
|
|
_baseUrl = 'https://api.waifu.im/search';
|
|
_mode = 'im'; // Allowed: im
|
|
_responses = [];
|
|
_queries = [];
|
|
_nsfw = false;
|
|
_minHeight = 600;
|
|
|
|
static {
|
|
Service.register(this, {
|
|
'initialized': [],
|
|
'clear': [],
|
|
'newResponse': ['int'],
|
|
'updateResponse': ['int'],
|
|
});
|
|
}
|
|
|
|
constructor() {
|
|
super();
|
|
this.emit('initialized');
|
|
}
|
|
|
|
clear() {
|
|
this._responses = [];
|
|
this._queries = [];
|
|
this.emit('clear');
|
|
}
|
|
|
|
get mode() { return this._mode }
|
|
set mode(value) {
|
|
this._mode = value;
|
|
this._baseUrl = APISERVICES[this._mode].endpoint;
|
|
}
|
|
get nsfw() { return this._nsfw }
|
|
set nsfw(value) { this._nsfw = value }
|
|
get queries() { return this._queries }
|
|
get responses() { return this._responses }
|
|
|
|
async fetch(msg) {
|
|
// Init
|
|
const userArgs = msg.split(/\s+/);
|
|
|
|
let taglist = [];
|
|
this._nsfw = false;
|
|
// Construct body/headers
|
|
for (let i = 0; i < userArgs.length; i++) {
|
|
const thisArg = userArgs[i].trim();
|
|
if (thisArg.length == 0) continue;
|
|
if (thisArg == '--im') this._mode = 'im';
|
|
else if (thisArg == '--nekos') this._mode = 'nekos';
|
|
else if (thisArg.includes('pics')) this._mode = 'pics';
|
|
else if (thisArg.includes('segs') || thisArg.includes('sex') || thisArg.includes('lewd')) this._nsfw = true;
|
|
else {
|
|
taglist.push(thisArg);
|
|
if (['ecchi', 'hentai', 'ero', 'ass', 'paizuri', 'oral', 'milf'].includes(thisArg)) this._nsfw = true;
|
|
}
|
|
}
|
|
const newMessageId = this._queries.length;
|
|
this._queries.push(taglist);
|
|
this.emit('newResponse', newMessageId);
|
|
const params = {
|
|
'included_tags': taglist,
|
|
'height': `>=${this._minHeight}`,
|
|
'nsfw': this._nsfw,
|
|
};
|
|
const paramString = paramStringFromObj(params);
|
|
// Fetch
|
|
// Note: body isn't included since passing directly to url is more reliable
|
|
const options = {
|
|
method: 'GET',
|
|
headers: APISERVICES[this._mode].headers,
|
|
};
|
|
let status = 0;
|
|
Utils.fetch(`${APISERVICES[this._mode].endpoint}?${paramString}`, options)
|
|
.then(result => {
|
|
status = result.status;
|
|
return result.text();
|
|
})
|
|
.then((dataString) => { // Store interesting stuff and emit
|
|
const parsedData = JSON.parse(dataString);
|
|
if (!parsedData.images) this._responses.push({ // Failed
|
|
status: status,
|
|
signature: -1,
|
|
url: '',
|
|
extension: '',
|
|
source: '',
|
|
dominant_color: '#383A40',
|
|
is_nsfw: false,
|
|
width: 0,
|
|
height: 0,
|
|
tags: [],
|
|
});
|
|
else {
|
|
const imageData = parsedData.images[0];
|
|
this._responses.push({
|
|
status: status,
|
|
signature: imageData?.signature || -1,
|
|
url: imageData?.url || undefined,
|
|
extension: imageData.extension,
|
|
source: imageData?.source,
|
|
dominant_color: imageData?.dominant_color || '#9392A6',
|
|
is_nsfw: imageData?.is_nsfw || false,
|
|
width: imageData?.width || 0,
|
|
height: imageData?.height || 0,
|
|
tags: imageData?.tags.map(obj => obj["name"]) || [],
|
|
});
|
|
}
|
|
this.emit('updateResponse', newMessageId);
|
|
})
|
|
.catch(print);
|
|
}
|
|
}
|
|
|
|
export default new WaifuService();
|
|
|