e621-sdk
Version:
从E621抓取帖子。支持搜索、引用、随机。
168 lines (167 loc) • 5.87 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PostWrapper = exports.RateLimiter = exports.E621 = exports.E621Authenticator = void 0;
const parser_1 = require("./parser");
const structs_1 = require("./structs");
const utils_1 = require("./utils");
const request_1 = require("./request");
const chalk_template_1 = __importDefault(require("chalk-template"));
const url_1 = require("url");
class E621Authenticator {
//镜像Url
imageUrls = {};
useImage = false;
//Axios
axiosConfig = {};
configureAxios(config) {
this.axiosConfig = (0, utils_1.assignRecursive)(this.axiosConfig, config);
}
//鉴权
accountInfo = null;
get isAuthorized() {
return this.accountInfo != null;
}
get authorizationCode() {
return this.isAuthorized ? "Basic " + btoa(`${this.accountInfo?.username}:${this.accountInfo?.apikey}`) : undefined;
}
async login(username, apikey) {
this.accountInfo = { username, apikey };
}
//镜像增删改查
delImage(name) {
delete this.imageUrls[name];
}
addImage(name, url, autoUse = false) {
this.imageUrls[name] = url;
if (autoUse) {
this.use(name);
}
}
use(name) {
this.useImage = name;
}
}
exports.E621Authenticator = E621Authenticator;
class E621 extends E621Authenticator {
rateLimiter = null;
log = false;
constructor(config) {
super();
Object.assign(this, config ?? {});
}
async searchPost(config = {}) {
const response = await (0, request_1.request)((0, parser_1.useApi)("posts", this) + (0, parser_1.query)(config), "get", this);
if (this.useImage)
return response.data.map((post) => new PostWrapper(post, this));
else
return response.data.posts.map((post) => new PostWrapper(post, this));
}
async fetchPost(id) {
const response = await (0, request_1.request)((0, parser_1.useApi)(`posts/${id}`, this), "get", this);
if (this.useImage)
return new PostWrapper(response.data, this);
else
return new PostWrapper(response.data.post, this);
}
async randomPost(...tags) {
const tag = tags[Math.floor(Math.random() * tags.length)];
const response = await (0, request_1.request)((0, parser_1.useApi)("posts/random", this) + (0, parser_1.query)({ tags: (0, parser_1.toSearchTag)(tag) }), "get", this);
if (this.useImage)
return new PostWrapper(response.data, this);
else
return new PostWrapper(response.data.post, this);
}
async static(md5, ext, progressCallback) {
this.axiosConfig.responseType = "arraybuffer";
if (progressCallback) {
this.axiosConfig.onDownloadProgress = e => {
progressCallback({
loaded: e.loaded,
total: e.total ?? 0,
percent: e.loaded / (e.total ?? 0),
});
};
}
const response = await (0, request_1.request)(this.useImage
? new url_1.URL(`/api/static/${md5}/${ext}`, this.imageUrls[this.useImage]).toString()
: `https://static1.e621.net/data/${md5.slice(0, 2)}/${md5.slice(2, 4)}/${md5}.${ext}`, "get", this);
if (progressCallback) {
delete this.axiosConfig.onDownloadProgress;
}
delete this.axiosConfig.responseType;
return response.data;
}
async serverStatus() {
try {
await (0, request_1.request)(this.useImage ? this.imageUrls[this.useImage] : parser_1.baseUrl, "get", this);
return {
status: true,
message: null,
};
}
catch (e) {
return {
status: false,
message: e,
};
}
}
}
exports.E621 = E621;
/**
* @description 限制请求速率
*/
class RateLimiter {
intervalPerRequest = (0, utils_1.count)(1).per(1000); //每1秒1次请求
lastRequest = 0;
get time() {
return Date.now();
}
get rest() {
return this.intervalPerRequest - (this.time - this.lastRequest);
}
get ready() {
return this.time - this.lastRequest >= this.intervalPerRequest;
}
start() {
if (this.ready) {
this.lastRequest = this.time;
return true;
}
else
return false;
}
async wait() {
return new Promise(resolve => {
const { rest } = this;
setTimeout(async () => {
if (!this.ready)
resolve(await this.wait() + rest);
else
resolve(rest);
}, rest + 1);
});
}
}
exports.RateLimiter = RateLimiter;
class PostWrapper {
data = null;
parentClient = null;
constructor(data, client) {
this.data = data;
this.parentClient = client;
}
get formatted() {
if (!this.data)
return null;
const { score, file, id } = this.data;
const { up, down } = score;
const { width, height, url } = file;
const rateText = structs_1.rateColorMap[this.data.rating](`${structs_1.rateNameMap[this.data.rating].slice(0, 4)}`);
return (0, chalk_template_1.default) `${rateText} {bold #${id}} {italic 👍${up} 👎${Math.abs(down)}} [{cyan ${width}}*{cyan ${height}}] {bold.underline ${url}}`;
}
}
exports.PostWrapper = PostWrapper;