tca-js 0.3.0 → 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 +202 -100
- package/dist/index.d.mts +369 -0
- package/dist/index.d.ts +362 -26
- package/dist/index.js +1304 -52
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1262 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +56 -10
- package/dist/api.d.ts +0 -75
- package/dist/api.js +0 -277
- package/dist/constants.d.ts +0 -86
- package/dist/constants.js +0 -77
- package/dist/context.d.ts +0 -32
- package/dist/context.js +0 -129
- package/dist/errors.d.ts +0 -18
- package/dist/errors.js +0 -17
- package/dist/listener.d.ts +0 -43
- package/dist/listener.js +0 -181
- package/dist/lz4.d.ts +0 -5
- package/dist/lz4.js +0 -57
- package/dist/media.d.ts +0 -27
- package/dist/media.js +0 -152
- package/dist/message.d.ts +0 -6
- package/dist/message.js +0 -113
- package/dist/proto.d.ts +0 -43
- package/dist/proto.js +0 -162
- package/dist/qr-login.d.ts +0 -41
- package/dist/qr-login.js +0 -212
- package/dist/types.d.ts +0 -109
- package/dist/types.js +0 -2
package/README.md
CHANGED
|
@@ -1,133 +1,235 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
websocket — **using session cookies only, no browser needed**. Same idea as [`zca-js`](https://github.com/RFS-ADRENO/zca-js)
|
|
5
|
-
for Zalo: it speaks the same protocol as TikTok Web (`tiktok.com/messages`, `tiktok.com/business-suite/messages`).
|
|
3
|
+
# tca-js
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
> and **can get the account restricted or banned** — use it at your own risk, don't spam.
|
|
5
|
+
**Unofficial TikTok Chat API for Node.js**
|
|
6
|
+
|
|
7
|
+
Read and send TikTok direct messages, react, and receive new messages in real time.
|
|
11
8
|
|
|
12
|
-
|
|
9
|
+
[](https://www.npmjs.com/package/tca-js)
|
|
10
|
+
[](LICENSE)
|
|
11
|
+
[](package.json)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
> [!WARNING]
|
|
16
|
+
> This project is not affiliated with or endorsed by TikTok / ByteDance. It relies on undocumented APIs that can change
|
|
17
|
+
> at any time. Automating an account may violate TikTok's Terms of Service and can get it restricted — use at your own risk.
|
|
18
|
+
|
|
19
|
+
## Table of Contents
|
|
20
|
+
|
|
21
|
+
- [Features](#features)
|
|
22
|
+
- [Installation](#installation)
|
|
23
|
+
- [Quick Start](#quick-start)
|
|
24
|
+
- [Authentication](#authentication)
|
|
25
|
+
- [API Reference](#api-reference)
|
|
26
|
+
- [Listener](#listener)
|
|
27
|
+
- [Error Handling](#error-handling)
|
|
28
|
+
- [Examples](#examples)
|
|
29
|
+
- [Contributing](#contributing)
|
|
30
|
+
- [Support Us](#support-us)
|
|
31
|
+
- [License](#license)
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- 💬 Send text and image messages
|
|
36
|
+
- 📥 List conversations, page through message history, look up users
|
|
37
|
+
- ⚡ Real-time listener over websocket with auto-reconnect
|
|
38
|
+
- 🖼️ Download and decrypt private images, download stickers and avatars
|
|
39
|
+
- ❤️ Read and set reactions, mark conversations as read
|
|
40
|
+
- 🔐 Cookie-based session — no browser at runtime
|
|
41
|
+
- 📱 Optional QR-code login
|
|
42
|
+
- 📦 Written in TypeScript, ships ESM + CommonJS builds with type definitions, one runtime dependency (`ws`)
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
13
45
|
|
|
14
46
|
```bash
|
|
15
47
|
npm install tca-js
|
|
16
48
|
```
|
|
17
49
|
|
|
18
|
-
Node.js
|
|
50
|
+
Requires **Node.js 22+**. Both ESM and CommonJS are supported:
|
|
19
51
|
|
|
20
|
-
|
|
52
|
+
```ts
|
|
53
|
+
import { TikTok } from 'tca-js'; // ESM / TypeScript
|
|
54
|
+
const { TikTok } = require('tca-js'); // CommonJS
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
QR login also needs a local Chrome or Chromium; cookie login does not.
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
21
60
|
|
|
22
61
|
```ts
|
|
23
|
-
import { TikTok
|
|
62
|
+
import { TikTok } from 'tca-js';
|
|
63
|
+
|
|
64
|
+
const api = await new TikTok().login({ cookies });
|
|
24
65
|
|
|
25
|
-
const api = await new TikTok().login(await loginQR({ chromePath, onEvent })); // or saved cookies
|
|
26
66
|
api.listener.on('message', async (msg) => {
|
|
27
67
|
if (msg.isSelf) return;
|
|
28
|
-
|
|
29
|
-
await api.sendMessage(msg, 'Got it, thanks!'); // a message carries its conversation
|
|
68
|
+
await api.sendMessage(msg, `You said: ${msg.text}`);
|
|
30
69
|
});
|
|
31
|
-
|
|
32
|
-
|
|
70
|
+
|
|
71
|
+
api.listener.start();
|
|
33
72
|
```
|
|
34
73
|
|
|
35
|
-
##
|
|
74
|
+
## Authentication
|
|
36
75
|
|
|
37
|
-
|
|
38
|
-
|---|---|
|
|
39
|
-
| `loginQR({chromePath, onEvent, signal})` | QR login through headless Chrome → `Credentials` |
|
|
40
|
-
| `new TikTok().login({cookies, deviceId?, userAgent?})` | validate cookies (`passport/web/account/info`), resolve `wid` as `device_id` → `API` |
|
|
41
|
-
| `api.getConversations(cursor?)` | 10 conversations per page + latest message; page with `cursor` |
|
|
42
|
-
| `api.getMessages(conv, {limit, before})` | messages of a conversation, newest → oldest |
|
|
43
|
-
| `api.getUsers(uids)` | display name, `@username`, avatar |
|
|
44
|
-
| `api.sendMessage(conv, text)` / `api.sendImage(conv, {data, filename})` | send |
|
|
45
|
-
| `api.setReaction(msg, emoji \| null)` | your reaction on a message (one per user, `null` = remove); read via `msg.reactions` |
|
|
46
|
-
| `api.downloadSticker(msg.sticker)` | sticker image (public CDN) |
|
|
47
|
-
| `api.downloadImage(msg)` | download + decrypt AES-256-GCM (listener messages carry no link — looked up from history) |
|
|
48
|
-
| `api.markRead(msg)` · `api.isAlive()` · `api.getCookies()` | |
|
|
49
|
-
| `api.listener` | events `connected` · `message` · `command` (read receipts…) · `closed` · `error` |
|
|
76
|
+
### Cookies
|
|
50
77
|
|
|
51
|
-
|
|
78
|
+
Log in with the cookies of a `tiktok.com` session. Accepted formats:
|
|
52
79
|
|
|
53
|
-
|
|
80
|
+
```ts
|
|
81
|
+
await new TikTok().login({ cookies: [{ name: 'sessionid', value: '…' } /* … */] }); // array
|
|
82
|
+
await new TikTok().login({ cookies: { sessionid: '…', ttwid: '…' } }); // object
|
|
83
|
+
await new TikTok().login({ cookies: 'sessionid=…; ttwid=…' }); // header string
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Required cookies: `sessionid`, `sid_tt`, `sid_guard`, `uid_tt`, `ttwid`, `odin_tt`, `store-idc`, `tt-target-idc`.
|
|
87
|
+
A session lasts about 6 months, and logging in does not sign out other devices.
|
|
88
|
+
|
|
89
|
+
### QR code
|
|
90
|
+
|
|
91
|
+
`loginQR` opens a headless Chrome on TikTok's QR page, emits the QR image, and resolves with credentials once the code is
|
|
92
|
+
scanned and confirmed on the phone.
|
|
54
93
|
|
|
55
94
|
```ts
|
|
56
95
|
import { loginQR, TikTok } from 'tca-js';
|
|
57
|
-
|
|
58
|
-
const
|
|
96
|
+
|
|
97
|
+
const credentials = await loginQR({
|
|
98
|
+
onEvent: (e) => {
|
|
99
|
+
if (e.type === 'qr') showQr(e.image); // data:image/png;base64,…
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const api = await new TikTok().login(credentials);
|
|
104
|
+
// Save `credentials` to skip scanning next time.
|
|
59
105
|
```
|
|
60
106
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
|
80
|
-
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
`
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
`
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
107
|
+
| Option | Type | Default | Description |
|
|
108
|
+
| ------------ | ------------- | ----------- | ---------------------------------------------------------------------------------- |
|
|
109
|
+
| `chromePath` | `string` | auto-detect | Path to Chrome / Chromium (falls back to `CHROME_PATH`, then common install paths) |
|
|
110
|
+
| `onEvent` | `(e) => void` | — | `qr` · `scanned` · `confirmed` |
|
|
111
|
+
| `signal` | `AbortSignal` | — | Cancel the login |
|
|
112
|
+
| `timeoutMs` | `number` | `300000` | Total time to wait for a scan |
|
|
113
|
+
| `maxRefresh` | `number` | `3` | Max QR regenerations after expiry |
|
|
114
|
+
| `userAgent` | `string` | — | Browser user agent |
|
|
115
|
+
|
|
116
|
+
## API Reference
|
|
117
|
+
|
|
118
|
+
`new TikTok(options?)` — `logger?: (level, msg) => void`, `timeoutMs?: number`.
|
|
119
|
+
`.login(credentials)` resolves to an `API` instance.
|
|
120
|
+
|
|
121
|
+
### Conversations & messages
|
|
122
|
+
|
|
123
|
+
| Method | Returns | Description |
|
|
124
|
+
| ---------------------------------------- | ------------------ | ---------------------------------------------------- |
|
|
125
|
+
| `getConversations(cursor?)` | `ConversationPage` | 10 conversations per page with their latest messages |
|
|
126
|
+
| `getMessages(conv, { limit?, before? })` | `MessagePage` | Messages of a conversation, newest first |
|
|
127
|
+
| `sendMessage(conv, text)` | `SendResult` | Send a text message |
|
|
128
|
+
| `sendImage(conv, { data, filename })` | `SendResult` | Send an image (`Buffer`) |
|
|
129
|
+
| `setReaction(msg, emoji \| null)` | `void` | Set your reaction; `null` removes it |
|
|
130
|
+
| `markRead(msg)` | `void` | Mark the conversation as read up to `msg` |
|
|
131
|
+
|
|
132
|
+
`conv` is any object with `conversationId` and `conversationShortId` — every message satisfies it, so you can reply
|
|
133
|
+
with `sendMessage(msg, …)`.
|
|
134
|
+
|
|
135
|
+
### Users & media
|
|
136
|
+
|
|
137
|
+
| Method | Returns | Description |
|
|
138
|
+
| ----------------------------------------- | ------------------------ | ------------------------------------ |
|
|
139
|
+
| `getUsers(uids)` | `TikTokUser[]` | Nickname, `@username`, avatar |
|
|
140
|
+
| `downloadImage(msg, 'origin' \| 'thumb')` | `Buffer` | Download and decrypt a private image |
|
|
141
|
+
| `downloadSticker(sticker)` | `{ data, type }` | Download a sticker image |
|
|
142
|
+
| `downloadAvatar(user)` | `{ data, type } \| null` | Download a user's avatar |
|
|
143
|
+
|
|
144
|
+
### Session
|
|
145
|
+
|
|
146
|
+
| Method / property | Description |
|
|
147
|
+
| ----------------- | ------------------------------------------------------------ |
|
|
148
|
+
| `account` | Logged-in account: `uid`, `username`, `screenName`, `avatar` |
|
|
149
|
+
| `getOwnId()` | Own user id |
|
|
150
|
+
| `getCookies()` | Current cookies — persist them to resume the session |
|
|
151
|
+
| `isAlive()` | `true` while the session is still valid |
|
|
152
|
+
|
|
153
|
+
### Message object
|
|
154
|
+
|
|
155
|
+
| Field | Type | Description |
|
|
156
|
+
| --------------------- | ------------------------------------------------------------------ | ------------------------ |
|
|
157
|
+
| `kind` | `'text' \| 'image' \| 'sticker' \| 'video' \| 'system' \| 'other'` | Message kind |
|
|
158
|
+
| `text` | `string` | Text content |
|
|
159
|
+
| `image` / `sticker` | `object \| null` | Attachment details |
|
|
160
|
+
| `reactions` | `{ emoji, userIds }[]` | Reactions on the message |
|
|
161
|
+
| `senderId` / `isSelf` | `string` / `boolean` | Sender |
|
|
162
|
+
| `createdAt` | `number` | Epoch milliseconds |
|
|
163
|
+
|
|
164
|
+
Full typings are shipped in `dist/index.d.ts`.
|
|
165
|
+
|
|
166
|
+
## Listener
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
api.listener.on('connected', () => console.log('connected'));
|
|
170
|
+
api.listener.on('message', (msg) => {
|
|
171
|
+
/* new message */
|
|
172
|
+
});
|
|
173
|
+
api.listener.on('command', (msg) => {
|
|
174
|
+
/* read receipts and other hidden commands */
|
|
175
|
+
});
|
|
176
|
+
api.listener.on('closed', (code, reason) => {});
|
|
177
|
+
api.listener.on('error', (err) => {});
|
|
178
|
+
|
|
179
|
+
api.listener.start(); // reconnects automatically; start({ retryOnClose: false }) to disable
|
|
180
|
+
api.listener.stop();
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Error Handling
|
|
184
|
+
|
|
185
|
+
All library errors are instances of `TikTokError` with a `code`:
|
|
186
|
+
|
|
187
|
+
| Code | Meaning |
|
|
188
|
+
| ----------------------------------- | ------------------------------------------ |
|
|
189
|
+
| `SESSION_EXPIRED` | Cookies are no longer valid — log in again |
|
|
190
|
+
| `IM_ERROR` | TikTok rejected the request |
|
|
191
|
+
| `HTTP_ERROR` · `BAD_RESPONSE` | Network or unexpected response |
|
|
192
|
+
| `UPLOAD_FAILED` · `DOWNLOAD_FAILED` | Media transfer failed |
|
|
193
|
+
| `LOGIN_FAILED` · `LOGIN_ABORTED` | QR login failed or was cancelled |
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import { TikTokError } from 'tca-js';
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
await api.sendMessage(conv, 'hi');
|
|
200
|
+
} catch (err) {
|
|
201
|
+
if (err instanceof TikTokError && err.code === 'SESSION_EXPIRED') {
|
|
202
|
+
// refresh credentials
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Examples
|
|
208
|
+
|
|
209
|
+
- [`examples/qr-login.ts`](examples/qr-login.ts) — log in with a QR code and save the credentials to a file
|
|
210
|
+
- [`examples/echo-bot.ts`](examples/echo-bot.ts) — reply to every incoming text message
|
|
211
|
+
|
|
212
|
+
## Contributing
|
|
213
|
+
|
|
214
|
+
Issues and pull requests are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). Protocol notes for maintainers are in [docs/PROTOCOL.md](docs/PROTOCOL.md).
|
|
120
215
|
|
|
121
216
|
```bash
|
|
122
|
-
npm install
|
|
123
|
-
|
|
124
|
-
|
|
217
|
+
npm install
|
|
218
|
+
npm test # unit tests (no network)
|
|
219
|
+
npm run lint && npm run typecheck
|
|
220
|
+
npm run build
|
|
221
|
+
node scripts/smoke.mjs --cookies cookies.json # read-only smoke test against a real account
|
|
125
222
|
```
|
|
126
223
|
|
|
127
|
-
|
|
224
|
+
## Support Us
|
|
225
|
+
|
|
226
|
+
- ⭐ **Star the repository** if you find it useful
|
|
227
|
+
- 🔄 **Share** it with others
|
|
228
|
+
- 💡 **Contribute** ideas and code
|
|
229
|
+
- ☕ **Buy me a coffee** — VietQR (MB Bank · `0776750418`)
|
|
128
230
|
|
|
129
|
-
|
|
231
|
+
<img src=".github/assets/vietqr-mb.png" alt="VietQR MB Bank 0776750418" width="220">
|
|
130
232
|
|
|
131
233
|
## License
|
|
132
234
|
|
|
133
|
-
[MIT](LICENSE)
|
|
235
|
+
[MIT](LICENSE) © rice2411
|