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
from pathlib import Path
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():

@ -3,20 +3,19 @@ import logging
import discord
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)
with open('config.json') as f:
bot_token = json.load(f)['token']
bot = commands.Bot(command_prefix='!', case_insensitive=True)
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.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
from functools import lru_cache
from timeit import default_timer
from typing import Callable, Any, Optional, Union
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 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
import datetime as dt
@ -22,7 +21,7 @@ class MasterFilterManager:
filter_function=lambda m: m.is_released,
fallback_naming_function=lambda m: m.id,
)
self.events = MasterFilter(
self.events = EventFilter(
self.manager.event_master,
aliases=event_aliases,
naming_function=lambda e: e.name,
@ -99,6 +98,21 @@ class MasterFilter:
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):
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
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.skill_master import SkillMaster
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.emoji import rarity_emoji_ids, attribute_emoji_ids_by_attribute_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.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.bot.master_asset_manager import hash_master
from miyu_bot.commands.common.reaction_message import run_tabbed_message, run_reaction_message, run_paged_message
class Card(commands.Cog):
def __init__(self, bot: commands.Bot):
bot: D4DJBot
def __init__(self, bot):
self.bot = bot
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.
display, _ = arguments.single(['display', 'disp'], sort, allowed_operators=['='],
converter=card_attribute_aliases)
characters = {characters_by_name[c].id for c in arguments.words(characters_by_name.keys())}
units = {units_by_name[unit].id
for unit in arguments.tags(names=units_by_name.keys(), aliases=unit_aliases)}
characters = {self.bot.aliases.characters_by_name[c].id
for c in arguments.words(self.bot.aliases.characters_by_name.keys())}
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\*']
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']))
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
if not characters:
@ -149,7 +151,7 @@ class Card(commands.Cog):
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):
sort = sort or CardAttribute.Power
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 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, \
parameter_bonus_emoji_ids_by_parameter_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.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
class Event(commands.Cog):
def __init__(self, bot: commands.Bot):
bot: D4DJBot
def __init__(self, bot):
self.bot = bot
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
if arg[0] in ['-', '+']:
try:
latest = get_latest_event(ctx)
event = masters.events.get(str(latest.id + int(arg)), ctx)
latest = self.bot.asset_filters.events.get_latest_event(ctx)
event = self.bot.asset_filters.events.get(str(latest.id + int(arg)), ctx)
except ValueError:
event = masters.events.get(arg, ctx)
event = self.bot.asset_filters.events.get(arg, ctx)
else:
event = masters.events.get(arg, ctx)
event = self.bot.asset_filters.events.get(arg, ctx)
else:
event = get_latest_event(ctx)
event = self.bot.asset_filters.events.get_latest_event(ctx)
if not event:
msg = f'Failed to find event "{arg}".'
@ -58,7 +59,7 @@ class Event(commands.Cog):
def generator(n):
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:
current_id = new_event.id
return self.get_event_embed(new_event)
@ -151,7 +152,7 @@ class Event(commands.Cog):
description='Displays the time left in the current event',
help='!timeleft')
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()
@ -214,7 +215,7 @@ class Event(commands.Cog):
async with session.get('http://www.projectdivar.com/eventdata/t20') as resp:
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')
embed = discord.Embed(title=f'{latest.name} t20').set_thumbnail(url=f'attachment://logo.png')
max_points_digits = len(str(leaderboard[0]['points']))

@ -3,7 +3,6 @@ import contextlib
import enum
import logging
import wave
from functools import lru_cache
from inspect import cleandoc
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 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.emoji import difficulty_emoji_ids
from miyu_bot.commands.common.formatting import format_info
from miyu_bot.commands.common.fuzzy_matching import romanize
from miyu_bot.commands.common.master_asset_manager import hash_master
from miyu_bot.commands.common.name_aliases import units_by_name, unit_aliases
from miyu_bot.bot.master_asset_manager import hash_master
from miyu_bot.commands.common.reaction_message import run_tabbed_message, run_paged_message
class Music(commands.Cog):
def __init__(self, bot: commands.Bot):
bot: D4DJBot
def __init__(self, bot):
self.bot = bot
self.logger = logging.getLogger(__name__)
@ -54,7 +54,7 @@ class Music(commands.Cog):
async def song(self, ctx: commands.Context, *, arg: commands.clean_content):
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:
msg = f'No results for song "{arg}".'
@ -67,7 +67,7 @@ class Music(commands.Cog):
thumb = discord.File(song.jacket_path, filename='jacket.png')
except FileNotFoundError:
# 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.set_thumbnail(url=f'attachment://jacket.png')
@ -107,7 +107,7 @@ class Music(commands.Cog):
self.logger.info(f'Searching for chart "{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:
msg = f'Failed to find chart "{name}".'
@ -129,7 +129,7 @@ class Music(commands.Cog):
self.logger.info(f'Searching for chart sections "{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:
msg = f'Failed to find chart "{name}".'
@ -179,8 +179,9 @@ class Music(commands.Cog):
reverse_sort = sort_op == '<' or arguments.tag('reverse')
display, _ = arguments.single(['display', 'disp'], sort, allowed_operators=['='],
converter=music_attribute_aliases)
units = {units_by_name[unit].id
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)}
def difficulty_converter(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,
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()
except ArgumentError as e:
@ -230,7 +231,7 @@ class Music(commands.Cog):
thumb = discord.File(song.jacket_path, filename='jacket.png')
except FileNotFoundError:
# 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]

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

@ -1,10 +1,10 @@
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 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
_param_re = re.compile(
r'(([a-zA-Z]+)(!=|>=|<=|>|<|==|=)(("(?:[^"\\]|\\.)*"|\'(?:[^\'\\]|\\.)*\'|[^,\s]+)(,("(?:[^"\\]|\\.)*"|\'(?:[^\'\\]|\\.)*\'|[^,\s]+))*)) ?')

@ -7,7 +7,6 @@ difficulty_emoji_ids = {
ChartDifficulty.Expert: 790050636225052694,
}
# \:buff_power: \:buff_heart: \:buff_technique: \:buff_physical:
parameter_bonus_emoji_ids = {
'all': 792930826735583293,
'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