from bs4 import BeautifulSoup from discord import option from discord.ext import commands, tasks import discord import os import requests import json import star_citizen if os.getenv("DRAGON_ENV") == "prod": channel_id = 1097567909640929340 else: channel_id = 932476007439552522 class StarCitizen(commands.Cog): def __init__(self, bot): self.bot: commands.Bot = bot self.poll_status_page.start() starcitizen = discord.SlashCommandGroup( "starcitizen", "StarCitizen related commands" ) @starcitizen.command( guild_ids=None, name="medpens", description="Posts an infographic about which medpens to use for which injuries in Star Citizen", ) async def post_medpen_guide(self, ctx: commands.Context): await ctx.respond("https://i.redd.it/lfswlf5c13t71.png") @starcitizen.command( guild_ids=None, name="drugs", description="Returns a list of all the drugs in game sorted by their price", ) async def post_drugs(self, ctx: commands.Context): headers = {"api_key": os.getenv("uexcorp_key")} response = requests.get( "https://portal.uexcorp.space/api/commodities/", headers=headers ) all_commodities = [x for x in response.json()["data"]] all_drugs = { item["name"]: item["trade_price_sell"] for item in all_commodities if item["kind"] == "Drug" or "Gasping" in item["name"] } sorted_dict = dict(sorted(all_drugs.items(), key=lambda item: item[1])) embed = discord.Embed( description="-------", color=discord.Color.orange(), type="rich" ) embed.set_thumbnail( url="https://media.starcitizen.tools/3/31/ViceCommodity_E%27tam.jpg" ) embed.set_author(name="Ranking of drugs by sell price") for k, v in sorted_dict.items(): embed.add_field( name=k, value=f"${v:,}", inline=False, ) await ctx.defer() await ctx.send_followup(embed=embed) async def get_all_ships(ctx: discord.AutocompleteContext): """ returns a list of all ships in the game, which can then be passed to the /ship command for auto complete """ url = "https://starcitizen.tools/Category:Ships" response = requests.get(url).text soup = BeautifulSoup(response, "html.parser") h2_heading = soup.find("h2", text='Pages in category "Ships"') all_ships = [link.text for link in h2_heading.find_next("div").find_all("a")] return all_ships @starcitizen.command( guild_ids=None, name="ship", description="Query the star citizen database about a ship", ) async def get_ship( self, ctx: commands.Context, ship: discord.Option( str, autocomplete=discord.utils.basic_autocomplete(get_all_ships), description="The ship to look up", ), ): await ctx.defer() embed = await star_citizen.get_ship(ship_name=ship) await ctx.send_followup(embed=embed) async def get_all_commodities(ctx: discord.AutocompleteContext): """ Returns a list of commododites that can be used for autocomplete for the /trade function. Turning off its call to the API just to save key usage / i hear the devs took data out of the game files so this may go away soon """ # headers = {"api_key": os.getenv("uexcorp_key")} # response = requests.get( # "https://portal.uexcorp.space/api/commodities/", headers=headers # ) # all_commodities = [x["name"] for x in response.json()["data"]] all_commodities = [ "Agricultural Supplies", "Agricium", "Agricium (Ore)", "Altruciatoxin", "Aluminum", "Aluminum (Ore)", "Amioshi Plague", "Aphorite", "Astatine", "Audio Visual Equipment", "Beryl (Raw)", "Beryl", "Bexalite", "Bexalite (Raw)", "Borase", "Borase (Ore)", "Chlorine", "Construction Materials", "Compboard", "Copper", "Copper (Ore)", "Corundum", "Corundum (Raw)", "Degnous Root", "Diamond", "Diamond (Ore)", "Distilled Spirits", "Dolivine", "E'tam", "Fireworks", "Fluorine", "Gasping Weevil Eggs", "Genalite", "Golden Medmon", "Gold", "Gold (Ore)", "Hadanite", "Helium", "Hephaestanite", "Hephaestanite (Raw)", "Heart of the Woods", "Hydrogen", "Inert Materials", "Iodine", "Iron", "Janalite", "Laranite", "Laranite (Ore)", "Luminalia Gift", "Maze", "Medical Supplies", "Neon", "Osoian Hides", "Party Favors", "Pitambu", "Processed Food", "Prota", "Quartz (Raw)", "Quantainium", "Quartz", "Quantainium (Raw)", "Ranta Dung", "Recycled Material Composite", "Red Festival Envelope", "Revenant Pod", "Revenant Tree Pollen", "Stone Bug Shell", "Scrap", "SLAM", "Stims", "Sunset Berries", "Souvenirs", "Taranite", "Taranite (Raw)", "Titanium", "Titanium (Ore)", "Tungsten", "Tungsten (Ore)", "Waste", "WiDoW", ] return all_commodities @starcitizen.command( guild_ids=None, name="price", description="Returns the price of Items in Star Citizen", ) @option( name="scu", description="How much SCU you found", required=True, min_value=1, max_value=98304, ) async def get_price( self, ctx: commands.Context, commodity: discord.Option( str, autocomplete=discord.utils.basic_autocomplete(get_all_commodities) ), scu: int, ): await ctx.defer() embed = await star_citizen.get_price(commodity=commodity, scu=scu) await ctx.send_followup(embed=embed) @starcitizen.command( guild_ids=None, name="trade", description="Calculates the most profitable route for a given commodity", ) @option( name="scu", description="Optinal how much SCU to fill", required=False, min_value=1, max_value=98304, ) async def calculate_trade_profits( self, ctx: commands.Context, commodity: discord.Option( str, autocomplete=discord.utils.basic_autocomplete(get_all_commodities) ), scu: int, ): await ctx.defer() embed = await star_citizen.calculate_trade_profits(commodity=commodity, scu=scu) await ctx.send_followup(embed=embed) @tasks.loop(seconds=5) async def poll_status_page(self): # Wait until the bot is ready before we actually start executing code await self.bot.wait_until_ready() status_url = "https://status.robertsspaceindustries.com" rsi_incident_file = "/tmp/rsi_incident" status_json = requests.get(status_url + "/index.json").json() if status_json["summaryStatus"] != "operational": # Extract systems with unresolved issues systems_with_issues = [ system for system in status_json["systems"] if system["unresolvedIssues"] ] print(systems_with_issues) unresolved_issue_permalink = systems_with_issues[0]["unresolvedIssues"][0][ "permalink" ] # Remove any single quote characters from the URL current_incident_url = unresolved_issue_permalink.replace("'", "") response = requests.get(current_incident_url).text incident_soup = BeautifulSoup(response, "html.parser") details = incident_soup.find("div", class_="article__content").get_text() if os.path.exists(rsi_incident_file): file_contents = json.loads(open(rsi_incident_file).read()) deets = file_contents["details"] incident_link = file_contents["incident_link"] if current_incident_url != incident_link: print( "Current incident url did not match whats in the file, must be a new incident, send alert" ) embed = star_citizen.build_alert_embed( color=discord.Color.red(), thumbnail="https://media.robertsspaceindustries.com/t0q21kbb3zrpt/source.png", author="🚨 OH NO THERES AN INCIDENT 🚨", image="https://media.giphy.com/media/WWIZJyXHXscn8JC1e0/giphy.gif", details=details, link=current_incident_url, ) star_citizen.write_incident_file( file_path=rsi_incident_file, url=current_incident_url, details=details, ) await star_citizen.send_alert(self, channel=channel_id, embed=embed) elif deets != details: # The details we have in the json file do not match what was recently posted to the website # Update the json file on disk and then send an update alert to the channel star_citizen.write_incident_file( file_path=rsi_incident_file, url=current_incident_url, details=details, ) embed = star_citizen.build_alert_embed( color=discord.Color.yellow(), thumbnail="https://media.robertsspaceindustries.com/t0q21kbb3zrpt/source.png", author="⚠️ THERE HAS BEEN AN UPDATE TO THE ONGOING INCIDENT ⚠️", image="https://media.giphy.com/media/WWIZJyXHXscn8JC1e0/giphy.gif", details=deets, link=incident_link, ) await star_citizen.send_alert(self, channel=channel_id, embed=embed) else: # Write the incident's body to a json file to read later star_citizen.write_incident_file( file_path=rsi_incident_file, url=current_incident_url, details=details, ) embed = star_citizen.build_alert_embed( color=discord.Color.red(), thumbnail="https://media.robertsspaceindustries.com/t0q21kbb3zrpt/source.png", author="🚨 OH NO THERES AN INCIDENT 🚨", image="https://media.giphy.com/media/WWIZJyXHXscn8JC1e0/giphy.gif", details=details, link=current_incident_url, ) await star_citizen.send_alert(self, channel=channel_id, embed=embed) @starcitizen.command( guild_ids=None, name="rsifind", description="Pull up info about a player from their RSI profile", ) @option( name="player", description="The player name to search for", required=True, ) async def rsi_find(self, ctx: commands.Context, player: str): await ctx.defer() embed = await star_citizen.rsi_find(player=player) await ctx.send_followup(embed=embed) def setup(bot): bot.add_cog(StarCitizen(bot))