Skip to content

Instantly share code, notes, and snippets.

@PCDSandwichMan
Last active March 23, 2024 08:16
Show Gist options
  • Save PCDSandwichMan/24576752644d12a81cc07b29a0bc7d39 to your computer and use it in GitHub Desktop.
Save PCDSandwichMan/24576752644d12a81cc07b29a0bc7d39 to your computer and use it in GitHub Desktop.
/*
Description:
This is a simple Twitch bot script that allows users to enter a giveaway,
pick a winner, and view the list of entered users.
Usage:
1. Locally install tmi.js and ts-node via npm (or similar package manager)
2. Replace <ADD_USERNAME_HERE> with your Twitch username that will act as the bot
3. Replace <ADD_TOKEN_HERE> with your oauth token (https://twitchapps.com/tmi/)
4. Run the script with ts-node - ts-node giveaway-bot.ts
Faq:
Q: How do I get my oauth token?
A: The easiest way to get your oauth token is to go to https://twitchapps.com/tmi/
*/
import tmi, { ChatUserstate } from "tmi.js";
/**
* ----------------------------------
* INITIALIZE THE TWITCH CONNECTION
* ----------------------------------
**/
const clientConfig = {
identity: {
username: "<ADD_USERNAME_HERE>", // Your Twitch username
password: "<ADD_TOKEN_HERE>", // The easiest way to get your oauth token is to go to https://twitchapps.com/tmi/
},
channels: ["thevioletneko"],
};
const client = new tmi.client(clientConfig);
// @ts-ignore
client.on("connected", onConnectedHandler);
client.connect();
/**
* ----------------------
* INITIALIZE THE BOT
* ----------------------
**/
client.on("chat", async (_channel, userState, message, self) => {
if (self) return;
console.log(`${userState.username}: ${message}`);
const args = message.trim().split(/\s+/);
const command = args.shift()?.toLowerCase();
switch (command) {
case "!misc":
await handleMiscCommand(_channel, args, userState);
break;
case "!help":
await handleHelpCommand(_channel);
break;
case "!enter":
await handleEnterCommand(_channel, userState);
break;
case "!pick":
await handlePickCommand(_channel, userState);
break;
case "!user-pool":
await handleUserPoolCommand(_channel);
break;
case "!clear":
await handleClearCommand(_channel, userState);
break;
}
});
/**
* -------------------
* HELPER FUNCTIONS
* -------------------
**/
const enteredUsers = new Set<string>();
/**
* Handles when the client connects to Twitch.
*
* @param {string} addr - The server address.
* @param {number} port - The server port.
*/
function onConnectedHandler(addr: string, port: string) {
console.log(`* Connected to ${addr}:${port}`);
}
/**
* Handles miscellaneous commands based on the given subCommand.
*
* @param {string} channel - The channel where the command is executed.
* @param {string} subCommand - The subcommand to handle.
* @param {ChatUserstate} userState - The user state object.
* @returns {Promise<void>} - A promise that resolves when the command handling is complete.
*/
async function handleMiscCommand(
channel: string,
args: string[],
userState: ChatUserstate
) {
const subCommand = args.shift()?.toLowerCase();
switch (subCommand) {
case "ping":
await client.say(channel, `Hello ${userState.username} 🥪`);
break;
}
}
/**
* Handles the help command by sending a message with the available commands to the specified channel.
*
* @param {string} channel - The channel where the command is executed.
* @returns {Promise<void>} - A promise that resolves when the help message is sent.
*/
async function handleHelpCommand(channel: string) {
await client.say(
channel,
`Available commands: !misc, !enter, !pick, !user-pool, !clear`
);
}
/**
* Handles the enter command for the giveaway.
*
* @param {string} channel - The channel where the command is executed.
* @param {ChatUserstate} userState - The user state object containing information about the user.
* @returns {Promise<void>} - A promise that resolves when the command is handled.
*/
async function handleEnterCommand(channel: string, userState: ChatUserstate) {
enteredUsers.add(userState.username!);
await client.say(channel, `${userState.username} has entered the giveaway!`);
}
/**
* Handles the pick command to select a winner for the giveaway.
* Only the broadcaster or moderators can pick a winner.
*
* @param {string} channel - The channel where the command is executed.
* @param {ChatUserstate} userState - The user state of the command executor.
* @returns {Promise<void>} - A promise that resolves when the winner is announced.
*/
async function handlePickCommand(channel: string, userState: ChatUserstate) {
if (
userState.mod ||
userState["user-type"] === "mod" ||
userState.username === channel.replace("#", "")
) {
if (enteredUsers.size > 0) {
const randomUser =
Array.from(enteredUsers)[Math.floor(Math.random() * enteredUsers.size)];
await client.say(
channel,
`🎉 Congratulations ${randomUser}, you won the giveaway!`
);
} else {
await client.say(channel, "No users have entered the giveaway yet.");
}
} else {
await client.say(
channel,
"Sorry, only the broadcaster or moderators can pick a winner."
);
}
}
/**
* Handles the user pool command by sending a message to the specified channel
* with the list of entered users or a message indicating that no users have entered yet.
*
* @param {string} channel - The channel to send the message to.
* @returns {Promise<void>} - A promise that resolves when the message is sent.
*/
async function handleUserPoolCommand(channel: string) {
if (enteredUsers.size > 0) {
const userList = Array.from(enteredUsers).join(", ");
await client.say(channel, `Entered users: ${userList}`);
} else {
await client.say(channel, "No users have entered the giveaway yet.");
}
}
/**
* Clears the entered users list and sends a message in the channel.
* Only the broadcaster or moderators can clear the entered users.
*
* @param {string} channel - The channel name.
* @param {ChatUserstate} userState - The user state object.
* @returns {Promise<void>} - A promise that resolves when the entered users list is cleared.
*/
async function handleClearCommand(channel: string, userState: ChatUserstate) {
if (
userState.mod ||
userState["user-type"] === "mod" ||
userState.username === channel.replace("#", "")
) {
enteredUsers.clear();
await client.say(channel, "The entered users list has been cleared.");
} else {
await client.say(
channel,
"Sorry, only the broadcaster or moderators can clear the entered users."
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment