statocysts 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/browser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as buildSenderRegistry, c as lark, d as defineTransport, f as defineProvider, i as bark, l as discord, n as json, o as telegram, p as assert, r as jsons, s as slack, t as serverChan, u as http } from "./server-chan-
|
|
1
|
+
import { a as buildSenderRegistry, c as lark, d as defineTransport, f as defineProvider, i as bark, l as discord, n as json, o as telegram, p as assert, r as jsons, s as slack, t as serverChan, u as http } from "./server-chan-WOnpnwST.js";
|
|
2
2
|
//#region src/browser.ts
|
|
3
3
|
const senderRegistry = buildSenderRegistry([
|
|
4
4
|
bark,
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as buildSenderRegistry, c as lark, d as defineTransport, f as defineProvider, i as bark, l as discord, n as json, o as telegram, p as assert, r as jsons, s as slack, t as serverChan, u as http } from "./server-chan-
|
|
1
|
+
import { a as buildSenderRegistry, c as lark, d as defineTransport, f as defineProvider, i as bark, l as discord, n as json, o as telegram, p as assert, r as jsons, s as slack, t as serverChan, u as http } from "./server-chan-WOnpnwST.js";
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { SMTPClient } from "emailjs";
|
|
4
4
|
//#region src/core/transports/smtp.ts
|
|
@@ -263,8 +263,8 @@ const telegram = defineProvider("telegram:", {
|
|
|
263
263
|
titleFormatted = `*${escapeMarkdown(this.message.title)}*`;
|
|
264
264
|
bodyFormatted = escapeMarkdown(this.message.body);
|
|
265
265
|
} else {
|
|
266
|
-
titleFormatted = `*${this.message.title}*`;
|
|
267
|
-
bodyFormatted = this.message.body;
|
|
266
|
+
titleFormatted = `*${escapeMarkdown(this.message.title)}*`;
|
|
267
|
+
bodyFormatted = escapeMarkdown(this.message.body);
|
|
268
268
|
}
|
|
269
269
|
text = `${titleFormatted}\n\n${bodyFormatted}`;
|
|
270
270
|
} else if (query.parse_mode === "MarkdownV2") text = escapeMarkdown(this.message.title);
|
|
@@ -462,4 +462,4 @@ const serverChan = defineProvider("server-chan:", {
|
|
|
462
462
|
//#endregion
|
|
463
463
|
export { buildSenderRegistry as a, lark as c, defineTransport as d, defineProvider as f, bark as i, discord as l, json as n, telegram as o, assert as p, jsons as r, slack as s, serverChan as t, http as u };
|
|
464
464
|
|
|
465
|
-
//# sourceMappingURL=server-chan-
|
|
465
|
+
//# sourceMappingURL=server-chan-WOnpnwST.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-chan-WOnpnwST.js","names":["querySchema"],"sources":["../src/utils/assert.ts","../src/utils/markdown.ts","../src/utils/url.ts","../src/core/provider.ts","../src/core/transport.ts","../src/core/transports/http.ts","../src/services/chat/discord/index.ts","../src/services/chat/lark/index.ts","../src/services/chat/slack/index.ts","../src/services/chat/telegram/index.ts","../src/core/sender.ts","../src/services/push/bark/index.ts","../src/services/specialized/json/index.ts","../src/services/push/server-chan/index.ts"],"sourcesContent":["export function assert(condition: any, message: string | Error): asserts condition {\n if (!condition) {\n throw typeof message === 'string' ? new Error(message) : message\n }\n}\n","/**\n * Escape special characters for Telegram MarkdownV2: _*[]()~`>#+-=|{}.!\n */\nexport function escapeMarkdown(text: string): string {\n return text.replace(/([_*[\\]()~`>#+\\-=|{}.!])/g, '\\\\$1')\n}\n\n/**\n * Escape special characters for HTML: &<>\n */\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n}\n","import { getQuery } from 'ufo'\n\nexport function getValidateQuery<T>(\n url: URL | string,\n parser: (params: unknown) => T,\n): T {\n const query = getQuery(url.toString())\n return parser(query)\n}\n\nexport function withoutPathname(input: string): string {\n const _url = new URL(input)\n _url.pathname = ''\n return _url.toString()\n}\n","import type { Transport } from './transport'\nimport { assert } from '#/utils'\nimport defu from 'defu'\n\n// Utility type to infer Payload from Transport\ntype InferTransportPayload<T> = T extends Transport<infer P> ? P : never\n\nexport interface ServiceProvider<\n Protocol extends string,\n Payload,\n Options = void,\n> {\n readonly $transport: Transport<Payload>\n readonly protocol: Protocol\n defaultOptions: Options | undefined\n send: (url: string, message: { title: string, body?: string }, options?: Options) => Promise<void>\n}\n\nexport interface DefineProviderContext {\n url: URL\n message: { title: string, body?: string }\n}\n\nexport interface DefineProviderOptions<T extends Transport, Options> {\n defaultOptions?: Options\n transport: T\n prepare: (\n this: DefineProviderContext,\n ctx: DefineProviderContext,\n options: Options,\n ) => Promise<InferTransportPayload<T>>\n}\n\nexport function defineProvider<const Protocol extends string, T extends Transport<any>, Options = void>(\n protocol: Protocol,\n createOptions: DefineProviderOptions<T, Options>,\n): ServiceProvider<Protocol, InferTransportPayload<T>, Options> {\n const send: ServiceProvider<Protocol, InferTransportPayload<T>, Options>['send'] = async (\n protocolUrl,\n message,\n options,\n ): Promise<void> => {\n const url = new URL(protocolUrl)\n\n assert(url.protocol === protocol, `Unexpected protocol \"${url.protocol}\"`)\n\n const ctx: DefineProviderContext = {\n url,\n message,\n }\n\n const opts = defu(options ?? {}, createOptions.defaultOptions ?? {}) as Options\n\n const payload = await createOptions.prepare.call(ctx, ctx, opts)\n\n await createOptions.transport.send(payload)\n }\n return {\n get protocol() {\n return protocol\n },\n get defaultOptions() {\n return createOptions.defaultOptions\n },\n get $transport() {\n return createOptions.transport\n },\n send,\n }\n}\n","/**\n * Transport interface for protocol-specific network communication\n * Each transport handles the actual sending of data over a specific protocol\n */\nexport interface Transport<Payload = unknown> {\n /**\n * Send data using the transport's protocol\n * @param payload Protocol-specific payload to send\n */\n send: (payload: Payload) => Promise<void>\n}\n\nexport function defineTransport<Payload>(\n transport: Transport<Payload>,\n): Transport<Payload> {\n return transport\n}\n","import type { FetchOptions } from 'ofetch'\nimport { ofetch } from 'ofetch'\nimport { defineTransport } from '../transport'\n\n/**\n * HTTP payload for HTTP transport\n */\nexport interface HttpPayload {\n request: Request\n fetchOptions?: FetchOptions\n}\n\n/**\n * HTTP transport implementation\n * Handles sending data over HTTP/HTTPS protocols\n */\nexport const http = defineTransport({\n async send(payload: HttpPayload) {\n await ofetch(payload.request, payload.fetchOptions)\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { assert, getValidateQuery } from '#/utils'\nimport defu from 'defu'\nimport z from 'zod'\n\ninterface DiscordOptions {\n fetchOptions?: FetchOptions\n}\n\nconst querySchema = z.object({\n avatar_url: z.string().optional(),\n username: z.string().optional(),\n\n wait: z.string().transform((val) => {\n if (val === 'false' || val === '0' || val === '') {\n return false\n }\n return true\n }).optional(),\n})\n\nexport const discord = defineProvider('discord:', {\n transport: http,\n defaultOptions: {} as DiscordOptions,\n async prepare(ctx, options) {\n const { url } = ctx\n\n assert(url.hostname === 'webhook', 'Invalid discord URL')\n assert(url.username, 'Webhook ID is required')\n assert(url.password, 'Webhook token is required')\n\n const queryResult = getValidateQuery(url, querySchema.safeParse)\n\n if (!queryResult.success) {\n throw new Error('Invalid discord query')\n }\n\n const { wait, ...query } = queryResult.data\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const content = ctx.message.body ? `## ${ctx.message.title}\\n\\n${ctx.message.body}` : ctx.message.title\n\n const body = defu({ content }, query)\n\n const requestUrl = new URL(`/api/webhooks/${url.username}/${url.password}`, 'https://discord.com')\n\n if (wait) {\n requestUrl.searchParams.set('wait', 'true')\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { assert } from '#/utils'\n\ninterface LarkOptions {\n baseUrl?: string\n fetchOptions?: FetchOptions\n}\n\nconst FEISHU_BASE_URL = 'https://open.feishu.cn'\nconst LARK_BASE_URL = 'https://open.larksuite.com'\n\nasync function computeSign(timestamp: string, secret: string): Promise<string> {\n const key = `${timestamp}\\n${secret}`\n const encoder = new TextEncoder()\n const cryptoKey = await globalThis.crypto.subtle.importKey(\n 'raw',\n encoder.encode(key),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n )\n const signature = await globalThis.crypto.subtle.sign('HMAC', cryptoKey, new Uint8Array(0))\n return btoa(String.fromCharCode(...new Uint8Array(signature)))\n}\n\nexport const lark = defineProvider('lark:', {\n transport: http,\n defaultOptions: {} as LarkOptions,\n async prepare(ctx, options) {\n const { url } = ctx\n\n assert(url.hostname === 'webhook', 'Invalid lark URL')\n assert(url.username, 'Webhook token is required')\n\n const token = url.username\n const secret = url.password || undefined\n const domain = url.searchParams.get('domain')\n\n const baseUrl = options.baseUrl\n ?? (domain === 'feishu' ? FEISHU_BASE_URL : LARK_BASE_URL)\n\n const requestUrl = new URL(`/open-apis/bot/v2/hook/${token}`, baseUrl)\n\n let body: Record<string, unknown>\n\n if (ctx.message.body) {\n body = {\n msg_type: 'interactive',\n card: {\n header: {\n title: { tag: 'plain_text', content: ctx.message.title },\n },\n elements: [\n { tag: 'markdown', content: ctx.message.body },\n ],\n },\n }\n }\n else {\n body = {\n msg_type: 'text',\n content: { text: ctx.message.title },\n }\n }\n\n if (secret) {\n const timestamp = Math.floor(Date.now() / 1000).toString()\n const sign = await computeSign(timestamp, secret)\n body.timestamp = timestamp\n body.sign = sign\n }\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { assert } from '#/utils'\nimport { withoutLeadingSlash } from 'ufo'\n\nexport interface SlackOptions {\n /**\n * The base URL for webhook services\n *\n * @default `https://hooks.slack.com/services`\n */\n hookBaseUrl?: string\n /**\n * The base URL for bot API services\n *\n * @default `https://slack.com/api`\n */\n botApiBaseUrl?: string\n\n /**\n * The body of the request\n *\n * NOTICE*: This will override the body of the request. You should known what you are doing.\n */\n body?: Record<string, any>\n\n fetchOptions?: FetchOptions\n}\n\nexport const slack = defineProvider('slack:', {\n transport: http,\n defaultOptions: {\n hookBaseUrl: 'https://hooks.slack.com/',\n botApiBaseUrl: 'https://slack.com/',\n } as SlackOptions,\n async prepare(_, options) {\n const { url } = this\n\n // Validate URL format\n assert(url.hostname === 'bot' || url.hostname === 'webhook', `Invalid slack URL: ${url.toString()}`)\n\n const type = url.hostname as 'bot' | 'webhook'\n\n if (type === 'bot') {\n assert(url.username, 'Channel ID is required')\n assert(url.password, 'Bot token is required')\n }\n else {\n const pathParts = url.pathname.split('/').filter(Boolean)\n assert(pathParts.length === 3, 'Webhook URL is invalid')\n }\n\n let requestUrl: URL\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n const body: Record<string, any> = {}\n\n // Build message content based on title and body\n if (this.message.body) {\n // When body is present, use blocks for rich markdown formatting\n body.blocks = [\n {\n type: 'header',\n text: {\n type: 'plain_text',\n text: this.message.title,\n },\n },\n {\n type: 'section',\n text: {\n type: 'mrkdwn',\n text: this.message.body,\n },\n },\n ]\n // Fallback text for notifications\n body.text = this.message.title\n }\n else {\n // When only title is present, use simple text format\n body.text = this.message.title\n }\n\n if (type === 'bot') {\n const { username: channel, password: token, searchParams } = url\n requestUrl = new URL('/api/chat.postMessage', options.botApiBaseUrl)\n searchParams.forEach((value, key) => {\n requestUrl.searchParams.set(key, value)\n })\n\n headers.set('Authorization', `Bearer ${token}`)\n\n body.channel = channel\n }\n else {\n const { searchParams } = url\n requestUrl = new URL(`/services/${withoutLeadingSlash(url.pathname)}`, options.hookBaseUrl)\n searchParams.forEach((value, key) => {\n requestUrl.searchParams.set(key, value)\n })\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(options.body ?? body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { escapeHtml, escapeMarkdown, getValidateQuery } from '#/utils'\nimport { assert } from '#/utils/assert'\nimport z from 'zod'\n\nexport const telegramQuerySchema = z.object({\n parse_mode: z.enum(['Markdown', 'MarkdownV2', 'HTML']).optional(),\n})\n\nexport interface TelegramOptions {\n /**\n * The base URL for Telegram Bot API\n *\n * @default `https://api.telegram.org`\n */\n apiBaseUrl?: string\n\n fetchOptions?: FetchOptions\n}\n\nexport const telegram = defineProvider('telegram:', {\n transport: http,\n defaultOptions: {\n apiBaseUrl: 'https://api.telegram.org',\n } as TelegramOptions,\n async prepare(_, options) {\n const { url } = this\n\n // Validate URL format\n assert(url.hostname === 'bot', `Invalid telegram URL: ${url.toString()}`)\n assert(url.username, 'Bot token is required')\n\n // Extract chat IDs from pathname (e.g., /chat-1/chat-2)\n const pathSegments = url.pathname.split('/').filter(Boolean)\n assert(pathSegments.length > 0, 'At least one chat ID is required')\n\n const queryResult = getValidateQuery(url, telegramQuerySchema.safeParse)\n\n if (!queryResult.success) {\n throw new Error('Invalid telegram query')\n }\n\n const query = queryResult.data\n\n // Bot token is in the username and password fields, because token contains `:` character\n const botToken = `${url.username}:${url.password}`\n\n // First chat ID from pathname (decode to handle @ symbols like @mychannel)\n // Support format: chat-id or chat-id:message-thread-id\n const chatPart = decodeURIComponent(pathSegments[0])\n const [chatId, messageThreadId] = chatPart.includes(':')\n ? chatPart.split(':', 2)\n : [chatPart, undefined]\n\n // Build API URL\n const requestUrl = new URL(`/bot${botToken}/sendMessage`, options.apiBaseUrl)\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n // Build message text based on parse_mode\n let text: string\n if (this.message.body) {\n // Title as h1, body as content\n const parseMode = query.parse_mode\n let titleFormatted: string\n let bodyFormatted: string\n\n if (parseMode === 'HTML') {\n // Escape title and body to prevent breaking HTML tags\n titleFormatted = `<b>${escapeHtml(this.message.title)}</b>`\n bodyFormatted = escapeHtml(this.message.body)\n }\n else if (parseMode === 'MarkdownV2') {\n // MarkdownV2 requires escaping special characters in title and body\n const escapedTitle = escapeMarkdown(this.message.title)\n titleFormatted = `*${escapedTitle}*`\n bodyFormatted = escapeMarkdown(this.message.body)\n }\n else {\n // Markdown or default - escape special chars to prevent parse errors\n titleFormatted = `*${escapeMarkdown(this.message.title)}*`\n bodyFormatted = escapeMarkdown(this.message.body)\n }\n\n text = `${titleFormatted}\\n\\n${bodyFormatted}`\n }\n else {\n // No body, title is the main content\n // Need to escape special characters in MarkdownV2/HTML mode\n if (query.parse_mode === 'MarkdownV2') {\n text = escapeMarkdown(this.message.title)\n }\n else if (query.parse_mode === 'HTML') {\n text = escapeHtml(this.message.title)\n }\n else {\n text = this.message.title\n }\n }\n\n const body: Record<string, any> = {\n chat_id: chatId,\n text,\n parse_mode: query.parse_mode,\n }\n\n // Add message_thread_id if specified (for topic/forum groups)\n if (messageThreadId) {\n body.message_thread_id = Number.parseInt(messageThreadId, 10)\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { ServiceProvider } from '#/core/provider'\n\nexport interface Sender {\n send: (title: string, body?: string) => Promise<void>\n}\n\nexport type SenderUrl = string | URL\n\nexport interface SenderRegistry {\n (urls: SenderUrl[]): Sender\n resolveProvider: (url: string | URL) => ServiceProvider<string, any, any> | undefined\n}\n\nexport function buildSenderRegistry(\n providers: ServiceProvider<string, any, any>[],\n): SenderRegistry {\n const providersRegistry = new Map<string, ServiceProvider<string, any, any>>()\n providers.forEach((provider) => {\n providersRegistry.set(provider.protocol, provider)\n })\n\n function resolveProvider(\n url: string | URL,\n ): ServiceProvider<string, any, any> | undefined {\n const _url = typeof url === 'string' ? new URL(url) : url\n\n return providersRegistry.get(_url.protocol)\n }\n\n function createSender(urls: SenderUrl[]): Sender {\n const registries = urls.map((url) => {\n const provider = resolveProvider(url)\n if (!provider) {\n return undefined\n }\n return { provider, url }\n }).filter((p): p is { provider: ServiceProvider<string, any, any>, url: SenderUrl } => !!p)\n\n return {\n async send(title: string, body?: string) {\n for (const registry of registries) {\n // Convert message string to { title, body? } format\n const messageObj = { title, body }\n await registry.provider.send(\n registry.url.toString(),\n messageObj,\n )\n }\n },\n }\n }\n\n return Object.assign(createSender, { resolveProvider })\n}\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider, http } from '#/shared'\nimport { assert, getValidateQuery, withoutPathname } from '#/utils'\nimport defu from 'defu'\nimport { withProtocol } from 'ufo'\nimport z from 'zod'\n\nexport interface BarkOptions {\n fetchOptions?: FetchOptions\n}\n\nconst querySchema = z.object({\n subtitle: z.string().optional(),\n group: z.string().optional(),\n url: z.string().optional(),\n icon: z.string().optional(),\n sound: z.string().optional(),\n call: z.enum(['1']).optional(),\n ciphertext: z.string().optional(),\n level: z.enum(['active', 'timeSensitive', 'passive', 'critical']).optional(),\n volume: z.string().optional(),\n badge: z.coerce.number().optional(),\n autoCopy: z.enum(['1']).optional(),\n copy: z.string().optional(),\n action: z.enum(['none']).optional(),\n isArchive: z.enum(['1']).optional(),\n})\n\nexport const bark = defineProvider('bark:', {\n transport: http,\n defaultOptions: {} as BarkOptions,\n async prepare(ctx, options) {\n const { message, url } = ctx\n\n assert(url.hostname, 'Server URL hostname is required')\n assert(url.pathname, 'Device key is required')\n\n const deviceKeys = url.pathname.split('/').filter(Boolean)\n assert(deviceKeys.length > 0, 'At least one device key is required')\n\n const queryResult = getValidateQuery(url, querySchema.safeParse)\n\n if (!queryResult.success) {\n throw new Error('Invalid Bark query parameters')\n }\n\n const query = queryResult.data\n\n const requestUrl = new URL(`/push`, withProtocol(withoutPathname(url.toString()), 'https:'))\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const contentData: { markdown: string, title?: string } = message.body ? { title: message.title, markdown: message.body } : { markdown: message.title }\n\n const body = defu({ device_keys: deviceKeys }, contentData, query)\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { DefineProviderContext } from '#/core/provider'\nimport type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { withProtocol } from 'ufo'\n\nasync function prepareJsonRequest(this: DefineProviderContext, _ctx: DefineProviderContext, defaultProtocol: string, options: FetchOptions) {\n const url = new URL(this.url)\n\n const protocol = defaultProtocol\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const body: Record<string, string> = {\n title: this.message.title,\n }\n\n if (this.message.body) {\n body.body = this.message.body\n }\n\n Array.from(url.searchParams.entries()).forEach(([key, value]) => {\n if (key.startsWith(' ')) {\n url.searchParams.delete(key)\n const headerKey = key.slice(1)\n if (headers.has(headerKey)) {\n headers.set(headerKey, value)\n }\n else {\n headers.append(headerKey, value)\n }\n }\n else if (key.startsWith(':')) {\n url.searchParams.delete(key)\n const propertyKey = key.slice(1)\n body[propertyKey] = value\n }\n })\n\n const requestUrl = withProtocol(url.toString(), protocol)\n\n const request = new Request(requestUrl, {\n method: 'POST',\n body: JSON.stringify(body),\n headers,\n })\n\n return {\n request,\n fetchOptions: options,\n }\n}\n\n// Supports json:// protocol (default to HTTP)\nexport const json = defineProvider('json:', {\n transport: http,\n defaultOptions: {} as FetchOptions,\n prepare(ctx, options) {\n return prepareJsonRequest.call(this, ctx, 'http:', options)\n },\n})\n\n// Supports jsons:// protocol (explicit HTTPS)\nexport const jsons = defineProvider('jsons:', {\n transport: http,\n defaultOptions: {} as FetchOptions,\n prepare(ctx, options) {\n return prepareJsonRequest.call(this, ctx, 'https:', options)\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider, http } from '#/shared'\nimport { assert } from '#/utils'\n\nexport interface ServerChanOptions {\n fetchOptions?: FetchOptions\n}\n\nexport const serverChan = defineProvider('server-chan:', {\n transport: http,\n defaultOptions: {} as ServerChanOptions,\n async prepare(_, options) {\n const { url } = this\n\n // Validate URL hostname to determine version\n assert(\n url.hostname === 'v3' || url.hostname === 'turbo',\n `Invalid server-chan URL: hostname must be 'v3' or 'turbo', got '${url.hostname}'`,\n )\n\n const version = url.hostname as 'v3' | 'turbo'\n\n let requestUrl: URL\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n const body: Record<string, any> = {\n title: this.message.title,\n }\n\n if (this.message.body) {\n body.desp = this.message.body\n }\n\n if (version === 'v3') {\n // Server Chan 3: server-chan://uid:sendKey@v3?tags=<tag1>&tags=<tag2>&short=<short>\n const { username: uid, password: sendKey, searchParams } = url\n\n assert(uid, 'UID is required for Server Chan 3')\n assert(sendKey, 'SendKey is required for Server Chan 3')\n\n requestUrl = new URL(`https://${uid}.push.ft07.com/send/${sendKey}.send`)\n\n // Add optional parameters from searchParams\n const tags: string[] = []\n searchParams.forEach((value, key) => {\n if (key === 'tags') {\n tags.push(value)\n }\n else if (key === 'short') {\n body.short = value\n }\n })\n\n if (tags.length > 0) {\n body.tags = tags.join('|')\n }\n }\n else {\n // Server Chan Turbo: server-chan://ftqq:SENDKEY@turbo?short=<short>&noip=<1|0|true|false>&channel=<channel>&openid=<openid>\n // Note: username (ftqq) is optional and not used in the API request\n const { password: sendKey, searchParams } = url\n\n assert(sendKey, 'SendKey is required for Server Chan Turbo')\n\n requestUrl = new URL(`https://sctapi.ftqq.com/${sendKey}.send`)\n\n // Add optional parameters from searchParams\n searchParams.forEach((value, key) => {\n if (key === 'short') {\n body.short = value\n }\n else if (key === 'noip') {\n body.noip = value === '1' || value === 'true' ? 1 : 0\n }\n else if (key === 'channel') {\n body.channel = value\n }\n else if (key === 'openid') {\n body.openid = value\n }\n })\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server-chan-DeSNBT3J.js","names":["querySchema"],"sources":["../src/utils/assert.ts","../src/utils/markdown.ts","../src/utils/url.ts","../src/core/provider.ts","../src/core/transport.ts","../src/core/transports/http.ts","../src/services/chat/discord/index.ts","../src/services/chat/lark/index.ts","../src/services/chat/slack/index.ts","../src/services/chat/telegram/index.ts","../src/core/sender.ts","../src/services/push/bark/index.ts","../src/services/specialized/json/index.ts","../src/services/push/server-chan/index.ts"],"sourcesContent":["export function assert(condition: any, message: string | Error): asserts condition {\n if (!condition) {\n throw typeof message === 'string' ? new Error(message) : message\n }\n}\n","/**\n * Escape special characters for Telegram MarkdownV2: _*[]()~`>#+-=|{}.!\n */\nexport function escapeMarkdown(text: string): string {\n return text.replace(/([_*[\\]()~`>#+\\-=|{}.!])/g, '\\\\$1')\n}\n\n/**\n * Escape special characters for HTML: &<>\n */\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n}\n","import { getQuery } from 'ufo'\n\nexport function getValidateQuery<T>(\n url: URL | string,\n parser: (params: unknown) => T,\n): T {\n const query = getQuery(url.toString())\n return parser(query)\n}\n\nexport function withoutPathname(input: string): string {\n const _url = new URL(input)\n _url.pathname = ''\n return _url.toString()\n}\n","import type { Transport } from './transport'\nimport { assert } from '#/utils'\nimport defu from 'defu'\n\n// Utility type to infer Payload from Transport\ntype InferTransportPayload<T> = T extends Transport<infer P> ? P : never\n\nexport interface ServiceProvider<\n Protocol extends string,\n Payload,\n Options = void,\n> {\n readonly $transport: Transport<Payload>\n readonly protocol: Protocol\n defaultOptions: Options | undefined\n send: (url: string, message: { title: string, body?: string }, options?: Options) => Promise<void>\n}\n\nexport interface DefineProviderContext {\n url: URL\n message: { title: string, body?: string }\n}\n\nexport interface DefineProviderOptions<T extends Transport, Options> {\n defaultOptions?: Options\n transport: T\n prepare: (\n this: DefineProviderContext,\n ctx: DefineProviderContext,\n options: Options,\n ) => Promise<InferTransportPayload<T>>\n}\n\nexport function defineProvider<const Protocol extends string, T extends Transport<any>, Options = void>(\n protocol: Protocol,\n createOptions: DefineProviderOptions<T, Options>,\n): ServiceProvider<Protocol, InferTransportPayload<T>, Options> {\n const send: ServiceProvider<Protocol, InferTransportPayload<T>, Options>['send'] = async (\n protocolUrl,\n message,\n options,\n ): Promise<void> => {\n const url = new URL(protocolUrl)\n\n assert(url.protocol === protocol, `Unexpected protocol \"${url.protocol}\"`)\n\n const ctx: DefineProviderContext = {\n url,\n message,\n }\n\n const opts = defu(options ?? {}, createOptions.defaultOptions ?? {}) as Options\n\n const payload = await createOptions.prepare.call(ctx, ctx, opts)\n\n await createOptions.transport.send(payload)\n }\n return {\n get protocol() {\n return protocol\n },\n get defaultOptions() {\n return createOptions.defaultOptions\n },\n get $transport() {\n return createOptions.transport\n },\n send,\n }\n}\n","/**\n * Transport interface for protocol-specific network communication\n * Each transport handles the actual sending of data over a specific protocol\n */\nexport interface Transport<Payload = unknown> {\n /**\n * Send data using the transport's protocol\n * @param payload Protocol-specific payload to send\n */\n send: (payload: Payload) => Promise<void>\n}\n\nexport function defineTransport<Payload>(\n transport: Transport<Payload>,\n): Transport<Payload> {\n return transport\n}\n","import type { FetchOptions } from 'ofetch'\nimport { ofetch } from 'ofetch'\nimport { defineTransport } from '../transport'\n\n/**\n * HTTP payload for HTTP transport\n */\nexport interface HttpPayload {\n request: Request\n fetchOptions?: FetchOptions\n}\n\n/**\n * HTTP transport implementation\n * Handles sending data over HTTP/HTTPS protocols\n */\nexport const http = defineTransport({\n async send(payload: HttpPayload) {\n await ofetch(payload.request, payload.fetchOptions)\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { assert, getValidateQuery } from '#/utils'\nimport defu from 'defu'\nimport z from 'zod'\n\ninterface DiscordOptions {\n fetchOptions?: FetchOptions\n}\n\nconst querySchema = z.object({\n avatar_url: z.string().optional(),\n username: z.string().optional(),\n\n wait: z.string().transform((val) => {\n if (val === 'false' || val === '0' || val === '') {\n return false\n }\n return true\n }).optional(),\n})\n\nexport const discord = defineProvider('discord:', {\n transport: http,\n defaultOptions: {} as DiscordOptions,\n async prepare(ctx, options) {\n const { url } = ctx\n\n assert(url.hostname === 'webhook', 'Invalid discord URL')\n assert(url.username, 'Webhook ID is required')\n assert(url.password, 'Webhook token is required')\n\n const queryResult = getValidateQuery(url, querySchema.safeParse)\n\n if (!queryResult.success) {\n throw new Error('Invalid discord query')\n }\n\n const { wait, ...query } = queryResult.data\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const content = ctx.message.body ? `## ${ctx.message.title}\\n\\n${ctx.message.body}` : ctx.message.title\n\n const body = defu({ content }, query)\n\n const requestUrl = new URL(`/api/webhooks/${url.username}/${url.password}`, 'https://discord.com')\n\n if (wait) {\n requestUrl.searchParams.set('wait', 'true')\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { assert } from '#/utils'\n\ninterface LarkOptions {\n baseUrl?: string\n fetchOptions?: FetchOptions\n}\n\nconst FEISHU_BASE_URL = 'https://open.feishu.cn'\nconst LARK_BASE_URL = 'https://open.larksuite.com'\n\nasync function computeSign(timestamp: string, secret: string): Promise<string> {\n const key = `${timestamp}\\n${secret}`\n const encoder = new TextEncoder()\n const cryptoKey = await globalThis.crypto.subtle.importKey(\n 'raw',\n encoder.encode(key),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n )\n const signature = await globalThis.crypto.subtle.sign('HMAC', cryptoKey, new Uint8Array(0))\n return btoa(String.fromCharCode(...new Uint8Array(signature)))\n}\n\nexport const lark = defineProvider('lark:', {\n transport: http,\n defaultOptions: {} as LarkOptions,\n async prepare(ctx, options) {\n const { url } = ctx\n\n assert(url.hostname === 'webhook', 'Invalid lark URL')\n assert(url.username, 'Webhook token is required')\n\n const token = url.username\n const secret = url.password || undefined\n const domain = url.searchParams.get('domain')\n\n const baseUrl = options.baseUrl\n ?? (domain === 'feishu' ? FEISHU_BASE_URL : LARK_BASE_URL)\n\n const requestUrl = new URL(`/open-apis/bot/v2/hook/${token}`, baseUrl)\n\n let body: Record<string, unknown>\n\n if (ctx.message.body) {\n body = {\n msg_type: 'interactive',\n card: {\n header: {\n title: { tag: 'plain_text', content: ctx.message.title },\n },\n elements: [\n { tag: 'markdown', content: ctx.message.body },\n ],\n },\n }\n }\n else {\n body = {\n msg_type: 'text',\n content: { text: ctx.message.title },\n }\n }\n\n if (secret) {\n const timestamp = Math.floor(Date.now() / 1000).toString()\n const sign = await computeSign(timestamp, secret)\n body.timestamp = timestamp\n body.sign = sign\n }\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { assert } from '#/utils'\nimport { withoutLeadingSlash } from 'ufo'\n\nexport interface SlackOptions {\n /**\n * The base URL for webhook services\n *\n * @default `https://hooks.slack.com/services`\n */\n hookBaseUrl?: string\n /**\n * The base URL for bot API services\n *\n * @default `https://slack.com/api`\n */\n botApiBaseUrl?: string\n\n /**\n * The body of the request\n *\n * NOTICE*: This will override the body of the request. You should known what you are doing.\n */\n body?: Record<string, any>\n\n fetchOptions?: FetchOptions\n}\n\nexport const slack = defineProvider('slack:', {\n transport: http,\n defaultOptions: {\n hookBaseUrl: 'https://hooks.slack.com/',\n botApiBaseUrl: 'https://slack.com/',\n } as SlackOptions,\n async prepare(_, options) {\n const { url } = this\n\n // Validate URL format\n assert(url.hostname === 'bot' || url.hostname === 'webhook', `Invalid slack URL: ${url.toString()}`)\n\n const type = url.hostname as 'bot' | 'webhook'\n\n if (type === 'bot') {\n assert(url.username, 'Channel ID is required')\n assert(url.password, 'Bot token is required')\n }\n else {\n const pathParts = url.pathname.split('/').filter(Boolean)\n assert(pathParts.length === 3, 'Webhook URL is invalid')\n }\n\n let requestUrl: URL\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n const body: Record<string, any> = {}\n\n // Build message content based on title and body\n if (this.message.body) {\n // When body is present, use blocks for rich markdown formatting\n body.blocks = [\n {\n type: 'header',\n text: {\n type: 'plain_text',\n text: this.message.title,\n },\n },\n {\n type: 'section',\n text: {\n type: 'mrkdwn',\n text: this.message.body,\n },\n },\n ]\n // Fallback text for notifications\n body.text = this.message.title\n }\n else {\n // When only title is present, use simple text format\n body.text = this.message.title\n }\n\n if (type === 'bot') {\n const { username: channel, password: token, searchParams } = url\n requestUrl = new URL('/api/chat.postMessage', options.botApiBaseUrl)\n searchParams.forEach((value, key) => {\n requestUrl.searchParams.set(key, value)\n })\n\n headers.set('Authorization', `Bearer ${token}`)\n\n body.channel = channel\n }\n else {\n const { searchParams } = url\n requestUrl = new URL(`/services/${withoutLeadingSlash(url.pathname)}`, options.hookBaseUrl)\n searchParams.forEach((value, key) => {\n requestUrl.searchParams.set(key, value)\n })\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(options.body ?? body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { escapeHtml, escapeMarkdown, getValidateQuery } from '#/utils'\nimport { assert } from '#/utils/assert'\nimport z from 'zod'\n\nexport const telegramQuerySchema = z.object({\n parse_mode: z.enum(['Markdown', 'MarkdownV2', 'HTML']).optional(),\n})\n\nexport interface TelegramOptions {\n /**\n * The base URL for Telegram Bot API\n *\n * @default `https://api.telegram.org`\n */\n apiBaseUrl?: string\n\n fetchOptions?: FetchOptions\n}\n\nexport const telegram = defineProvider('telegram:', {\n transport: http,\n defaultOptions: {\n apiBaseUrl: 'https://api.telegram.org',\n } as TelegramOptions,\n async prepare(_, options) {\n const { url } = this\n\n // Validate URL format\n assert(url.hostname === 'bot', `Invalid telegram URL: ${url.toString()}`)\n assert(url.username, 'Bot token is required')\n\n // Extract chat IDs from pathname (e.g., /chat-1/chat-2)\n const pathSegments = url.pathname.split('/').filter(Boolean)\n assert(pathSegments.length > 0, 'At least one chat ID is required')\n\n const queryResult = getValidateQuery(url, telegramQuerySchema.safeParse)\n\n if (!queryResult.success) {\n throw new Error('Invalid telegram query')\n }\n\n const query = queryResult.data\n\n // Bot token is in the username and password fields, because token contains `:` character\n const botToken = `${url.username}:${url.password}`\n\n // First chat ID from pathname (decode to handle @ symbols like @mychannel)\n // Support format: chat-id or chat-id:message-thread-id\n const chatPart = decodeURIComponent(pathSegments[0])\n const [chatId, messageThreadId] = chatPart.includes(':')\n ? chatPart.split(':', 2)\n : [chatPart, undefined]\n\n // Build API URL\n const requestUrl = new URL(`/bot${botToken}/sendMessage`, options.apiBaseUrl)\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n // Build message text based on parse_mode\n let text: string\n if (this.message.body) {\n // Title as h1, body as content\n const parseMode = query.parse_mode\n let titleFormatted: string\n let bodyFormatted: string\n\n if (parseMode === 'HTML') {\n // Escape title and body to prevent breaking HTML tags\n titleFormatted = `<b>${escapeHtml(this.message.title)}</b>`\n bodyFormatted = escapeHtml(this.message.body)\n }\n else if (parseMode === 'MarkdownV2') {\n // MarkdownV2 requires escaping special characters in title and body\n const escapedTitle = escapeMarkdown(this.message.title)\n titleFormatted = `*${escapedTitle}*`\n bodyFormatted = escapeMarkdown(this.message.body)\n }\n else {\n // Markdown or default\n titleFormatted = `*${this.message.title}*`\n bodyFormatted = this.message.body\n }\n\n text = `${titleFormatted}\\n\\n${bodyFormatted}`\n }\n else {\n // No body, title is the main content\n // Need to escape special characters in MarkdownV2/HTML mode\n if (query.parse_mode === 'MarkdownV2') {\n text = escapeMarkdown(this.message.title)\n }\n else if (query.parse_mode === 'HTML') {\n text = escapeHtml(this.message.title)\n }\n else {\n text = this.message.title\n }\n }\n\n const body: Record<string, any> = {\n chat_id: chatId,\n text,\n parse_mode: query.parse_mode,\n }\n\n // Add message_thread_id if specified (for topic/forum groups)\n if (messageThreadId) {\n body.message_thread_id = Number.parseInt(messageThreadId, 10)\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { ServiceProvider } from '#/core/provider'\n\nexport interface Sender {\n send: (title: string, body?: string) => Promise<void>\n}\n\nexport type SenderUrl = string | URL\n\nexport interface SenderRegistry {\n (urls: SenderUrl[]): Sender\n resolveProvider: (url: string | URL) => ServiceProvider<string, any, any> | undefined\n}\n\nexport function buildSenderRegistry(\n providers: ServiceProvider<string, any, any>[],\n): SenderRegistry {\n const providersRegistry = new Map<string, ServiceProvider<string, any, any>>()\n providers.forEach((provider) => {\n providersRegistry.set(provider.protocol, provider)\n })\n\n function resolveProvider(\n url: string | URL,\n ): ServiceProvider<string, any, any> | undefined {\n const _url = typeof url === 'string' ? new URL(url) : url\n\n return providersRegistry.get(_url.protocol)\n }\n\n function createSender(urls: SenderUrl[]): Sender {\n const registries = urls.map((url) => {\n const provider = resolveProvider(url)\n if (!provider) {\n return undefined\n }\n return { provider, url }\n }).filter((p): p is { provider: ServiceProvider<string, any, any>, url: SenderUrl } => !!p)\n\n return {\n async send(title: string, body?: string) {\n for (const registry of registries) {\n // Convert message string to { title, body? } format\n const messageObj = { title, body }\n await registry.provider.send(\n registry.url.toString(),\n messageObj,\n )\n }\n },\n }\n }\n\n return Object.assign(createSender, { resolveProvider })\n}\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider, http } from '#/shared'\nimport { assert, getValidateQuery, withoutPathname } from '#/utils'\nimport defu from 'defu'\nimport { withProtocol } from 'ufo'\nimport z from 'zod'\n\nexport interface BarkOptions {\n fetchOptions?: FetchOptions\n}\n\nconst querySchema = z.object({\n subtitle: z.string().optional(),\n group: z.string().optional(),\n url: z.string().optional(),\n icon: z.string().optional(),\n sound: z.string().optional(),\n call: z.enum(['1']).optional(),\n ciphertext: z.string().optional(),\n level: z.enum(['active', 'timeSensitive', 'passive', 'critical']).optional(),\n volume: z.string().optional(),\n badge: z.coerce.number().optional(),\n autoCopy: z.enum(['1']).optional(),\n copy: z.string().optional(),\n action: z.enum(['none']).optional(),\n isArchive: z.enum(['1']).optional(),\n})\n\nexport const bark = defineProvider('bark:', {\n transport: http,\n defaultOptions: {} as BarkOptions,\n async prepare(ctx, options) {\n const { message, url } = ctx\n\n assert(url.hostname, 'Server URL hostname is required')\n assert(url.pathname, 'Device key is required')\n\n const deviceKeys = url.pathname.split('/').filter(Boolean)\n assert(deviceKeys.length > 0, 'At least one device key is required')\n\n const queryResult = getValidateQuery(url, querySchema.safeParse)\n\n if (!queryResult.success) {\n throw new Error('Invalid Bark query parameters')\n }\n\n const query = queryResult.data\n\n const requestUrl = new URL(`/push`, withProtocol(withoutPathname(url.toString()), 'https:'))\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const contentData: { markdown: string, title?: string } = message.body ? { title: message.title, markdown: message.body } : { markdown: message.title }\n\n const body = defu({ device_keys: deviceKeys }, contentData, query)\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { DefineProviderContext } from '#/core/provider'\nimport type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { withProtocol } from 'ufo'\n\nasync function prepareJsonRequest(this: DefineProviderContext, _ctx: DefineProviderContext, defaultProtocol: string, options: FetchOptions) {\n const url = new URL(this.url)\n\n const protocol = defaultProtocol\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const body: Record<string, string> = {\n title: this.message.title,\n }\n\n if (this.message.body) {\n body.body = this.message.body\n }\n\n Array.from(url.searchParams.entries()).forEach(([key, value]) => {\n if (key.startsWith(' ')) {\n url.searchParams.delete(key)\n const headerKey = key.slice(1)\n if (headers.has(headerKey)) {\n headers.set(headerKey, value)\n }\n else {\n headers.append(headerKey, value)\n }\n }\n else if (key.startsWith(':')) {\n url.searchParams.delete(key)\n const propertyKey = key.slice(1)\n body[propertyKey] = value\n }\n })\n\n const requestUrl = withProtocol(url.toString(), protocol)\n\n const request = new Request(requestUrl, {\n method: 'POST',\n body: JSON.stringify(body),\n headers,\n })\n\n return {\n request,\n fetchOptions: options,\n }\n}\n\n// Supports json:// protocol (default to HTTP)\nexport const json = defineProvider('json:', {\n transport: http,\n defaultOptions: {} as FetchOptions,\n prepare(ctx, options) {\n return prepareJsonRequest.call(this, ctx, 'http:', options)\n },\n})\n\n// Supports jsons:// protocol (explicit HTTPS)\nexport const jsons = defineProvider('jsons:', {\n transport: http,\n defaultOptions: {} as FetchOptions,\n prepare(ctx, options) {\n return prepareJsonRequest.call(this, ctx, 'https:', options)\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider, http } from '#/shared'\nimport { assert } from '#/utils'\n\nexport interface ServerChanOptions {\n fetchOptions?: FetchOptions\n}\n\nexport const serverChan = defineProvider('server-chan:', {\n transport: http,\n defaultOptions: {} as ServerChanOptions,\n async prepare(_, options) {\n const { url } = this\n\n // Validate URL hostname to determine version\n assert(\n url.hostname === 'v3' || url.hostname === 'turbo',\n `Invalid server-chan URL: hostname must be 'v3' or 'turbo', got '${url.hostname}'`,\n )\n\n const version = url.hostname as 'v3' | 'turbo'\n\n let requestUrl: URL\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n const body: Record<string, any> = {\n title: this.message.title,\n }\n\n if (this.message.body) {\n body.desp = this.message.body\n }\n\n if (version === 'v3') {\n // Server Chan 3: server-chan://uid:sendKey@v3?tags=<tag1>&tags=<tag2>&short=<short>\n const { username: uid, password: sendKey, searchParams } = url\n\n assert(uid, 'UID is required for Server Chan 3')\n assert(sendKey, 'SendKey is required for Server Chan 3')\n\n requestUrl = new URL(`https://${uid}.push.ft07.com/send/${sendKey}.send`)\n\n // Add optional parameters from searchParams\n const tags: string[] = []\n searchParams.forEach((value, key) => {\n if (key === 'tags') {\n tags.push(value)\n }\n else if (key === 'short') {\n body.short = value\n }\n })\n\n if (tags.length > 0) {\n body.tags = tags.join('|')\n }\n }\n else {\n // Server Chan Turbo: server-chan://ftqq:SENDKEY@turbo?short=<short>&noip=<1|0|true|false>&channel=<channel>&openid=<openid>\n // Note: username (ftqq) is optional and not used in the API request\n const { password: sendKey, searchParams } = url\n\n assert(sendKey, 'SendKey is required for Server Chan Turbo')\n\n requestUrl = new URL(`https://sctapi.ftqq.com/${sendKey}.send`)\n\n // Add optional parameters from searchParams\n searchParams.forEach((value, key) => {\n if (key === 'short') {\n body.short = value\n }\n else if (key === 'noip') {\n body.noip = value === '1' || value === 'true' ? 1 : 0\n }\n else if (key === 'channel') {\n body.channel = value\n }\n else if (key === 'openid') {\n body.openid = value\n }\n })\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n"],"mappings":"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"}
|