async def campaign(self, message, lang, tier=None, **kwargs): campaign_data = self.expander.get_campaign_tasks(lang, tier) if not campaign_data['has_content']: title = _('[NO_CURRENT_TASK]', lang) description = _('[CAMPAIGN_COMING_SOON]', lang) e = discord.Embed(title=title, description=description, color=self.WHITE) return await self.answer(message, e) for category, tasks in campaign_data['campaigns'].items(): category_lines = [ f'**{task["title"]}**: {task["name"].replace("-->", "→")}' for task in tasks ] color = CAMPAIGN_COLORS.get(category, self.WHITE) skip_costs = f'{_("[SKIP_TASK]", lang)}: {TASK_SKIP_COSTS.get(category)} {_("[GEMS]", lang)}' e = discord.Embed( title=f'__**{_(category, lang)}**__ ({skip_costs})', description='\n'.join(category_lines), color=color) if any(['`?`' in line for line in category_lines]): e.set_footer(text=f'[?]: {_("[IN_PROGRESS]", lang)}') await self.answer(message, e, no_interaction=True)
def render_pet_rescue_config(self, config, lang): on = _('[ON]', lang) off = _('[OFF]', lang) pretty_display = { 'mention': '**Who gets mentioned?** `mention =', 'delete_pet': '**Deletion of the pet info** `delete_pet =', 'delete_mention': '**Deletion of the mention** `delete_mention =', 'delete_message': '**Deletion of the original request message¹** `delete_message =', } def translate_value(value): if value is False: return off elif value is True: return on return value answer = '\n'.join([ f'{pretty_display[key]} {translate_value(value)}`' for key, value in config.items() ]) e = discord.Embed(title=_('[PETRESCUE]', lang), color=self.WHITE) e.add_field(name=_('[SETTINGS]', lang), value=answer) e.set_footer( text= '¹ needs "Manage Messages" permission, or will react with ⛔ emoji.' ) return e
def render_events(self, events, _filter, lang): e = discord.Embed(title=_('[EVENTS]', lang), color=self.WHITE) message_lines = [] last_event_date = events[0]['start'] for event in events: if event['start'] > last_event_date and event['start'].weekday( ) == 0 and not _filter: message_lines.append('') last_event_date = event['start'] end = f'- {event["end"].strftime("%b %d")} ' if event['end'] == event['start'] + datetime.timedelta(days=1): end = '' this_line = f'{event["start"].strftime("%b %d")} ' \ f'{end}' \ f'{event["type"]}' \ f'{":" if event["extra_info"] else ""} ' \ f'{event["extra_info"]}' if not _filter or _filter.lower() in this_line.lower(): message_lines.append(this_line) message_lines = self.trim_text_lines_to_length(message_lines, 894) if not message_lines: message_lines = [ _('[QUEST9052_ENDCONV_0]', lang).replace('&& ', '\n') ] message_lines = ['```'] + message_lines + ['```'] e.add_field(name=_('[CALENDAR]', lang), value='\n'.join(message_lines)) return e
def render_storms(storms, lang): contents = [_('[TROOPHELP_STORM_2]', lang), ''] contents.extend( f'**{storm_data["name"]}**: {storm_data["description"]}' for storm_id, storm_data in storms.items() ) return discord.Embed(title=_('[TROOPHELP_STORM_1]', lang), description='\n'.join(contents))
def render_pet_rescue(self, rescue): lang = rescue.lang e = self.render_pet(rescue.pet, lang) e.title = _('[PETRESCUE]', lang) time_left = _('[PETRESCUE_ENDS_IN_HOURS]', lang).replace('%1', '00').replace('%2', f'{rescue.time_left:02d}') rescue_message = f'{_("[PETRESCUE_OVERVIEW_PETSUBTITLE]", lang)}\n{time_left}' e.add_field(name=_('[PETRESCUE_HELP_SHORT]', lang), value=rescue_message) return e
async def about(self, message, lang, **kwargs): color = discord.Color.from_rgb(*RARITY_COLORS['Mythic']) e = discord.Embed(title=_('[INFO]', lang), description='<https://garyatrics.com/>', color=color) e.set_thumbnail(url=self.user.avatar_url) version_title = _('[SETTINGS_VERSION_NO]', lang).replace(':', '') e.add_field(name=f'__{version_title}__:', value=self.VERSION, inline=False) with HumanizeTranslator(LANGUAGE_CODE_MAPPING.get(lang, lang)) as _t: offline = humanize.naturaldelta(self.downtimes) start_time = humanize.naturaltime(self.bot_start) e.add_field(name=f'__{_("[START]", lang)}__:', value=start_time) e.add_field(name=f'__{_("[OFF]", lang)}__:', value=offline) bot_runtime = datetime.datetime.now() - self.bot_start availability = (bot_runtime - self.downtimes) / bot_runtime e.add_field(name=f'__{_("[AVAILABLE]", lang)}__:', value=f'{availability:.3%}') slash_invite = self.invite_url.replace('scope=bot', 'scope=applications.commands') e.add_field( name=f'__{_("[INVITE]", lang)}__:', value= f'[Bot]({self.invite_url}) / [Slash Commands]({slash_invite})', inline=False) admin_invite = self.invite_url.split( 'permissions')[0] + 'permissions=8' admin_slash_invite = admin_invite.replace( 'scope=bot', 'scope=applications.commands') e.add_field( name=f'__{_("[INVITE]", lang)} ({_("[ADMIN]", lang)})__:', value= f'[Bot]({admin_invite}>) / [Slash Commands]({admin_slash_invite})', inline=False) my_prefix = self.prefix.get(message.guild) e.add_field(name=f'__{_("[HELP]", lang)}__:', value=f'`{my_prefix}help` / `{my_prefix}quickhelp`', inline=False) e.add_field(name=f'__{_("[SUPPORT]", lang)}__:', value='<https://discord.gg/XWs7x3cFTU>', inline=False) github = self.my_emojis.get('github') gold = self.my_emojis.get('gold') contribute = f'{gold} <https://www.buymeacoffee.com/garyatrics>\n' \ f'{github} <https://github.com/maduck/GoWDiscordTeamBot>' e.add_field(name=f'__{_("[CONTRIBUTE]", lang)}__:', value=contribute, inline=False) await self.answer(message, e)
async def waffles(self, message, lang, **kwargs): waffle_no = random.randint(0, 66) title = _('[QUEST9480_OBJ0_MSG]', lang) subtitle = _('[HAND_FEED]', lang) image_no = f'{_("[SPELLEFFECT_CAUSERANDOM]", lang)} #{waffle_no}' e = self.generate_response(title, self.WHITE, subtitle, image_no) e.set_image( url=f'https://garyatrics.com/images/waffles/{waffle_no:03d}.jpg') await self.answer(message, e)
def render_current_event(self, current_event, lang): title = f'{_("[WEEKLY_EVENT]", lang)}: {current_event["name"]}' e = discord.Embed(title=title, color=self.WHITE) if 'kingdom' in current_event: thumbnail_url = f'{CONFIG.get("graphics_url")}/Maplocations_{current_event["kingdom"]["filename"]}_full.png' e.set_thumbnail(url=thumbnail_url) event_ending = { 'en': 'Event ending on', 'de': 'Event endet am', 'fr': 'Evénement se terminant le', 'it': 'Evento che termina il', 'es': 'Evento que finaliza el', 'ru': 'Завершение события', 'zh': '活动结束时间', }.get(lang, '') e.set_footer(text=event_ending) e.timestamp = current_event['end'] data = { 'event': current_event, 'lore_title': _('[LORE]', lang), 'kingdom_title': _('[KINGDOM]', lang), 'overview': _('[OVERVIEW]', lang), 'score': _('[SCORE]', lang), 'medals': _('[MEDALS]', lang), 'troop_restrictions': _('[TROOP_RESTRICTIONS]', lang), 'event_troop': _('[EVENT_TROOP]', lang), 'event_color': _('[FILTER_MANACOLOR]', lang), 'event_weapon': f'{_("[GLOG_EVENT]", lang)} {_("[WEAPON]", lang)}', 'rewards': _('[REWARDS]', lang), } return self.render_embed(e, 'current_event.jinja', **data)
def render_active_gems(self, gems, lang): emojis = [self.my_emojis.get(gem['gem_type'], gem['gem_type']) for gem in gems] helps = [gem['tutorial'] for gem in gems] active_gems = [f'{emoji} {help}' for emoji, help in zip(emojis, helps)] if not active_gems: active_gems = [_('[QUEST9013_ENDCONV_1]', lang).split('&&')[0]] return discord.Embed( title=_('[GEMS]', lang), description=' '.join(active_gems), color=self.WHITE, )
async def stats(self, message, lang, **kwargs): color = discord.Color.from_rgb(*RARITY_COLORS['Mythic']) e = discord.Embed(title=_('[PVPSTATS]', lang), description='<https://garyatrics.com/>', color=color) collections = [ f'**{_("[GUILD]", lang)} {_("[AMOUNT]", lang)}**: {len(self.guilds)}', f'**{_("[NEWS]", lang)} {_("[CHANNELS]", lang)} (PC)**: {sum([s.get("pc", True) for s in self.subscriptions])}', f'**{_("[NEWS]", lang)} {_("[CHANNELS]", lang)} (Switch)**: {sum([s.get("switch", True) for s in self.subscriptions])}', f'**{_("[PETRESCUE]", lang)} ({_("[JUST_NOW]", lang)})**: {len(self.pet_rescues)}', ] e.add_field(name=_("[COLLECTION]", lang), value='\n'.join(collections)) await self.answer(message, e)
def render_class_level(self, lower_level, upper_level, xp_required, speeds, lang): title = f'{_("[CHAMPION_LEVEL_N]", lang)}'.replace('%1', f'{lower_level} - {upper_level}') e = discord.Embed(title=title, color=self.WHITE) name = f'{_("[CHAMPION_LEVEL]", lang)} {_("[XP]", lang)}' xp = f'{xp_required} {_("[XP]", lang)}' e.add_field(name=name, value=xp) xp_speed = _('[N_MINUTE]', lang).replace('%1', f'{_("[XP]", lang)} / ') hours = _('[N_HOURS]', lang) for i, (xp_per_min, time) in enumerate(speeds.items()): name = _(f'[ANIMATION_SPEED_{i}]', lang) value = f'{xp_per_min} {xp_speed}: **{hours.replace("%1", time)}**' e.add_field(name=name, value=value, inline=False) e.set_footer(text=_('[CHAMPION_XP_INFO]', lang)) return e
def render_color_kingdoms(self, kingdoms, lang): top_n = _('[TOP_N]', lang) mana_color_troop = _('[COLOR_TROOP]', lang) top_kingdoms = top_n.replace('%1%', _('[KINGDOMS]', lang)) title = f'{top_kingdoms} ({mana_color_troop})' e = discord.Embed(title=title, color=self.WHITE) for color_code, kingdom in kingdoms.items(): color = self.my_emojis.get(color_code, color_code) name = f'{color} __{kingdom["name"]}__ ({kingdom["percentage"]:0.0%})' color_name = _(f'[GEM_{color_code.upper()}]', lang) troops_title = _('[N_TROOPS]', lang).replace('%1', color_name) value = f'**{_("[TOTAL_TROOPS]", lang)}**: {kingdom["total"]}\n' \ f'**{troops_title}**: {kingdom["fitting_troops"]}' e.add_field(name=name, value=value) return e
def render_server_status(self, status): e = discord.Embed(title=_('[SERVER_STATUS]'), color=self.WHITE) e.timestamp = status['last_updated'] e.set_footer(text='Last Updated') return self.render_embed(e, f'server_status.jinja', status=status['status'])
async def set_pet_rescue_config(self, message, key, value, lang, **kwargs): key = key.lower() valid_keys = self.pet_rescue_config.get(message.channel).keys() if key not in valid_keys: answer = f'Error: `{key}` is not a valid setting for pet rescues.\n' \ f'Try one of those: `{"`, `".join(valid_keys)}`' e = self.generate_response(_('[PETRESCUE]', lang), self.BLACK, _("[SETTINGS]", lang), answer) return await self.answer(message, e) guild = message.guild channel = message.channel on = _('[ON]', lang) yes = _('[YES]', lang) translated_trues = [on.lower(), yes.lower()] await self.pet_rescue_config.update(guild, channel, key, value, translated_trues) await self.show_pet_rescue_config(message, lang)
async def waffles(self, message, lang, waffle_no, **kwargs): random_title = _('[SPELLEFFECT_CAUSERANDOM]', lang) max_waffles = 67 if waffle_no and waffle_no.isdigit( ) and 1 <= int(waffle_no) <= max_waffles: waffle_no = int(waffle_no) image_no = f'~~{random_title}~~ #{waffle_no}' else: waffle_no = random.randint(0, max_waffles) image_no = f'{random_title} #{waffle_no}' title = _('[QUEST9480_OBJ0_MSG]', lang) subtitle = _('[HAND_FEED]', lang) e = self.generate_response(title, self.WHITE, subtitle, image_no) url = f'https://garyatrics.com/images/waffles/{waffle_no:03d}.jpg' e.set_image(url=url) await self.answer(message, e)
def render_drop_chances(self, drop_chances, lang): chest = _('[CHEST]', lang) drop_rates = _('[DROP_RATES]', lang) e = discord.Embed(title=f'{chest} {drop_rates}', color=self.WHITE) for chest_type, drops in drop_chances.items(): field_lines = [] for category, items in drops.items(): if items: field_lines.append(f'**__{category}__**') for item, chances in sorted(items.items(), key=lambda x: x[1]['chance'], reverse=True): multiplier = chances.get('multiplier', '') if multiplier: multiplier = f' (x{multiplier})' field_lines.append(f'{item}{multiplier}: {chances["chance"]}%') e.add_field(name=chest_type, value='\n'.join(field_lines)) e.set_footer(text='*' + _('[KEYTYPE_5_SHORT_DESCRIPTION]', lang).replace('%1', '0')) return e
def render_adventure_board(self, adventures, lang): highest_rarity = max(a['raw_rarity'] for a in adventures) color = list(RARITY_COLORS.values())[highest_rarity] e = discord.Embed(title=_('[ADVENTURE_BOARD]', lang), color=discord.Color.from_rgb(*color)) for adventure in adventures: reward_emojis = [self.my_emojis.get(t.lower()[1:-1], '') for t in adventure['reward_types']] name = f'{"".join(reward_emojis)} __{adventure["name"]}__ ({adventure["rarity"]})' rewards = ', '.join([f'{v} {k}' for k, v in adventure['rewards'].items()]) e.add_field(name=name, value=rewards, inline=False) now = datetime.datetime.utcnow() reset_time = now.replace(hour=7, minute=0, second=0, microsecond=0) time_left = reset_time + datetime.timedelta(hours=24) - now hours = time_left.seconds // 3600 minutes = time_left.seconds // 60 - hours * 60 footer = _('[DAILY_ADVENTURES_RESET_IN]', lang).replace('%1', str(hours)).replace('%2', str(minutes)) e.set_footer(text=footer) return e
async def show_campaign_tasks(self, message, lang, tier, **kwargs): campaign_data = self.expander.get_campaign_tasks(lang, tier) if not campaign_data['has_content']: title = _('[NO_CURRENT_TASK]', lang) description = _('[CAMPAIGN_COMING_SOON]', lang) e = discord.Embed(title=title, description=description, color=self.WHITE) return await self.answer(message, e) for category, tasks in campaign_data['campaigns'].items(): category_lines = [ f'**{task["title"]}**: {task["name"]}' for task in tasks ] color = CAMPAIGN_COLORS.get(category, self.WHITE) e = discord.Embed(title=f'__**{category}**__', description='\n'.join(category_lines), color=color) await self.answer(message, e)
def render_type_kingdoms(self, kingdoms, lang): top_n = _('[TOP_N]', lang) troop_type = _('[FILTER_TROOPTYPE]', lang) top_kingdoms = top_n.replace('%1%', _('[KINGDOMS]', lang)) title = f'{top_kingdoms} ({troop_type})' e = discord.Embed(title=title, color=self.WHITE) half_size = math.ceil(len(kingdoms) / 2) chunked_kingdoms = chunks(kingdoms, half_size) for i, chunk in enumerate(chunked_kingdoms, start=0): chunk_title = _('[TROOP_TYPES]', lang) start = i * half_size + 1 end = i * half_size + len(chunk) title = f'{chunk_title} {start:n} - {end:n}' field_lines = [ f'{troop_type} __{kingdom["name"]}__ ({kingdom["percentage"]:0.0%})' for troop_type, kingdom in chunk] e.add_field(name=title, value='\n'.join(field_lines)) return e
async def memes(self, message, lang, meme_no, **kwargs): base_url = 'https://garyatrics.com/images/memes' r = requests.get(f'{base_url}/index.txt') available_memes = [m for m in r.text.split('\n') if m] random_title = _('[SPELLEFFECT_CAUSERANDOM]', lang) if meme_no and 1 <= int(meme_no) <= len(available_memes): meme = available_memes[int(meme_no) - 1] image_no = f'~~{random_title}~~ meme `#{int(meme_no)}`' else: meme_no = random.randint(0, len(available_memes) - 1) meme = available_memes[meme_no] image_no = f'{random_title} meme `#{meme_no}`' title = _('[Troop_K02_07_DESC]', lang) subtitle = _(f'[FUNNY_LOAD_TEXT_{random.randint(0, 19)}]', lang) meme = urllib.parse.quote(meme) url = f'{base_url}/{meme}' e = self.generate_response(title, self.WHITE, subtitle, image_no) e.set_image(url=url) await self.answer(message, e)
async def class_summary(self, message, lang, **kwargs): result = self.expander.class_summary(lang) table = prettytable.PrettyTable() table.field_names = [ _('[NAME_A_Z]', lang), _('[FILTER_TROOPTYPE]', lang), _('[FILTER_KINGDOMS]', lang) ] table.align = 'l' table.hrules = prettytable.HEADER table.vrules = prettytable.NONE [ table.add_row( [_class['name'], _class['type_short'], _class['kingdom']]) for _class in result ] e = await self.generate_embed_from_text(table.get_string().split('\n'), _('[CLASS]', lang), _('[OVERVIEW]', lang)) await self.answer(message, e)
async def kingdom_summary(self, message, lang, **kwargs): result = self.expander.kingdom_summary(lang) table = prettytable.PrettyTable() table.field_names = [ _('[NAME_A_Z]', lang), _('[TROOPS]', lang), _('[FACTIONS]', lang), ] table.align = 'l' table.hrules = prettytable.HEADER table.vrules = prettytable.NONE [ table.add_row([ kingdom['name'], len(kingdom['troops']), kingdom['linked_kingdom'] or '-' ]) for kingdom in result ] e = await self.generate_embed_from_text(table.get_string().split('\n'), _('[KINGDOMS]', lang), _('[OVERVIEW]', lang)) await self.answer(message, e)
def render_effects(self, effects, lang): title = f'{_("[OVERVIEW]", lang)}: {_("[FILTER_SPELLEFFECT]", lang)}' e = discord.Embed(title=title, color=self.WHITE) chunk_size = 5 for category, c_effects in effects.items(): chunked_effects = chunks(c_effects, chunk_size=chunk_size) for i, chunk in enumerate(chunked_effects, start=0): chunk_title = _(category, lang) start = i * chunk_size + 1 end = i * chunk_size + len(chunk) title = f'{chunk_title} {start:n} - {end:n}' field_lines = [ f'**{effect["name"]}**: {effect["description"]}' for effect in chunk] e.add_field(name=title, value='\n'.join(field_lines), inline=False) return e
def render_weekly_summary(self, summary, lang): title = f'{_("[ROSTER_WEEKLY]", lang)} {_("[OVERVIEW]", lang)} ' \ f'({summary["world_event"]["formatted_start"]} - {summary["world_event"]["formatted_end"]})' e = discord.Embed(title=title, color=self.WHITE) e.set_footer(text=_('[CREATED_BY_HAWX_AND_GARY]', lang)) return self.render_embed(e, 'weekly_summary.jinja', summary=summary)
def render_warbands(self, warbands, lang): e = discord.Embed(title=_('[WARBANDS]', lang), color=self.WHITE) return self.render_embed(e, 'warbands.jinja', warbands=warbands)
def render_heroic_gems(self, gems, lang): e = discord.Embed(title=_('[GEMS]', lang), color=self.WHITE) return self.render_embed(e, 'heroic_gems.jinja', gems=gems)
def render_current_event(self, current_event, shortened, lengthened, lang): title = f'{_("[WEEKLY_EVENT]", lang)}: {current_event["name"]}' e = discord.Embed(title=title, color=self.WHITE) if 'kingdom' in current_event: thumbnail_url = f'{CONFIG.get("graphics_url")}/Maplocations_{current_event["kingdom"]["filename"]}_full.png' e.set_thumbnail(url=thumbnail_url) event_ending = { 'en': 'Event ending on', 'de': 'Event endet am', 'fr': 'Evénement se terminant le', 'it': 'Evento che termina il', 'es': 'Evento que finaliza el', 'ru': 'Завершение события', 'zh': '活动结束时间', }.get(lang, '') e.set_footer(text=event_ending) e.timestamp = current_event['end'] data = { 'event': current_event, 'lore_title': _('[LORE]', lang), 'kingdom_title': _('[KINGDOM]', lang), 'overview': _('[OVERVIEW]', lang), 'score': _('[SCORE]', lang), 'medals': _('[MEDALS]', lang), 'troop_restrictions': _('[TROOP_RESTRICTIONS]', lang), 'weapon_title': _('[WEAPON]', lang), 'event_troop': _('[EVENT_TROOP]', lang), 'event_color': _('[FILTER_MANACOLOR]', lang), 'event_weapon': f'{_("[GLOG_EVENT]", lang)} {_("[WEAPON]", lang)}', 'rewards': _('[REWARDS]', lang), 'points': _('[POINTS]', lang), 'calculated_score_title': _('[CALCULATED_SCORE_TITLE]', lang), 'points_needed': _('[POINTS_NEEDED]', lang).format(current_event['score_per_member'], _('[POINTS]', lang)), 'battles_needed': _('[BATTLES_NEEDED]', lang).format(current_event['minimum_battles'], _('[BATTLES]', lang)), 'tier_needed': _('[TIER_NEEDED]', lang).format(f'{_("[TIER]", lang)} {current_event["minimum_tier"]}') } template_file = 'current_event.jinja' if shortened: template_file = 'current_event_shortened.jinja' elif lengthened: template_file = 'current_event_lengthened.jinja' return self.render_embed(e, template_file, **data)