Skip to content
This repository has been archived by the owner on Nov 3, 2024. It is now read-only.

Commit

Permalink
Update 1.0
Browse files Browse the repository at this point in the history
Commit bot files
  • Loading branch information
BOT-K4CP3R committed May 25, 2024
1 parent 7ba90de commit ee51174
Show file tree
Hide file tree
Showing 12 changed files with 4,655 additions and 0 deletions.
4,154 changes: 4,154 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

52 changes: 52 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "kick-chatbot",
"version": "1.0.0",
"description": "Example of chat bot on kick.com",
"main": "dist/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node dist/index.js",
"start:dev": "nodemon src/index.ts",
"prd": "node dist/index.js",
"build": "tsc -p . --noEmit false"
},
"repository": {
"type": "git",
"url": "git+https://github.com/BOT-K4CP3R/kick-chatbot.git"
},
"keywords": [
"kick.com",
"chatbot"
],
"author": "botk4cp3r",
"license": "MIT",
"bugs": {
"url": "https://github.com/BOT-K4CP3R/kick-chatbot/issues"
},
"homepage": "https://github.com/BOT-K4CP3R/kick-chatbot#readme",
"dependencies": {
"axios": "^1.4.0",
"cheerio": "1.0.0-rc.12",
"puppeteer": "^21.5.0",
"puppeteer-extra": "^3.3.6",
"puppeteer-extra-plugin-stealth": "^2.11.2",
"uuid": "^9.0.0",
"ws": "^8.12.1"
},
"devDependencies": {
"@ianvs/prettier-plugin-sort-imports": "^4.0.2",
"@types/eslint": "^8.40.2",
"@types/node": "^18.14.6",
"@types/prettier": "^2.7.3",
"@types/uuid": "^9.0.1",
"@types/ws": "^8.5.4",
"@typescript-eslint/eslint-plugin": "^5.59.6",
"@typescript-eslint/parser": "^5.59.6",
"dotenv": "^16.0.3",
"eslint": "^8.43.0",
"nodemon": "^3.0.1",
"prettier": "^2.8.8",
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
}
}
5 changes: 5 additions & 0 deletions src/commands/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { sendMessage } from "../handlers/sendMessage";

export const execute = (username: string, channelId: number) => {
sendMessage(channelId, `@${username}, this is test command!`);
};
11 changes: 11 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
interface Config {
token: string;
cookies: string;
}

const config: Config = {
token : '',
cookies: ''
};

export default config;
87 changes: 87 additions & 0 deletions src/handlers/onMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import WebSocket from "ws";
import fs from "fs";
import path from "path";

import { MessageData, MessageEvent } from "@/types/events";

import { runtimeChannelData } from "../utils/index";

let responseEvents: { [channelId: string]: number } = {};

const messageParser = (message: string) => {
const messageEventJSON: MessageEvent = JSON.parse(message);
if (messageEventJSON.event === "App\\Events\\ChatMessageEvent") {
const data: MessageData = JSON.parse(messageEventJSON.data);
const message = data.content;
const channelId = data.chatroom_id;
const username = data.sender.username;
const emoteRegex = /\[emote:\d+:[^\]]+\]/g;
const channelName = runtimeChannelData.get(channelId);

try {
if (message.match(emoteRegex)) {
const processedMsg = message.replace(emoteRegex, (match: any) => {
const parts = match.substring(7, match.length - 1).split(":");
return parts[1];
});
console.log(`${channelName} | ${username}: ${processedMsg}`);
} else {
console.log(`${channelName} | ${username}: ${message}`);
}
} catch (error) {
console.log("Message filter error:", error);
}
}
};

const handleCommand = (command: string, user: string, channelId: number) => {
const commandFilePath = path.resolve(__dirname, `../commands/${command}.ts`);
if (fs.existsSync(commandFilePath)) {
const commandHandler = require(commandFilePath);
commandHandler.execute(user, channelId);
} else {
console.log(`Command '${command}' not found.`);
}
};

export const onMessage = (messageEvent: WebSocket.Data, socket: any) => {
const message = messageEvent.toString();
messageParser(message);

const messageEventJSON: MessageEvent = JSON.parse(message);
const data: MessageData = JSON.parse(messageEventJSON.data);
const channelId = data.chatroom_id;
const user = data.sender;
const username = user ? user.username : "Brak nazwy użytkownika";

try {
const messageData = JSON.parse(message);

if (messageData && typeof messageData.data === 'string') {
const eventData = JSON.parse(messageData.data);

if (eventData && eventData.content && typeof eventData.content === 'string') {
const messageContent = eventData.content;

if (messageContent.startsWith("!")) {
const [command, ...args] = messageContent.slice(1).split(" ");

handleCommand(command, username, channelId);
}
}
}
} catch (error) {
console.log("Error parsing message data:", error);
}

eventCalculation(message);
};


function eventCalculation(message: string) {
const messageEventJSON: MessageEvent = JSON.parse(message);
if (messageEventJSON.event === "App\\Events\\ChatMessageEvent") {
const channelId = messageEventJSON.channel;
responseEvents[channelId] = (responseEvents[channelId] || 0) + 1;
}
}
20 changes: 20 additions & 0 deletions src/handlers/sendMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import axios from 'axios';
import config from '../config';

export const sendMessage = async (channelId: number, messageContent: string) => {
axios.post(`https://kick.com/api/v2/messages/send/${channelId}`,
{
content: messageContent,
type: "message"
},
{
headers: {
"accept": "application/json, text/plain, */*",
"authorization": `Bearer ${config.token}`,
"content-type": "application/json",
"x-xsrf-token": config.token,
"cookie": config.cookies,
"Referer": "https://kick.com/botk4cp3r"
}
});
};
96 changes: 96 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { URLSearchParams } from "url";
import { v4 as uuidv4 } from "uuid";
import WebSocket from "ws";
import config from './config'

import { onMessage } from "./handlers/onMessage";
import { getChatroomId, runtimeChannelData } from "./utils";

const baseUrl = "wss://ws-us2.pusher.com/app/eb1d5f283081a78b932c";
const urlParams = new URLSearchParams({
protocol: "7",
client: "js",
version: "7.4.0",
flash: "false",
});
const url = `${baseUrl}?${urlParams.toString()}`;

const maxChannelsPerSocket = 10;
let activeSockets: WebSocket[] = [];

const connectToChannels = async (socket: WebSocket, channels: any[]) => {
channels.forEach(async (channel) => {
const connect = JSON.stringify({
event: "pusher:subscribe",
data: { auth: config.token, channel: `chatrooms.${channel}.v2` },
});
await socket.send(connect);
const channelName = runtimeChannelData.get(channel);
console.log(`connected to #${channelName}`);
});
};

const createNewSocket = async (channels: number[]) => {
const socket = new WebSocket(url);
const id = uuidv4();
socket.on("open", () => {
console.log(`Connected to socket server ${id}`);
activeSockets.push(socket);
connectToChannels(socket, channels);
});
socket.on("message", (data: WebSocket.Data) => {
const messageEvent = data.toString();
onMessage(messageEvent, socket);
});
socket.on("close", () => {
console.log("Disconnected from server");
activeSockets = activeSockets.filter((s) => s !== socket);
});
};

const countConnectedChannels = (socket: WebSocket): number => {
let count = 0;
socket.listeners("message").forEach((listener) => {
const connectEvent = JSON.parse(listener.toString());
if (connectEvent && connectEvent.event === "pusher:subscribe") {
count++;
}
});
return count;
};

const connectToDynamicChannels = async (channels: number[]) => {
console.log(`Connecting to ${channels.length} channels...`);
activeSockets.forEach((socket) => {
const connectedChannelCount = countConnectedChannels(socket);
console.log(
`Socket ${socket.url} is connected to ${connectedChannelCount} channels`
);
});
let connectedChannelCount = 0;
activeSockets.forEach((socket) => {
if (connectedChannelCount < maxChannelsPerSocket) {
const channelsToConnect = channels.slice(
connectedChannelCount,
maxChannelsPerSocket - connectedChannelCount
);
connectToChannels(socket, channelsToConnect);
connectedChannelCount += channelsToConnect.length;
}
});
while (connectedChannelCount < channels.length) {
const channelsToConnect = channels.slice(
connectedChannelCount,
connectedChannelCount + maxChannelsPerSocket
);
await createNewSocket(channelsToConnect);
connectedChannelCount += channelsToConnect.length;
}
};

const client = async (channels: string[]) => {
const chatroomIds = await getChatroomId(channels);
connectToDynamicChannels(chatroomIds);
};

client(["botk4cp3r"]);
Loading

0 comments on commit ee51174

Please sign in to comment.