@phxgg/kick.js 0.1.1 → 0.1.3
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 +444 -448
- package/dist/BaseResponse.d.ts +0 -1
- package/dist/BaseResponse.js +0 -1
- package/dist/Errors.d.ts +0 -1
- package/dist/Errors.js +0 -1
- package/dist/EventManager.d.ts +0 -1
- package/dist/EventManager.js +0 -1
- package/dist/KickClient.d.ts +0 -1
- package/dist/KickClient.js +0 -1
- package/dist/OAuth.d.ts +0 -1
- package/dist/OAuth.js +0 -1
- package/dist/Scope.d.ts +0 -1
- package/dist/Scope.js +0 -1
- package/dist/Serializable.d.ts +0 -1
- package/dist/Serializable.js +0 -1
- package/dist/Version.d.ts +0 -1
- package/dist/Version.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/resources/Category.d.ts +0 -1
- package/dist/resources/Category.js +0 -1
- package/dist/resources/Channel.d.ts +0 -1
- package/dist/resources/Channel.js +0 -1
- package/dist/resources/ChannelReward.d.ts +0 -1
- package/dist/resources/ChannelReward.js +0 -1
- package/dist/resources/ChannelRewardRedemption.d.ts +0 -1
- package/dist/resources/ChannelRewardRedemption.js +0 -1
- package/dist/resources/EventSubscription.d.ts +0 -1
- package/dist/resources/EventSubscription.js +0 -1
- package/dist/resources/Leaderboard.d.ts +0 -1
- package/dist/resources/Leaderboard.js +0 -1
- package/dist/resources/Livestream.d.ts +0 -1
- package/dist/resources/Livestream.js +0 -1
- package/dist/resources/Message.d.ts +0 -1
- package/dist/resources/Message.js +0 -1
- package/dist/resources/User.d.ts +0 -1
- package/dist/resources/User.js +0 -1
- package/dist/services/CategoriesService.d.ts +0 -1
- package/dist/services/CategoriesService.js +0 -1
- package/dist/services/CategoriesServiceV2.d.ts +0 -1
- package/dist/services/CategoriesServiceV2.js +0 -1
- package/dist/services/ChannelRewardsService.d.ts +0 -1
- package/dist/services/ChannelRewardsService.js +0 -1
- package/dist/services/ChannelsService.d.ts +0 -1
- package/dist/services/ChannelsService.js +0 -1
- package/dist/services/ChatService.d.ts +0 -1
- package/dist/services/ChatService.js +0 -1
- package/dist/services/EventsService.d.ts +0 -1
- package/dist/services/EventsService.js +0 -1
- package/dist/services/KICKsService.d.ts +0 -1
- package/dist/services/KICKsService.js +0 -1
- package/dist/services/LivestreamsService.d.ts +0 -1
- package/dist/services/LivestreamsService.js +0 -1
- package/dist/services/ModerationService.d.ts +0 -1
- package/dist/services/ModerationService.js +0 -1
- package/dist/services/PublicKeyService.d.ts +0 -1
- package/dist/services/PublicKeyService.js +0 -1
- package/dist/services/UsersService.d.ts +0 -1
- package/dist/services/UsersService.js +0 -1
- package/dist/utils.d.ts +0 -1
- package/dist/utils.js +0 -1
- package/dist/webhooks/WebhookEvents.d.ts +0 -1
- package/dist/webhooks/WebhookEvents.js +0 -1
- package/dist/webhooks/dispatch.d.ts +0 -1
- package/dist/webhooks/dispatch.js +0 -1
- package/dist/webhooks/v1/Properties.d.ts +0 -1
- package/dist/webhooks/v1/Properties.js +0 -1
- package/dist/webhooks/v1/payloads/ChannelFollowed.d.ts +0 -1
- package/dist/webhooks/v1/payloads/ChannelFollowed.js +0 -1
- package/dist/webhooks/v1/payloads/ChannelRewardRedemptionUpdated.d.ts +0 -1
- package/dist/webhooks/v1/payloads/ChannelRewardRedemptionUpdated.js +0 -1
- package/dist/webhooks/v1/payloads/ChannelSubscriptionGifts.d.ts +0 -1
- package/dist/webhooks/v1/payloads/ChannelSubscriptionGifts.js +0 -1
- package/dist/webhooks/v1/payloads/ChannelSubscriptionNew.d.ts +0 -1
- package/dist/webhooks/v1/payloads/ChannelSubscriptionNew.js +0 -1
- package/dist/webhooks/v1/payloads/ChannelSubscriptionRenewal.d.ts +0 -1
- package/dist/webhooks/v1/payloads/ChannelSubscriptionRenewal.js +0 -1
- package/dist/webhooks/v1/payloads/ChatMessageSent.d.ts +0 -1
- package/dist/webhooks/v1/payloads/ChatMessageSent.js +0 -1
- package/dist/webhooks/v1/payloads/KicksGifted.d.ts +0 -1
- package/dist/webhooks/v1/payloads/KicksGifted.js +0 -1
- package/dist/webhooks/v1/payloads/LivestreamMetadataUpdated.d.ts +0 -1
- package/dist/webhooks/v1/payloads/LivestreamMetadataUpdated.js +0 -1
- package/dist/webhooks/v1/payloads/LivestreamStatusUpdated.d.ts +0 -1
- package/dist/webhooks/v1/payloads/LivestreamStatusUpdated.js +0 -1
- package/dist/webhooks/v1/payloads/ModerationBanned.d.ts +0 -1
- package/dist/webhooks/v1/payloads/ModerationBanned.js +0 -1
- package/dist/webhooks/v1/payloads/index.d.ts +0 -1
- package/dist/webhooks/v1/payloads/index.js +0 -1
- package/dist/webhooks/verify.d.ts +0 -1
- package/dist/webhooks/verify.js +0 -1
- package/package.json +1 -1
- package/dist/BaseResponse.d.ts.map +0 -1
- package/dist/BaseResponse.js.map +0 -1
- package/dist/Errors.d.ts.map +0 -1
- package/dist/Errors.js.map +0 -1
- package/dist/EventManager.d.ts.map +0 -1
- package/dist/EventManager.js.map +0 -1
- package/dist/KickClient.d.ts.map +0 -1
- package/dist/KickClient.js.map +0 -1
- package/dist/OAuth.d.ts.map +0 -1
- package/dist/OAuth.js.map +0 -1
- package/dist/Scope.d.ts.map +0 -1
- package/dist/Scope.js.map +0 -1
- package/dist/Serializable.d.ts.map +0 -1
- package/dist/Serializable.js.map +0 -1
- package/dist/Version.d.ts.map +0 -1
- package/dist/Version.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/resources/Category.d.ts.map +0 -1
- package/dist/resources/Category.js.map +0 -1
- package/dist/resources/Channel.d.ts.map +0 -1
- package/dist/resources/Channel.js.map +0 -1
- package/dist/resources/ChannelReward.d.ts.map +0 -1
- package/dist/resources/ChannelReward.js.map +0 -1
- package/dist/resources/ChannelRewardRedemption.d.ts.map +0 -1
- package/dist/resources/ChannelRewardRedemption.js.map +0 -1
- package/dist/resources/EventSubscription.d.ts.map +0 -1
- package/dist/resources/EventSubscription.js.map +0 -1
- package/dist/resources/Leaderboard.d.ts.map +0 -1
- package/dist/resources/Leaderboard.js.map +0 -1
- package/dist/resources/Livestream.d.ts.map +0 -1
- package/dist/resources/Livestream.js.map +0 -1
- package/dist/resources/Message.d.ts.map +0 -1
- package/dist/resources/Message.js.map +0 -1
- package/dist/resources/User.d.ts.map +0 -1
- package/dist/resources/User.js.map +0 -1
- package/dist/services/CategoriesService.d.ts.map +0 -1
- package/dist/services/CategoriesService.js.map +0 -1
- package/dist/services/CategoriesServiceV2.d.ts.map +0 -1
- package/dist/services/CategoriesServiceV2.js.map +0 -1
- package/dist/services/ChannelRewardsService.d.ts.map +0 -1
- package/dist/services/ChannelRewardsService.js.map +0 -1
- package/dist/services/ChannelsService.d.ts.map +0 -1
- package/dist/services/ChannelsService.js.map +0 -1
- package/dist/services/ChatService.d.ts.map +0 -1
- package/dist/services/ChatService.js.map +0 -1
- package/dist/services/EventsService.d.ts.map +0 -1
- package/dist/services/EventsService.js.map +0 -1
- package/dist/services/KICKsService.d.ts.map +0 -1
- package/dist/services/KICKsService.js.map +0 -1
- package/dist/services/LivestreamsService.d.ts.map +0 -1
- package/dist/services/LivestreamsService.js.map +0 -1
- package/dist/services/ModerationService.d.ts.map +0 -1
- package/dist/services/ModerationService.js.map +0 -1
- package/dist/services/PublicKeyService.d.ts.map +0 -1
- package/dist/services/PublicKeyService.js.map +0 -1
- package/dist/services/UsersService.d.ts.map +0 -1
- package/dist/services/UsersService.js.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
- package/dist/webhooks/WebhookEvents.d.ts.map +0 -1
- package/dist/webhooks/WebhookEvents.js.map +0 -1
- package/dist/webhooks/dispatch.d.ts.map +0 -1
- package/dist/webhooks/dispatch.js.map +0 -1
- package/dist/webhooks/v1/Properties.d.ts.map +0 -1
- package/dist/webhooks/v1/Properties.js.map +0 -1
- package/dist/webhooks/v1/payloads/ChannelFollowed.d.ts.map +0 -1
- package/dist/webhooks/v1/payloads/ChannelFollowed.js.map +0 -1
- package/dist/webhooks/v1/payloads/ChannelRewardRedemptionUpdated.d.ts.map +0 -1
- package/dist/webhooks/v1/payloads/ChannelRewardRedemptionUpdated.js.map +0 -1
- package/dist/webhooks/v1/payloads/ChannelSubscriptionGifts.d.ts.map +0 -1
- package/dist/webhooks/v1/payloads/ChannelSubscriptionGifts.js.map +0 -1
- package/dist/webhooks/v1/payloads/ChannelSubscriptionNew.d.ts.map +0 -1
- package/dist/webhooks/v1/payloads/ChannelSubscriptionNew.js.map +0 -1
- package/dist/webhooks/v1/payloads/ChannelSubscriptionRenewal.d.ts.map +0 -1
- package/dist/webhooks/v1/payloads/ChannelSubscriptionRenewal.js.map +0 -1
- package/dist/webhooks/v1/payloads/ChatMessageSent.d.ts.map +0 -1
- package/dist/webhooks/v1/payloads/ChatMessageSent.js.map +0 -1
- package/dist/webhooks/v1/payloads/KicksGifted.d.ts.map +0 -1
- package/dist/webhooks/v1/payloads/KicksGifted.js.map +0 -1
- package/dist/webhooks/v1/payloads/LivestreamMetadataUpdated.d.ts.map +0 -1
- package/dist/webhooks/v1/payloads/LivestreamMetadataUpdated.js.map +0 -1
- package/dist/webhooks/v1/payloads/LivestreamStatusUpdated.d.ts.map +0 -1
- package/dist/webhooks/v1/payloads/LivestreamStatusUpdated.js.map +0 -1
- package/dist/webhooks/v1/payloads/ModerationBanned.d.ts.map +0 -1
- package/dist/webhooks/v1/payloads/ModerationBanned.js.map +0 -1
- package/dist/webhooks/v1/payloads/index.d.ts.map +0 -1
- package/dist/webhooks/v1/payloads/index.js.map +0 -1
- package/dist/webhooks/verify.d.ts.map +0 -1
- package/dist/webhooks/verify.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,448 +1,444 @@
|
|
|
1
|
-
# @phxgg/kick.js
|
|
2
|
-
|
|
3
|
-
A JavaScript/TypeScript client for the [Kick.com public API](https://docs.kick.com).
|
|
4
|
-
|
|
5
|
-
> [!WARNING]
|
|
6
|
-
> This project is in early development. The API may change significantly between releases.
|
|
7
|
-
|
|
8
|
-
## Installation
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
npm install @phxgg/kick.js
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## Table of contents
|
|
15
|
-
|
|
16
|
-
- [Setup](#setup)
|
|
17
|
-
- [OAuth](#oauth)
|
|
18
|
-
- [Users](#users)
|
|
19
|
-
- [Channels](#channels)
|
|
20
|
-
- [Livestreams](#livestreams)
|
|
21
|
-
- [Categories](#categories)
|
|
22
|
-
- [Chat](#chat)
|
|
23
|
-
- [Channel Rewards](#channel-rewards)
|
|
24
|
-
- [Moderation](#moderation)
|
|
25
|
-
- [KICKs](#kicks)
|
|
26
|
-
- [Event Subscriptions](#event-subscriptions)
|
|
27
|
-
- [Webhooks](#webhooks)
|
|
28
|
-
- [Error handling](#error-handling)
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## Setup
|
|
33
|
-
|
|
34
|
-
```ts
|
|
35
|
-
import { KickClient } from '@phxgg/kick.js';
|
|
36
|
-
|
|
37
|
-
const client = new KickClient({
|
|
38
|
-
clientId: 'YOUR_CLIENT_ID',
|
|
39
|
-
clientSecret: 'YOUR_CLIENT_SECRET',
|
|
40
|
-
redirectUri: 'https://yourapp.com/oauth/callback', // required for OAuth flows
|
|
41
|
-
});
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Once you have a user token (obtained via [OAuth](#oauth)), attach it to the client:
|
|
45
|
-
|
|
46
|
-
```ts
|
|
47
|
-
client.setToken({
|
|
48
|
-
access_token: 'USER_ACCESS_TOKEN',
|
|
49
|
-
refresh_token: 'USER_REFRESH_TOKEN',
|
|
50
|
-
token_type: 'bearer',
|
|
51
|
-
expires_in: 3600,
|
|
52
|
-
scope: 'user:read channel:read',
|
|
53
|
-
});
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
After `setToken` is called, the client automatically fetches the authenticated user in the background and registers itself in the global event manager so that [webhook events](#webhooks) can be routed to it.
|
|
57
|
-
|
|
58
|
-
---
|
|
59
|
-
|
|
60
|
-
## OAuth
|
|
61
|
-
|
|
62
|
-
### Generate authorization URL
|
|
63
|
-
|
|
64
|
-
Redirect your user to this URL to begin the authorization flow. Store the `codeVerifier` in the session — you'll need it in the next step.
|
|
65
|
-
|
|
66
|
-
```ts
|
|
67
|
-
const { url, codeVerifier } = await client.oauth.generateAuthorizeURL();
|
|
68
|
-
// redirect user to `url`
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
### Exchange code for token
|
|
72
|
-
|
|
73
|
-
```ts
|
|
74
|
-
const token = await client.oauth.exchangeToken(code, codeVerifier);
|
|
75
|
-
client.setToken(token);
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### Generate an app token (client credentials)
|
|
79
|
-
|
|
80
|
-
Use this for API calls that don't require a user context.
|
|
81
|
-
|
|
82
|
-
```ts
|
|
83
|
-
const appToken = await client.oauth.generateAppToken();
|
|
84
|
-
client.appToken = appToken;
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Refresh a token
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
const refreshed = await client.oauth.refreshToken(token.refresh_token);
|
|
91
|
-
client.setToken(refreshed);
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### Revoke a token
|
|
95
|
-
|
|
96
|
-
```ts
|
|
97
|
-
import { TokenHintType } from '@phxgg/kick.js';
|
|
98
|
-
|
|
99
|
-
await client.oauth.revokeToken(token.access_token, TokenHintType.ACCESS_TOKEN);
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Introspect a token
|
|
103
|
-
|
|
104
|
-
```ts
|
|
105
|
-
const info = await client.oauth.introspect();
|
|
106
|
-
console.log(info.active, info.scope);
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
|
|
111
|
-
## Users
|
|
112
|
-
|
|
113
|
-
Required scope: `user:read`
|
|
114
|
-
|
|
115
|
-
```ts
|
|
116
|
-
// Fetch the authenticated user
|
|
117
|
-
const me = await client.users.me();
|
|
118
|
-
console.log(me.name, me.email, me.userId);
|
|
119
|
-
|
|
120
|
-
// Fetch specific users by ID
|
|
121
|
-
const users = await client.users.fetch([123, 456]);
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## Channels
|
|
127
|
-
|
|
128
|
-
Required scope: `channel:read` (read), `channel:write` (update)
|
|
129
|
-
|
|
130
|
-
```ts
|
|
131
|
-
// Fetch by slug
|
|
132
|
-
const channel = await client.channels.fetchBySlug('monstercat');
|
|
133
|
-
|
|
134
|
-
// Fetch by broadcaster user ID
|
|
135
|
-
const channel = await client.channels.fetchById(123);
|
|
136
|
-
|
|
137
|
-
// Fetch multiple at once
|
|
138
|
-
const channels = await client.channels.fetch({ slug: ['monstercat', 'kick'] });
|
|
139
|
-
// or: client.channels.fetch({ broadcasterUserId: [123, 456] })
|
|
140
|
-
|
|
141
|
-
// Update the authenticated user's channel
|
|
142
|
-
await client.channels.update({
|
|
143
|
-
streamTitle: 'My new stream title',
|
|
144
|
-
categoryId: 15,
|
|
145
|
-
customTags: ['gaming', 'chill'],
|
|
146
|
-
});
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
---
|
|
150
|
-
|
|
151
|
-
## Livestreams
|
|
152
|
-
|
|
153
|
-
```ts
|
|
154
|
-
// Fetch live streams (no scope required)
|
|
155
|
-
const streams = await client.livestreams.fetch({
|
|
156
|
-
broadcasterUserId: [123, 456],
|
|
157
|
-
categoryId: 15,
|
|
158
|
-
language: 'en',
|
|
159
|
-
limit: 20,
|
|
160
|
-
sort: 'viewer_count', // or 'started_at'
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
// Total live stream count
|
|
164
|
-
const stats = await client.livestreams.fetchStats();
|
|
165
|
-
console.log(stats.total_count);
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
---
|
|
169
|
-
|
|
170
|
-
## Categories
|
|
171
|
-
|
|
172
|
-
```ts
|
|
173
|
-
// v1: fetch all categories
|
|
174
|
-
const categories = await client.categories.fetch();
|
|
175
|
-
|
|
176
|
-
// v2: search with pagination
|
|
177
|
-
const results = await client.categoriesV2.search({ query: 'gaming', limit: 10 });
|
|
178
|
-
|
|
179
|
-
// v2: fetch a single category by ID
|
|
180
|
-
const category = await client.categoriesV2.fetch(15);
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
---
|
|
184
|
-
|
|
185
|
-
## Chat
|
|
186
|
-
|
|
187
|
-
Required scope: `chat:write` (send), `moderation:chat_message:manage` (delete)
|
|
188
|
-
|
|
189
|
-
```ts
|
|
190
|
-
import { ChatMessageType } from '@phxgg/kick.js';
|
|
191
|
-
|
|
192
|
-
// Send a bot message (default)
|
|
193
|
-
const message = await client.chat.send({
|
|
194
|
-
content: 'Hello from kick.js!',
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
// Send a message as the authenticated user to a specific channel
|
|
198
|
-
const message = await client.chat.send({
|
|
199
|
-
content: 'Hello!',
|
|
200
|
-
broadcasterUserId: 123,
|
|
201
|
-
type: ChatMessageType.USER,
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
// Reply to a message
|
|
205
|
-
const reply = await client.chat.send({
|
|
206
|
-
content: 'Nice catch!',
|
|
207
|
-
replyToMessageId: 'some-message-id',
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
// Delete a message
|
|
211
|
-
await client.chat.delete('some-message-id');
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
---
|
|
215
|
-
|
|
216
|
-
## Channel Rewards
|
|
217
|
-
|
|
218
|
-
Required scope: `channel:rewards:read` (read), `channel:rewards:write` (create / update / delete)
|
|
219
|
-
|
|
220
|
-
```ts
|
|
221
|
-
// Fetch all rewards for the authenticated broadcaster
|
|
222
|
-
const rewards = await client.channelRewards.fetch();
|
|
223
|
-
|
|
224
|
-
// Create a reward
|
|
225
|
-
const reward = await client.channelRewards.create({
|
|
226
|
-
title: 'Hydrate!',
|
|
227
|
-
cost: 500,
|
|
228
|
-
description: 'Make the streamer drink water.',
|
|
229
|
-
isEnabled: true,
|
|
230
|
-
isUserInputRequired: false,
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
// Update a reward
|
|
234
|
-
await client.channelRewards.update(reward.id, {
|
|
235
|
-
cost: 1000,
|
|
236
|
-
isPaused: false,
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
// Delete a reward
|
|
240
|
-
await client.channelRewards.delete(reward.id);
|
|
241
|
-
|
|
242
|
-
// Fetch redemptions (defaults to pending)
|
|
243
|
-
const redemptions = await client.channelRewards.getRedemptions({
|
|
244
|
-
rewardId: reward.id,
|
|
245
|
-
status: 'pending',
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
// Accept / reject redemptions (up to 25 per call)
|
|
249
|
-
await client.channelRewards.acceptRedemptions({ ids: [redemptions[0].id] });
|
|
250
|
-
await client.channelRewards.rejectRedemptions({ ids: [redemptions[1].id] });
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
---
|
|
254
|
-
|
|
255
|
-
## Moderation
|
|
256
|
-
|
|
257
|
-
Required scope: `moderation:ban`
|
|
258
|
-
|
|
259
|
-
```ts
|
|
260
|
-
// Ban a user permanently
|
|
261
|
-
await client.moderation.banUser({
|
|
262
|
-
broadcasterUserId: 123,
|
|
263
|
-
userId: 456,
|
|
264
|
-
reason: 'Spamming',
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
// Timeout a user (duration in minutes, max 10080 = 7 days)
|
|
268
|
-
await client.moderation.timeoutUser({
|
|
269
|
-
broadcasterUserId: 123,
|
|
270
|
-
userId: 456,
|
|
271
|
-
duration: 10,
|
|
272
|
-
reason: 'Cool off.',
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
// Remove a ban or timeout
|
|
276
|
-
await client.moderation.removeBan({
|
|
277
|
-
broadcasterUserId: 123,
|
|
278
|
-
userId: 456,
|
|
279
|
-
});
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
---
|
|
283
|
-
|
|
284
|
-
## KICKs
|
|
285
|
-
|
|
286
|
-
Required scope: `kicks:read`
|
|
287
|
-
|
|
288
|
-
```ts
|
|
289
|
-
// Fetch the KICKs leaderboard for the authenticated broadcaster
|
|
290
|
-
const leaderboard = await client.kicks.fetchLeaderboard({ top: 10 });
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
---
|
|
294
|
-
|
|
295
|
-
## Event subscriptions
|
|
296
|
-
|
|
297
|
-
Required scope: `events:subscribe`
|
|
298
|
-
|
|
299
|
-
Subscribe your app to receive webhook events for a broadcaster.
|
|
300
|
-
|
|
301
|
-
```ts
|
|
302
|
-
import { WebhookEvents } from '@phxgg/kick.js';
|
|
303
|
-
|
|
304
|
-
// Subscribe to a single event
|
|
305
|
-
await client.events.subscribe({
|
|
306
|
-
broadcasterUserId: 123,
|
|
307
|
-
event: { name: WebhookEvents.CHAT_MESSAGE_SENT, version: 1 },
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
// Subscribe to multiple events at once
|
|
311
|
-
await client.events.subscribeMultiple({
|
|
312
|
-
broadcasterUserId: 123,
|
|
313
|
-
events: [
|
|
314
|
-
{ name: WebhookEvents.CHANNEL_FOLLOWED, version: 1 },
|
|
315
|
-
{ name: WebhookEvents.LIVESTREAM_STATUS_UPDATED, version: 1 },
|
|
316
|
-
],
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
// List active subscriptions
|
|
320
|
-
const subs = await client.events.fetch();
|
|
321
|
-
|
|
322
|
-
// Unsubscribe
|
|
323
|
-
await client.events.unsubscribe(subs[0].id);
|
|
324
|
-
await client.events.unsubscribeMultiple(subs.map((s) => s.id));
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
---
|
|
328
|
-
|
|
329
|
-
## Webhooks
|
|
330
|
-
|
|
331
|
-
kick.js provides framework-agnostic primitives so you can handle Kick webhook deliveries in any HTTP server.
|
|
332
|
-
|
|
333
|
-
### Verify & dispatch
|
|
334
|
-
|
|
335
|
-
```ts
|
|
336
|
-
import {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
client.on(WebhookEvents.
|
|
372
|
-
console.log(`${payload.
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
client.on(WebhookEvents.
|
|
376
|
-
console.log(
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
|
396
|
-
|
|
397
|
-
| `
|
|
398
|
-
| `channel.
|
|
399
|
-
| `
|
|
400
|
-
| `
|
|
401
|
-
| `
|
|
402
|
-
| `
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
if (err instanceof
|
|
429
|
-
//
|
|
430
|
-
} else
|
|
431
|
-
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
##
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
## License
|
|
447
|
-
|
|
448
|
-
[MIT](./LICENSE)
|
|
1
|
+
# @phxgg/kick.js
|
|
2
|
+
|
|
3
|
+
A JavaScript/TypeScript client for the [Kick.com public API](https://docs.kick.com).
|
|
4
|
+
|
|
5
|
+
> [!WARNING]
|
|
6
|
+
> This project is in early development. The API may change significantly between releases.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @phxgg/kick.js
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Table of contents
|
|
15
|
+
|
|
16
|
+
- [Setup](#setup)
|
|
17
|
+
- [OAuth](#oauth)
|
|
18
|
+
- [Users](#users)
|
|
19
|
+
- [Channels](#channels)
|
|
20
|
+
- [Livestreams](#livestreams)
|
|
21
|
+
- [Categories](#categories)
|
|
22
|
+
- [Chat](#chat)
|
|
23
|
+
- [Channel Rewards](#channel-rewards)
|
|
24
|
+
- [Moderation](#moderation)
|
|
25
|
+
- [KICKs](#kicks)
|
|
26
|
+
- [Event Subscriptions](#event-subscriptions)
|
|
27
|
+
- [Webhooks](#webhooks)
|
|
28
|
+
- [Error handling](#error-handling)
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Setup
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { KickClient } from '@phxgg/kick.js';
|
|
36
|
+
|
|
37
|
+
const client = new KickClient({
|
|
38
|
+
clientId: 'YOUR_CLIENT_ID',
|
|
39
|
+
clientSecret: 'YOUR_CLIENT_SECRET',
|
|
40
|
+
redirectUri: 'https://yourapp.com/oauth/callback', // required for OAuth flows
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Once you have a user token (obtained via [OAuth](#oauth)), attach it to the client:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
client.setToken({
|
|
48
|
+
access_token: 'USER_ACCESS_TOKEN',
|
|
49
|
+
refresh_token: 'USER_REFRESH_TOKEN',
|
|
50
|
+
token_type: 'bearer',
|
|
51
|
+
expires_in: 3600,
|
|
52
|
+
scope: 'user:read channel:read',
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
After `setToken` is called, the client automatically fetches the authenticated user in the background and registers itself in the global event manager so that [webhook events](#webhooks) can be routed to it.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## OAuth
|
|
61
|
+
|
|
62
|
+
### Generate authorization URL
|
|
63
|
+
|
|
64
|
+
Redirect your user to this URL to begin the authorization flow. Store the `codeVerifier` in the session — you'll need it in the next step.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const { url, codeVerifier } = await client.oauth.generateAuthorizeURL();
|
|
68
|
+
// redirect user to `url`
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Exchange code for token
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const token = await client.oauth.exchangeToken(code, codeVerifier);
|
|
75
|
+
client.setToken(token);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Generate an app token (client credentials)
|
|
79
|
+
|
|
80
|
+
Use this for API calls that don't require a user context.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
const appToken = await client.oauth.generateAppToken();
|
|
84
|
+
client.appToken = appToken;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Refresh a token
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
const refreshed = await client.oauth.refreshToken(token.refresh_token);
|
|
91
|
+
client.setToken(refreshed);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Revoke a token
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { TokenHintType } from '@phxgg/kick.js';
|
|
98
|
+
|
|
99
|
+
await client.oauth.revokeToken(token.access_token, TokenHintType.ACCESS_TOKEN);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Introspect a token
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
const info = await client.oauth.introspect();
|
|
106
|
+
console.log(info.active, info.scope);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Users
|
|
112
|
+
|
|
113
|
+
Required scope: `user:read`
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
// Fetch the authenticated user
|
|
117
|
+
const me = await client.users.me();
|
|
118
|
+
console.log(me.name, me.email, me.userId);
|
|
119
|
+
|
|
120
|
+
// Fetch specific users by ID
|
|
121
|
+
const users = await client.users.fetch([123, 456]);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Channels
|
|
127
|
+
|
|
128
|
+
Required scope: `channel:read` (read), `channel:write` (update)
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
// Fetch by slug
|
|
132
|
+
const channel = await client.channels.fetchBySlug('monstercat');
|
|
133
|
+
|
|
134
|
+
// Fetch by broadcaster user ID
|
|
135
|
+
const channel = await client.channels.fetchById(123);
|
|
136
|
+
|
|
137
|
+
// Fetch multiple at once
|
|
138
|
+
const channels = await client.channels.fetch({ slug: ['monstercat', 'kick'] });
|
|
139
|
+
// or: client.channels.fetch({ broadcasterUserId: [123, 456] })
|
|
140
|
+
|
|
141
|
+
// Update the authenticated user's channel
|
|
142
|
+
await client.channels.update({
|
|
143
|
+
streamTitle: 'My new stream title',
|
|
144
|
+
categoryId: 15,
|
|
145
|
+
customTags: ['gaming', 'chill'],
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Livestreams
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
// Fetch live streams (no scope required)
|
|
155
|
+
const streams = await client.livestreams.fetch({
|
|
156
|
+
broadcasterUserId: [123, 456],
|
|
157
|
+
categoryId: 15,
|
|
158
|
+
language: 'en',
|
|
159
|
+
limit: 20,
|
|
160
|
+
sort: 'viewer_count', // or 'started_at'
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Total live stream count
|
|
164
|
+
const stats = await client.livestreams.fetchStats();
|
|
165
|
+
console.log(stats.total_count);
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Categories
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
// v1: fetch all categories
|
|
174
|
+
const categories = await client.categories.fetch();
|
|
175
|
+
|
|
176
|
+
// v2: search with pagination
|
|
177
|
+
const results = await client.categoriesV2.search({ query: 'gaming', limit: 10 });
|
|
178
|
+
|
|
179
|
+
// v2: fetch a single category by ID
|
|
180
|
+
const category = await client.categoriesV2.fetch(15);
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Chat
|
|
186
|
+
|
|
187
|
+
Required scope: `chat:write` (send), `moderation:chat_message:manage` (delete)
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
import { ChatMessageType } from '@phxgg/kick.js';
|
|
191
|
+
|
|
192
|
+
// Send a bot message (default)
|
|
193
|
+
const message = await client.chat.send({
|
|
194
|
+
content: 'Hello from kick.js!',
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Send a message as the authenticated user to a specific channel
|
|
198
|
+
const message = await client.chat.send({
|
|
199
|
+
content: 'Hello!',
|
|
200
|
+
broadcasterUserId: 123,
|
|
201
|
+
type: ChatMessageType.USER,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Reply to a message
|
|
205
|
+
const reply = await client.chat.send({
|
|
206
|
+
content: 'Nice catch!',
|
|
207
|
+
replyToMessageId: 'some-message-id',
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Delete a message
|
|
211
|
+
await client.chat.delete('some-message-id');
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Channel Rewards
|
|
217
|
+
|
|
218
|
+
Required scope: `channel:rewards:read` (read), `channel:rewards:write` (create / update / delete)
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
// Fetch all rewards for the authenticated broadcaster
|
|
222
|
+
const rewards = await client.channelRewards.fetch();
|
|
223
|
+
|
|
224
|
+
// Create a reward
|
|
225
|
+
const reward = await client.channelRewards.create({
|
|
226
|
+
title: 'Hydrate!',
|
|
227
|
+
cost: 500,
|
|
228
|
+
description: 'Make the streamer drink water.',
|
|
229
|
+
isEnabled: true,
|
|
230
|
+
isUserInputRequired: false,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// Update a reward
|
|
234
|
+
await client.channelRewards.update(reward.id, {
|
|
235
|
+
cost: 1000,
|
|
236
|
+
isPaused: false,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Delete a reward
|
|
240
|
+
await client.channelRewards.delete(reward.id);
|
|
241
|
+
|
|
242
|
+
// Fetch redemptions (defaults to pending)
|
|
243
|
+
const redemptions = await client.channelRewards.getRedemptions({
|
|
244
|
+
rewardId: reward.id,
|
|
245
|
+
status: 'pending',
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// Accept / reject redemptions (up to 25 per call)
|
|
249
|
+
await client.channelRewards.acceptRedemptions({ ids: [redemptions[0].id] });
|
|
250
|
+
await client.channelRewards.rejectRedemptions({ ids: [redemptions[1].id] });
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Moderation
|
|
256
|
+
|
|
257
|
+
Required scope: `moderation:ban`
|
|
258
|
+
|
|
259
|
+
```ts
|
|
260
|
+
// Ban a user permanently
|
|
261
|
+
await client.moderation.banUser({
|
|
262
|
+
broadcasterUserId: 123,
|
|
263
|
+
userId: 456,
|
|
264
|
+
reason: 'Spamming',
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// Timeout a user (duration in minutes, max 10080 = 7 days)
|
|
268
|
+
await client.moderation.timeoutUser({
|
|
269
|
+
broadcasterUserId: 123,
|
|
270
|
+
userId: 456,
|
|
271
|
+
duration: 10,
|
|
272
|
+
reason: 'Cool off.',
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// Remove a ban or timeout
|
|
276
|
+
await client.moderation.removeBan({
|
|
277
|
+
broadcasterUserId: 123,
|
|
278
|
+
userId: 456,
|
|
279
|
+
});
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## KICKs
|
|
285
|
+
|
|
286
|
+
Required scope: `kicks:read`
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
// Fetch the KICKs leaderboard for the authenticated broadcaster
|
|
290
|
+
const leaderboard = await client.kicks.fetchLeaderboard({ top: 10 });
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Event subscriptions
|
|
296
|
+
|
|
297
|
+
Required scope: `events:subscribe`
|
|
298
|
+
|
|
299
|
+
Subscribe your app to receive webhook events for a broadcaster.
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
import { WebhookEvents } from '@phxgg/kick.js';
|
|
303
|
+
|
|
304
|
+
// Subscribe to a single event
|
|
305
|
+
await client.events.subscribe({
|
|
306
|
+
broadcasterUserId: 123,
|
|
307
|
+
event: { name: WebhookEvents.CHAT_MESSAGE_SENT, version: 1 },
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Subscribe to multiple events at once
|
|
311
|
+
await client.events.subscribeMultiple({
|
|
312
|
+
broadcasterUserId: 123,
|
|
313
|
+
events: [
|
|
314
|
+
{ name: WebhookEvents.CHANNEL_FOLLOWED, version: 1 },
|
|
315
|
+
{ name: WebhookEvents.LIVESTREAM_STATUS_UPDATED, version: 1 },
|
|
316
|
+
],
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// List active subscriptions
|
|
320
|
+
const subs = await client.events.fetch();
|
|
321
|
+
|
|
322
|
+
// Unsubscribe
|
|
323
|
+
await client.events.unsubscribe(subs[0].id);
|
|
324
|
+
await client.events.unsubscribeMultiple(subs.map((s) => s.id));
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Webhooks
|
|
330
|
+
|
|
331
|
+
kick.js provides framework-agnostic primitives so you can handle Kick webhook deliveries in any HTTP server.
|
|
332
|
+
|
|
333
|
+
### Verify & dispatch
|
|
334
|
+
|
|
335
|
+
```ts
|
|
336
|
+
import { verifyKickSignature, dispatchWebhookEvent, getKickPublicKey } from '@phxgg/kick.js';
|
|
337
|
+
|
|
338
|
+
// Inside your POST /webhooks/kick handler:
|
|
339
|
+
const publicKey = await getKickPublicKey(); // cached, refreshes every hour
|
|
340
|
+
|
|
341
|
+
const valid = verifyKickSignature({
|
|
342
|
+
messageId: req.headers['kick-event-message-id'],
|
|
343
|
+
messageTimestamp: req.headers['kick-event-message-timestamp'],
|
|
344
|
+
rawBody: rawBody, // Buffer or string — must be read before JSON.parse
|
|
345
|
+
signature: req.headers['kick-event-signature'],
|
|
346
|
+
publicKey,
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
if (!valid) return res.sendStatus(403);
|
|
350
|
+
|
|
351
|
+
const eventType = req.headers['kick-event-type'];
|
|
352
|
+
const payload = JSON.parse(rawBody);
|
|
353
|
+
|
|
354
|
+
// Route to whichever KickClient is registered for this broadcaster
|
|
355
|
+
dispatchWebhookEvent(eventType, payload);
|
|
356
|
+
|
|
357
|
+
res.sendStatus(200);
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Per-client listeners
|
|
361
|
+
|
|
362
|
+
After calling `client.setToken()`, the client registers itself so that `dispatchWebhookEvent` can route events to the correct instance. Use `client.on()` to react to events:
|
|
363
|
+
|
|
364
|
+
```ts
|
|
365
|
+
import { WebhookEvents } from '@phxgg/kick.js';
|
|
366
|
+
|
|
367
|
+
client.on(WebhookEvents.CHAT_MESSAGE_SENT, (payload) => {
|
|
368
|
+
console.log(`${payload.sender.username}: ${payload.content}`);
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
client.on(WebhookEvents.CHANNEL_FOLLOWED, (payload) => {
|
|
372
|
+
console.log(`${payload.follower.username} followed the channel!`);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
client.on(WebhookEvents.LIVESTREAM_STATUS_UPDATED, (payload) => {
|
|
376
|
+
console.log('Stream is now', payload.is_live ? 'live' : 'offline');
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
// Remove a listener
|
|
380
|
+
client.off(WebhookEvents.CHAT_MESSAGE_SENT, myListener);
|
|
381
|
+
|
|
382
|
+
// Remove all listeners
|
|
383
|
+
client.removeAllListeners();
|
|
384
|
+
|
|
385
|
+
// Clean up the client and deregister it from the event manager
|
|
386
|
+
client.destroy();
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
**Supported webhook events**
|
|
390
|
+
|
|
391
|
+
| Event | Constant |
|
|
392
|
+
| ----------------------------------- | ------------------------------------------------- |
|
|
393
|
+
| `chat.message.sent` | `WebhookEvents.CHAT_MESSAGE_SENT` |
|
|
394
|
+
| `channel.followed` | `WebhookEvents.CHANNEL_FOLLOWED` |
|
|
395
|
+
| `channel.subscription.new` | `WebhookEvents.CHANNEL_SUBSCRIPTION_NEW` |
|
|
396
|
+
| `channel.subscription.renewal` | `WebhookEvents.CHANNEL_SUBSCRIPTION_RENEWAL` |
|
|
397
|
+
| `channel.subscription.gifts` | `WebhookEvents.CHANNEL_SUBSCRIPTION_GIFTS` |
|
|
398
|
+
| `channel.reward.redemption.updated` | `WebhookEvents.CHANNEL_REWARD_REDEMPTION_UPDATED` |
|
|
399
|
+
| `livestream.status.updated` | `WebhookEvents.LIVESTREAM_STATUS_UPDATED` |
|
|
400
|
+
| `livestream.metadata.updated` | `WebhookEvents.LIVESTREAM_METADATA_UPDATED` |
|
|
401
|
+
| `moderation.banned` | `WebhookEvents.MODERATION_BANNED` |
|
|
402
|
+
| `kicks.gifted` | `WebhookEvents.KICKS_GIFTED` |
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
406
|
+
## Error handling
|
|
407
|
+
|
|
408
|
+
All methods throw typed errors on non-2xx responses:
|
|
409
|
+
|
|
410
|
+
```ts
|
|
411
|
+
import {
|
|
412
|
+
UnauthorizedError,
|
|
413
|
+
ForbiddenError,
|
|
414
|
+
NotFoundError,
|
|
415
|
+
RateLimitError,
|
|
416
|
+
BadRequestError,
|
|
417
|
+
MissingScopeError,
|
|
418
|
+
NoTokenSetError,
|
|
419
|
+
} from '@phxgg/kick.js';
|
|
420
|
+
|
|
421
|
+
try {
|
|
422
|
+
const me = await client.users.me();
|
|
423
|
+
} catch (err) {
|
|
424
|
+
if (err instanceof UnauthorizedError) {
|
|
425
|
+
// token expired — refresh and retry
|
|
426
|
+
} else if (err instanceof MissingScopeError) {
|
|
427
|
+
// the token is missing a required scope
|
|
428
|
+
} else if (err instanceof RateLimitError) {
|
|
429
|
+
// back off and retry
|
|
430
|
+
} else {
|
|
431
|
+
throw err;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Example app
|
|
439
|
+
|
|
440
|
+
A full Express + MongoDB reference implementation is available in [`examples/express-app`](https://github.com/phxgg/kick.js/tree/main/examples/express-app).
|
|
441
|
+
|
|
442
|
+
## License
|
|
443
|
+
|
|
444
|
+
[MIT](./LICENSE)
|