supertelegram 0.3.1 → 0.4.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 +9 -5
- package/package.json +1 -1
- package/src/cli/commands.ts +10 -2
- package/src/cli/run.ts +3 -2
- package/src/client/telegram.ts +53 -3
- package/tsconfig.json +1 -0
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
telegram cli for ai to read/write messages using gramjs.
|
|
4
4
|
|
|
5
|
+
> **warning:** don't use this to send spam or abuse the telegram api. your account can get banned.
|
|
6
|
+
|
|
5
7
|
## installation
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -30,9 +32,11 @@ that's it! now you're ready to use telegram from the cli.
|
|
|
30
32
|
### messages
|
|
31
33
|
|
|
32
34
|
```bash
|
|
33
|
-
# send a message
|
|
35
|
+
# send a message — chat can be @username, a numeric id, or a name
|
|
34
36
|
telegram send @username "hello there"
|
|
35
|
-
telegram send
|
|
37
|
+
telegram send 7069934904 "hey" # by id (for chats with no username)
|
|
38
|
+
telegram send "Ben YC" "hello" # by name (partial, case-insensitive)
|
|
39
|
+
telegram send "me" "note to self" # use "me" for saved messages
|
|
36
40
|
|
|
37
41
|
# read messages (shows [photo], [video], [file] indicators)
|
|
38
42
|
telegram read @username 10
|
|
@@ -43,7 +47,7 @@ telegram reply "John" "hey back!"
|
|
|
43
47
|
# get unread messages (json output with media info)
|
|
44
48
|
telegram unread 20
|
|
45
49
|
|
|
46
|
-
# list dialogs
|
|
50
|
+
# list dialogs (shows @username and [id: ...] for each chat)
|
|
47
51
|
telegram dialogs 10
|
|
48
52
|
```
|
|
49
53
|
|
|
@@ -99,8 +103,8 @@ telegram send @friend "hey" --session ./custom.txt
|
|
|
99
103
|
|
|
100
104
|
clone repo and install:
|
|
101
105
|
```bash
|
|
102
|
-
git clone https://github.com/caffeinum/
|
|
103
|
-
cd
|
|
106
|
+
git clone https://github.com/caffeinum/supertelegram.git
|
|
107
|
+
cd supertelegram
|
|
104
108
|
bun install
|
|
105
109
|
```
|
|
106
110
|
|
package/package.json
CHANGED
package/src/cli/commands.ts
CHANGED
|
@@ -71,8 +71,16 @@ export async function dialogs(limit = 10) {
|
|
|
71
71
|
|
|
72
72
|
const dialogList = await getDialogs(limit);
|
|
73
73
|
for (const dialog of dialogList) {
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
const entity = dialog.entity;
|
|
75
|
+
const username =
|
|
76
|
+
entity && "username" in entity && entity.username
|
|
77
|
+
? ` @${entity.username}`
|
|
78
|
+
: "";
|
|
79
|
+
const id = dialog.id?.toString() ?? entity?.id?.toString() ?? "?";
|
|
80
|
+
const unread = dialog.unreadCount > 0 ? ` (${dialog.unreadCount} unread)` : "";
|
|
81
|
+
console.log(`- ${dialog.title}${username} [id: ${id}]${unread}`);
|
|
82
|
+
}
|
|
83
|
+
console.log("\nsend with: telegram send <@username|id> \"your message\"");
|
|
76
84
|
await disconnect();
|
|
77
85
|
}
|
|
78
86
|
|
package/src/cli/run.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { send, read, dialogs, unread, reply, login, config, sendFile, downloadMedia } from "./commands";
|
|
3
3
|
import { setVerbose, setSessionPath } from "../client/telegram";
|
|
4
|
+
import pkg from "../../package.json";
|
|
4
5
|
|
|
5
|
-
const VERSION =
|
|
6
|
+
const VERSION = pkg.version;
|
|
6
7
|
const NAME = "telegram";
|
|
7
8
|
|
|
8
9
|
const HELP = `
|
|
@@ -12,7 +13,7 @@ usage:
|
|
|
12
13
|
${NAME} <command> [options]
|
|
13
14
|
|
|
14
15
|
commands:
|
|
15
|
-
send <chat> <message> send a message
|
|
16
|
+
send <chat> <message> send a message (chat = @username, id, or name)
|
|
16
17
|
send-file <chat> <path> send a file/image/video (optional: caption)
|
|
17
18
|
read <chat> [limit] read messages from a chat (default: 10)
|
|
18
19
|
download <chat> <id> [out] download media from message id
|
package/src/client/telegram.ts
CHANGED
|
@@ -76,12 +76,60 @@ export async function login(callbacks: {
|
|
|
76
76
|
console.log("session saved!");
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
// a chat can be addressed by @username, "me", phone (+123), t.me link,
|
|
80
|
+
// or a numeric id copied from `telegram dialogs`. usernames/links resolve
|
|
81
|
+
// natively; numeric ids and bare names need the dialog entity cache, so we
|
|
82
|
+
// look them up here.
|
|
83
|
+
export async function resolveEntity(
|
|
84
|
+
identifier: string
|
|
85
|
+
): Promise<string | Api.TypeEntityLike> {
|
|
86
|
+
const c = await getClient();
|
|
87
|
+
const id = identifier.trim();
|
|
88
|
+
|
|
89
|
+
// things gramjs resolves on its own
|
|
90
|
+
if (
|
|
91
|
+
id === "me" ||
|
|
92
|
+
id.startsWith("@") ||
|
|
93
|
+
id.startsWith("+") ||
|
|
94
|
+
id.startsWith("http")
|
|
95
|
+
) {
|
|
96
|
+
return id;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// numeric id (users positive, chats/channels may be negative)
|
|
100
|
+
if (/^-?\d+$/.test(id)) {
|
|
101
|
+
try {
|
|
102
|
+
// fast path: entity already in the session cache
|
|
103
|
+
return await c.getInputEntity(id);
|
|
104
|
+
} catch {
|
|
105
|
+
// slow path: fetch dialogs to populate + match the entity
|
|
106
|
+
const match = (await c.getDialogs({ limit: 200 })).find(
|
|
107
|
+
(d) => d.id?.toString() === id || d.entity?.id?.toString() === id
|
|
108
|
+
);
|
|
109
|
+
if (match?.entity) return match.entity;
|
|
110
|
+
throw new Error(
|
|
111
|
+
`chat with id ${id} not found in your dialogs. run: telegram dialogs 200`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// bare name: partial, case-insensitive match against dialog titles
|
|
117
|
+
const match = (await c.getDialogs({ limit: 200 })).find((d) =>
|
|
118
|
+
d.title?.toLowerCase().includes(id.toLowerCase())
|
|
119
|
+
);
|
|
120
|
+
if (match?.entity) return match.entity;
|
|
121
|
+
|
|
122
|
+
// let gramjs take a final shot (e.g. a username without the @)
|
|
123
|
+
return id;
|
|
124
|
+
}
|
|
125
|
+
|
|
79
126
|
export async function sendMessage(
|
|
80
127
|
username: string,
|
|
81
128
|
message: string
|
|
82
129
|
): Promise<Api.Message> {
|
|
83
130
|
const c = await getClient();
|
|
84
|
-
|
|
131
|
+
const entity = await resolveEntity(username);
|
|
132
|
+
return c.sendMessage(entity, { message });
|
|
85
133
|
}
|
|
86
134
|
|
|
87
135
|
export async function sendFile(
|
|
@@ -90,7 +138,8 @@ export async function sendFile(
|
|
|
90
138
|
caption?: string
|
|
91
139
|
): Promise<Api.Message> {
|
|
92
140
|
const c = await getClient();
|
|
93
|
-
|
|
141
|
+
const entity = await resolveEntity(username);
|
|
142
|
+
return c.sendFile(entity, {
|
|
94
143
|
file: filePath,
|
|
95
144
|
caption: caption,
|
|
96
145
|
});
|
|
@@ -117,7 +166,8 @@ export async function getMessages(
|
|
|
117
166
|
limit = 10
|
|
118
167
|
): Promise<Api.Message[]> {
|
|
119
168
|
const c = await getClient();
|
|
120
|
-
const
|
|
169
|
+
const entity = await resolveEntity(username);
|
|
170
|
+
const messages = await c.getMessages(entity, { limit });
|
|
121
171
|
return messages as Api.Message[];
|
|
122
172
|
}
|
|
123
173
|
|