@operor/provider-telegram 0.1.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.
@@ -0,0 +1,24 @@
1
+ import EventEmitter from "eventemitter3";
2
+ import { MessageProvider, OutgoingMessage } from "@operor/core";
3
+
4
+ //#region src/TelegramProvider.d.ts
5
+ interface TelegramProviderConfig {
6
+ botToken: string;
7
+ /** Optional webhook URL. If not set, uses long polling. */
8
+ webhookUrl?: string;
9
+ }
10
+ declare class TelegramProvider extends EventEmitter implements MessageProvider {
11
+ readonly name = "telegram";
12
+ private bot;
13
+ private config;
14
+ private connected;
15
+ constructor(config: TelegramProviderConfig);
16
+ connect(): Promise<void>;
17
+ disconnect(): Promise<void>;
18
+ sendTypingIndicator(to: string): Promise<void>;
19
+ sendMessage(to: string, message: OutgoingMessage): Promise<void>;
20
+ isActive(): boolean;
21
+ }
22
+ //#endregion
23
+ export { TelegramProvider, type TelegramProviderConfig };
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/TelegramProvider.ts"],"mappings":";;;;UAIiB,sBAAA;EACf,QAAA;EADe;EAGf,UAAA;AAAA;AAAA,cAGW,gBAAA,SAAyB,YAAA,YAAwB,eAAA;EAAA,SAC5C,IAAA;EAAA,QACR,GAAA;EAAA,QACA,MAAA;EAAA,QACA,SAAA;cAEI,MAAA,EAAQ,sBAAA;EAMd,OAAA,CAAA,GAAW,OAAA;EAoDX,UAAA,CAAA,GAAc,OAAA;EAMd,mBAAA,CAAoB,EAAA,WAAa,OAAA;EAWjC,WAAA,CAAY,EAAA,UAAY,OAAA,EAAS,eAAA,GAAkB,OAAA;EAczD,QAAA,CAAA;AAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,81 @@
1
+ import EventEmitter from "eventemitter3";
2
+ import { Bot } from "grammy";
3
+
4
+ //#region src/TelegramProvider.ts
5
+ var TelegramProvider = class extends EventEmitter {
6
+ name = "telegram";
7
+ bot;
8
+ config;
9
+ connected = false;
10
+ constructor(config) {
11
+ super();
12
+ this.config = config;
13
+ this.bot = new Bot(config.botToken);
14
+ }
15
+ async connect() {
16
+ this.bot.on("message:text", (ctx) => {
17
+ const msg = {
18
+ id: String(ctx.message.message_id),
19
+ from: String(ctx.from?.id || ctx.chat.id),
20
+ text: ctx.message.text,
21
+ timestamp: ctx.message.date * 1e3,
22
+ channel: "telegram",
23
+ provider: this.name,
24
+ metadata: {
25
+ chatId: ctx.chat.id,
26
+ username: ctx.from?.username,
27
+ firstName: ctx.from?.first_name,
28
+ lastName: ctx.from?.last_name
29
+ }
30
+ };
31
+ console.log(`\nšŸ“„ [Telegram] New message from ${ctx.from?.first_name || ctx.from?.username || msg.from}`);
32
+ console.log(` Message: "${msg.text}"`);
33
+ this.emit("message", msg);
34
+ });
35
+ this.bot.catch((err) => {
36
+ console.error("āŒ [Telegram] Bot error:", err.message);
37
+ this.emit("error", err);
38
+ });
39
+ if (this.config.webhookUrl) {
40
+ await this.bot.api.setWebhook(this.config.webhookUrl);
41
+ console.log(`āœ… Telegram bot connected (webhook: ${this.config.webhookUrl})`);
42
+ } else {
43
+ this.bot.start({ onStart: () => {
44
+ console.log("āœ… Telegram bot connected (long polling)");
45
+ this.connected = true;
46
+ this.emit("ready");
47
+ } });
48
+ this.connected = true;
49
+ return;
50
+ }
51
+ this.connected = true;
52
+ this.emit("ready");
53
+ }
54
+ async disconnect() {
55
+ await this.bot.stop();
56
+ this.connected = false;
57
+ console.log("Telegram bot disconnected");
58
+ }
59
+ async sendTypingIndicator(to) {
60
+ if (!this.connected) return;
61
+ const chatId = parseInt(to, 10);
62
+ if (isNaN(chatId)) return;
63
+ try {
64
+ await this.bot.api.sendChatAction(chatId, "typing");
65
+ } catch {}
66
+ }
67
+ async sendMessage(to, message) {
68
+ if (!this.connected) throw new Error("Telegram bot not connected");
69
+ const chatId = parseInt(to, 10);
70
+ if (isNaN(chatId)) throw new Error(`Invalid Telegram chat ID: "${to}" — must be numeric`);
71
+ await this.bot.api.sendMessage(chatId, message.text);
72
+ console.log(`šŸ“¤ [Telegram] Sent reply to ${to}`);
73
+ }
74
+ isActive() {
75
+ return this.connected;
76
+ }
77
+ };
78
+
79
+ //#endregion
80
+ export { TelegramProvider };
81
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/TelegramProvider.ts"],"sourcesContent":["import EventEmitter from 'eventemitter3';\nimport { Bot } from 'grammy';\nimport type { MessageProvider, IncomingMessage, OutgoingMessage } from '@operor/core';\n\nexport interface TelegramProviderConfig {\n botToken: string;\n /** Optional webhook URL. If not set, uses long polling. */\n webhookUrl?: string;\n}\n\nexport class TelegramProvider extends EventEmitter implements MessageProvider {\n public readonly name = 'telegram';\n private bot: Bot;\n private config: TelegramProviderConfig;\n private connected = false;\n\n constructor(config: TelegramProviderConfig) {\n super();\n this.config = config;\n this.bot = new Bot(config.botToken);\n }\n\n async connect(): Promise<void> {\n // Listen for text messages\n this.bot.on('message:text', (ctx) => {\n const msg: IncomingMessage = {\n id: String(ctx.message.message_id),\n from: String(ctx.from?.id || ctx.chat.id),\n text: ctx.message.text,\n timestamp: ctx.message.date * 1000,\n channel: 'telegram',\n provider: this.name,\n metadata: {\n chatId: ctx.chat.id,\n username: ctx.from?.username,\n firstName: ctx.from?.first_name,\n lastName: ctx.from?.last_name,\n },\n };\n\n console.log(`\\nšŸ“„ [Telegram] New message from ${ctx.from?.first_name || ctx.from?.username || msg.from}`);\n console.log(` Message: \"${msg.text}\"`);\n\n this.emit('message', msg);\n });\n\n // Error handling\n this.bot.catch((err) => {\n console.error('āŒ [Telegram] Bot error:', err.message);\n this.emit('error', err);\n });\n\n // Start bot\n if (this.config.webhookUrl) {\n await this.bot.api.setWebhook(this.config.webhookUrl);\n console.log(`āœ… Telegram bot connected (webhook: ${this.config.webhookUrl})`);\n } else {\n // Long polling for development — non-blocking start\n this.bot.start({\n onStart: () => {\n console.log('āœ… Telegram bot connected (long polling)');\n this.connected = true;\n this.emit('ready');\n },\n });\n // bot.start() is non-blocking in grammY, but onStart fires after first poll\n this.connected = true;\n return;\n }\n\n this.connected = true;\n this.emit('ready');\n }\n\n async disconnect(): Promise<void> {\n await this.bot.stop();\n this.connected = false;\n console.log('Telegram bot disconnected');\n }\n\n async sendTypingIndicator(to: string): Promise<void> {\n if (!this.connected) return;\n const chatId = parseInt(to, 10);\n if (isNaN(chatId)) return;\n try {\n await this.bot.api.sendChatAction(chatId, 'typing');\n } catch {\n // Non-critical — silently ignore failures\n }\n }\n\n async sendMessage(to: string, message: OutgoingMessage): Promise<void> {\n if (!this.connected) {\n throw new Error('Telegram bot not connected');\n }\n\n const chatId = parseInt(to, 10);\n if (isNaN(chatId)) {\n throw new Error(`Invalid Telegram chat ID: \"${to}\" — must be numeric`);\n }\n await this.bot.api.sendMessage(chatId, message.text);\n\n console.log(`šŸ“¤ [Telegram] Sent reply to ${to}`);\n }\n\n isActive(): boolean {\n return this.connected;\n }\n}\n"],"mappings":";;;;AAUA,IAAa,mBAAb,cAAsC,aAAwC;CAC5E,AAAgB,OAAO;CACvB,AAAQ;CACR,AAAQ;CACR,AAAQ,YAAY;CAEpB,YAAY,QAAgC;AAC1C,SAAO;AACP,OAAK,SAAS;AACd,OAAK,MAAM,IAAI,IAAI,OAAO,SAAS;;CAGrC,MAAM,UAAyB;AAE7B,OAAK,IAAI,GAAG,iBAAiB,QAAQ;GACnC,MAAM,MAAuB;IAC3B,IAAI,OAAO,IAAI,QAAQ,WAAW;IAClC,MAAM,OAAO,IAAI,MAAM,MAAM,IAAI,KAAK,GAAG;IACzC,MAAM,IAAI,QAAQ;IAClB,WAAW,IAAI,QAAQ,OAAO;IAC9B,SAAS;IACT,UAAU,KAAK;IACf,UAAU;KACR,QAAQ,IAAI,KAAK;KACjB,UAAU,IAAI,MAAM;KACpB,WAAW,IAAI,MAAM;KACrB,UAAU,IAAI,MAAM;KACrB;IACF;AAED,WAAQ,IAAI,oCAAoC,IAAI,MAAM,cAAc,IAAI,MAAM,YAAY,IAAI,OAAO;AACzG,WAAQ,IAAI,gBAAgB,IAAI,KAAK,GAAG;AAExC,QAAK,KAAK,WAAW,IAAI;IACzB;AAGF,OAAK,IAAI,OAAO,QAAQ;AACtB,WAAQ,MAAM,2BAA2B,IAAI,QAAQ;AACrD,QAAK,KAAK,SAAS,IAAI;IACvB;AAGF,MAAI,KAAK,OAAO,YAAY;AAC1B,SAAM,KAAK,IAAI,IAAI,WAAW,KAAK,OAAO,WAAW;AACrD,WAAQ,IAAI,sCAAsC,KAAK,OAAO,WAAW,GAAG;SACvE;AAEL,QAAK,IAAI,MAAM,EACb,eAAe;AACb,YAAQ,IAAI,0CAA0C;AACtD,SAAK,YAAY;AACjB,SAAK,KAAK,QAAQ;MAErB,CAAC;AAEF,QAAK,YAAY;AACjB;;AAGF,OAAK,YAAY;AACjB,OAAK,KAAK,QAAQ;;CAGpB,MAAM,aAA4B;AAChC,QAAM,KAAK,IAAI,MAAM;AACrB,OAAK,YAAY;AACjB,UAAQ,IAAI,4BAA4B;;CAG1C,MAAM,oBAAoB,IAA2B;AACnD,MAAI,CAAC,KAAK,UAAW;EACrB,MAAM,SAAS,SAAS,IAAI,GAAG;AAC/B,MAAI,MAAM,OAAO,CAAE;AACnB,MAAI;AACF,SAAM,KAAK,IAAI,IAAI,eAAe,QAAQ,SAAS;UAC7C;;CAKV,MAAM,YAAY,IAAY,SAAyC;AACrE,MAAI,CAAC,KAAK,UACR,OAAM,IAAI,MAAM,6BAA6B;EAG/C,MAAM,SAAS,SAAS,IAAI,GAAG;AAC/B,MAAI,MAAM,OAAO,CACf,OAAM,IAAI,MAAM,8BAA8B,GAAG,qBAAqB;AAExE,QAAM,KAAK,IAAI,IAAI,YAAY,QAAQ,QAAQ,KAAK;AAEpD,UAAQ,IAAI,+BAA+B,KAAK;;CAGlD,WAAoB;AAClB,SAAO,KAAK"}
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@operor/provider-telegram",
3
+ "version": "0.1.0",
4
+ "description": "Telegram provider for Agent OS using grammY",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "dependencies": {
9
+ "eventemitter3": "^5.0.1",
10
+ "grammy": "^1.35.0",
11
+ "@operor/core": "0.1.0"
12
+ },
13
+ "devDependencies": {
14
+ "tsdown": "^0.20.3",
15
+ "typescript": "^5.3.3"
16
+ },
17
+ "scripts": {
18
+ "build": "tsdown",
19
+ "dev": "tsdown --watch"
20
+ }
21
+ }
@@ -0,0 +1,109 @@
1
+ import EventEmitter from 'eventemitter3';
2
+ import { Bot } from 'grammy';
3
+ import type { MessageProvider, IncomingMessage, OutgoingMessage } from '@operor/core';
4
+
5
+ export interface TelegramProviderConfig {
6
+ botToken: string;
7
+ /** Optional webhook URL. If not set, uses long polling. */
8
+ webhookUrl?: string;
9
+ }
10
+
11
+ export class TelegramProvider extends EventEmitter implements MessageProvider {
12
+ public readonly name = 'telegram';
13
+ private bot: Bot;
14
+ private config: TelegramProviderConfig;
15
+ private connected = false;
16
+
17
+ constructor(config: TelegramProviderConfig) {
18
+ super();
19
+ this.config = config;
20
+ this.bot = new Bot(config.botToken);
21
+ }
22
+
23
+ async connect(): Promise<void> {
24
+ // Listen for text messages
25
+ this.bot.on('message:text', (ctx) => {
26
+ const msg: IncomingMessage = {
27
+ id: String(ctx.message.message_id),
28
+ from: String(ctx.from?.id || ctx.chat.id),
29
+ text: ctx.message.text,
30
+ timestamp: ctx.message.date * 1000,
31
+ channel: 'telegram',
32
+ provider: this.name,
33
+ metadata: {
34
+ chatId: ctx.chat.id,
35
+ username: ctx.from?.username,
36
+ firstName: ctx.from?.first_name,
37
+ lastName: ctx.from?.last_name,
38
+ },
39
+ };
40
+
41
+ console.log(`\nšŸ“„ [Telegram] New message from ${ctx.from?.first_name || ctx.from?.username || msg.from}`);
42
+ console.log(` Message: "${msg.text}"`);
43
+
44
+ this.emit('message', msg);
45
+ });
46
+
47
+ // Error handling
48
+ this.bot.catch((err) => {
49
+ console.error('āŒ [Telegram] Bot error:', err.message);
50
+ this.emit('error', err);
51
+ });
52
+
53
+ // Start bot
54
+ if (this.config.webhookUrl) {
55
+ await this.bot.api.setWebhook(this.config.webhookUrl);
56
+ console.log(`āœ… Telegram bot connected (webhook: ${this.config.webhookUrl})`);
57
+ } else {
58
+ // Long polling for development — non-blocking start
59
+ this.bot.start({
60
+ onStart: () => {
61
+ console.log('āœ… Telegram bot connected (long polling)');
62
+ this.connected = true;
63
+ this.emit('ready');
64
+ },
65
+ });
66
+ // bot.start() is non-blocking in grammY, but onStart fires after first poll
67
+ this.connected = true;
68
+ return;
69
+ }
70
+
71
+ this.connected = true;
72
+ this.emit('ready');
73
+ }
74
+
75
+ async disconnect(): Promise<void> {
76
+ await this.bot.stop();
77
+ this.connected = false;
78
+ console.log('Telegram bot disconnected');
79
+ }
80
+
81
+ async sendTypingIndicator(to: string): Promise<void> {
82
+ if (!this.connected) return;
83
+ const chatId = parseInt(to, 10);
84
+ if (isNaN(chatId)) return;
85
+ try {
86
+ await this.bot.api.sendChatAction(chatId, 'typing');
87
+ } catch {
88
+ // Non-critical — silently ignore failures
89
+ }
90
+ }
91
+
92
+ async sendMessage(to: string, message: OutgoingMessage): Promise<void> {
93
+ if (!this.connected) {
94
+ throw new Error('Telegram bot not connected');
95
+ }
96
+
97
+ const chatId = parseInt(to, 10);
98
+ if (isNaN(chatId)) {
99
+ throw new Error(`Invalid Telegram chat ID: "${to}" — must be numeric`);
100
+ }
101
+ await this.bot.api.sendMessage(chatId, message.text);
102
+
103
+ console.log(`šŸ“¤ [Telegram] Sent reply to ${to}`);
104
+ }
105
+
106
+ isActive(): boolean {
107
+ return this.connected;
108
+ }
109
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { TelegramProvider } from './TelegramProvider.js';
2
+ export type { TelegramProviderConfig } from './TelegramProvider.js';
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "exclude": ["node_modules", "dist"]
9
+ }
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from 'tsdown';
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ format: ['esm'],
6
+ dts: true,
7
+ clean: true,
8
+ sourcemap: true,
9
+ outExtensions: () => ({ js: '.js', dts: '.d.ts' }),
10
+ });