def Execute(self, msg): tokens = msg.message.lower().split() if tokens[0] in self.customCommandList: util.LogReceived(msg.type, msg.user, msg.message, msg.tags, True) response = self.customCommandList[tokens[0]] if isinstance(response, dict): if msg.user in response: response = response[msg.user] else: response = response["other"] if isinstance(response, list): return random.choice(response) return response elif len(tokens) > 1 and (tokens[0] + " [ARG]") in self.customCommandList: util.LogReceived(msg.type, msg.user, msg.message, msg.tags, True) response = self.customCommandList[(tokens[0] + " [ARG]")].replace("[ARG]", tokens[1]) return response return None
def VoteBanAsync(self, user): util.SendMessage(random.choice(self.beginResponses).format(user)) time.sleep(1.800) util.SendMessage(f"{user} will be banned in 3...") time.sleep(0.680) util.SendMessage("2...") time.sleep(0.880) util.SendMessage("1...") time.sleep(1.080) util.SendMessage(f"/me {user} is cute and important and cannot be banned from this chat GivePLZ <3") self.threadRunning = False return
def EndPoll(self): with self.pollLock: if not self.pollRunning: return self.pollRunning = False if len(self.voters) == 0: response = "No one voted for the poll. :(" else: winner = max(self.voteCollection, key=self.voteCollection.get) percent = round(self.voteCollection[winner] / len(self.voters) * 100) response = f"Poll ended with {len(self.voters)} votes. " if self.voteCollection.keys() == {"y", "n"}: response += "VoteYea " if winner == "y" else "VoteNay " else: response += f"Option {winner.upper()} " response += f"wins with {percent}% of the vote" self.voteCollection = {} self.voters = [] self.pollTimeout = 0 util.SendMessage(response) return
def __init__(self): self.chan = botconfig.twitchChannel self.prefixes = botconfig.prefixes self.client = pymongo.MongoClient(f"{botconfig.DbConnectionString}", socketTimeoutMS=5000) # Send along all required information, and the bot will start # sending messages to your callback function. (self.message_handler in this case) self.ws = TwitchWebsocket( host="irc.chat.twitch.tv", port=6667, chan="#" + self.chan, nick=botconfig.twitchUser, auth=botconfig.oauth, callback=self.message_handler, capability=["membership", "tags", "commands"], live=True) util.InitializeUtils(self.ws, self.chan, self.client) # List of command names and args required for their constructor args = (self.chan, self.client) commandNames = { "WhoCommands": args, "ScoreCommands": args, "QuoteCommands": args, "CustomCommands": args, "PollCommands": (), "DiceCommands": (), "TimeCommands": (), "VoteBanCommands": (), "ShoutoutCommands": (), "FindGameCommands": (), "FindSongCommands": (), "FindFoodCommands": (), } for name in botconfig.exclude: del commandNames[name] self.commands = {} # Dynamically load commands with appropriate args for name, arg in commandNames.items(): self.commands[name] = getattr(globals()[name], name)(*arg) # Maps all active command strings caught by imported command modules to their respective Execute function self.execute = {} # Maps all active channel points custom reward ids caught by imported command modules to their respective RedeemReward function self.redeem = {} for cmd in self.commands.values(): if hasattr(cmd, "activeCommands"): self.execute = {**self.execute, **cmd.activeCommands} if hasattr(cmd, "activeRewards"): self.redeem = {**self.redeem, **cmd.activeRewards} self.ws.start_bot()
def ExecuteVote(self, msg): if not self.pollRunning: return f"[{msg.user}]: Nothing to vote for" if msg.user in self.voters: return f"[{msg.user}]: You already voted in this poll" if (regMatch := self.voteRegex.match(msg.message)) is None: return util.GetSyntax(msg.user, "vote LETTER")
def ExecutePollEnd(self, msg): if not util.CheckPrivMod(msg.tags): return f"[{msg.user}]: Only mods can end a poll" if not self.pollRunning: return f"[{msg.user}]: No poll active" self.EndPoll() return
def CheckModifyQuote(self, action, result, msg): if not util.CheckPrivMod(msg.tags): if result["user"] != msg.user: return f"[{msg.user}]: Only mods can {action} a quote someone else added" if result["date"].strftime( "%x") != datetime.datetime.now().strftime("%x"): return f"[{msg.user}]: Only mods can {action} a quote on a different day than it was added" return None
def PollAsync(self): while self.pollTimeout >= 30: time.sleep(30) self.pollTimeout -= 30 if (not self.pollRunning or self.pollTimeout < 30): break if self.pollTimeout % 60 == 0: minutes = int(self.pollTimeout / 60) minMsg = "minute" if minutes == 1 else "minutes" util.SendMessage( f"Don't forget to vote. Only {minutes} {minMsg} remaining") elif self.pollTimeout == 30: util.SendMessage(f"Last chance to vote! Only 30 seconds left") self.EndPoll() return
def message_handler(self, m): # Check for proper message type if (m.type != "PRIVMSG" and m.type != "WHISPER"): return # Check for valid message with prefix and valid rewards validReward = "custom-reward-id" in m.tags validCommand = m.message != None and len( m.message) > 1 and m.message[0] in self.prefixes if (not validReward and not validCommand): return try: if validReward: util.LogReceived(m.type, m.user, m.message, m.tags) util.SendMessage(self.redeem[m.tags["custom-reward-id"]](m), m.type, m.user) if validCommand: # Retrieve first word without prefix m.message = m.message[1:] token = m.message.lower().split()[0] if (token in self.execute): util.LogReceived(m.type, m.user, m.message, m.tags, True) util.SendMessage(self.execute[token](m), m.type, m.user) return # Simple response commands # Note that we don't get this far unless the message does not match other commands response = self.commands["CustomCommands"].Execute(m) if response != None: util.SendMessage(response, m.type, m.user) return except Exception as e: ptf(f"Error: {e}", time=True)
def ExecutePoll(self, msg): try: subCommand = msg.message.lower().split()[1] except IndexError: subCommand = None if subCommand in self.pollSubCommands: return self.pollSubCommands[subCommand](msg) if not util.CheckPrivMod(msg.tags): return f"[{msg.user}]: Only mods can start a poll" if self.pollRunning: return f"[{msg.user}]: Poll already active" self.pollThread = threading.Thread(target=self.PollAsync) # Get the first valid match from pollRegex list if (regMatch := next( (exp.match(msg.message) for exp in self.pollRegex if exp.match(msg.message) != None), None)) is None: return util.GetSyntax(msg.user, "poll NUM_MINUTES (NUM_CHOICES)")
def ExecuteClearBoard(self, msg): if not util.CheckPrivMod(msg.tags): return f"[{msg.user}]: Only mods can clear the leaderboard" self.colLeaderboard.remove({}) return f"[{msg.user}]: Leaderboard cleared"
def ExecuteQuoteDel(self, msg): if (regMatch := self.quoteDelRegex.match(msg.message)) is None: return util.GetSyntax(msg.user, "quote del NUMBER")
def ExecuteQuoteChange(self, msg): if (regMatch := self.quoteChangeRegex.match(msg.message)) is None: return util.GetSyntax(msg.user, "quote change NUMBER TEXT")
def ExecuteDelCom(self, msg): if not util.CheckPrivMod(msg.tags): return f"[{msg.user}]: Only mods can delete commands" if (regmatch := self.delComRegex.match(msg.message)) is None: return util.GetSyntax(msg.user, "delcom TEXT")
def ExecuteFindFood(self, msg): if (regMatch := self.findFoodRegex.match(msg.message)) is None: return util.GetSyntax(msg.user, "findfood TEXT")
def ExecuteShoutout(self, msg): if not util.CheckPrivMod(msg.tags): return f"[{msg.user}]: Only mods can shoutout" if (regMatch := self.shoutoutRegex.match(msg.message)) is None: return util.GetSyntax(msg.user, "shoutout USER")
def ExecuteWhoAdd(self, msg): if not util.CheckPrivSub(msg.tags): return f"[{msg.user}]: Only mods and subs can add a who quote" if (regMatch := self.whoAddRegex.match(msg.message)) is None: return util.GetSyntax(msg.user, "who add USER TEXT")
def ExecuteWhoDel(self, msg): if not util.CheckPrivMod(msg.tags): return f"[{msg.user}]: Only mods can delete a who quote" if (regMatch := self.whoDelRegex.match(msg.message)) is None: return util.GetSyntax(msg.user, "who del USER NUMBER")
def ExecuteFindSong(self, msg): self.CheckGetAccessToken() if (regMatch := self.findSongRegex.match(msg.message)) is None: return util.GetSyntax(msg.user, "findsong TEXT")
def RedeemSwapScore(self, msg): util.RedeemReward(msg.user, self.rewardSwapId) if (regMatch := self.redeemStealSwapScoreRegex.match( msg.message)) is None: return f"[{msg.user}]: You've redeemed swapscore. At any time, use the command: swapscore USER"
def ExecuteSwapScore(self, msg): if (regMatch := self.swapScoreRegex.match(msg.message)) is None: return util.GetSyntax(msg.user, "swapscore USER")
def ExecuteVoteBan(self, msg): if self.threadRunning: return f"[{msg.user}]: Busy banning someone else." if (regMatch := self.voteBanRegex.match(msg.message)) is None: return util.GetSyntax(msg.user, "voteban USER")
"user": user }, { "$set": { "score": score, "_ts": datetime.datetime.utcnow() } } def StealScoreHelper(self, user, targUser): targUser = targUser.lower() if (targResult := self.colLeaderboard.find_one({"user": targUser })) is None: return f"[{user}]: That user does not have a score" if not util.CheckRemoveReward(user, self.rewardStealId): return f"[{user}]: This command requires spending sushi rolls" targScore = targResult["score"] # Give the target a new score newScore = random.randint(self.scoreMin, self.scoreMax) self.colLeaderboard.update_one(*self.MakeUpdate(targUser, newScore)) # Set the user's score to the target's old score if (userResult := self.colLeaderboard.find_one({"user": user })) is None: self.colLeaderboard.insert_one(self.MakeInsert(user, targScore)) else: self.colLeaderboard.update_one(*self.MakeUpdate(user, targScore))
def ExecuteRoll(self, msg): if (regMatch := self.rollRegex.match(msg.message)) is None: return util.GetSyntax(msg.user, "roll NUMdNUM (roll 1d20)")