ccpa-telegram 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/README.md +169 -0
- package/dist/bot/commands/clear.d.ts +3 -0
- package/dist/bot/commands/clear.d.ts.map +1 -0
- package/dist/bot/commands/clear.js +20 -0
- package/dist/bot/commands/clear.js.map +1 -0
- package/dist/bot/commands/help.d.ts +3 -0
- package/dist/bot/commands/help.d.ts.map +1 -0
- package/dist/bot/commands/help.js +16 -0
- package/dist/bot/commands/help.js.map +1 -0
- package/dist/bot/commands/start.d.ts +3 -0
- package/dist/bot/commands/start.d.ts.map +1 -0
- package/dist/bot/commands/start.js +10 -0
- package/dist/bot/commands/start.js.map +1 -0
- package/dist/bot/handlers/document.d.ts +6 -0
- package/dist/bot/handlers/document.d.ts.map +1 -0
- package/dist/bot/handlers/document.js +128 -0
- package/dist/bot/handlers/document.js.map +1 -0
- package/dist/bot/handlers/index.d.ts +4 -0
- package/dist/bot/handlers/index.d.ts.map +1 -0
- package/dist/bot/handlers/index.js +4 -0
- package/dist/bot/handlers/index.js.map +1 -0
- package/dist/bot/handlers/photo.d.ts +6 -0
- package/dist/bot/handlers/photo.d.ts.map +1 -0
- package/dist/bot/handlers/photo.js +87 -0
- package/dist/bot/handlers/photo.js.map +1 -0
- package/dist/bot/handlers/text.d.ts +6 -0
- package/dist/bot/handlers/text.d.ts.map +1 -0
- package/dist/bot/handlers/text.js +84 -0
- package/dist/bot/handlers/text.js.map +1 -0
- package/dist/bot/middleware/auth.d.ts +6 -0
- package/dist/bot/middleware/auth.d.ts.map +1 -0
- package/dist/bot/middleware/auth.js +22 -0
- package/dist/bot/middleware/auth.js.map +1 -0
- package/dist/bot/middleware/rateLimit.d.ts +6 -0
- package/dist/bot/middleware/rateLimit.d.ts.map +1 -0
- package/dist/bot/middleware/rateLimit.js +54 -0
- package/dist/bot/middleware/rateLimit.js.map +1 -0
- package/dist/bot.d.ts +2 -0
- package/dist/bot.d.ts.map +1 -0
- package/dist/bot.js +73 -0
- package/dist/bot.js.map +1 -0
- package/dist/claude/executor.d.ts +17 -0
- package/dist/claude/executor.d.ts.map +1 -0
- package/dist/claude/executor.js +135 -0
- package/dist/claude/executor.js.map +1 -0
- package/dist/claude/parser.d.ts +13 -0
- package/dist/claude/parser.d.ts.map +1 -0
- package/dist/claude/parser.js +63 -0
- package/dist/claude/parser.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +124 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +167 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +4 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +31 -0
- package/dist/logger.js.map +1 -0
- package/dist/telegram/chunker.d.ts +10 -0
- package/dist/telegram/chunker.d.ts.map +1 -0
- package/dist/telegram/chunker.js +88 -0
- package/dist/telegram/chunker.js.map +1 -0
- package/dist/user/setup.d.ts +22 -0
- package/dist/user/setup.d.ts.map +1 -0
- package/dist/user/setup.js +63 -0
- package/dist/user/setup.js.map +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# ccpa-telegram
|
|
2
|
+
|
|
3
|
+
A Telegram bot that provides access to Claude Code as a personal assistant. Run Claude Code in any directory and interact with it through Telegram.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Chat with Claude Code via Telegram
|
|
8
|
+
- Send images and documents for analysis
|
|
9
|
+
- Persistent conversation sessions per user
|
|
10
|
+
- Configurable Claude settings per project
|
|
11
|
+
- Multi-user support with access control
|
|
12
|
+
|
|
13
|
+
## How It Works
|
|
14
|
+
|
|
15
|
+
This bot runs Claude Code as a subprocess in your chosen working directory. Claude Code reads all its standard configuration files from that directory, exactly as it would when running directly in a terminal:
|
|
16
|
+
|
|
17
|
+
- `CLAUDE.md` - Project-specific instructions and context
|
|
18
|
+
- `.claude/settings.json` - Permissions and tool settings
|
|
19
|
+
- `.claude/commands/` - Custom slash commands
|
|
20
|
+
- `.mcp.json` - MCP server configurations
|
|
21
|
+
|
|
22
|
+
This means you get the full power of Claude Code - including file access, code execution, and any configured MCP tools - all accessible through Telegram.
|
|
23
|
+
|
|
24
|
+
For complete documentation on Claude Code configuration, see the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code).
|
|
25
|
+
|
|
26
|
+
## Prerequisites
|
|
27
|
+
|
|
28
|
+
- Node.js 18+
|
|
29
|
+
- [Claude Code CLI](https://github.com/anthropics/claude-code) installed and authenticated.
|
|
30
|
+
- A Telegram bot token (from [@BotFather](https://t.me/BotFather)). See [Creating a Telegram Bot](#creating-a-telegram-bot) for instructions.
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Initialize a new project
|
|
36
|
+
npx ccpa-telegram init
|
|
37
|
+
|
|
38
|
+
# Edit ccpa.config.json with your bot token and allowed user IDs
|
|
39
|
+
|
|
40
|
+
# Start the bot
|
|
41
|
+
npx ccpa-telegram
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
### Using npx (recommended)
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npx ccpa-telegram init --cwd ./my-project
|
|
50
|
+
npx ccpa-telegram --cwd ./my-project
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Configuration
|
|
54
|
+
|
|
55
|
+
### ccpa.config.json
|
|
56
|
+
|
|
57
|
+
Create a `ccpa.config.json` file in your project directory:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"telegram": {
|
|
62
|
+
"botToken": "YOUR_BOT_TOKEN_HERE"
|
|
63
|
+
},
|
|
64
|
+
"access": {
|
|
65
|
+
"allowedUserIds": [123456789]
|
|
66
|
+
},
|
|
67
|
+
"claude": {
|
|
68
|
+
"command": "claude"
|
|
69
|
+
},
|
|
70
|
+
"logging": {
|
|
71
|
+
"level": "info"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Configuration Options
|
|
77
|
+
|
|
78
|
+
| Option | Description | Default |
|
|
79
|
+
| ----------------------- | ------------------------------------------------- | ---------- |
|
|
80
|
+
| `telegram.botToken` | Telegram bot token from BotFather | Required |
|
|
81
|
+
| `access.allowedUserIds` | Array of Telegram user IDs allowed to use the bot | `[]` |
|
|
82
|
+
| `claude.command` | Claude CLI command | `"claude"` |
|
|
83
|
+
| `logging.level` | Log level: debug, info, warn, error | `"info"` |
|
|
84
|
+
|
|
85
|
+
### Environment Variables
|
|
86
|
+
|
|
87
|
+
Environment variables override config file values:
|
|
88
|
+
|
|
89
|
+
| Variable | Description |
|
|
90
|
+
| -------------------- | ------------------------ |
|
|
91
|
+
| `TELEGRAM_BOT_TOKEN` | Telegram bot token |
|
|
92
|
+
| `ALLOWED_USER_IDS` | Comma-separated user IDs |
|
|
93
|
+
| `CLAUDE_COMMAND` | Claude CLI command |
|
|
94
|
+
| `LOG_LEVEL` | Logging level |
|
|
95
|
+
|
|
96
|
+
## Directory Structure
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
my-project/
|
|
100
|
+
├── ccpa.config.json # Bot configuration
|
|
101
|
+
├── CLAUDE.md # Claude system prompt
|
|
102
|
+
├── .claude/
|
|
103
|
+
│ └── settings.json # Claude settings
|
|
104
|
+
└── .ccpa/
|
|
105
|
+
└── users/
|
|
106
|
+
└── {userId}/
|
|
107
|
+
├── uploads/ # Uploaded files
|
|
108
|
+
└── session.json # Session data
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## CLI Commands
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Show help
|
|
115
|
+
npx ccpa-telegram --help
|
|
116
|
+
|
|
117
|
+
# Initialize config file
|
|
118
|
+
npx ccpa-telegram init
|
|
119
|
+
npx ccpa-telegram init --cwd ./my-project
|
|
120
|
+
|
|
121
|
+
# Start the bot
|
|
122
|
+
npx ccpa-telegram
|
|
123
|
+
npx ccpa-telegram --cwd ./my-project
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Bot Commands
|
|
127
|
+
|
|
128
|
+
| Command | Description |
|
|
129
|
+
| -------- | -------------------------- |
|
|
130
|
+
| `/start` | Welcome message |
|
|
131
|
+
| `/help` | Show help information |
|
|
132
|
+
| `/clear` | Clear conversation history |
|
|
133
|
+
|
|
134
|
+
## Creating a Telegram Bot
|
|
135
|
+
|
|
136
|
+
To create a new Telegram bot and get your bot token:
|
|
137
|
+
|
|
138
|
+
1. Open Telegram and message [@BotFather](https://t.me/BotFather)
|
|
139
|
+
2. Send `/newbot` command
|
|
140
|
+
3. Choose a **display name** for your bot (e.g., "My Claude Assistant")
|
|
141
|
+
4. Choose a **username** - must be unique and end with `bot` (e.g., `my_claude_assistant_bot`). The length of the username must be between 5 and 32 characters.
|
|
142
|
+
5. BotFather will reply with your bot token (looks like `123456789:ABCdefGHIjklMNOpqrsTUVwxyz`)
|
|
143
|
+
6. Copy this token to your `ccpa.config.json`
|
|
144
|
+
|
|
145
|
+
For detailed instructions, see the [Telegram Bot API documentation](https://core.telegram.org/bots#how-do-i-create-a-bot).
|
|
146
|
+
|
|
147
|
+
## Finding Your Telegram User ID
|
|
148
|
+
|
|
149
|
+
To find your Telegram user ID:
|
|
150
|
+
|
|
151
|
+
1. Message [@userinfobot](https://t.me/userinfobot) on Telegram
|
|
152
|
+
2. It will reply with your user ID
|
|
153
|
+
3. Add this ID to `allowedUserIds` in your config
|
|
154
|
+
|
|
155
|
+
## Security Notice
|
|
156
|
+
|
|
157
|
+
**Important**: Conversations with this bot are not end-to-end encrypted. Messages pass through Telegram's servers and are processed by the Claude API. Do not share sensitive information such as:
|
|
158
|
+
|
|
159
|
+
- Passwords or API keys
|
|
160
|
+
- Personal identification numbers
|
|
161
|
+
- Financial information
|
|
162
|
+
- Confidential business data
|
|
163
|
+
- Any other private or sensitive data
|
|
164
|
+
|
|
165
|
+
This bot is intended for development assistance and general queries only. Treat all conversations as potentially visible to third parties.
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
ISC
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clear.d.ts","sourceRoot":"","sources":["../../../src/bot/commands/clear.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAItC,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB9D"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { getConfig } from "../../config.js";
|
|
3
|
+
import { clearUserData } from "../../user/setup.js";
|
|
4
|
+
export async function clearHandler(ctx) {
|
|
5
|
+
const config = getConfig();
|
|
6
|
+
const userId = ctx.from?.id;
|
|
7
|
+
if (!userId) {
|
|
8
|
+
await ctx.reply("Could not identify user.");
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const userDir = join(config.dataDir, String(userId));
|
|
12
|
+
try {
|
|
13
|
+
await clearUserData(userDir);
|
|
14
|
+
await ctx.reply("Conversation history cleared. Your next message will start a fresh conversation.");
|
|
15
|
+
}
|
|
16
|
+
catch (_error) {
|
|
17
|
+
await ctx.reply("Failed to clear conversation history. Please try again.");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=clear.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clear.js","sourceRoot":"","sources":["../../../src/bot/commands/clear.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAY;IAC7C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;IAE5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAErD,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC;QAC7B,MAAM,GAAG,CAAC,KAAK,CACb,kFAAkF,CACnF,CAAC;IACJ,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,MAAM,GAAG,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/bot/commands/help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB7D"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export async function helpHandler(ctx) {
|
|
2
|
+
await ctx.reply(`*Claude Code Telegram Bot*\n\n` +
|
|
3
|
+
`*Commands:*\n` +
|
|
4
|
+
`/start - Welcome message\n` +
|
|
5
|
+
`/help - Show this help\n` +
|
|
6
|
+
`/clear - Clear conversation history\n\n` +
|
|
7
|
+
`*Usage:*\n` +
|
|
8
|
+
`Just send any message to chat with Claude.\n` +
|
|
9
|
+
`You can also send images and documents for analysis.\n\n` +
|
|
10
|
+
`Your conversation history is preserved between messages. ` +
|
|
11
|
+
`Use /clear to start a fresh conversation.\n\n` +
|
|
12
|
+
`*Configuration:*\n` +
|
|
13
|
+
`Claude reads configuration from your .claude folder.\n` +
|
|
14
|
+
`Edit CLAUDE.md for system prompts and .claude/settings.json for permissions.`, { parse_mode: "Markdown" });
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/bot/commands/help.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAY;IAC5C,MAAM,GAAG,CAAC,KAAK,CACb,gCAAgC;QAC9B,eAAe;QACf,4BAA4B;QAC5B,0BAA0B;QAC1B,yCAAyC;QACzC,YAAY;QACZ,8CAA8C;QAC9C,0DAA0D;QAC1D,2DAA2D;QAC3D,+CAA+C;QAC/C,oBAAoB;QACpB,wDAAwD;QACxD,8EAA8E,EAChF,EAAE,UAAU,EAAE,UAAU,EAAE,CAC3B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/bot/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAW9D"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export async function startHandler(ctx) {
|
|
2
|
+
const username = ctx.from?.first_name || "there";
|
|
3
|
+
await ctx.reply(`Hello ${username}! I'm a Claude Code assistant bot.\n\n` +
|
|
4
|
+
`You can:\n` +
|
|
5
|
+
`- Send any message to chat with me\n` +
|
|
6
|
+
`- Send images or documents for analysis\n` +
|
|
7
|
+
`- Use /clear to start a new conversation\n\n` +
|
|
8
|
+
`Type /help for more information.`);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/bot/commands/start.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAY;IAC7C,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,UAAU,IAAI,OAAO,CAAC;IAEjD,MAAM,GAAG,CAAC,KAAK,CACb,SAAS,QAAQ,wCAAwC;QACvD,YAAY;QACZ,sCAAsC;QACtC,2CAA2C;QAC3C,8CAA8C;QAC9C,kCAAkC,CACrC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../../src/bot/handlers/document.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAgDtC;;GAEG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA8GjE"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { executeClaudeQuery } from "../../claude/executor.js";
|
|
4
|
+
import { parseClaudeOutput } from "../../claude/parser.js";
|
|
5
|
+
import { getConfig } from "../../config.js";
|
|
6
|
+
import { getLogger } from "../../logger.js";
|
|
7
|
+
import { sendChunkedResponse } from "../../telegram/chunker.js";
|
|
8
|
+
import { ensureUserSetup, getSessionId, getUploadsPath, saveSessionId, } from "../../user/setup.js";
|
|
9
|
+
const SUPPORTED_MIME_TYPES = [
|
|
10
|
+
"application/pdf",
|
|
11
|
+
"text/plain",
|
|
12
|
+
"text/markdown",
|
|
13
|
+
"text/csv",
|
|
14
|
+
"application/json",
|
|
15
|
+
"application/xml",
|
|
16
|
+
"text/html",
|
|
17
|
+
"image/jpeg",
|
|
18
|
+
"image/png",
|
|
19
|
+
"image/gif",
|
|
20
|
+
"image/webp",
|
|
21
|
+
];
|
|
22
|
+
const SUPPORTED_EXTENSIONS = [
|
|
23
|
+
".pdf",
|
|
24
|
+
".txt",
|
|
25
|
+
".md",
|
|
26
|
+
".csv",
|
|
27
|
+
".json",
|
|
28
|
+
".xml",
|
|
29
|
+
".html",
|
|
30
|
+
".js",
|
|
31
|
+
".ts",
|
|
32
|
+
".py",
|
|
33
|
+
".go",
|
|
34
|
+
".rs",
|
|
35
|
+
".java",
|
|
36
|
+
".jpg",
|
|
37
|
+
".jpeg",
|
|
38
|
+
".png",
|
|
39
|
+
".gif",
|
|
40
|
+
".webp",
|
|
41
|
+
];
|
|
42
|
+
/**
|
|
43
|
+
* Handle document messages (PDFs, images, code files, etc.)
|
|
44
|
+
*/
|
|
45
|
+
export async function documentHandler(ctx) {
|
|
46
|
+
const config = getConfig();
|
|
47
|
+
const logger = getLogger();
|
|
48
|
+
const userId = ctx.from?.id;
|
|
49
|
+
const document = ctx.message?.document;
|
|
50
|
+
const caption = ctx.message?.caption || "Please analyze this document.";
|
|
51
|
+
if (!userId || !document) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const mimeType = document.mime_type || "";
|
|
55
|
+
const fileName = document.file_name || "document";
|
|
56
|
+
const ext = fileName.includes(".")
|
|
57
|
+
? `.${fileName.split(".").pop()?.toLowerCase()}`
|
|
58
|
+
: "";
|
|
59
|
+
const isSupported = SUPPORTED_MIME_TYPES.includes(mimeType) ||
|
|
60
|
+
SUPPORTED_EXTENSIONS.includes(ext);
|
|
61
|
+
if (!isSupported) {
|
|
62
|
+
await ctx.reply(`Unsupported file type. Supported: PDF, images, text, and code files.`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
logger.debug({ fileName, mimeType }, "Document received");
|
|
66
|
+
const userDir = resolve(join(config.dataDir, String(userId)));
|
|
67
|
+
try {
|
|
68
|
+
await ensureUserSetup(userDir);
|
|
69
|
+
const file = await ctx.api.getFile(document.file_id);
|
|
70
|
+
const filePath = file.file_path;
|
|
71
|
+
if (!filePath) {
|
|
72
|
+
await ctx.reply("Could not download the document.");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const fileUrl = `https://api.telegram.org/file/bot${config.telegram.botToken}/${filePath}`;
|
|
76
|
+
const response = await fetch(fileUrl);
|
|
77
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
78
|
+
const safeName = fileName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
79
|
+
const uploadsDir = getUploadsPath(userDir);
|
|
80
|
+
const docPath = join(uploadsDir, safeName);
|
|
81
|
+
await writeFile(docPath, buffer);
|
|
82
|
+
logger.debug({ path: docPath }, "Document saved");
|
|
83
|
+
const prompt = `Please read the file "./uploads/${safeName}" and ${caption}`;
|
|
84
|
+
const sessionId = await getSessionId(userDir);
|
|
85
|
+
const statusMsg = await ctx.reply("_Processing..._", {
|
|
86
|
+
parse_mode: "Markdown",
|
|
87
|
+
});
|
|
88
|
+
let lastProgressUpdate = Date.now();
|
|
89
|
+
let lastProgressText = "Processing...";
|
|
90
|
+
const onProgress = async (message) => {
|
|
91
|
+
const now = Date.now();
|
|
92
|
+
if (now - lastProgressUpdate > 2000 && message !== lastProgressText) {
|
|
93
|
+
lastProgressUpdate = now;
|
|
94
|
+
lastProgressText = message;
|
|
95
|
+
try {
|
|
96
|
+
await ctx.api.editMessageText(ctx.chat.id, statusMsg.message_id, `_${message}_`, { parse_mode: "Markdown" });
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Ignore edit errors
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
logger.debug("Executing Claude query with document");
|
|
104
|
+
const result = await executeClaudeQuery({
|
|
105
|
+
prompt,
|
|
106
|
+
userDir,
|
|
107
|
+
sessionId,
|
|
108
|
+
onProgress,
|
|
109
|
+
});
|
|
110
|
+
try {
|
|
111
|
+
await ctx.api.deleteMessage(ctx.chat.id, statusMsg.message_id);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// Ignore delete errors
|
|
115
|
+
}
|
|
116
|
+
const parsed = parseClaudeOutput(result);
|
|
117
|
+
if (parsed.sessionId) {
|
|
118
|
+
await saveSessionId(userDir, parsed.sessionId);
|
|
119
|
+
}
|
|
120
|
+
await sendChunkedResponse(ctx, parsed.text);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
logger.error({ error }, "Document handler error");
|
|
124
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
125
|
+
await ctx.reply(`An error occurred processing the document: ${errorMessage}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document.js","sourceRoot":"","sources":["../../../src/bot/handlers/document.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/bot/handlers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/bot/handlers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"photo.d.ts","sourceRoot":"","sources":["../../../src/bot/handlers/photo.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAatC;;GAEG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA8F9D"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { executeClaudeQuery } from "../../claude/executor.js";
|
|
4
|
+
import { parseClaudeOutput } from "../../claude/parser.js";
|
|
5
|
+
import { getConfig } from "../../config.js";
|
|
6
|
+
import { getLogger } from "../../logger.js";
|
|
7
|
+
import { sendChunkedResponse } from "../../telegram/chunker.js";
|
|
8
|
+
import { ensureUserSetup, getSessionId, getUploadsPath, saveSessionId, } from "../../user/setup.js";
|
|
9
|
+
/**
|
|
10
|
+
* Handle photo messages
|
|
11
|
+
*/
|
|
12
|
+
export async function photoHandler(ctx) {
|
|
13
|
+
const config = getConfig();
|
|
14
|
+
const logger = getLogger();
|
|
15
|
+
const userId = ctx.from?.id;
|
|
16
|
+
const photo = ctx.message?.photo;
|
|
17
|
+
const caption = ctx.message?.caption || "Please analyze this image.";
|
|
18
|
+
if (!userId || !photo || photo.length === 0) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
logger.debug({ userId }, "Photo received");
|
|
22
|
+
const userDir = resolve(join(config.dataDir, String(userId)));
|
|
23
|
+
try {
|
|
24
|
+
await ensureUserSetup(userDir);
|
|
25
|
+
// Get the largest photo (last in array)
|
|
26
|
+
const largestPhoto = photo[photo.length - 1];
|
|
27
|
+
const file = await ctx.api.getFile(largestPhoto.file_id);
|
|
28
|
+
const filePath = file.file_path;
|
|
29
|
+
if (!filePath) {
|
|
30
|
+
await ctx.reply("Could not download the image.");
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const fileUrl = `https://api.telegram.org/file/bot${config.telegram.botToken}/${filePath}`;
|
|
34
|
+
const response = await fetch(fileUrl);
|
|
35
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
36
|
+
const ext = filePath.split(".").pop() || "jpg";
|
|
37
|
+
const imageName = `image_${Date.now()}.${ext}`;
|
|
38
|
+
const uploadsDir = getUploadsPath(userDir);
|
|
39
|
+
const imagePath = join(uploadsDir, imageName);
|
|
40
|
+
await writeFile(imagePath, buffer);
|
|
41
|
+
logger.debug({ path: imagePath }, "Image saved");
|
|
42
|
+
const prompt = `Please look at the image file "./uploads/${imageName}" and ${caption}`;
|
|
43
|
+
const sessionId = await getSessionId(userDir);
|
|
44
|
+
const statusMsg = await ctx.reply("_Processing..._", {
|
|
45
|
+
parse_mode: "Markdown",
|
|
46
|
+
});
|
|
47
|
+
let lastProgressUpdate = Date.now();
|
|
48
|
+
let lastProgressText = "Processing...";
|
|
49
|
+
const onProgress = async (message) => {
|
|
50
|
+
const now = Date.now();
|
|
51
|
+
if (now - lastProgressUpdate > 2000 && message !== lastProgressText) {
|
|
52
|
+
lastProgressUpdate = now;
|
|
53
|
+
lastProgressText = message;
|
|
54
|
+
try {
|
|
55
|
+
await ctx.api.editMessageText(ctx.chat.id, statusMsg.message_id, `_${message}_`, { parse_mode: "Markdown" });
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Ignore edit errors
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
logger.debug("Executing Claude query with image");
|
|
63
|
+
const result = await executeClaudeQuery({
|
|
64
|
+
prompt,
|
|
65
|
+
userDir,
|
|
66
|
+
sessionId,
|
|
67
|
+
onProgress,
|
|
68
|
+
});
|
|
69
|
+
try {
|
|
70
|
+
await ctx.api.deleteMessage(ctx.chat.id, statusMsg.message_id);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Ignore delete errors
|
|
74
|
+
}
|
|
75
|
+
const parsed = parseClaudeOutput(result);
|
|
76
|
+
if (parsed.sessionId) {
|
|
77
|
+
await saveSessionId(userDir, parsed.sessionId);
|
|
78
|
+
}
|
|
79
|
+
await sendChunkedResponse(ctx, parsed.text);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
logger.error({ error }, "Photo handler error");
|
|
83
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
84
|
+
await ctx.reply(`An error occurred processing the image: ${errorMessage}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=photo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"photo.js","sourceRoot":"","sources":["../../../src/bot/handlers/photo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/bot/handlers/text.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAWtC;;GAEG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA8F7D"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { join, resolve } from "node:path";
|
|
2
|
+
import { executeClaudeQuery } from "../../claude/executor.js";
|
|
3
|
+
import { getConfig } from "../../config.js";
|
|
4
|
+
import { getLogger } from "../../logger.js";
|
|
5
|
+
import { sendChunkedResponse } from "../../telegram/chunker.js";
|
|
6
|
+
import { ensureUserSetup, getSessionId, saveSessionId, } from "../../user/setup.js";
|
|
7
|
+
/**
|
|
8
|
+
* Handle text messages - routes to Claude
|
|
9
|
+
*/
|
|
10
|
+
export async function textHandler(ctx) {
|
|
11
|
+
const config = getConfig();
|
|
12
|
+
const logger = getLogger();
|
|
13
|
+
const userId = ctx.from?.id;
|
|
14
|
+
const messageText = ctx.message?.text;
|
|
15
|
+
if (!userId || !messageText) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
logger.debug({
|
|
19
|
+
userId,
|
|
20
|
+
username: ctx.from?.username,
|
|
21
|
+
name: ctx.from?.first_name,
|
|
22
|
+
}, "Message received");
|
|
23
|
+
const userDir = resolve(join(config.dataDir, String(userId)));
|
|
24
|
+
try {
|
|
25
|
+
logger.debug({ userDir }, "Setting up user directory");
|
|
26
|
+
await ensureUserSetup(userDir);
|
|
27
|
+
if (!messageText.trim()) {
|
|
28
|
+
await ctx.reply("Please provide a message.");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const sessionId = await getSessionId(userDir);
|
|
32
|
+
logger.debug({ sessionId: sessionId || "new" }, "Session");
|
|
33
|
+
// Send initial status message
|
|
34
|
+
const statusMsg = await ctx.reply("_Processing..._", {
|
|
35
|
+
parse_mode: "Markdown",
|
|
36
|
+
});
|
|
37
|
+
let lastProgressUpdate = Date.now();
|
|
38
|
+
let lastProgressText = "Processing...";
|
|
39
|
+
// Progress callback - updates status message
|
|
40
|
+
const onProgress = async (message) => {
|
|
41
|
+
const now = Date.now();
|
|
42
|
+
if (now - lastProgressUpdate > 2000 && message !== lastProgressText) {
|
|
43
|
+
lastProgressUpdate = now;
|
|
44
|
+
lastProgressText = message;
|
|
45
|
+
try {
|
|
46
|
+
await ctx.api.editMessageText(ctx.chat.id, statusMsg.message_id, `_${message}_`, { parse_mode: "Markdown" });
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Ignore edit errors
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
logger.debug("Executing Claude query");
|
|
54
|
+
const result = await executeClaudeQuery({
|
|
55
|
+
prompt: messageText,
|
|
56
|
+
userDir,
|
|
57
|
+
sessionId,
|
|
58
|
+
onProgress,
|
|
59
|
+
});
|
|
60
|
+
logger.debug({ success: result.success, error: result.error }, "Claude result");
|
|
61
|
+
// Delete status message
|
|
62
|
+
try {
|
|
63
|
+
await ctx.api.deleteMessage(ctx.chat.id, statusMsg.message_id);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Ignore delete errors
|
|
67
|
+
}
|
|
68
|
+
if (result.sessionId) {
|
|
69
|
+
await saveSessionId(userDir, result.sessionId);
|
|
70
|
+
logger.debug({ sessionId: result.sessionId }, "Session saved");
|
|
71
|
+
}
|
|
72
|
+
const responseText = result.success
|
|
73
|
+
? result.output
|
|
74
|
+
: result.error || "An error occurred";
|
|
75
|
+
await sendChunkedResponse(ctx, responseText);
|
|
76
|
+
logger.debug("Response sent");
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
logger.error({ error }, "Text handler error");
|
|
80
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
81
|
+
await ctx.reply(`An error occurred: ${errorMessage}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../../src/bot/handlers/text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EACL,eAAe,EACf,YAAY,EACZ,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAY;IAC5C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC;IAEtC,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,MAAM,CAAC,KAAK,CACV;QACE,MAAM;QACN,QAAQ,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ;QAC5B,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,UAAU;KAC3B,EACD,kBAAkB,CACnB,CAAC;IAEF,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAE9D,IAAI,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,2BAA2B,CAAC,CAAC;QACvD,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;QAE/B,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC;YACxB,MAAM,GAAG,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC7C,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,SAAS,IAAI,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;QAE3D,8BAA8B;QAC9B,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,iBAAiB,EAAE;YACnD,UAAU,EAAE,UAAU;SACvB,CAAC,CAAC;QACH,IAAI,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACpC,IAAI,gBAAgB,GAAG,eAAe,CAAC;QAEvC,6CAA6C;QAC7C,MAAM,UAAU,GAAG,KAAK,EAAE,OAAe,EAAE,EAAE;YAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,IAAI,GAAG,GAAG,kBAAkB,GAAG,IAAI,IAAI,OAAO,KAAK,gBAAgB,EAAE,CAAC;gBACpE,kBAAkB,GAAG,GAAG,CAAC;gBACzB,gBAAgB,GAAG,OAAO,CAAC;gBAC3B,IAAI,CAAC;oBACH,MAAM,GAAG,CAAC,GAAG,CAAC,eAAe,CAC3B,GAAG,CAAC,IAAK,CAAC,EAAE,EACZ,SAAS,CAAC,UAAU,EACpB,IAAI,OAAO,GAAG,EACd,EAAE,UAAU,EAAE,UAAU,EAAE,CAC3B,CAAC;gBACJ,CAAC;gBAAC,MAAM,CAAC;oBACP,qBAAqB;gBACvB,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC;YACtC,MAAM,EAAE,WAAW;YACnB,OAAO;YACP,SAAS;YACT,UAAU;SACX,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CACV,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,EAChD,eAAe,CAChB,CAAC;QAEF,wBAAwB;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,IAAK,CAAC,EAAE,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;QAClE,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;QAED,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,MAAM,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;YAC/C,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,EAAE,eAAe,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO;YACjC,CAAC,CAAC,MAAM,CAAC,MAAM;YACf,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,mBAAmB,CAAC;QACxC,MAAM,mBAAmB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QAC7C,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,oBAAoB,CAAC,CAAC;QAC9C,MAAM,YAAY,GAChB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QAC3D,MAAM,GAAG,CAAC,KAAK,CAAC,sBAAsB,YAAY,EAAE,CAAC,CAAC;IACxD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/bot/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGpD;;GAEG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,OAAO,EACZ,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,IAAI,CAAC,CAqBf"}
|