reorganize and move variables to bot object

pull/1/head
qwewqa 4 years ago
parent f5042ee19c
commit 2aac31c099
  1. 4
      export_assets.py
  2. 7
      main.py
  3. 0
      miyu_bot/bot/aliases/event.py
  4. 17
      miyu_bot/bot/bot.py
  5. 22
      miyu_bot/bot/master_asset_manager.py
  6. 58
      miyu_bot/bot/name_aliases.py
  7. 26
      miyu_bot/commands/cogs/card.py
  8. 25
      miyu_bot/commands/cogs/event.py
  9. 27
      miyu_bot/commands/cogs/music.py
  10. 5
      miyu_bot/commands/cogs/utility.py
  11. 4
      miyu_bot/commands/common/argument_parsing.py
  12. 1
      miyu_bot/commands/common/emoji.py
  13. 19
      miyu_bot/commands/common/event.py
  14. 40
      miyu_bot/commands/common/name_aliases.py

@ -1,11 +1,9 @@
import hashlib
import shutil import shutil
from pathlib import Path from pathlib import Path
from d4dj_utils.manager.asset_manager import AssetManager from d4dj_utils.manager.asset_manager import AssetManager
from d4dj_utils.master.master_asset import MasterAsset
from miyu_bot.commands.common.master_asset_manager import MasterFilterManager, hash_master from miyu_bot.bot.master_asset_manager import hash_master
def main(): def main():

@ -3,20 +3,19 @@ import logging
import discord import discord
from d4dj_utils.manager.asset_manager import AssetManager from d4dj_utils.manager.asset_manager import AssetManager
from discord.ext import commands
from miyu_bot.commands.common.master_asset_manager import MasterFilterManager from miyu_bot.bot.bot import D4DJBot
from miyu_bot.bot.master_asset_manager import MasterFilterManager
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
with open('config.json') as f: with open('config.json') as f:
bot_token = json.load(f)['token'] bot_token = json.load(f)['token']
bot = commands.Bot(command_prefix='!', case_insensitive=True)
asset_manager = AssetManager('assets') asset_manager = AssetManager('assets')
bot = D4DJBot(asset_manager, MasterFilterManager(asset_manager), command_prefix='!', case_insensitive=True)
masters = MasterFilterManager(asset_manager)
bot.load_extension('miyu_bot.commands.cogs.card') bot.load_extension('miyu_bot.commands.cogs.card')
bot.load_extension('miyu_bot.commands.cogs.event') bot.load_extension('miyu_bot.commands.cogs.event')

@ -0,0 +1,17 @@
from d4dj_utils.manager.asset_manager import AssetManager
from discord.ext import commands
from miyu_bot.bot.master_asset_manager import MasterFilterManager
from miyu_bot.bot.name_aliases import NameAliases
class D4DJBot(commands.Bot):
assets: AssetManager
asset_filters: MasterFilterManager
aliases: NameAliases
def __init__(self, assets, asset_filters, *args, **kwargs):
self.assets = assets
self.asset_filters = asset_filters
self.aliases = NameAliases(assets)
super().__init__(*args, **kwargs)

@ -1,13 +1,12 @@
import hashlib import hashlib
from functools import lru_cache
from timeit import default_timer
from typing import Callable, Any, Optional, Union from typing import Callable, Any, Optional, Union
from d4dj_utils.manager.asset_manager import AssetManager from d4dj_utils.manager.asset_manager import AssetManager
from d4dj_utils.master.event_master import EventMaster, EventState
from d4dj_utils.master.master_asset import MasterDict, MasterAsset from d4dj_utils.master.master_asset import MasterDict, MasterAsset
from discord.ext import commands from discord.ext import commands
from miyu_bot.commands.common.aliases.event import event_aliases from miyu_bot.bot.aliases.event import event_aliases
from miyu_bot.commands.common.fuzzy_matching import FuzzyFilteredMap, romanize from miyu_bot.commands.common.fuzzy_matching import FuzzyFilteredMap, romanize
import datetime as dt import datetime as dt
@ -22,7 +21,7 @@ class MasterFilterManager:
filter_function=lambda m: m.is_released, filter_function=lambda m: m.is_released,
fallback_naming_function=lambda m: m.id, fallback_naming_function=lambda m: m.id,
) )
self.events = MasterFilter( self.events = EventFilter(
self.manager.event_master, self.manager.event_master,
aliases=event_aliases, aliases=event_aliases,
naming_function=lambda e: e.name, naming_function=lambda e: e.name,
@ -99,6 +98,21 @@ class MasterFilter:
return self.default_filter.values() return self.default_filter.values()
class EventFilter(MasterFilter):
def get_latest_event(self, ctx: commands.Context) -> EventMaster:
"""Returns the oldest event that has not ended or the newest event otherwise."""
try:
# NY event overlapped with previous event
return min((v for v in self.values(ctx) if v.state() == EventState.Open),
key=lambda e: e.start_datetime)
except ValueError:
try:
return min((v for v in self.values(ctx) if v.state() < EventState.Ended),
key=lambda e: e.start_datetime)
except ValueError:
return max(self.values(ctx), key=lambda v: v.start_datetime)
def hash_master(master: MasterAsset): def hash_master(master: MasterAsset):
return hashlib.md5(master.extended_description().encode('utf-8')).hexdigest() return hashlib.md5(master.extended_description().encode('utf-8')).hexdigest()

@ -0,0 +1,58 @@
from functools import cached_property
from d4dj_utils.manager.asset_manager import AssetManager
class NameAliases:
assets: AssetManager
def __init__(self, assets):
self.assets = assets
@cached_property
def characters_by_name(self):
characters_by_name = {}
for character in self.assets.character_master.values():
for name in character.full_name_english.split():
characters_by_name[name.lower()] = character
return characters_by_name
@cached_property
def attributes_by_name(self):
return {attribute.en_name: attribute for attribute in self.assets.attribute_master.values()}
@cached_property
def units_by_name(self):
units_by_name = {unit.name.lower().replace(' ', '_'): unit for unit in self.assets.unit_master.values()}
units_by_name['rondo'] = units_by_name['燐舞曲']
units_by_name['special'] = units_by_name['スペシャル']
units_by_name['other'] = units_by_name['その他']
return units_by_name
unit_aliases = {
'happyaround': 'happy_around!',
'happy_around': 'happy_around!',
'hapiara': 'happy_around!',
'happy': 'happy_around!',
'ha': 'happy_around',
'peakyp-key': 'peaky_p-key',
'peakypkey': 'peaky_p-key',
'peaky': 'peaky_p-key',
'p-key': 'peaky_p-key',
'pkey': 'peaky_p-key',
'pkpk': 'peaky_p-key',
'pk': 'peaky_p-key',
'photonmaiden': 'photon_maiden',
'photome': 'photon_maiden',
'photon': 'photon_maiden',
'pm': 'photon_maiden',
'mermaid': 'merm4id',
'mmd': 'merm4id',
'lyricallily': 'lyrical_lily',
'riririri': 'lyrical_lily',
'lililili': 'lyrical_lily',
'lily': 'lyrical_lily',
'lili': 'lyrical_lily',
'll': 'lyrical_lily',
'fuhifumi': 'lyrical_lily',
}

@ -4,24 +4,23 @@ import logging
import discord import discord
from d4dj_utils.master.card_master import CardMaster from d4dj_utils.master.card_master import CardMaster
from d4dj_utils.master.event_master import EventMaster
from d4dj_utils.master.event_specific_bonus_master import EventSpecificBonusMaster from d4dj_utils.master.event_specific_bonus_master import EventSpecificBonusMaster
from d4dj_utils.master.skill_master import SkillMaster from d4dj_utils.master.skill_master import SkillMaster
from discord.ext import commands from discord.ext import commands
from main import masters, asset_manager from miyu_bot.bot.bot import D4DJBot
from miyu_bot.commands.common.argument_parsing import ParsedArguments, parse_arguments, ArgumentError from miyu_bot.commands.common.argument_parsing import ParsedArguments, parse_arguments, ArgumentError
from miyu_bot.commands.common.emoji import rarity_emoji_ids, attribute_emoji_ids_by_attribute_id, \ from miyu_bot.commands.common.emoji import rarity_emoji_ids, attribute_emoji_ids_by_attribute_id, \
unit_emoji_ids_by_unit_id, parameter_bonus_emoji_ids_by_parameter_id unit_emoji_ids_by_unit_id, parameter_bonus_emoji_ids_by_parameter_id
from miyu_bot.commands.common.event import get_latest_event
from miyu_bot.commands.common.formatting import format_info from miyu_bot.commands.common.formatting import format_info
from miyu_bot.commands.common.master_asset_manager import hash_master from miyu_bot.bot.master_asset_manager import hash_master
from miyu_bot.commands.common.name_aliases import characters_by_name, attributes_by_name, units_by_name, unit_aliases
from miyu_bot.commands.common.reaction_message import run_tabbed_message, run_reaction_message, run_paged_message from miyu_bot.commands.common.reaction_message import run_tabbed_message, run_reaction_message, run_paged_message
class Card(commands.Cog): class Card(commands.Cog):
def __init__(self, bot: commands.Bot): bot: D4DJBot
def __init__(self, bot):
self.bot = bot self.bot = bot
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
@ -123,17 +122,20 @@ class Card(commands.Cog):
# Not used, but here because it's a valid argument before running require_all_arguments_used. # Not used, but here because it's a valid argument before running require_all_arguments_used.
display, _ = arguments.single(['display', 'disp'], sort, allowed_operators=['='], display, _ = arguments.single(['display', 'disp'], sort, allowed_operators=['='],
converter=card_attribute_aliases) converter=card_attribute_aliases)
characters = {characters_by_name[c].id for c in arguments.words(characters_by_name.keys())} characters = {self.bot.aliases.characters_by_name[c].id
units = {units_by_name[unit].id for c in arguments.words(self.bot.aliases.characters_by_name.keys())}
for unit in arguments.tags(names=units_by_name.keys(), aliases=unit_aliases)} units = {self.bot.aliases.units_by_name[unit].id
for unit in arguments.tags(names=self.bot.aliases.units_by_name.keys(),
aliases=self.bot.aliases.unit_aliases)}
rarity_names = ['4*', '3*', '2*', '1*', r'4\*', r'3\*', r'2\*', r'1\*'] rarity_names = ['4*', '3*', '2*', '1*', r'4\*', r'3\*', r'2\*', r'1\*']
rarities = {int(r[0]) for r in arguments.words(rarity_names) | arguments.tags(rarity_names)} rarities = {int(r[0]) for r in arguments.words(rarity_names) | arguments.tags(rarity_names)}
attributes = {attributes_by_name[a].id for a in arguments.tags(attributes_by_name.keys())} attributes = {self.bot.aliases.attributes_by_name[a].id
for a in arguments.tags(self.bot.aliases.attributes_by_name.keys())}
event_bonus = bool(arguments.tags(['event', 'eventbonus', 'event_bonus'])) event_bonus = bool(arguments.tags(['event', 'eventbonus', 'event_bonus']))
if event_bonus: if event_bonus:
latest_event = get_latest_event(ctx) latest_event = self.bot.asset_filters.events.get_latest_event(ctx)
bonus: EventSpecificBonusMaster = latest_event.bonus bonus: EventSpecificBonusMaster = latest_event.bonus
if not characters: if not characters:
@ -149,7 +151,7 @@ class Card(commands.Cog):
arguments.require_all_arguments_used() arguments.require_all_arguments_used()
cards = masters.cards.get_sorted(arguments.text(), ctx) cards = self.bot.asset_filters.cards.get_sorted(arguments.text(), ctx)
if not (arguments.text() and sort is None): if not (arguments.text() and sort is None):
sort = sort or CardAttribute.Power sort = sort or CardAttribute.Power
cards = sorted(cards, key=lambda c: (sort.get_sort_key_from_card(c), c.max_power_with_limit_break)) cards = sorted(cards, key=lambda c: (sort.get_sort_key_from_card(c), c.max_power_with_limit_break))

@ -10,19 +10,20 @@ from d4dj_utils.master.event_master import EventMaster, EventState
from discord.ext import commands from discord.ext import commands
from pytz import UnknownTimeZoneError from pytz import UnknownTimeZoneError
from main import asset_manager, masters from miyu_bot.bot.bot import D4DJBot
from miyu_bot.commands.common.emoji import attribute_emoji_ids_by_attribute_id, unit_emoji_ids_by_unit_id, \ from miyu_bot.commands.common.emoji import attribute_emoji_ids_by_attribute_id, unit_emoji_ids_by_unit_id, \
parameter_bonus_emoji_ids_by_parameter_id, \ parameter_bonus_emoji_ids_by_parameter_id, \
event_point_emoji_id event_point_emoji_id
from miyu_bot.commands.common.event import get_latest_event
from miyu_bot.commands.common.formatting import format_info from miyu_bot.commands.common.formatting import format_info
from miyu_bot.commands.common.fuzzy_matching import romanize from miyu_bot.commands.common.fuzzy_matching import romanize
from miyu_bot.commands.common.master_asset_manager import MasterFilter, hash_master from miyu_bot.bot.master_asset_manager import hash_master
from miyu_bot.commands.common.reaction_message import run_paged_message, run_dynamically_paged_message from miyu_bot.commands.common.reaction_message import run_paged_message, run_dynamically_paged_message
class Event(commands.Cog): class Event(commands.Cog):
def __init__(self, bot: commands.Bot): bot: D4DJBot
def __init__(self, bot):
self.bot = bot self.bot = bot
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
@ -38,14 +39,14 @@ class Event(commands.Cog):
# Allows relative id searches like `!event +1` for next event or `!event -2` for the event before last event # Allows relative id searches like `!event +1` for next event or `!event -2` for the event before last event
if arg[0] in ['-', '+']: if arg[0] in ['-', '+']:
try: try:
latest = get_latest_event(ctx) latest = self.bot.asset_filters.events.get_latest_event(ctx)
event = masters.events.get(str(latest.id + int(arg)), ctx) event = self.bot.asset_filters.events.get(str(latest.id + int(arg)), ctx)
except ValueError: except ValueError:
event = masters.events.get(arg, ctx) event = self.bot.asset_filters.events.get(arg, ctx)
else: else:
event = masters.events.get(arg, ctx) event = self.bot.asset_filters.events.get(arg, ctx)
else: else:
event = get_latest_event(ctx) event = self.bot.asset_filters.events.get_latest_event(ctx)
if not event: if not event:
msg = f'Failed to find event "{arg}".' msg = f'Failed to find event "{arg}".'
@ -58,7 +59,7 @@ class Event(commands.Cog):
def generator(n): def generator(n):
nonlocal current_id nonlocal current_id
new_event = masters.events.get(current_id + n, ctx) new_event = self.bot.asset_filters.events.get(current_id + n, ctx)
if new_event: if new_event:
current_id = new_event.id current_id = new_event.id
return self.get_event_embed(new_event) return self.get_event_embed(new_event)
@ -151,7 +152,7 @@ class Event(commands.Cog):
description='Displays the time left in the current event', description='Displays the time left in the current event',
help='!timeleft') help='!timeleft')
async def time_left(self, ctx: commands.Context): async def time_left(self, ctx: commands.Context):
latest = get_latest_event(ctx) latest = self.bot.asset_filters.events.get_latest_event(ctx)
state = latest.state() state = latest.state()
@ -214,7 +215,7 @@ class Event(commands.Cog):
async with session.get('http://www.projectdivar.com/eventdata/t20') as resp: async with session.get('http://www.projectdivar.com/eventdata/t20') as resp:
leaderboard = await resp.json(encoding='utf-8') leaderboard = await resp.json(encoding='utf-8')
latest = get_latest_event(ctx) latest = self.bot.asset_filters.events.get_latest_event(ctx)
logo = discord.File(latest.logo_path, filename='logo.png') logo = discord.File(latest.logo_path, filename='logo.png')
embed = discord.Embed(title=f'{latest.name} t20').set_thumbnail(url=f'attachment://logo.png') embed = discord.Embed(title=f'{latest.name} t20').set_thumbnail(url=f'attachment://logo.png')
max_points_digits = len(str(leaderboard[0]['points'])) max_points_digits = len(str(leaderboard[0]['points']))

@ -3,7 +3,6 @@ import contextlib
import enum import enum
import logging import logging
import wave import wave
from functools import lru_cache
from inspect import cleandoc from inspect import cleandoc
from typing import Tuple from typing import Tuple
@ -13,18 +12,19 @@ from d4dj_utils.master.common_enums import ChartSectionType
from d4dj_utils.master.music_master import MusicMaster from d4dj_utils.master.music_master import MusicMaster
from discord.ext import commands from discord.ext import commands
from main import asset_manager, masters from miyu_bot.bot.bot import D4DJBot
from miyu_bot.commands.common.argument_parsing import parse_arguments, ArgumentError, list_operator_for from miyu_bot.commands.common.argument_parsing import parse_arguments, ArgumentError, list_operator_for
from miyu_bot.commands.common.emoji import difficulty_emoji_ids from miyu_bot.commands.common.emoji import difficulty_emoji_ids
from miyu_bot.commands.common.formatting import format_info from miyu_bot.commands.common.formatting import format_info
from miyu_bot.commands.common.fuzzy_matching import romanize from miyu_bot.commands.common.fuzzy_matching import romanize
from miyu_bot.commands.common.master_asset_manager import hash_master from miyu_bot.bot.master_asset_manager import hash_master
from miyu_bot.commands.common.name_aliases import units_by_name, unit_aliases
from miyu_bot.commands.common.reaction_message import run_tabbed_message, run_paged_message from miyu_bot.commands.common.reaction_message import run_tabbed_message, run_paged_message
class Music(commands.Cog): class Music(commands.Cog):
def __init__(self, bot: commands.Bot): bot: D4DJBot
def __init__(self, bot):
self.bot = bot self.bot = bot
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
@ -54,7 +54,7 @@ class Music(commands.Cog):
async def song(self, ctx: commands.Context, *, arg: commands.clean_content): async def song(self, ctx: commands.Context, *, arg: commands.clean_content):
self.logger.info(f'Searching for song "{arg}".') self.logger.info(f'Searching for song "{arg}".')
song = masters.music.get(arg, ctx) song = self.bot.asset_filters.music.get(arg, ctx)
if not song: if not song:
msg = f'No results for song "{arg}".' msg = f'No results for song "{arg}".'
@ -67,7 +67,7 @@ class Music(commands.Cog):
thumb = discord.File(song.jacket_path, filename='jacket.png') thumb = discord.File(song.jacket_path, filename='jacket.png')
except FileNotFoundError: except FileNotFoundError:
# Just a fallback # Just a fallback
thumb = discord.File(asset_manager.path / 'ondemand/stamp/stamp_10006.png', filename='jacket.png') thumb = discord.File(self.bot.assets.path / 'ondemand/stamp/stamp_10006.png', filename='jacket.png')
embed = discord.Embed(title=song.name) embed = discord.Embed(title=song.name)
embed.set_thumbnail(url=f'attachment://jacket.png') embed.set_thumbnail(url=f'attachment://jacket.png')
@ -107,7 +107,7 @@ class Music(commands.Cog):
self.logger.info(f'Searching for chart "{arg}".') self.logger.info(f'Searching for chart "{arg}".')
name, difficulty = self.parse_chart_args(arg) name, difficulty = self.parse_chart_args(arg)
song = masters.music.get(name, ctx) song = self.bot.asset_filters.music.get(name, ctx)
if not song: if not song:
msg = f'Failed to find chart "{name}".' msg = f'Failed to find chart "{name}".'
@ -129,7 +129,7 @@ class Music(commands.Cog):
self.logger.info(f'Searching for chart sections "{arg}".') self.logger.info(f'Searching for chart sections "{arg}".')
name, difficulty = self.parse_chart_args(arg) name, difficulty = self.parse_chart_args(arg)
song = masters.music.get(name, ctx) song = self.bot.asset_filters.music.get(name, ctx)
if not song: if not song:
msg = f'Failed to find chart "{name}".' msg = f'Failed to find chart "{name}".'
@ -179,8 +179,9 @@ class Music(commands.Cog):
reverse_sort = sort_op == '<' or arguments.tag('reverse') reverse_sort = sort_op == '<' or arguments.tag('reverse')
display, _ = arguments.single(['display', 'disp'], sort, allowed_operators=['='], display, _ = arguments.single(['display', 'disp'], sort, allowed_operators=['='],
converter=music_attribute_aliases) converter=music_attribute_aliases)
units = {units_by_name[unit].id units = {self.bot.aliases.units_by_name[unit].id
for unit in arguments.tags(names=units_by_name.keys(), aliases=unit_aliases)} for unit in arguments.tags(names=self.bot.aliases.units_by_name.keys(),
aliases=self.bot.aliases.unit_aliases)}
def difficulty_converter(d): def difficulty_converter(d):
return int(d[:-1]) + 0.5 if d[-1] == '+' else int(d) return int(d[:-1]) + 0.5 if d[-1] == '+' else int(d)
@ -188,7 +189,7 @@ class Music(commands.Cog):
difficulty = arguments.repeatable(['difficulty', 'diff', 'level'], is_list=True, difficulty = arguments.repeatable(['difficulty', 'diff', 'level'], is_list=True,
converter=difficulty_converter) converter=difficulty_converter)
songs = masters.music.get_sorted(arguments.text(), ctx) songs = self.bot.asset_filters.music.get_sorted(arguments.text(), ctx)
arguments.require_all_arguments_used() arguments.require_all_arguments_used()
except ArgumentError as e: except ArgumentError as e:
@ -230,7 +231,7 @@ class Music(commands.Cog):
thumb = discord.File(song.jacket_path, filename='jacket.png') thumb = discord.File(song.jacket_path, filename='jacket.png')
except FileNotFoundError: except FileNotFoundError:
# fallback # fallback
thumb = discord.File(asset_manager.path / 'ondemand/stamp/stamp_10006.png', filename='jacket.png') thumb = discord.File(self.bot.assets.path / 'ondemand/stamp/stamp_10006.png', filename='jacket.png')
files = [thumb] files = [thumb]

@ -2,11 +2,14 @@ import logging
from discord.ext import commands from discord.ext import commands
from miyu_bot.bot.bot import D4DJBot
from miyu_bot.commands.common.fuzzy_matching import romanize, FuzzyMatcher from miyu_bot.commands.common.fuzzy_matching import romanize, FuzzyMatcher
class Utility(commands.Cog): class Utility(commands.Cog):
def __init__(self, bot: commands.Bot): bot: D4DJBot
def __init__(self, bot):
self.bot = bot self.bot = bot
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)

@ -1,10 +1,10 @@
import re import re
# https://stackoverflow.com/questions/249791/regex-for-quoted-string-with-escaping-quotes
# https://stackoverflow.com/questions/21105360/regex-find-comma-not-inside-quotes
from collections import namedtuple from collections import namedtuple
from typing import Dict, List, Optional, Container, Any, Union, Callable, Set, Iterable from typing import Dict, List, Optional, Container, Any, Union, Callable, Set, Iterable
# https://stackoverflow.com/questions/249791/regex-for-quoted-string-with-escaping-quotes
# https://stackoverflow.com/questions/21105360/regex-find-comma-not-inside-quotes
# The ` ?` is just so it matches the space after during the replace with blank so there's no double spaces # The ` ?` is just so it matches the space after during the replace with blank so there's no double spaces
_param_re = re.compile( _param_re = re.compile(
r'(([a-zA-Z]+)(!=|>=|<=|>|<|==|=)(("(?:[^"\\]|\\.)*"|\'(?:[^\'\\]|\\.)*\'|[^,\s]+)(,("(?:[^"\\]|\\.)*"|\'(?:[^\'\\]|\\.)*\'|[^,\s]+))*)) ?') r'(([a-zA-Z]+)(!=|>=|<=|>|<|==|=)(("(?:[^"\\]|\\.)*"|\'(?:[^\'\\]|\\.)*\'|[^,\s]+)(,("(?:[^"\\]|\\.)*"|\'(?:[^\'\\]|\\.)*\'|[^,\s]+))*)) ?')

@ -7,7 +7,6 @@ difficulty_emoji_ids = {
ChartDifficulty.Expert: 790050636225052694, ChartDifficulty.Expert: 790050636225052694,
} }
# \:buff_power: \:buff_heart: \:buff_technique: \:buff_physical:
parameter_bonus_emoji_ids = { parameter_bonus_emoji_ids = {
'all': 792930826735583293, 'all': 792930826735583293,
'heart': 792096971040620564, 'heart': 792096971040620564,

@ -1,19 +0,0 @@
from d4dj_utils.master.event_master import EventMaster, EventState
from discord.ext import commands
from main import masters
def get_latest_event(ctx: commands.Context) -> EventMaster:
"""Returns the oldest event that has not ended or the newest event otherwise."""
try:
# NY event overlapped with previous event
return min((v for v in masters.events.values(ctx) if v.state() == EventState.Open),
key=lambda e: e.start_datetime)
except ValueError:
try:
return min((v for v in masters.events.values(ctx) if v.state() < EventState.Ended),
key=lambda e: e.start_datetime)
except ValueError:
return max(masters.events.values(ctx), key=lambda v: v.start_datetime)

@ -1,40 +0,0 @@
from main import asset_manager
characters_by_name = {}
for character in asset_manager.character_master.values():
for name in character.full_name_english.split():
characters_by_name[name.lower()] = character
attributes_by_name = {attribute.en_name: attribute for attribute in asset_manager.attribute_master.values()}
units_by_name = {unit.name.lower().replace(' ', '_'): unit for unit in asset_manager.unit_master.values()}
units_by_name['rondo'] = units_by_name['燐舞曲']
units_by_name['special'] = units_by_name['スペシャル']
units_by_name['other'] = units_by_name['その他']
unit_aliases = {
'happyaround': 'happy_around!',
'happy_around': 'happy_around!',
'hapiara': 'happy_around!',
'happy': 'happy_around!',
'ha': 'happy_around',
'peakyp-key': 'peaky_p-key',
'peakypkey': 'peaky_p-key',
'peaky': 'peaky_p-key',
'p-key': 'peaky_p-key',
'pkey': 'peaky_p-key',
'pkpk': 'peaky_p-key',
'pk': 'peaky_p-key',
'photonmaiden': 'photon_maiden',
'photome': 'photon_maiden',
'photon': 'photon_maiden',
'pm': 'photon_maiden',
'mermaid': 'merm4id',
'mmd': 'merm4id',
'lyricallily': 'lyrical_lily',
'riririri': 'lyrical_lily',
'lililili': 'lyrical_lily',
'lily': 'lyrical_lily',
'lili': 'lyrical_lily',
'll': 'lyrical_lily',
'fuhifumi': 'lyrical_lily',
}
Loading…
Cancel
Save