npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

kick-live-connector

v1.0.0

Published

A Node.js library to receive live stream events such as comments and gifts in real-time from Kick LIVE

Downloads

229

Readme

Kick-Live-Connector

A Node.js library to receive real-time events from Kick LIVE by connecting to Kick's WebSocket service. This package enables tracking live stream events using a straightforward setup requiring only the streamer's username. You can connect to your own or other streamers' live chats without needing any credentials. Supported events include Chat Messages, Gifted Subscriptions, User Subscriptions, Viewer Counts, and other events like Streamer Is Live.

NOTE: This is not an official API. It's a reverse engineering project. While Kick has its own API, it currently requires registration for access. A public API is expected to be released by Kick in the future.

Library Design Tip: This library is written in TypeScript to provide enhanced type safety and better support for development. You can still use the library in JavaScript, but using TypeScript will allow you to see detailed type definitions for incoming data, making it simpler to handle each event. Some type definitions may still be refined, and improvements will be released in future updates.

NOTE: This library is designed for use in Node.js environments. If you want to process or display the data on the client side (in the browser), you’ll need to transfer it from the Node.js environment. One effective approach for this is to use Socket.IO or a similar low-latency communication framework.

Overview

Getting started

  1. Install the package via NPM
npm i kick-live-connector
  1. Create your first chat connection
import { KickConnection , Events} from "kick-live-connector";

const username = "lox-x";

const kickConnection = new KickConnection(username);

// Connect to the chat (await can be used as well)
kickConnection.connect().then((status) => {
    console.log(`Connected to chatroom ${status.roomID}`);
  })
  .catch((error) => {
    console.error("Connection failed:", error);
  });

// Define the events that you want to handle
kickConnection.on(Events.ChatMessage, (data) => {
  const { content, sender } = data;
  console.log(`${sender.username} says: ${content}`);
});

// ... more events described in the documentation below

Events

Connection Events:

Chat Events:

Stream Events:

Connection Events

Connected

Triggered when the connection is successfully established.

tiktokLiveConnection.on(Events.Connected, state => {
    console.log(`Connected. RoomID:${state.roomID}`);
})

Disconnected

Triggered when the connection gets disconnected. In that case you can call connect() again to have a reconnect logic.

tiktokLiveConnection.on(Events.Disconnected, () => {
    console.log('Disconnected');
})

Error

General error event. You should handle this.

tiktokLiveConnection.on(Events.Error, err => {
    console.error('Error!', err);
})

Chat Events

Chat Message

Triggered every time a new chat comment arrives.

tiktokLiveConnection.on(Events.ChatMessage, message => {
    if(message.type == "reply") {
        console.log(`${message.sender.username} replyed to ${metadata.original_sender.username} said: ${message.content}`);
    }else{
        console.log(`${message.sender.username} said: ${message.content}`);
    }
})
//Message
{
  id: '00000000-0000-0000-0000-000000000000',
  chatroom_id: 0000,
  content: 'test',
  type: 'message',
  created_at: '2024-10-27T14:11:52+00:00',
  sender: {
    id: 346148,
    username: 'User',
    slug: 'user',
    identity: { color: '#FF9D00', badges: [
        { type: 'subscriber', text: 'Subscriber', count: 4 },
        { type: 'sub_gifter', text: 'Sub Gifter', count: 4 }
    ]}
  }
}

//Reply
{
  id: '00000000-0000-0000-0000-000000000000',
  chatroom_id: 00000000,
  content: 'test2',
  type: 'reply',
  created_at: '2024-10-27T14:21:32+00:00',
  sender: {
    id: 000000,
    username: 'User2',
    slug: 'user2',
    identity: { color: '#E9113C', badges: [] }
  },
  metadata: {
    original_sender: { id: 44065611, username: 'User1' },
    original_message: { id: '579f6afc-88ea-45fc-8dfd-1336e29ecb8b', content: 'test' }
  }
}

Message Deleted

Triggered every time a message is deleted.

kickConnection.on(Events.MessageDeleted,(message)=>{
    console.log(`Message Deleted ${message.id}`)
})
{
{
  id: '00000000-0000-0000-0000-000000000000',
  message: { id: '00000000-0000-0000-0000-000000000000' },
  aiModerated: false // True if deleted by bot
}
}

Pinned Message Created

Triggered every time a message is pinned. If a new message is pinned while there’s already a pinned message, the existing pinned message will be replaced, and this event will trigger again.

kickConnection.on(Events.PinnedMessageCreated,(message)=>{
    console.log(message)
})
{
  message: {
    id: '00000000-0000-0000-0000-000000000000',
    chatroom_id: 00000000,
    content: 'test',
    type: 'message',
    created_at: '2024-10-27T14:48:44+00:00',
    sender: {
      id: 00000000,
      username: 'User',
      slug: 'user',
      identity: [{
        color: string;
         badges: [ { type: 'broadcaster', text: 'Broadcaster', active: true } ];
      }]
    },
    metadata: null
  },
  duration: '1200',
  pinnedBy: {
    id: 44065611,
    username: 'User',
    slug: 'user',
    identity: { color: '#E9113C', badges: [] }
  }
}

Pinned Message Deleted

Triggered when a previously pinned message is unpinned.

kickConnection.on(Events.PinnedMessageDeleted,()=>{
    console.log(`Pinned Message Unpinned`)
})

Poll Update

Triggered when a poll is created or updated. When a poll is created, when a user votes, this event provides the latest details about the poll, including the current vote counts for each option and the remaining time.

kickConnection.on(Events.PollUpdate, (data) => {
    if(data.poll.has_voted === false){
        console.log(`Poll Created: "${data.poll.title}" - Remaining Time: ${data.poll.remaining} seconds`);
    }else{
        console.log(`Poll Updated: "${data.poll.title}" - Remaining Time: ${data.poll.remaining} seconds`);
        data.poll.options.forEach(option => {
            console.log(`Option: ${option.label}, Votes: ${option.votes}`);
        });
    }
});
//when poll is created
{
  poll: {
    title: 'What do you prefer?',
    options: [
        { id: 0, label: 'javascript', votes: 0 },
        { id: 1, label: 'typescript', votes: 0 }
    ],
    duration: 30,
    remaining: 30,
    result_display_duration: 15,
    has_voted: false,
    voted_option_id: null
  }
}

// When a user votes (poll update)
{
  poll: {
    title: 'What do you prefer?',
    options: [ 
        { id: 0, label: 'javascript', votes: 0 },
        { id: 1, label: 'typescript', votes: 1 }
    ],
    duration: 30,
    remaining: 22,
    result_display_duration: 15
  }
}

Poll Delete

Triggered when a poll is deleted. This event indicates that the poll is no longer active, and any associated data, such as vote counts and options, will no longer be available.

kickConnection.on(Events.PollDelete, () => {
    console.log(`Poll Deleted`);
});

User Banned

Triggered every time a user get Permanent ban or Timeout.


kickConnection.on(Events.UserBanned,  (data) => {
    if(permanent){
        console.log(`${data.user.username} was permanently banned by ${data.banned_by.username}`)
        //User2 was permanently banned by User1
    }else{
        console.log(`User ${data.user} was timed out by ${data.banned_by} for ${data.duration}`);
        //User2 was timed out by User1 for 1440(1 day)
    }
});

//Permanent Ban
{
  id: '00000000-0000-0000-0000-000000000000',
  user: { id: 00000000, username: 'User2', slug: 'user2' },
  banned_by: { id: 00000000, username: 'User1', slug: 'user1' },
  permanent: true
}

//Timeout
{
  id: '00000000-0000-0000-0000-000000000000',
  user: { id: 00000000, username: 'User2', slug: 'user2' },
  banned_by: { id: 00000000, username: 'User1', slug: 'user1' },
  permanent: false,
  duration: 1440,//1 day
  expires_at: '2024-10-27T16:48:34+00:00'
}

User UnBanned

Triggered every time a user get UnBanned or UnMuted.

kickConnection.on(Events.UserUnBanned,  (data) => {
     if(permanent){
        console.log(`${data.user.username} has unbanned by ${data.banned_by.username}`)
    }else{
        console.log(`User ${data.user} has been unmuted by ${data.banned_by} for ${data.duration}`);
    }
});
//Permanent Ban Removed
{
  id: '00000000-0000-0000-0000-000000000000',
  user: { id: 00000000, username: 'User2', slug: 'user2' },
  unbanned_by: { id: 00000000, username: 'User1', slug: 'user1' },
  permanent: true
}

//Timeout Removed
{
  id: '00000000-0000-0000-0000-000000000000',
  user: { id: 00000000, username: 'User2', slug: 'user2' },
  unbanned_by: { id: 00000000, username: 'User1', slug: 'user1' },
  permanent: false,
}

Subscription

Triggered every time someone subscribe to the channel.

kickConnection.on(Events.Subscription,  (data) => {
    console.log(`${data.username} has Subscribed for ${data.months} month`)
});
{
    chatroom_id: 0000;
    username: "user";
    months: 12;
};

Gifted Subscriptions

Triggered every time a user gift subscription to users. After this event, Gifts Leaderboard Updated will be triggered and Lucky Users Who Got Gift Subscriptions.

kickConnection.on(Events.GiftedSubscriptions,  (data) => {
    const giftedAmount = data.gifted_usernames.length
    console.log(`${data.gifter_username} gifted ${giftedAmount} subscriptions! 🎁`);
    console.log(`Total gifts by ${gifter_username}: ${gifter_total} subscriptions.`);
});
{
  chatroom_id: 0000,
  gifted_usernames: [ 'user1', 'user2', 'user3', 'user4', 'user5' ],
  gifter_username: 'user',
  gifter_total: 10
}

Lucky Users Who Got Gift Subscriptions

Triggered after the Gifted Subscriptions event, this event provides details about users who received gift subscriptions, including the gifter.

kickConnection.on(Events.LuckyUsersWhoGotGiftSubscriptions,(data)=>{
     console.log(`${data.gifter_username} gifted subscriptions to the following users:`);
    data.usernames.forEach(username => {
        console.log(`* ${username}`);
    });
})
{
  channel: {
    id: 0000,
    user_id: 0000,
    slug: 'hostName',
    is_banned: false,
    playback_url: 'https://',
    name_updated_at: null,
    vod_enabled: true,
    subscription_enabled: true,
    can_host: true
  },
  usernames: [ 'user1', 'user2', 'user3', 'user4', 'user5' ],
  gifter_username: 'user'
}

Gifts Leaderboard Updated

Triggered after a Gifted Subscriptions event, updating the leaderboard with the latest gift data.

kickConnection.on(Events.GiftsLeaderboardUpdated,(data)=>{
    console.log(`${data.gifter_username} gifted ${data.gifted_quantity} subscriptions! 🎁`)
})
{
  channel: {
    id: 0000,
    user_id: 0000,
    slug: 'user',
    is_banned: false,
    playback_url: 'https://',
    name_updated_at: null,
    vod_enabled: true,
    subscription_enabled: true,
    can_host: true,
    chatroom: {
      id: 0000,
      chatable_type: 'App\\Models\\Channel',
      channel_id: 0000,
      created_at: '2022-11-19T21:18:18.000000Z',
      updated_at: '2024-10-27T15:50:44.000000Z',
      chat_mode_old: 'public',
      chat_mode: 'followers_only',
      slow_mode: true,
      chatable_id: 0000,
      followers_mode: true,
      subscribers_mode: false,
      emotes_mode: false,
      message_interval: 2,
      following_min_duration: 10
    }
  },
  leaderboard: [
    { user_id: 00000000, username: 'user1', quantity: 3889 },
    { user_id: 00000000, username: 'user2', quantity: 3281 },
    { user_id: 00000000, username: 'user3', quantity: 661 },
    { user_id: 00000000, username: 'user4', quantity: 560 },
    { user_id: 00000000, username: 'user5', quantity: 450 },
    { user_id: 00000000, username: 'user6', quantity: 330 },
    { user_id: 00000000, username: 'user7', quantity: 309 },
    { user_id: 00000000, username: 'user8', quantity: 250 },
    { user_id: 00000000, username: 'user9', quantity: 230 },
    { user_id: 00000000, username: 'user10', quantity: 175 }
  ],
  weekly_leaderboard: [],
  monthly_leaderboard: [
    { user_id: 00000000, username: 'user11', quantity: 450 },
    { user_id: 00000000, username: 'user12', quantity: 299 },
    { user_id: 00000000, username: 'user13', quantity: 54 },
    { user_id: 00000000, username: 'user14', quantity: 45 },
    { user_id: 00000000, username: 'user15', quantity: 20 },
    { user_id: 00000000, username: 'user16', quantity: 15 },
    { user_id: 00000000, username: 'user17', quantity: 9 },
    { user_id: 00000000, username: 'user18', quantity: 8 },
    { user_id: 00000000, username: 'user19', quantity: 6 },
    { user_id: 00000000, username: 'user20', quantity: 6 }
  ],
  gifter_id: 0000,
  gifted_quantity: 5,
  gifter_username: 'user'
}

Stream Events

Stream End

Triggers when the host end the live. This event takes some time after the streamer is offline.

kickConnection.on(Events.StreamEnd,  (data) => {
    console.log(`${data.username} went offline`)
}); 

Streamer Is Live

Triggers when the host is back online.

kickConnection.on(Events.StreamerIsLive,  () => {
    console.log(`I am back`)
});
{
    livestream: {
      id: number;
      channel_id: number;
      session_title: string;
      source: null | any;
      created_at: string;
    };
}

Stream Host

Triggered when a streamer hosts another user.

kickConnection.on(Events.StreamHost,  (data) => {
    console.log(`Hosting Stream: ${data.host_username} with ${data.number_viewers} viewers.`);
}); 
{
  chatroom_id: 0000,
  optional_message: 'have fun',
  number_viewers: 77,
  host_username: 'user'
}

Chat Move To Supported Channel

This event's triggering conditions are currently unknown.

kickConnection.on(Events.ChatMoveToSupportedChannel, (data) => {
    console.log("Chat has moved to a supported channel:", data);
});
{
  channel: {
    id: 0000,
    user_id: 0000,
    slug: 'user1',
    is_banned: false,
    playback_url: 'https://',
    name_updated_at: null,
    vod_enabled: true,
    subscription_enabled: true,
    can_host: false,
    current_livestream: {
      id: 0000000,
      slug: '0000000-0000-0000-0000',
      channel_id: 0000,
      created_at: '2024-10-27 14:19:25',
      session_title: 'title',
      is_live: true,
      risk_level_id: null,
      start_time: '2024-10-27 14:19:21',
      source: null,
      twitch_channel: null,
      duration: 0,
      language: 'English',
      is_mature: true,
      viewer_count: 13617
    },
    user: {
      id: 0000,
      username: 'user1',
      agreed_to_terms: true,
      email_verified_at: '2022-11-19T21:18:59.000000Z',
      bio: 'you are the best',
      country: '',
      state: '',
      city: '',
      instagram: '',
      twitter: '',
      youtube: '',
      discord: '',
      tiktok: '',
      facebook: ''
    }
  },
  slug: 'user2',
  hosted: {
    id: 0000,
    username: 'user2',
    slug: 'user2',
    viewers_count: 13747,
    is_live: true,
    profile_pic: 'https://',
    category: 'just-chatting',
    preview_thumbnail: {
      srcset: 'https://',
      src: 'https://'
    }
  }
}

Viewer Count

Triggered every 1 minute, providing the current viewer count.This event may lead to rate limiting.

kickConnection.on(Events.ViewerCount,(data)=>{
    console.log(data.viewers)
})

Chatroom Clear

Triggers when the host clear the chat.

kickConnection.on(Events.ChatroomClear,()=>{
    console.log("The chatroom has been cleared by the host.")
})

Contributing

Your improvements are welcome! Feel free to open an issue or pull request.