koishi-plugin-onebot-manager
Version:
适用于 Onebot 的 QQ 群管,可自动处理好友申请、群邀请和入群请求,提供群组管理功能
1,138 lines (1,131 loc) • 53.7 kB
JavaScript
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 name2 in all)
__defProp(target, name2, { get: all[name2], 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, {
Config: () => Config,
apply: () => apply,
inject: () => inject,
name: () => name,
usage: () => usage
});
module.exports = __toCommonJS(src_exports);
var import_koishi2 = require("koishi");
// src/request.ts
var OnebotRequest = class {
/**
* 创建 OneBot 请求处理实例
* @param ctx - Koishi 上下文
* @param logger - 日志记录器
* @param config - 配置项
*/
constructor(ctx, logger, config = {}) {
this.ctx = ctx;
this.logger = logger;
this.config = config;
}
static {
__name(this, "OnebotRequest");
}
pendingRequests = /* @__PURE__ */ new Map();
requestNumberMap = /* @__PURE__ */ new Map();
nextRequestNumber = 1;
activeRequests = /* @__PURE__ */ new Map();
/**
* 生成请求的唯一键
* @param session - Koishi 会话
* @param type - 请求类型
* @returns 请求唯一键
*/
getRequestKey(session, type) {
return type === "friend" ? `friend:${session.userId}` : type === "guild" ? `guild:${session.guildId}` : `member:${session.userId}:${session.guildId}`;
}
/**
* 取消活动中的请求
* @param requestKey - 请求唯一键
*/
cancelActiveRequest(requestKey) {
const activeRequest = this.activeRequests.get(requestKey);
if (!activeRequest) return;
activeRequest.disposer?.();
if (activeRequest.timeoutTimer) clearTimeout(activeRequest.timeoutTimer);
if (activeRequest.requestNumber !== void 0) this.requestNumberMap.delete(activeRequest.requestNumber);
this.activeRequests.delete(requestKey);
}
/**
* 处理收到的请求
* @param session - Koishi 会话
* @param type - 请求类型
*/
async processRequest(session, type) {
const requestKey = this.getRequestKey(session, type);
this.cancelActiveRequest(requestKey);
const requestMode = this.config[`${type}Request`] || "reject";
const needsNotification = requestMode === "manual" || requestMode === "auto";
let notificationSent = false;
try {
if (needsNotification) notificationSent = await this.setupNotification(session, type, requestKey, requestMode === "manual");
if (requestMode === "manual" && notificationSent) return;
let approve = false;
let reason = "";
if (requestMode === "accept") {
approve = true;
} else if (requestMode === "auto") {
const result = await this.shouldAutoAccept(session, type);
approve = result === true;
reason = typeof result === "string" ? result : "条件不符";
} else if (requestMode === "manual" && !notificationSent) {
reason = "通知失败,已自动拒绝";
}
await this.processRequestAction(session, type, approve, reason);
} catch (error) {
this.logger.error(`处理请求${requestKey}失败: ${error}`);
try {
await this.processRequestAction(session, type, false, "处理出错");
} catch {
}
} finally {
if (requestMode !== "manual" || !notificationSent) this.cleanupRequest(requestKey);
}
}
/**
* 清理请求数据
* @param requestId - 请求 ID
*/
cleanupRequest(requestId) {
this.pendingRequests.delete(requestId);
for (const [num, id] of this.requestNumberMap.entries()) if (id === requestId) this.requestNumberMap.delete(num);
}
/**
* 检查用户条件是否满足自动接受要求
* @param session - Koishi 会话
* @param regTimeLimit - 注册时间要求(年数,-1表示不检查)
* @param levelLimit - QQ等级要求(-1表示不检查)
* @param vipLevelLimit - VIP等级要求(-1表示不检查)
* @returns 是否满足条件,如不满足返回原因
*/
async checkUserConditions(session, regTimeLimit = -1, levelLimit = -1, vipLevelLimit = -1) {
if (regTimeLimit < 0 && levelLimit < 0 && vipLevelLimit < 0) return false;
try {
const userInfo = await session.onebot.getStrangerInfo(Number(session.userId), false);
const regTime = userInfo.reg_time || userInfo.regTime || 0;
const regYear = regTime > 0 ? new Date(regTime * 1e3).getFullYear() : (/* @__PURE__ */ new Date()).getFullYear();
if (regTimeLimit >= 0 && (/* @__PURE__ */ new Date()).getFullYear() - regYear < regTimeLimit) return `注册时间不满${regTimeLimit}年`;
if (levelLimit >= 0 && (userInfo.level || userInfo.qqLevel || 0) < levelLimit) return `QQ等级低于${levelLimit}级`;
if (vipLevelLimit >= 0 && (!userInfo.is_vip || (userInfo.vip_level || 0) < vipLevelLimit)) return `会员等级低于${vipLevelLimit}级`;
return true;
} catch (error) {
return `获取用户信息失败: ${error}`;
}
}
/**
* 判断是否应自动接受请求
* @param session - Koishi 会话
* @param type - 请求类型
* @returns 是否接受,如不接受返回原因
*/
async shouldAutoAccept(session, type) {
if (type === "friend" || type === "member") {
const prefix = type === "friend" ? "Friend" : "Member";
return this.checkUserConditions(
session,
this.config[`${prefix}RegTime`] ?? -1,
this.config[`${prefix}Level`] ?? -1,
this.config[`${prefix}VipLevel`] ?? -1
);
}
if (type === "guild") {
const { GuildAllowUsers = [], GuildMinMemberCount = -1, GuildMaxCapacity = -1 } = this.config;
if (GuildAllowUsers.includes(session.userId)) return true;
let user;
try {
user = await this.ctx.database.getUser(session.platform, session.userId);
} catch {
}
if (user?.authority > 1) return true;
if (GuildMinMemberCount >= 0 || GuildMaxCapacity >= 0) {
try {
const info = await session.onebot.getGroupInfo(Number(session.guildId), true);
if (GuildMinMemberCount >= 0 && info.member_count < GuildMinMemberCount) return `群成员数量不足${GuildMinMemberCount}人`;
if (GuildMaxCapacity >= 0 && info.max_member_count < GuildMaxCapacity) return `群最大容量不足${GuildMaxCapacity}人`;
return true;
} catch (error) {
return `获取群信息失败: ${error}`;
}
}
}
return false;
}
/**
* 处理请求操作(接受或拒绝)
* @param session - Koishi 会话
* @param type - 请求类型
* @param approve - 是否接受请求
* @param reason - 拒绝原因
* @param remark - 好友备注(仅适用于好友请求)
* @returns 处理是否成功
*/
async processRequestAction(session, type, approve, reason = "", remark = "") {
try {
const eventData = session.event?._data || {};
if (!approve && type === "guild" && (session.event?.type === "guild-added" || eventData.notice_type === "group_increase")) {
if (reason) {
try {
await session.bot.sendMessage(session.guildId, `将退出该群 ${reason}`);
} catch (error) {
this.logger.warn(`发送退群通知失败: ${error}`);
}
}
try {
await session.onebot.setGroupLeave(Number(session.guildId), false);
return true;
} catch (error) {
this.logger.error(`退出群组 ${session.guildId} 失败: ${error}`);
return false;
}
}
const flag = eventData.flag;
if (!flag) return false;
if (type === "friend") await session.onebot.setFriendAddRequest(flag, approve, remark);
else await session.onebot.setGroupAddRequest(flag, eventData.sub_type ?? "add", approve, approve ? "" : reason);
return true;
} catch (error) {
this.logger.error(`请求处理失败: ${error}`);
return false;
}
}
/**
* 设置通知
* @param session - Koishi 会话
* @param type - 请求类型
* @param requestId - 请求 ID
* @param isManualMode - 是否为手动处理模式
*/
async setupNotification(session, type, requestId, isManualMode) {
const { enableNotify = false, notifyTarget = "" } = this.config;
if (!enableNotify || !notifyTarget) return false;
const [targetType, targetId] = notifyTarget.split(":");
const isPrivate = targetType?.toLowerCase() === "private";
if (!targetId || targetType !== "guild" && targetType !== "private") {
this.logger.warn(`通知目标错误: ${notifyTarget}`);
return false;
}
try {
const requestNumber = this.nextRequestNumber++;
this.requestNumberMap.set(requestNumber, requestId);
if (!this.activeRequests.has(requestId)) {
this.activeRequests.set(requestId, { requestNumber });
} else {
this.activeRequests.get(requestId).requestNumber = requestNumber;
}
const eventData = session.event?._data || {};
let user = null, guild = null, operator = null;
user = await session.bot.getUser?.(session.userId)?.catch(() => null) ?? null;
if (type !== "friend") guild = await session.bot.getGuild?.(session.guildId)?.catch(() => null) ?? null;
if (type === "guild" && eventData.operator_id && eventData.operator_id !== session.userId) {
operator = await session.bot.getUser?.(eventData.operator_id.toString())?.catch(() => null) ?? null;
}
const isDirectBotJoin = type === "guild" && eventData.sub_type !== "invite" && session.userId === session.selfId;
let msg = user?.avatar ? `<image url="${user.avatar}"/>
` : "";
msg += `类型:${type === "friend" ? "好友申请" : type === "member" ? "加群请求" : eventData.sub_type === "invite" ? "群邀请" : "直接入群"}
`;
if (session.userId && !isDirectBotJoin) msg += `用户:${user?.name ? `${user.name}(${session.userId})` : session.userId}
`;
if (type === "guild" && eventData.operator_id && eventData.operator_id !== session.userId) msg += `操作者:${operator?.name ? `${operator.name}(${eventData.operator_id})` : eventData.operator_id}
`;
if (type !== "friend" && session.guildId) msg += `群组:${guild?.name ? `${guild.name}(${session.guildId})` : session.guildId}
`;
if (eventData.comment) msg += `验证信息:${eventData.comment}
`;
const requestMode = this.config[`${type}Request`] || "reject";
msg += `处理模式:${isManualMode ? "人工审核" : requestMode === "auto" ? "自动审核" : requestMode === "accept" ? "自动通过" : "自动拒绝"}
`;
const sendFunc = isPrivate ? (m) => session.bot.sendPrivateMessage(targetId, m) : (m) => session.bot.sendMessage(targetId, m);
await sendFunc(msg);
if (isManualMode) {
this.pendingRequests.set(requestId, { session, type });
this.setupPromptResponse(session, type, requestId, requestNumber, targetId, isPrivate);
}
return true;
} catch (error) {
this.logger.error(`通知发送失败: ${error}`);
return false;
}
}
/**
* 设置人工审核响应监听
*/
async setupPromptResponse(session, type, requestId, requestNumber, targetId, isPrivate) {
const sendFunc = isPrivate ? (msg) => session.bot.sendPrivateMessage(targetId, msg) : (msg) => session.bot.sendMessage(targetId, msg);
await sendFunc(`请回复以下命令处理请求 #${requestNumber}:
通过[y]${requestNumber} [备注] | 拒绝[n]${requestNumber} [理由]`);
let disposed = false;
const disposer = this.ctx.middleware(async (s, next) => {
if (disposed || s.userId !== targetId && s.guildId !== targetId) return next();
const match = s.content.trim().match(new RegExp(`^(y|n|通过|拒绝)(${requestNumber})\\s*(.*)$`));
if (!match) return next();
disposed = true;
disposer();
this.cleanupRequest(requestId);
const isApprove = match[1] === "y" || match[1] === "通过";
const extraContent = match[3]?.trim() || "";
try {
await this.processRequestAction(
session,
type,
isApprove,
!isApprove ? extraContent : "",
isApprove && type === "friend" ? extraContent : ""
);
await sendFunc(`请求 #${requestNumber} 已${isApprove ? "通过" : "拒绝"}${extraContent ? `,${isApprove ? "备注" : "原因"}:${extraContent}` : ""}`);
} catch (error) {
this.logger.error(`响应处理失败: ${error}`);
await sendFunc(`处理请求 #${requestNumber} 失败: ${error.message || "未知错误"}`);
}
this.activeRequests.delete(requestId);
});
const activeRequest = this.activeRequests.get(requestId) || {};
activeRequest.disposer = disposer;
this.activeRequests.set(requestId, activeRequest);
const timeoutMin = typeof this.config.manualTimeout === "number" ? this.config.manualTimeout : 60;
const timeoutAction = this.config.manualTimeoutAction === "accept" || this.config.manualTimeoutAction === "reject" ? this.config.manualTimeoutAction : "reject";
if (timeoutMin > 0) {
const timeoutTimer = setTimeout(async () => {
if (disposed) return;
disposed = true;
disposer();
this.cleanupRequest(requestId);
try {
await this.processRequestAction(
session,
type,
timeoutAction === "accept",
timeoutAction === "reject" ? "请求处理超时,已自动拒绝" : ""
);
await sendFunc(`请求 #${requestNumber} 超时,已自动${timeoutAction === "accept" ? "通过" : "拒绝"}`);
} catch (e) {
this.logger.error(`超时处理失败: ${e}`);
}
this.activeRequests.delete(requestId);
}, timeoutMin * 60 * 1e3);
activeRequest.timeoutTimer = timeoutTimer;
this.activeRequests.set(requestId, activeRequest);
}
}
/**
* 注册事件监听器,自动处理 OneBot 请求事件
*/
registerEventListeners() {
const handleRequest = /* @__PURE__ */ __name((type) => async (session) => {
const data = session.event?._data || {};
session.userId = (data.user_id || data.userId || session.userId)?.toString();
if (type !== "friend") session.guildId = (data.group_id || data.groupId || session.guildId)?.toString() || "";
await this.processRequest(session, type);
}, "handleRequest");
this.ctx.on("friend-request", handleRequest("friend"));
this.ctx.on("guild-request", handleRequest("guild"));
this.ctx.on("guild-member-request", handleRequest("member"));
this.ctx.on("guild-added", handleRequest("guild"));
}
};
// src/utils.ts
var import_koishi = require("koishi");
var ROLE_MAP = { owner: "群主", admin: "管理员", member: "成员" };
var getRoleName = /* @__PURE__ */ __name((role) => ROLE_MAP[role] || role || "未知", "getRoleName");
var utils = {
/**
* 解析目标字符串,返回QQ号或null
*/
parseTarget(target) {
if (!target) return null;
try {
const at = import_koishi.h.select(import_koishi.h.parse(target), "at")[0]?.attrs?.id;
if (at && !isNaN(Number(at))) return at;
const match = target.match(/@?(\d{5,10})/)?.[1];
return match && !isNaN(Number(match)) ? match : null;
} catch {
return null;
}
},
/**
* 处理错误并发送提示消息
*/
handleError(session, error) {
const errorMsg = error?.message || String(error);
return session.send(errorMsg).then((msg) => {
if (typeof msg === "string")
setTimeout(() => session.bot.deleteMessage(session.channelId, msg).catch(() => {
}), 1e4);
return null;
});
},
/**
* 检查机器人和用户在群内的权限角色
*/
async checkPermission(session, logger) {
if (!session.guildId) return { bot: null, user: null };
try {
const [bot, user] = await Promise.all([
session.onebot.getGroupMemberInfo(+session.guildId, +session.selfId, true),
session.onebot.getGroupMemberInfo(+session.guildId, +session.userId, true)
]);
return { bot: bot?.role ?? null, user: user?.role ?? null };
} catch (e) {
logger?.error("获取群成员信息失败:", e);
return { bot: null, user: null };
}
},
/**
* 包装函数,执行前检查机器人和用户的群权限
*/
withRoleCheck(session, logger, requiredBotRoles = [], requiredUserRoles = [], fn) {
return (...args) => utils.checkPermission(session, logger).then(({ bot, user }) => {
const errors = [];
if (requiredBotRoles.length && (!bot || !requiredBotRoles.includes(bot))) {
errors.push(`需要${requiredBotRoles.map(getRoleName).join("或")}(当前为${getRoleName(bot)})`);
}
if (requiredUserRoles.length && (!user || !requiredUserRoles.includes(user))) {
errors.push(`用户需要${requiredUserRoles.map(getRoleName).join("或")}(当前为${getRoleName(user)})`);
}
if (errors.length) return utils.handleError(session, `权限不足:${errors.join(";")}`);
return fn(...args);
});
}
};
// src/command.ts
function getTitleLen(title) {
return Array.from(title).reduce((len, char) => {
const code = char.codePointAt(0);
if (code && (code >= 126976 && code <= 131071 || code >= 9728 && code <= 9983 || code >= 9984 && code <= 10175 || code === 12349 || code === 8265 || code === 8252 || code === 8505 || code >= 8192 && code <= 8207 || code >= 8232 && code <= 8239 || code === 8287 || code >= 8293 && code <= 8303 || code >= 8400 && code <= 8447 || code >= 8448 && code <= 8527 || code >= 8960 && code <= 9215 || code >= 11008 && code <= 11263 || code >= 10496 && code <= 10623 || code >= 12800 && code <= 13055 || code >= 55296 && code <= 57343 || code >= 65024 && code <= 65039 || code >= 65520 && code <= 65535)) {
return len + 6;
}
if (code && code >= 32 && code <= 126) {
return len + 1;
}
return len + 3;
}, 0);
}
__name(getTitleLen, "getTitleLen");
function getGroupId(options, session) {
const groupId = options.group ? Number(options.group) : Number(session.guildId);
if (isNaN(groupId) || groupId <= 0) throw new Error("无效群号");
return groupId;
}
__name(getGroupId, "getGroupId");
async function getTargetId(target, session, utils2, groupId, roleCheck = false) {
if (!target) return session.userId;
const parsed = utils2.parseTarget(target);
if (!parsed) return "无效成员";
if (!roleCheck) return parsed;
try {
const info = await session.onebot.getGroupMemberInfo(groupId, Number(session.userId), true);
return info?.role !== "member" ? parsed : session.userId;
} catch {
return "获取成员信息失败";
}
}
__name(getTargetId, "getTargetId");
function createCommandAction(utils2, logger, botRoles, userRoles, actionFn) {
return ({ session, options }, ...args) => utils2.withRoleCheck(
session,
logger,
botRoles,
userRoles,
() => {
try {
return actionFn(session, options, ...args);
} catch (error) {
return utils2.handleError(session, error);
}
}
)();
}
__name(createCommandAction, "createCommandAction");
function adminAction(set, utils2, logger) {
return createCommandAction(
utils2,
logger,
["owner"],
["owner", "admin"],
async (session, options, target) => {
if (!target) return "请指定成员";
const groupId = getGroupId(options, session);
const targetId = utils2.parseTarget(target);
if (!targetId) return "无效的成员ID";
await session.onebot.setGroupAdmin(groupId, Number(targetId), set);
return set ? `已设置成员 ${targetId} 为管理` : `已取消成员 ${targetId} 的管理`;
}
);
}
__name(adminAction, "adminAction");
function registerCommands(qgroup, logger, utils2) {
qgroup.subcommand("tag [title:string] [target]", "设置专属头衔").option("group", "-g, --group <groupId> 指定群号").usage("设置或清除指定成员的群头衔\n使用引号添加不连续的内容,最多18字符\n英文(标点)和数字1字符,中文和其他符号3字符,Emoji6字符").action(createCommandAction(
utils2,
logger,
["owner"],
[],
async (session, options, title = "", target) => {
if (title && getTitleLen(title) > 18) return "设置头衔失败: 长度超过18字符";
const groupId = getGroupId(options, session);
const targetId = await getTargetId(target, session, utils2, groupId, !!target);
await session.onebot.setGroupSpecialTitle(groupId, Number(targetId), title);
return `已${title ? "将" : "清除"}${targetId === session.userId ? "您" : `用户 ${targetId}`}的头衔${title ? `设置为:${title}` : ""}`;
}
));
qgroup.subcommand("membercard [card:string] [target]", "设置群名片").option("group", "-g, --group <groupId> 指定群号").usage("设置或清除指定成员的群名片").action(createCommandAction(
utils2,
logger,
["owner", "admin"],
["owner", "admin"],
async (session, options, card = "", target) => {
const groupId = getGroupId(options, session);
const targetId = await getTargetId(target, session, utils2, groupId, !!target);
await session.onebot.setGroupCard(groupId, Number(targetId), card);
return `已${card ? "将" : "清除"}${targetId === session.userId ? "您" : `用户 ${targetId}`}的群名片${card ? `设置为:${card}` : ""}`;
}
));
qgroup.subcommand("groupname <group_name:string>", "设置群名称").option("group", "-g, --group <groupId> 指定群号").usage("设置当前群的名称").action(createCommandAction(
utils2,
logger,
["owner", "admin"],
["owner", "admin"],
async (session, options, group_name) => {
if (!group_name) return "请输入群名";
const groupId = getGroupId(options, session);
await session.onebot.setGroupName(groupId, group_name);
return `已将群名设置为:${group_name}`;
}
));
const essence = qgroup.subcommand("essence [messageId:string]", "设置精华消息").option("group", "-g, --group <groupId> 指定群号").usage("设置指定消息为精华消息").action(createCommandAction(
utils2,
logger,
["owner", "admin"],
["owner", "admin"],
async (session, options, messageId) => {
messageId = messageId || session.quote?.id;
if (!messageId) return "请提供消息ID或引用消息";
await session.onebot.setEssenceMsg(messageId);
return "已设置精华消息";
}
));
essence.subcommand(".del [messageId:string]", "移除精华消息").option("group", "-g, --group <groupId> 指定群号").usage("移除指定消息的精华消息").action(createCommandAction(
utils2,
logger,
["owner", "admin"],
["owner", "admin"],
async (session, options, messageId) => {
messageId = messageId || session.quote?.id;
if (!messageId) return "请提供消息ID或引用消息";
await session.onebot.deleteEssenceMsg(messageId);
return "已移除精华消息";
}
));
const admin = qgroup.subcommand("admin <target>", "设置群管理").option("group", "-g, --group <groupId> 指定群号").usage("设置指定成员为群管理").action(adminAction(true, utils2, logger));
admin.subcommand(".del <target>", "取消群管理").option("group", "-g, --group <groupId> 指定群号").usage("取消指定成员的群管理").action(adminAction(false, utils2, logger));
const mute = qgroup.subcommand("mute <target> [duration]", "禁言群成员").option("cancel", "-c, --cancel 取消禁言").option("group", "-g, --group <groupId> 指定群号").usage("禁言指定成员,默认 30 分钟").action(createCommandAction(
utils2,
logger,
["owner", "admin"],
["owner", "admin"],
async (session, options, target, duration) => {
const groupId = getGroupId(options, session);
const targetId = utils2.parseTarget(target);
if (!targetId) return "请指定有效成员";
const banDuration = options.cancel ? 0 : duration ? Number(duration) : 1800;
await session.onebot.setGroupBan(groupId, Number(targetId), banDuration);
return options.cancel ? `已取消禁言成员 ${targetId}` : `已禁言成员 ${targetId} ${banDuration} 秒`;
}
));
mute.subcommand(".all [enable:boolean]", "全体禁言").option("group", "-g, --group <groupId> 指定群号").usage("开启或关闭全体禁言").action(createCommandAction(
utils2,
logger,
["owner", "admin"],
["owner", "admin"],
async (session, options, enable) => {
const val = typeof enable === "boolean" ? enable : true;
const groupId = getGroupId(options, session);
await session.onebot.setGroupWholeBan(groupId, val);
return val ? "已开启全体禁言" : "已关闭全体禁言";
}
));
qgroup.subcommand("kick <target>", "逐出群成员").option("reject", "-r, --reject 拒绝再次加群").option("group", "-g, --group <groupId> 指定群号").usage("逐出指定成员,使用 -r 拒绝此人再次加群").action(createCommandAction(
utils2,
logger,
["owner", "admin"],
["owner", "admin"],
async (session, options, target) => {
const targetId = utils2.parseTarget(target);
if (!targetId) return "请指定有效的成员";
const groupId = getGroupId(options, session);
await session.onebot.setGroupKick(groupId, Number(targetId), !!options.reject);
return `已将成员 ${targetId} 逐出群${options.reject ? ",并拒绝其再次加群" : ""}`;
}
));
qgroup.subcommand("revoke", "撤回消息").option("group", "-g, --group <groupId> 指定群号").usage("撤回指定回复消息(仅限撤回自己的消息)").action(createCommandAction(
utils2,
logger,
["owner", "admin"],
[],
async (session) => {
const messageId = session.quote?.id;
if (!messageId) return "请回复需要撤回的消息";
let senderId = session.quote.user.id;
if (senderId && String(senderId) === session.userId) {
await session.onebot.deleteMsg(messageId);
return "";
}
}
));
}
__name(registerCommands, "registerCommands");
// src/onebot.ts
var Onebot = class _Onebot {
static {
__name(this, "Onebot");
}
static sexMap = {
"male": "男",
"female": "女"
};
/**
* 分页处理
* @param session 会话对象
* @param data 数据数组
* @param page 页码或'all'
* @param pageSize 每页数量
* @returns 分页结果
*/
handlePagination(session, data, page, pageSize = 10) {
if (page === "all") return { displayData: data, pageInfo: ":\n", totalPages: 1 };
const totalPages = Math.ceil(data.length / pageSize);
const pageNum = parseInt(page) || 1;
if (isNaN(pageNum) || pageNum < 1 || (pageNum - 1) * pageSize >= data.length) {
utils.handleError(session, new Error("操作失败: 无效页码"));
return null;
}
const start = (pageNum - 1) * pageSize;
return { displayData: data.slice(start, start + pageSize), pageInfo: `(第 ${pageNum}/${totalPages} 页):
`, totalPages };
}
/**
* 格式化用户信息
* @param info 用户信息对象
* @returns 格式化字符串
*/
static formatUserInfo(info) {
let result = `${info.nickname || info.nick}(${info.user_id || info.uin})
`;
if (info.qid) result += `QID: ${info.qid}
`;
if (info.uid) result += `UID: ${info.uid}
`;
if (info.long_nick || info.longNick) result += `个性签名:
${info.long_nick || info.longNick}
`;
result += "\n个人信息: \n";
const personalInfo = [
info.sex && info.sex !== "unknown" ? _Onebot.sexMap[info.sex] || info.sex : "",
info.age ? `${info.age}岁` : "",
info.birthday_year && info.birthday_month && info.birthday_day ? `${info.birthday_year}-${info.birthday_month}-${info.birthday_day}` : ""
].filter(Boolean);
if (personalInfo.length) result += `${personalInfo.join(" | ")}
`;
const shengXiaos = ["", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"];
const constellations = ["", "水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", "天蝎座", "射手座", "摩羯座"];
const bloodTypes = ["", "A型", "B型", "AB型", "O型"];
const zodiacInfo = [
info.shengXiao && shengXiaos[info.shengXiao],
info.constellation && constellations[info.constellation],
info.kBloodType && bloodTypes[info.kBloodType]
].filter(Boolean);
if (zodiacInfo.length) result += `${zodiacInfo.join(" | ")}
`;
const contactInfo = [info.phoneNum, info.eMail].filter((x) => x && x !== "-");
if (contactInfo.length) result += `${contactInfo.join(" | ")}
`;
let locationLine = [info.country, info.province, info.city].filter(Boolean).join(" ");
if (info.homeTown && info.homeTown !== "0-0-0") {
const [province, city] = info.homeTown.split("-").map(Number);
if (province > 0 || city > 0) locationLine += (locationLine ? " | " : "") + `家乡: ${province}-${city}`;
}
if (locationLine) result += `${locationLine}
`;
const educationInfo = [info.college, info.pos].filter(Boolean);
if (educationInfo.length) result += `${educationInfo.join(" | ")}
`;
result += "\n账号信息: \n";
const statusMap = { 10: "离线", 20: "在线", 30: "离开", 40: "忙碌", 50: "请勿打扰", 60: "隐身" };
const termTypes = ["", "电脑", "手机", "网页", "平板"];
const netTypes = ["", "WiFi", "移动网络", "有线网络"];
const eNetworkTypes = { 1: "2G网络", 2: "3G网络", 3: "4G网络", 4: "5G网络", 5: "WiFi" };
const accountInfo = [
info.is_vip || info.vip_level ? info.is_years_vip ? `年VIP${info.vip_level || ""}` : `VIP${info.vip_level || ""}` : "",
info.qqLevel ? `Lv:${info.qqLevel}` : "",
info.status !== void 0 && statusMap[info.status] ? statusMap[info.status] : "",
info.batteryStatus >= 0 && info.batteryStatus <= 100 ? `电量${info.batteryStatus}%` : "",
info.termType && termTypes[info.termType] ? info.termDesc ? `${termTypes[info.termType]}(${info.termDesc})` : termTypes[info.termType] : "",
[info.netType && netTypes[info.netType], info.eNetworkType && eNetworkTypes[info.eNetworkType]].filter(Boolean).join("-")
].filter(Boolean);
if (accountInfo.length) result += `${accountInfo.join(" | ")}
`;
if (info.regTime || info.reg_time) {
const regDate = new Date((info.regTime || info.reg_time) * 1e3);
result += `注册于: ${regDate.toLocaleDateString()}${info.login_days ? ` (登录${info.login_days}天)` : ""}
`;
}
return result;
}
/**
* 格式化好友信息
* @param friend 好友信息对象
* @returns 格式化字符串
*/
static formatFriendInfo(friend) {
let result = `${friend.nickname}(${friend.user_id})${friend.level ? ` | LV:${friend.level}` : ""}
`;
const personalInfo = [friend.remark, friend.sex && friend.sex !== "unknown" ? _Onebot.sexMap[friend.sex] || friend.sex : "", friend.age > 0 ? `${friend.age}岁` : ""].filter(Boolean);
if (friend.birthday_year || friend.birthday_month || friend.birthday_day) {
personalInfo.push(`${friend.birthday_year || "?"}-${friend.birthday_month || "?"}-${friend.birthday_day || "?"}`);
}
if (personalInfo.length) result += `- ${personalInfo.join(" | ")}
`;
const contactInfo = [friend.phone_num, friend.email].filter((x) => x && x.trim() && x !== "-");
if (contactInfo.length) result += `- ${contactInfo.join(" | ")}
`;
return result;
}
/**
* 格式化群信息
* @param info 群信息对象
* @returns 格式化字符串
*/
static formatGroupInfo(info) {
return `${info.group_name}(${info.group_id}) [${info.member_count}/${info.max_member_count}]${info.group_remark?.trim() ? `
备注: ${info.group_remark}` : ""}`;
}
/**
* 格式化群成员信息
* @param member 群成员信息对象
* @returns 格式化字符串
*/
static formatGroupMemberInfo(member) {
const roleMap = { owner: "群主", admin: "管理员", member: "成员" };
let result = `成员 ${member.card?.trim() ? `[${member.card}]` : ""}${member.nickname}(${member.user_id}) 信息:
`;
const identityInfo = [
member.level && member.level !== "0" ? `LV${member.level}` : "",
member.title?.trim() || "",
member.card?.trim() || "",
member.role !== "member" ? roleMap[member.role] || member.role : "",
member.is_robot ? "Bot" : ""
].filter(Boolean);
if (identityInfo.length) result += `- ${identityInfo.join(" | ")}
`;
const personalInfo = [
member.qq_level > 0 ? `LV${member.qq_level}` : "",
member.sex && member.sex !== "unknown" ? _Onebot.sexMap[member.sex] || member.sex : "",
member.age > 0 ? `${member.age}岁` : "",
member.area?.trim() || ""
].filter(Boolean);
if (personalInfo.length) result += `- ${personalInfo.join(" | ")}
`;
if (member.shut_up_timestamp > Math.floor(Date.now() / 1e3)) {
const shutUpEnd = new Date(member.shut_up_timestamp * 1e3);
result += `- 禁言至: ${shutUpEnd.toLocaleDateString()} ${shutUpEnd.toLocaleTimeString()}
`;
}
if (member.join_time) result += `- 入群时间: ${new Date(member.join_time * 1e3).toLocaleString()}
`;
if (member.last_sent_time) result += `- 最后发言: ${new Date(member.last_sent_time * 1e3).toLocaleString()}`;
return result;
}
/**
* 提取语音文件名
* @param content 消息内容
* @returns 文件名或null
*/
static extractAudioFile(content) {
if (!content) return null;
return /<audio.*?file="(.*?)".*?\/>/i.exec(content)?.[1] || /\[CQ:record,file=(.*?)(?:,|])/i.exec(content)?.[1] || /"file"\s*:\s*"([^"]+)"/i.exec(content)?.[1] || null;
}
/**
* 提取文件ID
* @param content 消息内容
* @returns 文件ID或null
*/
static extractFileId(content) {
if (!content) return null;
return /<file.*?id="(.*?)".*?\/>/i.exec(content)?.[1] || /\[CQ:file,file=(?:.*?),id=(.*?)(?:,|])/i.exec(content)?.[1] || /"file_id"\s*:\s*"([^"]+)"/i.exec(content)?.[1] || null;
}
/**
* 提取图片文件名
* @param content 消息内容
* @returns 文件名或null
*/
static extractImageFile(content) {
if (!content) return null;
return /<image.*?file="([^"]+)".*?\/>/i.exec(content)?.[1] || /<img.*?file="([^"]+)".*?\/>/i.exec(content)?.[1] || /\[CQ:image,(?:.*?,)?file=([^,\]]+)(?:,|])/i.exec(content)?.[1] || /"file"(?:\s*):(?:\s*)"([^"]+)"/i.exec(content)?.[1] || /https?:\/\/[^\s"'<>]+\.(jpg|jpeg|png|gif|bmp|webp)/i.exec(content)?.[0] || null;
}
/**
* 注册onebot相关命令
* @param qgroup qgroup命令对象
*/
registerCommands(qgroup) {
qgroup.subcommand(".restart", "重启 OneBot", { authority: 5 }).usage("重启 OneBot 实现和 API 服务").action(async ({ session }) => {
try {
await session.onebot.setRestart(2e3);
return "正在重启 OneBot,请稍候...";
} catch (e) {
return utils.handleError(session, e);
}
});
qgroup.subcommand(".clean", "清理缓存", { authority: 4 }).usage("清理积攒的缓存文件").action(async ({ session }) => {
try {
await session.onebot.cleanCache();
return "清理缓存成功";
} catch (e) {
return utils.handleError(session, e);
}
});
const get = qgroup.subcommand("get", "获取消息内容及状态").usage("获取指定ID消息的完整内容").option("id", "-i <id:string> 消息ID").action(async ({ session, options }) => {
let messageId = options.id || session.quote?.id || session.messageId;
try {
const msg = await session.onebot.getMsg(messageId);
return JSON.stringify(msg, null, 2);
} catch (e) {
return utils.handleError(session, e);
}
});
get.subcommand(".forward", "获取合并转发内容").usage("获取指定合并转发ID消息的完整内容").option("id", "-i <id:string> 合并转发ID").action(async ({ session, options }) => {
let messageId = options.id || session.quote?.id || session.messageId;
try {
const msg = await session.onebot.getForwardMsg(messageId);
return JSON.stringify(msg, null, 2);
} catch (e) {
return utils.handleError(session, e);
}
});
get.subcommand(".record", "获取语音文件", { authority: 2 }).usage("获取指定语音文件并转换格式").option("file", "-f <file:string> 文件名", { type: "string" }).option("format", "-t <format:string> 转换格式 (mp3/amr/wma/m4a/spx/ogg/wav/flac)", { fallback: "mp3" }).action(async ({ session, options }) => {
let fileName = options.file || session.quote && _Onebot.extractAudioFile(session.quote.content);
if (!fileName) return utils.handleError(session, new Error("未发现语音文件"));
try {
const result = await session.onebot.getRecord(fileName, options.format);
return `语音文件路径: ${result.file}`;
} catch (e) {
return utils.handleError(session, e);
}
});
get.subcommand(".image", "获取图片文件", { authority: 2 }).usage("获取指定图片文件的本地路径").option("file", "-f <file:string> 文件名", { type: "string" }).action(async ({ session, options }) => {
let fileName = options.file || session.quote && _Onebot.extractImageFile(session.quote.content);
if (!fileName) return utils.handleError(session, new Error("未发现图片文件"));
try {
const result = await session.onebot.getImage(fileName);
return `图片文件路径: ${result.file}`;
} catch (e) {
return utils.handleError(session, e);
}
});
get.subcommand(".file", "获取文件信息", { authority: 2 }).usage("获取指定文件ID对应的文件信息").option("id", "-i <id:string> 文件ID").action(async ({ session, options }) => {
let fileId = options.id || session.quote && _Onebot.extractFileId(session.quote.content);
if (!fileId) return utils.handleError(session, new Error("未发现文件"));
try {
const fileInfo = await session.onebot._request("get_file", { file_id: fileId });
let result = "文件信息:\n";
if (fileInfo.file_name) result += `文件名: ${fileInfo.file_name}
`;
if (fileInfo.file_size) result += `文件大小: ${fileInfo.file_size}
`;
if (fileInfo.file) result += `文件路径: ${fileInfo.file}
`;
if (fileInfo.url) result += `文件链接: ${fileInfo.url}
`;
if (fileInfo.base64) result += `文件Base64长度: ${fileInfo.base64.length}字符
`;
return result;
} catch (e) {
return utils.handleError(session, e);
}
});
get.subcommand(".stat", "获取运行状态").usage("获取运行状态信息").action(async ({ session }) => {
try {
const status = await session.onebot.getStatus();
let result = `运行状态: ${status.online ? "在线" : "离线"} | ${status.good ? "正常" : "异常"}
`;
Object.entries(status).forEach(([k, v]) => {
if (k !== "online" && k !== "good") result += `${k}: ${JSON.stringify(v)}
`;
});
return result;
} catch (e) {
return utils.handleError(session, e);
}
});
get.subcommand(".ver", "获取版本信息").usage("获取版本信息").action(async ({ session }) => {
try {
const version = await session.onebot.getVersionInfo();
let result = `应用标识: ${version.app_name}
应用版本: ${version.app_version}
协议版本: ${version.protocol_version}
`;
Object.entries(version).forEach(([k, v]) => {
if (!["app_name", "app_version", "protocol_version"].includes(k)) result += `${k}: ${JSON.stringify(v)}
`;
});
return result;
} catch (e) {
return utils.handleError(session, e);
}
});
get.subcommand(".csrf [domain:string]", "获取相关接口凭证", { authority: 4 }).usage("获取指定域名的Cookies和CSRF Token").action(async ({ session }, domain) => {
try {
const credentials = await session.onebot.getCredentials(domain || "");
return `接口凭证信息:
CSRF Token: ${credentials.csrf_token}
Cookies: ${credentials.cookies}`;
} catch (e) {
return utils.handleError(session, e);
}
});
const info = qgroup.subcommand("info", "查询账号信息", { authority: 5 }).usage("查询当前账号的基本信息").option("no-cache", "-n 不使用缓存", { fallback: false }).action(async ({ session, options }) => {
try {
const loginInfo = await session.onebot.getLoginInfo();
try {
const detailInfo = await session.onebot.getStrangerInfo(loginInfo.user_id, options["no-cache"]);
return _Onebot.formatUserInfo(detailInfo);
} catch {
return `账号信息:
${loginInfo.nickname}(${loginInfo.user_id})`;
}
} catch (e) {
return utils.handleError(session, e);
}
});
info.subcommand(".user <user_id:string>", "查询其它账号信息").usage("查询指定账号的基本信息").option("no-cache", "-n 不使用缓存", { fallback: false }).action(async ({ session, options }, user_id) => {
const parsedId = utils.parseTarget(user_id);
if (!parsedId) return utils.handleError(session, new Error("请提供QQ号"));
try {
const botInfo = await session.onebot.getLoginInfo();
if (parsedId === botInfo.user_id.toString()) return utils.handleError(session, new Error("不允许查询自身信息"));
const info2 = await session.onebot.getStrangerInfo(+parsedId, options["no-cache"]);
return _Onebot.formatUserInfo(info2);
} catch (e) {
return utils.handleError(session, e);
}
});
info.subcommand(".myfriend [page:string]", "获取本账号好友列表", { authority: 4 }).usage("获取本账号的完整好友列表及备注").action(async ({ session }, page) => {
try {
const friends = await session.onebot.getFriendList();
let result = `好友数量: ${friends.length}`;
const pagination = this.handlePagination(session, friends, page);
if (!pagination) return;
result += pagination.pageInfo;
pagination.displayData.forEach((friend) => result += _Onebot.formatFriendInfo(friend));
return result;
} catch (e) {
return utils.handleError(session, e);
}
});
info.subcommand(".mygroup [page:string]", "获取本账号群组列表", { authority: 4 }).usage("获取本账号加入的群组列表").action(async ({ session }, page) => {
try {
const groups = await session.onebot.getGroupList();
let result = `群数量: ${groups.length}`;
const pagination = this.handlePagination(session, groups, page);
if (!pagination) return;
result += pagination.pageInfo;
pagination.displayData.forEach((group) => result += _Onebot.formatGroupInfo(group) + "\n");
return result;
} catch (e) {
return utils.handleError(session, e);
}
});
info.subcommand(".group [group_id:number]", "查询群信息").usage("查询指定群的基本信息").option("no-cache", "-n 不使用缓存", { fallback: false }).action(async ({ session, options }, group_id) => {
group_id = group_id || +session.guildId;
if (!group_id) return utils.handleError(session, new Error("请提供群号"));
try {
const info2 = await session.onebot.getGroupInfo(group_id, options["no-cache"]);
return _Onebot.formatGroupInfo(info2);
} catch (e) {
return utils.handleError(session, e);
}
});
info.subcommand(".groupuser <user_id:string> [group_id:number]", "查询群成员信息").usage("查询群内指定成员的基本信息").option("no-cache", "-n 不使用缓存", { fallback: false }).action(async ({ session, options }, user_id, group_id) => {
const parsedId = utils.parseTarget(user_id);
if (!parsedId) return utils.handleError(session, new Error("请提供QQ号"));
group_id = group_id || +session.guildId;
if (!group_id) return utils.handleError(session, new Error("请提供群号"));
try {
const info2 = await session.onebot.getGroupMemberInfo(group_id, +parsedId, options["no-cache"]);
return _Onebot.formatGroupMemberInfo(info2);
} catch (e) {
return utils.handleError(session, e);
}
});
info.subcommand(".memberlist [group_id:number] [page:string]", "获取群成员列表").usage("获取指定群的成员列表").action(async ({ session }, group_id, page) => {
group_id = group_id || +session.guildId;
if (!group_id) return utils.handleError(session, new Error("请提供群号"));
try {
const members = await session.onebot.getGroupMemberList(group_id);
let result = `群 ${group_id} 成员列表`;
members.sort((a, b) => ({ owner: 0, admin: 1, member: 2 })[a.role] - { owner: 0, admin: 1, member: 2 }[b.role]);
const pagination = this.handlePagination(session, members, page, 5);
if (!pagination) return;
result += pagination.pageInfo;
pagination.displayData.forEach((member) => result += _Onebot.formatGroupMemberInfo(member) + "\n");
return result;
} catch (e) {
return utils.handleError(session, e);
}
});
info.subcommand(".grouphonor [group_id:number]", "查询群荣誉信息").usage("可用参数:\n- talkative: 历史龙王\n- performer: 群聊之火\n- legend: 群聊炽焰\n- strong_newbie: 冒尖小春笋\n- emotion: 快乐之源").option("type", "-t <type> 荣誉类型", { fallback: "all" }).action(async ({ session, options }, group_id) => {
group_id = group_id || +session.guildId;
if (!group_id) return utils.handleError(session, new Error("请提供群号"));
try {
const honorInfo = await session.onebot.getGroupHonorInfo(group_id, options.type);
let result = `群 ${group_id} 荣誉信息:
`;
const honorTypeNames = {
talkative: "历史龙王",
performer: "群聊之火",
legend: "群聊炽焰",
strong_newbie: "冒尖小春笋",
emotion: "快乐之源"
};
if (honorInfo.current_talkative) result += `- 龙王: ${honorInfo.current_talkative.nickname}(${honorInfo.current_talkative.user_id})
`;
for (const type of Object.keys(honorTypeNames)) {
const list = honorInfo[`${type}_list`];
if (list?.length) {
result += `${honorTypeNames[type]} (${list.length}名):
`;
list.slice(0, 5).forEach((item) => result += `- ${item.nickname}(${item.user_id}) | ${item.description}
`);
}
}
return result;
} catch (e) {
return utils.handleError(session, e);
}
});
}
};
// src/index.ts
var name = "onebot-manager";
var inject = { optional: ["database"] };
var usage = `
<div style="border-radius: 10px; border: 1px solid #ddd; padding: 16px; margin-bottom: 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.1);">
<h2 style="margin-top: 0; color: #4a6ee0;">📌 插件说明</h2>
<p>📖 <strong>使用文档</strong>:请点击左上角的 <strong>插件主页</strong> 查看插件使用文档</p>
<p>🔍 <strong>更多插件</strong>:可访问 <a href="https://github.com/YisRime" style="color:#4a6ee0;text-decoration:none;">苡淞的 GitHub</a> 查看本人的所有插件</p>
</div>
<div style="border-radius: 10px; border: 1px solid #ddd; padding: 16px; margin-bottom: 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.1);">
<h2 style="margin-top: 0; color: #e0574a;">❤️ 支持与反馈</h2>
<p>🌟 喜欢这个插件?请在 <a href="https://github.com/YisRime" style="color:#e0574a;text-decoration:none;">GitHub</a> 上给我一个 Star!</p>
<p>🐛 遇到问题?请通过 <strong>Issues</strong> 提交反馈,或加入 QQ 群 <a href="https://qm.qq.com/q/PdLMx9Jowq" style="color:#e0574a;text-decoration:none;"><strong>855571375</strong></a> 进行交流</p>
</div>
`;
var Config = import_koishi2.Schema.intersect([
import_koishi2.Schema.object({
enable: import_koishi2.Schema.boolean().description("开启请求监听").default(true)
}).description("基础配置"),
import_koishi2.Schema.object({
friendRequest: import_koishi2.Schema.union([
import_koishi2.Schema.const("accept").description("同意"),
import_koishi2.Schema.const("reject").description("拒绝"),
import_koishi2.Schema.const("manual").description("手动"),
import_koishi2.Schema.const("auto").description("自动")
]).description("处理好友请求").default("reject"),
memberRequest: import_koishi2.Schema.union([
import_koishi2.Schema.const("accept").description("同意"),
import_koishi2.Schema.const("reject").description("拒绝"),
import_koishi2.Schema.const("manual").description("手动"),
import_koishi2.Schema.const("auto").description("自动")
]).description("处理加群请求").default("reject"),
guildRequest: import_koishi2.Schema.union([
import_koishi2.Schema.const("accept").description("同意"),
import_koishi2.Schema.const("reject").description("拒绝"),
import_koishi2.Schema.const("manual").description("手动"),
import_koishi2.Schema.const("auto").description("自动")
]).description("处理入群邀请").default("reject"),
manualTimeout: import_koishi2.Schema.number().description("手动超时时间(分钟)").default(720).min(0),
manualTimeoutAction: import_koishi2.Schema.union([
import_koishi2.Schema.const("accept").description("同意"),
import_koishi2.Schema.const("reject").description("拒绝")
]).description("超时自动操作").default("reject"),
enableNotify: import_koishi2.Schema.boolean().description("开启请求通知").default(false)
}).description("请求配置"),
import_koishi2.Schema.union([
import_koishi2.Schema.object({
enableNotify: import_koishi2.Schema.const(true).required(),
notifyTarget: import_koishi2.Schema.string().description("通知目标(guild/private)").default("private:10000")
}),
import_koishi2.Schema.object({})
]),
import_koishi2.Schema.union([
import_koishi2.Schema.object({
friendRequest: import_koishi2.Schema.const("auto").required(),
FriendRegTime: import_koishi2.Schema.number().description("最短注册年份").default(-1).min(-1),
FriendLevel: import_koishi2.Schema.number().description("最低QQ等级").default(-1).min(-1).max(256),
FriendVipLevel: import_koishi2.Schema.number().description("最低会员等级").default(-1).min(-1).max(10)
}).description("好友请求通过配置"),
import_koishi2.Schema.object({})
]),
import_koishi2.Schema.union([
import_koishi2.Schema.object({
memberRequest: import_koishi2.Schema.const("auto").required(),
MemberRegTime: import_koishi2.Schema.number().description("最短注册年份").default(-1).min(-1),
MemberLevel: import_koishi2.Schema.number().description("最低QQ等级").default(-1).min(-1).max(256),
MemberVipLevel: import_koishi2.Schema.number().description("最低会员等级").default(-1).min(-1).max(10)
}).description("加群请求通过配置"),
import_koishi2.Schema.object({})
]),
import_koishi2.Schema.union([
import_koishi2.Schema.object({
guildRequest: import_koishi2.Schema.const("auto").required(),
GuildAllowUsers: import_koishi2.Schema.array(String).description("白名单邀请人ID").default([]),
GuildMinMemberCount: import_koishi2.Schema.number().description("最低群成员数量").default(-1).min(-1).max(3e3),
GuildMaxCapacity: import_koishi2.Schema.union([
import_koishi2.Schema.const(-1).description("不限制"),
import_koishi2.Schema.const(200).description("200"),
import_koishi2.Schema.const(500).description("500"),
import_koishi2.Schema.const(1e3).description("1000"),
import_koishi2.Schema.const(2e3).description("2000"),
import_koishi2.Schema.const(3e3).description("3000")
]).description("最低群容量要求").default(-1)
}).description("入群邀请通过配置"),
import_koishi2.Schema.object({})
])
]);
function apply(ctx, config = {}) {
const logger = ctx.logger("onebot-manager");
if (config.enable !== false)
new OnebotRequest(ctx, logger, config).registerEventListeners();
const qgroup = ctx.command("qgroup", "QQ 群管").usage("群管相关功能,需要管理权限");
new Onebot().registerCommands(qgroup);
registerCommands(qgroup, logger, utils);
}
__name(apply, "apply");
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
Config,
apply,
inject,
name,
usage
});