Skip to content

Instantly share code, notes, and snippets.

@ellisgeek
Created March 8, 2019 03:59
Show Gist options
  • Save ellisgeek/2a2044c086a50a03728d17f04662b6d7 to your computer and use it in GitHub Desktop.
Save ellisgeek/2a2044c086a50a03728d17f04662b6d7 to your computer and use it in GitHub Desktop.
basic bot for people to guess koopa freerunning times.
import logging
import irc.bot
import requests
import toml
import re
from copy import deepcopy
from time import time, strftime, localtime
class TwitchBot(irc.bot.SingleServerIRCBot):
"""Base Class for Twitch IRC Bot"""
def __init__(self, username, oauth_token, client_id, channel):
self.token = oauth_token
self.channel = '#' + channel.lower()
self.minigames = {
"race": {
"type": "time",
'friendly_name': "Race",
"about": "guess the exact time it takes to win the race",
'guess_regex': re.compile("^(([01]):)?([0-5]?\d)\.([0-5]?\d)$"),
'guess_help': "Make guesses in the format [<minutes>:]<seconds>.<milliseconds> (minutes are optional)",
'guesses': {}
}
}
self.active_minigame = None
self.minigame_active = False
# Get the channel id, we will need this for v5 API calls
url = 'https://api.twitch.tv/kraken/users?login=' + channel
headers = {'Client-ID': client_id, 'Accept': 'application/vnd.twitchtv.v5+json'}
r = requests.get(url, headers=headers).json()
self.channel_id = r['users'][0]['_id']
logging.info(f"Channel ID is {self.channel_id}")
# Create IRC bot connection
server = 'irc.chat.twitch.tv'
port = 6667
logging.info(f"Connecting to {server}:{port} as {username}")
irc.bot.SingleServerIRCBot.__init__(
self,
[(server, port, 'oauth:' + oauth_token)],
username,
username
)
def on_welcome(self, c, e):
"""Join Channel when we connect to the server"""
c.cap('REQ', ':twitch.tv/membership')
c.cap('REQ', ':twitch.tv/tags')
logging.info(f"Joining Channel {self.channel}")
c.join(self.channel)
def on_pubmsg(self, c, e):
"""Parse chat messages for bot commands starting with !"""
tags = {}
for i in e.tags:
tags[i['key']] = i['value']
e.tags = tags
if e.arguments[0][:1] == '!':
cmd = e.arguments[0].split(' ')[0][1:]
logging.debug(f"Received Command: !{cmd}")
self.do_command(e, cmd)
return
def do_command(self, e, cmd):
"""Execute bot commands"""
c = self.connection
cmd_user = e.source.split('!')[0]
is_broadcaster = True if e.tags['badges'] and 'broadcaster' in e.tags['badges'] else False
is_mod = True if e.tags['mod'] == '1' else False
is_vip = True if e.tags['badges'] and 'vip' in e.tags['badges'] else False
if cmd == "minigame":
if is_mod or is_broadcaster:
logging.debug("Start a minigame")
args = (e.arguments[0].split(' ')[1:]) or None
if self.minigame_active:
c.privmsg(self.channel, "Minigame is already active!")
return
minigames_help = ""
leng = len(self.minigames)
iter = 1
for key, value in self.minigames.items():
if iter == leng:
sep = ''
else:
sep = ', '
minigames_help += f"{key} ({value['about']}){sep}"
iter += 1
if not args:
c.privmsg(self.channel, f"Available minigames are: {minigames_help}")
return
minigame = args[0]
if minigame not in self.minigames:
c.privmsg(
self.channel,
f"That is not a valid minigame, available minigames are: {minigames_help}"
)
return
self.minigame_active = True
self.active_minigame = deepcopy(self.minigames[minigame])
c.privmsg(
self.channel,
f"Starting minigame {self.active_minigame['friendly_name']}, the goal is {self.active_minigame['about']}"
)
if cmd == "guess":
args = (e.arguments[0].split(' ')[1:]) or None
if not self.minigame_active:
c.privmsg(self.channel, f"Sorry @{cmd_user}, no minigame is running.")
return
if not args or not self.active_minigame['guess_regex'].match(args[0]):
c.privmsg(
self.channel,
f"{self.active_minigame['guess_help']} @{cmd_user}"
)
return
if cmd_user in self.active_minigame['guesses']:
c.privmsg(self.channel, f"You have already guessed for this minigame @{cmd_user}")
return
self.active_minigame['guesses'][cmd_user] = args[0]
if cmd == 'guesses':
if is_mod or is_broadcaster:
if not self.minigame_active:
c.privmsg(self.channel, "No minigame active!")
return
guesses = "Current Guesses: "
leng = len(self.minigames)
iter = 1
for user, guess in self.active_minigame['guesses'].items():
if iter == leng:
sep = ''
else:
sep = ', '
guesses += f"{user} = {guess}{sep}"
iter += 1
c.privmsg(self.channel, guesses)
if cmd == "endgame":
if is_mod or is_broadcaster:
args = (e.arguments[0].split(' ')[1:]) or None
if not self.minigame_active:
c.privmsg(self.channel, "No minigame active!")
return
if not args or not self.active_minigame['guess_regex'].match(args[0]):
c.privmsg(
self.channel,
f"winning time needs to be in same format as guess @{cmd_user}"
)
return
winning_time = args[0]
c.privmsg(self.channel, f"{self.active_minigame['friendly_name']} is ending, {self.channel.strip('#')}'s time was {winning_time}")
for user, guess in self.active_minigame['guesses'].items():
if guess == winning_time:
c.privmsg(self.channel, f"Congratulations @{user}, you guessed @{self.channel.strip('#')}'s time down to the millisecond PogChamp")
break
c.privmsg(self.channel, f"No one guessed {self.channel.strip('#')}'s time, better luck next time!")
self.active_minigame = None
self.minigame_active = False
if cmd == "ping":
if is_mod or is_broadcaster:
logging.debug("Pong")
c.privmsg(self.channel, "!pong")
else:
return
def main():
"""Main Entry point"""
logging.basicConfig(level=logging.DEBUG)
username = "SyneArdwin"
oauth_token = "40x03hdf0e7fuzexb1rj7rpwmt5jqk"
client_id = "905i1wl26azhpevr9bxfwxh45qalxt"
channel = "syneardwin"
bot = TwitchBot(username, oauth_token, client_id, channel)
bot.start()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment