from bs4 import BeautifulSoup from datetime import datetime from discord.ext import commands, tasks import core_utils import discord import os import json import requests import tarkov if os.getenv("DRAGON_ENV") == "prod": channel_id = 815310511776202773 time_limit = 600 else: channel_id = 932476007439552522 time_limit = 10 class Tarkov(commands.Cog): def __init__(self, bot): self.bot: commands.Bot = bot self.check_boss_spawns.start() # tarkov = discord.SlashCommandGroup("tarkov", "Tarkov related commands") @tasks.loop(seconds=time_limit) async def check_boss_spawns(self): # Wait until the bot is ready before we actually start executing code await self.bot.wait_until_ready() local_spawn_rates = "/tmp/boss_spawns.json" spawns_from_api = tarkov.get_tarkov_boss_info() if os.path.exists(local_spawn_rates): embed = discord.Embed( description="-------", color=discord.Color.blue(), type="rich" ) with open(local_spawn_rates, "r") as f: known_spawns = json.load(f) if spawns_from_api != known_spawns: embed.set_author(name="🎲 Boss Spawn Rates Have Changed 🎲") # Send both dicts to this method to see if any spawn rates have been updated changes_dict = tarkov.compare_boss_spawns(known_spawns, spawns_from_api) for level, boss in changes_dict.items(): if boss: embed.add_field( name=level, value="\n".join( f"{boss_name}: {change}" for boss_name, change in boss.items() ), inline=False, ) await self.bot.get_channel(channel_id).send(embed=embed) with open(local_spawn_rates, "w") as f: json.dump(spawns_from_api, f) else: with open(local_spawn_rates, "w") as f: json.dump(spawns_from_api, f) async def get_all_bosses(ctx: discord.AutocompleteContext): """ Returns a list of boss names to be used in auto complete """ bosses = tarkov.request_wiki("Bosses", "Bosses") for boss in bosses: if boss == "Knight": bosses[bosses.index(boss)] = "The Goons" return bosses @commands.slash_command( name="kappa", description="Posts a link to a google doc containing all the tasks you need for kappa", contexts={ discord.InteractionContextType.guild, discord.InteractionContextType.bot_dm, discord.InteractionContextType.private_channel, }, integration_types={ discord.IntegrationType.guild_install, discord.IntegrationType.user_install, }, ) async def post_kappa(self, ctx: discord.ApplicationContext): await ctx.respond( "https://docs.google.com/spreadsheets/d/1lwU7T1Yxt0s28xZdfFRiDEYH7BbwOkZfsv-Ozv1Ka00/edit?gid=1115791232#gid=1115791232" ) @commands.slash_command( name="traders", description="Time until trader resets", contexts={ discord.InteractionContextType.guild, discord.InteractionContextType.bot_dm, discord.InteractionContextType.private_channel, }, integration_types={ discord.IntegrationType.guild_install, discord.IntegrationType.user_install, }, ) async def trader_resets(self, ctx: discord.ApplicationContext): await ctx.defer() embed = discord.Embed( description="-------", color=discord.Color.blue(), type="rich" ) embed.set_author(name="PVE Trader Reset Times") embed.set_thumbnail( url="https://static1.thegamerimages.com/wordpress/wp-content/uploads/2023/03/from-left-to-right-the-escape-from-tarkov-trader-jaeger-the-escape-from-trakov-trader-therapist-and-the-escape-from-tarkov-trader-peacekeeper.jpg" ) query = """ { traders(gameMode:pve) { name resetTime } } """ response = tarkov.query_tarkov_api(query)["traders"] # Sort the response alphabetically by trader name response = sorted(response, key=lambda entry: entry["name"]) # Loop through the dataset for entry in response: trader_name = entry["name"] # Convert to datetime object reset_time = datetime.fromisoformat( entry["resetTime"].replace("Z", "+00:00") ) # Print the name and formatted time until reset embed.add_field( name=trader_name, value=discord.utils.format_dt(reset_time, style="R"), inline=True, ) await ctx.send_followup(embed=embed) @commands.slash_command( name="spawns", description="Boss Spawn Rates", contexts={ discord.InteractionContextType.guild, discord.InteractionContextType.bot_dm, discord.InteractionContextType.private_channel, }, integration_types={ discord.IntegrationType.guild_install, discord.IntegrationType.user_install, }, ) async def boss_spawns( self, ctx: discord.ApplicationContext, boss_name: discord.Option( str, autocomplete=discord.utils.basic_autocomplete(get_all_bosses), description="The boss you want to look up", required=False, ), ): await ctx.defer() embed = discord.Embed( description="-------", color=discord.Color.blue(), type="rich", ) embed.set_author(name="🎲 Boss Spawn chances by map 🎲") embed.set_thumbnail(url="https://i.ytimg.com/vi/Yis5rmgo_bM/maxresdefault.jpg") if boss_name: for item in tarkov.get_boss_pictures(): if item["name"] == boss_name: embed.set_thumbnail(url=item["imagePortraitLink"]) break embed.set_author(name=f"🎲 Spawn chance for {boss_name} 🎲") levels = tarkov.get_tarkov_boss_info() if not boss_name: for key, value in levels.items(): embed.add_field( name=key, value="\n".join( f"{k}: {v['spawnChance']}" for k, v in value.items() ), inline=False, ) else: for key, value in levels.items(): if boss_name in value: embed.add_field( name=key, value=f"{boss_name}: {value[boss_name]['spawnChance']}", inline=False, ) # break embed.set_footer(text="Pulled from the api") await ctx.send_followup(embed=embed) @commands.slash_command( guild_ids=None, name="boss", description="Boss Info", contexts={ discord.InteractionContextType.guild, discord.InteractionContextType.bot_dm, discord.InteractionContextType.private_channel, }, integration_types={ discord.IntegrationType.guild_install, discord.IntegrationType.user_install, }, ) async def boss_info( self, ctx: discord.ApplicationContext, boss_name: discord.Option( str, autocomplete=discord.utils.basic_autocomplete(get_all_bosses) ), ): await ctx.defer() embed = discord.Embed( description="-------", color=discord.Color.blue(), type="rich", title=f"Boss info for {boss_name}", ) wiki_url = "https://escapefromtarkov.fandom.com/wiki/" response = requests.get(wiki_url + boss_name).text soup = BeautifulSoup(response, "html.parser") # boss_info = tarkov.get_tarkov_boss_info() # for k, v in boss_info.items(): # if boss_name in v: # print(k, v) # embed.set_thumbnail(url=v[boss_name]["picture"]) # embed.add_field( # name="Followers", value=v[boss_name]["escorts"], inline=False # ) # embed.add_field( # name="Spawn Chance", # value=f"{v[boss_name]['spawnChance']}", # inline=False, # ) # break portraits = tarkov.get_boss_pictures() for boss in portraits: if boss["name"] == boss_name: embed.set_thumbnail(url=boss["imagePortraitLink"]) break health = soup.find("table", class_="wikitable").find_next("td").text.rstrip() embed.add_field(name="Health", value=health, inline=False) followers = "None" if soup.find("span", id="Followers"): # Find the amount of followers in the text followers = soup.find("span", id="Followers").find_next("p").text embed.add_field(name="Followers", value=followers, inline=False) spawn_chance = "%\n".join( soup.find("td", class_="va-infobox-label", string="Spawn chance") .find_next("td", class_="va-infobox-content") .text.split("%") ) embed.add_field(name="Spawn Chance", value=f"**{spawn_chance}**", inline=False) embed.add_field( name="Link", value=f"{wiki_url + boss_name.replace(' ', '_')}", inline=False ) await ctx.send_followup(embed=embed) def setup(bot): bot.add_cog(Tarkov(bot))