diff --git a/CHANGELOG.md b/CHANGELOG.md index 28cfdcb..e8f9c76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# kickbot-sdk +# kick-js ## 0.1.1 diff --git a/README.md b/README.md index f114a0e..b82d986 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -**kickbot-sdk** +**kick-js** A demo package for Total TypeScript. diff --git a/examples/basic-bot.ts b/examples/basic-bot.ts index d2e7550..6a69658 100644 --- a/examples/basic-bot.ts +++ b/examples/basic-bot.ts @@ -1,14 +1,42 @@ import { createClient } from "../src"; import type { MessageData } from "../src/types/events"; +import "dotenv/config"; const client = createClient("xqc", { logger: true }); client.on("ready", () => { - console.log(`Logged into ${client.user?.tag}!`); + console.log(`Bot ready & logged into ${client.user?.tag}!`); }); +client.login({ process.env.TOKEN, process.env.COOKIES }); + client.on("ChatMessage", async (message: MessageData) => { console.log(`${message.sender.username}: ${message.content}`); + + if (message.content.match("!ping")) { + client.sendMessage("pong"); + } + + if (message.content.match("!slowmode on")) { + const splitMessage = message.content.split(" "); + const duration = splitMessage[1]; + if (duration) { + const durationNumber = parseInt(duration); + client.slowMode("on", durationNumber); + } + } + if (message.content.match("!slowmode off")) { + client.slowMode("off"); + } + + if (message.content.match("!ban")) { + const splitMessage = message.content.split(" "); + const bannedUser = splitMessage[1]; + if (bannedUser) { + client.permanentBan(bannedUser); + } + } + }); client.on("Subscription", async (subscription) => { diff --git a/package.json b/package.json index dc0ce3c..8312281 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,19 @@ { - "name": "kickbot-sdk", + "name": "kick-js", "version": "0.1.1", - "description": "A typescript bot sdk for kick.com", + "description": "A typescript bot interface for kick.com", "keywords": [ "demo", "typescript" ], - "homepage": "https://github.com/retconned/kickbot-sdk", + "homepage": "https://github.com/retconned/kick-js", "bugs": { - "url": "https://github.com/retconned/kickbot-sdk/issues" + "url": "https://github.com/retconned/kick-js/issues" }, "author": "retconned ", "repository": { "type": "git", - "url": "git+https://github.com/retconned/kickbot-sdk.git" + "url": "git+https://github.com/retconned/kick-js.git" }, "files": [ "dist" diff --git a/src/client/client.ts b/src/client/client.ts index a56c7cd..f3ca208 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -5,9 +5,9 @@ import { createWebSocket } from "../core/websocket"; import { parseMessage } from "../utils/messageHandling"; import type { KickChannelInfo } from "../types/channels"; import type { KickClient, ClientOptions } from "../types/client"; +import type { MessageData } from "../types/events"; import axios from "axios"; -import type { MessageData } from "../types/events"; export const createClient = ( channelName: string, @@ -87,7 +87,7 @@ export const createClient = ( emitter.on(event, listener); }; - // TODO: Implement authentication, this is just a placeholder + // TODO: Implement proper authentication, this is just a temp token & cookies passer const login = async (credentials: { token: string; cookies: string }) => { token = credentials.token; cookies = credentials.cookies; @@ -129,6 +129,102 @@ export const createClient = ( } }; + const permanentBan = async (bannedUser: string) => { + if (!token || !cookies || !channelInfo) { + throw new Error("Not logged in or channel info not available"); + } + + if (!bannedUser) { + throw new Error("Specify a user to ban"); + } + + try { + const response = await axios.post( + `https://kick.com/api/v2/channels/${channelInfo.id}/bans`, + { banned_username: bannedUser, permanent: true }, + { + headers: { + accept: "application/json, text/plain, */*", + authorization: `Bearer ${token}`, + "content-type": "application/json", + "x-xsrf-token": token, + cookie: cookies, + Referer: `https://kick.com/${channelInfo.slug}`, + }, + }, + ); + + if (response.status === 200) { + console.log(`Banned user ${bannedUser} sent successfully`); + } else { + console.error(`Failed to Ban user. Status: ${response.status}`); + } + } catch (error) { + console.error("Error sending message:", error); + } + }; + const slowMode = async (mode: "on" | "off", durationInSeconds?: number) => { + if (!token || !cookies || !channelInfo) { + throw new Error("Not logged in or channel info not available"); + } + if (mode !== "on" && mode !== "off") { + throw new Error("Invalid mode, must be 'on' or 'off'"); + } + if (mode === "on" && durationInSeconds && durationInSeconds < 1) { + throw new Error( + "Invalid duration, must be greater than 0 if mode is 'on'", + ); + } + + try { + if (mode === "off") { + const response = await await axios.put( + `https://kick.com/api/v2/channels/${channelInfo.slug}/chatroom`, + { slow_mode: false }, + { + headers: { + accept: "application/json, text/plain, */*", + authorization: `Bearer ${token}`, + "content-type": "application/json", + "x-xsrf-token": token, + cookie: cookies, + Referer: `https://kick.com/${channelInfo.slug}`, + }, + }, + ); + + if (response.status === 200) { + console.log(`Turned slow mode off successfully`); + } else { + console.error(`Failed to Ban user. Status: ${response.status}`); + } + } else { + const response = await await axios.put( + `https://kick.com/api/v2/channels/${channelInfo.slug}/chatroom`, + { slow_mode: true, message_interval: durationInSeconds }, + { + headers: { + accept: "application/json, text/plain, */*", + authorization: `Bearer ${token}`, + "content-type": "application/json", + "x-xsrf-token": token, + cookie: cookies, + Referer: `https://kick.com/${channelInfo.slug}`, + }, + }, + ); + + if (response.status === 200) { + console.log(`Turned slow mode on for ${durationInSeconds} seconds`); + } else { + console.error(`Failed to Ban user. Status: ${response.status}`); + } + } + } catch (error) { + console.error("Error sending message:", error); + } + }; + void initialize(); return { @@ -136,7 +232,9 @@ export const createClient = ( get user() { return getUser(); }, - sendMessage, login, + sendMessage, + permanentBan, + slowMode, }; }; diff --git a/src/types/actions.ts b/src/types/actions.ts deleted file mode 100644 index f6dbb3d..0000000 --- a/src/types/actions.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type ReplyProps = { - channelUsername: string; - replyContent: string; - originalMessageId: string; - originalMessageContent: string; - originalSenderId: number; - originalSenderUsername: string; -}; diff --git a/src/types/client.ts b/src/types/client.ts index eb462fa..af88db9 100644 --- a/src/types/client.ts +++ b/src/types/client.ts @@ -8,11 +8,13 @@ export interface ClientOptions { export interface KickClient { on: (event: string, listener: (...args: any[]) => void) => void; + login: (credentials: { token: string; cookies: string }) => Promise; user: { id: number; username: string; tag: string; } | null; sendMessage: (messageContent: string) => Promise; - login: (credentials: { token: string; cookies: string }) => Promise; + permanentBan: (bannedUser: string) => Promise; + slowMode: (mode: "on" | "off", durationInSeconds?: number) => Promise; } diff --git a/src/types/events.ts b/src/types/events.ts index 4931711..02addce 100644 --- a/src/types/events.ts +++ b/src/types/events.ts @@ -44,8 +44,8 @@ export interface ChatMessage { }; } +// these are not implemented yet export interface Subscription { - // Define subscription event properties id: string; user_id: number; username: string;