@tiktool/live 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/LICENSE +21 -0
- package/README.md +251 -0
- package/dist/index.d.mts +173 -0
- package/dist/index.d.ts +173 -0
- package/dist/index.js +500 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +463 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 tiktool
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# @tiktool/live
|
|
4
|
+
|
|
5
|
+
### Connect to any TikTok LIVE stream in 3 lines of code.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@tiktool/live)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://nodejs.org)
|
|
10
|
+
[](https://www.typescriptlang.org)
|
|
11
|
+
|
|
12
|
+
Real-time chat, gifts, viewers, battles, follows & 18+ event types from any TikTok livestream.
|
|
13
|
+
|
|
14
|
+
**No API key required** · **Zero config** · **Direct connection**
|
|
15
|
+
|
|
16
|
+
[Quick Start](#-quick-start) · [Events](#-events) · [API](#-api-reference) · [Rate Limits](#-rate-limits)
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## ⚡ Quick Start
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @tiktool/live
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { TikTokLive } from '@tiktool/live';
|
|
30
|
+
|
|
31
|
+
const live = new TikTokLive({ uniqueId: 'tv_asahi_news' });
|
|
32
|
+
|
|
33
|
+
live.on('chat', e => console.log(`${e.user.uniqueId}: ${e.comment}`));
|
|
34
|
+
live.on('gift', e => console.log(`${e.user.uniqueId} sent ${e.giftName} (${e.diamondCount} diamonds)`));
|
|
35
|
+
live.on('member', e => console.log(`${e.user.uniqueId} joined`));
|
|
36
|
+
live.on('roomUserSeq', e => console.log(`Viewers: ${e.viewerCount}`));
|
|
37
|
+
|
|
38
|
+
await live.connect();
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
No API key, no configuration, no server setup. Install and connect.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## How It Works
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
Your App tik.tools TikTok
|
|
49
|
+
+-----------+ +--------------+ +--------------+
|
|
50
|
+
| -+-- sign_url --> Signs URL | | |
|
|
51
|
+
| Your <-+-- X-Bogus --| with params | | TikTok |
|
|
52
|
+
| Code | | | | WebSocket |
|
|
53
|
+
| -+------------ Connect directly ---------->| Server |
|
|
54
|
+
| <-+------------ Live events (protobuf) <---| |
|
|
55
|
+
+-----------+ +--------------+ +--------------+
|
|
56
|
+
^ Only interaction ^ Direct from
|
|
57
|
+
with our server YOUR IP
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- Your app connects directly to TikTok from your IP address
|
|
61
|
+
- The sign server only generates cryptographic signatures
|
|
62
|
+
- TikTok never sees the sign server
|
|
63
|
+
- Built-in protobuf parser, no external dependencies
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Events
|
|
68
|
+
|
|
69
|
+
### Listening
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
live.on('chat', (event) => {
|
|
73
|
+
event.user.uniqueId // string
|
|
74
|
+
event.comment // string
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
live.on('event', (event) => {
|
|
78
|
+
console.log(event.type, event);
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Reference
|
|
83
|
+
|
|
84
|
+
| Event | Type | Description | Fields |
|
|
85
|
+
|-------|------|-------------|--------|
|
|
86
|
+
| `chat` | `ChatEvent` | Chat message | `user`, `comment` |
|
|
87
|
+
| `member` | `MemberEvent` | User joined | `user`, `action` |
|
|
88
|
+
| `like` | `LikeEvent` | User liked | `user`, `likeCount`, `totalLikes` |
|
|
89
|
+
| `gift` | `GiftEvent` | Gift sent | `user`, `giftName`, `diamondCount`, `repeatCount`, `combo` |
|
|
90
|
+
| `social` | `SocialEvent` | Follow / Share | `user`, `action` |
|
|
91
|
+
| `roomUserSeq` | `RoomUserSeqEvent` | Viewer count | `viewerCount`, `totalViewers` |
|
|
92
|
+
| `battle` | `BattleEvent` | Link Mic battle | `status` |
|
|
93
|
+
| `battleArmies` | `BattleArmiesEvent` | Battle teams | — |
|
|
94
|
+
| `subscribe` | `SubscribeEvent` | New subscriber | `user`, `subMonth` |
|
|
95
|
+
| `emoteChat` | `EmoteChatEvent` | Emote in chat | `user`, `emoteId` |
|
|
96
|
+
| `envelope` | `EnvelopeEvent` | Treasure chest | `diamondCount` |
|
|
97
|
+
| `question` | `QuestionEvent` | Q&A question | `user`, `questionText` |
|
|
98
|
+
| `control` | `ControlEvent` | Stream control | `action` (3 = ended) |
|
|
99
|
+
| `room` | `RoomEvent` | Room status | `status` |
|
|
100
|
+
| `liveIntro` | `LiveIntroEvent` | Stream intro | `title` |
|
|
101
|
+
| `rankUpdate` | `RankUpdateEvent` | Rank update | `rankType` |
|
|
102
|
+
| `linkMic` | `LinkMicEvent` | Link Mic | `action` |
|
|
103
|
+
| `unknown` | `UnknownEvent` | Unrecognized | `method` |
|
|
104
|
+
|
|
105
|
+
### Connection Events
|
|
106
|
+
|
|
107
|
+
| Event | Callback | Description |
|
|
108
|
+
|-------|----------|-------------|
|
|
109
|
+
| `connected` | `() => void` | Connected to stream |
|
|
110
|
+
| `disconnected` | `(code, reason) => void` | Disconnected |
|
|
111
|
+
| `roomInfo` | `(info: RoomInfo) => void` | Room info |
|
|
112
|
+
| `error` | `(error: Error) => void` | Error |
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## API Reference
|
|
117
|
+
|
|
118
|
+
### `new TikTokLive(options)`
|
|
119
|
+
|
|
120
|
+
| Option | Type | Default | Description |
|
|
121
|
+
|--------|------|---------|-------------|
|
|
122
|
+
| `uniqueId` | `string` | — | TikTok username (without @) |
|
|
123
|
+
| `signServerUrl` | `string` | `https://api.tik.tools` | Sign server URL |
|
|
124
|
+
| `apiKey` | `string` | — | API key for higher rate limits |
|
|
125
|
+
| `autoReconnect` | `boolean` | `true` | Auto-reconnect on disconnect |
|
|
126
|
+
| `maxReconnectAttempts` | `number` | `5` | Max reconnect attempts |
|
|
127
|
+
| `heartbeatInterval` | `number` | `10000` | Heartbeat interval (ms) |
|
|
128
|
+
| `debug` | `boolean` | `false` | Debug logging |
|
|
129
|
+
|
|
130
|
+
### Methods
|
|
131
|
+
|
|
132
|
+
| Method | Returns | Description |
|
|
133
|
+
|--------|---------|-------------|
|
|
134
|
+
| `connect()` | `Promise<void>` | Connect to livestream |
|
|
135
|
+
| `disconnect()` | `void` | Disconnect |
|
|
136
|
+
| `connected` | `boolean` | Connection status |
|
|
137
|
+
| `eventCount` | `number` | Total events received |
|
|
138
|
+
| `roomId` | `string` | Current room ID |
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Rate Limits
|
|
143
|
+
|
|
144
|
+
| Tier | Rate Limit | API Key | Price |
|
|
145
|
+
|------|-----------|---------|-------|
|
|
146
|
+
| Free | 5 signs/min | No | Free |
|
|
147
|
+
| Basic | 30 signs/min | Yes | Free (with key) |
|
|
148
|
+
| Premium | 120 signs/min | Yes | Coming soon |
|
|
149
|
+
|
|
150
|
+
Most users only need the free tier. The SDK calls the sign server once per connection, then stays connected via WebSocket.
|
|
151
|
+
|
|
152
|
+
### Using an API Key
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
const live = new TikTokLive({
|
|
156
|
+
uniqueId: 'username',
|
|
157
|
+
apiKey: 'your-api-key',
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Examples
|
|
164
|
+
|
|
165
|
+
### Chat Bot
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { TikTokLive } from '@tiktool/live';
|
|
169
|
+
|
|
170
|
+
const live = new TikTokLive({ uniqueId: 'streamer_name' });
|
|
171
|
+
|
|
172
|
+
live.on('chat', (e) => {
|
|
173
|
+
if (e.comment.toLowerCase() === '!hello') {
|
|
174
|
+
console.log(`Hello, ${e.user.nickname}!`);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
live.on('gift', (e) => {
|
|
179
|
+
if (e.repeatEnd) {
|
|
180
|
+
console.log(`${e.user.uniqueId} sent ${e.repeatCount}x ${e.giftName} (${e.diamondCount * e.repeatCount} diamonds)`);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
await live.connect();
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### OBS Overlay
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { TikTokLive } from '@tiktool/live';
|
|
191
|
+
import { WebSocketServer } from 'ws';
|
|
192
|
+
|
|
193
|
+
const wss = new WebSocketServer({ port: 8080 });
|
|
194
|
+
const live = new TikTokLive({ uniqueId: 'streamer_name' });
|
|
195
|
+
|
|
196
|
+
live.on('event', (event) => {
|
|
197
|
+
for (const client of wss.clients) {
|
|
198
|
+
client.send(JSON.stringify(event));
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
await live.connect();
|
|
203
|
+
console.log('Forwarding events to ws://localhost:8080');
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Gift Tracker
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import { TikTokLive } from '@tiktool/live';
|
|
210
|
+
|
|
211
|
+
const live = new TikTokLive({ uniqueId: 'streamer_name' });
|
|
212
|
+
let totalDiamonds = 0;
|
|
213
|
+
|
|
214
|
+
live.on('gift', (e) => {
|
|
215
|
+
if (e.repeatEnd || !e.combo) {
|
|
216
|
+
const diamonds = e.diamondCount * (e.repeatCount || 1);
|
|
217
|
+
totalDiamonds += diamonds;
|
|
218
|
+
console.log(`${e.user.uniqueId}: ${e.giftName} = ${diamonds} diamonds (Total: ${totalDiamonds})`);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
await live.connect();
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## TypeScript
|
|
228
|
+
|
|
229
|
+
Full TypeScript support with type inference:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
import { TikTokLive, ChatEvent, GiftEvent } from '@tiktool/live';
|
|
233
|
+
|
|
234
|
+
const live = new TikTokLive({ uniqueId: 'username' });
|
|
235
|
+
|
|
236
|
+
live.on('chat', (event: ChatEvent) => {
|
|
237
|
+
const username: string = event.user.uniqueId;
|
|
238
|
+
const message: string = event.comment;
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
live.on('gift', (event: GiftEvent) => {
|
|
242
|
+
const diamonds: number = event.diamondCount;
|
|
243
|
+
const isCombo: boolean = event.combo;
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## License
|
|
250
|
+
|
|
251
|
+
MIT © [tiktool](https://tik.tools)
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
|
|
3
|
+
interface TikTokUser {
|
|
4
|
+
id: string;
|
|
5
|
+
nickname: string;
|
|
6
|
+
uniqueId: string;
|
|
7
|
+
profilePicture?: string;
|
|
8
|
+
badges?: string[];
|
|
9
|
+
}
|
|
10
|
+
interface BaseEvent {
|
|
11
|
+
type: string;
|
|
12
|
+
timestamp: number;
|
|
13
|
+
msgId: string;
|
|
14
|
+
}
|
|
15
|
+
interface ChatEvent extends BaseEvent {
|
|
16
|
+
type: 'chat';
|
|
17
|
+
user: TikTokUser;
|
|
18
|
+
comment: string;
|
|
19
|
+
}
|
|
20
|
+
interface MemberEvent extends BaseEvent {
|
|
21
|
+
type: 'member';
|
|
22
|
+
user: TikTokUser;
|
|
23
|
+
action: number;
|
|
24
|
+
}
|
|
25
|
+
interface LikeEvent extends BaseEvent {
|
|
26
|
+
type: 'like';
|
|
27
|
+
user: TikTokUser;
|
|
28
|
+
likeCount: number;
|
|
29
|
+
totalLikes: number;
|
|
30
|
+
}
|
|
31
|
+
interface GiftEvent extends BaseEvent {
|
|
32
|
+
type: 'gift';
|
|
33
|
+
user: TikTokUser;
|
|
34
|
+
giftId: number;
|
|
35
|
+
giftName: string;
|
|
36
|
+
diamondCount: number;
|
|
37
|
+
repeatCount: number;
|
|
38
|
+
repeatEnd: boolean;
|
|
39
|
+
combo: boolean;
|
|
40
|
+
}
|
|
41
|
+
interface SocialEvent extends BaseEvent {
|
|
42
|
+
type: 'social';
|
|
43
|
+
user: TikTokUser;
|
|
44
|
+
action: 'follow' | 'share' | string;
|
|
45
|
+
}
|
|
46
|
+
interface RoomUserSeqEvent extends BaseEvent {
|
|
47
|
+
type: 'roomUserSeq';
|
|
48
|
+
viewerCount: number;
|
|
49
|
+
totalViewers: number;
|
|
50
|
+
}
|
|
51
|
+
interface BattleEvent extends BaseEvent {
|
|
52
|
+
type: 'battle';
|
|
53
|
+
status: number;
|
|
54
|
+
}
|
|
55
|
+
interface BattleArmiesEvent extends BaseEvent {
|
|
56
|
+
type: 'battleArmies';
|
|
57
|
+
}
|
|
58
|
+
interface SubscribeEvent extends BaseEvent {
|
|
59
|
+
type: 'subscribe';
|
|
60
|
+
user: TikTokUser;
|
|
61
|
+
subMonth: number;
|
|
62
|
+
}
|
|
63
|
+
interface EmoteChatEvent extends BaseEvent {
|
|
64
|
+
type: 'emoteChat';
|
|
65
|
+
user: TikTokUser;
|
|
66
|
+
emoteId: string;
|
|
67
|
+
}
|
|
68
|
+
interface EnvelopeEvent extends BaseEvent {
|
|
69
|
+
type: 'envelope';
|
|
70
|
+
diamondCount: number;
|
|
71
|
+
}
|
|
72
|
+
interface QuestionEvent extends BaseEvent {
|
|
73
|
+
type: 'question';
|
|
74
|
+
user: TikTokUser;
|
|
75
|
+
questionText: string;
|
|
76
|
+
}
|
|
77
|
+
interface ControlEvent extends BaseEvent {
|
|
78
|
+
type: 'control';
|
|
79
|
+
action: number;
|
|
80
|
+
}
|
|
81
|
+
interface RoomEvent extends BaseEvent {
|
|
82
|
+
type: 'room';
|
|
83
|
+
status: string;
|
|
84
|
+
}
|
|
85
|
+
interface LiveIntroEvent extends BaseEvent {
|
|
86
|
+
type: 'liveIntro';
|
|
87
|
+
title: string;
|
|
88
|
+
}
|
|
89
|
+
interface RankUpdateEvent extends BaseEvent {
|
|
90
|
+
type: 'rankUpdate';
|
|
91
|
+
rankType: string;
|
|
92
|
+
}
|
|
93
|
+
interface LinkMicEvent extends BaseEvent {
|
|
94
|
+
type: 'linkMic';
|
|
95
|
+
action: number;
|
|
96
|
+
}
|
|
97
|
+
interface UnknownEvent extends BaseEvent {
|
|
98
|
+
type: 'unknown';
|
|
99
|
+
method: string;
|
|
100
|
+
}
|
|
101
|
+
type LiveEvent = ChatEvent | MemberEvent | LikeEvent | GiftEvent | SocialEvent | RoomUserSeqEvent | BattleEvent | BattleArmiesEvent | SubscribeEvent | EmoteChatEvent | EnvelopeEvent | QuestionEvent | ControlEvent | RoomEvent | LiveIntroEvent | RankUpdateEvent | LinkMicEvent | UnknownEvent;
|
|
102
|
+
interface TikTokLiveEvents {
|
|
103
|
+
connected: () => void;
|
|
104
|
+
disconnected: (code: number, reason: string) => void;
|
|
105
|
+
roomInfo: (info: RoomInfo) => void;
|
|
106
|
+
error: (error: Error) => void;
|
|
107
|
+
chat: (event: ChatEvent) => void;
|
|
108
|
+
member: (event: MemberEvent) => void;
|
|
109
|
+
like: (event: LikeEvent) => void;
|
|
110
|
+
gift: (event: GiftEvent) => void;
|
|
111
|
+
social: (event: SocialEvent) => void;
|
|
112
|
+
roomUserSeq: (event: RoomUserSeqEvent) => void;
|
|
113
|
+
battle: (event: BattleEvent) => void;
|
|
114
|
+
battleArmies: (event: BattleArmiesEvent) => void;
|
|
115
|
+
subscribe: (event: SubscribeEvent) => void;
|
|
116
|
+
emoteChat: (event: EmoteChatEvent) => void;
|
|
117
|
+
envelope: (event: EnvelopeEvent) => void;
|
|
118
|
+
question: (event: QuestionEvent) => void;
|
|
119
|
+
control: (event: ControlEvent) => void;
|
|
120
|
+
room: (event: RoomEvent) => void;
|
|
121
|
+
liveIntro: (event: LiveIntroEvent) => void;
|
|
122
|
+
rankUpdate: (event: RankUpdateEvent) => void;
|
|
123
|
+
linkMic: (event: LinkMicEvent) => void;
|
|
124
|
+
unknown: (event: UnknownEvent) => void;
|
|
125
|
+
event: (event: LiveEvent) => void;
|
|
126
|
+
}
|
|
127
|
+
interface RoomInfo {
|
|
128
|
+
roomId: string;
|
|
129
|
+
wsHost: string;
|
|
130
|
+
clusterRegion: string;
|
|
131
|
+
connectedAt: string;
|
|
132
|
+
}
|
|
133
|
+
interface TikTokLiveOptions {
|
|
134
|
+
uniqueId: string;
|
|
135
|
+
signServerUrl?: string;
|
|
136
|
+
apiKey?: string;
|
|
137
|
+
autoReconnect?: boolean;
|
|
138
|
+
maxReconnectAttempts?: number;
|
|
139
|
+
heartbeatInterval?: number;
|
|
140
|
+
debug?: boolean;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
declare class TikTokLive extends EventEmitter {
|
|
144
|
+
private ws;
|
|
145
|
+
private heartbeatTimer;
|
|
146
|
+
private reconnectAttempts;
|
|
147
|
+
private intentionalClose;
|
|
148
|
+
private _connected;
|
|
149
|
+
private _eventCount;
|
|
150
|
+
private _roomId;
|
|
151
|
+
private readonly uniqueId;
|
|
152
|
+
private readonly signServerUrl;
|
|
153
|
+
private readonly apiKey?;
|
|
154
|
+
private readonly autoReconnect;
|
|
155
|
+
private readonly maxReconnectAttempts;
|
|
156
|
+
private readonly heartbeatInterval;
|
|
157
|
+
private readonly debug;
|
|
158
|
+
constructor(options: TikTokLiveOptions);
|
|
159
|
+
connect(): Promise<void>;
|
|
160
|
+
disconnect(): void;
|
|
161
|
+
get connected(): boolean;
|
|
162
|
+
get eventCount(): number;
|
|
163
|
+
get roomId(): string;
|
|
164
|
+
on<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this;
|
|
165
|
+
once<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this;
|
|
166
|
+
off<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this;
|
|
167
|
+
emit<K extends keyof TikTokLiveEvents>(event: K, ...args: Parameters<TikTokLiveEvents[K]>): boolean;
|
|
168
|
+
private handleFrame;
|
|
169
|
+
private startHeartbeat;
|
|
170
|
+
private stopHeartbeat;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export { type BaseEvent, type BattleArmiesEvent, type BattleEvent, type ChatEvent, type ControlEvent, type EmoteChatEvent, type EnvelopeEvent, type GiftEvent, type LikeEvent, type LinkMicEvent, type LiveEvent, type LiveIntroEvent, type MemberEvent, type QuestionEvent, type RankUpdateEvent, type RoomEvent, type RoomInfo, type RoomUserSeqEvent, type SocialEvent, type SubscribeEvent, TikTokLive, type TikTokLiveEvents, type TikTokLiveOptions, type TikTokUser, type UnknownEvent };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
|
|
3
|
+
interface TikTokUser {
|
|
4
|
+
id: string;
|
|
5
|
+
nickname: string;
|
|
6
|
+
uniqueId: string;
|
|
7
|
+
profilePicture?: string;
|
|
8
|
+
badges?: string[];
|
|
9
|
+
}
|
|
10
|
+
interface BaseEvent {
|
|
11
|
+
type: string;
|
|
12
|
+
timestamp: number;
|
|
13
|
+
msgId: string;
|
|
14
|
+
}
|
|
15
|
+
interface ChatEvent extends BaseEvent {
|
|
16
|
+
type: 'chat';
|
|
17
|
+
user: TikTokUser;
|
|
18
|
+
comment: string;
|
|
19
|
+
}
|
|
20
|
+
interface MemberEvent extends BaseEvent {
|
|
21
|
+
type: 'member';
|
|
22
|
+
user: TikTokUser;
|
|
23
|
+
action: number;
|
|
24
|
+
}
|
|
25
|
+
interface LikeEvent extends BaseEvent {
|
|
26
|
+
type: 'like';
|
|
27
|
+
user: TikTokUser;
|
|
28
|
+
likeCount: number;
|
|
29
|
+
totalLikes: number;
|
|
30
|
+
}
|
|
31
|
+
interface GiftEvent extends BaseEvent {
|
|
32
|
+
type: 'gift';
|
|
33
|
+
user: TikTokUser;
|
|
34
|
+
giftId: number;
|
|
35
|
+
giftName: string;
|
|
36
|
+
diamondCount: number;
|
|
37
|
+
repeatCount: number;
|
|
38
|
+
repeatEnd: boolean;
|
|
39
|
+
combo: boolean;
|
|
40
|
+
}
|
|
41
|
+
interface SocialEvent extends BaseEvent {
|
|
42
|
+
type: 'social';
|
|
43
|
+
user: TikTokUser;
|
|
44
|
+
action: 'follow' | 'share' | string;
|
|
45
|
+
}
|
|
46
|
+
interface RoomUserSeqEvent extends BaseEvent {
|
|
47
|
+
type: 'roomUserSeq';
|
|
48
|
+
viewerCount: number;
|
|
49
|
+
totalViewers: number;
|
|
50
|
+
}
|
|
51
|
+
interface BattleEvent extends BaseEvent {
|
|
52
|
+
type: 'battle';
|
|
53
|
+
status: number;
|
|
54
|
+
}
|
|
55
|
+
interface BattleArmiesEvent extends BaseEvent {
|
|
56
|
+
type: 'battleArmies';
|
|
57
|
+
}
|
|
58
|
+
interface SubscribeEvent extends BaseEvent {
|
|
59
|
+
type: 'subscribe';
|
|
60
|
+
user: TikTokUser;
|
|
61
|
+
subMonth: number;
|
|
62
|
+
}
|
|
63
|
+
interface EmoteChatEvent extends BaseEvent {
|
|
64
|
+
type: 'emoteChat';
|
|
65
|
+
user: TikTokUser;
|
|
66
|
+
emoteId: string;
|
|
67
|
+
}
|
|
68
|
+
interface EnvelopeEvent extends BaseEvent {
|
|
69
|
+
type: 'envelope';
|
|
70
|
+
diamondCount: number;
|
|
71
|
+
}
|
|
72
|
+
interface QuestionEvent extends BaseEvent {
|
|
73
|
+
type: 'question';
|
|
74
|
+
user: TikTokUser;
|
|
75
|
+
questionText: string;
|
|
76
|
+
}
|
|
77
|
+
interface ControlEvent extends BaseEvent {
|
|
78
|
+
type: 'control';
|
|
79
|
+
action: number;
|
|
80
|
+
}
|
|
81
|
+
interface RoomEvent extends BaseEvent {
|
|
82
|
+
type: 'room';
|
|
83
|
+
status: string;
|
|
84
|
+
}
|
|
85
|
+
interface LiveIntroEvent extends BaseEvent {
|
|
86
|
+
type: 'liveIntro';
|
|
87
|
+
title: string;
|
|
88
|
+
}
|
|
89
|
+
interface RankUpdateEvent extends BaseEvent {
|
|
90
|
+
type: 'rankUpdate';
|
|
91
|
+
rankType: string;
|
|
92
|
+
}
|
|
93
|
+
interface LinkMicEvent extends BaseEvent {
|
|
94
|
+
type: 'linkMic';
|
|
95
|
+
action: number;
|
|
96
|
+
}
|
|
97
|
+
interface UnknownEvent extends BaseEvent {
|
|
98
|
+
type: 'unknown';
|
|
99
|
+
method: string;
|
|
100
|
+
}
|
|
101
|
+
type LiveEvent = ChatEvent | MemberEvent | LikeEvent | GiftEvent | SocialEvent | RoomUserSeqEvent | BattleEvent | BattleArmiesEvent | SubscribeEvent | EmoteChatEvent | EnvelopeEvent | QuestionEvent | ControlEvent | RoomEvent | LiveIntroEvent | RankUpdateEvent | LinkMicEvent | UnknownEvent;
|
|
102
|
+
interface TikTokLiveEvents {
|
|
103
|
+
connected: () => void;
|
|
104
|
+
disconnected: (code: number, reason: string) => void;
|
|
105
|
+
roomInfo: (info: RoomInfo) => void;
|
|
106
|
+
error: (error: Error) => void;
|
|
107
|
+
chat: (event: ChatEvent) => void;
|
|
108
|
+
member: (event: MemberEvent) => void;
|
|
109
|
+
like: (event: LikeEvent) => void;
|
|
110
|
+
gift: (event: GiftEvent) => void;
|
|
111
|
+
social: (event: SocialEvent) => void;
|
|
112
|
+
roomUserSeq: (event: RoomUserSeqEvent) => void;
|
|
113
|
+
battle: (event: BattleEvent) => void;
|
|
114
|
+
battleArmies: (event: BattleArmiesEvent) => void;
|
|
115
|
+
subscribe: (event: SubscribeEvent) => void;
|
|
116
|
+
emoteChat: (event: EmoteChatEvent) => void;
|
|
117
|
+
envelope: (event: EnvelopeEvent) => void;
|
|
118
|
+
question: (event: QuestionEvent) => void;
|
|
119
|
+
control: (event: ControlEvent) => void;
|
|
120
|
+
room: (event: RoomEvent) => void;
|
|
121
|
+
liveIntro: (event: LiveIntroEvent) => void;
|
|
122
|
+
rankUpdate: (event: RankUpdateEvent) => void;
|
|
123
|
+
linkMic: (event: LinkMicEvent) => void;
|
|
124
|
+
unknown: (event: UnknownEvent) => void;
|
|
125
|
+
event: (event: LiveEvent) => void;
|
|
126
|
+
}
|
|
127
|
+
interface RoomInfo {
|
|
128
|
+
roomId: string;
|
|
129
|
+
wsHost: string;
|
|
130
|
+
clusterRegion: string;
|
|
131
|
+
connectedAt: string;
|
|
132
|
+
}
|
|
133
|
+
interface TikTokLiveOptions {
|
|
134
|
+
uniqueId: string;
|
|
135
|
+
signServerUrl?: string;
|
|
136
|
+
apiKey?: string;
|
|
137
|
+
autoReconnect?: boolean;
|
|
138
|
+
maxReconnectAttempts?: number;
|
|
139
|
+
heartbeatInterval?: number;
|
|
140
|
+
debug?: boolean;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
declare class TikTokLive extends EventEmitter {
|
|
144
|
+
private ws;
|
|
145
|
+
private heartbeatTimer;
|
|
146
|
+
private reconnectAttempts;
|
|
147
|
+
private intentionalClose;
|
|
148
|
+
private _connected;
|
|
149
|
+
private _eventCount;
|
|
150
|
+
private _roomId;
|
|
151
|
+
private readonly uniqueId;
|
|
152
|
+
private readonly signServerUrl;
|
|
153
|
+
private readonly apiKey?;
|
|
154
|
+
private readonly autoReconnect;
|
|
155
|
+
private readonly maxReconnectAttempts;
|
|
156
|
+
private readonly heartbeatInterval;
|
|
157
|
+
private readonly debug;
|
|
158
|
+
constructor(options: TikTokLiveOptions);
|
|
159
|
+
connect(): Promise<void>;
|
|
160
|
+
disconnect(): void;
|
|
161
|
+
get connected(): boolean;
|
|
162
|
+
get eventCount(): number;
|
|
163
|
+
get roomId(): string;
|
|
164
|
+
on<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this;
|
|
165
|
+
once<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this;
|
|
166
|
+
off<K extends keyof TikTokLiveEvents>(event: K, listener: TikTokLiveEvents[K]): this;
|
|
167
|
+
emit<K extends keyof TikTokLiveEvents>(event: K, ...args: Parameters<TikTokLiveEvents[K]>): boolean;
|
|
168
|
+
private handleFrame;
|
|
169
|
+
private startHeartbeat;
|
|
170
|
+
private stopHeartbeat;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export { type BaseEvent, type BattleArmiesEvent, type BattleEvent, type ChatEvent, type ControlEvent, type EmoteChatEvent, type EnvelopeEvent, type GiftEvent, type LikeEvent, type LinkMicEvent, type LiveEvent, type LiveIntroEvent, type MemberEvent, type QuestionEvent, type RankUpdateEvent, type RoomEvent, type RoomInfo, type RoomUserSeqEvent, type SocialEvent, type SubscribeEvent, TikTokLive, type TikTokLiveEvents, type TikTokLiveOptions, type TikTokUser, type UnknownEvent };
|