def _player_str(self, player: BSPlayer, sort='trophies'): """Player profile as plain text.""" avatar = self.get_avatar(player) o = [ '{}'.format(avatar), '{} #{}'.format(bold(player.name), player.tag), '{}, {} #{}'.format(player.club.role, player.club.name, player.club.tag) if player.club else 'No Clan', '{} {} / {}'.format(self.get_emoji('bstrophy'), player.trophies, player.highestTrophies), '{emoji} {time} Best time as Boss'.format( emoji=self.get_emoji('bossfight'), time=inline(player.bestTimeAsBoss)), '{emoji} {time} Best Robo Rumble time'.format( emoji=self.get_emoji('roborumble'), time=inline(player.bestRoboRumbleTime)), # victories '{normal} {solo} {duo}'.format( normal='{emoji} {value} {name}'.format( emoji=self.get_emoji('battlelog'), value=inline(player.victories), name='Victories'), solo='{emoji} {value} {name}'.format( emoji=self.get_emoji('showdown'), value=inline(player.soloShowdownVictories), name='Solo SD'), duo='{emoji} {value} {name}'.format( emoji=self.get_emoji('duoshowdown'), value=inline(player.duoShowdownVictories), name='Duo SD'), ), # brawler stats 'Brawlers: {}'.format(len(player.brawlers)), 'Trophy per Brawler Level: {:.2f}'.format( player.trophies / sum([b.level for b in player.brawlers])), 'Trophy per Brawler: {:.2f}'.format(player.trophies / len(player.brawlers)), ] # brawlers brawlers = player.brawlers.copy() if sort == 'level': brawlers.sort(key=lambda x: x.level, reverse=True) elif sort == 'trophy_by_level': brawlers.sort(key=lambda x: x.trophies / x.level, reverse=True) for b in brawlers or []: o.append( '{emoji} `\u2800{trophies: >3} Lvl {level: >2} {trophy_per_level: >2.2f}\u2800` {name}' .format( emoji=self.get_emoji(b.name.lower().replace(' ', '')), trophies=b.trophies, pb=b.highestTrophies, level=b.level, name=b.name, trophy_per_level=b.trophies / b.level, )) return '\n'.join(o)
def key_display_str(self, key, member, show_token=False): """Return formatted output of a key.""" default = '-' out = [] out.append("{member} ({id})".format(member=bold(member), id=key.get('id', default))) registered = key.get('registered', default) if isinstance(registered, int): registered_iso = dt.datetime.utcfromtimestamp(registered / 1000).isoformat() registered_str = "{} / {}".format(registered, registered_iso) else: registered_str = '-' out.append("Registered: {}".format(registered_str)) out.append("Last Request: {}".format(key.get('lastRequest', default))) out.append("Blacklisted: {}".format(key.get('blacklisted', default))) if show_token: out.append("Token: {}".format(key.get('token', default))) request_count = key.get('requestCount', default) request_count_str = '' if isinstance(request_count, dict): request_count_str = box('\n'.join([ "{} : {:>10,}".format(k, v) for k, v in request_count.items() ]), lang='python') out.append('Request Count: {}'.format(request_count_str)) return '\n'.join(out)
async def myentries(self, ctx): entryAuthor = ctx.message.author jsonEntries = newEntriesList serverID = ctx.message.server.id serverIDPath = dataPath + "/" + serverID entriesList = [] count = 0; # get list of existing entries with open(serverIDPath + '/entries.txt', 'r') as file: try: jsonEntries = json.load(file) entriesList = jsonEntries['entries'] except ValueError: # I guess the array didn't exist in the entries.txt file or something. print("ERROR: Composeprompt: [p]newprompt: Could not get data from JSON file!") # send list of entries via PM to requesting user messageText = "" if len(entriesList) == 0: await self.bot.send_message(ctx.message.author, content="No one has submitted anything yet.\nAnd that includes you.", tts=False, embed=None) return await self.bot.send_message(ctx.message.author, content=bold("List of entries:"), tts=False, embed=None) for entry in entriesList: if entry['author'] == entryAuthor.id: count = count + 1 messageText = "Entry #" + str(count) + ": " + entry['entry'] await self.bot.send_message(ctx.message.author, content=messageText, tts=False, embed=None) if count is 0: await self.bot.send_message(ctx.message.author, content="This list is empty because you have submitted exactly nothing.\nGood job.", tts=False, embed=None)
async def viewentries(self, ctx): """Show all entries submitted for this week's prompt so far!""" entryAuthor = ctx.message.author jsonEntries = newEntriesList serverID = ctx.message.server.id serverIDPath = dataPath + "/" + serverID entriesList = [] # get list of existing entries with open(serverIDPath + '/entries.txt', 'r') as file: try: jsonEntries = json.load(file) entriesList = jsonEntries['entries'] except ValueError: # I guess the array didn't exist in the entries.txt file or something. print("ERROR: Composeprompt: [p]newprompt: Could not get data from JSON file!") # send list of entries via PM to requesting user messageText = "" if len(entriesList) == 0: await self.bot.send_message(ctx.message.author, content="No entries yet! Get working!", tts=False, embed=None) return await self.bot.send_message(ctx.message.author, content=bold("List of entries:"), tts=False, embed=None) for entry in entriesList: userObject = await self.bot.get_user_info(entry['author']) messageText = userObject.name +":\n" + entry['entry'] await self.bot.send_message(ctx.message.author, content=messageText, tts=False, embed=None)
async def get_reactions(self, message, exclude_self=True): title = message.channel.name description = message.content out = [ bold('Channel: {}'.format(title)), escape_mass_mentions(description) ] server = message.server total_count = 0 reaction_votes = [] for reaction in message.reactions: if reaction.custom_emoji: # <:emoji_name:emoji_id> emoji = '<:{}:{}>'.format( reaction.emoji.name, reaction.emoji.id) else: emoji = reaction.emoji reaction_users = await self.bot.get_reaction_users(reaction) valid_users = [] for u in reaction_users: if exclude_self and u == self.bot.user: continue valid_users.append(u) valid_users = sorted(valid_users, key=lambda u: u.display_name.lower()) user_ids = [u.id for u in valid_users] members = [] for uid in user_ids: member = server.get_member(uid) if member: members.append(member) total_count += 1 users_str = ', '.join([m.display_name for m in members]) count = len(valid_users) reaction_votes.append({ "emoji": emoji, "count": count, "users_str": users_str }) for v in reaction_votes: emoji = v['emoji'] count = v['count'] ratio = count / total_count users_str = v['users_str'] value = '{}: **{}** ({:.2%}): {}'.format(emoji, count, ratio, users_str) out.append(value) return out
def _player_mini_str(self, player: BSPlayer): """Minimal player profile for verification.""" avatar = self.get_avatar(player) o = [ '{}'.format(avatar), '{} #{}'.format(bold(player.name), player.tag), '{}, {} #{}'.format(player.club.role, player.club.name, player.club.tag) if player.club else 'No Clan', '{} {} / {}'.format(self.get_emoji('bstrophy'), player.trophies, player.highestTrophies), ] return "\n".join(o)
async def toggleroleset_list(self, ctx): """List all toggleable roles.""" server = ctx.message.server out = [] out.append('Toggleable roles on {}'.format(server.name)) for actor_role, v in self.settings[server.id].items(): toggleable_roles = v.keys() toggleable_roles = sorted(toggleable_roles, key=lambda x: x.lower()) if len(toggleable_roles): toggleable_roles_str = ', '.join(toggleable_roles) else: toggleable_roles_str = 'None' out.append('{}: {}'.format(bold(actor_role), toggleable_roles_str)) for page in pagify('\n'.join(out)): await self.bot.say(page)
async def rm_get(self, ctx, channel: discord.Channel, message_id, exclude_self=True): """Display list of reactions added by users.""" message = await self.bot.get_message(channel, message_id) if message is None: await self.bot.say("Cannot find that message id.") return title = message.channel.name description = message.content out = [ bold('Channel: {}'.format(title)), escape_mass_mentions(description) ] for reaction in message.reactions: if reaction.custom_emoji: # <:emoji_name:emoji_id> emoji = '<:{}:{}>'.format(reaction.emoji.name, reaction.emoji.id) else: emoji = reaction.emoji reaction_users = await self.bot.get_reaction_users(reaction) valid_users = [] for u in reaction_users: if exclude_self and u == self.bot.user: continue valid_users.append(u) valid_users = sorted(valid_users, key=lambda u: u.display_name.lower()) users_str = ', '.join([u.display_name for u in valid_users]) count = len(valid_users) value = '{}: {}: {}'.format(emoji, count, users_str) out.append(value) for page in pagify('\n'.join(out), shorten_by=24): await self.bot.say(page)
def clanwars_str(self, clans): """ Clan Wars info as a str output (save space) :param clans: list of clans :return: str """ import datetime as dt # somehow dt not registered from global import o = [] config = self.clans_config legend = ("\n{wins} " "{crowns} " "{battles_played}" "{trophies}").format( wins=emoji_value('win', 'Wins', inline=False, truncate=False), crowns=emoji_value('crown', 'Crowns', inline=False, truncate=False), battles_played=emoji_value('battle', 'Battles Played', inline=False, truncate=False), trophies=emoji_value('cwtrophy', 'CW Trophies', inline=False, truncate=False) ) o += [ bold(config.name), "Last updated: {}".format(dt.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S UTC')), legend ] # Badge badge_url = config.badge_url # clan list STATES = { 'collectionDay': 'Coll', 'warDay': 'War', 'notInWar': 'N/A', 'matchMaking': 'MM', } for c in clans: clan = Box(c, default_box=True) state = clan.state timespan = None wins = clan.clan.wins crowns = clan.clan.crowns battles_played = clan.clan.battlesPlayed if state == 'collectionDay': end_time = clan.get('collectionEndTime') elif state == 'warDay': end_time = clan.get('warEndTime') else: end_time = None if end_time is not None: dt = arrow.get(end_time, 'YYYYMMDDTHHmmss.SSS').datetime now = arrow.utcnow().datetime span = dt - now hours, remainder = divmod(span.total_seconds(), 3600) minutes, seconds = divmod(remainder, 60) timespan = '{: 2}h{: 2}m{: 2}s'.format(int(hours), int(minutes), int(seconds)) clan_name = clan.clan.name clan_score = clan.clan.clanScore state = clan.get('state', 'ERR') if state in ['collectionDay', 'warDay']: o += [ "\u2800", ( wrap_inline("{clan_name:<15.15} {state: <4} {timespan: >11.11}") + "\n{wins} " "{crowns} " "{battles_played}" "{trophies}" ).format( clan_name=clan_name, state=STATES.get(state, 'ERR'), timespan=timespan or '', wins=emoji_value('win', wins, 2), crowns=emoji_value('crown', crowns, 2), battles_played=emoji_value('battle', battles_played, 3), trophies=emoji_value('cwtrophy', clan_score, 5) ) ] else: o += [ wrap_inline( "---\nNot in war" ) ] return '\n'.join(o)
async def promptRestart(self, serverID): serverIDPath = dataPath + "/" + serverID channel = -1 prompts = {} priPrompts = [] promptsToUse = {} newPrompt = {} canidatePrompts = [] channelObject = None prompts = {} #if this bot isn't even logged in yet, don't bother if not self.bot.is_logged_in: return True #see if busy file exists for this server. If so, promptRestart is already running and this instance should abort if os.path.isdir(serverIDPath + busyFile): print("Crap, promptRestart is already running!") return False else: os.makedirs(serverIDPath + busyFile) if not os.path.isfile(serverIDPath + '/settings.txt'): #remove busyfile if os.path.isdir(serverIDPath + busyFile): shutil.rmtree(serverIDPath + busyFile) return True #get settings information from JSON file with open(serverIDPath + '/settings.txt', 'r') as file: try: settings = json.load(file) settings = settings['settings'] except ValueError: print("could not get settings from global settings") await self.bot.say("ERROR: Composeprompt: promptRestart: Could not get data from globalsettings.txt JSON file!") return True print("checking if promptrun is in settings") #check to see if composeprompt is supposed to be running in this server if "promptrun" in settings: if settings["promptrun"] is False: return True else: return True #if it gets to this point, then it is supposed to be running this this server #get which channel composeprompt should run in for this server if "channel" in settings: channel = settings["channel"] channelObject = self.bot.get_channel(settings["channel"]) else: channel = self.bot.get_server(serverID) channelObject = channel await self.bot.send_message(channel, 'Error. Bot does not have channel to run in. Using default channel') with open(serverIDPath + '/entries.txt', 'r') as file: try: entries = json.load(file) except ValueError: await self.bot.say("ERROR: Composeprompt: promptRestart: Could not get data from entires.txt JSON file!") return True #get prompts from file with open(serverIDPath + '/prompts.txt', 'r') as file: try: prompts = json.load(file) except ValueError: await self.bot.say("ERROR: Composeprompt: promptRestart: Could not get data from prompts.txt JSON file!") return True #get if there was a prompt for the previous week. If so, show it and what was submitted last week. if "prompt" in settings: userMention = await self.bot.get_user_info(settings["prompt"]["author"]) await self.bot.send_message(self.bot.get_channel(channel), bold("Last week's prompt was:\n") + box(settings["prompt"]["prompt"]) + "Submitted by " + userMention.mention) #see if list of entries is empty if len(entries["entries"]) > 0: #if not empty, print out all the entires await self.bot.send_message(self.bot.get_channel(channel), bold("Here's what people submitted!:\n")) for entry in entries["entries"]: userMention = await self.bot.get_user_info(entry["author"]) await self.bot.send_message(self.bot.get_channel(channel), "Submission by " + userMention.mention + " :\n" + entry["entry"]) # delete entries with open(serverIDPath + '/entries.txt', 'w+') as file: json.dump(newEntriesList, file, indent=4) else: #state that there were no entries await self.bot.send_message(self.bot.get_channel(channel), warning('There were no submitted entries this week. Gosh darn it!')) #see if there are any priority prompts with open(serverIDPath + '/priorityprompts.txt', 'r') as file: try: priPrompts = json.load(file) except ValueError: await self.bot.say("ERROR: Composeprompt: promptRestart: Could not get data from prompts.txt JSON file!") return True #see if priority list is empty. If it has stuff in it, use that first. Else, use regular prompts if len(priPrompts["priprompts"]) > 0: promptsToUse = priPrompts["priprompts"][0] priPrompts["priprompts"].pop(0) with open(serverIDPath + '/priorityprompts.txt', 'w+') as file: json.dump({"priprompts": priPrompts["priprompts"]}, file, indent=4) else: #use regular prompts #see if candidate exist if so, choose winner. Otherwise, randomly choose a prompt from all available prompts candidatePrompts = []; settings = {} with open(serverIDPath + '/settings.txt', 'r') as file: try: settings = json.load(file) except ValueError: await self.bot.say("ERROR: Composeprompt: promptRestart: Could not get data from settigns.txt JSON file!") return True #see if there are condidate prompts if 'candidateprompts' in settings['settings']: #see which prompt has the most votes on it. topReacted = settings['settings']['candidateprompts'] highestNum = 0; authors = [] server = self.bot.get_server(serverID) for candidatePrompt in settings['settings']['candidateprompts']: channelObject = server.get_channel(settings['settings']["channel"]) candidateMessage = await self.bot.get_message(channelObject, candidatePrompt['id']) #count the number of stars on each reaction for reaction in candidateMessage.reactions: if(type(reaction.emoji) is str and str(ord(reaction.emoji[0])) == str(likeEmoji) and reaction.count >= highestNum): if reaction.count > highestNum: topReacted = [] highestNum = reaction.count topReacted.append(candidatePrompt) promptsToUse = topReacted[randint(0, len(topReacted) - 1)] else: if len(prompts["prompts"]) >= minPrompts: #randomly choose a new prompt to set for this week's prompt #ensure the chosen prompt is placed at the front of the list #do not consider last week's chosen prompt for this week index = randint(1, len(prompts["prompts"]) - 1) promptsToUse = prompts["prompts"][index] prompts["prompts"][index], prompts["prompts"][0] = prompts["prompts"][0], prompts["prompts"][index] #swap prompts settings["prompt"] = promptsToUse else: promptsToUse["prompt"] = "There are not enough prompts. Please submit some!" promptsToUse["author"] = self.bot.user.id settings.pop("prompt", None) try: promptToRemove = promptsToUse promptToRemove.pop("id", None) prompts["prompts"].remove(promptToRemove) except Exception as e: print("Exception:") print(str(e)) with open(serverIDPath + '/prompts.txt', 'w+') as promptFile: json.dump({'prompts': prompts["prompts"]}, promptFile, indent=4) # rewrite prompts.txt with updated list of prompts #print out new prompt userMention = await self.bot.get_user_info(promptsToUse["author"]) await self.bot.send_message(self.bot.get_channel(channel), bold("This week's prompt:\n") + box(promptsToUse["prompt"]) + "Submitted by " + userMention.mention) if(len(priPrompts["priprompts"]) <= 0): settings = {} with open(serverIDPath + '/settings.txt', 'r') as file: try: settings = json.load(file) except ValueError: print("couldn't write settings!") await self.bot.say("ERROR: Composeprompt: promptRestart: Could not get data from settings.txt JSON file!") return True #if there are enough promtps, choose 5 canidate prompts print(str(len(prompts["prompts"])) + " " + str(minPrompts)) if len(prompts["prompts"]) >= minPrompts: #choose 5 more prompts index = randint(0, len(prompts["prompts"]) - 1) await self.bot.send_message(self.bot.get_channel(channel), bold("This week's canidate prompts")) for i in range(1, 6): canidatePrompts.append(prompts["prompts"][(index + i) % len(prompts["prompts"])]) message = await self.bot.send_message(self.bot.get_channel(channel), box(canidatePrompts[i-1]["prompt"])) canidatePrompts[i-1]["id"] = message.id await self.bot.send_message(self.bot.get_channel(channel), bold("Please vote for the prompt you'd like to do next week by reacting to it with a " + str(chr(likeEmoji)) + "!")) #re-write settings settings['settings']['candidateprompts'] = canidatePrompts; else: #at this point, you are running out of prompts await self.bot.send_message(self.bot.get_channel(channel), bold("No canidate prompts for this week. Please submit some ideas for new ones.")) settings['settings'].pop('candidateprompts', None) #set new prompt and re-write settings settings['settings']['prompt'] = promptsToUse with open(serverIDPath + '/settings.txt', 'w+') as file: json.dump({'settings': settings['settings']}, file, indent=4) else: await self.bot.send_message(self.bot.get_channel(channel), "Next week's prompt has already been decided..."); #re-write settings to remove canidateprompts...since there are none settings = {} with open(serverIDPath + '/settings.txt', 'r') as file: try: settings = json.load(file) except ValueError: print("Had trouble writing to settings!") await self.bot.say("ERROR: Composeprompt: promptRestart: Could not write data to settings.txt JSON file!") return True settings['settings'].pop('candidateprompts', None) settings['settings']['prompt'] = promptsToUse with open(serverIDPath + '/settings.txt', 'w+') as file: json.dump({'settings': settings['settings']}, file, indent=4) #restart prompt timer with open(dataPath + '/globalsettings.txt', 'r') as file: try: globalSettings = json.load(file) except ValueError: await self.bot.say("ERROR: Composeprompt: promptRestart: Could not get data from globalsettings.txt JSON file!") print("globalsettings not working") return True isInList = False for x in globalSettings["globalsettings"]["promptstarttimes"]: if x == serverID: isInList = True break #record new time and start new timer if isInList: newTimeStruct = self.convertToStructTime(globalSettings["globalsettings"]["promptstarttimes"][serverID]) globalSettings["globalsettings"]["nextpromptreset"][serverID] = [newTimeStruct.year, newTimeStruct.month, newTimeStruct.day, newTimeStruct.hour, newTimeStruct.minute] with open(dataPath + "/globalsettings.txt", "w+") as settingsFile: json.dump(globalSettings, settingsFile, indent=4) #remove busyfile if os.path.isdir(serverIDPath + busyFile): shutil.rmtree(serverIDPath + busyFile) return True