views.py
import datetime
import math
import discord
from jinja2 import Environment, FileSystemLoader
from configurations import CONFIG
from game_constants import RARITY_COLORS
from search import _
from translations import LANGUAGE_CODE_MAPPING
from util import chunks, flatten
class Views:
WHITE = discord.Color.from_rgb(254, 254, 254)
BLACK = discord.Color.from_rgb(0, 0, 0)
RED = discord.Color.from_rgb(255, 0, 0)
def __init__(self, emojis):
self.my_emojis = emojis
self.jinja_env = Environment(loader=FileSystemLoader('templates'))
def banner_colors(self, banner):
return [f'{self.my_emojis.get(d[0], f":{d[0]}:")}{abs(d[1]) * f"{d[1]:+d}"[0]}' for d in banner['colors']]
def render_embed(self, embed, template_name, **kwargs):
def get_emoji(name, _=None):
cut_name = name[:32]
return self.my_emojis.get(cut_name, cut_name)
self.jinja_env.filters['emoji'] = get_emoji
self.jinja_env.filters['banner_colors'] = self.banner_colors
self.jinja_env.globals.update({
'flatten': flatten,
})
template = self.jinja_env.get_template(template_name)
content = template.render(**kwargs)
for i, split in enumerate(content.split('<T>')):
if i == 0:
embed.description = split
else:
title_end = split.index('</T>')
inline = split.startswith('inline')
embed.add_field(
name=split[inline * len('inline'):title_end],
value=split[title_end + 4:],
inline=inline)
return embed
def render_help(self, prefix, lang):
title = f'garyatrics.com bot {_("[HELP]", lang)}'
e = discord.Embed(title=title, color=self.WHITE)
self.render_embed(e, f'help/help-{lang}.jinja', prefix=prefix)
e.add_field(name=f'__{_("[SUPPORT]", lang)}__:', value='<https://discord.gg/XWs7x3cFTU>')
return e
def render_weapon(self, weapon, shortened, lang):
rarity_color = RARITY_COLORS.get(weapon['raw_rarity'], RARITY_COLORS['Mythic'])
color = discord.Color.from_rgb(*rarity_color)
e = discord.Embed(title='Weapon search found one exact match', color=color)
thumbnail_url = f'{CONFIG.get("graphics_url")}/Spells/Cards_{weapon["spell_id"]}_full.png'
e.set_thumbnail(url=thumbnail_url)
if shortened:
return self.render_embed(e, 'weapon_shortened.jinja', weapon=weapon)
if 'release_date' in weapon:
e.set_footer(text=_('[RELEASE_DATE]', lang))
e.timestamp = weapon["release_date"]
return self.render_embed(e, 'weapon.jinja', weapon=weapon)
def render_affix(self, affix, *__):
e = discord.Embed(title='Affix search found one exact match', color=self.WHITE)
affix['weapons'] = [f'{w["name"]} `#{w["id"]}`' for w in affix['weapons']]
thumbnail_url = f'{CONFIG.get("graphics_url")}/Ingots/Ingots_AnvilIcon_full.png'
e.set_thumbnail(url=thumbnail_url)
return self.render_embed(e, 'affix.jinja', affix=affix)
def render_pet(self, pet, shortened=False, lang='en'):
e = discord.Embed(title='Pet search found one exact match', color=self.WHITE)
thumbnail_url = f'{CONFIG.get("graphics_url")}/Pets/Cards_{pet.filename}_full.png'
e.set_thumbnail(url=thumbnail_url)
if shortened:
return self.render_embed(e, 'pet_shortened.jinja', pet=pet)
if 'release_date' in pet:
e.set_footer(text=_('[RELEASE_DATE]', lang))
e.timestamp = pet.release_date
return self.render_embed(e, 'pet.jinja', pet=pet)
def render_troop(self, troop, shortened, lang):
rarity_color = RARITY_COLORS.get(troop['raw_rarity'], RARITY_COLORS['Mythic'])
if 'Boss' in troop['raw_types']:
rarity_color = RARITY_COLORS['Doomed']
e = discord.Embed(title='Troop search found one exact match', color=discord.Color.from_rgb(*rarity_color))
thumbnail_url = f'{CONFIG.get("graphics_url")}/Troops/Cards_{troop["filename"]}_full.png'
e.set_thumbnail(url=thumbnail_url)
if shortened:
return self.render_embed(e, 'troop_shortened.jinja', troop=troop)
if 'release_date' in troop:
e.set_footer(text=_('[RELEASE_DATE]', lang))
e.timestamp = troop["release_date"]
return self.render_embed(e, 'troop.jinja', troop=troop)
def render_traitstone(self, traitstone, shortened, __):
e = discord.Embed(color=self.WHITE)
e.title = traitstone['name']
thumbnail_url = f'{CONFIG.get("graphics_url")}/Runes_Rune{traitstone["id"]:02d}_full.png'
e.set_thumbnail(url=thumbnail_url)
troops = ['{0} ({1})'.format(*troop) for troop in traitstone['troops']]
chunk_size = 50
troop_chunks = [', '.join(chunk) for chunk in chunks(troops, chunk_size)][:6]
class_list = ['{0} ({1})'.format(*_class) for _class in traitstone['classes']]
classes = self.trim_text_to_length(", ".join(sorted(class_list)), 900, ',', ', ...')
if shortened:
troop_chunks = None
classes = None
kingdom_list = list(traitstone['kingdoms'])
kingdoms = self.trim_text_to_length(", ".join(sorted(kingdom_list)), 900, ',', ', ...')
return self.render_embed(e, 'traitstone.jinja',
traitstone=traitstone,
troops=troops,
troop_chunks=troop_chunks,
chunk_size=chunk_size,
classes=classes,
kingdoms=kingdoms)
def render_talent(self, tree, shortened, __):
e = discord.Embed(color=self.WHITE)
if shortened:
e.title = tree["name"]
return self.render_embed(e, 'talent_shortened.jinja', tree=tree)
e.title = 'Talent search found one exact match'
return self.render_embed(e, 'talent.jinja', tree=tree)
def render_team(self, team, author, shortened, lengthened, title=None):
color = discord.Color.from_rgb(*RARITY_COLORS['Mythic'])
e = discord.Embed(color=color)
if team['banner']:
thumbnail_url = f'{CONFIG.get("graphics_url")}/Banners/Banners_{team["banner"]["filename"]}_full.png'
e.set_thumbnail(url=thumbnail_url)
if shortened:
troops = []
for troop in team['troops']:
addon = ''
if 'affixes' in troop:
addon = self.my_emojis.get('weapon')
troops.append(f'{troop["name"]}{addon}')
e.title = ', '.join(troops)
return self.render_embed(e, 'team_shortened.jinja', team=team)
e.title = f"{author} team"
if title:
e.title = title
template_file = 'team_lengthened.jinja' if lengthened else 'team.jinja'
return self.render_embed(e, template_file, team=team)
def render_kingdom(self, kingdom, shortened, lang):
e = discord.Embed(title='Kingdom search found one exact match', color=self.WHITE)
underworld = 'underworld' if kingdom['underworld'] else ''
thumbnail_url = f'{CONFIG.get("graphics_url")}/Maplocations{underworld}_{kingdom["filename"]}_full.png'
e.set_thumbnail(url=thumbnail_url)
if 'release_date' in kingdom:
e.set_footer(text=_('[RELEASE_DATE]', lang))
e.timestamp = kingdom['release_date']
if shortened:
return self.render_embed(e, 'kingdom_shortened.jinja', kingdom=kingdom)
if kingdom['underworld']:
return self.render_embed(e, 'faction.jinja', kingdom=kingdom)
return self.render_embed(e, 'kingdom.jinja', kingdom=kingdom)
render_faction = render_kingdom
def render_trait(self, trait, *__):
e = discord.Embed(title='Trait search found one exact match', color=self.WHITE)
thumbnail_url = f'{CONFIG.get("graphics_url")}/Troopcardall_Traits/{trait["image"]}_full.png'
e.set_thumbnail(url=thumbnail_url)
trait['thumbnail'] = thumbnail_url
result = self.render_embed(e, 'trait.jinja', trait=trait)
for i, field in enumerate(result.fields):
if len(field.value) > 1024:
result.set_field_at(i, name=field.name, value=f"{field.value[:1020]} ...", inline=field.inline)
return result
def render_class(self, _class, shortened, __):
e = discord.Embed(title='Class search found one exact match', color=self.WHITE)
thumbnail_url = f'{CONFIG.get("graphics_url")}/Classes_{_class["code"]}_full.png'
e.set_thumbnail(url=thumbnail_url)
if shortened:
return self.render_embed(e, 'class_shortened.jinja', _class=_class)
return self.render_embed(e, 'class.jinja', _class=_class)
@staticmethod
def trim_text_to_length(text, limit, break_character='\n', indicator=''):
input_text = f'{text}{break_character}'
trimmed_text = input_text[:input_text[:limit].rfind(break_character)]
if trimmed_text != text:
trimmed_text += indicator
return trimmed_text
@classmethod
def trim_text_lines_to_length(cls, lines, limit, break_character='\n'):
if not lines:
return lines
input_text = break_character.join(lines) + break_character
trimmed_text = cls.trim_text_to_length(input_text, limit)
return trimmed_text.split(break_character)
@classmethod
def trim_news_to_length(cls, text, link, max_length=900):
trimmed_text = cls.trim_text_to_length(text, max_length)
if len(trimmed_text) > max_length:
trimmed_text = cls.trim_text_to_length(text, max_length, break_character=' ')
read_more = ''
if len(trimmed_text) != len(text):
read_more = f'[...]\n\n[Read full news article]({link}).'
return f'{trimmed_text}{read_more}'
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["formatted_end"]} '
if event['end'] == event['start'] + datetime.timedelta(days=1):
end = ''
extra_info = event['extra_info']
if event['raw_type'] in ('[DELVE_EVENT]',):
extra_info = event.get('kingdom', '')
this_line = f'{event["formatted_start"]} ' \
f'{end}' \
f'{event["type"]}' \
f'{":" if extra_info else ""} ' \
f'{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_event_kingdoms(self, events):
e = discord.Embed(title='Upcoming Event Kingdoms', color=self.WHITE)
message_lines = ['```']
message_lines.extend(f'{event["start"].strftime("%b %d")} - '
f'{event["end"].strftime("%b %d")} '
f'{event["kingdom"]}' for event in events)
message_lines = self.trim_text_lines_to_length(message_lines, 900)
message_lines.append('```')
e.add_field(name='Spoilers', value='\n'.join(message_lines))
e.set_footer(text='* Prediction from troop spoilers or future campaigns. Subject to change.')
return e
def render_levels(self, levels):
e = discord.Embed(title='Level progression overview', color=self.WHITE)
return self.render_embed(e, 'levels.jinja', levels=levels)
def render_toplist(self, toplist):
if not toplist:
return discord.Embed(title='Toplist not found.', color=self.BLACK)
e = discord.Embed(title=f'Toplist ID `{toplist["id"]}` by {toplist["author_name"]}', color=self.WHITE)
e.set_footer(text='Last modified')
e.timestamp = toplist['modified']
chunk_size = 3
item_chunks = chunks(toplist['items'], chunk_size)
character_count = 0
for i, chunk in enumerate(item_chunks, start=1):
formatted_chunk = [
f'**{chunk_size * (i - 1) + j}. {self.my_emojis.get(item["color_code"])} {item["name"]}** '
f'({item["kingdom"]} {item["rarity"]}) '
f'{item["spell"]["description"]}'
for j, item in enumerate(chunk, start=1)]
chunk_message = '\n'.join(formatted_chunk)
title = f'__{(i - 1) * chunk_size + 1}...{(i - 1) * chunk_size + len(chunk)}__'
if i == 1:
title = toplist['description']
character_count += len(chunk_message) + len(title)
if character_count < 6000:
e.add_field(name=title, value=chunk_message, inline=False)
return e
def render_my_toplists(self, toplists, author_name):
e = discord.Embed(title='Toplists', color=self.WHITE)
message_lines = [
f'**{toplist["id"]}** {toplist["description"]}' for toplist in toplists
]
if not message_lines:
message_lines = ['No toplists created yet.']
e.add_field(name=f'Overview for {author_name}', value='\n'.join(message_lines), inline=False)
return e
def render_pet_rescue(self, rescue):
lang = rescue.lang
e = self.render_pet(rescue.pet, lang)
e.title = _('[PETRESCUE]', lang)
hours = rescue.time_left // 60
minutes = rescue.time_left % 60
time_left = _('[PETRESCUE_ENDS_IN_HOURS]', lang).replace('%1', f'{hours:02d}').replace('%2', f'{minutes:02d}')
rescue_message = f'{_("[PETRESCUE_OVERVIEW_PETSUBTITLE]", lang)}\n{time_left}'
e.add_field(name=_('[PETRESCUE_HELP_SHORT]', lang), value=rescue_message)
return e
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_permissions(self, channel, permissions):
e = discord.Embed(title=f'Channel Permissions for {channel}', color=self.WHITE)
permission_lines = [f'{v} {k.replace("_", " ").title()}' for k, v in permissions.items()]
e.add_field(name='__Checklist__', value='\n'.join(permission_lines))
return e
def render_quickhelp(self, prefix, lang, languages):
e = discord.Embed(title='Quick Help', color=self.WHITE)
return self.render_embed(e, f'help/quickhelp-{lang}.jinja', prefix=prefix, languages='|'.join(languages))
def render_tower_help(self, prefix, lang):
title = f'{_("[TOWER_OF_DOOM]", lang)} {_("[HELP]", lang)}'
e = discord.Embed(title=title, color=self.WHITE)
lang = LANGUAGE_CODE_MAPPING.get(lang, lang)
return self.render_embed(e, f'help/tower_of_doom-{lang}.jinja', prefix=prefix)
def render_news(self, article):
e = discord.Embed(title=article['title'], color=self.WHITE, url=article['url'])
content = self.transform_news_article(article['content'], article['url'])
self.enrich_author(e, article['author'])
for title, text in content.items():
if len(title) > 256:
title = f'{title[:250]} ...'
if not text:
text = '-'
e.add_field(name=title, value=text, inline=False)
result = [e]
for i, image_url in enumerate(article['images']):
if i >= len(result):
e = discord.Embed(type='image', color=self.WHITE)
e.set_image(url=image_url)
result.append(e)
else:
e = result[i]
e.set_image(url=image_url)
return result
def transform_news_article(self, content, url=''):
# FIXME: the following works around bug reported in:
# https://community.gemsofwar.com/t/news-contain-invalid-html-tags-reported/67756/
# Needs to be removed as soon as the bug is resolved.
content = content.replace('_Scoring_', '\n_Scoring_\n')
text_lines = content.split('\n')
result = {}
field = []
field_title = 'News'
for line in text_lines:
if line.startswith('_') and line.endswith('_'):
if field:
result[field_title] = self.trim_news_to_length('\n'.join(field), link=url)
field = []
field_title = line
else:
field.append(line)
result[field_title] = self.trim_news_to_length('\n'.join(field), link=url)
return result
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_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
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
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_tools(self):
e = discord.Embed(title='Community Tools', color=self.WHITE)
return self.render_embed(e, 'tools.jinja')
def render_my_bookmarks(self, bookmarks, display_name):
e = discord.Embed(title='Bookmarks', color=self.WHITE)
message_lines = [
f'**{bookmark["id"]}** {bookmark["description"]}'
for bookmark in bookmarks
]
if not message_lines:
message_lines = ['No bookmarks created yet.']
e.add_field(name=f'Overview for {display_name}', value='\n'.join(message_lines), inline=False)
return e
@staticmethod
def enrich_author(e, author):
author_details = {
'Nimhain': {
'url': 'https://community.gemsofwar.com/u/Nimhain',
'icon_url': 'https://sea1.discourse-cdn.com/business5/'
'user_avatar/community.gemsofwar.com/nimhain/360/47049_2.png'},
'Saltypatra': {
'url': 'https://community.gemsofwar.com/u/saltypatra/',
'icon_url': 'https://sjc3.discourse-cdn.com/business5/'
'user_avatar/community.gemsofwar.com/saltypatra/360/59750.png'},
}
e.set_author(name=author)
if details := author_details.get(author):
e.set_author(name=author, **details)
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, 'server_status.jinja', status=status['status'])
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_welcome_message(self):
e = discord.Embed(title='Thank you for inviting me!', color=self.WHITE)
return self.render_embed(e, 'welcome.jinja')
def render_ban_message(self, ban):
e = discord.Embed(title='Invalid Server', color=self.RED)
thumbnail_url = f'{CONFIG.get("graphics_url")}/Liveevents/Liveeventscurrencies_skull_full.png'
e.set_thumbnail(url=thumbnail_url)
e.set_footer(text='Ban time')
e.timestamp = ban['ban_time']
return self.render_embed(e, 'ban.jinja', ban=ban)
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 current_event['lore']:
e.add_field(name=f'__{_("[LORE]", lang)}__', value=current_event['lore'])
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)
def render_guilds(self, matching_guilds):
e = discord.Embed(title='List of guilds', color=self.RED)
return self.render_embed(e, 'guilds.jinja', guilds=matching_guilds)
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_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} {description}' for emoji, description in zip(emojis, helps)]
if not active_gems:
active_gems = [_('[QUEST9013_ENDCONV_1]', lang).split('&&')[0]]
return discord.Embed(
title=_('[GEMS]', lang),
description='\n'.join(active_gems),
color=self.WHITE,
)
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)
@staticmethod
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_warbands(self, warbands, lang):
e = discord.Embed(title=_('[WARBANDS]', lang), color=self.WHITE)
return self.render_embed(e, 'warbands.jinja', warbands=warbands)
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_faction_summary(self, factions, lang):
title = f'{_("[FACTIONS]", lang)} ({_("[NAME_A_Z]", lang)})'
e = discord.Embed(title=title, color=self.WHITE)
return self.render_embed(e, 'factions_overview.jinja', factions=factions)
def render_streamers(self):
e = discord.Embed(title='Streamers', colour=self.WHITE)
return self.render_embed(e, 'streamers.jinja')
def render_hoard_potions(self, potions, lang):
e = discord.Embed(title=f'{_("[TREASURE_HOARD]", lang)} {_("[POTIONS_TEXT]", lang)}', colour=self.WHITE)
texts = {
'hoard_level': _('[HOARD_LEVEL]', lang),
}
return self.render_embed(e, 'hoard_potions.jinja', potions=potions, texts=texts)
def render_communities(self):
e = discord.Embed(title='Communities', colour=self.WHITE)
return self.render_embed(e, 'communities.jinja')
def render_pet_rescue_stats(self, stats, rescues, _):
e = discord.Embed(title='Pet Rescue Stats', colour=self.WHITE)
e.set_footer(text=f'{rescues} pets were brutally slaughtered by whole guilds in the making of this analysis.')
e = self.render_embed(e, 'pet_rescue_stats.jinja', stats=stats)
e.description = "\n".join(self.trim_text_lines_to_length(e.description.split('\n'), 4096))
return e
def render_all_talents(self, talents, __):
talent_list = [t['name'] for t in talents]
return discord.Embed(title=_('[TALENTS]'), description='\n'.join(talent_list), colour=self.WHITE)
def render_dungeon_features(self, items, lang):
e = discord.Embed(title=_('[DUNGEON]', lang), colour=self.WHITE)
return self.render_embed(e, "dungeon.jinja", items=items)
def render_summoning_stones(self, title, stones, lang):
e = discord.Embed(title=title, description=_('[SUMMONING_STONE_DESC]', lang), color=self.WHITE)
for category, troops in stones.items():
message_lines = '\n'.join([f'{t["count"]}x {self.my_emojis.get(t["rarity"])} {t["name"]}' for t in troops])
e.add_field(name=category, value=message_lines, inline=True)
e.set_footer(text=_('[SUMMONING_STONE_MENU_TIP]', lang))
return e
def render_banners(self, banners, lang):
result = []
half_length = len(banners) // 2
for i, split_banners in enumerate((banners[:half_length], banners[half_length:])):
e = discord.Embed(title=f'{_("[BANNERS]", lang)} ({i + 1}/2)',
description=_('[REWARD_HELP_DESC_BANNER]', lang),
color=self.WHITE)
result.append(self.render_embed(e, "banners.jinja", banners=split_banners, offset=i * half_length))
return result
def render_orbs(self, orbs, lang):
e = discord.Embed(title=_('[ORBS]', lang), colour=self.WHITE)
return self.render_embed(e, "orbs.jinja", orbs=orbs)
def render_medals(self, medals, lang):
e = discord.Embed(title=_('[BADGES_AND_MEDALS]', lang), colour=self.WHITE)
return self.render_embed(e, "medals.jinja", medals=medals)