def reset_cooldown(channel_name: str) -> None: """ Updates the cooldown for the given channel, setting the last accessed time to now. """ if channel_name[0] == "#": channel_name = channel_name[1:] log.error("Someplace in the code is using channels with #.") cooldowns[channel_name] = datetime.datetime.utcnow()
async def on_message(self, message): full_cmd = message.content.split() if not full_cmd: return cmd = full_cmd[0] if not cmd: return if not cmd[0] == settings["prefix"]: return cmd = cmd[len(settings["prefix"]):] # skip past "!" # check cooldown for this channel. guild = message.guild if not guild: return channel = str( guild.id) # this is a unique int representing this discord server. author = message.author is_mod = (author.guild_permissions.administrator if author.guild_permissions else False) context = CommandContext( author=AuthorInfo(name=message.author.display_name, is_mod=is_mod), channel=channel, platform="discord", ) db = Database.get() content = " ".join(full_cmd[1:] or []) if check_cooldown(db, context.channel): # Enforce cooldown for this channel. return try: resp = self.logic.exec(context, cmd, content) if resp: embed = discord.Embed( title="LogicEFTBot", url="https://eft.bot", description="The Free Tarkov Bot", color=0x780A81, ) # embed.set_thumbnail(url="") #Will be implimented soon embed.add_field(name=cmd.capitalize() + " check", value=resp, inline=True) await message.channel.send(embed=embed) reset_cooldown(context.channel) except CommandNotFoundException: # just be silent if we don't know the command. pass except Exception as e: # Log all other exceptions. log.error( f"Exception processing command ({cmd}) for channel '{guild.name}' (id={context.channel}) -" ) log.error(e) traceback.print_exc()
def check_cooldown(db: Database, channel_name: str) -> bool: """ Returns true if the given channel is under cooldown. (API requests should be blocked to avoid overloading backend.) """ if channel_name[0] == "#": channel_name = channel_name[1:] log.error("Someplace in the code is using channels with #.") cooldown_time = cooldowns[channel_name] if channel_name in cooldowns else None if cooldown_time is None: return False # no cooldown found. cooldown = db.get_cd(channel_name) if cooldown is None: cooldown = int(settings["default_cooldown"]) return not datetime.datetime.utcnow() - cooldown_time > timedelta(seconds=cooldown)
def _connect(self): """ Establish a connection to the server at the front of the server_list. """ server = self.servers.peek() try: self.connect( server.host, server.port, self._nickname, server.password, ircname=self._realname, ) except Exception as e: log.error("Error connecting to the server: %s", str(e)) pass
def get_command_aliases(self, channel: str) -> Optional[Dict[str, str]]: """ Returns all of the aliases set for this channel (or None.) """ self.sql.execute("SELECT aliases FROM users WHERE username=%s", (channel, )) aliases = self.sql.fetchone() if aliases: aliases = aliases[0] if not aliases: return None try: return cast(Dict[str, str], json.loads(aliases)) except json.decoder.JSONDecodeError: log.error( "Got invalid JSON while deserializing commands for channel %s", channel) return None
def do_command(self, context: CommandContext, event: Any, command: str, content: Optional[str]): c = self.connection try: resp = self.logic.exec(context, command, content) if resp: self.do_send_msg(context.channel, resp) except CommandNotFoundException: # just be silent if we don't know the command. pass except Exception as e: # Log all other exceptions. log.error( f"Exception processing command ({command}) for channel ({context.channel}) -" ) log.error(e) traceback.print_exc()
def bot_alias(self, ctx: CommandContext, data: str) -> str: if not ctx.author.is_mod: return "You ain't a mod you dingus!" parts = data.split() if data else None if not parts or len(parts) != 2: return "Usage: !alias <alias> <existingCommand>" alias = parts[0].lower() existingCommand = parts[1].lower() if alias in self.commands: return f"Alias `{alias}` would overwrite an existing command. Please choose another alias." if not existingCommand in self.commands: return "Can't set an alias to a command which doesn't exist!" try: self.db.add_command_alias(ctx.channel, existingCommand, alias) return f"Set new alias ({alias}) for ({existingCommand})!" except Exception as e: log.error(str(e)) return "Failed to add alias."
def between_frames() -> None: # this is run when the twitch bot has free time, roughly every 5s. volume = bot.processed_commands bot.processed_commands = 0 try: commands = [] target_time = time.time() + 2 while time.time() < target_time: # for 2 seconds, attempt to read all of the items out of the queue. # we don't want to spend too much time here, since this is called every 5 seconds, # and we have a responsibility to PONG the server. try: command = queue.get(timeout=0.1) if command: commands.append(command) except Empty: # no more items left to pull break for command in commands: if command == END_OF_LIFE: # exit command. bot.disconnect() # we need to be careful to empty the queue before exiting, so that # there is not a deadlock. # see: https://stackoverflow.com/questions/31665328/python-3-multiprocessing-queue-deadlock-when-calling-join-before-the-queue-is-em while not queue.empty(): queue.get() os._exit(0) else: feedbackQueue.put( ShardUpdate( status=":smiley: Healthy", message=f"Joining #{command}", RPM=volume, )) # issue a join command to the twitch bot. bot.do_join(str(command)) feedbackQueue.put( ShardUpdate(status=bot.status, message=bot.message, RPM=volume)) except Exception as e: # nothing to do. log.error("Exception in shard: %s", str(e))
def _connect(self): """ Establish a connection to the server at the front of the server_list. """ server = self.servers.peek() self.status = ":mobile_phone_with_arrow: Connecting" self.message = "Reaching twitch..." try: self.connect( server.host, server.port, self._nickname, server.password, ircname=self._realname, ) self.status = ":white_heavy_check_mark: Healthy" self.message = "Connected" except Exception as e: log.error("Error connecting to the server: %s", str(e)) pass
async def on_message(self, message): full_cmd = message.content.split() if not full_cmd: return cmd = full_cmd[0] if not cmd: return if not cmd[0] == settings["prefix"]: return cmd = cmd[len(settings["prefix"]):] # skip past "!" # check cooldown for this channel. guild = message.guild if not guild: return channel = str( guild.id) # this is a unique int representing this discord server. author = message.author is_mod = (author.guild_permissions.administrator if author.guild_permissions else False) context = CommandContext( author=AuthorInfo(name=message.author.display_name, is_mod=is_mod), channel=channel, platform="discord", ) db = Database.get() content = " ".join(full_cmd[1:] or []) if check_cooldown(db, context.channel): # Enforce cooldown for this channel. return try: resp = self.logic.exec(context, cmd, content) if isinstance(resp, str): await message.channel.send(resp) elif isinstance(resp, discord.Embed): await message.channel.send(embed=resp) else: log.error("Unknown response: {}".format(str(resp))) reset_cooldown(context.channel) except CommandNotFoundException: # just be silent if we don't know the command. pass except Exception as e: # Log all other exceptions. log.error( f"Exception processing command ({cmd}) for channel '{guild.name}' (id={context.channel}) -" ) log.error(e) traceback.print_exc()