@lagent_titi/kick.js-ts 1.0.1

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.
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@lagent_titi/kick.js-ts",
3
+ "version": "1.0.1",
4
+ "description": "Node.js TypeScript client for Kick.com API",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/lagentiti/kick.api-ts.git"
13
+ },
14
+ "keywords": [
15
+ "kick",
16
+ "kickapi",
17
+ "kickcom",
18
+ "api"
19
+ ],
20
+ "author": "botk4cp3r",
21
+ "license": "MIT",
22
+ "bugs": {
23
+ "url": "https://github.com/BOT-K4CP3R/kick.api/issues"
24
+ },
25
+ "homepage": "https://github.com/BOT-K4CP3R/kick.api#readme",
26
+ "dependencies": {
27
+ "express": "^4.21.2"
28
+ },
29
+ "devDependencies": {
30
+ "@types/express": "^5.0.3",
31
+ "@types/node": "^24.0.10",
32
+ "cpx": "^1.5.0",
33
+ "typescript": "^5.8.3"
34
+ },
35
+ "scripts": {
36
+ "build": "tsc && cpx \"package.json\" dist && cpx \"README.md\" dist",
37
+ "start": "node dist/index.js",
38
+ "dev": "ts-node src/index.ts"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public",
42
+ "registry": "https://registry.npmjs.org/"
43
+ }
44
+ }
@@ -0,0 +1,7 @@
1
+ export declare class CategoriesService {
2
+ private apiClient;
3
+ private baseUrl;
4
+ constructor(apiClient: any);
5
+ getCategories(searchQuery?: string, token?: string): Promise<any>;
6
+ getCategory(categoryId: string | number, token?: string): Promise<any>;
7
+ }
@@ -0,0 +1,30 @@
1
+ export class CategoriesService {
2
+ constructor(apiClient) {
3
+ this.apiClient = apiClient;
4
+ this.baseUrl = 'https://api.kick.com/public/v1/categories';
5
+ }
6
+ async getCategories(searchQuery = '', token = '') {
7
+ const url = new URL(this.baseUrl);
8
+ if (searchQuery) {
9
+ url.searchParams.append('q', searchQuery);
10
+ }
11
+ const response = await fetch(url.toString(), {
12
+ method: 'GET',
13
+ headers: Object.assign({}, (token && { Authorization: `Bearer ${token}` }))
14
+ });
15
+ if (!response.ok) {
16
+ throw new Error(`HTTP error! status: ${response.status}`);
17
+ }
18
+ return await response.json();
19
+ }
20
+ async getCategory(categoryId, token = '') {
21
+ const response = await fetch(`${this.baseUrl}/${categoryId}`, {
22
+ method: 'GET',
23
+ headers: Object.assign({}, (token && { Authorization: `Bearer ${token}` }))
24
+ });
25
+ if (!response.ok) {
26
+ throw new Error(`HTTP error! status: ${response.status}`);
27
+ }
28
+ return await response.json();
29
+ }
30
+ }
@@ -0,0 +1,10 @@
1
+ export declare class ChannelsService {
2
+ private apiClient;
3
+ private baseUrl;
4
+ constructor(apiClient: any);
5
+ getChannels(broadcasterIds: (string | number)[] | undefined, token: string): Promise<any>;
6
+ updateChannel(options: {
7
+ categoryId: number | string;
8
+ streamTitle: string;
9
+ }, token: string): Promise<boolean>;
10
+ }
@@ -0,0 +1,46 @@
1
+ import { UnauthorizedError, ForbiddenError } from '../errors';
2
+ export class ChannelsService {
3
+ constructor(apiClient) {
4
+ this.apiClient = apiClient;
5
+ this.baseUrl = 'https://api.kick.com/public/v1/channels';
6
+ }
7
+ async getChannels(broadcasterIds = [], token) {
8
+ const url = new URL(this.baseUrl);
9
+ if (broadcasterIds.length > 0) {
10
+ broadcasterIds.forEach(id => url.searchParams.append('broadcaster_user_id[]', id.toString()));
11
+ }
12
+ const response = await fetch(url.toString(), {
13
+ method: 'GET',
14
+ headers: {
15
+ Authorization: `Bearer ${token}`
16
+ }
17
+ });
18
+ if (response.status === 401)
19
+ throw new UnauthorizedError();
20
+ if (response.status === 403)
21
+ throw new ForbiddenError();
22
+ if (!response.ok)
23
+ throw new Error(`HTTP error! status: ${response.status}`);
24
+ return await response.json();
25
+ }
26
+ async updateChannel(options, token) {
27
+ const response = await fetch(this.baseUrl, {
28
+ method: 'PATCH',
29
+ headers: {
30
+ Authorization: `Bearer ${token}`,
31
+ 'Content-Type': 'application/json'
32
+ },
33
+ body: JSON.stringify({
34
+ category_id: options.categoryId,
35
+ stream_title: options.streamTitle
36
+ })
37
+ });
38
+ if (response.status === 401)
39
+ throw new UnauthorizedError();
40
+ if (response.status === 403)
41
+ throw new ForbiddenError();
42
+ if (!response.ok)
43
+ throw new Error(`HTTP error! status: ${response.status}`);
44
+ return response.status === 204;
45
+ }
46
+ }
@@ -0,0 +1,13 @@
1
+ interface SendMessageOptions {
2
+ content: string;
3
+ type?: 'user' | 'bot';
4
+ broadcasterUserId?: number | string;
5
+ token: string;
6
+ }
7
+ export declare class ChatService {
8
+ private apiClient;
9
+ private baseUrl;
10
+ constructor(apiClient: any);
11
+ sendMessage(options: SendMessageOptions): Promise<any>;
12
+ }
13
+ export {};
@@ -0,0 +1,43 @@
1
+ import { UnauthorizedError, ForbiddenError } from '../errors';
2
+ export class ChatService {
3
+ constructor(apiClient) {
4
+ this.apiClient = apiClient;
5
+ this.baseUrl = 'https://api.kick.com/public/v1/chat';
6
+ }
7
+ async sendMessage(options) {
8
+ const payload = {
9
+ content: options.content,
10
+ type: options.type || 'bot'
11
+ };
12
+ if (payload.type === 'user') {
13
+ if (!options.broadcasterUserId) {
14
+ throw new Error('broadcaster_user_id is required for user type messages');
15
+ }
16
+ payload.broadcaster_user_id = options.broadcasterUserId;
17
+ }
18
+ if (payload.content.length > 500) {
19
+ throw new Error('Message content cannot exceed 500 characters');
20
+ }
21
+ if (!['user', 'bot'].includes(payload.type)) {
22
+ throw new Error('Message type must be either "user" or "bot"');
23
+ }
24
+ const response = await fetch(this.baseUrl, {
25
+ method: 'POST',
26
+ headers: {
27
+ Authorization: `Bearer ${options.token}`,
28
+ 'Content-Type': 'application/json'
29
+ },
30
+ body: JSON.stringify(payload)
31
+ });
32
+ if (response.status === 401)
33
+ throw new UnauthorizedError();
34
+ if (response.status === 403)
35
+ throw new ForbiddenError();
36
+ if (!response.ok) {
37
+ const error = await response.json().catch(() => ({}));
38
+ throw new Error(`HTTP error! status: ${response.status}, message: ${error.message || 'Unknown error'}`);
39
+ }
40
+ const result = await response.json();
41
+ return result.data || result;
42
+ }
43
+ }
@@ -0,0 +1,40 @@
1
+ import { WebhookType } from '../types/webhooks';
2
+ export type { WebhookType };
3
+ export interface WebhookHeaders {
4
+ 'kick-event-message-id': string;
5
+ 'kick-event-message-timestamp': string;
6
+ 'kick-event-signature': string;
7
+ 'kick-event-type': WebhookType;
8
+ 'kick-event-version': string;
9
+ [key: string]: string;
10
+ }
11
+ interface ApiClient {
12
+ getPublicKey: () => Promise<{
13
+ data: {
14
+ public_key: string;
15
+ };
16
+ }>;
17
+ options: {
18
+ webhookBaseUrl: string;
19
+ webhookPort: number;
20
+ webhookPath: string;
21
+ };
22
+ }
23
+ export declare class EventsService {
24
+ private apiClient;
25
+ private verifier;
26
+ private baseUrl;
27
+ constructor(apiClient: ApiClient);
28
+ initializeVerifier(): Promise<void>;
29
+ validateWebhook(headers: WebhookHeaders, body: string): {
30
+ isValid: boolean;
31
+ eventType: WebhookType;
32
+ version: string;
33
+ messageId: string;
34
+ timestamp: string;
35
+ payload: unknown;
36
+ };
37
+ getSubscriptions(token: string): Promise<unknown>;
38
+ subscribe(events: WebhookType[], method: "webhook" | string | undefined, token: string): Promise<unknown>;
39
+ unsubscribe(subscriptionIds: string[], token: string): Promise<boolean>;
40
+ }
@@ -0,0 +1,100 @@
1
+ import { SignatureVerifier } from '../utils/signature';
2
+ import { UnauthorizedError, ForbiddenError } from '../errors';
3
+ import { parseWebhookPayload } from '../types/webhooks';
4
+ export class EventsService {
5
+ constructor(apiClient) {
6
+ this.verifier = null;
7
+ this.baseUrl = 'https://api.kick.com/public/v1/events';
8
+ this.apiClient = apiClient;
9
+ }
10
+ async initializeVerifier() {
11
+ if (!this.verifier) {
12
+ const publicKeyResponse = await this.apiClient.getPublicKey();
13
+ this.verifier = new SignatureVerifier(publicKeyResponse.data.public_key);
14
+ }
15
+ }
16
+ validateWebhook(headers, body) {
17
+ if (!this.verifier) {
18
+ throw new Error('Signature verifier not initialized');
19
+ }
20
+ const messageId = headers['kick-event-message-id'];
21
+ const timestamp = headers['kick-event-message-timestamp'];
22
+ const signature = headers['kick-event-signature'];
23
+ const eventType = headers['kick-event-type'];
24
+ const version = headers['kick-event-version'];
25
+ if (!messageId || !timestamp || !signature) {
26
+ throw new Error('Missing required webhook headers');
27
+ }
28
+ const isValid = this.verifier.verify(messageId, timestamp, body, signature);
29
+ const parsedPayload = parseWebhookPayload(eventType, JSON.parse(body));
30
+ return {
31
+ isValid,
32
+ eventType,
33
+ version,
34
+ messageId,
35
+ timestamp,
36
+ payload: parsedPayload
37
+ };
38
+ }
39
+ async getSubscriptions(token) {
40
+ const response = await fetch(`${this.baseUrl}/subscriptions`, {
41
+ method: 'GET',
42
+ headers: {
43
+ Authorization: `Bearer ${token}`
44
+ }
45
+ });
46
+ if (response.status === 401)
47
+ throw new UnauthorizedError();
48
+ if (response.status === 403)
49
+ throw new ForbiddenError();
50
+ if (!response.ok)
51
+ throw new Error(`HTTP error! status: ${response.status}`);
52
+ return await response.json();
53
+ }
54
+ async subscribe(events, method = 'webhook', token) {
55
+ const webhookUrl = `${this.apiClient.options.webhookBaseUrl}:${this.apiClient.options.webhookPort}${this.apiClient.options.webhookPath}`;
56
+ const payload = {
57
+ method: method,
58
+ url: webhookUrl,
59
+ types: events.map((eventName) => ({
60
+ name: eventName,
61
+ version: 1
62
+ }))
63
+ };
64
+ const response = await fetch(`${this.baseUrl}/subscriptions`, {
65
+ method: 'POST',
66
+ headers: {
67
+ Authorization: `Bearer ${token}`,
68
+ 'Content-Type': 'application/json'
69
+ },
70
+ body: JSON.stringify(payload)
71
+ });
72
+ if (response.status === 401)
73
+ throw new UnauthorizedError();
74
+ if (response.status === 403)
75
+ throw new ForbiddenError();
76
+ if (!response.ok) {
77
+ const error = await response.json().catch(() => ({}));
78
+ throw new Error(`HTTP error! status: ${response.status}, message: ${JSON.stringify(error)}`);
79
+ }
80
+ return await response.json();
81
+ }
82
+ async unsubscribe(subscriptionIds, token) {
83
+ const url = new URL(`${this.baseUrl}/subscriptions`);
84
+ subscriptionIds.forEach(id => url.searchParams.append('id[]', id));
85
+ const response = await fetch(url.toString(), {
86
+ method: 'DELETE',
87
+ headers: {
88
+ Authorization: `Bearer ${token}`
89
+ }
90
+ });
91
+ if (response.status === 401)
92
+ throw new UnauthorizedError();
93
+ if (response.status === 403)
94
+ throw new ForbiddenError();
95
+ if (!response.ok && response.status !== 204) {
96
+ throw new Error(`HTTP error! status: ${response.status}`);
97
+ }
98
+ return response.status === 204;
99
+ }
100
+ }
@@ -0,0 +1,6 @@
1
+ export declare class PublicKeyService {
2
+ private apiClient;
3
+ private baseUrl;
4
+ constructor(apiClient: any);
5
+ getPublicKey(): Promise<any>;
6
+ }
@@ -0,0 +1,17 @@
1
+ import { UnauthorizedError } from '../errors';
2
+ export class PublicKeyService {
3
+ constructor(apiClient) {
4
+ this.apiClient = apiClient;
5
+ this.baseUrl = 'https://api.kick.com/public/v1/public-key';
6
+ }
7
+ async getPublicKey() {
8
+ const response = await fetch(this.baseUrl, {
9
+ method: 'GET'
10
+ });
11
+ if (response.status === 401)
12
+ throw new UnauthorizedError();
13
+ if (!response.ok)
14
+ throw new Error(`HTTP error! status: ${response.status}`);
15
+ return await response.json();
16
+ }
17
+ }
@@ -0,0 +1,7 @@
1
+ export declare class UsersService {
2
+ private apiClient;
3
+ private baseUrl;
4
+ constructor(apiClient: any);
5
+ introspectToken(token: string): Promise<any>;
6
+ getUsers(userIds: string[] | undefined, token: string): Promise<any>;
7
+ }
@@ -0,0 +1,39 @@
1
+ import { UnauthorizedError, ForbiddenError } from '../errors';
2
+ export class UsersService {
3
+ constructor(apiClient) {
4
+ this.apiClient = apiClient;
5
+ this.baseUrl = 'https://api.kick.com/public/v1';
6
+ }
7
+ async introspectToken(token) {
8
+ const response = await fetch(`${this.baseUrl}/token/introspect`, {
9
+ method: 'POST',
10
+ headers: {
11
+ Authorization: `Bearer ${token}`
12
+ }
13
+ });
14
+ if (response.status === 401)
15
+ throw new UnauthorizedError();
16
+ if (!response.ok)
17
+ throw new Error(`HTTP error! status: ${response.status}`);
18
+ return await response.json();
19
+ }
20
+ async getUsers(userIds = [], token) {
21
+ const url = new URL(`${this.baseUrl}/users`);
22
+ if (userIds.length > 0) {
23
+ userIds.forEach(id => url.searchParams.append('id[]', id));
24
+ }
25
+ const response = await fetch(url, {
26
+ method: 'GET',
27
+ headers: {
28
+ Authorization: `Bearer ${token}`
29
+ }
30
+ });
31
+ if (response.status === 401)
32
+ throw new UnauthorizedError();
33
+ if (response.status === 403)
34
+ throw new ForbiddenError();
35
+ if (!response.ok)
36
+ throw new Error(`HTTP error! status: ${response.status}`);
37
+ return await response.json();
38
+ }
39
+ }
@@ -0,0 +1,9 @@
1
+ export declare const WEBHOOK_TYPES: {
2
+ readonly CHAT_MESSAGE: "chat.message.sent";
3
+ readonly CHANNEL_FOLLOWED: "channel.followed";
4
+ readonly SUBSCRIPTION_RENEWAL: "channel.subscription.renewal";
5
+ readonly SUBSCRIPTION_GIFTS: "channel.subscription.gifts";
6
+ readonly SUBSCRIPTION_NEW: "channel.subscription.new";
7
+ };
8
+ export type WebhookType = (typeof WEBHOOK_TYPES)[keyof typeof WEBHOOK_TYPES];
9
+ export declare function parseWebhookPayload(type: WebhookType, payload: any): any;
@@ -0,0 +1,111 @@
1
+ export const WEBHOOK_TYPES = {
2
+ CHAT_MESSAGE: 'chat.message.sent',
3
+ CHANNEL_FOLLOWED: 'channel.followed',
4
+ SUBSCRIPTION_RENEWAL: 'channel.subscription.renewal',
5
+ SUBSCRIPTION_GIFTS: 'channel.subscription.gifts',
6
+ SUBSCRIPTION_NEW: 'channel.subscription.new'
7
+ };
8
+ export function parseWebhookPayload(type, payload) {
9
+ switch (type) {
10
+ case WEBHOOK_TYPES.CHAT_MESSAGE:
11
+ return {
12
+ messageId: payload.message_id,
13
+ broadcaster: {
14
+ isAnonymous: payload.broadcaster.is_anonymous,
15
+ userId: payload.broadcaster.user_id,
16
+ username: payload.broadcaster.username,
17
+ isVerified: payload.broadcaster.is_verified,
18
+ profilePicture: payload.broadcaster.profile_picture,
19
+ channelSlug: payload.broadcaster.channel_slug
20
+ },
21
+ sender: {
22
+ isAnonymous: payload.sender.is_anonymous,
23
+ userId: payload.sender.user_id,
24
+ username: payload.sender.username,
25
+ isVerified: payload.sender.is_verified,
26
+ profilePicture: payload.sender.profile_picture,
27
+ channelSlug: payload.sender.channel_slug
28
+ },
29
+ content: payload.content,
30
+ emotes: Array.isArray(payload.emotes)
31
+ ? payload.emotes.map((emote) => ({
32
+ emoteId: emote.emote_id,
33
+ positions: emote.positions
34
+ }))
35
+ : null
36
+ };
37
+ case WEBHOOK_TYPES.CHANNEL_FOLLOWED:
38
+ return {
39
+ broadcaster: {
40
+ isAnonymous: payload.broadcaster.is_anonymous,
41
+ userId: payload.broadcaster.user_id,
42
+ username: payload.broadcaster.username,
43
+ isVerified: payload.broadcaster.is_verified,
44
+ profilePicture: payload.broadcaster.profile_picture,
45
+ channelSlug: payload.broadcaster.channel_slug
46
+ },
47
+ follower: {
48
+ isAnonymous: payload.follower.is_anonymous,
49
+ userId: payload.follower.user_id,
50
+ username: payload.follower.username,
51
+ isVerified: payload.follower.is_verified,
52
+ profilePicture: payload.follower.profile_picture,
53
+ channelSlug: payload.follower.channel_slug
54
+ }
55
+ };
56
+ case WEBHOOK_TYPES.SUBSCRIPTION_RENEWAL:
57
+ case WEBHOOK_TYPES.SUBSCRIPTION_NEW:
58
+ return {
59
+ broadcaster: {
60
+ isAnonymous: payload.broadcaster.is_anonymous,
61
+ userId: payload.broadcaster.user_id,
62
+ username: payload.broadcaster.username,
63
+ isVerified: payload.broadcaster.is_verified,
64
+ profilePicture: payload.broadcaster.profile_picture,
65
+ channelSlug: payload.broadcaster.channel_slug
66
+ },
67
+ subscriber: {
68
+ isAnonymous: payload.subscriber.is_anonymous,
69
+ userId: payload.subscriber.user_id,
70
+ username: payload.subscriber.username,
71
+ isVerified: payload.subscriber.is_verified,
72
+ profilePicture: payload.subscriber.profile_picture,
73
+ channelSlug: payload.subscriber.channel_slug
74
+ },
75
+ duration: payload.duration,
76
+ createdAt: new Date(payload.created_at)
77
+ };
78
+ case WEBHOOK_TYPES.SUBSCRIPTION_GIFTS:
79
+ return {
80
+ broadcaster: {
81
+ isAnonymous: payload.broadcaster.is_anonymous,
82
+ userId: payload.broadcaster.user_id,
83
+ username: payload.broadcaster.username,
84
+ isVerified: payload.broadcaster.is_verified,
85
+ profilePicture: payload.broadcaster.profile_picture,
86
+ channelSlug: payload.broadcaster.channel_slug
87
+ },
88
+ gifter: payload.gifter.is_anonymous
89
+ ? { isAnonymous: true }
90
+ : {
91
+ isAnonymous: false,
92
+ userId: payload.gifter.user_id,
93
+ username: payload.gifter.username,
94
+ isVerified: payload.gifter.is_verified,
95
+ profilePicture: payload.gifter.profile_picture,
96
+ channelSlug: payload.gifter.channel_slug
97
+ },
98
+ giftees: payload.giftees.map((giftee) => ({
99
+ isAnonymous: giftee.is_anonymous,
100
+ userId: giftee.user_id,
101
+ username: giftee.username,
102
+ isVerified: giftee.is_verified,
103
+ profilePicture: giftee.profile_picture,
104
+ channelSlug: giftee.channel_slug
105
+ })),
106
+ createdAt: new Date(payload.created_at)
107
+ };
108
+ default:
109
+ return payload;
110
+ }
111
+ }
@@ -0,0 +1,6 @@
1
+ export declare class SignatureVerifier {
2
+ private publicKey;
3
+ constructor(publicKey: string | Buffer);
4
+ createSignaturePayload(messageId: string, timestamp: string, body: string): string;
5
+ verify(messageId: string, timestamp: string, body: string, signature: string): boolean;
6
+ }
@@ -0,0 +1,21 @@
1
+ import crypto from 'crypto';
2
+ export class SignatureVerifier {
3
+ constructor(publicKey) {
4
+ this.publicKey = publicKey;
5
+ }
6
+ createSignaturePayload(messageId, timestamp, body) {
7
+ return `${messageId}.${timestamp}.${body}`;
8
+ }
9
+ verify(messageId, timestamp, body, signature) {
10
+ const payload = this.createSignaturePayload(messageId, timestamp, body);
11
+ const verifier = crypto.createVerify('RSA-SHA256');
12
+ verifier.update(payload);
13
+ try {
14
+ const signatureBuffer = Buffer.from(signature, 'base64');
15
+ return verifier.verify(this.publicKey, signatureBuffer);
16
+ }
17
+ catch (error) {
18
+ return false;
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,10 @@
1
+ import { EventEmitter } from 'events';
2
+ export declare class WebhookHandler {
3
+ private client;
4
+ constructor(client: EventEmitter);
5
+ handleWebhook(headers: Record<string, string>, rawBody: Buffer | string | object): Promise<{
6
+ eventType: string;
7
+ eventVersion: string;
8
+ payload: any;
9
+ }>;
10
+ }
@@ -0,0 +1,59 @@
1
+ export class WebhookHandler {
2
+ constructor(client) {
3
+ this.client = client;
4
+ }
5
+ async handleWebhook(headers, rawBody) {
6
+ const body = rawBody instanceof Buffer ? rawBody.toString('utf8') : rawBody;
7
+ const payload = typeof body === 'string' ? JSON.parse(body) : body;
8
+ const eventType = headers['kick-event-type'];
9
+ const eventVersion = headers['kick-event-version'];
10
+ switch (eventType) {
11
+ case 'chat.message.sent':
12
+ this.client.emit('chatMessage', {
13
+ messageId: payload.message_id,
14
+ broadcaster: payload.broadcaster,
15
+ sender: payload.sender,
16
+ content: payload.content,
17
+ emotes: payload.emotes || []
18
+ });
19
+ break;
20
+ case 'channel.followed':
21
+ this.client.emit('channelFollowed', {
22
+ broadcaster: payload.broadcaster,
23
+ follower: payload.follower
24
+ });
25
+ break;
26
+ case 'channel.subscription.renewal':
27
+ this.client.emit('subscriptionRenewal', {
28
+ broadcaster: payload.broadcaster,
29
+ subscriber: payload.subscriber,
30
+ duration: payload.duration,
31
+ createdAt: payload.created_at
32
+ });
33
+ break;
34
+ case 'channel.subscription.gifts':
35
+ this.client.emit('subscriptionGifts', {
36
+ broadcaster: payload.broadcaster,
37
+ gifter: payload.gifter,
38
+ giftees: payload.giftees,
39
+ createdAt: payload.created_at
40
+ });
41
+ break;
42
+ case 'channel.subscription.new':
43
+ this.client.emit('subscriptionNew', {
44
+ broadcaster: payload.broadcaster,
45
+ subscriber: payload.subscriber,
46
+ duration: payload.duration,
47
+ createdAt: payload.created_at
48
+ });
49
+ break;
50
+ default:
51
+ this.client.emit('unknownEvent', { eventType, payload });
52
+ }
53
+ return {
54
+ eventType,
55
+ eventVersion,
56
+ payload
57
+ };
58
+ }
59
+ }
@@ -0,0 +1,17 @@
1
+ import { EventEmitter } from 'events';
2
+ interface WebhookServerOptions {
3
+ port?: number;
4
+ path?: string;
5
+ }
6
+ export declare class WebhookServer {
7
+ private client;
8
+ private port;
9
+ private path;
10
+ private app;
11
+ private server;
12
+ constructor(client: EventEmitter, options?: WebhookServerOptions);
13
+ private setup;
14
+ start(): Promise<void>;
15
+ stop(): Promise<void>;
16
+ }
17
+ export {};