{"version":3,"file":"index.mjs","names":["colors: any","Debugger","customEmailConfigSchema: CustomEmailConfigSchema","customEmailOptionSchema: CustomEmailOptionSchema","Debugger","error","Debugger","dingtalkConfigSchema: DingtalkConfigSchema","dingtalkOptionSchema: DingtalkOptionSchema","Debugger","discordConfigSchema: DiscordConfigSchema","discordOptionSchema: DiscordOptionSchema","Debugger","feishuConfigSchema: FeishuConfigSchema","feishuOptionSchema: FeishuOptionSchema","Debugger","iGotConfigSchema: IGotConfigSchema","iGotOptionSchema: IGotOptionSchema","Debugger","ntfyConfigSchema: NtfyConfigSchema","ntfyOptionSchema: NtfyOptionSchema","headers: any","Debugger","oneBotConfigSchema: OneBotConfigSchema","oneBotOptionSchema: OneBotOptionSchema","Debugger","pushDeerConfigSchema: PushDeerConfigSchema","pushDeerOptionSchema: PushDeerOptionSchema","Debugger","pushPlusConfigSchema: PushPlusConfigSchema","pushPlusOptionSchema: PushPlusOptionSchema","Debugger","qmsgConfigSchema: QmsgConfigSchema","qmsgOptionSchema: QmsgOptionSchema","Debugger","serverChanTurboConfigSchema: ServerChanTurboConfigSchema","serverChanTurboOptionSchema: ServerChanTurboOptionSchema","Debugger","serverChanV3ConfigSchema: ServerChanV3ConfigSchema","serverChanV3OptionSchema: ServerChanV3OptionSchema","Debugger","telegramConfigSchema: TelegramConfigSchema","telegramOptionSchema: TelegramOptionSchema","Debugger","wechatAppConfigSchema: WechatAppConfigSchema","wechatAppOptionSchema: WechatAppOptionSchema","Debugger","wechatRobotConfigSchema: WechatRobotConfigSchema","wechatRobotOptionSchema: WechatRobotOptionSchema","Debugger","xiZhiConfigSchema: XiZhiConfigSchema","xiZhiOptionSchema: XiZhiOptionSchema","wxPusherConfigSchema: WxPusherConfigSchema","wxPusherOptionSchema: WxPusherOptionSchema"],"sources":["../src/utils/helper.ts","../src/utils/validate.ts","../src/push/custom-email.ts","../src/utils/ajax.ts","../src/utils/crypto.ts","../src/push/dingtalk.ts","../src/push/discord.ts","../src/push/feishu.ts","../src/push/i-got.ts","../src/push/ntfy.ts","../src/push/one-bot.ts","../src/push/push-deer.ts","../src/push/push-plus.ts","../src/push/qmsg.ts","../src/push/server-chan-turbo.ts","../src/push/server-chan-v3.ts","../src/push/telegram.ts","../src/push/wechat-app.ts","../src/push/wechat-robot.ts","../src/push/xi-zhi.ts","../src/push/wx-pusher.ts","../src/one.ts"],"sourcesContent":["let colors: any\n\nif (globalThis.process && typeof globalThis.process.on === 'function') {\n    try {\n        // eslint-disable-next-line @typescript-eslint/no-require-imports\n        colors = require('@colors/colors')\n    } catch {\n        import('@colors/colors').then((value) => {\n            colors = value.default\n        }).catch(console.error)\n    }\n}\n\nexport function warn(text: any): void {\n    if (colors) {\n        text = colors.yellow(text)\n    }\n    console.warn(text)\n}\n\nexport function error(text: any): void {\n    if (colors) {\n        text = colors.red(text)\n    }\n    console.error(text)\n}\n\nexport const logger = {\n    warn,\n    error,\n}\n\n/**\n * 检测是否为 http/https 开头的 url\n * @param url\n * @returns\n */\nexport const isHttpURL = (url: string): boolean => /^(https?:\\/\\/)/.test(url)\n\n/**\n * 检测是否为 socks/socks5 开头的 url\n * @param url\n * @returns\n */\nexport const isSocksUrl = (url: string): boolean => /^(socks5?:\\/\\/)/.test(url)\n\n/**\n * 判断是否为 null 或 undefined\n * @param value\n * @returns\n */\nexport function isNil(value: unknown): boolean {\n    return value === null || value === undefined\n}\n\n/**\n * 判断是否不为 null 且不为 undefined\n * @param value\n * @returns\n */\nexport function isNotNil(value: unknown): boolean {\n    return !isNil(value)\n}\n\n/**\n *  判断是否为 null 或 undefined 或 空字符串\n * @param value\n * @returns\n */\nexport function isEmpty(value: unknown): boolean {\n    return value === null || value === undefined || value === ''\n}\n/**\n * 判断是否不为 null 且不为 undefined 且不为 空字符串\n * @param value\n * @returns\n */\nexport function isNotEmpty(value: unknown): boolean {\n    return !isEmpty(value)\n}\n\n/**\n *  数组去重\n *\n * @author CaoMeiYouRen\n * @date 2025-03-05\n * @export\n * @template T\n * @param arr\n */\nexport function uniq<T>(arr: T[]): T[] {\n    return Array.from(new Set(arr))\n}\n","import { isEmpty } from './helper'\nimport { Config, ConfigSchema } from '@/interfaces/schema'\n\n/**\n * 验证配置是否符合 Schema 规则，如果不符合则抛出错误\n *\n * @author CaoMeiYouRen\n * @date 2024-11-17\n * @export\n * @template T\n * @param config\n * @param schema\n */\nexport function validate<T = Config>(config: T, schema: ConfigSchema<T>): void {\n    Object.keys(schema).forEach((key) => {\n        const item = schema[key]\n        const value = config[key]\n        if (!item.required && isEmpty(value)) {\n            return\n        }\n        if (item.required && isEmpty(value)) {\n            throw new Error(`\"${key}\" 字段是必须的！`)\n        }\n        if (item.type === 'select') {\n            const { options } = item as any\n            if (!options.map((e) => e.value).includes(value)) {\n                throw new Error(`\"${key}\" 字段必须是以下选项之一：${options.map((e) => e.value).join(',')}`)\n            }\n            return\n        }\n        if (item.type === 'string') {\n            if (typeof value !== 'string') {\n                throw new Error(`\"${key}\" 字段必须是字符串！`)\n            }\n            return\n        }\n        if (item.type === 'number') {\n            if (typeof value !== 'number') {\n                throw new Error(`\"${key}\" 字段必须是数字！`)\n            }\n            return\n        }\n        if (item.type === 'boolean') {\n            if (typeof value !== 'boolean') {\n                throw new Error(`\"${key}\" 字段必须是布尔值！`)\n            }\n            return\n        }\n        if (item.type === 'array') {\n            if (!Array.isArray(value)) {\n                throw new Error(`\"${key}\" 字段必须是数组！`)\n            }\n            return\n        }\n        if (item.type === 'object') {\n            if (typeof value !== 'object') {\n                throw new Error(`\"${key}\" 字段必须是对象！`)\n            }\n            return\n        }\n        throw new Error(`\"${key}\" 字段类型不支持！`)\n    })\n}\n","import debug from 'debug'\nimport nodemailer from 'nodemailer'\nimport SMTPTransport from 'nodemailer/lib/smtp-transport'\nimport Mail from 'nodemailer/lib/mailer'\nimport { Send } from '@/interfaces/send'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:custom-email')\n\nexport type CustomEmailType = 'text' | 'html'\nexport interface CustomEmailConfig {\n    /**\n     *  邮件类型\n     */\n    EMAIL_TYPE: CustomEmailType\n    /**\n     * 收件邮箱\n     */\n    EMAIL_TO_ADDRESS: string\n    /**\n     * 发件邮箱\n     */\n    EMAIL_AUTH_USER: string\n    /**\n     * 发件授权码(或密码)\n     */\n    EMAIL_AUTH_PASS: string\n    /**\n     * 发件域名\n     */\n    EMAIL_HOST: string\n    /**\n     * 发件端口\n     */\n    EMAIL_PORT: number\n}\n\nexport type CustomEmailConfigSchema = ConfigSchema<CustomEmailConfig>\n\nexport const customEmailConfigSchema: CustomEmailConfigSchema = {\n    EMAIL_TYPE: {\n        type: 'select',\n        title: '邮件类型',\n        description: '邮件类型',\n        required: true,\n        default: 'text',\n        options: [\n            {\n                label: '文本',\n                value: 'text',\n            },\n            {\n                label: 'HTML',\n                value: 'html',\n            },\n        ],\n    },\n    EMAIL_TO_ADDRESS: {\n        type: 'string',\n        title: '收件邮箱',\n        description: '收件邮箱',\n        required: true,\n        default: '',\n    },\n    EMAIL_AUTH_USER: {\n        type: 'string',\n        title: '发件邮箱',\n        description: '发件邮箱',\n        required: true,\n        default: '',\n    },\n    EMAIL_AUTH_PASS: {\n        type: 'string',\n        title: '发件授权码(或密码)',\n        description: '发件授权码(或密码)',\n        required: true,\n        default: '',\n    },\n    EMAIL_HOST: {\n        type: 'string',\n        title: '发件域名',\n        description: '发件域名',\n        required: true,\n        default: '',\n    },\n    EMAIL_PORT: {\n        type: 'number',\n        title: '发件端口',\n        description: '发件端口',\n        required: true,\n        default: 465,\n    },\n} as const\n\nexport type CustomEmailOption = Mail.Options\n\ntype OptionalCustomEmailOption = Pick<CustomEmailOption, 'to' | 'from' | 'subject' | 'text' | 'html'>\n\n/**\n * 由于 CustomEmailOption 的配置太多，所以不提供完整的 Schema，只提供部分配置 schema。\n * 如需使用完整的配置，请查看官方文档\n */\nexport type CustomEmailOptionSchema = OptionSchema<{\n    [K in keyof OptionalCustomEmailOption]: string\n}>\n\nexport const customEmailOptionSchema: CustomEmailOptionSchema = {\n    to: {\n        type: 'string',\n        title: '收件邮箱',\n        description: '收件邮箱',\n        required: false,\n        default: '',\n    },\n    from: {\n        type: 'string',\n        title: '发件邮箱',\n        description: '发件邮箱',\n        required: false,\n        default: '',\n    },\n    subject: {\n        type: 'string',\n        title: '邮件主题',\n        description: '邮件主题',\n        required: false,\n        default: '',\n    },\n    text: {\n        type: 'string',\n        title: '邮件内容',\n        description: '邮件内容',\n        required: false,\n        default: '',\n    },\n    html: {\n        type: 'string',\n        title: '邮件内容',\n        description: '邮件内容',\n        required: false,\n        default: '',\n    },\n} as const\n\n/**\n * 自定义邮件。官方文档: https://github.com/nodemailer/nodemailer\n *\n * @author CaoMeiYouRen\n * @date 2023-03-12\n * @export\n * @class CustomEmail\n */\nexport class CustomEmail implements Send {\n\n    // 命名空间\n    static readonly namespace = '自定义邮件'\n\n    static readonly configSchema = customEmailConfigSchema\n\n    static readonly optionSchema = customEmailOptionSchema\n\n    private config: CustomEmailConfig\n\n    private transporter: nodemailer.Transporter<SMTPTransport.SentMessageInfo, SMTPTransport.Options>\n\n    constructor(config: CustomEmailConfig) {\n        this.config = config\n        Debugger('CustomEmailConfig: %o', config)\n        // 根据 configSchema 验证 config\n        validate(config, CustomEmail.configSchema)\n        const { EMAIL_AUTH_USER, EMAIL_AUTH_PASS, EMAIL_HOST, EMAIL_PORT } = this.config\n        this.transporter = nodemailer.createTransport({\n            host: EMAIL_HOST,\n            port: Number(EMAIL_PORT),\n            auth: {\n                user: EMAIL_AUTH_USER,\n                pass: EMAIL_AUTH_PASS,\n            },\n        })\n    }\n\n    /**\n     * 释放资源（需要支持 Symbol.dispose）\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     */\n    [Symbol.dispose](): void {\n        if (this.transporter) {\n            this.transporter.close()\n        }\n    }\n\n    /**\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param title 消息的标题\n     * @param [desp] 消息的内容，支持 html\n     * @param [option] 额外选项\n     */\n    async send(title: string, desp?: string, option?: CustomEmailOption): Promise<SendResponse<SMTPTransport.SentMessageInfo>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: %o', title, desp, option)\n        const { EMAIL_TYPE, EMAIL_TO_ADDRESS, EMAIL_AUTH_USER } = this.config\n        if (!await this.transporter.verify()) {\n            throw new Error('自定义邮件的发件配置无效')\n        }\n        const { to: _to, ...args } = option || {}\n        const from = EMAIL_AUTH_USER\n        const to = _to || EMAIL_TO_ADDRESS\n        const type = EMAIL_TYPE\n        const response = await this.transporter.sendMail({\n            from,\n            to,\n            subject: title,\n            [type]: desp,\n            ...args,\n        })\n        if (typeof Symbol.dispose === 'undefined') { // 如果不支持 Symbol.dispose ，则手动释放\n            this.transporter.close()\n        }\n        Debugger('CustomEmail Response: %o', response)\n        if (response.response?.includes('250 OK')) {\n            return {\n                status: 200,\n                statusText: 'OK',\n                data: response,\n                headers: {},\n            }\n        }\n        return {\n            status: 500,\n            statusText: 'Internal Server Error',\n            data: response,\n            headers: {},\n        }\n    }\n\n}\n","import axios, { AxiosResponse, Method, AxiosRequestHeaders } from 'axios'\nimport debug from 'debug'\nimport { HttpsProxyAgent } from 'https-proxy-agent'\nimport { SocksProxyAgent } from 'socks-proxy-agent'\nimport { isHttpURL, isSocksUrl, logger } from './helper'\n\nconst Debugger = debug('push:ajax')\n\ninterface AjaxConfig {\n    url: string\n    query?: Record<string, unknown>\n    data?: Record<string, unknown> | string | Buffer | ArrayBuffer\n    method?: Method\n    headers?: Record<string, unknown>\n    baseURL?: string\n    proxyUrl?: string\n}\n\n/**\n * axios 接口封装\n *\n * @author CaoMeiYouRen\n * @date 2021-02-27\n * @export\n * @param config\n * @returns\n */\nexport async function ajax<T = any>(config: AjaxConfig): Promise<AxiosResponse<T>> {\n    try {\n        Debugger('ajax config: %O', config)\n        const { url, query = {}, method = 'GET', baseURL = '', proxyUrl } = config\n        const headers = (config.headers || {}) as AxiosRequestHeaders\n        let { data = {} } = config\n\n        if (headers['Content-Type'] === 'application/x-www-form-urlencoded' && typeof data === 'object') {\n            data = new URLSearchParams(data as Record<string, string>).toString()\n        }\n\n        let httpAgent = null\n        Debugger('NO_PROXY: %s', process.env.NO_PROXY)\n        if (process.env.NO_PROXY !== 'true') {\n            Debugger('HTTP_PROXY: %s', process.env.HTTP_PROXY)\n            Debugger('HTTPS_PROXY: %s', process.env.HTTPS_PROXY)\n            Debugger('SOCKS_PROXY: %s', process.env.SOCKS_PROXY)\n            if (isHttpURL(proxyUrl)) {\n                httpAgent = new HttpsProxyAgent(proxyUrl)\n            } else if (isSocksUrl(proxyUrl)) {\n                httpAgent = new SocksProxyAgent(proxyUrl)\n            } else if (process.env.HTTPS_PROXY) {\n                httpAgent = new HttpsProxyAgent(process.env.HTTPS_PROXY)\n            } else if (process.env.HTTP_PROXY) {\n                httpAgent = new HttpsProxyAgent(process.env.HTTP_PROXY)\n            } else if (process.env.SOCKS_PROXY) {\n                httpAgent = new SocksProxyAgent(process.env.SOCKS_PROXY)\n            }\n        }\n        const response = await axios(url, {\n            baseURL,\n            method,\n            headers,\n            params: query,\n            data,\n            timeout: 60000,\n            httpAgent,\n            httpsAgent: httpAgent,\n            proxy: false,\n        })\n        Debugger('response data: %O', response.data)\n        return response\n    } catch (error) {\n        if (error?.response) {\n            logger.error(error.response)\n            return error.response\n        }\n        throw error\n    }\n}\n","import crypto from 'crypto'\n\n/**\n * 生成钉钉签名\n *\n * @author CaoMeiYouRen\n * @date 2024-10-30\n * @export\n * @param timestamp\n * @param suiteTicket\n * @param suiteSecret\n */\nexport function generateSignature(timestamp: string | number, suiteTicket: string, suiteSecret: crypto.BinaryLike | crypto.KeyObject): string {\n    // 创建要签名的字符串\n    const stringToSign = `${timestamp}\\n${suiteTicket}`\n\n    // 创建 HMAC 实例\n    const hmac = crypto.createHmac('sha256', suiteSecret)\n\n    // 更新 HMAC 实例的数据\n    hmac.update(stringToSign, 'utf8')\n\n    // 计算 HMAC 签名并进行 Base64 编码\n    const signature = hmac.digest('base64')\n\n    return signature\n}\n\nexport function base64Encode(str: string): string {\n    return Buffer.from(str).toString('base64')\n}\n\nexport function rfc2047Encode(str: string): string {\n    return `=?utf-8?B?${base64Encode(str)}?=`\n}\n","import { AxiosResponse } from 'axios'\nimport debug from 'debug'\nimport { Markdown } from './dingtalk/markdown'\nimport { Text } from './dingtalk/text'\nimport { Link } from './dingtalk/link'\nimport { FeedCard } from './dingtalk/feed-card'\nimport { ActionCard, IndependentJump, OverallJump } from './dingtalk/action-card'\nimport { Send } from '@/interfaces/send'\nimport { warn } from '@/utils/helper'\nimport { ajax } from '@/utils/ajax'\nimport { generateSignature } from '@/utils/crypto'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:dingtalk')\n\nexport type DingtalkMsgType = 'text' | 'markdown' | 'link' | 'actionCard' | 'feedCard'\n\nexport interface DingtalkConfig {\n    /**\n     * 钉钉机器人 access_token。官方文档：https://developers.dingtalk.com/document/app/custom-robot-access\n     */\n    DINGTALK_ACCESS_TOKEN: string\n    /**\n     * 加签安全秘钥（HmacSHA256）\n     */\n    DINGTALK_SECRET?: string\n}\n\nexport type DingtalkConfigSchema = ConfigSchema<DingtalkConfig>\n\nexport const dingtalkConfigSchema: DingtalkConfigSchema = {\n    DINGTALK_ACCESS_TOKEN: {\n        type: 'string',\n        title: '钉钉机器人 access_token',\n        description: '钉钉机器人 access_token',\n        required: true,\n        default: '',\n    },\n    DINGTALK_SECRET: {\n        type: 'string',\n        title: '加签安全秘钥（HmacSHA256）',\n        required: false,\n        default: '',\n    },\n} as const\n\nexport type DingtalkOption = Partial<(Text | Markdown | Link | FeedCard | ActionCard)>\n\ntype TempDingtalkOption = {\n    msgtype?: DingtalkOption['msgtype']\n    text?: Partial<Text['text']>\n    markdown?: Partial<Markdown['markdown']>\n    link?: Partial<Link['link']>\n    actionCard?: Partial<{\n        // 首屏会话透出的展示内容\n        title: string\n        // markdown 格式的消息内容\n        text: string\n        // 0：按钮竖直排列；1：按钮横向排列\n        btnOrientation?: '0' | '1'\n    }> & Partial<OverallJump> & Partial<IndependentJump>\n    feedCard?: Partial<FeedCard['feedCard']>\n\n    at?: Text['at']\n    [key: string]: any\n}\n\nexport type DingtalkOptionSchema = OptionSchema<TempDingtalkOption>\n\nexport const dingtalkOptionSchema: DingtalkOptionSchema = {\n    msgtype: {\n        type: 'select',\n        title: '消息类型',\n        description: '消息类型',\n        required: false,\n        default: 'text',\n        options: [\n            {\n                label: '文本',\n                value: 'text',\n            },\n            {\n                label: 'Markdown',\n                value: 'markdown',\n            },\n            {\n                label: '链接',\n                value: 'link',\n            },\n            {\n                label: '按钮',\n                value: 'actionCard',\n            },\n            {\n                label: 'FeedCard',\n                value: 'feedCard',\n            },\n        ],\n    },\n    text: {\n        type: 'object',\n        title: '文本',\n        description: '文本',\n        required: false,\n        default: {},\n    },\n    markdown: {\n        type: 'object',\n        title: 'Markdown',\n        description: 'Markdown',\n        required: false,\n        default: {},\n    },\n    link: {\n        type: 'object',\n        title: '链接',\n        description: '链接',\n        required: false,\n        default: {},\n    },\n    actionCard: {\n        type: 'object',\n        title: '动作卡片',\n        description: '动作卡片',\n        required: false,\n        default: {},\n    },\n    feedCard: {\n        type: 'object',\n        title: '订阅卡片',\n        description: '订阅卡片',\n        required: false,\n        default: {},\n    },\n} as const\n\nexport interface DingtalkResponse {\n    errcode: number\n    errmsg: string\n}\n\n/**\n * 钉钉机器人推送\n * 在 [dingtalk-robot-sdk](https://github.com/ineo6/dingtalk-robot-sdk) 的基础上重构了一下，用法几乎完全一致。\n * @author CaoMeiYouRen\n * @date 2021-02-27\n * @export\n * @class Dingtalk\n */\nexport class Dingtalk implements Send {\n\n    static readonly namespace = '钉钉'\n\n    static readonly configSchema = dingtalkConfigSchema\n\n    static readonly optionSchema = dingtalkOptionSchema\n\n    private ACCESS_TOKEN: string\n    /**\n     * 加签安全秘钥（HmacSHA256）\n     *\n     * @private\n     */\n    private SECRET?: string\n    private webhook: string = 'https://oapi.dingtalk.com/robot/send'\n\n    /**\n     * 参考文档 [钉钉开放平台 - 自定义机器人接入](https://developers.dingtalk.com/document/app/custom-robot-access)\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param config\n     */\n    constructor(config: DingtalkConfig) {\n        const { DINGTALK_ACCESS_TOKEN, DINGTALK_SECRET } = config\n        this.ACCESS_TOKEN = DINGTALK_ACCESS_TOKEN\n        this.SECRET = DINGTALK_SECRET\n        Debugger('DINGTALK_ACCESS_TOKEN: %s , DINGTALK_SECRET: %s', this.ACCESS_TOKEN, this.SECRET)\n        // 根据 configSchema 验证 config\n        validate(config, Dingtalk.configSchema)\n        if (!this.SECRET) {\n            warn('未提供 DINGTALK_SECRET ！')\n        }\n    }\n\n    private getSign(timeStamp: number): string {\n        let signStr = ''\n        if (this.SECRET) {\n            signStr = generateSignature(timeStamp, this.SECRET, this.SECRET)\n            Debugger('Sign string is %s, result is %s', `${timeStamp}\\n${this.SECRET}`, signStr)\n        }\n        return signStr\n    }\n\n    private async push(data: DingtalkOption): Promise<AxiosResponse<DingtalkResponse>> {\n        const timestamp = Date.now()\n        const sign = this.getSign(timestamp)\n        const result = await ajax({\n            url: this.webhook,\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/json',\n            },\n            query: {\n                timestamp,\n                sign,\n                access_token: this.ACCESS_TOKEN,\n            },\n            data,\n        })\n        Debugger('Result is %s, %s。', result.data.errcode, result.data.errmsg)\n        if (result.data.errcode === 310000) {\n            console.error('Send Failed:', result.data)\n            Debugger('Please check safe config : %O', result.data)\n        }\n        return result\n    }\n\n    /**\n     *\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param title 消息的标题\n     * @param [desp] 消息的内容，支持 Markdown\n     * @returns\n     */\n    async send(title: string, desp?: string, option?: DingtalkOption): Promise<SendResponse<DingtalkResponse>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: %O', title, desp, option)\n        switch (option.msgtype) {\n            case 'text':\n                return this.push({\n                    msgtype: 'text',\n                    text: {\n                        content: `${title}${desp ? `\\n${desp}` : ''}`,\n                    },\n                    ...option,\n                })\n            case 'markdown':\n                return this.push({\n                    msgtype: 'markdown',\n                    markdown: {\n                        title,\n                        text: `# ${title}${desp ? `\\n\\n${desp}` : ''}`,\n                    },\n                    ...option,\n                })\n            case 'link':\n                return this.push({\n                    msgtype: 'link',\n                    link: {\n                        title,\n                        text: desp || '',\n                        picUrl: option?.link?.picUrl || '',\n                        messageUrl: option.link?.messageUrl || '',\n                    },\n                    ...option,\n                })\n            case 'actionCard':\n                return this.push({\n                    msgtype: 'actionCard',\n                    actionCard: {\n                        title,\n                        text: desp || '',\n                        btnOrientation: option?.actionCard?.btnOrientation || '0',\n                        btns: (option?.actionCard as any)?.btns,\n                        singleTitle: (option?.actionCard as any)?.singleTitle,\n                        singleURL: (option?.actionCard as any)?.singleURL,\n                    },\n                    ...option,\n                })\n            case 'feedCard':\n                return this.push({\n                    msgtype: 'feedCard',\n                    feedCard: {\n                        links: option?.feedCard?.links || [],\n                    },\n                    ...option,\n                })\n            default:\n                throw new Error('msgtype is required!')\n        }\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:discord')\n\nexport interface DiscordConfig {\n    /**\n     * Webhook Url 可在服务器设置 -> 整合 -> Webhook -> 创建 Webhook 中获取\n     */\n    DISCORD_WEBHOOK: string\n\n    /**\n     * 代理地址\n     */\n    PROXY_URL?: string\n}\n\nexport type DiscordConfigSchema = ConfigSchema<DiscordConfig>\n\nexport const discordConfigSchema: DiscordConfigSchema = {\n    DISCORD_WEBHOOK: {\n        type: 'string',\n        title: 'Webhook Url',\n        description: 'Webhook Url 可在服务器设置 -> 整合 -> Webhook -> 创建 Webhook 中获取',\n        required: true,\n    },\n    PROXY_URL: {\n        type: 'string',\n        title: '代理地址',\n        description: '代理地址',\n        required: false,\n    },\n} as const\n\n/**\n * Discord 额外选项\n * 由于参数过多，因此请参考官方文档进行配置。\n * @link https://discord.com/developers/docs/resources/webhook#execute-webhook\n */\nexport type DiscordOption = {\n    /**\n     * 机器人显示的名称\n     */\n    username?: string\n    /**\n     * 机器人头像的 Url\n     */\n    avatar_url?: string\n    [key: string]: any\n}\n\nexport type DiscordOptionSchema = OptionSchema<DiscordOption>\n\nexport const discordOptionSchema: DiscordOptionSchema = {\n    username: {\n        type: 'string',\n        title: '机器人显示的名称',\n        description: '机器人显示的名称',\n        required: false,\n    },\n    avatar_url: {\n        type: 'string',\n        title: '机器人头像的 Url',\n        description: '机器人头像的 Url',\n        required: false,\n    },\n} as const\n\nexport interface DiscordResponse { }\n\n/**\n * Discord Webhook 推送\n *\n * @author CaoMeiYouRen\n * @date 2023-09-17\n * @export\n * @class Discord\n */\nexport class Discord implements Send {\n\n    static readonly namespace = 'Discord'\n    static readonly configSchema = discordConfigSchema\n    static readonly optionSchema = discordOptionSchema\n\n    /**\n     * Webhook Url 可在服务器设置 -> 整合 -> Webhook -> 创建 Webhook 中获取\n     *\n     * @author CaoMeiYouRen\n     * @date 2023-09-17\n     * @private\n     */\n    private DISCORD_WEBHOOK: string\n\n    proxyUrl: string\n\n    /**\n     * 创建 Discord 实例\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param config 配置\n     */\n    constructor(config: DiscordConfig) {\n        const { DISCORD_WEBHOOK, PROXY_URL } = config\n        Debugger('DISCORD_WEBHOOK: %s, PROXY_URL: %s', DISCORD_WEBHOOK, PROXY_URL)\n        this.DISCORD_WEBHOOK = DISCORD_WEBHOOK\n        if (PROXY_URL) {\n            this.proxyUrl = PROXY_URL\n        }\n        // 根据 configSchema 验证 config\n        validate(config, Discord.configSchema)\n    }\n\n    /**\n     * 发送消息\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param title 消息的标题\n     * @param [desp] 消息的描述。最多 2000 个字符\n     * @param [option] 额外选项\n     */\n    async send(title: string, desp?: string, option?: DiscordOption): Promise<SendResponse<DiscordResponse>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: %o', title, desp, option)\n        const { username, avatar_url, ...args } = option || {}\n        const proxyUrl = this.proxyUrl\n        const content = `${title}${desp ? `\\n${desp}` : ''}`\n        return ajax({\n            url: this.DISCORD_WEBHOOK,\n            method: 'POST',\n            proxyUrl,\n            data: {\n                username,\n                content,\n                avatar_url,\n                ...args,\n            },\n        })\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:feishu')\n\nexport interface FeishuConfig {\n    /**\n     * 飞书应用 ID。官方文档：https://open.feishu.cn/document/server-docs/api-call-guide/terminology#b047be0c\n     */\n    FEISHU_APP_ID: string\n    /**\n     * 飞书应用密钥。官方文档：https://open.feishu.cn/document/server-docs/api-call-guide/terminology#1b5fb6cd\n     */\n    FEISHU_APP_SECRET: string\n}\n\nexport type FeishuConfigSchema = ConfigSchema<FeishuConfig>\n\nexport const feishuConfigSchema: FeishuConfigSchema = {\n    FEISHU_APP_ID: {\n        type: 'string',\n        title: '飞书应用 ID',\n        description: '飞书应用 ID',\n        required: true,\n        default: '',\n    },\n    FEISHU_APP_SECRET: {\n        type: 'string',\n        title: '飞书应用密钥',\n        description: '飞书应用密钥',\n        required: true,\n        default: '',\n    },\n}\n\nexport type FeishuOption = {\n    // 用户 ID 类型\n    receive_id_type: 'open_id' | 'union_id' | 'user_id' | 'email' | 'chat_id'\n    // 消息接收者的 ID，ID 类型与查询参数 receive_id_type 的取值一致。\n    receive_id: string\n    // 消息类型。\n    msg_type: 'text' | 'post' | 'image' | 'file' | 'audio' | 'media' | 'sticker' | 'interactive' | 'share_chat' | 'share_user' | 'system'\n    // 消息内容，JSON 结构序列化后的字符串。该参数的取值与 msg_type 对应，例如 msg_type 取值为 text，则该参数需要传入文本类型的内容。\n    content?: string\n    // 自定义设置的唯一字符串序列，用于在发送消息时请求去重。持有相同 uuid 的请求，在 1 小时内至多成功发送一条消息。\n    uuid?: string\n}\n\nexport type FeishuOptionSchema = OptionSchema<FeishuOption>\n\nexport const feishuOptionSchema: FeishuOptionSchema = {\n    receive_id_type: {\n        type: 'select',\n        title: '用户 ID 类型',\n        description: '用户 ID 类型',\n        required: true,\n        options: [\n            {\n                label: 'open_id',\n                value: 'open_id',\n            },\n            {\n                label: 'union_id',\n                value: 'union_id',\n            },\n            {\n                label: 'user_id',\n                value: 'user_id',\n            },\n            {\n                label: 'email',\n                value: 'email',\n            },\n            {\n                label: 'chat_id',\n                value: 'chat_id',\n            },\n        ],\n    },\n    receive_id: {\n        type: 'string',\n        title: '消息接收者的 ID',\n        description: '消息接收者的 ID，ID 类型与查询参数 receive_id_type 的取值一致。',\n        required: true,\n    },\n    msg_type: {\n        type: 'select',\n        title: '消息类型',\n        description: '消息类型',\n        required: true,\n        options: [\n            {\n                label: '文本',\n                value: 'text',\n            },\n            {\n                label: '富文本',\n                value: 'post',\n            },\n            {\n                label: '图片',\n                value: 'image',\n            },\n            {\n                label: '文件',\n                value: 'file',\n            },\n            {\n                label: '语音',\n                value: 'audio',\n            },\n            {\n                label: '视频',\n                value: 'media',\n            },\n            {\n                label: '表情包',\n                value: 'sticker',\n            },\n            {\n                label: '卡片',\n                value: 'interactive',\n            },\n            {\n                label: '分享群名片',\n                value: 'share_chat',\n            },\n            {\n                label: '分享个人名片',\n                value: 'share_user',\n            },\n            {\n                label: '系统消息',\n                value: 'system',\n            },\n        ],\n    },\n    content: {\n        type: 'string',\n        title: '消息内容',\n        description: '消息内容，JSON 结构序列化后的字符串。该参数的取值与 msg_type 对应，例如 msg_type 取值为 text，则该参数需要传入文本类型的内容。',\n        required: false,\n    },\n    uuid: {\n        type: 'string',\n        title: '自定义设置的唯一字符串序列',\n        description: '自定义设置的唯一字符串序列，用于在发送消息时请求去重。持有相同 uuid 的请求，在 1 小时内至多成功发送一条消息。',\n        required: false,\n    },\n}\n\n/**\n * 飞书。官方文档：https://open.feishu.cn/document/home/index\n *\n * @author CaoMeiYouRen\n * @date 2025-02-10\n * @export\n * @class Feishu\n */\nexport class Feishu implements Send {\n\n    static readonly namespace = '飞书'\n\n    static readonly configSchema = feishuConfigSchema\n\n    static readonly optionSchema = feishuOptionSchema\n\n    private readonly config: FeishuConfig\n\n    /**\n    * accessToken 的过期时间(时间戳)\n    */\n    private expiresTime: number\n\n    private accessToken: string\n\n    constructor(config: FeishuConfig) {\n        this.config = config\n        // 根据 configSchema 验证 config\n        validate(config, Feishu.configSchema)\n    }\n\n    private async getAccessToken() {\n        const { FEISHU_APP_ID, FEISHU_APP_SECRET } = this.config\n        const url = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal'\n        const data = {\n            app_id: FEISHU_APP_ID,\n            app_secret: FEISHU_APP_SECRET,\n        }\n        const result = await ajax({\n            url,\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/json; charset=utf-8',\n            },\n            data,\n        })\n        const { code, msg, tenant_access_token, expire } = result.data\n        if (code !== 0) { // 出错返回码，为0表示成功，非0表示调用失败\n            throw new Error(msg || '获取 tenant_access_token 失败！')\n        }\n        this.expiresTime = Date.now() + expire * 1000\n        Debugger('获取 tenant_access_token 成功: %s', tenant_access_token)\n        return tenant_access_token as string\n    }\n\n    async send(title: string, desp?: string, option?: FeishuOption): Promise<SendResponse> {\n        Debugger('title: \"%s\", desp: \"%s\", option: %O', title, desp, option)\n        if (!this.accessToken || Date.now() >= this.expiresTime) {\n            this.accessToken = await this.getAccessToken()\n        }\n        const { receive_id_type = 'open_id', receive_id, msg_type = 'text', content, uuid } = option\n        const data = { receive_id, msg_type, content, uuid }\n        if (!data.content) {\n            switch (msg_type) {\n                case 'text':\n                    data.content = JSON.stringify({\n                        text: `${title}${desp ? `\\n${desp}` : ''}`,\n                    })\n                    break\n                case 'post':\n                    data.content = JSON.stringify({\n                        post: {\n                            zh_cn: {\n                                title,\n                                content: [\n                                    [\n                                        {\n                                            tag: 'text',\n                                            text: desp,\n                                        },\n                                    ],\n                                ],\n                            },\n                        },\n                    })\n                    break\n                default:\n                    throw new Error('msg_type is required!')\n            }\n        }\n        const result = await ajax({\n            url: 'https://open.feishu.cn/open-apis/im/v1/messages',\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/json; charset=utf-8',\n                Authorization: `Bearer ${this.accessToken}`,\n            },\n            data,\n            query: {\n                receive_id_type: receive_id_type || 'open_id',\n            },\n        })\n        return result\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:i-got')\n\nexport interface IGotConfig {\n    /**\n     * 微信搜索小程序“iGot”获取推送key\n     */\n    I_GOT_KEY: string\n}\n\nexport type IGotConfigSchema = ConfigSchema<IGotConfig>\n\nexport const iGotConfigSchema: IGotConfigSchema = {\n    I_GOT_KEY: {\n        type: 'string',\n        title: 'iGot 推送key',\n        description: 'iGot 推送key',\n        required: true,\n        default: '',\n    },\n} as const\n\nexport interface IGotOption {\n    /**\n     * 链接； 点开消息后会主动跳转至此地址\n     */\n    url?: string\n    /**\n     * 是否自动复制； 为1自动复制\n     */\n    automaticallyCopy?: number\n    /**\n     * 紧急消息，为1表示紧急。此消息将置顶在小程序内， 同时会在推送的消息内做一定的特殊标识\n     */\n    urgent?: number\n    /**\n     * 需要自动复制的文本内容\n     */\n    copy?: string\n    /**\n     * 主题； 订阅链接下有效；对推送内容分类，用户可选择性订阅\n     */\n    topic?: string\n    [key: string]: any\n}\n\nexport type IGotOptionSchema = OptionSchema<IGotOption>\n\nexport const iGotOptionSchema: IGotOptionSchema = {\n    url: {\n        type: 'string',\n        title: '链接',\n        description: '链接； 点开消息后会主动跳转至此地址',\n        required: false,\n        default: '',\n    },\n    automaticallyCopy: {\n        type: 'number',\n        title: '是否自动复制',\n        description: '是否自动复制； 为1自动复制',\n        required: false,\n        default: 0,\n    },\n    urgent: {\n        type: 'number',\n        title: '紧急消息',\n        description: '紧急消息，为1表示紧急。此消息将置顶在小程序内， 同时会在推送的消息内做一定的特殊标识',\n        required: false,\n        default: 0,\n    },\n    copy: {\n        type: 'string',\n        title: '需要自动复制的文本内容',\n        description: '需要自动复制的文本内容',\n        required: false,\n        default: '',\n    },\n    topic: {\n        type: 'string',\n        title: '主题',\n        description: '主题； 订阅链接下有效；对推送内容分类，用户可选择性订阅',\n        required: false,\n        default: '',\n    },\n} as const\n\nexport interface IGotResponse {\n    /**\n     * 状态码； 0为正常\n     */\n    ret: number\n    /**\n     * 响应结果\n     */\n    data: {\n        /**\n         * 消息记录，后期开放其他接口用\n         * */\n        id: string\n    }\n    /**\n     * 结果描述\n     */\n    errMsg: string\n}\n\n/**\n * iGot 推送，官方文档：http://hellyw.com\n *\n * @author CaoMeiYouRen\n * @date 2021-03-03\n * @export\n * @class IGot\n */\nexport class IGot implements Send {\n\n    static readonly namespace = 'iGot'\n    static readonly configSchema = iGotConfigSchema\n    static readonly optionSchema = iGotOptionSchema\n    /**\n     * 微信搜索小程序“iGot”获取推送key\n     *\n     * @private\n     */\n    private I_GOT_KEY: string\n    /**\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param config 微信搜索小程序“iGot”获取推送key\n     */\n    constructor(config: IGotConfig) {\n        const { I_GOT_KEY } = config\n        this.I_GOT_KEY = I_GOT_KEY\n        Debugger('set I_GOT_KEY: \"%s\"', I_GOT_KEY)\n        // 根据 configSchema 验证 config\n        validate(config, IGot.configSchema)\n    }\n\n    /**\n     *\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param title 消息标题\n     * @param [desp] 消息正文\n     * @param [option] 额外选项\n     * @returns\n     */\n    send(title: string, desp?: string, option?: IGotOption): Promise<SendResponse<IGotResponse>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: \"%o\"', title, desp, option)\n        return ajax({\n            url: `https://push.hellyw.com/${this.I_GOT_KEY}`,\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/json',\n            },\n            data: {\n                title,\n                content: desp || title,\n                automaticallyCopy: 0, // 关闭自动复制\n                ...option,\n            },\n        })\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\nimport { rfc2047Encode } from '@/utils/crypto'\n\nconst Debugger = debug('push:ntfy')\n\nexport interface NtfyConfig {\n    /**\n     * 推送地址\n     */\n    NTFY_URL: string\n\n    /**\n     * 主题\n     * 用于区分不同的推送目标。\n     * 主题本质上是一个密码，所以请选择不容易猜到的东西。\n     * 例如：`my-topic`\n     */\n    NTFY_TOPIC: string\n\n    /**\n     * 认证参数。\n     * 支持 Basic Auth、Bearer Token。\n     * Basic Auth 示例：\"Basic dGVzdDpwYXNz\"\n     * Bearer Token 示例：\"Bearer tk_...\"\n     */\n    NTFY_AUTH?: string\n}\n\nexport type NtfyConfigSchema = ConfigSchema<NtfyConfig>\nexport const ntfyConfigSchema: NtfyConfigSchema = {\n    NTFY_URL: {\n        type: 'string',\n        title: '推送地址',\n        description: '推送地址',\n        required: true,\n        default: '',\n    },\n    NTFY_TOPIC: {\n        type: 'string',\n        title: '主题',\n        description: '主题',\n        required: true,\n        default: '',\n    },\n    NTFY_AUTH: {\n        type: 'string',\n        title: '认证参数',\n        description: '支持 Basic Auth、Bearer Token。\\n'\n            + 'Basic Auth 示例：\"Basic dGVzdDpwYXNz\"\\n'\n            + 'Bearer Token 示例：\"Bearer tk_...\"',\n        required: false,\n        default: '',\n    },\n} as const\n\nexport interface NtfyOption {\n    /**\n     * 通知中显示的标题\n     */\n    title?: string\n    /**\n     * 通知中显示的消息正文\n     */\n    message?: string\n    /**\n     * 消息正文\n     */\n    body?: string\n    /**\n     * 消息优先级（1-5，1最低，5最高）\n     */\n    priority?: number\n    /**\n     * 标签列表（逗号分隔），支持Emoji短代码\n     */\n    tags?: string\n    /**\n     * 启用Markdown格式化（设为`true`或`yes`）\n     */\n    markdown?: boolean\n    /**\n     * 延迟发送时间（支持时间戳、自然语言如`tomorrow 10am`）\n     */\n    delay?: string\n    /**\n     * 点击通知时打开的URL\n     */\n    click?: string\n    /**\n     * 附加文件的URL\n     */\n    attach?: string\n    /**\n     * 附件的显示文件名\n     */\n    filename?: string\n    /**\n     * 通知图标的URL（仅支持JPEG/PNG）\n     */\n    icon?: string\n    /**\n     * 定义通知的操作按钮（JSON或简写格式）\n     */\n    actions?: string\n    /**\n     * 设为`no`禁止服务器缓存消息\n     */\n    cache?: boolean\n    /**\n     * 设为`no`禁止转发到Firebase（仅影响Android推送）\n     */\n    firebase?: boolean\n    /**\n     * 设为`1`启用UnifiedPush模式（用于Matrix网关）\n     */\n    unifiedPush?: boolean\n    /**\n     * 将通知转发到指定邮箱\n     */\n    email?: string\n    /**\n     * 发送语音呼叫（需验证手机号，仅限认证用户）\n     */\n    call?: string\n    /**\n     * 设为`text/markdown`启用Markdown\n     */\n    contentType?: string\n    /**\n     * 直接上传文件作为附件（需设置`X-Filename`）\n     */\n    file?: File\n}\n\nexport type NtfyOptionSchema = OptionSchema<NtfyOption>\n\nexport const ntfyOptionSchema: NtfyOptionSchema = {\n    title: {\n        type: 'string',\n        title: '标题',\n        description: '标题',\n        required: false,\n        default: '',\n    },\n    body: {\n        type: 'string',\n        title: '消息正文',\n        description: '消息正文',\n        required: false,\n        default: '',\n    },\n    priority: {\n        type: 'number',\n        title: '消息优先级',\n        description: '消息优先级（1-5，1最低，5最高）',\n        required: false,\n        default: 3,\n    },\n    tags: {\n        type: 'string',\n        title: '标签列表',\n        description: '标签列表（逗号分隔），支持Emoji短代码',\n        required: false,\n        default: '',\n    },\n    markdown: {\n        type: 'boolean',\n        title: '启用Markdown格式',\n        description: '启用Markdown格式（设为`true`或`yes`）',\n        required: false,\n        default: false,\n    },\n    delay: {\n        type: 'string',\n        title: '延迟发送时间',\n        description: '延迟发送时间（支持时间戳、自然语言如`tomorrow 10am`）',\n        required: false,\n        default: '',\n    },\n    click: {\n        type: 'string',\n        title: '点击通知时打开的URL',\n        description: '点击通知时打开的URL',\n        required: false,\n        default: '',\n    },\n    attach: {\n        type: 'string',\n        title: '附加文件的URL',\n        description: '附加文件的URL',\n        required: false,\n        default: '',\n    },\n    filename: {\n        type: 'string',\n        title: '附件的显示文件名',\n        description: '附件的显示文件名',\n        required: false,\n        default: '',\n    },\n    icon: {\n        type: 'string',\n        title: '通知图标的URL',\n        description: '通知图标的URL（仅支持JPEG/PNG）',\n        required: false,\n        default: '',\n    },\n    actions: {\n        type: 'string',\n        title: '定义通知的操作按钮',\n        description: '定义通知的操作按钮（JSON或简写格式）',\n        required: false,\n        default: '',\n    },\n    cache: {\n        type: 'boolean',\n        title: '禁止服务器缓存消息',\n        description: '设为`no`禁止服务器缓存消息',\n        required: false,\n        default: false,\n    },\n    firebase: {\n        type: 'boolean',\n        title: '禁止转发到Firebase',\n        description: '设为`no`禁止转发到Firebase（仅影响Android推送）',\n        required: false,\n        default: false,\n    },\n    unifiedPush: {\n        type: 'boolean',\n        title: '启用UnifiedPush模式',\n        description: '设为`1`启用UnifiedPush模式（用于Matrix网关）',\n        required: false,\n        default: false,\n    },\n    email: {\n        type: 'string',\n        title: '邮箱',\n        description: '将通知转发到指定邮箱',\n        required: false,\n        default: '',\n    },\n    call: {\n        type: 'string',\n        title: '发送语音呼叫',\n        description: '发送语音呼叫（需验证手机号，仅限认证用户）',\n        required: false,\n        default: '',\n    },\n    contentType: {\n        type: 'string',\n        title: '编码格式',\n        description: '设为`text/markdown`启用Markdown',\n        required: false,\n        default: '',\n    },\n    file: {\n        type: 'object',\n        title: '附件',\n        description: '直接上传文件作为附件（需设置`X-Filename`）',\n        required: false,\n    },\n} as const\n\nexport interface NtfyResponse {\n    /**\n     * 消息ID\n     */\n    id: string\n    /**\n     * 消息发布时间（Unix时间戳）\n     */\n    time: number\n    /**\n     * 消息过期时间（Unix时间戳）\n     */\n    expires: number\n    /**\n     * 事件类型\n     */\n    event: string\n    /**\n     * 主题\n     */\n    topic: string\n    /**\n     * 消息内容\n     */\n    message: string\n}\n\n/**\n * ntfy推送。\n * 官方文档：https://ntfy.sh/docs/publish/\n *\n * @author CaoMeiYouRen\n * @date 2025-02-11\n * @export\n * @class Ntfy\n */\nexport class Ntfy implements Send {\n\n    static readonly namespace = 'ntfy'\n    static readonly configSchema = ntfyConfigSchema\n    static readonly optionSchema = ntfyOptionSchema\n    /**\n     * 推送地址\n     */\n    private NTFY_URL: string\n    /**\n     * 认证参数。\n     * 支持 Basic Auth、Bearer Token。\n     * Basic Auth 示例：\"Basic dGVzdDpwYXNz\"\n     * Bearer Token 示例：\"Bearer tk_...\"\n     */\n    private NTFY_AUTH?: string\n\n    /**\n     * 主题\n     * 用于区分不同的推送目标。\n     * 主题本质上是一个密码，所以请选择不容易猜到的东西。\n     * 例如：`my-topic`\n     */\n    private NTFY_TOPIC: string\n\n    constructor(config: NtfyConfig) {\n        const { NTFY_URL, NTFY_AUTH, NTFY_TOPIC } = config\n        this.NTFY_URL = NTFY_URL\n        this.NTFY_TOPIC = NTFY_TOPIC\n        this.NTFY_AUTH = NTFY_AUTH\n        Debugger('set NTFY_URL: \"%s\", NTFY_TOPIC: \"%s\", NTFY_AUTH: \"%s\"', NTFY_URL, NTFY_TOPIC, NTFY_AUTH)\n        // 根据 configSchema 验证 config\n        validate(config, Ntfy.configSchema)\n    }\n\n    async send(title: string, desp: string, option?: NtfyOption): Promise<SendResponse<NtfyResponse>> {\n        Debugger('option: \"%o\"', option)\n        const { message, body, priority, tags, markdown, delay, click, attach, filename, icon, actions, cache, firebase, unifiedPush, email, call, contentType, file } = option || {}\n        const headers: any = {}\n        if (this.NTFY_AUTH) {\n            headers['Authorization'] = this.NTFY_AUTH\n        }\n        if (contentType) {\n            headers['Content-Type'] = contentType\n        }\n        const xTitle = title || option.title\n        if (xTitle) {\n            headers['X-Title'] = rfc2047Encode(xTitle)\n        }\n        if (message) {\n            headers['X-Message'] = rfc2047Encode(message)\n        }\n        if (priority) {\n            headers['X-Priority'] = priority.toString()\n        }\n        if (tags) {\n            headers['X-Tags'] = tags\n        }\n        if (markdown) {\n            headers['X-Markdown'] = markdown.toString()\n        }\n        if (delay) {\n            headers['X-Delay'] = delay\n        }\n        if (click) {\n            headers['X-Click'] = click\n        }\n        if (attach) {\n            headers['X-Attach'] = attach\n        }\n        if (filename) {\n            headers['X-Filename'] = filename\n        }\n        if (icon) {\n            headers['X-Icon'] = icon\n        }\n        if (actions) {\n            headers['X-Actions'] = actions\n        }\n        if (cache) {\n            headers['X-Cache'] = cache ? 'yes' : 'no'\n        }\n        if (firebase) {\n            headers['X-Firebase'] = firebase ? 'yes' : 'no'\n        }\n        if (unifiedPush) {\n            headers['X-UnifiedPush'] = unifiedPush ? '1' : '0'\n        }\n        if (email) {\n            headers['X-Email'] = email\n        }\n        if (call) {\n            headers['X-Call'] = call\n        }\n        if (file) {\n            headers['X-Filename'] = file.name\n            headers['Content-Type'] = 'application/octet-stream'\n            headers['Content-Length'] = file.size\n            headers['Content-Disposition'] = `attachment; filename=\"${file.name}\"`\n        }\n        Debugger('headers: \"%o\"', headers)\n        const data = desp || body || message\n        Debugger('data: \"%s\"', data)\n        const url = new URL(this.NTFY_TOPIC, this.NTFY_URL).toString()\n        const response = await ajax({\n            url,\n            method: 'POST',\n            headers,\n            data,\n        })\n        return response\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { warn } from '@/utils/helper'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:one-bot')\n\nexport interface OneBotConfig {\n    /**\n     * OneBot HTTP 基础路径\n     */\n    ONE_BOT_BASE_URL: string\n    /**\n     * OneBot AccessToken\n     * 出于安全原因，请务必设置 AccessToken\n     */\n    ONE_BOT_ACCESS_TOKEN?: string\n}\n\nexport type OneBotConfigSchema = ConfigSchema<OneBotConfig>\nexport const oneBotConfigSchema: OneBotConfigSchema = {\n    ONE_BOT_BASE_URL: {\n        type: 'string',\n        title: 'OneBot HTTP 基础路径',\n        description: 'OneBot HTTP 基础路径',\n        required: true,\n    },\n    ONE_BOT_ACCESS_TOKEN: {\n        type: 'string',\n        title: 'OneBot AccessToken',\n        description: '出于安全原因，请务必设置 AccessToken',\n        required: false,\n    },\n} as const\n\nexport interface OneBotPrivateMsgOption {\n    /**\n     * 消息类型\n     */\n    message_type: 'private'\n    /**\n     * 对方 QQ 号\n     */\n    user_id: number\n}\n\nexport interface OneBotGroupMsgOption {\n    /**\n     * 消息类型\n     */\n    message_type: 'group'\n    /**\n     * 群号\n     */\n    group_id: number\n\n}\n\nexport type OneBotOption = (OneBotPrivateMsgOption | OneBotGroupMsgOption) & {\n    /**\n     * 消息内容是否作为纯文本发送（即不解析 CQ 码），只在 message 字段是字符串时有效\n     */\n    auto_escape?: boolean\n}\n\nexport type OneBotMsgType = OneBotOption['message_type']\n\nexport type OneBotOptionSchema = OptionSchema<{\n    // 消息类型，private 或 group\n    message_type: OneBotMsgType\n    // 如果为 private，对方 QQ 号\n    user_id?: number\n    // 如果为 group，群号\n    group_id?: number\n    // 消息内容是否作为纯文本发送（即不解析 CQ 码），只在 message 字段是字符串时有效\n    auto_escape?: boolean\n}>\n\nexport const oneBotOptionSchema: OneBotOptionSchema = {\n    message_type: {\n        type: 'select',\n        title: '消息类型',\n        description: '消息类型，private 或 group，默认为 private',\n        required: true,\n        default: 'private',\n        options: [\n            {\n                label: '私聊',\n                value: 'private',\n            },\n            {\n                label: '群聊',\n                value: 'group',\n            },\n        ],\n    },\n    user_id: {\n        type: 'number',\n        title: ' QQ 号',\n        description: '对方 QQ 号。仅私聊有效。',\n        required: false,\n    },\n    group_id: {\n        type: 'number',\n        title: '群号',\n        description: '群号。仅群聊有效。',\n        required: false,\n    },\n    auto_escape: {\n        type: 'boolean',\n        title: '消息内容是否作为纯文本发送（即不解析 CQ 码），只在 message 字段是字符串时有效',\n        description: '消息内容是否作为纯文本发送（即不解析 CQ 码），只在 message 字段是字符串时有效',\n        required: false,\n    },\n} as const\n\nexport interface OneBotData {\n    ClassType: string\n    // 消息 ID\n    message_id: number\n}\n\nexport interface OneBotResponse {\n    status: string\n    retcode: number\n    data: OneBotData\n    echo?: any\n}\n\n/**\n * OneBot。官方文档：https://github.com/botuniverse/onebot-11\n * 本项目实现的版本为 OneBot 11\n * @author CaoMeiYouRen\n * @date 2023-10-22\n * @export\n * @class OneBot\n */\nexport class OneBot implements Send {\n\n    static readonly namespace = 'OneBot'\n    static readonly configSchema = oneBotConfigSchema\n    static readonly optionSchema = oneBotOptionSchema\n\n    /**\n     *  OneBot 协议版本号\n     *\n     * @author CaoMeiYouRen\n     * @date 2023-10-22\n     * @static\n     */\n    static version = 11\n\n    /**\n     * OneBot HTTP 基础路径\n     *\n     * @author CaoMeiYouRen\n     * @date 2023-10-22\n     * @private\n     * @example http://127.0.0.1\n     */\n    private ONE_BOT_BASE_URL: string\n    /**\n     * OneBot AccessToken\n     * 出于安全原因，请务必设置 AccessToken\n     * @author CaoMeiYouRen\n     * @date 2023-10-22\n     * @private\n     */\n    private ONE_BOT_ACCESS_TOKEN?: string\n\n    /**\n     * 创建 OneBot 实例\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param config OneBot 配置\n     */\n    constructor(config: OneBotConfig) {\n        const { ONE_BOT_BASE_URL, ONE_BOT_ACCESS_TOKEN } = config\n        this.ONE_BOT_BASE_URL = ONE_BOT_BASE_URL\n        this.ONE_BOT_ACCESS_TOKEN = ONE_BOT_ACCESS_TOKEN\n        Debugger('set ONE_BOT_BASE_URL: \"%s\", ONE_BOT_ACCESS_TOKEN: \"%s\"', ONE_BOT_BASE_URL, ONE_BOT_ACCESS_TOKEN)\n        // 根据 configSchema 验证 config\n        validate(config, OneBot.configSchema)\n        if (!this.ONE_BOT_ACCESS_TOKEN) {\n            warn('未提供 ONE_BOT_ACCESS_TOKEN ！出于安全原因，请务必设置 AccessToken！')\n        }\n    }\n\n    /**\n     *\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param title 消息标题\n     * @param desp 消息正文\n     * @param option 额外推送选项\n     */\n    async send(title: string, desp: string, option: OneBotOption): Promise<SendResponse<OneBotResponse>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: \"%o\"', title, desp, option)\n        // !由于 OneBot 的 option 中带有必填项，所以需要校验\n        // 根据 optionSchema 验证 option\n        validate(option, OneBot.optionSchema as OptionSchema<OneBotOption>)\n        if (option.message_type === 'private' && !option.user_id) {\n            throw new Error('OneBot 私聊消息类型必须提供 user_id')\n        }\n        if (option.message_type === 'group' && !option.group_id) {\n            throw new Error('OneBot 群聊消息类型必须提供 group_id')\n        }\n        const { message_type = 'private', ...args } = option || {}\n        const message = `${title}${desp ? `\\n${desp}` : ''}`\n        return ajax<OneBotResponse>({\n            baseURL: this.ONE_BOT_BASE_URL,\n            url: '/send_msg',\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/json',\n                Authorization: `Bearer ${this.ONE_BOT_ACCESS_TOKEN}`,\n            },\n            data: {\n                auto_escape: false,\n                message_type,\n                message,\n                ...args,\n            },\n        })\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:push-deer')\n\nexport type PushDeerPushType = 'markdown' | 'text' | 'image'\n\nexport interface PushDeerConfig {\n    /**\n     * pushkey。请参考 https://github.com/easychen/pushdeer 获取\n     */\n    PUSH_DEER_PUSH_KEY: string\n\n    /**\n     * 使用自架版时的服务器端地址。例如 http://127.0.0.1:8800。默认为 https://api2.pushdeer.com\n     */\n    PUSH_DEER_ENDPOINT?: string\n}\n\nexport type PushDeerConfigSchema = ConfigSchema<PushDeerConfig>\n\nexport const pushDeerConfigSchema: PushDeerConfigSchema = {\n    PUSH_DEER_PUSH_KEY: {\n        type: 'string',\n        title: 'pushkey',\n        description: '请参考 https://github.com/easychen/pushdeer 获取',\n        required: true,\n    },\n    PUSH_DEER_ENDPOINT: {\n        type: 'string',\n        title: '使用自架版时的服务器端地址',\n        description: '例如 http://127.0..1:8800。默认为 https://api2.pushdeer.com',\n        required: false,\n        default: 'https://api2.pushdeer.com',\n    },\n} as const\n\nexport interface PushDeerOption {\n    /**\n     * 格式。文本=text，markdown，图片=image，默认为markdown。type 为 image 时，text 中为要发送图片的URL\n     */\n    type?: PushDeerPushType\n}\n\nexport type PushDeerOptionSchema = OptionSchema<PushDeerOption>\nexport const pushDeerOptionSchema: PushDeerOptionSchema = {\n    type: {\n        type: 'select',\n        title: '格式',\n        description: '文本=text，markdown，图片=image，默认为markdown。type 为 image 时，text 中为要发送图片的URL',\n        required: false,\n        default: 'markdown',\n        options: [\n            {\n                label: '文本',\n                value: 'text',\n            },\n            {\n                label: 'Markdown',\n                value: 'markdown',\n            },\n            {\n                label: '图片',\n                value: 'image',\n            },\n        ],\n    },\n} as const\n\nexport interface PushDeerResponse {\n    /**\n     * 正确为0，错误为非0\n     */\n    code: number\n    /**\n     * 错误信息。无错误时无此字段\n     */\n    error: string\n    /**\n     * 消息内容，错误时无此字段\n     */\n    content: {\n        result: string[]\n    }\n}\n\n/**\n * PushDeer 推送。 官方文档 https://github.com/easychen/pushdeer\n *\n * @author CaoMeiYouRen\n * @date 2022-02-28\n * @export\n * @class PushDeer\n */\nexport class PushDeer implements Send {\n\n    static readonly namespace = 'PushDeer'\n    static readonly configSchema = pushDeerConfigSchema\n    static readonly optionSchema = pushDeerOptionSchema\n\n    /**\n     * pushkey，请参考 https://github.com/easychen/pushdeer 获取\n     *\n     * @author CaoMeiYouRen\n     * @date 2022-02-28\n     * @private\n     */\n    private PUSH_DEER_PUSH_KEY: string\n\n    /**\n     * 使用自架版时的服务器端地址。例如 http://127.0.0.1:8800\n     *\n     * @author CaoMeiYouRen\n     * @date 2022-02-28\n     * @private\n     */\n    private PUSH_DEER_ENDPOINT: string\n\n    /**\n     * 创建 PushDeer 实例\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param config 配置\n     */\n    constructor(config: PushDeerConfig) {\n        const { PUSH_DEER_PUSH_KEY, PUSH_DEER_ENDPOINT } = config\n        this.PUSH_DEER_PUSH_KEY = PUSH_DEER_PUSH_KEY\n        this.PUSH_DEER_ENDPOINT = PUSH_DEER_ENDPOINT || 'https://api2.pushdeer.com'\n        Debugger('set PUSH_DEER_PUSH_KEY: \"%s\", PUSH_DEER_ENDPOINT: \"%s\"', PUSH_DEER_PUSH_KEY, PUSH_DEER_ENDPOINT)\n        // 根据 configSchema 验证 config\n        validate(config, PushDeer.configSchema)\n    }\n\n    /**\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param text 推送消息内容\n     * @param [desp=''] 消息内容第二部分\n     * @param [option={}] 额外推送选项\n     */\n    async send(title: string, desp: string = '', option?: PushDeerOption): Promise<SendResponse<PushDeerResponse>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: \"%o\"', title, desp, option)\n        const { type = 'markdown' } = option || {}\n        return ajax({\n            baseURL: this.PUSH_DEER_ENDPOINT,\n            url: '/message/push',\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/x-www-form-urlencoded',\n            },\n            data: {\n                text: title,\n                desp,\n                pushkey: this.PUSH_DEER_PUSH_KEY,\n                type,\n            },\n        })\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:push-plus')\n/**\nhtml\t默认模板，支持html文本\ntxt\t纯文本展示，不转义html\njson\t内容基于json格式展示\nmarkdown\t内容基于markdown格式展示\ncloudMonitor\t阿里云监控报警定制模板\njenkins\tjenkins插件定制模板\nroute\t路由器插件定制模板 */\nexport type PushPlusTemplateType = 'html' | 'txt' | 'json' | 'markdown' | 'cloudMonitor' | 'jenkins' | 'route'\n/**\nwechat\t免费\t微信公众号\nwebhook\t免费\t第三方webhook；企业微信、钉钉、飞书、server酱；webhook机器人推送\ncp\t免费\t企业微信应用；具体参考企业微信应用推送\nmail\t免费\t邮箱；具体参考邮件渠道使用说明\nsms\t收费\t短信，未开放\n */\nexport type PushPlusChannelType = 'wechat' | 'webhook' | 'cp' | 'sms' | 'mail'\n\nexport interface PushPlusConfig {\n    /**\n     *  请前往 https://www.pushplus.plus 领取\n     */\n    PUSH_PLUS_TOKEN: string\n}\n\nexport type PushPlusConfigSchema = ConfigSchema<PushPlusConfig>\n\nexport const pushPlusConfigSchema: PushPlusConfigSchema = {\n    PUSH_PLUS_TOKEN: {\n        type: 'string',\n        title: 'PushPlus Token',\n        description: '请前往 https://www.pushplus.plus/ 领取',\n        required: true,\n    },\n}\n\nexport interface PushPlusOption {\n    /**\n     * 模板类型\n     */\n    template?: PushPlusTemplateType\n    /**\n     * 渠道类型\n     */\n    channel?: PushPlusChannelType\n    /**\n     * 群组编码，不填仅发送给自己；channel为webhook时无效\n     */\n    topic?: string\n    /**\n     * webhook编码，仅在channel使用webhook渠道和CP渠道时需要填写\n     */\n    webhook?: string\n    /**\n     * 发送结果回调地址\n     */\n    callbackUrl?: string\n    /**\n     * 毫秒时间戳。格式如：1632993318000。服务器时间戳大于此时间戳，则消息不会发送\n     */\n    timestamp?: number\n}\n\nexport type PushPlusOptionSchema = OptionSchema<PushPlusOption>\n\nexport const pushPlusOptionSchema: PushPlusOptionSchema = {\n    template: {\n        type: 'select',\n        title: '模板类型',\n        description: 'html，txt，json，markdown，cloudMonitor，jenkins，route',\n        required: false,\n        default: 'html',\n        options: [\n            {\n                label: 'HTML',\n                value: 'html',\n            },\n            {\n                label: '文本',\n                value: 'txt',\n            },\n            {\n                label: 'JSON',\n                value: 'json',\n            },\n            {\n                label: 'Markdown',\n                value: 'markdown',\n            },\n            {\n                label: '阿里云监控',\n                value: 'cloudMonitor',\n            },\n            {\n                label: 'Jenkins',\n                value: 'jenkins',\n            },\n            {\n                label: '路由器',\n                value: 'route',\n            },\n        ],\n    },\n    channel: {\n        type: 'select',\n        title: '渠道类型',\n        description: 'wechat，webhook，cp，sms，mail',\n        required: false,\n        default: 'wechat',\n        options: [\n            {\n                label: '微信',\n                value: 'wechat',\n            },\n            {\n                label: 'Webhook',\n                value: 'webhook',\n            },\n            {\n                label: '企业微信',\n                value: 'cp',\n            },\n            {\n                label: '邮件',\n                value: 'mail',\n            },\n            {\n                label: '短信',\n                value: 'sms',\n            },\n        ],\n    },\n    topic: {\n        type: 'string',\n        title: '群组编码',\n        description: '不填仅发送给自己；channel为webhook时无效',\n        required: false,\n        default: '',\n    },\n    webhook: {\n        type: 'string',\n        title: 'webhook编码',\n        description: '仅在channel使用webhook渠道和CP渠道时需要填写',\n        required: false,\n        default: '',\n    },\n    callbackUrl: {\n        type: 'string',\n        title: '发送结果回调地址',\n        description: '发送结果回调地址',\n        required: false,\n        default: '',\n    },\n    timestamp: {\n        type: 'number',\n        title: '毫秒时间戳',\n        description: '格式如：1632993318000。服务器时间戳大于此时间戳，则消息不会发送',\n        required: false,\n        // default: 0,\n    },\n}\n\nexport interface PushPlusResponse {\n    // 200 为正确\n    code: number\n    msg: string\n    data: any\n}\n\n/**\n * pushplus 推送加开放平台，仅支持一对一推送。官方文档：https://www.pushplus.plus/doc/\n *\n * @author CaoMeiYouRen\n * @date 2021-03-03\n * @export\n * @class PushPlus\n */\nexport class PushPlus implements Send {\n\n    static readonly namespace = 'PushPlus'\n    static readonly configSchema = pushPlusConfigSchema\n    static readonly optionSchema = pushPlusOptionSchema\n    /**\n     * 请前往 https://www.pushplus.plus 领取\n     *\n     * @private\n     */\n    private PUSH_PLUS_TOKEN: string\n\n    /**\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param config 请前往 https://www.pushplus.plus 领取\n     */\n    constructor(config: PushPlusConfig) {\n        const { PUSH_PLUS_TOKEN } = config\n        this.PUSH_PLUS_TOKEN = PUSH_PLUS_TOKEN\n        Debugger('set PUSH_PLUS_TOKEN: \"%s\"', PUSH_PLUS_TOKEN)\n        // 根据 configSchema 验证 config\n        validate(config, PushPlus.configSchema)\n    }\n\n    /**\n     * 发送消息\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param title 消息标题\n     * @param [desp=''] 消息内容\n     * @param [option] 额外推送选项\n     */\n    send(title: string, desp: string = '', option?: PushPlusOption): Promise<SendResponse<PushPlusResponse>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: \"%o\"', title, desp, option)\n        const { template = 'html', channel = 'wechat', ...args } = option || {}\n        const content = desp || title\n        return ajax({\n            url: 'http://www.pushplus.plus/send',\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/json',\n            },\n            data: {\n                token: this.PUSH_PLUS_TOKEN,\n                title,\n                content: content || title,\n                template,\n                channel,\n                ...args,\n            },\n        })\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:qmsg')\n\n/**\n * 推送类型，见 [Qmsg](https://qmsg.zendee.cn/docs/api)。\n */\nexport type QmsgPushType = 'send' | 'group'\n\nexport interface QmsgConfig {\n    /**\n     * 推送的 key。在 [Qmsg 酱管理台](https://qmsg.zendee.cn/user) 查看\n     */\n    QMSG_KEY: string\n}\nexport type QmsgConfigSchema = ConfigSchema<QmsgConfig>\n\nexport const qmsgConfigSchema: QmsgConfigSchema = {\n    QMSG_KEY: {\n        type: 'string',\n        title: '推送的 key',\n        description: '在 [Qmsg 酱管理台](https://qmsg.zendee.cn/user) 查看',\n        required: true,\n    },\n} as const\n\nexport interface QmsgPrivateMsgOption {\n    /**\n     * send 表示发送消息给指定的QQ号，group 表示发送消息给指定的QQ群。默认为 send\n     */\n    type: 'send'\n    /**\n     * 指定要接收消息的QQ号或者QQ群。多个以英文逗号分割，例如：12345,12346\n     */\n    qq: string\n}\n\nexport interface QmsgGroupMsgOption {\n    /**\n     * send 表示发送消息给指定的QQ号，group 表示发送消息给指定的QQ群。默认为 send\n     */\n    type: 'group'\n    /**\n     * 指定要接收消息的QQ号或者QQ群。多个以英文逗号分割，例如：12345,12346\n     */\n    qq: string\n\n}\n\nexport type QmsgOption = (QmsgPrivateMsgOption | QmsgGroupMsgOption) & {\n    /**\n     * 机器人的QQ号。指定使用哪个机器人来发送消息，不指定则会自动随机选择一个在线的机器人发送消息。该参数仅私有云有效\n     */\n    bot?: string\n}\n\nexport type QmsgOptionSchema = OptionSchema<{\n    // 消息类型\n    type: 'send' | 'group'\n    // 指定要接收消息的QQ号或者QQ群。多个以英文逗号分割，例如：12345,12346\n    qq: string\n    // 机器人的QQ号。指定使用哪个机器人来发送消息，不指定则会自动随机选择一个在线的机器人发送消息。该参数仅私有云有效\n    bot?: string\n}>\n\nexport const qmsgOptionSchema: QmsgOptionSchema = {\n    type: {\n        type: 'select',\n        title: '消息类型',\n        description: 'send 表示发送消息给指定的QQ号，group 表示发送消息给指定的QQ群。默认为 send',\n        required: true,\n        default: 'send',\n        options: [\n            {\n                label: '私聊',\n                value: 'send',\n            },\n            {\n                label: '群聊',\n                value: 'group',\n            },\n        ],\n    },\n    qq: {\n        type: 'string',\n        title: '指定要接收消息的QQ号或者QQ群',\n        description: '多个以英文逗号分割，例如：12345,12346',\n        required: true,\n    },\n    bot: {\n        type: 'string',\n        title: '机器人的QQ号',\n        description: '指定使用哪个机器人来发送消息，不指定则会自动随机选择一个在线的机器人发送消息。该参数仅私有云有效',\n        required: false,\n    },\n} as const\n\nexport interface QmsgResponse {\n    /**\n     * 本次请求是否成功\n     */\n    success: boolean\n    /**\n     * 本次请求结果描述\n     */\n    reason: string\n    /**\n     * 错误代码。错误代码目前不可靠，如果要判断是否成功请使用success\n     */\n    code: number\n    info: any\n}\n\n/**\n * Qmsg酱。使用说明见 [Qmsg酱](https://qmsg.zendee.cn/docs)\n *\n * @author CaoMeiYouRen\n * @date 2022-02-17\n * @export\n * @class Qmsg\n */\nexport class Qmsg implements Send {\n\n    static readonly namespace = 'Qmsg酱'\n    static readonly configSchema = qmsgConfigSchema\n    static readonly optionSchema = qmsgOptionSchema\n\n    private QMSG_KEY: string\n\n    constructor(config: QmsgConfig) {\n        const { QMSG_KEY } = config\n        this.QMSG_KEY = QMSG_KEY\n        Debugger('set QMSG_KEY: \"%s\"', QMSG_KEY)\n        // 根据 configSchema 验证 config\n        validate(config, Qmsg.configSchema)\n    }\n\n    /**\n     *\n     * 发送消息\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param title 消息标题\n     * @param [desp] 消息描述\n     * @param [option] QmsgOption 选项\n     */\n    async send(title: string, desp: string, option: QmsgOption): Promise<SendResponse<QmsgResponse>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: \"%o\"', title, desp, option)\n        // !由于 Qmsg 酱的 option 中带有必填项，所以需要校验\n        // 根据 optionSchema 验证 option\n        validate(option, Qmsg.optionSchema)\n        const { qq, type = 'send', bot } = option || {}\n        const msg = `${title}${desp ? `\\n${desp}` : ''}`\n        return ajax({\n            url: `https://qmsg.zendee.cn/${type}/${this.QMSG_KEY}`,\n            headers: {\n                'Content-Type': 'application/x-www-form-urlencoded',\n            },\n            method: 'POST',\n            data: { msg, qq, bot },\n        })\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:server-chan-turbo')\n\nexport type ChannelValue = 98 | 66 | 1 | 2 | 3 | 8 | 0 | 88 | 18 | 9\n\nexport type Channel = `${ChannelValue}` | `${ChannelValue}|${ChannelValue}`\n\nexport interface ServerChanTurboConfig {\n    /**\n     * Server酱 Turbo 的 SCTKEY\n     * 请前往 https://sct.ftqq.com/sendkey 领取\n     */\n    SERVER_CHAN_TURBO_SENDKEY: string\n}\n\nexport type ServerChanTurboConfigSchema = ConfigSchema<ServerChanTurboConfig>\nexport const serverChanTurboConfigSchema: ServerChanTurboConfigSchema = {\n    SERVER_CHAN_TURBO_SENDKEY: {\n        type: 'string',\n        title: 'SCTKEY',\n        description: 'Server酱 Turbo 的 SCTKEY。请前往 https://sct.ftqq.com/sendkey 领取',\n        required: true,\n    },\n} as const\n\n/**\n * 附加参数\n */\nexport type ServerChanTurboOption = {\n    /**\n     *  消息卡片内容，选填。最大长度 64。如果不指定，将自动从 desp 中截取生成。\n     */\n    short?: string\n    /**\n     * 是否隐藏调用 IP，选填。如果不指定，则显示；为 1 则隐藏。\n     */\n    noip?: '1' | 1 | true\n    /**\n     * 动态指定本次推送使用的消息通道，选填。如不指定，则使用网站上的消息通道页面设置的通道。支持最多两个通道，多个通道值用竖线 \"|\" 隔开。\n     * 通道对应的值如下：\n     * 官方Android版·β=98\n     * 企业微信应用消息=66\n     * 企业微信群机器人=1\n     * 钉钉群机器人=2\n     * 飞书群机器人=3\n     * Bark iOS=8\n     * 测试号=0\n     * 自定义=88\n     * PushDeer=18\n     * 方糖服务号=9\n     */\n    channel?: Channel\n    /**\n     * 消息抄送的 openid，选填。只支持测试号和企业微信应用消息通道。多个 openid 用 \",\" 隔开。企业微信应用消息通道的 openid 参数，内容为接收人在企业微信中的 UID，多个人请 \"|\" 隔开。\n     */\n    openid?: string\n}\n\nexport type ServerChanTurboOptionSchema = OptionSchema<{\n    short?: string\n    openid?: string\n    channel?: string\n    noip?: boolean\n}>\nexport const serverChanTurboOptionSchema: ServerChanTurboOptionSchema = {\n    short: {\n        type: 'string',\n        title: '消息卡片内容',\n        description: '选填。最大长度 64。如果不指定，将自动从 desp 中截取生成。',\n        required: false,\n    },\n    noip: {\n        type: 'boolean',\n        title: '是否隐藏调用 IP',\n        description: '选填。如果不指定，则显示；为 1/true 则隐藏。',\n        required: false,\n    },\n    channel: {\n        type: 'string',\n        title: '消息通道',\n        description: '选填。动态指定本次推送使用的消息通道，支持最多两个通道，多个通道值用竖线 \"|\" 隔开。',\n        required: false,\n    },\n    openid: {\n        type: 'string',\n        title: '消息抄送的 openid',\n        description: '选填。只支持测试号和企业微信应用消息通道。多个 openid 用 \",\" 隔开。企业微信应用消息通道的 openid 参数，内容为接收人在企业微信中的 UID，多个人请 \"|\" 隔开。',\n        required: false,\n    },\n}\n\nexport interface ServerChanTurboResponse {\n    // 0 表示成功，其他值表示失败\n    code: number\n    message: string\n    data: {\n        // 推送消息的 ID\n        pushid: string\n        // 推送消息的阅读凭证\n        readkey: string\n        error: string\n        errno: number\n    }\n}\n\n/**\n * Server 酱·Turbo\n * 文档 https://sct.ftqq.com/\n *\n * @author CaoMeiYouRen\n * @date 2021-02-27\n * @export\n * @class ServerChanTurbo\n */\nexport class ServerChanTurbo implements Send {\n\n    static readonly namespace = 'Server酱·Turbo'\n    static readonly configSchema = serverChanTurboConfigSchema\n    static readonly optionSchema = serverChanTurboOptionSchema\n\n    /**\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param config 请前往 https://sct.ftqq.com/sendkey 领取\n     */\n    constructor(config: ServerChanTurboConfig) {\n        const { SERVER_CHAN_TURBO_SENDKEY } = config\n        this.SCTKEY = SERVER_CHAN_TURBO_SENDKEY\n        Debugger('set SCTKEY: \"%s\"', this.SCTKEY)\n        // 根据 configSchema 验证 config\n        validate(config, ServerChanTurbo.configSchema)\n    }\n\n    /**\n     *\n     *\n     * @private 请前往 https://sct.ftqq.com/sendkey 领取\n     */\n    private SCTKEY: string\n\n    /**\n     * 发送消息\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param title 消息的标题\n     * @param [desp=''] 消息的内容，支持 Markdown\n     * @param [option={}] 额外发送选项\n     */\n    async send(title: string, desp: string = '', option: ServerChanTurboOption = {}): Promise<SendResponse<ServerChanTurboResponse>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: %O', title, desp, option)\n        if (option.noip === 1 || option.noip === true) {\n            option.noip = '1'\n        }\n        const data = {\n            text: title,\n            desp,\n            ...option,\n        }\n        return ajax({\n            url: `https://sctapi.ftqq.com/${this.SCTKEY}.send`,\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/x-www-form-urlencoded',\n            },\n            data,\n        })\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:server-chan-v3')\n\nexport interface ServerChanV3Config {\n    /**\n     * 请前往 https://sc3.ft07.com/sendkey 领取\n     */\n    SERVER_CHAN_V3_SENDKEY: string\n}\n\nexport type ServerChanV3ConfigSchema = ConfigSchema<ServerChanV3Config>\nexport const serverChanV3ConfigSchema: ServerChanV3ConfigSchema = {\n    SERVER_CHAN_V3_SENDKEY: {\n        type: 'string',\n        title: 'SENDKEY',\n        description: '请前往 https://sc3.ft07.com/sendkey 领取',\n        required: true,\n    },\n} as const\n\n/**\n * 附加参数\n */\nexport type ServerChanV3Option = {\n    tags?: string | string[] // 标签列表，多个标签使用竖线分隔；也可以用数组格式，数组格式下不要加竖线\n    short?: string // 推送消息的简短描述，用于指定消息卡片的内容部分，尤其是在推送markdown的时候\n}\n\nexport type ServerChanV3OptionSchema = OptionSchema<{\n    tags?: string[]\n    short?: string\n}>\nexport const serverChanV3OptionSchema: ServerChanV3OptionSchema = {\n    tags: {\n        type: 'array',\n        title: '标签列表',\n        description: '多个标签用数组格式',\n        required: false,\n    },\n    short: {\n        type: 'string',\n        title: '推送消息的简短描述',\n        description: '用于指定消息卡片的内容部分，尤其是在推送markdown的时候',\n        required: false,\n    },\n} as const\n\nexport interface ServerChanV3Response {\n    // 0 表示成功，其他值表示失败\n    code: number\n    message: string\n    errno: number\n    data: {\n        // 推送消息的 ID\n        pushid: string\n        meta: {\n            android: any\n            devices: any[]\n        }\n    }\n}\n\n/**\n * Server酱³\n * 文档：https://sc3.ft07.com/doc\n * @author CaoMeiYouRen\n * @date 2024-10-04\n * @export\n * @class ServerChanV3\n */\nexport class ServerChanV3 implements Send {\n\n    static readonly namespace = 'Server酱³'\n    static readonly configSchema = serverChanV3ConfigSchema\n    static readonly optionSchema = serverChanV3OptionSchema\n\n    /**\n     * 请前往 https://sc3.ft07.com/sendkey 领取\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-10-04\n     * @private\n     */\n    private sendkey: string\n\n    private uid: string = ''\n\n    /**\n     * 创建 ServerChanV3 实例\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param config 请前往 https://sc3.ft07.com/sendkey 领取\n     */\n    constructor(config: ServerChanV3Config) {\n        const { SERVER_CHAN_V3_SENDKEY } = config\n        const sendkey = SERVER_CHAN_V3_SENDKEY\n        this.sendkey = sendkey\n        Debugger('set sendkey: \"%s\"', sendkey)\n        // 根据 configSchema 验证 config\n        validate(config, ServerChanV3.configSchema)\n        this.uid = this.sendkey.match(/^sctp(\\d+)t/)?.[1]\n        if (!this.uid) {\n            throw new Error('SERVER_CHAN_V3_SENDKEY 不合法！')\n        }\n    }\n\n    /**\n     * 发送消息\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param title 消息的标题\n     * @param [desp=''] 消息的内容，支持 Markdown\n     * @param [option={}] 额外发送选项\n     */\n    async send(title: string, desp: string = '', option: ServerChanV3Option = {}): Promise<SendResponse<ServerChanV3Response>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: %O', title, desp, option)\n        if (Array.isArray(option.tags)) {\n            option.tags = option.tags.join('|')\n        }\n        const data = {\n            text: title,\n            desp,\n            ...option,\n        }\n        return ajax({\n            url: `https://${this.uid}.push.ft07.com/send/${this.sendkey}.send`,\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/json',\n            },\n            data,\n        })\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:telegram')\n\nexport interface TelegramConfig {\n    /**\n     * 机器人令牌\n     * 您可以从 https://t.me/BotFather 获取 Token。\n     * @author CaoMeiYouRen\n     * @date 2023-10-22\n     */\n    TELEGRAM_BOT_TOKEN: string\n    /**\n     * 支持对话/群组/频道的 Chat ID\n     * 您可以转发消息到 https://t.me/JsonDumpBot 获取 Chat ID\n     * @author CaoMeiYouRen\n     * @date 2023-10-22\n     */\n    TELEGRAM_CHAT_ID: number\n    /**\n     * 代理地址\n     */\n    PROXY_URL?: string\n}\n\nexport type TelegramConfigSchema = ConfigSchema<TelegramConfig>\nexport const telegramConfigSchema: TelegramConfigSchema = {\n    TELEGRAM_BOT_TOKEN: {\n        type: 'string',\n        title: '机器人令牌',\n        description: '您可以从 https://t.me/BotFather 获取 Token。',\n        required: true,\n    },\n    TELEGRAM_CHAT_ID: {\n        type: 'number',\n        title: '支持对话/群组/频道的 Chat ID',\n        description: '您可以转发消息到 https://t.me/JsonDumpBot 获取 Chat ID',\n        required: true,\n    },\n    PROXY_URL: {\n        type: 'string',\n        title: '代理地址',\n        description: '代理地址',\n        required: false,\n    },\n} as const\n\n/**\n * 参考 https://core.telegram.org/bots/api#sendmessage\n *\n * @author CaoMeiYouRen\n * @date 2024-11-09\n * @export\n * @interface TelegramOption\n */\nexport interface TelegramOption {\n    /**\n     * 静默发送\n     * 静默地发送消息。消息发布后用户会收到无声通知。\n     */\n    disable_notification?: boolean\n    /**\n     * 阻止转发/保存\n     * 如果启用，Telegram 中的机器人消息将受到保护，不会被转发和保存。\n     */\n    protect_content?: boolean\n    /**\n     * 话题 ID\n     * 可选的唯一标识符，用以向该标识符对应的话题发送消息，仅限启用了话题功能的超级群组可用\n     */\n    message_thread_id?: string\n\n    /**\n     * 消息格式，支持 MarkdownV2、HTML 等格式。Markdown字段已弃用，请改为使用MarkdownV2。\n     * 详见：https://core.telegram.org/bots/api#formatting-options\n     */\n    parse_mode?: 'MarkdownV2' | 'HTML'\n    [key: string]: any\n}\n\nexport type TelegramOptionSchema = OptionSchema<TelegramOption>\n\nexport const telegramOptionSchema: TelegramOptionSchema = {\n    disable_notification: {\n        type: 'boolean',\n        title: '静默发送',\n        description: '静默地发送消息。消息发布后用户会收到无声通知。',\n        required: false,\n    },\n    protect_content: {\n        type: 'boolean',\n        title: '阻止转发/保存',\n        description: '如果启用，Telegram 中的机器人消息将受到保护，不会被转发和保存。',\n        required: false,\n    },\n    message_thread_id: {\n        type: 'string',\n        title: '话题 ID',\n        description: '可选的唯一标识符，用以向该标识符对应的话题发送消息，仅限启用了话题功能的超级群组可用',\n        required: false,\n    },\n    parse_mode: {\n        type: 'select',\n        title: '消息格式',\n        description: '消息格式，支持 MarkdownV2、HTML 等格式。Markdown字段已弃用，请改为使用MarkdownV2。',\n        required: false,\n        options: [{ label: 'MarkdownV2', value: 'MarkdownV2' }, { label: 'HTML', value: 'HTML' }],\n    },\n} as const\n\ninterface From {\n    id: number\n    is_bot: boolean\n    first_name: string\n    username: string\n}\ninterface Chat {\n    id: number\n    first_name: string\n    last_name: string\n    username: string\n    type: string\n}\ninterface Result {\n    message_id: number\n    from: From\n    chat: Chat\n    date: number\n    text: string\n}\nexport interface TelegramResponse {\n    ok: boolean\n    result: Result\n}\n\n/**\n *  Telegram Bot 推送。\n *  官方文档：https://core.telegram.org/bots/api#making-requests\n *\n * @author CaoMeiYouRen\n * @date 2023-09-16\n * @export\n * @class Telegram\n */\nexport class Telegram implements Send {\n\n    static readonly namespace = 'Telegram'\n    static readonly configSchema = telegramConfigSchema\n    static readonly optionSchema = telegramOptionSchema\n\n    /**\n     * 机器人令牌\n     * 您可以从 https://t.me/BotFather 获取 Token。\n     * @author CaoMeiYouRen\n     * @date 2023-10-22\n     * @private\n     */\n    private TELEGRAM_BOT_TOKEN: string\n    /**\n     * 支持对话/群组/频道的 Chat ID\n     * 您可以转发消息到 https://t.me/JsonDumpBot 获取 Chat ID\n     * @author CaoMeiYouRen\n     * @date 2023-10-22\n     * @private\n     */\n    private TELEGRAM_CHAT_ID: number\n\n    proxyUrl?: string\n\n    constructor(config: TelegramConfig) {\n        Debugger('config: %O', config)\n        Object.assign(this, config)\n        // 根据 configSchema 验证 config\n        validate(config, Telegram.configSchema)\n        if (config.PROXY_URL) {\n            this.proxyUrl = config.PROXY_URL\n        }\n    }\n\n    /**\n     * 发送消息\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-09\n     * @param title 消息标题\n     * @param [desp] 消息正文，和 title 相加后不超过 4096 个字符\n     * @param [option] 其他参数\n     */\n    async send(title: string, desp?: string, option?: TelegramOption): Promise<SendResponse<TelegramResponse>> {\n        const url = `https://api.telegram.org/bot${this.TELEGRAM_BOT_TOKEN}/sendMessage`\n        Debugger('title: \"%s\", desp: \"%s\", option: %O', title, desp, option)\n        const text = `${title}${desp ? `\\n${desp}` : ''}`\n        return ajax<TelegramResponse>({\n            url,\n            method: 'POST',\n            proxyUrl: this.proxyUrl,\n            data: {\n                chat_id: this.TELEGRAM_CHAT_ID,\n                text,\n            },\n        })\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { warn } from '@/utils/helper'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:wechat-app')\nexport type WechatAppMsgType = 'text' | 'markdown' | 'voice' | 'file' | 'image' | 'voice' | 'video' | 'textcard' | 'news' | 'mpnews' | 'miniprogram_notice' | 'template_card'\nexport interface WechatAppConfig {\n    /**\n     * 企业ID，获取方式参考：[术语说明-corpid](https://work.weixin.qq.com/api/doc/90000/90135/91039#14953/corpid)\n     *\n     */\n    WECHAT_APP_CORPID: string\n    /**\n     * 应用的凭证密钥，获取方式参考：[术语说明-secret](https://work.weixin.qq.com/api/doc/90000/90135/91039#14953/secret)\n     *\n     */\n    WECHAT_APP_SECRET: string\n    /**\n     * 企业应用的id。企业内部开发，可在应用的设置页面查看\n     *\n     */\n    WECHAT_APP_AGENTID: number\n}\n\nexport type WechatAppConfigSchema = ConfigSchema<WechatAppConfig>\n\nexport const wechatAppConfigSchema: WechatAppConfigSchema = {\n    WECHAT_APP_CORPID: {\n        type: 'string',\n        title: '企业ID',\n        description: '企业ID，获取方式参考：[术语说明-corpid](https://work.weixin.qq.com/api/doc/90000/90135/91039#14953/corpid)',\n        required: true,\n        default: '',\n    },\n    WECHAT_APP_SECRET: {\n        type: 'string',\n        title: '应用的凭证密钥',\n        description: '应用的凭证密钥，获取方式参考：[术语说明-secret](https://work.weixin.qq.com/api/doc/90000/90135/91039#14953/secret)',\n        required: true,\n        default: '',\n    },\n    WECHAT_APP_AGENTID: {\n        type: 'number',\n        title: '企业应用的id',\n        description: '企业应用的id。企业内部开发，可在应用的设置页面查看',\n        required: true,\n        default: 0,\n    },\n} as const\n\nexport type WechatAppOption = {\n    // 消息类型\n    msgtype: WechatAppMsgType\n    // 表示是否是保密消息，0表示可对外分享，1表示不能，默认0。\n    safe?: 0 | 1\n    // 表示是否开启id转译，0表示否，1表示是，默认0。\n    enable_id_trans?: 0 | 1\n    // 表示是否开启重复消息检查，0表示否，1表示是，默认0\n    enable_duplicate_check?: 0 | 1\n    // 表示是否重复消息检查的时间间隔，默认1800s，最大不超过4小时\n    duplicate_check_interval?: number\n    [key: string]: any\n    // 指定接收消息的成员，成员ID列表（多个接收者用‘|’分隔，最多支持1000个）。\n    // 特殊情况：指定为\"@all\"，则向该企业应用的全部成员发送\n    touser?: string\n} & ({\n    // 指定接收消息的部门，部门ID列表，多个接收者用‘|’分隔，最多支持100个。\n    // 当touser为\"@all\"时忽略本参数\n    toparty?: string\n} | {\n    // 指定接收消息的标签，标签ID列表，多个接收者用‘|’分隔，最多支持100个。\n    // 当touser为\"@all\"时忽略本参数\n    totag?: string\n})\n\nexport type WechatAppOptionSchema = OptionSchema<WechatAppOption>\nexport const wechatAppOptionSchema: WechatAppOptionSchema = {\n    msgtype: {\n        type: 'select',\n        title: '消息类型',\n        description: '消息类型',\n        required: true,\n        options: [\n            {\n                label: '文本',\n                value: 'text',\n            },\n            {\n                label: 'Markdown',\n                value: 'markdown',\n            },\n            {\n                label: '语音',\n                value: 'voice',\n            },\n            {\n                label: '文件',\n                value: 'file',\n            },\n            {\n                label: '图片',\n                value: 'image',\n            },\n            {\n                label: '视频',\n                value: 'video',\n            },\n            {\n                label: '图文',\n                value: 'news',\n            },\n            {\n                label: '小程序通知',\n                value: 'miniprogram_notice',\n            },\n            {\n                label: '模板卡片',\n                value: 'template_card',\n            },\n        ],\n    },\n    safe: {\n        type: 'select',\n        title: '是否是保密消息',\n        description: '表示是否是保密消息，0表示可对外分享，1表示不能',\n        required: false,\n        options: [\n            {\n                label: '否',\n                value: 0,\n            },\n            {\n                label: '是',\n                value: 1,\n            },\n        ],\n    },\n    enable_id_trans: {\n        type: 'select',\n        title: '是否开启id转译',\n        description: '表示是否开启id转译，0表示否，1表示是，默认0。',\n        required: false,\n        options: [\n            {\n                label: '否',\n                value: 0,\n            },\n            {\n                label: '是',\n                value: 1,\n            },\n        ],\n    },\n    enable_duplicate_check: {\n        type: 'select',\n        title: '是否开启重复消息检查',\n        description: '表示是否开启重复消息检查，0表示否，1表示是，默认',\n        required: false,\n        options: [\n            {\n                label: '否',\n                value: 0,\n            },\n            {\n                label: '是',\n                value: 1,\n            },\n        ],\n    },\n    duplicate_check_interval: {\n        type: 'number',\n        title: '重复消息检查的时间间隔',\n        description: '表示是否重复消息检查的时间间隔，默认1800s，最大不超过4小时',\n        required: false,\n    },\n    touser: {\n        type: 'string',\n        title: '指定接收消息的成员',\n        description: '指定接收消息的成员，成员ID列表（多个接收者用‘|’分隔，最多支持1000个）。',\n        required: false,\n    },\n    toparty: {\n        type: 'string',\n        title: '指定接收消息的部门',\n        description: '指定接收消息的部门，部门ID列表，多个接收者用‘|’分隔，最多支持100个。',\n        required: false,\n    },\n    totag: {\n        type: 'string',\n        title: '指定接收消息的标签',\n        description: '指定接收消息的标签，标签ID列表，多个接收者用‘|’分隔，最多支持100个。',\n        required: false,\n    },\n} as const\n\nexport interface WechatAppResponse {\n    // 企业微信返回的错误码，为0表示成功，非0表示调用失败\n    errcode: number\n    errmsg: string\n    invaliduser?: string\n    invalidparty?: string\n    invalidtag?: string\n    unlicenseduser?: string\n    msgid: string\n    response_code?: string\n}\n/**\n * 企业微信应用推送，文档：https://developer.work.weixin.qq.com/document/path/90664\n *\n * @author CaoMeiYouRen\n * @date 2021-02-28\n * @export\n * @class WechatApp\n */\nexport class WechatApp implements Send {\n\n    static readonly namespace = '企业微信应用'\n    static readonly configSchema = wechatAppConfigSchema\n    static readonly optionSchema = wechatAppOptionSchema\n\n    private ACCESS_TOKEN: string\n\n    private WECHAT_APP_CORPID: string\n    private WECHAT_APP_SECRET: string\n    private WECHAT_APP_AGENTID: number\n\n    /**\n     * ACCESS_TOKEN 的过期时间(时间戳)\n     *\n     * @private\n     */\n    private expiresTime: number\n\n    constructor(config: WechatAppConfig) {\n        Debugger('config: %O', config)\n        Object.assign(this, config)\n        // 根据 configSchema 验证 config\n        validate(config, WechatApp.configSchema)\n    }\n\n    private async getAccessToken(): Promise<string> {\n        const { data } = await ajax({\n            url: 'https://qyapi.weixin.qq.com/cgi-bin/gettoken',\n            query: {\n                corpid: this.WECHAT_APP_CORPID,\n                corpsecret: this.WECHAT_APP_SECRET,\n            },\n        })\n        if (data?.errcode !== 0) { // 出错返回码，为0表示成功，非0表示调用失败\n            throw new Error(data?.errmsg || '获取 access_token 失败！')\n        }\n        const { access_token, expires_in = 7200 } = data\n        Debugger('获取 access_token 成功: %s', access_token)\n        this.extendexpiresTime(expires_in)\n        return access_token\n    }\n\n    /**\n     * 延长过期时间\n     *\n     * @author CaoMeiYouRen\n     * @date 2021-03-03\n     * @private\n     * @param expiresIn 延长的秒数\n     */\n    private extendexpiresTime(expiresIn: number): void {\n        this.expiresTime = Date.now() + expiresIn * 1000 // 设置过期时间\n    }\n\n    /**\n     * 发送消息\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param title 消息标题\n     * @param [desp] 消息内容，最长不超过2048个字节，超过将截断（支持id转译）\n     * @param [option] 额外推送选项\n     */\n    async send(title: string, desp?: string, option?: WechatAppOption): Promise<SendResponse<WechatAppResponse>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: %O', title, desp, option)\n        if (!this.ACCESS_TOKEN || Date.now() >= this.expiresTime) {\n            this.ACCESS_TOKEN = await this.getAccessToken()\n        }\n        const { msgtype = 'text', touser: _touser, ...args } = option || {}\n        if (!_touser) {\n            warn('未指定 touser，将使用 \"@all\" 向全体成员推送')\n        }\n        const sep = msgtype === 'markdown' ? '\\n\\n' : '\\n'\n        const content = `${title}${desp ? `${sep}${desp}` : ''}`\n        const touser = _touser || '@all' // 如果没有指定 touser，则使用全体成员\n        return ajax({\n            url: 'https://qyapi.weixin.qq.com/cgi-bin/message/send',\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/json',\n            },\n            query: {\n                access_token: this.ACCESS_TOKEN,\n            },\n            data: {\n                touser,\n                msgtype,\n                agentid: this.WECHAT_APP_AGENTID,\n                [msgtype]: {\n                    content,\n                },\n                ...args,\n            },\n        })\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:wechat-robot')\n\nexport type WechatRobotMsgType = 'text' | 'markdown' | 'image' | 'news' | 'file' | 'voice' | 'template_card'\n\nexport interface WechatRobotConfig {\n    // 企业微信机器人的key\n    WECHAT_ROBOT_KEY: string\n}\nexport type WechatRobotConfigSchema = ConfigSchema<WechatRobotConfig>\nexport const wechatRobotConfigSchema: WechatRobotConfigSchema = {\n    WECHAT_ROBOT_KEY: {\n        type: 'string',\n        title: '企业微信机器人的key',\n        description: '企业微信机器人的key',\n        required: true,\n    },\n} as const\n\nexport interface WechatRobotOption {\n    msgtype?: WechatRobotMsgType\n    [key: string]: any\n}\nexport type WechatRobotOptionSchema = OptionSchema<WechatRobotOption>\nexport const wechatRobotOptionSchema: WechatRobotOptionSchema = {\n    msgtype: {\n        type: 'select',\n        title: '消息类型',\n        description: '消息类型',\n        options: [\n            {\n                label: '文本',\n                value: 'text',\n            },\n            {\n                label: 'Markdown',\n                value: 'markdown',\n            },\n            {\n                label: '图片',\n                value: 'image',\n            },\n            {\n                label: '图文',\n                value: 'news',\n            },\n            {\n                label: '文件',\n                value: 'file',\n            },\n            {\n                label: '语音',\n                value: 'voice',\n            },\n            {\n                label: '模板卡片',\n                value: 'template_card',\n            },\n        ],\n        required: false,\n        default: 'text',\n    },\n} as const\n\nexport interface WechatRobotResponse {\n    // 企业微信机器人返回的错误码，为0表示成功，非0表示调用失败\n    errcode: number\n    errmsg: string\n}\n\n/**\n * 企业微信群机器人。文档: [如何使用群机器人](https://developer.work.weixin.qq.com/document/path/91770)\n *\n * @author CaoMeiYouRen\n * @date 2021-02-28\n * @export\n * @class WechatRobot\n */\nexport class WechatRobot implements Send {\n\n    static readonly namespace = '企业微信群机器人'\n    static readonly configSchema = wechatRobotConfigSchema\n    static readonly optionSchema = wechatRobotOptionSchema\n\n    private WECHAT_ROBOT_KEY: string\n\n    constructor(config: WechatRobotConfig) {\n        const { WECHAT_ROBOT_KEY } = config\n        this.WECHAT_ROBOT_KEY = WECHAT_ROBOT_KEY\n        Debugger('set WECHAT_ROBOT_KEY: \"%s\"', WECHAT_ROBOT_KEY)\n        // 根据 configSchema 验证 config\n        validate(config, WechatRobot.configSchema)\n    }\n\n    /**\n     *\n     *\n     * @author CaoMeiYouRen\n     * @date 2024-11-08\n     * @param title 消息标题\n     * @param [desp] 消息内容。text内容，最长不超过2048个字节；markdown内容，最长不超过4096个字节；必须是utf8编码\n     * @param [option] 额外推送选项\n     */\n    async send(title: string, desp?: string, option?: WechatRobotOption): Promise<SendResponse<WechatRobotResponse>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: %O', title, desp, option)\n        const { msgtype = 'text', ...args } = option || {}\n        const sep = msgtype === 'markdown' ? '\\n\\n' : '\\n'\n        const content = `${title}${desp ? `${sep}${desp}` : ''}`\n        return ajax({\n            url: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send',\n            headers: {\n                'Content-Type': 'application/json',\n            },\n            method: 'POST',\n            query: { key: this.WECHAT_ROBOT_KEY },\n            data: {\n                msgtype,\n                [msgtype]: { content },\n                ...args,\n            },\n        })\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\n\nconst Debugger = debug('push:xi-zhi')\n\nexport interface XiZhiConfig {\n    // 息知的 key，前往 https://xz.qqoq.net/#/index 获取\n    XI_ZHI_KEY: string\n}\n\nexport type XiZhiConfigSchema = ConfigSchema<XiZhiConfig>\nexport const xiZhiConfigSchema: XiZhiConfigSchema = {\n    XI_ZHI_KEY: {\n        type: 'string',\n        title: '息知的 key',\n        description: '前往 https://xz.qqoq.net/#/index 获取',\n        required: true,\n    },\n} as const\n\nexport interface XiZhiOption {\n}\n\nexport type XiZhiOptionSchema = OptionSchema<XiZhiOption>\nexport const xiZhiOptionSchema: XiZhiOptionSchema = {\n} as const\n\nexport interface XiZhiResponse {\n    // 状态码，200 表示成功\n    code: number\n    msg: string\n}\n\n/**\n * 息知 推送，官方文档：https://xz.qqoq.net/#/index\n *\n * @author CaoMeiYouRen\n * @date 2022-02-18\n * @export\n * @class XiZhi\n */\nexport class XiZhi implements Send {\n\n    static readonly namespace = '息知'\n    static readonly configSchema = xiZhiConfigSchema\n    static readonly optionSchema = xiZhiOptionSchema\n\n    private XI_ZHI_KEY: string\n\n    constructor(config: XiZhiConfig) {\n        const { XI_ZHI_KEY } = config\n        this.XI_ZHI_KEY = XI_ZHI_KEY\n        Debugger('set XI_ZHI_KEY: \"%s\"', XI_ZHI_KEY)\n        // 根据 configSchema 验证 config\n        validate(config, XiZhi.configSchema)\n    }\n\n    async send(title: string, desp?: string, option?: XiZhiOption): Promise<SendResponse<XiZhiResponse>> {\n        Debugger('title: \"%s\", desp: \"%s\"', title, desp)\n        return ajax({\n            url: `https://xizhi.qqoq.net/${this.XI_ZHI_KEY}.send`,\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/json',\n            },\n            data: {\n                title,\n                content: desp,\n            },\n        })\n    }\n\n}\n","import debug from 'debug'\nimport { Send } from '@/interfaces/send'\nimport { ajax } from '@/utils/ajax'\nimport { SendResponse } from '@/interfaces/response'\nimport { ConfigSchema, OptionSchema } from '@/interfaces/schema'\nimport { validate } from '@/utils/validate'\nimport { uniq } from '@/utils/helper'\n\nconst Debugger = debug('push:wx-pusher')\n\nexport interface WxPusherConfig {\n    /**\n     * WxPusher 的 appToken。在 https://wxpusher.zjiecode.com/admin/main/app/appToken 申请\n     */\n    WX_PUSHER_APP_TOKEN: string\n    /**\n     * WxPusher 的 uid。在 https://wxpusher.zjiecode.com/admin/main/wxuser/list 查看\n     */\n    WX_PUSHER_UID: string\n}\n\nexport type WxPusherConfigSchema = ConfigSchema<WxPusherConfig>\n\nexport const wxPusherConfigSchema: WxPusherConfigSchema = {\n    WX_PUSHER_APP_TOKEN: {\n        type: 'string',\n        title: 'appToken',\n        description: '在 https://wxpusher.zjiecode.com/admin/main/app/appToken 申请',\n        required: true,\n    },\n    WX_PUSHER_UID: {\n        type: 'string',\n        title: 'uid',\n        description: '在 https://wxpusher.zjiecode.com/admin/main/wxuser/list 查看',\n        required: true,\n    },\n} as const\n\nexport interface WxPusherOption {\n    /**\n     * 消息摘要，显示在微信聊天页面或者模版消息卡片上，限制长度20，可以不传，不传默认截取content前面的内容。\n     */\n    summary?: string\n    /**\n     * 内容类型 1表示文字  2表示html(只发送body标签内部的数据即可，不包括body标签) 3表示markdown\n     * @default 1\n     */\n    contentType?: 1 | 2 | 3\n    /**\n     * 是否保存发送内容，1保存，0不保存\n     * @default 0\n     */\n    save?: 0 | 1\n    /**\n     * 主题ID，可以根据主题ID发送消息，可以在主题管理中查看主题ID\n     */\n    topicIds?: number[]\n    /**\n     * 发送目标的UID，是一个数组。注意uids和topicIds可以同时填写，也可以只填写一个。\n     */\n    uids?: string[]\n    /**\n     * 发送url，可以不传，如果传了，则根据url弹出通知\n     */\n    url?: string\n    /**\n     * 验证负载，仅针对text消息类型有效\n     */\n    verifyPayload?: string\n}\n\nexport type WxPusherOptionSchema = OptionSchema<WxPusherOption>\n\nexport const wxPusherOptionSchema: WxPusherOptionSchema = {\n    summary: {\n        type: 'string',\n        title: '消息摘要',\n        description: '显示在微信聊天页面或者模版消息卡片上，限制长度20，可以不传，不传默认截取content前面的内容。',\n        required: false,\n    },\n    contentType: {\n        type: 'select',\n        title: '内容类型',\n        description: '内容类型',\n        required: false,\n        default: 1,\n        options: [\n            {\n                label: '文本',\n                value: 1,\n            },\n            {\n                label: 'HTML',\n                value: 2,\n            },\n            {\n                label: 'Markdown',\n                value: 3,\n            },\n        ],\n    },\n    save: {\n        type: 'select',\n        title: '是否保存发送内容',\n        description: '是否保存发送内容，1保存，0不保存，默认0',\n        required: false,\n        default: 0,\n        options: [\n            {\n                label: '不保存',\n                value: 0,\n            },\n            {\n                label: '保存',\n                value: 1,\n            },\n        ],\n    },\n    topicIds: {\n        type: 'array',\n        title: '主题ID',\n        description: '主题ID，可以根据主题ID发送消息，可以在主题管理中查看主题ID',\n        required: false,\n    },\n    uids: {\n        type: 'array',\n        title: '用户ID',\n        description: '发送目标的UID，是一个数组。注意uids和topicIds可以同时填写，也可以只填写一个。',\n        required: false,\n    },\n    url: {\n        type: 'string',\n        title: '发送url',\n        description: '发送url，可以不传，如果传了，则根据url弹出通知',\n        required: false,\n    },\n    verifyPayload: {\n        type: 'string',\n        title: '验证负载',\n        description: '仅针对text消息类型有效',\n        required: false,\n    },\n} as const\n\nexport interface WxPusherResponse {\n    /**\n     * 请求是否成功\n     */\n    success: boolean\n    /**\n     * 请求返回码\n     */\n    code: number\n    /**\n     * 请求返回消息\n     */\n    msg: string\n    /**\n     * 请求返回数据\n     */\n    data: {\n        /**\n         * 消息ID\n         */\n        messageId: number\n        /**\n         * 消息编码\n         */\n        code: string\n    }\n}\n\n/**\n * WxPusher 推送。官方文档：https://wxpusher.zjiecode.com/docs\n *\n * @author CaoMeiYouRen\n * @date 2024-11-09\n * @export\n * @class WxPusher\n */\nexport class WxPusher implements Send {\n\n    static readonly namespace = 'WxPusher'\n    static readonly configSchema = wxPusherConfigSchema\n    static readonly optionSchema = wxPusherOptionSchema\n\n    private WX_PUSHER_APP_TOKEN: string\n    private WX_PUSHER_UID: string\n\n    constructor(config: WxPusherConfig) {\n        const { WX_PUSHER_APP_TOKEN, WX_PUSHER_UID } = config\n        this.WX_PUSHER_APP_TOKEN = WX_PUSHER_APP_TOKEN\n        this.WX_PUSHER_UID = WX_PUSHER_UID\n        Debugger('set WX_PUSHER_APP_TOKEN: \"%s\", WX_PUSHER_UID: \"%s\"', WX_PUSHER_APP_TOKEN, WX_PUSHER_UID)\n        // 根据 configSchema 验证 config\n        validate(config, WxPusher.configSchema)\n    }\n\n    async send(title: string, desp?: string, option?: WxPusherOption): Promise<SendResponse<WxPusherResponse>> {\n        Debugger('title: \"%s\", desp: \"%s\", option: %O', title, desp, option)\n        const { contentType = 1, ...args } = option || {}\n        const uids = uniq([...option.uids || [], this.WX_PUSHER_UID])\n        const content = `${title}${desp ? `\\n${desp}` : ''}`\n        return ajax({\n            url: 'https://wxpusher.zjiecode.com/api/send/message',\n            method: 'POST',\n            headers: {\n                'Content-Type': 'application/json',\n            },\n            data: {\n                ...args,\n                appToken: this.WX_PUSHER_APP_TOKEN,\n                content,\n                contentType,\n                uids,\n            },\n        })\n    }\n\n}\n","import { ajax } from './utils/ajax'\nimport { CustomEmail, Dingtalk, Discord, Feishu, IGot, Ntfy, OneBot, PushDeer, PushPlus, Qmsg, ServerChanTurbo, ServerChanV3, Telegram, WechatApp, WechatRobot, XiZhi, WxPusher } from './index'\nimport { SendResponse } from '@/interfaces/response'\n\nexport const PushAllInOne = {\n    CustomEmail,\n    Dingtalk,\n    Discord,\n    Feishu,\n    IGot,\n    Ntfy,\n    OneBot,\n    PushDeer,\n    PushPlus,\n    Qmsg,\n    ServerChanTurbo,\n    ServerChanV3,\n    Telegram,\n    WechatApp,\n    WechatRobot,\n    WxPusher,\n    XiZhi,\n} as const\n\nexport type IPushAllInOne = typeof PushAllInOne\n\nexport type PushType = keyof IPushAllInOne\n\nexport type MetaPushConfig<T extends PushType = PushType> = {\n    type: T\n    config: ConstructorParameters<IPushAllInOne[T]>[0]\n    option: Parameters<IPushAllInOne[T]['prototype']['send']>[2]\n}\n\n/**\n * 从传入变量中读取配置，并选择一个渠道推送\n *\n * @author CaoMeiYouRen\n * @date 2024-11-09\n * @export\n * @template T\n * @param title 推送标题\n * @param desp 推送内容\n * @param pushConfig 推送配置\n */\nexport async function runPushAllInOne<T extends PushType>(title: string, desp: string, pushConfig: MetaPushConfig<T>): Promise<SendResponse<any>> {\n    const { type, config, option } = pushConfig\n    if (PushAllInOne[type]) {\n        const push = new PushAllInOne[type](config as any)\n        return push.send(title, desp, option as any)\n    }\n    throw new Error('未匹配到任何推送方式！')\n}\n\nexport type MetaCloudPushConfig<T extends PushType = PushType> = {\n    type: T\n    config: ConstructorParameters<IPushAllInOne[T]>[0]\n    option: Parameters<IPushAllInOne[T]['prototype']['send']>[2]\n    /**\n     * push-all-in-cloud 服务器地址\n     */\n    baseUrl: string\n    /**\n     * push-all-in-cloud AUTH_FORWARD_KEY 鉴权密钥\n     */\n    authToken: string\n}\n\n/**\n * 调用 push-all-in-cloud 服务进行推送\n *\n * @author CaoMeiYouRen\n * @date 2025-11-06\n * @export\n * @template T\n * @param title 推送标题\n * @param desp 推送内容\n * @param pushConfig 推送配置\n */\nexport async function runPushAllInCloud<T extends PushType>(title: string, desp: string, pushConfig: MetaCloudPushConfig<T>): Promise<SendResponse<any>> {\n    const { type, config, option, baseUrl, authToken } = pushConfig\n\n    const payload = {\n        title,\n        desp,\n        type,\n        config,\n        option,\n    }\n    const url = new URL(baseUrl)\n    url.pathname = '/forward'\n    const response = await ajax({\n        url: url.toString(),\n        method: 'POST',\n        headers: {\n            'Content-Type': 'application/json',\n            Authorization: `Bearer ${authToken}`,\n        },\n        data: payload,\n    })\n\n    if (!response.status || response.status >= 400) {\n        throw new Error(`推送请求失败，状态码：${response.status}`)\n    }\n\n    const data = response.data\n    return data as SendResponse<any>\n}\n"],"mappings":";;;;;;;;;;;;;AAAA,IAAIA;AAEJ,IAAI,WAAW,WAAW,OAAO,WAAW,QAAQ,OAAO,WACvD,KAAI;AAEA,oBAAiB,iBAAiB;QAC9B;AACJ,QAAO,kBAAkB,MAAM,UAAU;AACrC,WAAS,MAAM;GACjB,CAAC,MAAM,QAAQ,MAAM;;AAI/B,SAAgB,KAAK,MAAiB;AAClC,KAAI,OACA,QAAO,OAAO,OAAO,KAAK;AAE9B,SAAQ,KAAK,KAAK;;AAGtB,SAAgB,MAAM,MAAiB;AACnC,KAAI,OACA,QAAO,OAAO,IAAI,KAAK;AAE3B,SAAQ,MAAM,KAAK;;AAGvB,MAAa,SAAS;CAClB;CACA;CACH;;;;;;AAOD,MAAa,aAAa,QAAyB,iBAAiB,KAAK,IAAI;;;;;;AAO7E,MAAa,cAAc,QAAyB,kBAAkB,KAAK,IAAI;;;;;;AAyB/E,SAAgB,QAAQ,OAAyB;AAC7C,QAAO,UAAU,QAAQ,UAAU,UAAa,UAAU;;;;;;;;;;;AAoB9D,SAAgB,KAAQ,KAAe;AACnC,QAAO,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC;;;;;;;;;;;;;;;AC9EnC,SAAgB,SAAqB,QAAW,QAA+B;AAC3E,QAAO,KAAK,OAAO,CAAC,SAAS,QAAQ;EACjC,MAAM,OAAO,OAAO;EACpB,MAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,KAAK,YAAY,QAAQ,MAAM,CAChC;AAEJ,MAAI,KAAK,YAAY,QAAQ,MAAM,CAC/B,OAAM,IAAI,MAAM,IAAI,IAAI,WAAW;AAEvC,MAAI,KAAK,SAAS,UAAU;GACxB,MAAM,EAAE,YAAY;AACpB,OAAI,CAAC,QAAQ,KAAK,MAAM,EAAE,MAAM,CAAC,SAAS,MAAM,CAC5C,OAAM,IAAI,MAAM,IAAI,IAAI,gBAAgB,QAAQ,KAAK,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,GAAG;AAEpF;;AAEJ,MAAI,KAAK,SAAS,UAAU;AACxB,OAAI,OAAO,UAAU,SACjB,OAAM,IAAI,MAAM,IAAI,IAAI,aAAa;AAEzC;;AAEJ,MAAI,KAAK,SAAS,UAAU;AACxB,OAAI,OAAO,UAAU,SACjB,OAAM,IAAI,MAAM,IAAI,IAAI,YAAY;AAExC;;AAEJ,MAAI,KAAK,SAAS,WAAW;AACzB,OAAI,OAAO,UAAU,UACjB,OAAM,IAAI,MAAM,IAAI,IAAI,aAAa;AAEzC;;AAEJ,MAAI,KAAK,SAAS,SAAS;AACvB,OAAI,CAAC,MAAM,QAAQ,MAAM,CACrB,OAAM,IAAI,MAAM,IAAI,IAAI,YAAY;AAExC;;AAEJ,MAAI,KAAK,SAAS,UAAU;AACxB,OAAI,OAAO,UAAU,SACjB,OAAM,IAAI,MAAM,IAAI,IAAI,YAAY;AAExC;;AAEJ,QAAM,IAAI,MAAM,IAAI,IAAI,YAAY;GACtC;;;;;ACpDN,MAAMC,cAAW,MAAM,oBAAoB;AAgC3C,MAAaC,0BAAmD;CAC5D,YAAY;EACR,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACT,SAAS,CACL;GACI,OAAO;GACP,OAAO;GACV,EACD;GACI,OAAO;GACP,OAAO;GACV,CACJ;EACJ;CACD,kBAAkB;EACd,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,iBAAiB;EACb,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,iBAAiB;EACb,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,YAAY;EACR,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,YAAY;EACR,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACJ;AAcD,MAAaC,0BAAmD;CAC5D,IAAI;EACA,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,SAAS;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACJ;;;;;;;;;AAUD,IAAa,cAAb,MAAa,YAA4B;CAGrC,OAAgB,YAAY;CAE5B,OAAgB,eAAe;CAE/B,OAAgB,eAAe;CAE/B,AAAQ;CAER,AAAQ;CAER,YAAY,QAA2B;AACnC,OAAK,SAAS;AACd,cAAS,yBAAyB,OAAO;AAEzC,WAAS,QAAQ,YAAY,aAAa;EAC1C,MAAM,EAAE,iBAAiB,iBAAiB,YAAY,eAAe,KAAK;AAC1E,OAAK,cAAc,WAAW,gBAAgB;GAC1C,MAAM;GACN,MAAM,OAAO,WAAW;GACxB,MAAM;IACF,MAAM;IACN,MAAM;IACT;GACJ,CAAC;;;;;;;;CASN,CAAC,OAAO,WAAiB;AACrB,MAAI,KAAK,YACL,MAAK,YAAY,OAAO;;;;;;;;;;CAYhC,MAAM,KAAK,OAAe,MAAe,QAAkF;AACvH,cAAS,2CAAuC,OAAO,MAAM,OAAO;EACpE,MAAM,EAAE,YAAY,kBAAkB,oBAAoB,KAAK;AAC/D,MAAI,CAAC,MAAM,KAAK,YAAY,QAAQ,CAChC,OAAM,IAAI,MAAM,eAAe;EAEnC,MAAM,EAAE,IAAI,KAAK,GAAG,SAAS,UAAU,EAAE;EACzC,MAAM,OAAO;EACb,MAAM,KAAK,OAAO;EAClB,MAAM,OAAO;EACb,MAAM,WAAW,MAAM,KAAK,YAAY,SAAS;GAC7C;GACA;GACA,SAAS;IACR,OAAO;GACR,GAAG;GACN,CAAC;AACF,MAAI,OAAO,OAAO,YAAY,YAC1B,MAAK,YAAY,OAAO;AAE5B,cAAS,4BAA4B,SAAS;AAC9C,MAAI,SAAS,UAAU,SAAS,SAAS,CACrC,QAAO;GACH,QAAQ;GACR,YAAY;GACZ,MAAM;GACN,SAAS,EAAE;GACd;AAEL,SAAO;GACH,QAAQ;GACR,YAAY;GACZ,MAAM;GACN,SAAS,EAAE;GACd;;;;;;ACvOT,MAAMC,cAAW,MAAM,YAAY;;;;;;;;;;AAqBnC,eAAsB,KAAc,QAA+C;AAC/E,KAAI;AACA,cAAS,mBAAmB,OAAO;EACnC,MAAM,EAAE,KAAK,QAAQ,EAAE,EAAE,SAAS,OAAO,UAAU,IAAI,aAAa;EACpE,MAAM,UAAW,OAAO,WAAW,EAAE;EACrC,IAAI,EAAE,OAAO,EAAE,KAAK;AAEpB,MAAI,QAAQ,oBAAoB,uCAAuC,OAAO,SAAS,SACnF,QAAO,IAAI,gBAAgB,KAA+B,CAAC,UAAU;EAGzE,IAAI,YAAY;AAChB,cAAS,gBAAgB,QAAQ,IAAI,SAAS;AAC9C,MAAI,QAAQ,IAAI,aAAa,QAAQ;AACjC,eAAS,kBAAkB,QAAQ,IAAI,WAAW;AAClD,eAAS,mBAAmB,QAAQ,IAAI,YAAY;AACpD,eAAS,mBAAmB,QAAQ,IAAI,YAAY;AACpD,OAAI,UAAU,SAAS,CACnB,aAAY,IAAI,gBAAgB,SAAS;YAClC,WAAW,SAAS,CAC3B,aAAY,IAAI,gBAAgB,SAAS;YAClC,QAAQ,IAAI,YACnB,aAAY,IAAI,gBAAgB,QAAQ,IAAI,YAAY;YACjD,QAAQ,IAAI,WACnB,aAAY,IAAI,gBAAgB,QAAQ,IAAI,WAAW;YAChD,QAAQ,IAAI,YACnB,aAAY,IAAI,gBAAgB,QAAQ,IAAI,YAAY;;EAGhE,MAAM,WAAW,MAAM,MAAM,KAAK;GAC9B;GACA;GACA;GACA,QAAQ;GACR;GACA,SAAS;GACT;GACA,YAAY;GACZ,OAAO;GACV,CAAC;AACF,cAAS,qBAAqB,SAAS,KAAK;AAC5C,SAAO;UACFC,SAAO;AACZ,MAAIA,SAAO,UAAU;AACjB,UAAO,MAAMA,QAAM,SAAS;AAC5B,UAAOA,QAAM;;AAEjB,QAAMA;;;;;;;;;;;;;;;;AC9Dd,SAAgB,kBAAkB,WAA4B,aAAqB,aAA2D;CAE1I,MAAM,eAAe,GAAG,UAAU,IAAI;CAGtC,MAAM,OAAO,OAAO,WAAW,UAAU,YAAY;AAGrD,MAAK,OAAO,cAAc,OAAO;AAKjC,QAFkB,KAAK,OAAO,SAAS;;AAK3C,SAAgB,aAAa,KAAqB;AAC9C,QAAO,OAAO,KAAK,IAAI,CAAC,SAAS,SAAS;;AAG9C,SAAgB,cAAc,KAAqB;AAC/C,QAAO,aAAa,aAAa,IAAI,CAAC;;;;;AClB1C,MAAMC,cAAW,MAAM,gBAAgB;AAiBvC,MAAaC,uBAA6C;CACtD,uBAAuB;EACnB,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,iBAAiB;EACb,MAAM;EACN,OAAO;EACP,UAAU;EACV,SAAS;EACZ;CACJ;AAyBD,MAAaC,uBAA6C;CACtD,SAAS;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACT,SAAS;GACL;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACJ;EACJ;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,EAAE;EACd;CACD,UAAU;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,EAAE;EACd;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,EAAE;EACd;CACD,YAAY;EACR,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,EAAE;EACd;CACD,UAAU;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,EAAE;EACd;CACJ;;;;;;;;;AAeD,IAAa,WAAb,MAAa,SAAyB;CAElC,OAAgB,YAAY;CAE5B,OAAgB,eAAe;CAE/B,OAAgB,eAAe;CAE/B,AAAQ;;;;;;CAMR,AAAQ;CACR,AAAQ,UAAkB;;;;;;;CAQ1B,YAAY,QAAwB;EAChC,MAAM,EAAE,uBAAuB,oBAAoB;AACnD,OAAK,eAAe;AACpB,OAAK,SAAS;AACd,cAAS,mDAAmD,KAAK,cAAc,KAAK,OAAO;AAE3F,WAAS,QAAQ,SAAS,aAAa;AACvC,MAAI,CAAC,KAAK,OACN,MAAK,wBAAwB;;CAIrC,AAAQ,QAAQ,WAA2B;EACvC,IAAI,UAAU;AACd,MAAI,KAAK,QAAQ;AACb,aAAU,kBAAkB,WAAW,KAAK,QAAQ,KAAK,OAAO;AAChE,eAAS,mCAAmC,GAAG,UAAU,IAAI,KAAK,UAAU,QAAQ;;AAExF,SAAO;;CAGX,MAAc,KAAK,MAAgE;EAC/E,MAAM,YAAY,KAAK,KAAK;EAC5B,MAAM,OAAO,KAAK,QAAQ,UAAU;EACpC,MAAM,SAAS,MAAM,KAAK;GACtB,KAAK,KAAK;GACV,QAAQ;GACR,SAAS,EACL,gBAAgB,oBACnB;GACD,OAAO;IACH;IACA;IACA,cAAc,KAAK;IACtB;GACD;GACH,CAAC;AACF,cAAS,qBAAqB,OAAO,KAAK,SAAS,OAAO,KAAK,OAAO;AACtE,MAAI,OAAO,KAAK,YAAY,MAAQ;AAChC,WAAQ,MAAM,gBAAgB,OAAO,KAAK;AAC1C,eAAS,iCAAiC,OAAO,KAAK;;AAE1D,SAAO;;;;;;;;;;;CAYX,MAAM,KAAK,OAAe,MAAe,QAAkE;AACvG,cAAS,2CAAuC,OAAO,MAAM,OAAO;AACpE,UAAQ,OAAO,SAAf;GACI,KAAK,OACD,QAAO,KAAK,KAAK;IACb,SAAS;IACT,MAAM,EACF,SAAS,GAAG,QAAQ,OAAO,KAAK,SAAS,MAC5C;IACD,GAAG;IACN,CAAC;GACN,KAAK,WACD,QAAO,KAAK,KAAK;IACb,SAAS;IACT,UAAU;KACN;KACA,MAAM,KAAK,QAAQ,OAAO,OAAO,SAAS;KAC7C;IACD,GAAG;IACN,CAAC;GACN,KAAK,OACD,QAAO,KAAK,KAAK;IACb,SAAS;IACT,MAAM;KACF;KACA,MAAM,QAAQ;KACd,QAAQ,QAAQ,MAAM,UAAU;KAChC,YAAY,OAAO,MAAM,cAAc;KAC1C;IACD,GAAG;IACN,CAAC;GACN,KAAK,aACD,QAAO,KAAK,KAAK;IACb,SAAS;IACT,YAAY;KACR;KACA,MAAM,QAAQ;KACd,gBAAgB,QAAQ,YAAY,kBAAkB;KACtD,OAAO,QAAQ,aAAoB;KACnC,cAAc,QAAQ,aAAoB;KAC1C,YAAY,QAAQ,aAAoB;KAC3C;IACD,GAAG;IACN,CAAC;GACN,KAAK,WACD,QAAO,KAAK,KAAK;IACb,SAAS;IACT,UAAU,EACN,OAAO,QAAQ,UAAU,SAAS,EAAE,EACvC;IACD,GAAG;IACN,CAAC;GACN,QACI,OAAM,IAAI,MAAM,uBAAuB;;;;;;;AClRvD,MAAMC,cAAW,MAAM,eAAe;AAgBtC,MAAaC,sBAA2C;CACpD,iBAAiB;EACb,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,WAAW;EACP,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;AAqBD,MAAaC,sBAA2C;CACpD,UAAU;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,YAAY;EACR,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;;;;;;;;;AAYD,IAAa,UAAb,MAAa,QAAwB;CAEjC,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;;;;;;;;CAS/B,AAAQ;CAER;;;;;;;CAQA,YAAY,QAAuB;EAC/B,MAAM,EAAE,iBAAiB,cAAc;AACvC,cAAS,sCAAsC,iBAAiB,UAAU;AAC1E,OAAK,kBAAkB;AACvB,MAAI,UACA,MAAK,WAAW;AAGpB,WAAS,QAAQ,QAAQ,aAAa;;;;;;;;;;;CAY1C,MAAM,KAAK,OAAe,MAAe,QAAgE;AACrG,cAAS,2CAAuC,OAAO,MAAM,OAAO;EACpE,MAAM,EAAE,UAAU,YAAY,GAAG,SAAS,UAAU,EAAE;EACtD,MAAM,WAAW,KAAK;EACtB,MAAM,UAAU,GAAG,QAAQ,OAAO,KAAK,SAAS;AAChD,SAAO,KAAK;GACR,KAAK,KAAK;GACV,QAAQ;GACR;GACA,MAAM;IACF;IACA;IACA;IACA,GAAG;IACN;GACJ,CAAC;;;;;;ACrIV,MAAMC,cAAW,MAAM,cAAc;AAerC,MAAaC,qBAAyC;CAClD,eAAe;EACX,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,mBAAmB;EACf,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACJ;AAiBD,MAAaC,qBAAyC;CAClD,iBAAiB;EACb,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;GACL;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACJ;EACJ;CACD,YAAY;EACR,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,UAAU;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;GACL;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACJ;EACJ;CACD,SAAS;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;;;;;;;;;AAUD,IAAa,SAAb,MAAa,OAAuB;CAEhC,OAAgB,YAAY;CAE5B,OAAgB,eAAe;CAE/B,OAAgB,eAAe;CAE/B,AAAiB;;;;CAKjB,AAAQ;CAER,AAAQ;CAER,YAAY,QAAsB;AAC9B,OAAK,SAAS;AAEd,WAAS,QAAQ,OAAO,aAAa;;CAGzC,MAAc,iBAAiB;EAC3B,MAAM,EAAE,eAAe,sBAAsB,KAAK;EAClD,MAAM,MAAM;EACZ,MAAM,OAAO;GACT,QAAQ;GACR,YAAY;GACf;EASD,MAAM,EAAE,MAAM,KAAK,qBAAqB,YARzB,MAAM,KAAK;GACtB;GACA,QAAQ;GACR,SAAS,EACL,gBAAgB,mCACnB;GACD;GACH,CAAC,EACwD;AAC1D,MAAI,SAAS,EACT,OAAM,IAAI,MAAM,OAAO,6BAA6B;AAExD,OAAK,cAAc,KAAK,KAAK,GAAG,SAAS;AACzC,cAAS,iCAAiC,oBAAoB;AAC9D,SAAO;;CAGX,MAAM,KAAK,OAAe,MAAe,QAA8C;AACnF,cAAS,2CAAuC,OAAO,MAAM,OAAO;AACpE,MAAI,CAAC,KAAK,eAAe,KAAK,KAAK,IAAI,KAAK,YACxC,MAAK,cAAc,MAAM,KAAK,gBAAgB;EAElD,MAAM,EAAE,kBAAkB,WAAW,YAAY,WAAW,QAAQ,SAAS,SAAS;EACtF,MAAM,OAAO;GAAE;GAAY;GAAU;GAAS;GAAM;AACpD,MAAI,CAAC,KAAK,QACN,SAAQ,UAAR;GACI,KAAK;AACD,SAAK,UAAU,KAAK,UAAU,EAC1B,MAAM,GAAG,QAAQ,OAAO,KAAK,SAAS,MACzC,CAAC;AACF;GACJ,KAAK;AACD,SAAK,UAAU,KAAK,UAAU,EAC1B,MAAM,EACF,OAAO;KACH;KACA,SAAS,CACL,CACI;MACI,KAAK;MACL,MAAM;MACT,CACJ,CACJ;KACJ,EACJ,EACJ,CAAC;AACF;GACJ,QACI,OAAM,IAAI,MAAM,wBAAwB;;AAepD,SAZe,MAAM,KAAK;GACtB,KAAK;GACL,QAAQ;GACR,SAAS;IACL,gBAAgB;IAChB,eAAe,UAAU,KAAK;IACjC;GACD;GACA,OAAO,EACH,iBAAiB,mBAAmB,WACvC;GACJ,CAAC;;;;;;ACzPV,MAAMC,cAAW,MAAM,aAAa;AAWpC,MAAaC,mBAAqC,EAC9C,WAAW;CACP,MAAM;CACN,OAAO;CACP,aAAa;CACb,UAAU;CACV,SAAS;CACZ,EACJ;AA4BD,MAAaC,mBAAqC;CAC9C,KAAK;EACD,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,mBAAmB;EACf,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,QAAQ;EACJ,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,OAAO;EACH,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACJ;;;;;;;;;AA8BD,IAAa,OAAb,MAAa,KAAqB;CAE9B,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;;;;;;CAM/B,AAAQ;;;;;;CAMR,YAAY,QAAoB;EAC5B,MAAM,EAAE,cAAc;AACtB,OAAK,YAAY;AACjB,cAAS,yBAAuB,UAAU;AAE1C,WAAS,QAAQ,KAAK,aAAa;;;;;;;;;;;;CAavC,KAAK,OAAe,MAAe,QAA0D;AACzF,cAAS,+CAAyC,OAAO,MAAM,OAAO;AACtE,SAAO,KAAK;GACR,KAAK,2BAA2B,KAAK;GACrC,QAAQ;GACR,SAAS,EACL,gBAAgB,oBACnB;GACD,MAAM;IACF;IACA,SAAS,QAAQ;IACjB,mBAAmB;IACnB,GAAG;IACN;GACJ,CAAC;;;;;;AChKV,MAAMC,cAAW,MAAM,YAAY;AA0BnC,MAAaC,mBAAqC;CAC9C,UAAU;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,YAAY;EACR,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,WAAW;EACP,MAAM;EACN,OAAO;EACP,aAAa;EAGb,UAAU;EACV,SAAS;EACZ;CACJ;AAmFD,MAAaC,mBAAqC;CAC9C,OAAO;EACH,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,UAAU;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,UAAU;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,OAAO;EACH,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,OAAO;EACH,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,QAAQ;EACJ,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,UAAU;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,SAAS;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,OAAO;EACH,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,UAAU;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,aAAa;EACT,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,OAAO;EACH,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,aAAa;EACT,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;;;;;;;;;;AAsCD,IAAa,OAAb,MAAa,KAAqB;CAE9B,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;;;;CAI/B,AAAQ;;;;;;;CAOR,AAAQ;;;;;;;CAQR,AAAQ;CAER,YAAY,QAAoB;EAC5B,MAAM,EAAE,UAAU,WAAW,eAAe;AAC5C,OAAK,WAAW;AAChB,OAAK,aAAa;AAClB,OAAK,YAAY;AACjB,cAAS,+DAAyD,UAAU,YAAY,UAAU;AAElG,WAAS,QAAQ,KAAK,aAAa;;CAGvC,MAAM,KAAK,OAAe,MAAc,QAA0D;AAC9F,cAAS,kBAAgB,OAAO;EAChC,MAAM,EAAE,SAAS,MAAM,UAAU,MAAM,UAAU,OAAO,OAAO,QAAQ,UAAU,MAAM,SAAS,OAAO,UAAU,aAAa,OAAO,MAAM,aAAa,SAAS,UAAU,EAAE;EAC7K,MAAMC,UAAe,EAAE;AACvB,MAAI,KAAK,UACL,SAAQ,mBAAmB,KAAK;AAEpC,MAAI,YACA,SAAQ,kBAAkB;EAE9B,MAAM,SAAS,SAAS,OAAO;AAC/B,MAAI,OACA,SAAQ,aAAa,cAAc,OAAO;AAE9C,MAAI,QACA,SAAQ,eAAe,cAAc,QAAQ;AAEjD,MAAI,SACA,SAAQ,gBAAgB,SAAS,UAAU;AAE/C,MAAI,KACA,SAAQ,YAAY;AAExB,MAAI,SACA,SAAQ,gBAAgB,SAAS,UAAU;AAE/C,MAAI,MACA,SAAQ,aAAa;AAEzB,MAAI,MACA,SAAQ,aAAa;AAEzB,MAAI,OACA,SAAQ,cAAc;AAE1B,MAAI,SACA,SAAQ,gBAAgB;AAE5B,MAAI,KACA,SAAQ,YAAY;AAExB,MAAI,QACA,SAAQ,eAAe;AAE3B,MAAI,MACA,SAAQ,aAAa,QAAQ,QAAQ;AAEzC,MAAI,SACA,SAAQ,gBAAgB,WAAW,QAAQ;AAE/C,MAAI,YACA,SAAQ,mBAAmB,cAAc,MAAM;AAEnD,MAAI,MACA,SAAQ,aAAa;AAEzB,MAAI,KACA,SAAQ,YAAY;AAExB,MAAI,MAAM;AACN,WAAQ,gBAAgB,KAAK;AAC7B,WAAQ,kBAAkB;AAC1B,WAAQ,oBAAoB,KAAK;AACjC,WAAQ,yBAAyB,yBAAyB,KAAK,KAAK;;AAExE,cAAS,mBAAiB,QAAQ;EAClC,MAAM,OAAO,QAAQ,QAAQ;AAC7B,cAAS,gBAAc,KAAK;AAQ5B,SANiB,MAAM,KAAK;GACxB,KAFQ,IAAI,IAAI,KAAK,YAAY,KAAK,SAAS,CAAC,UAAU;GAG1D,QAAQ;GACR;GACA;GACH,CAAC;;;;;;ACtZV,MAAMC,cAAW,MAAM,eAAe;AAetC,MAAaC,qBAAyC;CAClD,kBAAkB;EACd,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,sBAAsB;EAClB,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;AA6CD,MAAaC,qBAAyC;CAClD,cAAc;EACV,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACT,SAAS,CACL;GACI,OAAO;GACP,OAAO;GACV,EACD;GACI,OAAO;GACP,OAAO;GACV,CACJ;EACJ;CACD,SAAS;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,UAAU;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,aAAa;EACT,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;;;;;;;;;AAuBD,IAAa,SAAb,MAAa,OAAuB;CAEhC,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;;;;;;;;CAS/B,OAAO,UAAU;;;;;;;;;CAUjB,AAAQ;;;;;;;;CAQR,AAAQ;;;;;;;CAQR,YAAY,QAAsB;EAC9B,MAAM,EAAE,kBAAkB,yBAAyB;AACnD,OAAK,mBAAmB;AACxB,OAAK,uBAAuB;AAC5B,cAAS,8DAA0D,kBAAkB,qBAAqB;AAE1G,WAAS,QAAQ,OAAO,aAAa;AACrC,MAAI,CAAC,KAAK,qBACN,MAAK,sDAAsD;;;;;;;;;;;CAanE,MAAM,KAAK,OAAe,MAAc,QAA6D;AACjG,cAAS,+CAAyC,OAAO,MAAM,OAAO;AAGtE,WAAS,QAAQ,OAAO,aAA2C;AACnE,MAAI,OAAO,iBAAiB,aAAa,CAAC,OAAO,QAC7C,OAAM,IAAI,MAAM,4BAA4B;AAEhD,MAAI,OAAO,iBAAiB,WAAW,CAAC,OAAO,SAC3C,OAAM,IAAI,MAAM,6BAA6B;EAEjD,MAAM,EAAE,eAAe,WAAW,GAAG,SAAS,UAAU,EAAE;EAC1D,MAAM,UAAU,GAAG,QAAQ,OAAO,KAAK,SAAS;AAChD,SAAO,KAAqB;GACxB,SAAS,KAAK;GACd,KAAK;GACL,QAAQ;GACR,SAAS;IACL,gBAAgB;IAChB,eAAe,UAAU,KAAK;IACjC;GACD,MAAM;IACF,aAAa;IACb;IACA;IACA,GAAG;IACN;GACJ,CAAC;;;;;;AC5NV,MAAMC,aAAW,MAAM,iBAAiB;AAkBxC,MAAaC,uBAA6C;CACtD,oBAAoB;EAChB,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,oBAAoB;EAChB,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACJ;AAUD,MAAaC,uBAA6C,EACtD,MAAM;CACF,MAAM;CACN,OAAO;CACP,aAAa;CACb,UAAU;CACV,SAAS;CACT,SAAS;EACL;GACI,OAAO;GACP,OAAO;GACV;EACD;GACI,OAAO;GACP,OAAO;GACV;EACD;GACI,OAAO;GACP,OAAO;GACV;EACJ;CACJ,EACJ;;;;;;;;;AA2BD,IAAa,WAAb,MAAa,SAAyB;CAElC,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;;;;;;;;CAS/B,AAAQ;;;;;;;;CASR,AAAQ;;;;;;;CAQR,YAAY,QAAwB;EAChC,MAAM,EAAE,oBAAoB,uBAAuB;AACnD,OAAK,qBAAqB;AAC1B,OAAK,qBAAqB,sBAAsB;AAChD,aAAS,8DAA0D,oBAAoB,mBAAmB;AAE1G,WAAS,QAAQ,SAAS,aAAa;;;;;;;;;CAU3C,MAAM,KAAK,OAAe,OAAe,IAAI,QAAkE;AAC3G,aAAS,+CAAyC,OAAO,MAAM,OAAO;EACtE,MAAM,EAAE,OAAO,eAAe,UAAU,EAAE;AAC1C,SAAO,KAAK;GACR,SAAS,KAAK;GACd,KAAK;GACL,QAAQ;GACR,SAAS,EACL,gBAAgB,qCACnB;GACD,MAAM;IACF,MAAM;IACN;IACA,SAAS,KAAK;IACd;IACH;GACJ,CAAC;;;;;;ACzJV,MAAMC,aAAW,MAAM,iBAAiB;AA4BxC,MAAaC,uBAA6C,EACtD,iBAAiB;CACb,MAAM;CACN,OAAO;CACP,aAAa;CACb,UAAU;CACb,EACJ;AA+BD,MAAaC,uBAA6C;CACtD,UAAU;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACT,SAAS;GACL;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACJ;EACJ;CACD,SAAS;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACT,SAAS;GACL;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACJ;EACJ;CACD,OAAO;EACH,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,SAAS;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,aAAa;EACT,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,WAAW;EACP,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EAEb;CACJ;;;;;;;;;AAiBD,IAAa,WAAb,MAAa,SAAyB;CAElC,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;;;;;;CAM/B,AAAQ;;;;;;;CAQR,YAAY,QAAwB;EAChC,MAAM,EAAE,oBAAoB;AAC5B,OAAK,kBAAkB;AACvB,aAAS,+BAA6B,gBAAgB;AAEtD,WAAS,QAAQ,SAAS,aAAa;;;;;;;;;;;CAY3C,KAAK,OAAe,OAAe,IAAI,QAAkE;AACrG,aAAS,+CAAyC,OAAO,MAAM,OAAO;EACtE,MAAM,EAAE,WAAW,QAAQ,UAAU,UAAU,GAAG,SAAS,UAAU,EAAE;EACvE,MAAM,UAAU,QAAQ;AACxB,SAAO,KAAK;GACR,KAAK;GACL,QAAQ;GACR,SAAS,EACL,gBAAgB,oBACnB;GACD,MAAM;IACF,OAAO,KAAK;IACZ;IACA,SAAS,WAAW;IACpB;IACA;IACA,GAAG;IACN;GACJ,CAAC;;;;;;ACvOV,MAAMC,aAAW,MAAM,YAAY;AAenC,MAAaC,mBAAqC,EAC9C,UAAU;CACN,MAAM;CACN,OAAO;CACP,aAAa;CACb,UAAU;CACb,EACJ;AAyCD,MAAaC,mBAAqC;CAC9C,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACT,SAAS,CACL;GACI,OAAO;GACP,OAAO;GACV,EACD;GACI,OAAO;GACP,OAAO;GACV,CACJ;EACJ;CACD,IAAI;EACA,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,KAAK;EACD,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;;;;;;;;;AA0BD,IAAa,OAAb,MAAa,KAAqB;CAE9B,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;CAE/B,AAAQ;CAER,YAAY,QAAoB;EAC5B,MAAM,EAAE,aAAa;AACrB,OAAK,WAAW;AAChB,aAAS,wBAAsB,SAAS;AAExC,WAAS,QAAQ,KAAK,aAAa;;;;;;;;;;;CAYvC,MAAM,KAAK,OAAe,MAAc,QAAyD;AAC7F,aAAS,+CAAyC,OAAO,MAAM,OAAO;AAGtE,WAAS,QAAQ,KAAK,aAAa;EACnC,MAAM,EAAE,IAAI,OAAO,QAAQ,QAAQ,UAAU,EAAE;EAC/C,MAAM,MAAM,GAAG,QAAQ,OAAO,KAAK,SAAS;AAC5C,SAAO,KAAK;GACR,KAAK,0BAA0B,KAAK,GAAG,KAAK;GAC5C,SAAS,EACL,gBAAgB,qCACnB;GACD,QAAQ;GACR,MAAM;IAAE;IAAK;IAAI;IAAK;GACzB,CAAC;;;;;;AC9JV,MAAMC,aAAW,MAAM,yBAAyB;AAehD,MAAaC,8BAA2D,EACpE,2BAA2B;CACvB,MAAM;CACN,OAAO;CACP,aAAa;CACb,UAAU;CACb,EACJ;AAyCD,MAAaC,8BAA2D;CACpE,OAAO;EACH,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,SAAS;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,QAAQ;EACJ,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;;;;;;;;;;AAyBD,IAAa,kBAAb,MAAa,gBAAgC;CAEzC,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;;;;;;;CAQ/B,YAAY,QAA+B;EACvC,MAAM,EAAE,8BAA8B;AACtC,OAAK,SAAS;AACd,aAAS,sBAAoB,KAAK,OAAO;AAEzC,WAAS,QAAQ,gBAAgB,aAAa;;;;;;;CAQlD,AAAQ;;;;;;;;;;CAWR,MAAM,KAAK,OAAe,OAAe,IAAI,SAAgC,EAAE,EAAkD;AAC7H,aAAS,2CAAuC,OAAO,MAAM,OAAO;AACpE,MAAI,OAAO,SAAS,KAAK,OAAO,SAAS,KACrC,QAAO,OAAO;EAElB,MAAM,OAAO;GACT,MAAM;GACN;GACA,GAAG;GACN;AACD,SAAO,KAAK;GACR,KAAK,2BAA2B,KAAK,OAAO;GAC5C,QAAQ;GACR,SAAS,EACL,gBAAgB,qCACnB;GACD;GACH,CAAC;;;;;;ACtKV,MAAMC,aAAW,MAAM,sBAAsB;AAU7C,MAAaC,2BAAqD,EAC9D,wBAAwB;CACpB,MAAM;CACN,OAAO;CACP,aAAa;CACb,UAAU;CACb,EACJ;AAcD,MAAaC,2BAAqD;CAC9D,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,OAAO;EACH,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;;;;;;;;;AAyBD,IAAa,eAAb,MAAa,aAA6B;CAEtC,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;;;;;;;;CAS/B,AAAQ;CAER,AAAQ,MAAc;;;;;;;CAQtB,YAAY,QAA4B;EACpC,MAAM,EAAE,2BAA2B;EACnC,MAAM,UAAU;AAChB,OAAK,UAAU;AACf,aAAS,uBAAqB,QAAQ;AAEtC,WAAS,QAAQ,aAAa,aAAa;AAC3C,OAAK,MAAM,KAAK,QAAQ,MAAM,cAAc,GAAG;AAC/C,MAAI,CAAC,KAAK,IACN,OAAM,IAAI,MAAM,8BAA8B;;;;;;;;;;;CAatD,MAAM,KAAK,OAAe,OAAe,IAAI,SAA6B,EAAE,EAA+C;AACvH,aAAS,2CAAuC,OAAO,MAAM,OAAO;AACpE,MAAI,MAAM,QAAQ,OAAO,KAAK,CAC1B,QAAO,OAAO,OAAO,KAAK,KAAK,IAAI;EAEvC,MAAM,OAAO;GACT,MAAM;GACN;GACA,GAAG;GACN;AACD,SAAO,KAAK;GACR,KAAK,WAAW,KAAK,IAAI,sBAAsB,KAAK,QAAQ;GAC5D,QAAQ;GACR,SAAS,EACL,gBAAgB,oBACnB;GACD;GACH,CAAC;;;;;;ACnIV,MAAMC,aAAW,MAAM,gBAAgB;AAwBvC,MAAaC,uBAA6C;CACtD,oBAAoB;EAChB,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,kBAAkB;EACd,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,WAAW;EACP,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;AAqCD,MAAaC,uBAA6C;CACtD,sBAAsB;EAClB,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,iBAAiB;EACb,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,mBAAmB;EACf,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,YAAY;EACR,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,CAAC;GAAE,OAAO;GAAc,OAAO;GAAc,EAAE;GAAE,OAAO;GAAQ,OAAO;GAAQ,CAAC;EAC5F;CACJ;;;;;;;;;;AAoCD,IAAa,WAAb,MAAa,SAAyB;CAElC,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;;;;;;;;CAS/B,AAAQ;;;;;;;;CAQR,AAAQ;CAER;CAEA,YAAY,QAAwB;AAChC,aAAS,cAAc,OAAO;AAC9B,SAAO,OAAO,MAAM,OAAO;AAE3B,WAAS,QAAQ,SAAS,aAAa;AACvC,MAAI,OAAO,UACP,MAAK,WAAW,OAAO;;;;;;;;;;;CAa/B,MAAM,KAAK,OAAe,MAAe,QAAkE;EACvG,MAAM,MAAM,+BAA+B,KAAK,mBAAmB;AACnE,aAAS,2CAAuC,OAAO,MAAM,OAAO;EACpE,MAAM,OAAO,GAAG,QAAQ,OAAO,KAAK,SAAS;AAC7C,SAAO,KAAuB;GAC1B;GACA,QAAQ;GACR,UAAU,KAAK;GACf,MAAM;IACF,SAAS,KAAK;IACd;IACH;GACJ,CAAC;;;;;;ACrMV,MAAMC,aAAW,MAAM,kBAAkB;AAsBzC,MAAaC,wBAA+C;CACxD,mBAAmB;EACf,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,mBAAmB;EACf,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACD,oBAAoB;EAChB,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACZ;CACJ;AA4BD,MAAaC,wBAA+C;CACxD,SAAS;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;GACL;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACJ;EACJ;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,CACL;GACI,OAAO;GACP,OAAO;GACV,EACD;GACI,OAAO;GACP,OAAO;GACV,CACJ;EACJ;CACD,iBAAiB;EACb,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,CACL;GACI,OAAO;GACP,OAAO;GACV,EACD;GACI,OAAO;GACP,OAAO;GACV,CACJ;EACJ;CACD,wBAAwB;EACpB,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS,CACL;GACI,OAAO;GACP,OAAO;GACV,EACD;GACI,OAAO;GACP,OAAO;GACV,CACJ;EACJ;CACD,0BAA0B;EACtB,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,QAAQ;EACJ,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,SAAS;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,OAAO;EACH,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;;;;;;;;;AAqBD,IAAa,YAAb,MAAa,UAA0B;CAEnC,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;CAE/B,AAAQ;CAER,AAAQ;CACR,AAAQ;CACR,AAAQ;;;;;;CAOR,AAAQ;CAER,YAAY,QAAyB;AACjC,aAAS,cAAc,OAAO;AAC9B,SAAO,OAAO,MAAM,OAAO;AAE3B,WAAS,QAAQ,UAAU,aAAa;;CAG5C,MAAc,iBAAkC;EAC5C,MAAM,EAAE,SAAS,MAAM,KAAK;GACxB,KAAK;GACL,OAAO;IACH,QAAQ,KAAK;IACb,YAAY,KAAK;IACpB;GACJ,CAAC;AACF,MAAI,MAAM,YAAY,EAClB,OAAM,IAAI,MAAM,MAAM,UAAU,sBAAsB;EAE1D,MAAM,EAAE,cAAc,aAAa,SAAS;AAC5C,aAAS,0BAA0B,aAAa;AAChD,OAAK,kBAAkB,WAAW;AAClC,SAAO;;;;;;;;;;CAWX,AAAQ,kBAAkB,WAAyB;AAC/C,OAAK,cAAc,KAAK,KAAK,GAAG,YAAY;;;;;;;;;;;CAYhD,MAAM,KAAK,OAAe,MAAe,QAAoE;AACzG,aAAS,2CAAuC,OAAO,MAAM,OAAO;AACpE,MAAI,CAAC,KAAK,gBAAgB,KAAK,KAAK,IAAI,KAAK,YACzC,MAAK,eAAe,MAAM,KAAK,gBAAgB;EAEnD,MAAM,EAAE,UAAU,QAAQ,QAAQ,SAAS,GAAG,SAAS,UAAU,EAAE;AACnE,MAAI,CAAC,QACD,MAAK,kCAAgC;EAGzC,MAAM,UAAU,GAAG,QAAQ,OAAO,GADtB,YAAY,aAAa,SAAS,OACH,SAAS;EACpD,MAAM,SAAS,WAAW;AAC1B,SAAO,KAAK;GACR,KAAK;GACL,QAAQ;GACR,SAAS,EACL,gBAAgB,oBACnB;GACD,OAAO,EACH,cAAc,KAAK,cACtB;GACD,MAAM;IACF;IACA;IACA,SAAS,KAAK;KACb,UAAU,EACP,SACH;IACD,GAAG;IACN;GACJ,CAAC;;;;;;ACjTV,MAAMC,aAAW,MAAM,oBAAoB;AAS3C,MAAaC,0BAAmD,EAC5D,kBAAkB;CACd,MAAM;CACN,OAAO;CACP,aAAa;CACb,UAAU;CACb,EACJ;AAOD,MAAaC,0BAAmD,EAC5D,SAAS;CACL,MAAM;CACN,OAAO;CACP,aAAa;CACb,SAAS;EACL;GACI,OAAO;GACP,OAAO;GACV;EACD;GACI,OAAO;GACP,OAAO;GACV;EACD;GACI,OAAO;GACP,OAAO;GACV;EACD;GACI,OAAO;GACP,OAAO;GACV;EACD;GACI,OAAO;GACP,OAAO;GACV;EACD;GACI,OAAO;GACP,OAAO;GACV;EACD;GACI,OAAO;GACP,OAAO;GACV;EACJ;CACD,UAAU;CACV,SAAS;CACZ,EACJ;;;;;;;;;AAgBD,IAAa,cAAb,MAAa,YAA4B;CAErC,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;CAE/B,AAAQ;CAER,YAAY,QAA2B;EACnC,MAAM,EAAE,qBAAqB;AAC7B,OAAK,mBAAmB;AACxB,aAAS,gCAA8B,iBAAiB;AAExD,WAAS,QAAQ,YAAY,aAAa;;;;;;;;;;;CAY9C,MAAM,KAAK,OAAe,MAAe,QAAwE;AAC7G,aAAS,2CAAuC,OAAO,MAAM,OAAO;EACpE,MAAM,EAAE,UAAU,QAAQ,GAAG,SAAS,UAAU,EAAE;EAElD,MAAM,UAAU,GAAG,QAAQ,OAAO,GADtB,YAAY,aAAa,SAAS,OACH,SAAS;AACpD,SAAO,KAAK;GACR,KAAK;GACL,SAAS,EACL,gBAAgB,oBACnB;GACD,QAAQ;GACR,OAAO,EAAE,KAAK,KAAK,kBAAkB;GACrC,MAAM;IACF;KACC,UAAU,EAAE,SAAS;IACtB,GAAG;IACN;GACJ,CAAC;;;;;;ACvHV,MAAMC,aAAW,MAAM,cAAc;AAQrC,MAAaC,oBAAuC,EAChD,YAAY;CACR,MAAM;CACN,OAAO;CACP,aAAa;CACb,UAAU;CACb,EACJ;AAMD,MAAaC,oBAAuC,EACnD;;;;;;;;;AAgBD,IAAa,QAAb,MAAa,MAAsB;CAE/B,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;CAE/B,AAAQ;CAER,YAAY,QAAqB;EAC7B,MAAM,EAAE,eAAe;AACvB,OAAK,aAAa;AAClB,aAAS,0BAAwB,WAAW;AAE5C,WAAS,QAAQ,MAAM,aAAa;;CAGxC,MAAM,KAAK,OAAe,MAAe,QAA4D;AACjG,aAAS,+BAA2B,OAAO,KAAK;AAChD,SAAO,KAAK;GACR,KAAK,0BAA0B,KAAK,WAAW;GAC/C,QAAQ;GACR,SAAS,EACL,gBAAgB,oBACnB;GACD,MAAM;IACF;IACA,SAAS;IACZ;GACJ,CAAC;;;;;;ACjEV,MAAM,WAAW,MAAM,iBAAiB;AAexC,MAAaC,uBAA6C;CACtD,qBAAqB;EACjB,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,eAAe;EACX,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;AAqCD,MAAaC,uBAA6C;CACtD,SAAS;EACL,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,aAAa;EACT,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACT,SAAS;GACL;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACD;IACI,OAAO;IACP,OAAO;IACV;GACJ;EACJ;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,SAAS;EACT,SAAS,CACL;GACI,OAAO;GACP,OAAO;GACV,EACD;GACI,OAAO;GACP,OAAO;GACV,CACJ;EACJ;CACD,UAAU;EACN,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,MAAM;EACF,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,KAAK;EACD,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACD,eAAe;EACX,MAAM;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACb;CACJ;;;;;;;;;AAsCD,IAAa,WAAb,MAAa,SAAyB;CAElC,OAAgB,YAAY;CAC5B,OAAgB,eAAe;CAC/B,OAAgB,eAAe;CAE/B,AAAQ;CACR,AAAQ;CAER,YAAY,QAAwB;EAChC,MAAM,EAAE,qBAAqB,kBAAkB;AAC/C,OAAK,sBAAsB;AAC3B,OAAK,gBAAgB;AACrB,WAAS,0DAAsD,qBAAqB,cAAc;AAElG,WAAS,QAAQ,SAAS,aAAa;;CAG3C,MAAM,KAAK,OAAe,MAAe,QAAkE;AACvG,WAAS,2CAAuC,OAAO,MAAM,OAAO;EACpE,MAAM,EAAE,cAAc,GAAG,GAAG,SAAS,UAAU,EAAE;EACjD,MAAM,OAAO,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,EAAE,KAAK,cAAc,CAAC;EAC7D,MAAM,UAAU,GAAG,QAAQ,OAAO,KAAK,SAAS;AAChD,SAAO,KAAK;GACR,KAAK;GACL,QAAQ;GACR,SAAS,EACL,gBAAgB,oBACnB;GACD,MAAM;IACF,GAAG;IACH,UAAU,KAAK;IACf;IACA;IACA;IACH;GACJ,CAAC;;;;;;ACpNV,MAAa,eAAe;CACxB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACH;;;;;;;;;;;;AAuBD,eAAsB,gBAAoC,OAAe,MAAc,YAA2D;CAC9I,MAAM,EAAE,MAAM,QAAQ,WAAW;AACjC,KAAI,aAAa,MAEb,QADa,IAAI,aAAa,MAAM,OAAc,CACtC,KAAK,OAAO,MAAM,OAAc;AAEhD,OAAM,IAAI,MAAM,cAAc;;;;;;;;;;;;;AA4BlC,eAAsB,kBAAsC,OAAe,MAAc,YAAgE;CACrJ,MAAM,EAAE,MAAM,QAAQ,QAAQ,SAAS,cAAc;CAErD,MAAM,UAAU;EACZ;EACA;EACA;EACA;EACA;EACH;CACD,MAAM,MAAM,IAAI,IAAI,QAAQ;AAC5B,KAAI,WAAW;CACf,MAAM,WAAW,MAAM,KAAK;EACxB,KAAK,IAAI,UAAU;EACnB,QAAQ;EACR,SAAS;GACL,gBAAgB;GAChB,eAAe,UAAU;GAC5B;EACD,MAAM;EACT,CAAC;AAEF,KAAI,CAAC,SAAS,UAAU,SAAS,UAAU,IACvC,OAAM,IAAI,MAAM,cAAc,SAAS,SAAS;AAIpD,QADa,SAAS"}