supertelegram 0.2.0 → 0.3.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 +22 -7
- package/package.json +1 -1
- package/src/cli/commands.ts +67 -1
- package/src/cli/run.ts +28 -8
- package/src/client/telegram.ts +28 -0
package/README.md
CHANGED
|
@@ -27,21 +27,36 @@ that's it! now you're ready to use telegram from the cli.
|
|
|
27
27
|
|
|
28
28
|
## usage
|
|
29
29
|
|
|
30
|
+
### messages
|
|
31
|
+
|
|
30
32
|
```bash
|
|
31
33
|
# send a message
|
|
32
|
-
telegram send
|
|
34
|
+
telegram send @username "hello there"
|
|
33
35
|
|
|
34
|
-
# read messages
|
|
35
|
-
telegram read
|
|
36
|
+
# read messages (shows [photo], [video], [file] indicators)
|
|
37
|
+
telegram read @username 10
|
|
36
38
|
|
|
37
39
|
# reply to latest message
|
|
38
|
-
telegram reply
|
|
40
|
+
telegram reply "John" "hey back!"
|
|
39
41
|
|
|
40
|
-
# get unread messages (json output)
|
|
41
|
-
telegram unread
|
|
42
|
+
# get unread messages (json output with media info)
|
|
43
|
+
telegram unread 20
|
|
42
44
|
|
|
43
45
|
# list dialogs
|
|
44
|
-
telegram dialogs
|
|
46
|
+
telegram dialogs 10
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### media (images/videos/files)
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# send a file with optional caption
|
|
53
|
+
telegram send-file @username photo.jpg
|
|
54
|
+
telegram send-file @username video.mp4 "check this out!"
|
|
55
|
+
|
|
56
|
+
# download media from a message
|
|
57
|
+
# (use 'read' command to get message IDs)
|
|
58
|
+
telegram download @username 12345 ./downloaded.jpg
|
|
59
|
+
telegram download @username 12346 # auto-named file
|
|
45
60
|
```
|
|
46
61
|
|
|
47
62
|
### config
|
package/package.json
CHANGED
package/src/cli/commands.ts
CHANGED
|
@@ -6,9 +6,12 @@ import {
|
|
|
6
6
|
disconnect,
|
|
7
7
|
getClient,
|
|
8
8
|
login as telegramLogin,
|
|
9
|
+
sendFile as telegramSendFile,
|
|
10
|
+
downloadMedia as telegramDownloadMedia,
|
|
9
11
|
} from "../client/telegram";
|
|
10
12
|
import { askPhoneNumber, askPhoneCode, askPassword, askAppId, askAppHash } from "./prompts";
|
|
11
13
|
import { getApiCredentials, setConfig } from "../config/manager";
|
|
14
|
+
import { Api } from "telegram";
|
|
12
15
|
|
|
13
16
|
export async function send(username: string, message: string) {
|
|
14
17
|
if (!(await isLoggedIn())) {
|
|
@@ -21,6 +24,29 @@ export async function send(username: string, message: string) {
|
|
|
21
24
|
await disconnect();
|
|
22
25
|
}
|
|
23
26
|
|
|
27
|
+
function getMediaInfo(msg: Api.Message): string {
|
|
28
|
+
if (!msg.media) return "";
|
|
29
|
+
|
|
30
|
+
if (msg.media instanceof Api.MessageMediaPhoto) {
|
|
31
|
+
return " [photo]";
|
|
32
|
+
}
|
|
33
|
+
if (msg.media instanceof Api.MessageMediaDocument) {
|
|
34
|
+
const doc = msg.media.document;
|
|
35
|
+
if (doc instanceof Api.Document) {
|
|
36
|
+
const attrs = doc.attributes;
|
|
37
|
+
const filenameAttr = attrs.find((a) => "fileName" in a && a.fileName);
|
|
38
|
+
const filename = filenameAttr && "fileName" in filenameAttr ? filenameAttr.fileName : undefined;
|
|
39
|
+
const isVideo = attrs.some((a) => a instanceof Api.DocumentAttributeVideo);
|
|
40
|
+
const isAudio = attrs.some((a) => a instanceof Api.DocumentAttributeAudio);
|
|
41
|
+
|
|
42
|
+
if (isVideo) return ` [video${filename ? `: ${filename}` : ""}]`;
|
|
43
|
+
if (isAudio) return ` [audio${filename ? `: ${filename}` : ""}]`;
|
|
44
|
+
return ` [file${filename ? `: ${filename}` : ""}]`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return " [media]";
|
|
48
|
+
}
|
|
49
|
+
|
|
24
50
|
export async function read(username: string, limit = 10) {
|
|
25
51
|
if (!(await isLoggedIn())) {
|
|
26
52
|
console.error("not logged in. run: telegram login");
|
|
@@ -31,7 +57,8 @@ export async function read(username: string, limit = 10) {
|
|
|
31
57
|
for (const msg of messages.reverse()) {
|
|
32
58
|
const sender = msg.senderId?.toString() ?? "unknown";
|
|
33
59
|
const date = msg.date ? new Date(msg.date * 1000).toISOString() : "";
|
|
34
|
-
|
|
60
|
+
const mediaInfo = getMediaInfo(msg);
|
|
61
|
+
console.log(`[${date}] [${sender}]: ${msg.message}${mediaInfo}`);
|
|
35
62
|
}
|
|
36
63
|
await disconnect();
|
|
37
64
|
}
|
|
@@ -88,6 +115,7 @@ export async function unread(limit = 20) {
|
|
|
88
115
|
messages: fromOthers.map((m) => ({
|
|
89
116
|
id: m.id,
|
|
90
117
|
text: m.message,
|
|
118
|
+
media: m.media ? getMediaInfo(m).trim() : null,
|
|
91
119
|
date: m.date ? new Date(m.date * 1000).toISOString() : null,
|
|
92
120
|
})),
|
|
93
121
|
});
|
|
@@ -179,3 +207,41 @@ export async function config(action?: string, key?: string, value?: string) {
|
|
|
179
207
|
console.log(" telegram config set appHash <hash>");
|
|
180
208
|
console.log(" telegram config get appId");
|
|
181
209
|
}
|
|
210
|
+
|
|
211
|
+
export async function sendFile(username: string, filePath: string, caption?: string) {
|
|
212
|
+
if (!(await isLoggedIn())) {
|
|
213
|
+
console.error("not logged in. run: telegram login");
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const result = await telegramSendFile(username, filePath, caption);
|
|
218
|
+
console.log(`sent file id: ${result.id}`);
|
|
219
|
+
await disconnect();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export async function downloadMedia(username: string, messageId: number, outputPath?: string) {
|
|
223
|
+
if (!(await isLoggedIn())) {
|
|
224
|
+
console.error("not logged in. run: telegram login");
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const messages = await getMessages(username, 100);
|
|
229
|
+
const msg = messages.find((m) => m.id === messageId);
|
|
230
|
+
|
|
231
|
+
if (!msg) {
|
|
232
|
+
console.error(`message ${messageId} not found`);
|
|
233
|
+
await disconnect();
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (!msg.media) {
|
|
238
|
+
console.error(`message ${messageId} has no media`);
|
|
239
|
+
await disconnect();
|
|
240
|
+
process.exit(1);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
console.log("downloading media...");
|
|
244
|
+
const path = await telegramDownloadMedia(msg, outputPath);
|
|
245
|
+
console.log(`saved to: ${path || outputPath || "unknown"}`);
|
|
246
|
+
await disconnect();
|
|
247
|
+
}
|
package/src/cli/run.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import { send, read, dialogs, unread, reply, login, config } from "./commands";
|
|
2
|
+
import { send, read, dialogs, unread, reply, login, config, sendFile, downloadMedia } from "./commands";
|
|
3
3
|
import { setVerbose, setSessionPath } from "../client/telegram";
|
|
4
4
|
|
|
5
5
|
const VERSION = "0.1.0";
|
|
@@ -12,13 +12,15 @@ usage:
|
|
|
12
12
|
${NAME} <command> [options]
|
|
13
13
|
|
|
14
14
|
commands:
|
|
15
|
-
send <chat> <message>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
send <chat> <message> send a message to a chat
|
|
16
|
+
send-file <chat> <path> send a file/image/video (optional: caption)
|
|
17
|
+
read <chat> [limit] read messages from a chat (default: 10)
|
|
18
|
+
download <chat> <id> [out] download media from message id
|
|
19
|
+
reply <chat> <message> reply to a chat by name (partial match)
|
|
20
|
+
dialogs [limit] list recent dialogs (default: 10)
|
|
21
|
+
unread [limit] show unread messages as json (default: 20)
|
|
22
|
+
login authenticate with telegram
|
|
23
|
+
config set <key> <val> set API credentials (appId, appHash)
|
|
22
24
|
|
|
23
25
|
options:
|
|
24
26
|
-v, --verbose show debug logs
|
|
@@ -27,7 +29,9 @@ options:
|
|
|
27
29
|
|
|
28
30
|
examples:
|
|
29
31
|
${NAME} send @username "hello there"
|
|
32
|
+
${NAME} send-file @username photo.jpg "check this out"
|
|
30
33
|
${NAME} read @username 5
|
|
34
|
+
${NAME} download @username 12345 ./photo.jpg
|
|
31
35
|
${NAME} reply "John" "hey!"
|
|
32
36
|
${NAME} unread
|
|
33
37
|
${NAME} dialogs 20
|
|
@@ -88,6 +92,22 @@ async function main() {
|
|
|
88
92
|
await reply(rest[0], rest.slice(1).join(" "));
|
|
89
93
|
break;
|
|
90
94
|
|
|
95
|
+
case "send-file":
|
|
96
|
+
if (rest.length < 2 || !rest[0] || !rest[1]) {
|
|
97
|
+
console.error("usage: telegram send-file <chat> <path> [caption]");
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
await sendFile(rest[0], rest[1], rest.slice(2).join(" ") || undefined);
|
|
101
|
+
break;
|
|
102
|
+
|
|
103
|
+
case "download":
|
|
104
|
+
if (rest.length < 2 || !rest[0] || !rest[1]) {
|
|
105
|
+
console.error("usage: telegram download <chat> <message-id> [output-path]");
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
await downloadMedia(rest[0], Number.parseInt(rest[1]), rest[2]);
|
|
109
|
+
break;
|
|
110
|
+
|
|
91
111
|
case "login":
|
|
92
112
|
await login();
|
|
93
113
|
break;
|
package/src/client/telegram.ts
CHANGED
|
@@ -84,6 +84,34 @@ export async function sendMessage(
|
|
|
84
84
|
return c.sendMessage(username, { message });
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
export async function sendFile(
|
|
88
|
+
username: string,
|
|
89
|
+
filePath: string,
|
|
90
|
+
caption?: string
|
|
91
|
+
): Promise<Api.Message> {
|
|
92
|
+
const c = await getClient();
|
|
93
|
+
return c.sendFile(username, {
|
|
94
|
+
file: filePath,
|
|
95
|
+
caption: caption,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export async function downloadMedia(
|
|
100
|
+
message: Api.Message,
|
|
101
|
+
outputPath?: string
|
|
102
|
+
): Promise<string | undefined> {
|
|
103
|
+
const c = await getClient();
|
|
104
|
+
if (!message.media) {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const buffer = await c.downloadMedia(message, {
|
|
109
|
+
outputFile: outputPath,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
return buffer as string | undefined;
|
|
113
|
+
}
|
|
114
|
+
|
|
87
115
|
export async function getMessages(
|
|
88
116
|
username: string,
|
|
89
117
|
limit = 10
|