async def deck(self, ctx: commands.Context, *, nation: Union[int, Link[Nation]]): """Retrieves general info about the specified nation's deck.""" is_id = isinstance(nation, int) if is_id: api = Api("cards info", nationid=nation) else: api = Api("cards info", nationname=nation) root = await api if not root.INFO.countchildren(): if is_id: return await ctx.send(f"No such deck for ID {nation}.") return await ctx.send(f"No such deck for nation {nation!r}.") n_id = root.INFO.NAME.text if n_id not in self.db_cache: self.db_cache[n_id] = {"dbid": root.INFO.ID.pyval} await self.config.custom("NATION", n_id).dbid.set(root.INFO.ID.pyval) embed = ProxyEmbed( title=n_id.replace("_", " ").title(), url=f"https://www.nationstates.net/page=deck/nation={n_id}", description=f"{root.INFO.NUM_CARDS.text} cards", colour=await ctx.embed_colour(), timestamp=datetime.utcfromtimestamp(root.INFO.LAST_VALUED.pyval), ) embed.add_field(name="Bank", value=root.INFO.BANK.text) embed.add_field( name="Deck Value", value= f"[{root.INFO.DECK_VALUE.text}](https://www.nationstates.net/nation={n_id}/detail=trend/censusid=86)" f"\nRanked #{root.INFO.RANK.text} worldwide, #{root.INFO.REGION_RANK.text} regionally.", inline=False, ) embed.set_footer(text="Last Valued") await embed.send_to(ctx)
async def invoice(self, ctx): """ Configure or view settings for automated voice-based permissions. """ if ctx.invoked_subcommand: return color = await ctx.embed_colour() embed = ProxyEmbed(title=f"Current settings", color=color) g_settings = self.guild_cache[ctx.guild.id] g_msg = [] for key, value in g_settings.items(): if value is not None and key == "role": value = ctx.guild.get_role(value) value = value.name if value else "<Deleted role>" key = key.replace("_", " ").title() g_msg.append(f"{key}: {value}") embed.add_field(name=f"Guild {ctx.guild} settings", value="\n".join(g_msg)) vc = ctx.author.voice.channel if ctx.author.voice else None if vc: c_settings = self.channel_cache[ctx.channel.id] c_msg = [] for key, value in c_settings.items(): if value is not None: if key == "role": value = ctx.guild.get_role(value) value = value.name if value else "<Deleted role>" elif key == "channel": value = ctx.guild.get_channel(value) value = value.name if value else "<Deleted channel>" key = key.replace("_", " ").title() c_msg.append(f"{key}: {value}") embed.add_field(name=f"Channel {vc} settings", value="\n".join(c_msg)) await embed.send_to(ctx)
async def show( self, ctx: commands.GuildContext, *, scope: Union[discord.CategoryChannel, GuildVoice] = None, ): """ Show the current settings for the specified scope. See `[p]help invoice set` for explanations of the various settings. """ guild = ctx.guild scoped = scope or guild chain = Chain.from_scope(scoped, self.cache) embed = ProxyEmbed(title=f"Current settings for {scoped}", color=await ctx.embed_color()) for key, value in chain.items(): if value and key == "role": value = guild.get_role(value) or "<Deleted role>" elif value and key == "channel": value = guild.get_channel(value) or "<Deleted channel>" elif not value and key == "dynamic_name": value = "\N{SPEAKER WITH THREE SOUND WAVES} {vc}" else: value = value or False embed.add_field(name=key.replace("_", " ").title(), value=getattr(value, "mention", str(value))) embed.set_footer( text= "Settings shown here reflect the effective settings for the scope," " including inherited settings from the category or guild.") await embed.send_to( ctx, allowed_mentions=discord.AllowedMentions(users=False))
async def wa(self, ctx: commands.Context, resolution_id: Optional[int] = None, *options: WA): """ Retrieves general info about World Assembly resolutions. Defaults to the General Assembly. Use [p]sc to get info about the Security Council. If no resolution ID is provided, the current at-vote resolution is used. Valid options: text - The resolution's text votes - The total votes for and against nations - The total nations for and against delegates - The top ten Delegates for and against """ option = WA.collapse(*options, default=0) if resolution_id and option & (WA.NATION | WA.DELEGATE): return await ctx.send( "The Nations and Delegates options are not available for past resolutions." ) is_sc = ctx.invoked_with == "sc" shards = ["resolution"] request = {"wa": "2" if is_sc else "1"} if option & WA.DELEGATE: shards.append("delvotes") if resolution_id: request["id"] = str(resolution_id) else: shards.append("lastresolution") root = await Api(request, q=shards) if not root.RESOLUTION.countchildren(): out = (unescape(root.LASTRESOLUTION.text).replace( "<strong>", "**").replace("</strong>", "**")) try: out = "{}[{}](https://www.nationstates.net{}){}".format( out[:out.index("<a")], out[out.index('">') + 2:out.index("</a")], out[out.index('="') + 2:out.index('">')], out[out.index("</a>") + 4:], ) except ValueError: pass embed = ProxyEmbed(title="Last Resolution", description=out, colour=await ctx.embed_colour()) embed.set_thumbnail( url="https://www.nationstates.net/images/{}.jpg".format( "sc" if is_sc else "ga")) return await embed.send_to(ctx) root = root.RESOLUTION img = { "Commendation": "images/commend.png", "Condemnation": "images/condemn.png", "Liberation": "images/liberate.png", }.get(root.CATEGORY.text, "images/ga.jpg") if option & WA.TEXT: description = "**Category: {}**\n\n{}".format( root.CATEGORY.text, escape(root.DESC.text, formatting=True)) short = next( pagify( description, delims=("\n", " ", "]"), escape_mass_mentions=False, page_length=2047, priority=True, )) if len(short) < len(description): description = short + "\N{HORIZONTAL ELLIPSIS}" else: description = "Category: {}".format(root.CATEGORY.text) if resolution_id: impl = root.IMPLEMENTED.pyval else: # mobile embeds can't handle the FUTURE impl = root.PROMOTED.pyval # + (4 * 24 * 60 * 60) # 4 Days embed = ProxyEmbed( title=root.NAME.text, url="https://www.nationstates.net/page={}".format( "sc" if is_sc else "ga") if not resolution_id else "https://www.nationstates.net/page=WA_past_resolution/id={}/council={}" .format(resolution_id, "2" if is_sc else "1"), description=description, timestamp=datetime.utcfromtimestamp(impl), colour=await ctx.embed_colour(), ) try: authroot = await Api("fullname flag", nation=root.PROPOSED_BY.text) except NotFound: embed.set_author( name=root.PROPOSED_BY.text.replace("_", " ").title(), url="https://www.nationstates.net/page=boneyard?nation={}". format(root.PROPOSED_BY.text), icon_url="http://i.imgur.com/Pp1zO19.png", ) else: embed.set_author( name=authroot.FULLNAME.text, url="https://www.nationstates.net/nation={}".format( root.PROPOSED_BY.text), icon_url=authroot.FLAG.text, ) embed.set_thumbnail(url="https://www.nationstates.net/{}".format(img)) if option & WA.DELEGATE: for_del_votes = heapq.nlargest( 10, root.iterfind("DELVOTES_FOR/DELEGATE"), key=operator.attrgetter("VOTES.pyval")) against_del_votes = heapq.nlargest( 10, root.iterfind("DELVOTES_AGAINST/DELEGATE"), key=operator.attrgetter("VOTES.pyval"), ) if for_del_votes: embed.add_field( name="Top Delegates For", value="\t|\t".join( "[{}](https://www.nationstates.net/nation={}) ({})". format( e.NATION.text.replace("_", " ").title(), e.NATION.text, e.VOTES.text) for e in for_del_votes), inline=False, ) if against_del_votes: embed.add_field( name="Top Delegates Against", value="\t|\t".join( "[{}](https://www.nationstates.net/nation={}) ({})". format( e.NATION.text.replace("_", " ").title(), e.NATION.text, e.VOTES.text) for e in against_del_votes), inline=False, ) if option & WA.VOTE: percent = ( 100 * root.TOTAL_VOTES_FOR.pyval / (root.TOTAL_VOTES_FOR.pyval + root.TOTAL_VOTES_AGAINST.pyval)) embed.add_field( name="Total Votes", value="For {}\t{:◄<13}\t{} Against".format( root.TOTAL_VOTES_FOR.pyval, "►" * int(round(percent / 10)) + str(int(round(percent))) + "%", root.TOTAL_VOTES_AGAINST.pyval, ), inline=False, ) if option & WA.NATION: percent = (100 * root.TOTAL_NATIONS_FOR.pyval / (root.TOTAL_NATIONS_FOR.pyval + root.TOTAL_NATIONS_AGAINST.pyval)) embed.add_field( name="Total Nations", value="For {}\t{:◄<13}\t{} Against".format( root.TOTAL_NATIONS_FOR.pyval, "►" * int(round(percent / 10)) + str(int(round(percent))) + "%", root.TOTAL_NATIONS_AGAINST.pyval, ), inline=False, ) # I can only blame my own buggy code for the following repealed_by = root.find("REPEALED_BY") if repealed_by is not None: embed.add_field( name="Repealed By", value= '[Repeal "{}"](https://www.nationstates.net/page=WA_past_resolution/id={}/council={})' .format(root.NAME.text, root.REPEALED_BY.text, "2" if is_sc else "1"), inline=False, ) repeals = root.find("REPEALS_COUNCILID") if repeals is not None: embed.add_field( name="Repeals", value= "[{}](https://www.nationstates.net/page=WA_past_resolution/id={}/council={})" .format(root.NAME.text[8:-1], repeals, "2" if is_sc else "1"), inline=False, ) embed.set_footer(text="Passed" if resolution_id else "Voting Started") await embed.send_to(ctx)
async def card( self, ctx: commands.Context, season: Optional[int] = 2, *, nation: Optional[Union[int, Link[Nation]]] = None, ): """ Retrieves general info about the specified card. If a number is provided, the bot will look for the card with that ID. Otherwise, the bot will look for the specified nation's card. If you want to find a nation that has a numerical name, use a link or "quotes" to specify that it is a name, and not an ID. A season must be specified if this is the case. """ if season is not None and nation is None: season, nation = 2, season if isinstance(nation, str) and nation not in self.db_cache: api = Api("dbid", nation=nation) try: root = await api except NotFound: return await ctx.send( f"Nation {nation!r} does not exist. " "Please provide its card ID instead, and I'll remember it for next time." ) n_id, nation = root.get("id"), root.DBID.pyval self.db_cache[n_id] = {"dbid": nation} await self.config.custom("NATION", n_id).dbid.set(nation) else: n_id, nation = None, self.db_cache.get(nation, {}).get("dbid", nation) assert isinstance(nation, int), repr(nation) api = Api("card info markets", cardid=nation, season=season) root = await api if not root.countchildren(): if n_id: return await ctx.send( f"No such S{season} card for nation {n_id!r}.") return await ctx.send(f"No such S{season} card for ID {nation!r}.") n_id = root.NAME.text.casefold().replace(" ", "_") if n_id not in self.db_cache: self.db_cache[n_id] = {"dbid": nation} await self.config.custom("NATION", n_id).dbid.set(nation) embed = ProxyEmbed( title=f"The {root.TYPE.text} of {root.NAME.text}", url= f"https://www.nationstates.net/page=deck/card={nation}/season={season}", colour=CARD_COLORS.get(root.CATEGORY.text, 0), ) embed.set_author(name=root.CATEGORY.text.title()) embed.set_thumbnail( url= f"https://www.nationstates.net/images/cards/s{season}/{root.FLAG.text}" ) embed.add_field( name="Market Value (estimated)", value=box(root.MARKET_VALUE.text, lang="swift"), inline=False, ) sellers: List[Tuple[int, str]] = [] buyers: List[Tuple[int, str]] = [] for market in root.MARKETS.iterchildren(): if market.TYPE.text == "bid": # negative price to reverse sorting bisect.insort(buyers, (-market.PRICE.pyval, market.NATION.text.replace("_", " ").title())) elif market.TYPE.text == "ask": bisect.insort(sellers, (market.PRICE.pyval, market.NATION.text.replace("_", " ").title())) if not any((buyers, sellers)): return await embed.send_to(ctx) max_listed = 5 max_len = max(len(buyers), len(sellers)) max_len = min(max_len, max_listed + 1) for is_buyers, arr in enumerate((sellers, buyers)): pad = "\n\u200b" * max(0, max_len - len(arr)) if not arr: embed.add_field(name="Buyers" if is_buyers else "Sellers", value=box(pad)) embed.overwrites.set_field_at( is_buyers + 1, name=embed.fields[is_buyers + 1].name, value=box("\u200b", lang="swift"), ) continue tarr = [ f"{-j[0]:.02f}\xa0{j[1]}" if is_buyers else f"{j[1]}\xa0{j[0]:.02f}" for j in arr[:max_listed] ] if len(arr) > max_listed: num = len(arr) - max_listed tarr.append( f"+ {num} more {'bid' if is_buyers else 'ask'}{'' if num == 1 else 's'}\N{HORIZONTAL ELLIPSIS}" ) raw_text = "\n".join(tarr) if not is_buyers: width = max(map(len, tarr)) for i, t in enumerate(tarr): tarr[i] = t.rjust(width) text = "\n".join(tarr) + pad embed.add_field(name="Buyers" if is_buyers else "Sellers", value=box(text, lang="swift")) embed.overwrites.set_field_at( is_buyers + 1, name=embed.fields[is_buyers + 1].name, value=box(raw_text, lang="swift"), ) await embed.send_to(ctx)
async def region(self, ctx: commands.Context, *, region: Link[Region]): """Retrieves general info about a specified NationStates region""" api: Api = Api( "delegate delegateauth delegatevotes flag founded founder founderauth lastupdate name numnations power tags zombie", region=region, ) try: root = await api except NotFound: embed = ProxyEmbed(title=region.replace("_", " ").title(), description="This region does not exist.") embed.set_author(name="NationStates", url="https://www.nationstates.net/") return await embed.send_to(ctx) if root.DELEGATE.text == "0": delvalue = "No Delegate" else: endo = root.DELEGATEVOTES.pyval - 1 if endo == 1: endo = "{:.0f} endorsement".format(endo) else: endo = "{:.0f} endorsements".format(endo) delvalue = "[{}](https://www.nationstates.net/nation={}) | {}".format( root.DELEGATE.text.replace("_", " ").title(), root.DELEGATE.text, endo) if "X" in root.DELEGATEAUTH.text: delheader = "Delegate" else: delheader = "Delegate (Non-Executive)" tags = {t.text for t in root.iterfind("TAGS/TAG")} founderless = "Founderless" in tags founded = "in Antiquity" if root.FOUNDED.pyval == 0 else root.FOUNDED.pyval if root.FOUNDER.text == "0": foundervalue = "No Founder" else: if founderless: url = "https://www.nationstates.net/page=boneyard?nation=" else: url = "https://www.nationstates.net/nation=" foundervalue = "[{}]({}{}){}".format( root.FOUNDER.text.replace("_", " ").title(), url, root.FOUNDER.text, " (Ceased to Exist)" if founderless else "", ) founderheader = "Founderless" if founderless else "Founder" if not root.FOUNDERAUTH.text or "X" not in root.FOUNDERAUTH.text: founderheader += " (Non-Executive)" fash = "Fascist" in tags and "Anti-Fascist" not in tags # why do people hoard tags... name = "{}{}".format("\N{LOCK} " if "Password" in tags else "", root.NAME.text) warning = ( "\n**```css\n\N{HEAVY EXCLAMATION MARK SYMBOL} Region Tagged as Fascist \N{HEAVY EXCLAMATION MARK SYMBOL}\n```**" if fash else "") description = "[{} nations](https://www.nationstates.net/region={}/page=list_nations) | Founded {} | Power: {}{}".format( root.NUMNATIONS.pyval, root.get("id"), founded, root.POWER.text, warning) is_zday = self._is_zday(ctx.message, dev=ctx.author.id == 215640856839979008) embed = ProxyEmbed( title=name, url="https://www.nationstates.net/region={}".format( root.get("id")), description=description, timestamp=datetime.utcfromtimestamp(root.LASTUPDATE.pyval), colour=0x000001 if fash else 0x8BBC21 if is_zday else await ctx.embed_colour(), ) embed.set_author(name="NationStates", url="https://www.nationstates.net/") if root.FLAG.text: embed.set_thumbnail(url=root.FLAG.text) embed.add_field(name=founderheader, value=foundervalue, inline=False) embed.add_field(name=delheader, value=delvalue, inline=False) if is_zday: embed.add_field( name="Zombies", value="Survivors: {} | Zombies: {} | Dead: {}".format( self._illion(root.ZOMBIE.SURVIVORS), self._illion(root.ZOMBIE.ZOMBIES), self._illion(root.ZOMBIE.DEAD), ), inline=False, ) embed.set_footer(text="Last Updated") await embed.send_to(ctx)
async def nation(self, ctx: commands.Context, *, nation: Link[Nation]): """Retrieves general info about a specified NationStates nation""" api: Api = Api( "census category dbid", "demonym2plural flag founded freedom", "fullname influence lastlogin motto", "name population region wa zombie", nation=nation, mode="score", scale="65 66", ) try: root = await api except NotFound: embed = ProxyEmbed( title=nation.replace("_", " ").title(), url="https://www.nationstates.net/page=" "boneyard?nation={}".format(nation), description="This nation does not exist.", ) embed.set_author(name="NationStates", url="https://www.nationstates.net/") embed.set_thumbnail(url="http://i.imgur.com/Pp1zO19.png") return await embed.send_to(ctx) n_id = root.get("id") if n_id not in self.db_cache: self.db_cache[n_id] = {"dbid": root.DBID.pyval} await self.config.custom("NATION", n_id).dbid.set(root.DBID.pyval) endo = root.find("CENSUS/SCALE[@id='66']/SCORE").pyval if endo == 1: endo = "{:.0f} endorsement".format(endo) else: endo = "{:.0f} endorsements".format(endo) founded = root.FOUNDED.pyval or "in Antiquity" is_zday = self._is_zday(ctx.message, dev=ctx.author.id == 215640856839979008) embed = ProxyEmbed( title=root.FULLNAME.text, url="https://www.nationstates.net/nation={}".format( root.get("id")), description="[{}](https://www.nationstates.net/region={})" " | {} {} | Founded {}".format( root.REGION.text, "_".join(root.REGION.text.lower().split()), self._illion(root.POPULATION.pyval), root["DEMONYM2PLURAL"].text, founded, ), timestamp=datetime.utcfromtimestamp(root.LASTLOGIN.pyval), colour=0x8BBC21 if is_zday else await ctx.embed_colour(), ) embed.set_author(name="NationStates", url="https://www.nationstates.net/") embed.set_thumbnail(url=root.FLAG.text) embed.add_field( name=root.CATEGORY.text, value="{}\t|\t{}\t|\t{}".format( root.find("FREEDOM/CIVILRIGHTS"), root.find("FREEDOM/ECONOMY"), root.find("FREEDOM/POLITICALFREEDOM"), ), inline=False, ) embed.add_field( name=root.UNSTATUS.text, value="{} | {:.0f} influence ({})".format( endo, root.find("CENSUS/SCALE[@id='65']/SCORE").pyval, root.INFLUENCE.text), inline=False, ) if is_zday: embed.add_field( name="{}{}".format( (root.ZOMBIE.ZACTION.text or "No Action").title(), " (Unintended)" if root.ZOMBIE.ZACTIONINTENDED.text else "", ), value="Survivors: {} | Zombies: {} | Dead: {}".format( self._illion(root.ZOMBIE.SURVIVORS), self._illion(root.ZOMBIE.ZOMBIES), self._illion(root.ZOMBIE.DEAD), ), inline=False, ) embed.add_field( name="Cards", value= ("[{0}'s Deck](https://www.nationstates.net/page=deck/nation={1})\t|" "\t[{0}'s Card](https://www.nationstates.net/page=deck/card={2})". format(root.NAME.text, n_id, root.DBID.text)), ) embed.set_footer(text="Last Active") await embed.send_to(ctx)