UNPKG

e621-sdk

Version:

从E621抓取帖子。支持搜索、引用、随机。

168 lines (167 loc) 5.87 kB
"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;