@stacksjs/chat 0.70.86 → 0.70.88
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/package.json +5 -5
- package/dist/drivers/base.d.ts +0 -11
- package/dist/drivers/discord.d.ts +0 -82
- package/dist/drivers/slack.d.ts +0 -82
- package/dist/drivers/teams.d.ts +0 -76
- package/dist/index.d.ts +0 -43
- package/dist/index.js +0 -2
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/chat",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.70.
|
|
5
|
+
"version": "0.70.88",
|
|
6
6
|
"description": "Easily interact with chat APIs.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -53,10 +53,10 @@
|
|
|
53
53
|
"prepublishOnly": "bun run build"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@stacksjs/cli": "0.70.
|
|
57
|
-
"@stacksjs/config": "0.70.
|
|
56
|
+
"@stacksjs/cli": "0.70.88",
|
|
57
|
+
"@stacksjs/config": "0.70.88",
|
|
58
58
|
"better-dx": "^0.2.16",
|
|
59
|
-
"@stacksjs/error-handling": "0.70.
|
|
60
|
-
"@stacksjs/types": "0.70.
|
|
59
|
+
"@stacksjs/error-handling": "0.70.88",
|
|
60
|
+
"@stacksjs/types": "0.70.88"
|
|
61
61
|
}
|
|
62
62
|
}
|
package/dist/drivers/base.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { ChatDriver, ChatDriverConfig, ChatMessage, ChatResult, RenderOptions } from '@stacksjs/types';
|
|
2
|
-
export declare abstract class BaseChatDriver implements ChatDriver {
|
|
3
|
-
abstract name: string;
|
|
4
|
-
protected config: Required<ChatDriverConfig>;
|
|
5
|
-
constructor(config?: ChatDriverConfig);
|
|
6
|
-
configure(config: ChatDriverConfig): void;
|
|
7
|
-
abstract send(message: ChatMessage, options?: RenderOptions): Promise<ChatResult>;
|
|
8
|
-
protected validateMessage(message: ChatMessage): boolean;
|
|
9
|
-
protected handleError(error: unknown, message: ChatMessage): Promise<ChatResult>;
|
|
10
|
-
protected handleSuccess(message: ChatMessage, messageId?: string): Promise<ChatResult>;
|
|
11
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { BaseChatDriver } from './base';
|
|
2
|
-
import type { ChatMessage, ChatResult, RenderOptions } from '@stacksjs/types';
|
|
3
|
-
/**
|
|
4
|
-
* Configure Discord with webhook URL or bot token.
|
|
5
|
-
*
|
|
6
|
-
* Validates that the webhook URL (when provided) is HTTPS pointing at
|
|
7
|
-
* Discord's host. Same reasoning as the Slack driver — `http://` URLs
|
|
8
|
-
* leak the webhook token; off-domain URLs are typo'd configuration.
|
|
9
|
-
*/
|
|
10
|
-
export declare function configure(options: DiscordConfig): void;
|
|
11
|
-
/**
|
|
12
|
-
* Send a message to Discord
|
|
13
|
-
*/
|
|
14
|
-
export declare function send(message: ChatMessage, options?: RenderOptions): Promise<ChatResult>;
|
|
15
|
-
/**
|
|
16
|
-
* Send a simple message via Discord webhook
|
|
17
|
-
*/
|
|
18
|
-
export declare function sendWebhook(webhookUrl: string, content: string, options?: Partial<DiscordMessage>): Promise<ChatResult>;
|
|
19
|
-
/**
|
|
20
|
-
* Send an embed message via Discord webhook
|
|
21
|
-
*/
|
|
22
|
-
export declare function sendEmbed(webhookUrl: string, embed: DiscordEmbed, options?: Partial<DiscordMessage>): Promise<ChatResult>;
|
|
23
|
-
export declare const driver: DiscordDriver;
|
|
24
|
-
declare const __dtsx_default_export__: {
|
|
25
|
-
send: typeof send;
|
|
26
|
-
sendWebhook: typeof sendWebhook;
|
|
27
|
-
sendEmbed: typeof sendEmbed;
|
|
28
|
-
configure: typeof configure;
|
|
29
|
-
DiscordDriver: typeof DiscordDriver
|
|
30
|
-
};
|
|
31
|
-
export declare interface DiscordConfig {
|
|
32
|
-
webhookUrl?: string
|
|
33
|
-
botToken?: string
|
|
34
|
-
maxRetries?: number
|
|
35
|
-
retryTimeout?: number
|
|
36
|
-
}
|
|
37
|
-
export declare interface DiscordEmbed {
|
|
38
|
-
title?: string
|
|
39
|
-
description?: string
|
|
40
|
-
url?: string
|
|
41
|
-
color?: number
|
|
42
|
-
timestamp?: string
|
|
43
|
-
footer?: {
|
|
44
|
-
text: string
|
|
45
|
-
icon_url?: string
|
|
46
|
-
}
|
|
47
|
-
image?: {
|
|
48
|
-
url: string
|
|
49
|
-
}
|
|
50
|
-
thumbnail?: {
|
|
51
|
-
url: string
|
|
52
|
-
}
|
|
53
|
-
author?: {
|
|
54
|
-
name: string
|
|
55
|
-
url?: string
|
|
56
|
-
icon_url?: string
|
|
57
|
-
}
|
|
58
|
-
fields?: Array<{
|
|
59
|
-
name: string
|
|
60
|
-
value: string
|
|
61
|
-
inline?: boolean
|
|
62
|
-
}>
|
|
63
|
-
}
|
|
64
|
-
export declare interface DiscordMessage {
|
|
65
|
-
content?: string
|
|
66
|
-
username?: string
|
|
67
|
-
avatarUrl?: string
|
|
68
|
-
tts?: boolean
|
|
69
|
-
embeds?: DiscordEmbed[]
|
|
70
|
-
allowedMentions?: {
|
|
71
|
-
parse?: Array<'roles' | 'users' | 'everyone'>
|
|
72
|
-
roles?: string[]
|
|
73
|
-
users?: string[]
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
export declare class DiscordDriver extends BaseChatDriver {
|
|
77
|
-
name: string;
|
|
78
|
-
constructor(options?: DiscordConfig);
|
|
79
|
-
send(message: ChatMessage, options?: RenderOptions): Promise<ChatResult>;
|
|
80
|
-
}
|
|
81
|
-
export { DiscordDriver as Driver };
|
|
82
|
-
export default __dtsx_default_export__;
|
package/dist/drivers/slack.d.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { BaseChatDriver } from './base';
|
|
2
|
-
import type { ChatMessage, ChatResult, RenderOptions } from '@stacksjs/types';
|
|
3
|
-
/**
|
|
4
|
-
* Configure Slack with webhook URL or bot token.
|
|
5
|
-
*
|
|
6
|
-
* Validates that the webhook URL (when provided) is HTTPS pointing at
|
|
7
|
-
* Slack's webhook host. A misconfigured `http://` URL would leak the
|
|
8
|
-
* channel-specific token in plaintext to anyone watching network
|
|
9
|
-
* traffic; a typo'd domain would silently send messages to whatever
|
|
10
|
-
* server happens to accept them.
|
|
11
|
-
*/
|
|
12
|
-
export declare function configure(options: SlackConfig): void;
|
|
13
|
-
/**
|
|
14
|
-
* Send a message to Slack
|
|
15
|
-
*/
|
|
16
|
-
export declare function send(message: ChatMessage, options?: RenderOptions): Promise<ChatResult>;
|
|
17
|
-
/**
|
|
18
|
-
* Send a simple text message to a Slack channel via webhook
|
|
19
|
-
*/
|
|
20
|
-
export declare function sendWebhook(webhookUrl: string, text: string, options?: Partial<SlackMessage>): Promise<ChatResult>;
|
|
21
|
-
export declare const driver: SlackDriver;
|
|
22
|
-
declare const __dtsx_default_export__: {
|
|
23
|
-
send: typeof send;
|
|
24
|
-
sendWebhook: typeof sendWebhook;
|
|
25
|
-
configure: typeof configure;
|
|
26
|
-
SlackDriver: typeof SlackDriver
|
|
27
|
-
};
|
|
28
|
-
export declare interface SlackConfig {
|
|
29
|
-
webhookUrl?: string
|
|
30
|
-
botToken?: string
|
|
31
|
-
maxRetries?: number
|
|
32
|
-
retryTimeout?: number
|
|
33
|
-
}
|
|
34
|
-
export declare interface SlackMessage {
|
|
35
|
-
channel?: string
|
|
36
|
-
text?: string
|
|
37
|
-
blocks?: SlackBlock[]
|
|
38
|
-
attachments?: SlackAttachment[]
|
|
39
|
-
username?: string
|
|
40
|
-
iconEmoji?: string
|
|
41
|
-
iconUrl?: string
|
|
42
|
-
threadTs?: string
|
|
43
|
-
mrkdwn?: boolean
|
|
44
|
-
}
|
|
45
|
-
export declare interface SlackBlock {
|
|
46
|
-
type: 'section' | 'divider' | 'header' | 'context' | 'actions' | 'image'
|
|
47
|
-
text?: {
|
|
48
|
-
type: 'plain_text' | 'mrkdwn'
|
|
49
|
-
text: string
|
|
50
|
-
emoji?: boolean
|
|
51
|
-
}
|
|
52
|
-
accessory?: any
|
|
53
|
-
elements?: any[]
|
|
54
|
-
block_id?: string
|
|
55
|
-
}
|
|
56
|
-
export declare interface SlackAttachment {
|
|
57
|
-
color?: string
|
|
58
|
-
pretext?: string
|
|
59
|
-
author_name?: string
|
|
60
|
-
author_link?: string
|
|
61
|
-
author_icon?: string
|
|
62
|
-
title?: string
|
|
63
|
-
title_link?: string
|
|
64
|
-
text?: string
|
|
65
|
-
fields?: Array<{
|
|
66
|
-
title: string
|
|
67
|
-
value: string
|
|
68
|
-
short?: boolean
|
|
69
|
-
}>
|
|
70
|
-
image_url?: string
|
|
71
|
-
thumb_url?: string
|
|
72
|
-
footer?: string
|
|
73
|
-
footer_icon?: string
|
|
74
|
-
ts?: number
|
|
75
|
-
}
|
|
76
|
-
export declare class SlackDriver extends BaseChatDriver {
|
|
77
|
-
name: string;
|
|
78
|
-
constructor(options?: SlackConfig);
|
|
79
|
-
send(message: ChatMessage, options?: RenderOptions): Promise<ChatResult>;
|
|
80
|
-
}
|
|
81
|
-
export { SlackDriver as Driver };
|
|
82
|
-
export default __dtsx_default_export__;
|
package/dist/drivers/teams.d.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { BaseChatDriver } from './base';
|
|
2
|
-
import type { ChatMessage, ChatResult, RenderOptions } from '@stacksjs/types';
|
|
3
|
-
/**
|
|
4
|
-
* Configure Teams with webhook URL
|
|
5
|
-
*/
|
|
6
|
-
export declare function configure(options: TeamsConfig): void;
|
|
7
|
-
/**
|
|
8
|
-
* Send a message to Microsoft Teams
|
|
9
|
-
*/
|
|
10
|
-
export declare function send(message: ChatMessage, options?: RenderOptions): Promise<ChatResult>;
|
|
11
|
-
/**
|
|
12
|
-
* Send a simple text message to Teams via webhook
|
|
13
|
-
*/
|
|
14
|
-
export declare function sendWebhook(webhookUrl: string, text: string): Promise<ChatResult>;
|
|
15
|
-
/**
|
|
16
|
-
* Send an Adaptive Card to Teams via webhook
|
|
17
|
-
*/
|
|
18
|
-
export declare function sendCard(webhookUrl: string, card: TeamsAdaptiveCard, summary?: string): Promise<ChatResult>;
|
|
19
|
-
export declare const driver: TeamsDriver;
|
|
20
|
-
declare const __dtsx_default_export__: {
|
|
21
|
-
send: typeof send;
|
|
22
|
-
sendWebhook: typeof sendWebhook;
|
|
23
|
-
sendCard: typeof sendCard;
|
|
24
|
-
configure: typeof configure;
|
|
25
|
-
TeamsDriver: typeof TeamsDriver
|
|
26
|
-
};
|
|
27
|
-
export declare interface TeamsConfig {
|
|
28
|
-
webhookUrl?: string
|
|
29
|
-
maxRetries?: number
|
|
30
|
-
retryTimeout?: number
|
|
31
|
-
}
|
|
32
|
-
export declare interface TeamsAdaptiveCard {
|
|
33
|
-
type: 'AdaptiveCard'
|
|
34
|
-
version: string
|
|
35
|
-
body: TeamsCardElement[]
|
|
36
|
-
actions?: TeamsCardAction[]
|
|
37
|
-
$schema?: string
|
|
38
|
-
}
|
|
39
|
-
export declare interface TeamsCardElement {
|
|
40
|
-
type: 'TextBlock' | 'Image' | 'Container' | 'ColumnSet' | 'Column' | 'FactSet' | 'ImageSet'
|
|
41
|
-
text?: string
|
|
42
|
-
size?: 'Small' | 'Default' | 'Medium' | 'Large' | 'ExtraLarge'
|
|
43
|
-
weight?: 'Lighter' | 'Default' | 'Bolder'
|
|
44
|
-
color?: 'Default' | 'Dark' | 'Light' | 'Accent' | 'Good' | 'Warning' | 'Attention'
|
|
45
|
-
wrap?: boolean
|
|
46
|
-
url?: string
|
|
47
|
-
altText?: string
|
|
48
|
-
items?: TeamsCardElement[]
|
|
49
|
-
columns?: TeamsCardElement[]
|
|
50
|
-
width?: string
|
|
51
|
-
facts?: Array<{ title: string, value: string }>
|
|
52
|
-
images?: Array<{ type: 'Image', url: string, size?: string }>
|
|
53
|
-
}
|
|
54
|
-
export declare interface TeamsCardAction {
|
|
55
|
-
type: 'Action.OpenUrl' | 'Action.Submit' | 'Action.ShowCard'
|
|
56
|
-
title: string
|
|
57
|
-
url?: string
|
|
58
|
-
data?: Record<string, any>
|
|
59
|
-
card?: TeamsAdaptiveCard
|
|
60
|
-
}
|
|
61
|
-
export declare interface TeamsMessage {
|
|
62
|
-
type?: 'message'
|
|
63
|
-
summary?: string
|
|
64
|
-
text?: string
|
|
65
|
-
attachments?: Array<{
|
|
66
|
-
contentType: 'application/vnd.microsoft.card.adaptive'
|
|
67
|
-
content: TeamsAdaptiveCard
|
|
68
|
-
}>
|
|
69
|
-
}
|
|
70
|
-
export declare class TeamsDriver extends BaseChatDriver {
|
|
71
|
-
name: string;
|
|
72
|
-
constructor(options?: TeamsConfig);
|
|
73
|
-
send(message: ChatMessage, options?: RenderOptions): Promise<ChatResult>;
|
|
74
|
-
}
|
|
75
|
-
export { TeamsDriver as Driver };
|
|
76
|
-
export default __dtsx_default_export__;
|
package/dist/index.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import * as discord from './drivers/discord';
|
|
2
|
-
import * as slack from './drivers/slack';
|
|
3
|
-
import * as teams from './drivers/teams';
|
|
4
|
-
import type { ChatMessage, ChatResult } from '@stacksjs/types';
|
|
5
|
-
// Re-export types
|
|
6
|
-
export type { SlackConfig, SlackMessage, SlackBlock, SlackAttachment } from './drivers/slack';
|
|
7
|
-
export type { DiscordConfig, DiscordMessage, DiscordEmbed } from './drivers/discord';
|
|
8
|
-
export type { TeamsConfig, TeamsMessage, TeamsAdaptiveCard, TeamsCardElement, TeamsCardAction } from './drivers/teams';
|
|
9
|
-
/**
|
|
10
|
-
* Send a chat message using the specified driver
|
|
11
|
-
*/
|
|
12
|
-
export declare function send(message: ChatMessage, options?: SendOptions): Promise<ChatResult>;
|
|
13
|
-
/**
|
|
14
|
-
* Send a message to Slack via webhook
|
|
15
|
-
*/
|
|
16
|
-
export declare function sendToSlack(webhookUrl: string, text: string, options?: Parameters<typeof slack.sendWebhook>[2]): Promise<ChatResult>;
|
|
17
|
-
/**
|
|
18
|
-
* Send a message to Discord via webhook
|
|
19
|
-
*/
|
|
20
|
-
export declare function sendToDiscord(webhookUrl: string, content: string, options?: Parameters<typeof discord.sendWebhook>[2]): Promise<ChatResult>;
|
|
21
|
-
/**
|
|
22
|
-
* Send a message to Teams via webhook
|
|
23
|
-
*/
|
|
24
|
-
export declare function sendToTeams(webhookUrl: string, text: string): Promise<ChatResult>;
|
|
25
|
-
/**
|
|
26
|
-
* Configure Slack driver
|
|
27
|
-
*/
|
|
28
|
-
export declare function configureSlack(config: slack.SlackConfig): void;
|
|
29
|
-
/**
|
|
30
|
-
* Configure Discord driver
|
|
31
|
-
*/
|
|
32
|
-
export declare function configureDiscord(config: discord.DiscordConfig): void;
|
|
33
|
-
/**
|
|
34
|
-
* Configure Teams driver
|
|
35
|
-
*/
|
|
36
|
-
export declare function configureTeams(config: teams.TeamsConfig): void;
|
|
37
|
-
export declare interface SendOptions {
|
|
38
|
-
driver?: ChatDriver
|
|
39
|
-
}
|
|
40
|
-
export type ChatDriver = 'slack' | 'discord' | 'teams';
|
|
41
|
-
export * as discord from './drivers/discord';
|
|
42
|
-
export * as slack from './drivers/slack';
|
|
43
|
-
export * as teams from './drivers/teams';
|
package/dist/index.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
var w=Object.defineProperty;var h=(q)=>q;function f(q,z){this[q]=h.bind(null,z)}var B=(q,z)=>{for(var F in z)w(q,F,{get:z[F],enumerable:!0,configurable:!0,set:f.bind(z,F)})};var j={};B(j,{sendWebhook:()=>P,sendEmbed:()=>S,send:()=>Z,driver:()=>u,default:()=>k,configure:()=>N,Driver:()=>O,DiscordDriver:()=>O});import{log as R}from"@stacksjs/logging";import{log as D}from"@stacksjs/logging";class K{config;constructor(q){this.config={maxRetries:q?.maxRetries||3,retryTimeout:q?.retryTimeout||1000,...q}}configure(q){this.config={...this.config,...q}}validateMessage(q){if(!q.to)throw Error("Message recipient is required");if(!q.content&&!q.template)throw Error("Either message content or template is required");return!0}async handleError(q,z){let F=q instanceof Error?q:Error(String(q));D.error(`[${this.name}] Message sending failed`,{error:F.message,stack:F.stack?.replace(/https?:\/\/[^\s)\]"']+/g,"[REDACTED-URL]"),to:z.to,subject:z.subject});let G={message:`Message sending failed: ${F.message}`,success:!1,provider:this.name};if(z.onError){let H=z.onError(F),J=H instanceof Promise?await H:H;G={...G,...J,success:!1,provider:this.name}}return G}async handleSuccess(q,z){let F={message:"Message sent successfully",success:!0,provider:this.name,messageId:z};try{if(q.handle){let G=q.handle(),H=G instanceof Promise?await G:G;F={...F,...H,success:!0,provider:this.name,messageId:z}}if(q.onSuccess){let G=q.onSuccess(),H=G instanceof Promise?await G:G;F={...F,...H,success:!0,provider:this.name,messageId:z}}}catch(G){return this.handleError(G,q)}return F}}var L={};function N(q){if(q.webhookUrl){let z;try{z=new URL(q.webhookUrl)}catch{throw Error(`[chat/discord] webhookUrl is not a valid URL: ${q.webhookUrl}`)}if(z.protocol!=="https:")throw Error("[chat/discord] webhookUrl must use https://");if(!/(?:^|\.)discord(?:app)?\.com$/i.test(z.hostname))throw Error(`[chat/discord] webhookUrl host "${z.hostname}" is not a Discord-owned domain.`)}L={...L,...q}}class O extends K{name="discord";constructor(q){super({maxRetries:q?.maxRetries??3,retryTimeout:q?.retryTimeout??1000});if(q)N(q)}async send(q,z){let F={provider:this.name,to:q.to,subject:q.subject||"No subject"};R.info("Sending message via Discord...",F);try{return this.validateMessage(q),await this.sendWithRetry(q,z)}catch(G){return this.handleError(G,q)}}async sendWithRetry(q,z,F=1){try{let G=await this.sendMessage(q,z);return this.handleSuccess(q,G.id)}catch(G){if(F<this.config.maxRetries)return R.warn(`[${this.name}] Message send failed, retrying (${F}/${this.config.maxRetries})`),await new Promise((H)=>setTimeout(H,this.config.retryTimeout)),this.sendWithRetry(q,z,F+1);throw G}}async sendMessage(q,z){if(L.webhookUrl)return this.sendViaWebhook(q);if(L.botToken)return this.sendViaBotToken(q);throw Error("Discord not configured: provide webhookUrl or botToken")}async sendViaWebhook(q){let z={content:q.content,username:q.from};if(q.subject||q.template)z.embeds=[this.buildEmbed(q)];let F=await fetch(L.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(z)});if(!F.ok){let H=await F.text();throw Error(`Discord webhook failed: ${F.status} - ${H}`)}if(F.status===204)return{};return{id:(await F.json()).id}}async sendViaBotToken(q){let z=q.to,F={content:q.content};if(q.subject||q.template)F.embeds=[this.buildEmbed(q)];let G=await fetch(`https://discord.com/api/v10/channels/${z}/messages`,{method:"POST",headers:{Authorization:`Bot ${L.botToken}`,"Content-Type":"application/json"},body:JSON.stringify(F)});if(!G.ok){let J=await G.json();throw Error(`Discord API failed: ${G.status} - ${J.message}`)}return{id:(await G.json()).id}}buildEmbed(q){let z={};if(q.subject)z.title=q.subject;if(q.content)z.description=q.content;return z.color=5793266,z.timestamp=new Date().toISOString(),z}}async function Z(q,z){return new O().send(q,z)}async function P(q,z,F){try{let G={content:z,...F},H=await fetch(q,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(G)});if(!H.ok){let J=await H.text();return{success:!1,provider:"discord",message:`Webhook failed: ${H.status} - ${J}`}}return{success:!0,provider:"discord",message:"Message sent successfully"}}catch(G){return{success:!1,provider:"discord",message:(G instanceof Error?G:Error(String(G))).message}}}async function S(q,z,F){return P(q,"",{...F,embeds:[z]})}var u=new O,k={send:Z,sendWebhook:P,sendEmbed:S,configure:N,DiscordDriver:O};var W={};B(W,{sendWebhook:()=>$,send:()=>_,driver:()=>b,default:()=>v,configure:()=>Q,SlackDriver:()=>V,Driver:()=>V});import{log as y}from"@stacksjs/logging";var M={};function Q(q){if(q.webhookUrl){let z;try{z=new URL(q.webhookUrl)}catch{throw Error(`[chat/slack] webhookUrl is not a valid URL: ${q.webhookUrl}`)}if(z.protocol!=="https:")throw Error("[chat/slack] webhookUrl must use https:// \u2014 Slack does not accept plain HTTP webhooks.");if(!/(?:^|\.)slack\.com$/i.test(z.hostname))throw Error(`[chat/slack] webhookUrl host "${z.hostname}" is not a Slack-owned domain.`)}M={...M,...q}}class V extends K{name="slack";constructor(q){super({maxRetries:q?.maxRetries??3,retryTimeout:q?.retryTimeout??1000});if(q)Q(q)}async send(q,z){let F={provider:this.name,to:q.to,subject:q.subject||"No subject"};y.info("Sending message via Slack...",F);try{return this.validateMessage(q),await this.sendWithRetry(q,z)}catch(G){return this.handleError(G,q)}}async sendWithRetry(q,z,F=1){try{let G=await this.sendMessage(q,z);return this.handleSuccess(q,G.ts)}catch(G){if(F<this.config.maxRetries)return y.warn(`[${this.name}] Message send failed, retrying (${F}/${this.config.maxRetries})`),await new Promise((H)=>setTimeout(H,this.config.retryTimeout)),this.sendWithRetry(q,z,F+1);throw G}}async sendMessage(q,z){if(M.webhookUrl)return this.sendViaWebhook(q);if(M.botToken)return this.sendViaBotToken(q);throw Error("Slack not configured: provide webhookUrl or botToken")}async sendViaWebhook(q){let F=q.content||q.subject||"",H={text:F.length>40000?`${F.slice(0,39986)}\u2026 [truncated]`:F,username:q.from,mrkdwn:!0};if(q.template)H.blocks=this.buildBlocks(q);let J=await fetch(M.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(H)});if(!J.ok){let x=await J.text();throw Error(`Slack webhook failed: ${J.status} - ${x}`)}return{}}async sendViaBotToken(q){let z={channel:q.to,text:q.content||q.subject,mrkdwn:!0};if(q.template)z.blocks=this.buildBlocks(q);let F=await fetch("https://slack.com/api/chat.postMessage",{method:"POST",headers:{Authorization:`Bearer ${M.botToken}`,"Content-Type":"application/json"},body:JSON.stringify(z)});if(!F.ok)throw Error(`Slack API failed: ${F.status}`);let G=await F.json();if(!G.ok)throw Error(`Slack API error: ${G.error}`);return{ts:G.ts}}buildBlocks(q){let z=[];if(q.subject)z.push({type:"header",text:{type:"plain_text",text:q.subject,emoji:!0}});if(q.content)z.push({type:"section",text:{type:"mrkdwn",text:q.content}});return z}}async function _(q,z){return new V().send(q,z)}async function $(q,z,F){try{let G={text:z,...F},H=await fetch(q,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(G)});if(!H.ok){let J=await H.text();return{success:!1,provider:"slack",message:`Webhook failed: ${H.status} - ${J}`}}return{success:!0,provider:"slack",message:"Message sent successfully"}}catch(G){return{success:!1,provider:"slack",message:(G instanceof Error?G:Error(String(G))).message}}}var b=new V,v={send:_,sendWebhook:$,configure:Q,SlackDriver:V};var C={};B(C,{sendWebhook:()=>E,sendCard:()=>T,send:()=>A,driver:()=>d,default:()=>c,configure:()=>X,TeamsDriver:()=>Y,Driver:()=>Y});import{log as U}from"@stacksjs/logging";var I={};function X(q){I={...I,...q}}class Y extends K{name="teams";constructor(q){super({maxRetries:q?.maxRetries??3,retryTimeout:q?.retryTimeout??1000});if(q)X(q)}async send(q,z){let F={provider:this.name,to:q.to,subject:q.subject||"No subject"};U.info("Sending message via Microsoft Teams...",F);try{return this.validateMessage(q),await this.sendWithRetry(q,z)}catch(G){return this.handleError(G,q)}}async sendWithRetry(q,z,F=1){try{return await this.sendMessage(q,z),this.handleSuccess(q)}catch(G){if(F<this.config.maxRetries)return U.warn(`[${this.name}] Message send failed, retrying (${F}/${this.config.maxRetries})`),await new Promise((H)=>setTimeout(H,this.config.retryTimeout)),this.sendWithRetry(q,z,F+1);throw G}}async sendMessage(q,z){let F=I.webhookUrl||q.to;if(!F||!F.includes("webhook.office.com"))throw Error("Teams webhook URL not configured or invalid");let G=this.buildPayload(q),H=await fetch(F,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(G)});if(!H.ok){let J=await H.text();throw Error(`Teams webhook failed: ${H.status} - ${J}`)}}buildPayload(q){if(!q.subject&&!q.template)return{type:"message",text:q.content||""};let z=this.buildAdaptiveCard(q);return{type:"message",summary:q.subject||q.content?.substring(0,50)||"Notification",attachments:[{contentType:"application/vnd.microsoft.card.adaptive",content:z}]}}buildAdaptiveCard(q){let z=[];if(q.subject)z.push({type:"TextBlock",text:q.subject,size:"Large",weight:"Bolder",wrap:!0});if(q.content)z.push({type:"TextBlock",text:q.content,wrap:!0});return z.push({type:"TextBlock",text:new Date().toLocaleString(),size:"Small",color:"Dark",wrap:!0}),{type:"AdaptiveCard",version:"1.4",$schema:"http://adaptivecards.io/schemas/adaptive-card.json",body:z}}}async function A(q,z){return new Y().send(q,z)}async function E(q,z){try{let G=await fetch(q,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"message",text:z})});if(!G.ok){let H=await G.text();return{success:!1,provider:"teams",message:`Webhook failed: ${G.status} - ${H}`}}return{success:!0,provider:"teams",message:"Message sent successfully"}}catch(F){return{success:!1,provider:"teams",message:(F instanceof Error?F:Error(String(F))).message}}}async function T(q,z,F){try{let H=await fetch(q,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"message",summary:F||"Notification",attachments:[{contentType:"application/vnd.microsoft.card.adaptive",content:z}]})});if(!H.ok){let J=await H.text();return{success:!1,provider:"teams",message:`Webhook failed: ${H.status} - ${J}`}}return{success:!0,provider:"teams",message:"Card sent successfully"}}catch(G){return{success:!1,provider:"teams",message:(G instanceof Error?G:Error(String(G))).message}}}var d=new Y,c={send:A,sendWebhook:E,sendCard:T,configure:X,TeamsDriver:Y};async function o(q,z={}){let F=z.driver??"slack";switch(F){case"slack":return _(q);case"discord":return Z(q);case"teams":return A(q);default:return{success:!1,provider:F,message:`Unknown chat driver: ${F}`}}}async function s(q,z,F){return $(q,z,F)}async function e(q,z,F){return P(q,z,F)}async function qq(q,z){return E(q,z)}function zq(q){Q(q)}function Fq(q){N(q)}function Gq(q){X(q)}export{C as teams,W as slack,qq as sendToTeams,s as sendToSlack,e as sendToDiscord,o as send,j as discord,Gq as configureTeams,zq as configureSlack,Fq as configureDiscord};
|