@auxiora/channels 1.0.0
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/LICENSE +191 -0
- package/dist/adapters/bluebubbles.d.ts +63 -0
- package/dist/adapters/bluebubbles.d.ts.map +1 -0
- package/dist/adapters/bluebubbles.js +197 -0
- package/dist/adapters/bluebubbles.js.map +1 -0
- package/dist/adapters/discord.d.ts +27 -0
- package/dist/adapters/discord.d.ts.map +1 -0
- package/dist/adapters/discord.js +202 -0
- package/dist/adapters/discord.js.map +1 -0
- package/dist/adapters/email.d.ts +39 -0
- package/dist/adapters/email.d.ts.map +1 -0
- package/dist/adapters/email.js +359 -0
- package/dist/adapters/email.js.map +1 -0
- package/dist/adapters/googlechat.d.ts +77 -0
- package/dist/adapters/googlechat.d.ts.map +1 -0
- package/dist/adapters/googlechat.js +232 -0
- package/dist/adapters/googlechat.js.map +1 -0
- package/dist/adapters/matrix.d.ts +37 -0
- package/dist/adapters/matrix.d.ts.map +1 -0
- package/dist/adapters/matrix.js +262 -0
- package/dist/adapters/matrix.js.map +1 -0
- package/dist/adapters/signal.d.ts +32 -0
- package/dist/adapters/signal.d.ts.map +1 -0
- package/dist/adapters/signal.js +216 -0
- package/dist/adapters/signal.js.map +1 -0
- package/dist/adapters/slack.d.ts +29 -0
- package/dist/adapters/slack.d.ts.map +1 -0
- package/dist/adapters/slack.js +202 -0
- package/dist/adapters/slack.js.map +1 -0
- package/dist/adapters/teams.d.ts +66 -0
- package/dist/adapters/teams.d.ts.map +1 -0
- package/dist/adapters/teams.js +227 -0
- package/dist/adapters/teams.js.map +1 -0
- package/dist/adapters/telegram.d.ts +28 -0
- package/dist/adapters/telegram.d.ts.map +1 -0
- package/dist/adapters/telegram.js +170 -0
- package/dist/adapters/telegram.js.map +1 -0
- package/dist/adapters/twilio.d.ts +63 -0
- package/dist/adapters/twilio.d.ts.map +1 -0
- package/dist/adapters/twilio.js +193 -0
- package/dist/adapters/twilio.js.map +1 -0
- package/dist/adapters/whatsapp.d.ts +99 -0
- package/dist/adapters/whatsapp.d.ts.map +1 -0
- package/dist/adapters/whatsapp.js +218 -0
- package/dist/adapters/whatsapp.js.map +1 -0
- package/dist/adapters/zalo.d.ts +64 -0
- package/dist/adapters/zalo.d.ts.map +1 -0
- package/dist/adapters/zalo.js +216 -0
- package/dist/adapters/zalo.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/manager.d.ts +35 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +127 -0
- package/dist/manager.js.map +1 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +32 -0
- package/src/adapters/bluebubbles.ts +294 -0
- package/src/adapters/discord.ts +253 -0
- package/src/adapters/email.ts +457 -0
- package/src/adapters/googlechat.ts +364 -0
- package/src/adapters/matrix.ts +376 -0
- package/src/adapters/signal.ts +313 -0
- package/src/adapters/slack.ts +252 -0
- package/src/adapters/teams.ts +320 -0
- package/src/adapters/telegram.ts +208 -0
- package/src/adapters/twilio.ts +256 -0
- package/src/adapters/whatsapp.ts +342 -0
- package/src/adapters/zalo.ts +319 -0
- package/src/index.ts +78 -0
- package/src/manager.ts +180 -0
- package/src/types.ts +84 -0
- package/tests/bluebubbles.test.ts +438 -0
- package/tests/email.test.ts +136 -0
- package/tests/googlechat.test.ts +439 -0
- package/tests/matrix.test.ts +564 -0
- package/tests/signal.test.ts +404 -0
- package/tests/slack.test.ts +343 -0
- package/tests/teams.test.ts +429 -0
- package/tests/twilio.test.ts +269 -0
- package/tests/whatsapp.test.ts +530 -0
- package/tests/zalo.test.ts +499 -0
- package/tsconfig.json +8 -0
- package/tsconfig.tsbuildinfo +1 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Types
|
|
2
|
+
export type {
|
|
3
|
+
ChannelType,
|
|
4
|
+
ChannelAdapter,
|
|
5
|
+
ChannelConfig,
|
|
6
|
+
InboundMessage,
|
|
7
|
+
OutboundMessage,
|
|
8
|
+
SendResult,
|
|
9
|
+
Attachment,
|
|
10
|
+
} from './types.js';
|
|
11
|
+
|
|
12
|
+
// Adapters
|
|
13
|
+
export {
|
|
14
|
+
DiscordAdapter,
|
|
15
|
+
type DiscordAdapterConfig,
|
|
16
|
+
} from './adapters/discord.js';
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
TelegramAdapter,
|
|
20
|
+
type TelegramAdapterConfig,
|
|
21
|
+
} from './adapters/telegram.js';
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
SlackAdapter,
|
|
25
|
+
type SlackAdapterConfig,
|
|
26
|
+
} from './adapters/slack.js';
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
TwilioAdapter,
|
|
30
|
+
type TwilioAdapterConfig,
|
|
31
|
+
type TwilioWebhookBody,
|
|
32
|
+
} from './adapters/twilio.js';
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
MatrixAdapter,
|
|
36
|
+
type MatrixAdapterConfig,
|
|
37
|
+
} from './adapters/matrix.js';
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
SignalAdapter,
|
|
41
|
+
type SignalAdapterConfig,
|
|
42
|
+
} from './adapters/signal.js';
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
EmailAdapter,
|
|
46
|
+
type EmailAdapterConfig,
|
|
47
|
+
} from './adapters/email.js';
|
|
48
|
+
|
|
49
|
+
export {
|
|
50
|
+
TeamsAdapter,
|
|
51
|
+
type TeamsAdapterConfig,
|
|
52
|
+
} from './adapters/teams.js';
|
|
53
|
+
|
|
54
|
+
export {
|
|
55
|
+
WhatsAppAdapter,
|
|
56
|
+
type WhatsAppAdapterConfig,
|
|
57
|
+
} from './adapters/whatsapp.js';
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
GoogleChatAdapter,
|
|
61
|
+
type GoogleChatAdapterConfig,
|
|
62
|
+
} from './adapters/googlechat.js';
|
|
63
|
+
|
|
64
|
+
export {
|
|
65
|
+
BlueBubblesAdapter,
|
|
66
|
+
type BlueBubblesAdapterConfig,
|
|
67
|
+
} from './adapters/bluebubbles.js';
|
|
68
|
+
|
|
69
|
+
export {
|
|
70
|
+
ZaloAdapter,
|
|
71
|
+
type ZaloAdapterConfig,
|
|
72
|
+
} from './adapters/zalo.js';
|
|
73
|
+
|
|
74
|
+
// Manager
|
|
75
|
+
export {
|
|
76
|
+
ChannelManager,
|
|
77
|
+
type ChannelManagerConfig,
|
|
78
|
+
} from './manager.js';
|
package/src/manager.ts
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { audit } from '@auxiora/audit';
|
|
2
|
+
import { getLogger } from '@auxiora/logger';
|
|
3
|
+
|
|
4
|
+
const logger = getLogger('channels');
|
|
5
|
+
import type {
|
|
6
|
+
ChannelAdapter,
|
|
7
|
+
ChannelType,
|
|
8
|
+
ChannelConfig,
|
|
9
|
+
InboundMessage,
|
|
10
|
+
OutboundMessage,
|
|
11
|
+
SendResult,
|
|
12
|
+
} from './types.js';
|
|
13
|
+
import { DiscordAdapter, type DiscordAdapterConfig } from './adapters/discord.js';
|
|
14
|
+
import { TelegramAdapter, type TelegramAdapterConfig } from './adapters/telegram.js';
|
|
15
|
+
import { SlackAdapter, type SlackAdapterConfig } from './adapters/slack.js';
|
|
16
|
+
import { TwilioAdapter, type TwilioAdapterConfig } from './adapters/twilio.js';
|
|
17
|
+
import { GoogleChatAdapter, type GoogleChatAdapterConfig } from './adapters/googlechat.js';
|
|
18
|
+
import { BlueBubblesAdapter, type BlueBubblesAdapterConfig } from './adapters/bluebubbles.js';
|
|
19
|
+
import { ZaloAdapter, type ZaloAdapterConfig } from './adapters/zalo.js';
|
|
20
|
+
|
|
21
|
+
export interface ChannelManagerConfig {
|
|
22
|
+
discord?: DiscordAdapterConfig;
|
|
23
|
+
telegram?: TelegramAdapterConfig;
|
|
24
|
+
slack?: SlackAdapterConfig;
|
|
25
|
+
twilio?: TwilioAdapterConfig;
|
|
26
|
+
googlechat?: GoogleChatAdapterConfig;
|
|
27
|
+
bluebubbles?: BlueBubblesAdapterConfig;
|
|
28
|
+
zalo?: ZaloAdapterConfig;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class ChannelManager {
|
|
32
|
+
private adapters: Map<ChannelType, ChannelAdapter> = new Map();
|
|
33
|
+
private messageHandler?: (message: InboundMessage) => Promise<void>;
|
|
34
|
+
private errorHandler?: (error: Error, channelType: ChannelType) => void;
|
|
35
|
+
|
|
36
|
+
constructor(config: ChannelManagerConfig) {
|
|
37
|
+
// Initialize configured adapters
|
|
38
|
+
if (config.discord?.token) {
|
|
39
|
+
this.adapters.set('discord', new DiscordAdapter(config.discord));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (config.telegram?.token) {
|
|
43
|
+
this.adapters.set('telegram', new TelegramAdapter(config.telegram));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (config.slack?.botToken && config.slack?.appToken) {
|
|
47
|
+
this.adapters.set('slack', new SlackAdapter(config.slack));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (config.twilio?.accountSid && config.twilio?.authToken) {
|
|
51
|
+
this.adapters.set('twilio', new TwilioAdapter(config.twilio));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (config.googlechat?.serviceAccountKey) {
|
|
55
|
+
this.adapters.set('googlechat', new GoogleChatAdapter(config.googlechat));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (config.bluebubbles?.serverUrl && config.bluebubbles?.password) {
|
|
59
|
+
this.adapters.set('bluebubbles', new BlueBubblesAdapter(config.bluebubbles));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (config.zalo?.oaAccessToken && config.zalo?.oaSecretKey) {
|
|
63
|
+
this.adapters.set('zalo', new ZaloAdapter(config.zalo));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async connectAll(): Promise<void> {
|
|
68
|
+
const results = await Promise.allSettled(
|
|
69
|
+
Array.from(this.adapters.entries()).map(async ([type, adapter]) => {
|
|
70
|
+
try {
|
|
71
|
+
// Set up message handler
|
|
72
|
+
adapter.onMessage(async (message) => {
|
|
73
|
+
if (this.messageHandler) {
|
|
74
|
+
await this.messageHandler(message);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Set up error handler
|
|
79
|
+
adapter.onError((error) => {
|
|
80
|
+
if (this.errorHandler) {
|
|
81
|
+
this.errorHandler(error, type);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
await adapter.connect();
|
|
86
|
+
logger.info(`Connected to ${adapter.name}`);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
logger.error(`Failed to connect to ${adapter.name}`, { error: error instanceof Error ? error : new Error(String(error)) });
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const failures = results.filter((r) => r.status === 'rejected');
|
|
95
|
+
if (failures.length > 0) {
|
|
96
|
+
logger.warn(`${failures.length} channel(s) failed to connect`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async disconnectAll(): Promise<void> {
|
|
101
|
+
await Promise.allSettled(
|
|
102
|
+
Array.from(this.adapters.values()).map((adapter) => adapter.disconnect())
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async connect(type: ChannelType): Promise<void> {
|
|
107
|
+
const adapter = this.adapters.get(type);
|
|
108
|
+
if (!adapter) {
|
|
109
|
+
throw new Error(`Channel not configured: ${type}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
adapter.onMessage(async (message) => {
|
|
113
|
+
if (this.messageHandler) {
|
|
114
|
+
await this.messageHandler(message);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
adapter.onError((error) => {
|
|
119
|
+
if (this.errorHandler) {
|
|
120
|
+
this.errorHandler(error, type);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
await adapter.connect();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async disconnect(type: ChannelType): Promise<void> {
|
|
128
|
+
const adapter = this.adapters.get(type);
|
|
129
|
+
if (adapter) {
|
|
130
|
+
await adapter.disconnect();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async send(
|
|
135
|
+
channelType: ChannelType,
|
|
136
|
+
channelId: string,
|
|
137
|
+
message: OutboundMessage
|
|
138
|
+
): Promise<SendResult> {
|
|
139
|
+
const adapter = this.adapters.get(channelType);
|
|
140
|
+
if (!adapter) {
|
|
141
|
+
return { success: false, error: `Channel not configured: ${channelType}` };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (!adapter.isConnected()) {
|
|
145
|
+
return { success: false, error: `Channel not connected: ${channelType}` };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return adapter.send(channelId, message);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async startTyping(channelType: ChannelType, channelId: string): Promise<() => void> {
|
|
152
|
+
const adapter = this.adapters.get(channelType);
|
|
153
|
+
if (!adapter?.startTyping || !adapter.isConnected()) {
|
|
154
|
+
return () => {};
|
|
155
|
+
}
|
|
156
|
+
return adapter.startTyping(channelId);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
getAdapter<T extends ChannelAdapter>(type: ChannelType): T | undefined {
|
|
160
|
+
return this.adapters.get(type) as T | undefined;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
getConnectedChannels(): ChannelType[] {
|
|
164
|
+
return Array.from(this.adapters.entries())
|
|
165
|
+
.filter(([_, adapter]) => adapter.isConnected())
|
|
166
|
+
.map(([type]) => type);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
getConfiguredChannels(): ChannelType[] {
|
|
170
|
+
return Array.from(this.adapters.keys());
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
onMessage(handler: (message: InboundMessage) => Promise<void>): void {
|
|
174
|
+
this.messageHandler = handler;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
onError(handler: (error: Error, channelType: ChannelType) => void): void {
|
|
178
|
+
this.errorHandler = handler;
|
|
179
|
+
}
|
|
180
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export type ChannelType = 'discord' | 'telegram' | 'slack' | 'twilio' | 'webchat' | 'matrix' | 'signal' | 'email' | 'teams' | 'whatsapp' | 'googlechat' | 'bluebubbles' | 'zalo';
|
|
2
|
+
|
|
3
|
+
export interface InboundMessage {
|
|
4
|
+
id: string;
|
|
5
|
+
channelType: ChannelType;
|
|
6
|
+
channelId: string; // Server/chat ID
|
|
7
|
+
senderId: string; // User ID
|
|
8
|
+
senderName?: string; // Display name
|
|
9
|
+
content: string;
|
|
10
|
+
timestamp: number;
|
|
11
|
+
replyToId?: string; // If replying to a message
|
|
12
|
+
attachments?: Attachment[];
|
|
13
|
+
raw?: unknown; // Original platform message
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface Attachment {
|
|
17
|
+
type: 'image' | 'audio' | 'video' | 'file';
|
|
18
|
+
url?: string;
|
|
19
|
+
data?: Buffer;
|
|
20
|
+
mimeType?: string;
|
|
21
|
+
filename?: string;
|
|
22
|
+
size?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface OutboundMessage {
|
|
26
|
+
content: string;
|
|
27
|
+
replyToId?: string;
|
|
28
|
+
attachments?: Attachment[];
|
|
29
|
+
formatting?: {
|
|
30
|
+
markdown?: boolean;
|
|
31
|
+
html?: boolean;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface SendResult {
|
|
36
|
+
success: boolean;
|
|
37
|
+
messageId?: string;
|
|
38
|
+
error?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ChannelAdapter {
|
|
42
|
+
readonly type: ChannelType;
|
|
43
|
+
readonly name: string;
|
|
44
|
+
|
|
45
|
+
// Lifecycle
|
|
46
|
+
connect(): Promise<void>;
|
|
47
|
+
disconnect(): Promise<void>;
|
|
48
|
+
isConnected(): boolean;
|
|
49
|
+
|
|
50
|
+
// Messaging
|
|
51
|
+
send(channelId: string, message: OutboundMessage): Promise<SendResult>;
|
|
52
|
+
|
|
53
|
+
// Typing indicator — returns a cleanup function to stop the indicator
|
|
54
|
+
startTyping?(channelId: string): Promise<() => void>;
|
|
55
|
+
|
|
56
|
+
// Events
|
|
57
|
+
onMessage(handler: (message: InboundMessage) => Promise<void>): void;
|
|
58
|
+
onError(handler: (error: Error) => void): void;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface ChannelConfig {
|
|
62
|
+
discord?: {
|
|
63
|
+
token: string;
|
|
64
|
+
mentionOnly?: boolean;
|
|
65
|
+
allowedGuilds?: string[];
|
|
66
|
+
};
|
|
67
|
+
telegram?: {
|
|
68
|
+
token: string;
|
|
69
|
+
webhookUrl?: string;
|
|
70
|
+
allowedChats?: string[];
|
|
71
|
+
};
|
|
72
|
+
slack?: {
|
|
73
|
+
botToken: string;
|
|
74
|
+
appToken: string;
|
|
75
|
+
signingSecret?: string;
|
|
76
|
+
};
|
|
77
|
+
twilio?: {
|
|
78
|
+
accountSid: string;
|
|
79
|
+
authToken: string;
|
|
80
|
+
phoneNumber: string; // Your Twilio phone number
|
|
81
|
+
webhookUrl?: string; // For incoming messages
|
|
82
|
+
whatsappNumber?: string; // WhatsApp-enabled number
|
|
83
|
+
};
|
|
84
|
+
}
|