UNPKG

koishi-plugin-emojihub-bili

Version:

[<ruby>Emojihub-bili<rp>(</rp><rt>点我查看食用方法</rt><rp>)</rp></ruby>](https://www.npmjs.com/package/koishi-plugin-emojihub-bili)🐱支持QQ官方json按钮!20群即可发按钮!😍可自定义添加或删除任意表情包!基本每个指令都有上千张!支持定时/定量消息触发![点我查看食用方法](https://www.npmjs.com/package/koishi-plugin-emojihub-bi

235 lines (201 loc) 7.01 kB
import { Context, Session } from "koishi"; import { Config } from "./config"; import { h } from "koishi"; import { replacePlaceholders, logInfo, logError } from "./utils"; import { loadCanvasImageSource } from "./canvas-source"; function clampPage(page: number, totalPages: number) { if (!Number.isFinite(page) || page < 1) return 1; return Math.min(Math.floor(page), totalPages); } function pickColumns(total: number) { if (total < 5) return 1; if (total <= 10) return 2; if (total <= 15) return 3; return 4; } function chunk<T>(items: T[], size: number) { const rows: T[][] = []; for (let i = 0; i < items.length; i += size) { rows.push(items.slice(i, i + size)); } return rows; } function createMarkdownMessage(session: Session) { const markdownMessage: any = { msg_type: 2, markdown: {}, keyboard: {}, }; if (session.messageId) { markdownMessage.msg_id = session.messageId; } return markdownMessage; } function getCommandLabel(rootCommandName: string, command: any) { const fullName = String(command?.name || command?.displayName || "").trim(); const root = String(rootCommandName || "").trim(); if (!fullName) return ""; if (root && fullName.startsWith(`${root}/`)) return fullName.slice(root.length + 1); return fullName.split("/").pop() || fullName; } function collectVisibleCommands(ctx: Context, session: Session, rootCommandName: string) { const rootCommand = ctx.$commander.get(rootCommandName, session) as any; const children = Array.isArray(rootCommand?.children) ? rootCommand.children : []; const entries: Array<[string, any]> = []; for (const command of children) { if (typeof command?.match === "function" && !command.match(session)) continue; const label = getCommandLabel(rootCommandName, command); if (!label) continue; if (entries.some(([existing]) => existing === label)) continue; entries.push([label, command]); } return entries; } function buildKeyboardRows(ctx: Context, session: Session, rootCommandName: string, page: number) { const commands = collectVisibleCommands(ctx, session, rootCommandName); const columns = pickColumns(commands.length); const pageSize = columns * 5; const totalPages = Math.max(1, Math.ceil(commands.length / pageSize)); const currentPage = clampPage(page, totalPages); const pageItems = commands.slice((currentPage - 1) * pageSize, currentPage * pageSize); const rows = chunk(pageItems, columns).map((row) => ({ buttons: row.map(([label]) => ({ render_data: { label, style: 1, }, action: { type: 2, permission: { type: 2 }, data: `/${label}`, enter: true, }, })), })); if (totalPages > 1) { const navButtons: any[] = []; if (currentPage > 1) { navButtons.push({ render_data: { label: "上一页", style: 2 }, action: { type: 2, permission: { type: 2 }, data: `/${rootCommandName} ${currentPage - 1}`, enter: true, }, }); } if (currentPage < totalPages) { navButtons.push({ render_data: { label: "下一页", style: 2 }, action: { type: 2, permission: { type: 2 }, data: `/${rootCommandName} ${currentPage + 1}`, enter: true, }, }); } if (navButtons.length) rows.push({ buttons: navButtons }); } return rows; } export function collectVisibleSubcommands(ctx: Context, session: Session, rootCommandName: string) { return collectVisibleCommands(ctx, session, rootCommandName).map(([label]) => label); } export function command_list_markdown(ctx: Context, session: Session, config: Config, rootCommandName: string, page = 1) { const markdownMessage: any = createMarkdownMessage(session); markdownMessage.markdown = { content: config.nestedlist.raw_markdown_button_content || "", }; try { const rows = buildKeyboardRows(ctx, session, rootCommandName, Number(page) || 1); markdownMessage.keyboard = { content: { rows }, }; } catch (error) { logError(`解析列表 Markdown 出错: ${error}`); return null; } logInfo(config, `列表 Markdown 参数: ${JSON.stringify(markdownMessage, null, 2)}`); return markdownMessage; } export interface MarkdownImageSize { width: number; height: number; } export async function markdown( ctx: Context, session: Session, command, imageUrl, config: Config, localimage?: string, imageSize?: MarkdownImageSize, ) { const markdownMessage: any = createMarkdownMessage(session); let originalWidth: number; let originalHeight: number; const sizeMatch = typeof imageUrl === "string" ? imageUrl.match(/\?px=(\d+)x(\d+)$/) : null; if (imageSize?.width && imageSize?.height) { originalWidth = imageSize.width; originalHeight = imageSize.height; } else if (sizeMatch) { originalWidth = parseInt(sizeMatch[1], 10); originalHeight = parseInt(sizeMatch[2], 10); } else { const loadTarget = localimage || imageUrl; const canvasimage = await loadCanvasImageSource(ctx, String(loadTarget)); // @ts-ignore originalWidth = canvasimage.naturalWidth || canvasimage.width; // @ts-ignore originalHeight = canvasimage.naturalHeight || canvasimage.height; } try { const rawMarkdownContent = config.nested.raw_markdown_button_content; const rawMarkdownKeyboard = config.nested.raw_markdown_button_keyboard; const replacedMarkdownContent = replacePlaceholders(rawMarkdownContent, { session, config, img_pxpx: `img#${originalWidth}px #${originalHeight}px`, img_url: imageUrl, command, }, true); const replacedMarkdownKeyboard = replacePlaceholders(rawMarkdownKeyboard, { session, config, command }, true) .replace(/^[\s\S]*?"keyboard":\s*/, "") .replace(/\\n/g, "") .replace(/\\"/g, '"') .trim(); const keyboard = JSON.parse(replacedMarkdownKeyboard); markdownMessage.markdown = { content: replacedMarkdownContent, }; markdownMessage.keyboard = { content: keyboard, }; } catch (error) { logError(`解析原生 Markdown 出错: ${error}`); return null; } logInfo(config, `Markdown 模板参数: ${JSON.stringify(markdownMessage, null, 2)}`); return markdownMessage; } export async function sendmarkdownMessage(ctx, session, message, config?: Config) { if (!message) return; if (config) logInfo(config, "正在调用sendmarkdownMessage发送md"); try { const { guild, user } = session.event; const { qq, qqguild, channelId } = session; if (guild?.id) { if (qq) { await qq.sendMessage(channelId, message); } else if (qqguild) { await qqguild.sendMessage(channelId, message); } } else if (user?.id && qq) { await qq.sendPrivateMessage(user.id, message); } } catch (error) { ctx.logger.error(`发送 markdown 消息时出错`, error); } }