thearstbot-twitch/bot.py

174 lines
6 KiB
Python
Raw Normal View History

2022-09-12 19:02:45 -04:00
# Basic twitch bot
import os
2022-11-27 23:06:02 -05:00
import random
2022-09-13 23:00:59 -04:00
import sqlite3
2022-09-12 19:02:45 -04:00
from twitchio.ext import commands
from twitchio.ext import pubsub
2022-09-12 19:02:45 -04:00
from dotenv import load_dotenv
2023-02-15 22:32:09 -05:00
import requests
2022-09-12 19:02:45 -04:00
2022-09-12 22:17:49 -04:00
PREFIX = "!"
2022-09-13 23:00:59 -04:00
DB_PATH = "storage.db"
2022-09-12 22:17:49 -04:00
2022-09-12 19:02:45 -04:00
class Bot(commands.Bot):
def __init__(self):
2022-09-12 22:17:49 -04:00
super().__init__(token = os.environ["TMI_TOKEN"], prefix=PREFIX, initial_channels=[os.environ["CHANNEL"]])
2022-09-13 23:00:59 -04:00
self.db_con = sqlite3.connect(DB_PATH)
self.db_cur = self.db_con.cursor()
self.db_cur.execute("CREATE TABLE IF NOT EXISTS custom_commands(command TEXT, output_text TEXT, author TEXT)")
self.db_cur.execute("CREATE TABLE IF NOT EXISTS channel_reward_messages(title TEXT, output_text TEXT)")
print("Created database table")
commands = self.db_cur.execute("SELECT count(*) FROM custom_commands").fetchone()
print(f"{commands[0]} custom commands available")
2022-09-12 19:02:45 -04:00
# Adds a custom command from a string
async def add_custom_command(self, ctx, command_str, author):
args = command_str.split(" ", 1)
if len(args) < 2:
await ctx.send("lmao plz supply 2 args")
return
command_name = args[0]
command_text = args[1]
if not command_name.isalnum():
await ctx.send("lmao that command name is too funky")
return
if self.db_cur.execute("SELECT * FROM custom_commands WHERE command=?", [command_name]).fetchone() is not None \
or self.get_command(command_name) is not None:
await ctx.send("lmao that command already exists")
return
self.db_cur.execute("INSERT INTO custom_commands VALUES (?, ?, ?)", [command_name, command_text, author])
self.db_con.commit()
await ctx.send(f"Adding command: \"{PREFIX}{command_name}\" -> \"{command_text}\"")
2022-09-12 19:02:45 -04:00
async def event_ready(self):
print(f"Logged in as | {self.nick}")
print(f"User id is | {self.user_id}")
# This entire pubsub thing feels so janky... There simply must be a better way to do it
if "PUBSUB_TOKEN" in os.environ and "PUBSUB_USER_ID" in os.environ:
self.pubsub = pubsub.PubSubPool(self)
topics = [
pubsub.channel_points(os.environ["PUBSUB_TOKEN"])[int(os.environ["PUBSUB_USER_ID"])]
]
await self.pubsub.subscribe_topics(topics)
# Can I put this function somewhere else LMAO
@self.event()
async def event_pubsub_channel_points(event: pubsub.PubSubChannelPointsMessage):
reward_title = event.reward.title
result = self.db_cur.execute("SELECT output_text FROM channel_reward_messages WHERE title=?", [reward_title]).fetchone()
if result is not None:
message = result[0]
message = message.replace("%USER%", event.user.name)
if event.input:
message = message.replace("%INPUT%", event.input)
await self.get_channel(os.environ["CHANNEL"]).send(message)
2022-09-12 22:13:41 -04:00
async def event_message(self, message):
if message.echo:
return
# I really want to do this with the add_command function and have no need for this event_message override, but
# I cannot for the life of me figure out how to make "anonymous" coroutines (like, async lambda or something),
# so I'm just manually handling the command here before passing to the command handler
if message.content.startswith(PREFIX):
first_token = message.content[len(PREFIX):].strip().split()[0]
res = self.db_cur.execute("SELECT output_text FROM custom_commands WHERE command=?", [first_token]).fetchone()
if res is not None:
await message.channel.send(res[0])
2022-09-12 22:13:41 -04:00
return
await self.handle_commands(message)
2022-09-12 19:02:45 -04:00
@commands.command()
async def hello(self, ctx: commands.Context):
# Basic hello world command, executed with "!hello". Reply hello to whoever made the command
2022-09-12 19:44:30 -04:00
response = f"Hello {ctx.author.name}! "
if ctx.author.is_broadcaster:
response += "👑"
else:
if ctx.author.is_mod:
response += ""
# Uncomment these once twitchio gets a new release
#elif ctx.author.is_vip:
# response += "💎"
2022-09-12 19:44:30 -04:00
if ctx.author.is_subscriber:
response += "🤑"
await ctx.send(response.strip())
2022-09-12 19:02:45 -04:00
2022-09-12 22:13:41 -04:00
@commands.command()
async def addcmd(self, ctx: commands.Context):
2022-09-12 22:13:41 -04:00
# Lets moderators add custom text responses
if not ctx.author.is_mod:
await ctx.send("lmao nice try ur not a mod")
return
# Not sure if ctx.args is supposed to work but it seems like it doesn't...
# I want the last arg to not get split anyway, so I do it myself
args = ctx.message.content.split(" ", 1)
if len(args) < 2:
await ctx.send("lmao plz supply 2 args")
2022-09-12 22:13:41 -04:00
return
await self.add_custom_command(ctx, args[1], ctx.author.name)
2022-09-12 22:13:41 -04:00
2022-09-12 22:25:54 -04:00
@commands.command()
async def removecmd(self, ctx: commands.Context):
2022-09-12 22:25:54 -04:00
if not ctx.author.is_mod:
await ctx.send("lmao nice try ur not a mod")
return
args = ctx.message.content.split(" ", 1)
if len(args) < 2:
await ctx.send("lmao wut command")
return
command_name = args[1]
if self.get_command(command_name) is not None:
await ctx.send("lmao u cant delet this")
return
if self.db_cur.execute("SELECT * FROM custom_commands WHERE command=?", [command_name]).fetchone() is None:
2022-09-12 22:25:54 -04:00
await ctx.send("lmao wut is that command")
return
2022-09-13 23:00:59 -04:00
self.db_cur.execute("DELETE FROM custom_commands WHERE command=?", [command_name])
self.db_con.commit()
2022-09-12 22:25:54 -04:00
await ctx.send(f"Deleted command \"{PREFIX}{command_name}\"")
2022-09-12 23:25:48 -04:00
@commands.command()
async def help(self, ctx: commands.Context):
message = "Available commands:"
for command in self.commands:
if command not in ["addcmd", "removecmd"] or ctx.author.is_mod:
message += f" {PREFIX}{command}"
for command in self.db_cur.execute("SELECT command FROM custom_commands").fetchall():
message += f" {PREFIX}{command[0]}"
2022-09-12 23:25:48 -04:00
await ctx.send(message)
2022-11-27 23:06:02 -05:00
@commands.command()
async def balls(self, ctx: commands.Context):
word_list = "cubes are just balls with corners lmao".split(" ")
random.shuffle(word_list)
await ctx.send(" ".join(word_list))
2023-02-15 22:32:09 -05:00
@commands.command()
async def donation(self, ctx: commands.Context):
r = requests.get("https://taskinoz.com/gdq/api/")
await ctx.send(r.text)
2022-09-12 19:02:45 -04:00
def main():
load_dotenv()
bot = Bot()
bot.run()
# bot.run() is blocking and will stop execution of any below code here until stopped or closed.
if __name__ == "__main__":
main()