var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { Card: () => Card, GuildMute: () => GuildMute, HttpServer: () => HttpServer, Internal: () => Internal, Kook: () => utils_exports, KookBot: () => KookBot, KookMessageEncoder: () => KookMessageEncoder, Permissions: () => Permissions, Signal: () => Signal, Type: () => Type, UserStatus: () => UserStatus, WsClient: () => WsClient, adaptGroup: () => adaptGroup, adaptMessage: () => adaptMessage, adaptSession: () => adaptSession, adaptUser: () => adaptUser, decodeGuildMember: () => decodeGuildMember, decodeRole: () => decodeRole, default: () => src_default, encodeRole: () => encodeRole, hasPermission: () => hasPermission, isDirectChannel: () => isDirectChannel }); module.exports = __toCommonJS(src_exports); // src/bot.ts var import_core5 = require("@satorijs/core"); // src/utils.ts var utils_exports = {}; __export(utils_exports, { Card: () => Card, GuildMute: () => GuildMute, Internal: () => Internal, Permissions: () => Permissions, Signal: () => Signal, Type: () => Type, UserStatus: () => UserStatus, adaptGroup: () => adaptGroup, adaptMessage: () => adaptMessage, adaptSession: () => adaptSession, adaptUser: () => adaptUser, decodeGuildMember: () => decodeGuildMember, decodeRole: () => decodeRole, encodeRole: () => encodeRole, hasPermission: () => hasPermission }); var import_core = require("@satorijs/core"); // src/types.ts var Signal = /* @__PURE__ */ ((Signal2) => { Signal2[Signal2["event"] = 0] = "event"; Signal2[Signal2["hello"] = 1] = "hello"; Signal2[Signal2["ping"] = 2] = "ping"; Signal2[Signal2["pong"] = 3] = "pong"; Signal2[Signal2["reconnect"] = 4] = "reconnect"; Signal2[Signal2["resume"] = 5] = "resume"; return Signal2; })(Signal || {}); var Type = /* @__PURE__ */ ((Type2) => { Type2[Type2["text"] = 1] = "text"; Type2[Type2["image"] = 2] = "image"; Type2[Type2["video"] = 3] = "video"; Type2[Type2["file"] = 4] = "file"; Type2[Type2["unknown"] = 7] = "unknown"; Type2[Type2["audio"] = 8] = "audio"; Type2[Type2["kmarkdown"] = 9] = "kmarkdown"; Type2[Type2["card"] = 10] = "card"; Type2[Type2["system"] = 255] = "system"; return Type2; })(Type || {}); var Card; ((Card2) => { Card2.Theme = ["primary", "secondary", "warning", "danger", "info", "none", "success"]; let Button; ((Button2) => { Button2.Theme = ["primary", "secondary", "warning", "danger", "info", "none", "success"]; })(Button = Card2.Button || (Card2.Button = {})); })(Card || (Card = {})); var UserStatus = /* @__PURE__ */ ((UserStatus2) => { UserStatus2[UserStatus2["normal"] = 0] = "normal"; UserStatus2[UserStatus2["normal_1"] = 1] = "normal_1"; UserStatus2[UserStatus2["banned"] = 10] = "banned"; return UserStatus2; })(UserStatus || {}); var Permissions = /* @__PURE__ */ ((Permissions2) => { Permissions2[Permissions2["GUILD_ADMIN"] = 0] = "GUILD_ADMIN"; Permissions2[Permissions2["GUILD_MANAGE"] = 1] = "GUILD_MANAGE"; Permissions2[Permissions2["GUILD_LOG"] = 2] = "GUILD_LOG"; Permissions2[Permissions2["GUILD_INVITE_CREATE"] = 3] = "GUILD_INVITE_CREATE"; Permissions2[Permissions2["GUILD_INVITE_MANAGE"] = 4] = "GUILD_INVITE_MANAGE"; Permissions2[Permissions2["CHANNEL_MANAGE"] = 5] = "CHANNEL_MANAGE"; Permissions2[Permissions2["GUILD_USER_KICK"] = 6] = "GUILD_USER_KICK"; Permissions2[Permissions2["GUILD_USER_BAN"] = 7] = "GUILD_USER_BAN"; Permissions2[Permissions2["GUILD_EMOJI_MANAGE"] = 8] = "GUILD_EMOJI_MANAGE"; Permissions2[Permissions2["GUILD_USER_NAME_CHANGE"] = 9] = "GUILD_USER_NAME_CHANGE"; Permissions2[Permissions2["GUILD_ROLE_MANAGE"] = 10] = "GUILD_ROLE_MANAGE"; Permissions2[Permissions2["CHANNEL_VIEW"] = 11] = "CHANNEL_VIEW"; Permissions2[Permissions2["CHANNEL_MESSAGE"] = 12] = "CHANNEL_MESSAGE"; Permissions2[Permissions2["CHANNEL_MANAGE_MESSAGE"] = 13] = "CHANNEL_MANAGE_MESSAGE"; Permissions2[Permissions2["CHANNEL_UPLOAD"] = 14] = "CHANNEL_UPLOAD"; Permissions2[Permissions2["CHANNEL_VOICE_CONNECT"] = 15] = "CHANNEL_VOICE_CONNECT"; Permissions2[Permissions2["CHANNEL_VOICE_MANAGE"] = 16] = "CHANNEL_VOICE_MANAGE"; Permissions2[Permissions2["CHANNEL_MESSAGE_AT_ALL"] = 17] = "CHANNEL_MESSAGE_AT_ALL"; Permissions2[Permissions2["CHANNEL_MESSAGE_REACTION_CREATE"] = 18] = "CHANNEL_MESSAGE_REACTION_CREATE"; Permissions2[Permissions2["CHANNEL_MESSAGE_REACTION_FOLLOW"] = 19] = "CHANNEL_MESSAGE_REACTION_FOLLOW"; Permissions2[Permissions2["CHANNEL_VOICE_CONNECT_PASSIVE"] = 20] = "CHANNEL_VOICE_CONNECT_PASSIVE"; Permissions2[Permissions2["CHANNEL_VOICE_SPEAK_KEY_ONLY"] = 21] = "CHANNEL_VOICE_SPEAK_KEY_ONLY"; Permissions2[Permissions2["CHANNEL_VOICR_SPEAK_FREE"] = 22] = "CHANNEL_VOICR_SPEAK_FREE"; Permissions2[Permissions2["CHANNEL_VOICE_SPEAK"] = 23] = "CHANNEL_VOICE_SPEAK"; Permissions2[Permissions2["GUILD_USER_DEAFEN"] = 24] = "GUILD_USER_DEAFEN"; Permissions2[Permissions2["GUILD_USER_MUTEGUILD_USER_NAME_CHANGE_OTHER"] = 25] = "GUILD_USER_MUTEGUILD_USER_NAME_CHANGE_OTHER"; Permissions2[Permissions2["GUILD_USER_NAME_CHANGE_OTHER"] = 26] = "GUILD_USER_NAME_CHANGE_OTHER"; Permissions2[Permissions2["CHANNEL_VOICE_BGM"] = 27] = "CHANNEL_VOICE_BGM"; return Permissions2; })(Permissions || {}); function hasPermission(permissions, permission) { return (permissions & 1 << permission) === 1 << permission; } __name(hasPermission, "hasPermission"); var GuildMute; ((GuildMute2) => { let Type2; ((Type3) => { Type3[Type3["mic"] = 1] = "mic"; Type3[Type3["headset"] = 2] = "headset"; })(Type2 = GuildMute2.Type || (GuildMute2.Type = {})); })(GuildMute || (GuildMute = {})); var Internal = class _Internal { constructor(http) { this.http = http; } static { __name(this, "Internal"); } static define(name, method, path) { _Internal.prototype[name] = async function(...args) { const config = {}; if (method === "GET" || method === "DELETE") { config.params = args[0]; } else { config.data = args[0]; } const { data } = await this.http(method, path, config); if (data?.code !== 0) throw new Error(data?.message || "Unexpected Error"); return data?.data; }; } }; Internal.define("getGuildList", "GET", "/guild/list"); Internal.define("getGuildView", "GET", "/guild/view"); Internal.define("getGuildUserList", "GET", "/guild/user-list"); Internal.define("setGuildUserNickname", "POST", "/guild/nickname"); Internal.define("leaveGuild", "POST", "/guild/leave"); Internal.define("kickoutGuildUser", "POST", "/guild/kickout"); Internal.define("getGuildMuteList", "GET", "/guild-mute/list"); Internal.define("createGuildMute", "POST", "/guild-mute/create"); Internal.define("deleteGuildMute", "POST", "/guild-mute/delete"); Internal.define("getGuildBoostHistory", "GET", "/guild-boost/history"); Internal.define("getChannelList", "GET", "/channel/list"); Internal.define("getChannelView", "GET", "/channel/view"); Internal.define("createChannel", "POST", "/channel/create"); Internal.define("updateChannel", "POST", "/channel/update"); Internal.define("deleteChannel", "POST", "/channel/delete"); Internal.define("getChannelUserList", "GET", "/channel/user-list"); Internal.define("kickChannelUser", "POST", "/channel/kickout"); Internal.define("moveChannelUser", "POST", "/channel/move-user"); Internal.define("getChannelRoleIndex", "GET", "/channel-role/index"); Internal.define("createChannelRole", "POST", "/channel-role/create"); Internal.define("updateChannelRole", "POST", "/channel-role/update"); Internal.define("deleteChannelRole", "POST", "/channel-role/delete"); Internal.define("getMessageList", "GET", "/message/list"); Internal.define("getMessageView", "GET", "/message/view"); Internal.define("createMessage", "POST", "/message/create"); Internal.define("updateMessage", "POST", "/message/update"); Internal.define("deleteMessage", "POST", "/message/delete"); Internal.define("getMessageReactionList", "GET", "/message/reaction-list"); Internal.define("addMessageReaction", "POST", "/message/add-reaction"); Internal.define("deleteMessageReaction", "POST", "/message/delete-reaction"); Internal.define("getChannelJoinedUserList", "GET", "/channel-user/get-joined-channel"); Internal.define("getPrivateChatList", "GET", "/user-chat/list"); Internal.define("getPrivateChatView", "GET", "/user-chat/view"); Internal.define("createPrivateChat", "POST", "/user-chat/create"); Internal.define("deletePrivateChat", "POST", "/user-chat/delete"); Internal.define("getDirectMessageList", "GET", "/direct-message/list"); Internal.define("createDirectMessage", "POST", "/direct-message/create"); Internal.define("updateDirectMessage", "POST", "/direct-message/update"); Internal.define("deleteDirectMessage", "POST", "/direct-message/delete"); Internal.define("getDirectMessageReactionList", "GET", "/direct-message/reaction-list"); Internal.define("addDirectMessageReaction", "POST", "/direct-message/add-reaction"); Internal.define("deleteDirectMessageReaction", "POST", "/direct-message/delete-reaction"); Internal.define("getGateway", "GET", "/gateway/index"); Internal.define("getToken", "POST", "/oauth2/token"); Internal.define("createAsset", "POST", "/asset/create"); Internal.define("getUserMe", "GET", "/user/me"); Internal.define("getUserView", "GET", "/user/view"); Internal.define("offline", "POST", "/user/offline"); Internal.define("getGuildRoleList", "GET", "/guild-role/list"); Internal.define("createGuildRole", "POST", "/guild-role/create"); Internal.define("updateGuildRole", "POST", "/guild-role/update"); Internal.define("deleteGuildRole", "POST", "/guild-role/delete"); Internal.define("grantGuildRole", "POST", "/guild-role/grant"); Internal.define("revokeGuildRole", "POST", "/guild-role/revoke"); Internal.define("getIntimacy", "GET", "/intimacy/index"); Internal.define("updateIntimacy", "POST", "/intimacy/update"); Internal.define("getGuildEmojiList", "GET", "/guild-emoji/list"); Internal.define("createGuildEmoji", "POST", "/guild-emoji/create"); Internal.define("updateGuildEmoji", "POST", "/guild-emoji/update"); Internal.define("deleteGuildEmoji", "POST", "/guild-emoji/delete"); Internal.define("getInviteList", "GET", "/invite/list"); Internal.define("createInvite", "POST", "/invite/create"); Internal.define("deleteInvite", "POST", "/invite/delete"); Internal.define("getBlacklist", "GET", "/blacklist/list"); Internal.define("createBlacklist", "POST", "/blacklist/create"); Internal.define("deleteBlacklist", "POST", "/blacklist/delete"); Internal.define("getGuildBadge", "GET", "/badge/guild"); Internal.define("getGameList", "GET", "/game"); Internal.define("createGame", "POST", "/game/create"); Internal.define("updateGame", "POST", "/game/update"); Internal.define("deleteGame", "POST", "/game/delete"); Internal.define("createGameActivity", "POST", "/game/activity"); Internal.define("deleteGameActivity", "POST", "/game/delete-activity"); // src/utils.ts var adaptGroup = /* @__PURE__ */ __name((data) => ({ id: data.id, name: data.name }), "adaptGroup"); var adaptUser = /* @__PURE__ */ __name((user) => ({ id: user.id, name: user.username, userId: user.id, avatar: user.avatar, username: user.username, discriminator: user.identify_num }), "adaptUser"); var decodeGuildMember = /* @__PURE__ */ __name((member) => ({ user: adaptUser(member), nick: member.nickname }), "decodeGuildMember"); var decodeRole = /* @__PURE__ */ __name((role) => ({ ...role, id: "" + role.role_id, permissions: BigInt(role.permissions), hoist: !!role.hoist, mentionable: !!role.mentionable }), "decodeRole"); function encodeBit(value) { return (0, import_core.isNullable)(value) ? value : value ? 1 : 0; } __name(encodeBit, "encodeBit"); var encodeRole = /* @__PURE__ */ __name((role) => ({ ...role, role_id: +role.id, permissions: role.permissions && Number(role.permissions), hoist: encodeBit(role.hoist), mentionable: encodeBit(role.mentionable) }), "encodeRole"); function transformCardElement(data) { const { type, modules, text, elements, fields, ...attrs } = data; const children = modules || elements || fields || (text ? [text] : []); return (0, import_core.h)(type, attrs, children.map(transformCardElement)); } __name(transformCardElement, "transformCardElement"); function adaptMessageMeta(base, data, message = {}, payload = message) { if (base.type === 1 /* text */) { message.content = base.content.replace(/@(.+?)#(\d+)/, (_, name, id) => (0, import_core.h)("at", { id, name }).toString()).replace(/@全体成员/, () => (0, import_core.h)("at", { type: "all" }).toString()).replace(/@在线成员/, () => (0, import_core.h)("at", { type: "here" }).toString()).replace(/@role:(\d+);/, (_, role) => (0, import_core.h)("at", { role }).toString()).replace(/#channel:(\d+);/, (_, id) => import_core.h.sharp(id).toString()); message.elements = import_core.h.parse(message.content); } else if (base.type === 2 /* image */) { const element = (0, import_core.h)("img", { src: base.content, file: data.attachments?.name }); message.elements = [element]; message.content = element.toString(); } else if (base.type === 10 /* card */) { const data2 = JSON.parse(base.content); message.elements = data2.map(transformCardElement); message.content = message.elements.join(""); } else if (base.type === 9 /* kmarkdown */) { let content = base.content; let buffer = ""; let cap; const elements = []; const flushText = /* @__PURE__ */ __name(() => { if (!buffer) return; elements.push(import_core.h.text(buffer.replace(/\\(.)/g, (_, char) => char))); buffer = ""; }, "flushText"); while (content) { if (content.startsWith("\\") && content.length > 1) { buffer += content[1]; content = content.slice(2); } else if (cap = /^(\((met|chn|rol)\))(\w+)\1/.exec(content)) { content = content.slice(cap[0].length); flushText(); if (cap[2] === "met") { if (cap[3] === "all" || cap[3] === "here") { elements.push((0, import_core.h)("at", { type: cap[3] })); } else { const name = data.kmarkdown.mention_part.find((mention) => mention.id === cap[3])?.username; elements.push((0, import_core.h)("at", { id: cap[3], name })); } } else if (cap[2] === "chn") { elements.push(import_core.h.sharp(cap[3])); } else if (cap[2] === "rol") { const name = data.kmarkdown.mention_role_part.find((mention) => mention.role_id + "" === cap[3])?.name; elements.push((0, import_core.h)("at", { role: cap[3], name })); } } else { buffer += content[0]; content = content.slice(1); } } flushText(); message.content = elements.join(""); message.elements = elements; } if (data.author) { payload.user = adaptUser(data.author); payload.member = decodeGuildMember(data.author); } return message; } __name(adaptMessageMeta, "adaptMessageMeta"); function adaptMessage(data, message = {}, payload = message) { adaptMessageMeta(data, data, message, payload); message.id = message.messageId = data.id; return message; } __name(adaptMessage, "adaptMessage"); function adaptMessageSession(data, meta, message = {}, payload = message) { adaptMessageMeta(data, meta, message); message.id = message.messageId = data.msg_id; message.timestamp = data.msg_timestamp; if (meta.quote) { message.quote = adaptMessageMeta(meta.quote, meta.quote); message.quote.messageId = message.quote.id = meta.quote.rong_id; } return message; } __name(adaptMessageSession, "adaptMessageSession"); function adaptMessageCreate(data, meta, session) { session.guildId = meta.guild_id; if (data.channel_type === "GROUP") { session.isDirect = false; session.channelId = data.target_id; } else { session.isDirect = true; session.channelId = meta.code; } session.event.channel.name = meta.channel_name; session.event.member = decodeGuildMember(data.extra.author); session.event.user = session.event.member.user; delete session.event.member.user; adaptMessageSession(data, meta, session.event.message = {}, session.event); } __name(adaptMessageCreate, "adaptMessageCreate"); async function adaptMessageModify(bot, data, meta, session) { session.guildId = meta.guild_id; session.event.user = meta.user_info && adaptUser(meta.user_info); session.userId = meta.author_id; if ((meta.channel_type || data.channel_type) === "GROUP") { session.isDirect = false; session.channelId = meta.channel_id || meta.target_id; } else { session.isDirect = true; session.channelId = meta.chat_code || (await bot.createDirectChannel(session.userId)).id; } adaptMessageSession(data, meta, session.event.message = {}, session.event); } __name(adaptMessageModify, "adaptMessageModify"); function adaptReaction(body, session) { session.channelId = body.channel_id; session.messageId = body.msg_id; session.userId = body.user_id; session["emoji"] = body.emoji.id; } __name(adaptReaction, "adaptReaction"); async function adaptSession(bot, input) { const session = bot.session(); session.setInternal("kook", input); if (input.type === 255 /* system */) { const { type, body } = input.extra; bot.dispatch(bot.session({ type: "internal", _type: "kook/" + type.replace(/_/g, "-"), _data: body })); switch (type) { case "message_btn_click": session.type = "interaction/button"; await adaptMessageModify(bot, input, body, session); session.event.button = { id: body.value }; break; case "updated_message": case "updated_private_message": session.type = "message-updated"; await adaptMessageModify(bot, input, body, session); break; case "deleted_message": case "deleted_private_message": session.type = "message-deleted"; await adaptMessageModify(bot, input, body, session); break; case "added_reaction": case "private_added_reaction": session.type = "reaction-added"; adaptReaction(body, session); break; case "deleted_reaction": case "private_deleted_reaction": session.type = "reaction-deleted"; adaptReaction(body, session); break; case "updated_channel": case "deleted_channel": session.type = "channel-deleted"; session.subtype = "group"; session.channelId = body.id; break; case "pinned_message": case "unpinned_message": session.type = type === "pinned_message" ? "message-pinned" : "message-unpinned"; session.operatorId = body.operator_id; session.messageId = body.msg_id; session.channelId = body.channel_id; break; case "joined_guild": case "exited_guild": case "updated_guild": case "deleted_guild": case "self_joined_guild": case "self_exited_guild": case "updated_guild_member": session.type = { joined_guild: "guild-member-added", exited_guild: "guild-member-deleted", updated_guild: "guild-updated", deleted_guild: "guild-deleted", self_joined_guild: "guild-added", self_exited_guild: "guild-deleted", updated_guild_member: "guild-member-updated" }[type]; session.guildId = input.target_id; session.userId = body.user_id || bot.selfId; break; case "added_role": case "deleted_role": case "updated_role": session.type = { added_role: "guild-role-added", deleted_role: "guild-role-deleted", updated_role: "guild-role-updated" }[type]; session.guildId = input.target_id; session.roleId = "" + body.role_id; session.event.role = decodeRole(body); break; default: return; } } else { session.type = "message"; adaptMessageCreate(input, input.extra, session); if (!session.content) return; } return session; } __name(adaptSession, "adaptSession"); // src/ws.ts var import_core2 = require("@satorijs/core"); var heartbeatIntervals = [6, 2, 4]; var WsClient = class extends import_core2.Adapter.WsClient { static { __name(this, "WsClient"); } _sn = 0; _ping; _heartbeat; async prepare() { const { url } = await this.bot.request("GET", "/gateway/index?compress=0"); const headers = { Authorization: `Bot ${this.bot.config.token}` }; return this.bot.ctx.http.ws(url, { headers }); } heartbeat() { if (!this.socket || this.bot.status !== import_core2.Universal.Status.ONLINE) { clearInterval(this._heartbeat); return; } let trials = 0; const send = /* @__PURE__ */ __name(() => { if (!this.socket) return; if (trials >= 2) { return this.socket.close(1e3); } this.socket.send(JSON.stringify({ s: 2 /* ping */, sn: this._sn })); this._ping = setTimeout(send, heartbeatIntervals[trials++] * import_core2.Time.second); }, "send"); send(); } async accept() { this._sn = 0; clearInterval(this._heartbeat); this.socket.addEventListener("message", async ({ data }) => { let parsed; data = data.toString(); try { parsed = JSON.parse(data); } catch (error) { return this.bot.logger.warn("cannot parse message", data); } this.bot.logger.debug("[receive] %o", parsed); if (parsed.s === 0 /* event */) { this._sn = Math.max(this._sn, parsed.sn); const session = await adaptSession(this.bot, parsed.d); if (session) this.bot.dispatch(session); } else if (parsed.s === 1 /* hello */) { this._heartbeat = setInterval(() => this.heartbeat(), import_core2.Time.minute * 0.5); await this.bot.getLogin(); this.bot.online(); } else if (parsed.s === 3 /* pong */) { clearTimeout(this._ping); } else if (parsed.s === 5 /* resume */) { this.socket.close(1e3); } }); } }; ((WsClient2) => { WsClient2.Options = import_core2.Schema.intersect([ import_core2.Schema.object({ protocol: import_core2.Schema.const("ws").required(process.env.KOISHI_ENV !== "browser"), token: import_core2.Schema.string().description("机器人的用户令牌。").role("secret").required() }), import_core2.Adapter.WsClientConfig ]); })(WsClient || (WsClient = {})); // src/http.ts var import_core3 = require("@satorijs/core"); var HttpServer = class extends import_core3.Adapter { static { __name(this, "HttpServer"); } static inject = ["server"]; logger; constructor(ctx, bot) { super(ctx); this.logger = ctx.logger("kook"); let { path } = bot.config; path = (0, import_core3.sanitize)(path); ctx.server.post(path, async (ctx2) => { const { body } = ctx2.request; this.logger.debug("receive %o", body); const { challenge } = body.d; ctx2.status = 200; if (challenge) { ctx2.body = { challenge }; return; } const bot2 = this.bots.find((bot3) => bot3.config.verifyToken === body.d.verify_token); if (!bot2) return; const session = await adaptSession(bot2, body.d); if (session) bot2.dispatch(session); }); } async connect(bot) { await bot.getLogin(); bot.online(); } }; ((HttpServer2) => { HttpServer2.Options = import_core3.Schema.object({ protocol: import_core3.Schema.const("http").required(), token: import_core3.Schema.string().description("机器人令牌。").role("secret").required(), verifyToken: import_core3.Schema.string().description("验证令牌。").role("secret").required(), path: import_core3.Schema.string().description("服务器监听的路径。").default("/kook") }); })(HttpServer || (HttpServer = {})); // src/message.ts var import_core4 = require("@satorijs/core"); function isDirectChannel(channelId) { return channelId.length > 30; } __name(isDirectChannel, "isDirectChannel"); var KookMessageEncoder = class extends import_core4.MessageEncoder { static { __name(this, "KookMessageEncoder"); } path; params = {}; additional = {}; textBuffer = ""; cardBuffer = { type: "card", modules: [] }; async prepare() { if (isDirectChannel(this.session.channelId)) { this.session.isDirect = true; this.params.chat_code = this.session.channelId; this.path = "/user-chat/create-msg"; } else { this.session.isDirect = false; this.params.target_id = this.session.channelId; this.path = "/message/create"; } } async post(type, content) { try { const params = { ...this.params, ...this.additional, type, content }; const result = await this.bot.request("POST", this.path, params); if (!result.msg_id) return; const session = this.bot.session(); session.type = "send"; session.content = ""; session.messageId = result.msg_id; session.timestamp = result.timestamp; this.results.push(session.event.message); session.app.emit(session, "send", session); } catch (e) { this.errors.push(e); } } async transformUrl({ type, attrs }) { const src = attrs.src || attrs.url; if (await this.bot.http.isLocal(src)) { const payload = new FormData(); const { data, type: type2, filename } = await this.bot.http.file(src, attrs); payload.append("file", new Blob([data], { type: type2 }), attrs.file || filename); const { data: { url } } = await this.bot.http.post("/asset/create", payload); return url; } else if (!src.includes("kookapp.cn")) { const { data, headers } = await this.bot.ctx.http("GET", src, { headers: { accept: type + "/*" }, responseType: "arraybuffer", timeout: +attrs.timeout || void 0 }); const payload = new FormData(); payload.append("file", new Blob([data], { type: headers.get("Content-Type") }), "file"); const { data: { url } } = await this.bot.http.post("/asset/create", payload); return url; } else { return src; } } flushText() { const content = this.textBuffer.trim(); if (!content) return; this.textBuffer = ""; this.cardBuffer.modules.push({ type: "section", text: { type: "kmarkdown", content } }); } async flush(forceCard = false) { if (this.cardBuffer.modules.length || forceCard) { this.flushText(); await this.post(10 /* card */, JSON.stringify([this.cardBuffer])); this.cardBuffer = { type: "card", modules: [] }; } else { const content = this.textBuffer.trim(); if (!content) return; this.textBuffer = ""; await this.post(9 /* kmarkdown */, content); } this.additional = {}; } async visit(element) { const { type, attrs, children } = element; if (type === "text") { this.textBuffer += attrs.content.replace(/[\\*`~()]/g, "\\$&"); } else if (type === "b" || type === "strong") { this.textBuffer += "**"; await this.render(children); this.textBuffer += "**"; } else if (type === "i" || type === "em") { this.textBuffer += "*"; await this.render(children); this.textBuffer += "*"; } else if (type === "u" || type === "ins") { this.textBuffer += "(ins)"; await this.render(children); this.textBuffer += "(ins)"; } else if (type === "s" || type === "del") { this.textBuffer += "~~"; await this.render(children); this.textBuffer += "~~"; } else if (type === "spl") { this.textBuffer += "(spl)"; await this.render(children); this.textBuffer += "(spl)"; } else if (type === "code") { this.textBuffer += "`"; await this.render(children); this.textBuffer += "`"; } else if (type === "a") { this.textBuffer += `[`; await this.render(children); this.textBuffer += `](${attrs.href})`; } else if (type === "br") { this.textBuffer += "\n"; } else if (type === "p") { if (!this.textBuffer.endsWith("\n")) this.textBuffer += "\n"; await this.render(children); if (!this.textBuffer.endsWith("\n")) this.textBuffer += "\n"; } else if (type === "at") { if (attrs.id) { this.textBuffer += `(met)${attrs.id}(met)`; } else if (attrs.type === "all") { this.textBuffer += `(met)all(met)`; } else if (attrs.type === "here") { this.textBuffer += `(met)here(met)`; } else if (attrs.role) { this.textBuffer += `(rol)${attrs.role}(rol)`; } } else if (type === "code") { this.textBuffer += `\`${element.toString(true)}\``; } else if (type === "sharp") { this.textBuffer += `(chn)${attrs.id}(chn)`; } else if (["video", "audio", "file", "kook:video", "kook:audio", "kook:file"].includes(type)) { this.flushText(); this.cardBuffer.modules.push({ type: type.startsWith("kook:") ? type.slice(5) : type, src: await this.transformUrl(element), title: attrs.title, cover: attrs.poster }); } else if (type === "img" || type === "image" || type === "kook:image") { this.flushText(); this.cardBuffer.modules.push({ type: "container", elements: [{ type: "image", src: await this.transformUrl(element) }] }); } else if (type === "kook:image-group") { this.flushText(); const elements = await Promise.all(element.children.map(async (child) => ({ type: "image", src: await this.transformUrl(child), title: child.attrs.title }))); while (elements.length) { this.cardBuffer.modules.push({ type: "image-group", elements: elements.splice(0, 9) }); } } else if (type === "button" || type === "kook:button") { this.flushText(); this.cardBuffer.modules.push({ type: "action-group", elements: [encodeButton(element)] }); } else if (type === "button-group" || type === "kook:action-group") { this.flushText(); const elements = element.children.map(encodeButton); while (elements.length) { this.cardBuffer.modules.push({ type: "action-group", elements: elements.splice(0, 4) }); } } else if (type === "hr" || type === "kook:divider") { this.flushText(); this.cardBuffer.modules.push({ type: "divider" }); } else if (type === "kook:header") { this.flushText(); this.cardBuffer.modules.push({ type: "header", text: { type: attrs.type, content: attrs.content } }); } else if (type === "kook:countdown") { this.flushText(); this.cardBuffer.modules.push({ type: "countdown", startTime: +attrs.startTime, endTime: +attrs.endTime, mode: attrs.mode }); } else if (type === "kook:invite") { this.flushText(); this.cardBuffer.modules.push({ type: "invite", code: attrs.code }); } else if (type === "kook:card") { await this.flush(); this.cardBuffer.theme = attrs["kook:theme"] ?? (Card.Theme.includes(attrs.class) ? attrs.class : "primary"); this.cardBuffer.size = attrs["kook:size"]; await this.render(children); await this.flush(true); } else if (type === "quote") { await this.flush(); this.additional.quote = attrs.id; } else if (type === "message") { await this.flush(); await this.render(children); await this.flush(); } else { await this.render(children); } } }; ((KookMessageEncoder2) => { KookMessageEncoder2.Config = import_core4.Schema.object({ handleMixedContent: import_core4.Schema.union([ import_core4.Schema.const("separate").description("将每个不同形式的内容分开发送"), import_core4.Schema.const("card").description("使用卡片发送内容"), import_core4.Schema.const("mixed").description("使用混合模式发送内容") ]).role("radio").description("发送图文等混合内容时采用的方式。").default("separate") }).description("发送设置"); })(KookMessageEncoder || (KookMessageEncoder = {})); function encodeButton({ attrs, children }) { let theme = "primary"; if (attrs.class === "secondary") theme = "info"; if (attrs.class === "warning") theme = "warning"; if (attrs.class === "danger") theme = "danger"; if (attrs.class === "success") theme = "success"; return { type: "button", theme, value: attrs.type === "link" ? attrs.href : attrs.id, click: attrs.type === "link" ? "link" : "return-val", text: { type: "kmarkdown", content: encodeMarkdown(children) } }; } __name(encodeButton, "encodeButton"); function encodeMarkdown(children) { let content = ""; for (const element of children) { const { type, attrs, children: children2 } = element; if (type === "text") { content += attrs.content.replace(/[\\*`~()]/g, "\\$&"); } else if (type === "b" || type === "strong") { content += "**" + encodeMarkdown(children2) + "**"; } else if (type === "i" || type === "em") { content += "*" + encodeMarkdown(children2) + "*"; } else if (type === "u" || type === "ins") { content += "(ins)" + encodeMarkdown(children2) + "(ins)"; } else if (type === "s" || type === "del") { content += "~~" + encodeMarkdown(children2) + "~~"; } else if (type === "spl") { content += "(spl)" + encodeMarkdown(children2) + "(spl)"; } else if (type === "code") { content += "`" + element.toString(true) + "`"; } else if (type === "a") { content += `[${encodeMarkdown(children2)}](${attrs.href})`; } } return content; } __name(encodeMarkdown, "encodeMarkdown"); // src/bot.ts var KookBot = class extends import_core5.Bot { static { __name(this, "KookBot"); } static MessageEncoder = KookMessageEncoder; static inject = ["http"]; http; internal; constructor(ctx, config) { super(ctx, config, "kook"); this.http = ctx.http.extend({ headers: { "Authorization": `Bot ${config.token}` } }).extend(config); this.proxyUrls.push("https://www.kookapp.cn/"); this.internal = new Internal(this.http); if (config.protocol === "http") { ctx.plugin(HttpServer, this); } else if (config.protocol === "ws") { ctx.plugin(WsClient, this); } } async request(method, path, data = {}, headers = {}) { if (method === "GET") { return (await this.http.get(path, { params: data, headers })).data; } else { return (await this.http(method, path, { data, headers })).data?.data; } } async deleteMessage(channelId, msg_id) { if (isDirectChannel(channelId)) { await this.request("POST", "/user-chat/delete-msg", { msg_id }); } else { await this.request("POST", "/message/delete", { msg_id }); } } async editMessage(channelId, msg_id, content) { content = import_core5.h.normalize(content).join(""); if (isDirectChannel(channelId)) { await this.request("POST", "/user-chat/update-msg", { msg_id, content }); } else { await this.request("POST", "/message/update", { msg_id, content }); } } async getMessage(channelId, msg_id) { if (isDirectChannel(channelId)) { return adaptMessage(await this.request("POST", "/user-chat/view", { msg_id })); } else { return adaptMessage(await this.request("POST", "/message/view", { msg_id })); } } async $createReaction(channelId, msg_id, emoji) { if (isDirectChannel(channelId)) { await this.request("POST", "/direct-message/add-reaction", { msg_id, emoji }); } else { await this.request("POST", "/message/add-reaction", { msg_id, emoji }); } } async $deleteReaction(channelId, messageId, emoji, user_id) { if (isDirectChannel(channelId)) { await this.request("POST", "/direct-message/delete-reaction", { msg_id: messageId, emoji }); } else { await this.request("POST", "/message/delete-reaction", { msg_id: messageId, emoji, user_id }); } } async getLogin() { this.user = adaptUser(await this.request("GET", "/user/me")); return this.toJSON(); } async getGuildList() { const { items } = await this.request("GET", "/guild/list"); return { data: items.map(adaptGroup) }; } async getGuildMemberList(guild_id) { const { items } = await this.request("GET", "/guild/user-list", { guild_id }); return { data: items.map(decodeGuildMember) }; } async setGroupNickname(guild_id, user_id, nickname) { await this.request("POST", "/guild/nickname", { guild_id, user_id, nickname }); } async leaveGroup(guild_id) { await this.request("POST", "/guild/leave", { guild_id }); } async kickGroup(guild_id, user_id) { await this.request("POST", "/guild/kickout", { guild_id, user_id }); } async createDirectChannel(userId) { const { code } = await this.request("POST", "/user-chat/create", { target_id: userId }); return { id: code, type: import_core5.Universal.Channel.Type.DIRECT }; } createReaction(channelId, messageId, emoji) { if (isDirectChannel(channelId)) { return this.internal.addDirectMessageReaction({ msg_id: messageId, emoji }); } else { return this.internal.addMessageReaction({ msg_id: messageId, emoji }); } } deleteReaction(channelId, messageId, emoji, userId) { if (isDirectChannel(channelId)) { return this.internal.deleteDirectMessageReaction({ msg_id: messageId, emoji, user_id: userId }); } else { return this.internal.deleteMessageReaction({ msg_id: messageId, emoji, user_id: userId }); } } async getReactionList(channelId, messageId, emoji) { let users; if (isDirectChannel(channelId)) { users = await this.internal.getDirectMessageReactionList({ msg_id: messageId, emoji }); } else { users = await this.internal.getMessageReactionList({ msg_id: messageId, emoji }); } return { data: users.map(adaptUser) }; } async setGuildMemberRole(guildId, userId, roleId) { await this.internal.grantGuildRole({ guild_id: guildId, user_id: userId, role_id: +roleId }); } async unsetGuildMemberRole(guildId, userId, roleId) { await this.internal.revokeGuildRole({ guild_id: guildId, user_id: userId, role_id: +roleId }); } async getGuildRoles(guildId) { const { items } = await this.internal.getGuildRoleList({ guild_id: guildId }); return { data: items.map(decodeRole) }; } async createGuildRole(guildId, data) { const role = await this.internal.createGuildRole({ guild_id: guildId, ...data }); return decodeRole(role); } async updateGuildRole(guildId, roleId, data) { await this.internal.updateGuildRole({ guild_id: guildId, ...encodeRole(data), role_id: +roleId }); } async deleteGuildRole(guildId, roleId) { await this.internal.deleteGuildRole({ guild_id: guildId, role_id: +roleId }); } }; ((KookBot2) => { KookBot2.Config = import_core5.Schema.intersect([ import_core5.Schema.object({ protocol: process.env.KOISHI_ENV === "browser" ? import_core5.Schema.const("ws").default("ws") : import_core5.Schema.union(["http", "ws"]).description("选择要使用的协议。").required() }), import_core5.Schema.union([ WsClient.Options, HttpServer.Options ]), KookMessageEncoder.Config, import_core5.HTTP.createConfig("https://www.kookapp.cn/api/v3") ]); })(KookBot || (KookBot = {})); // src/index.ts var src_default = KookBot; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Card, GuildMute, HttpServer, Internal, Kook, KookBot, KookMessageEncoder, Permissions, Signal, Type, UserStatus, WsClient, adaptGroup, adaptMessage, adaptSession, adaptUser, decodeGuildMember, decodeRole, encodeRole, hasPermission, isDirectChannel }); //# sourceMappingURL=index.cjs.map