agent-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.
- package/README.md +350 -0
- package/bin/custom-gcl +0 -0
- package/bin/golangci-lint +0 -0
- package/bin/run.js +25 -0
- package/package.json +30 -0
- package/scripts/build-all.sh +39 -0
- package/scripts/install.js +171 -0
package/README.md
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# agent-telegram
|
|
2
|
+
|
|
3
|
+
Telegram automation CLI for AI agents. Fast Go binary with MTProto API.
|
|
4
|
+
|
|
5
|
+
By Aslan Dukaev [X](https://x.com/dukaev) ·[Telegram](https://t.me/dukaev)
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
### Package Managers
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bun add -g agent-telegram
|
|
13
|
+
npm install -g agent-telegram
|
|
14
|
+
pnpm add -g agent-telegram
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### From Source
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/dukaev/agent-telegram
|
|
21
|
+
cd agent-telegram
|
|
22
|
+
go build -o agent-telegram .
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
agent-telegram serve # Start IPC server (runs in background)
|
|
29
|
+
agent-telegram login # Interactive login
|
|
30
|
+
agent-telegram my-info # Get your profile
|
|
31
|
+
agent-telegram chat list # List all chats
|
|
32
|
+
agent-telegram chat open @username # View messages from chat
|
|
33
|
+
agent-telegram send --to @user "Hello!" # Send message
|
|
34
|
+
agent-telegram stop # Stop server
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Commands
|
|
38
|
+
|
|
39
|
+
### Authentication
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
agent-telegram login # Interactive login
|
|
43
|
+
agent-telegram logout # Logout and clear session
|
|
44
|
+
agent-telegram my-info # Get your profile information
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Send Messages
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
agent-telegram send --to @user "text" # Text message
|
|
51
|
+
agent-telegram send --to @user --photo image.png # Photo
|
|
52
|
+
agent-telegram send --to @user --video video.mp4 # Video
|
|
53
|
+
agent-telegram send --to @user --voice voice.ogg # Voice message
|
|
54
|
+
agent-telegram send --to @user --video-note vid.mp4 # Video note (circle)
|
|
55
|
+
agent-telegram send --to @user --sticker file.webp # Sticker
|
|
56
|
+
agent-telegram send --to @user --gif anim.mp4 # GIF/animation
|
|
57
|
+
agent-telegram send --to @user --document file.pdf # Document
|
|
58
|
+
agent-telegram send --to @user --audio music.mp3 # Audio
|
|
59
|
+
agent-telegram send --to @user --contact "+1234567890" --first-name "John" # Contact
|
|
60
|
+
agent-telegram send --to @user --reply-to 123 "Reply text" # Reply
|
|
61
|
+
agent-telegram send --to @user --poll "Question?" --option "Yes" --option "No" # Poll
|
|
62
|
+
agent-telegram send --to @user --latitude 55.7558 --longitude 37.6173 # Location
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Message Management (`msg`)
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
agent-telegram msg read @user # Mark messages as read
|
|
69
|
+
agent-telegram msg typing @user # Send typing indicator
|
|
70
|
+
agent-telegram msg scheduled @user # List scheduled messages
|
|
71
|
+
agent-telegram msg delete @user 123 # Delete message by ID
|
|
72
|
+
agent-telegram msg forward @user --to @other 123 # Forward message
|
|
73
|
+
agent-telegram msg pin @user 123 # Pin message
|
|
74
|
+
agent-telegram msg pin @user 123 --unpin # Unpin message
|
|
75
|
+
agent-telegram msg reaction @user 123 "👍" # Add reaction
|
|
76
|
+
agent-telegram msg inspect-buttons @user 123 # View inline buttons
|
|
77
|
+
agent-telegram msg press-button @user 123 0 0 # Press button (row, col)
|
|
78
|
+
agent-telegram msg inspect-keyboard @user # View reply keyboard
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Chat Management (`chat`)
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
agent-telegram chat list # List all chats
|
|
85
|
+
agent-telegram chat list -l 50 # List with limit
|
|
86
|
+
agent-telegram chat info @channel # Get chat information
|
|
87
|
+
agent-telegram chat open @user # View messages
|
|
88
|
+
agent-telegram chat open @user -l 50 # View 50 messages
|
|
89
|
+
agent-telegram chat open @user -l 50 -o 100 # With offset
|
|
90
|
+
agent-telegram chat create-group "Name" @user1 @user2 # Create group
|
|
91
|
+
agent-telegram chat create-channel "Name" "Description" # Create channel
|
|
92
|
+
agent-telegram chat join https://t.me/+invite # Join via link
|
|
93
|
+
agent-telegram chat subscribe @channel # Subscribe to channel
|
|
94
|
+
agent-telegram chat leave @group # Leave chat/channel
|
|
95
|
+
agent-telegram chat invite @group @user # Invite user
|
|
96
|
+
agent-telegram chat edit-title @group "New Title" # Edit title
|
|
97
|
+
agent-telegram chat set-photo @group photo.jpg # Set photo
|
|
98
|
+
agent-telegram chat delete-photo @group # Delete photo
|
|
99
|
+
agent-telegram chat pin @group # Pin chat in list
|
|
100
|
+
agent-telegram chat pin @group --unpin # Unpin from list
|
|
101
|
+
agent-telegram chat mute @group # Mute notifications
|
|
102
|
+
agent-telegram chat mute @group --unmute # Unmute
|
|
103
|
+
agent-telegram chat archive @group # Archive chat
|
|
104
|
+
agent-telegram chat archive @group --unarchive # Unarchive
|
|
105
|
+
agent-telegram chat topics @forum # List forum topics
|
|
106
|
+
agent-telegram chat invite-link @group # Get/create invite link
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Members & Admins
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
agent-telegram chat participants @group # List members
|
|
113
|
+
agent-telegram chat admins @group # List admins
|
|
114
|
+
agent-telegram chat banned @group # List banned users
|
|
115
|
+
agent-telegram chat promote-admin @group @user # Promote to admin
|
|
116
|
+
agent-telegram chat demote-admin @group @user # Demote admin
|
|
117
|
+
agent-telegram chat slow-mode @group 30 # Set slow mode (seconds)
|
|
118
|
+
agent-telegram chat permissions @group # Set default permissions
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Contacts (`contact`)
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
agent-telegram contact list # List contacts
|
|
125
|
+
agent-telegram contact add "+1234567890" "John" "Doe" # Add contact
|
|
126
|
+
agent-telegram contact delete @user # Delete contact
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### User (`user`)
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
agent-telegram user info @user # Get user info
|
|
133
|
+
agent-telegram user ban @user # Block user
|
|
134
|
+
agent-telegram user ban @user --unban # Unblock user
|
|
135
|
+
agent-telegram user mute @user # Mute user
|
|
136
|
+
agent-telegram user mute @user --unmute # Unmute user
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Folders (`folders`)
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
agent-telegram folders list # List chat folders
|
|
143
|
+
agent-telegram folders create "Work" # Create folder
|
|
144
|
+
agent-telegram folders delete 1 # Delete folder by ID
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Privacy (`privacy`)
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
agent-telegram privacy get phone_number # Get privacy setting
|
|
151
|
+
agent-telegram privacy set phone_number allow_contacts # Set privacy
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Privacy keys:** `status_timestamp`, `phone_number`, `profile_photo`, `forwards`, `phone_call`, `voice_messages`, `about`
|
|
155
|
+
|
|
156
|
+
**Rules:** `allow_all`, `allow_contacts`, `disallow_all`, `allow_close_friends`
|
|
157
|
+
|
|
158
|
+
### Search
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
agent-telegram search "query" # Search in chats
|
|
162
|
+
agent-telegram search "query" --global # Global search
|
|
163
|
+
agent-telegram search "query" --in @user # Search in specific chat
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Server
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
agent-telegram serve # Start IPC server (background)
|
|
170
|
+
agent-telegram status # Check server status
|
|
171
|
+
agent-telegram stop # Stop server
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Other
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
agent-telegram open @user # Quick open chat (alias)
|
|
178
|
+
agent-telegram updates # Get pending updates
|
|
179
|
+
agent-telegram updates -l 50 # Get 50 updates
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Options
|
|
183
|
+
|
|
184
|
+
| Option | Description |
|
|
185
|
+
|--------|-------------|
|
|
186
|
+
| `-s, --socket <path>` | Path to Unix socket (default: `/tmp/agent-telegram.sock`) |
|
|
187
|
+
| `-j, --json` | JSON output (for agents) |
|
|
188
|
+
| `-l, --limit <n>` | Limit results |
|
|
189
|
+
| `-o, --offset <n>` | Offset for pagination |
|
|
190
|
+
|
|
191
|
+
## Environment Variables
|
|
192
|
+
|
|
193
|
+
| Variable | Description |
|
|
194
|
+
|----------|-------------|
|
|
195
|
+
| `TELEGRAM_APP_ID` | Telegram API App ID (optional, has default) |
|
|
196
|
+
| `TELEGRAM_APP_HASH` | Telegram API App Hash (optional, has default) |
|
|
197
|
+
| `TELEGRAM_PHONE` | Phone number for auth (optional) |
|
|
198
|
+
| `AGENT_TELEGRAM_SESSION_PATH` | Custom session file path |
|
|
199
|
+
|
|
200
|
+
Default API credentials are built-in, so you can start using agent-telegram immediately. To use your own credentials, get them at https://my.telegram.org and set via environment variables or `.env` file.
|
|
201
|
+
|
|
202
|
+
## Agent Mode
|
|
203
|
+
|
|
204
|
+
Use `--json` / `-j` for machine-readable output:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
agent-telegram chat list --json
|
|
208
|
+
agent-telegram chat open @user -l 10 --json
|
|
209
|
+
agent-telegram send --to @user "Hello" --json
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Optimal AI Workflow
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# 1. Start server and verify status
|
|
216
|
+
agent-telegram serve
|
|
217
|
+
agent-telegram status --json
|
|
218
|
+
|
|
219
|
+
# 2. List chats to find targets
|
|
220
|
+
agent-telegram chat list -l 20 --json
|
|
221
|
+
|
|
222
|
+
# 3. Read messages from a chat
|
|
223
|
+
agent-telegram chat open @username -l 50 --json
|
|
224
|
+
|
|
225
|
+
# 4. Send messages
|
|
226
|
+
agent-telegram send --to @username "Hello!" --json
|
|
227
|
+
|
|
228
|
+
# 5. Check for new messages
|
|
229
|
+
agent-telegram updates --json
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## IPC Protocol (JSON-RPC)
|
|
233
|
+
|
|
234
|
+
All commands communicate via JSON-RPC over Unix socket at `/tmp/agent-telegram.sock`:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Direct IPC call
|
|
238
|
+
echo '{"method":"send_message","params":{"peer":"@user","message":"Hi"}}' | nc -U /tmp/agent-telegram.sock
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Available Methods (77+)
|
|
242
|
+
|
|
243
|
+
**Messages:** `send_message`, `send_reply`, `update_message`, `delete_message`, `forward_message`, `get_messages`, `clear_messages`, `clear_history`, `read_messages`, `set_typing`, `get_scheduled_messages`
|
|
244
|
+
|
|
245
|
+
**Media:** `send_photo`, `send_video`, `send_file`, `send_voice`, `send_video_note`, `send_sticker`, `send_gif`, `send_location`, `send_contact`, `send_poll`
|
|
246
|
+
|
|
247
|
+
**Reactions:** `add_reaction`, `remove_reaction`, `list_reactions`
|
|
248
|
+
|
|
249
|
+
**Buttons:** `inspect_inline_buttons`, `press_inline_button`, `inspect_reply_keyboard`
|
|
250
|
+
|
|
251
|
+
**Pins:** `pin_message`, `unpin_message`, `pin_chat`
|
|
252
|
+
|
|
253
|
+
**Chats:** `get_chats`, `get_topics`, `create_group`, `create_channel`, `edit_title`, `set_photo`, `delete_photo`, `leave`, `invite`, `join_chat`, `subscribe_channel`, `get_invite_link`
|
|
254
|
+
|
|
255
|
+
**Members:** `get_participants`, `get_admins`, `get_banned`, `promote_admin`, `demote_admin`
|
|
256
|
+
|
|
257
|
+
**Settings:** `set_slow_mode`, `set_chat_permissions`
|
|
258
|
+
|
|
259
|
+
**Folders:** `get_folders`, `create_folder`, `delete_folder`
|
|
260
|
+
|
|
261
|
+
**Users:** `get_me`, `get_user_info`, `update_profile`, `update_avatar`, `block`, `unblock`
|
|
262
|
+
|
|
263
|
+
**Contacts:** `get_contacts`, `add_contact`, `delete_contact`
|
|
264
|
+
|
|
265
|
+
**Privacy:** `get_privacy`, `set_privacy`
|
|
266
|
+
|
|
267
|
+
**Search:** `search_global`, `search_in_chat`
|
|
268
|
+
|
|
269
|
+
**System:** `status`, `shutdown`, `ping`
|
|
270
|
+
|
|
271
|
+
## Architecture
|
|
272
|
+
|
|
273
|
+
agent-telegram uses a client-daemon architecture:
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
┌─────────────┐ IPC ┌──────────────┐ MTProto
|
|
277
|
+
│ CLI Command │ ─────────────> │ IPC Server │ ──────────────> Telegram
|
|
278
|
+
│ (Go binary) │ Unix Socket │ (background) │ (gotd/td)
|
|
279
|
+
└─────────────┘ └──────────────┘
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
- **CLI Commands** - Parse arguments, communicate with daemon via IPC
|
|
283
|
+
- **IPC Server** - Background daemon managing Telegram connection
|
|
284
|
+
- **Telegram Client** - MTProto client using [gotd/td](https://github.com/gotd/td) library
|
|
285
|
+
|
|
286
|
+
The daemon starts automatically on first command and persists between commands for fast subsequent operations.
|
|
287
|
+
|
|
288
|
+
### File Locations
|
|
289
|
+
|
|
290
|
+
| File | Path |
|
|
291
|
+
|------|------|
|
|
292
|
+
| Unix socket | `/tmp/agent-telegram.sock` |
|
|
293
|
+
| Session | `~/.agent-telegram/session.json` |
|
|
294
|
+
| Logs | `~/.agent-telegram/server.log` |
|
|
295
|
+
| PID file | `~/.agent-telegram/server.pid` |
|
|
296
|
+
| Lock file | `~/.agent-telegram/server.lock` |
|
|
297
|
+
|
|
298
|
+
## Sessions
|
|
299
|
+
|
|
300
|
+
Each session maintains its own:
|
|
301
|
+
- Telegram connection
|
|
302
|
+
- Authentication state
|
|
303
|
+
- Message history cache
|
|
304
|
+
- Update store
|
|
305
|
+
|
|
306
|
+
Use `--socket` to run multiple isolated instances:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
# Different sessions
|
|
310
|
+
agent-telegram --socket /tmp/agent1.sock serve
|
|
311
|
+
agent-telegram --socket /tmp/agent2.sock serve
|
|
312
|
+
|
|
313
|
+
# Use specific session
|
|
314
|
+
agent-telegram --socket /tmp/agent1.sock chat list
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Usage with AI Agents
|
|
318
|
+
|
|
319
|
+
### Just ask the agent
|
|
320
|
+
|
|
321
|
+
The simplest approach - just tell your agent to use it:
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
Use agent-telegram to send a message to @username. Run agent-telegram --help to see available commands.
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
```markdown
|
|
328
|
+
## Telegram Automation
|
|
329
|
+
|
|
330
|
+
Use `agent-telegram` for Telegram automation. Run `agent-telegram --help` for all commands.
|
|
331
|
+
|
|
332
|
+
Core workflow:
|
|
333
|
+
1. `agent-telegram serve` - Start background server
|
|
334
|
+
2. `agent-telegram status` - Verify connection
|
|
335
|
+
3. `agent-telegram chat list --json` - List available chats
|
|
336
|
+
4. `agent-telegram chat open @user --json` - Read messages
|
|
337
|
+
5. `agent-telegram send --to @user "message"` - Send message
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## Development
|
|
341
|
+
|
|
342
|
+
See [DEVELOPMENT.md](DEVELOPMENT.md) for:
|
|
343
|
+
- Architecture overview
|
|
344
|
+
- Adding new commands
|
|
345
|
+
- Common patterns
|
|
346
|
+
- Project structure
|
|
347
|
+
|
|
348
|
+
## License
|
|
349
|
+
|
|
350
|
+
MIT
|
package/bin/custom-gcl
ADDED
|
Binary file
|
|
Binary file
|
package/bin/run.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require("child_process");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
const BINARY_NAME = process.platform === "win32" ? "agent-telegram.exe" : "agent-telegram";
|
|
7
|
+
const binaryPath = path.join(__dirname, BINARY_NAME);
|
|
8
|
+
|
|
9
|
+
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
10
|
+
stdio: "inherit",
|
|
11
|
+
env: process.env,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
child.on("error", (err) => {
|
|
15
|
+
if (err.code === "ENOENT") {
|
|
16
|
+
console.error(`Binary not found at ${binaryPath}`);
|
|
17
|
+
console.error("Run 'npm run postinstall' or build from source");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
throw err;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
child.on("exit", (code) => {
|
|
24
|
+
process.exit(code ?? 0);
|
|
25
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-telegram",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Telegram IPC agent CLI - interact with Telegram via command line",
|
|
5
|
+
"bin": {
|
|
6
|
+
"agent-telegram": "./bin/run.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"postinstall": "node ./scripts/install.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"bin/",
|
|
13
|
+
"scripts/"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"telegram",
|
|
17
|
+
"cli",
|
|
18
|
+
"ipc",
|
|
19
|
+
"agent",
|
|
20
|
+
"messaging"
|
|
21
|
+
],
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/dukaev/agent-telegram.git"
|
|
25
|
+
},
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=16"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Build binaries for all supported platforms
|
|
4
|
+
# Run from project root: ./scripts/build-all.sh
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
VERSION=${1:-$(node -p "require('./package.json').version")}
|
|
9
|
+
OUTPUT_DIR="dist"
|
|
10
|
+
BINARY_NAME="agent-telegram"
|
|
11
|
+
|
|
12
|
+
# Platforms to build for
|
|
13
|
+
PLATFORMS=(
|
|
14
|
+
"darwin/amd64"
|
|
15
|
+
"darwin/arm64"
|
|
16
|
+
"linux/amd64"
|
|
17
|
+
"linux/arm64"
|
|
18
|
+
"windows/amd64"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
echo "Building ${BINARY_NAME} v${VERSION}..."
|
|
22
|
+
mkdir -p "${OUTPUT_DIR}"
|
|
23
|
+
|
|
24
|
+
for PLATFORM in "${PLATFORMS[@]}"; do
|
|
25
|
+
GOOS="${PLATFORM%/*}"
|
|
26
|
+
GOARCH="${PLATFORM#*/}"
|
|
27
|
+
|
|
28
|
+
OUTPUT="${OUTPUT_DIR}/${BINARY_NAME}-${GOOS}-${GOARCH}"
|
|
29
|
+
if [ "$GOOS" = "windows" ]; then
|
|
30
|
+
OUTPUT="${OUTPUT}.exe"
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
echo "Building ${GOOS}/${GOARCH}..."
|
|
34
|
+
GOOS=$GOOS GOARCH=$GOARCH go build -ldflags="-s -w -X main.version=${VERSION}" -o "$OUTPUT" .
|
|
35
|
+
done
|
|
36
|
+
|
|
37
|
+
echo ""
|
|
38
|
+
echo "Built binaries:"
|
|
39
|
+
ls -lh "${OUTPUT_DIR}/"
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const https = require("https");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const { execSync } = require("child_process");
|
|
7
|
+
const zlib = require("zlib");
|
|
8
|
+
|
|
9
|
+
const PACKAGE = require("../package.json");
|
|
10
|
+
const BINARY_NAME = "agent-telegram";
|
|
11
|
+
const REPO = "dukaev/agent-telegram";
|
|
12
|
+
|
|
13
|
+
// Map Node.js platform/arch to Go GOOS/GOARCH
|
|
14
|
+
const PLATFORM_MAP = {
|
|
15
|
+
darwin: "darwin",
|
|
16
|
+
linux: "linux",
|
|
17
|
+
win32: "windows",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const ARCH_MAP = {
|
|
21
|
+
x64: "amd64",
|
|
22
|
+
arm64: "arm64",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function getPlatform() {
|
|
26
|
+
const platform = PLATFORM_MAP[process.platform];
|
|
27
|
+
const arch = ARCH_MAP[process.arch];
|
|
28
|
+
|
|
29
|
+
if (!platform || !arch) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`Unsupported platform: ${process.platform}-${process.arch}`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return { platform, arch };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function getBinaryName(platform) {
|
|
39
|
+
return platform === "windows" ? `${BINARY_NAME}.exe` : BINARY_NAME;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getDownloadUrl(version, platform, arch) {
|
|
43
|
+
// GoReleaser archive format: agent-telegram_0.1.0_darwin_arm64.tar.gz
|
|
44
|
+
const ext = platform === "windows" ? "zip" : "tar.gz";
|
|
45
|
+
return `https://github.com/${REPO}/releases/download/v${version}/${BINARY_NAME}_${version}_${platform}_${arch}.${ext}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function fetch(url) {
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
const request = (url) => {
|
|
51
|
+
https
|
|
52
|
+
.get(url, (response) => {
|
|
53
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
54
|
+
request(response.headers.location);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (response.statusCode !== 200) {
|
|
58
|
+
reject(new Error(`HTTP ${response.statusCode}: ${url}`));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
resolve(response);
|
|
62
|
+
})
|
|
63
|
+
.on("error", reject);
|
|
64
|
+
};
|
|
65
|
+
request(url);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function downloadAndExtract(url, destDir, binaryName) {
|
|
70
|
+
console.log(`Downloading from ${url}...`);
|
|
71
|
+
|
|
72
|
+
const response = await fetch(url);
|
|
73
|
+
const chunks = [];
|
|
74
|
+
|
|
75
|
+
await new Promise((resolve, reject) => {
|
|
76
|
+
response.on("data", (chunk) => chunks.push(chunk));
|
|
77
|
+
response.on("end", resolve);
|
|
78
|
+
response.on("error", reject);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const buffer = Buffer.concat(chunks);
|
|
82
|
+
|
|
83
|
+
if (url.endsWith(".tar.gz")) {
|
|
84
|
+
// Extract tar.gz using tar command
|
|
85
|
+
const archivePath = path.join(destDir, "archive.tar.gz");
|
|
86
|
+
fs.writeFileSync(archivePath, buffer);
|
|
87
|
+
execSync(`tar -xzf "${archivePath}" -C "${destDir}"`, { stdio: "pipe" });
|
|
88
|
+
fs.unlinkSync(archivePath);
|
|
89
|
+
} else if (url.endsWith(".zip")) {
|
|
90
|
+
// For Windows zip files
|
|
91
|
+
const archivePath = path.join(destDir, "archive.zip");
|
|
92
|
+
fs.writeFileSync(archivePath, buffer);
|
|
93
|
+
try {
|
|
94
|
+
execSync(`unzip -o "${archivePath}" -d "${destDir}"`, { stdio: "pipe" });
|
|
95
|
+
} catch {
|
|
96
|
+
// Try PowerShell on Windows
|
|
97
|
+
execSync(
|
|
98
|
+
`powershell -command "Expand-Archive -Path '${archivePath}' -DestinationPath '${destDir}' -Force"`,
|
|
99
|
+
{ stdio: "pipe" }
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
fs.unlinkSync(archivePath);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Find and move binary to bin directory
|
|
106
|
+
const extractedBinary = findBinary(destDir, binaryName);
|
|
107
|
+
if (extractedBinary) {
|
|
108
|
+
const finalPath = path.join(destDir, binaryName);
|
|
109
|
+
if (extractedBinary !== finalPath) {
|
|
110
|
+
fs.renameSync(extractedBinary, finalPath);
|
|
111
|
+
}
|
|
112
|
+
fs.chmodSync(finalPath, 0o755);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Clean up extra files from archive
|
|
116
|
+
const keepFiles = [binaryName, "run.js"];
|
|
117
|
+
for (const file of fs.readdirSync(destDir)) {
|
|
118
|
+
if (!keepFiles.includes(file)) {
|
|
119
|
+
const filePath = path.join(destDir, file);
|
|
120
|
+
const stat = fs.statSync(filePath);
|
|
121
|
+
if (stat.isFile() && !file.endsWith(".js")) {
|
|
122
|
+
// Keep JS files, remove others like LICENSE, README
|
|
123
|
+
fs.unlinkSync(filePath);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function findBinary(dir, binaryName) {
|
|
130
|
+
const files = fs.readdirSync(dir);
|
|
131
|
+
for (const file of files) {
|
|
132
|
+
const filePath = path.join(dir, file);
|
|
133
|
+
const stat = fs.statSync(filePath);
|
|
134
|
+
if (stat.isDirectory()) {
|
|
135
|
+
const found = findBinary(filePath, binaryName);
|
|
136
|
+
if (found) return found;
|
|
137
|
+
} else if (file === binaryName) {
|
|
138
|
+
return filePath;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async function main() {
|
|
145
|
+
const binDir = path.join(__dirname, "..", "bin");
|
|
146
|
+
const { platform, arch } = getPlatform();
|
|
147
|
+
const binaryName = getBinaryName(platform);
|
|
148
|
+
const binaryPath = path.join(binDir, binaryName);
|
|
149
|
+
|
|
150
|
+
// Skip if binary already exists
|
|
151
|
+
if (fs.existsSync(binaryPath)) {
|
|
152
|
+
console.log(`Binary already exists at ${binaryPath}`);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const url = getDownloadUrl(PACKAGE.version, platform, arch);
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
await downloadAndExtract(url, binDir, binaryName);
|
|
160
|
+
console.log(`Successfully installed ${BINARY_NAME} v${PACKAGE.version}`);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error(`Failed to download binary: ${error.message}`);
|
|
163
|
+
console.error("");
|
|
164
|
+
console.error("Manual installation options:");
|
|
165
|
+
console.error(` 1. Download from: https://github.com/${REPO}/releases`);
|
|
166
|
+
console.error(" 2. Build from source: go build -o bin/agent-telegram .");
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
main();
|