add asset export script and change online asset structure

pull/1/head
qwewqa 4 years ago
parent ce89600cf1
commit 758cb4ca1c
  1. 1
      .gitignore
  2. 54
      export_assets.py
  3. 12
      miyu_bot/commands/cogs/music.py
  4. 48
      miyu_bot/commands/common/master_asset_manager.py

1
.gitignore vendored

@ -249,3 +249,4 @@ dmypy.json
config.json config.json
assets/ assets/
export/

@ -0,0 +1,54 @@
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
def main():
target_dir = Path('./export')
target_dir.mkdir(parents=True, exist_ok=True)
asset_manager = AssetManager('assets')
music_dir = target_dir / 'music'
chart_dir = music_dir / 'charts'
card_dir = target_dir / 'cards'
card_icon_dir = card_dir / 'icons'
card_art_dir = card_dir / 'art'
music_dir.mkdir(exist_ok=True)
chart_dir.mkdir(exist_ok=True)
card_dir.mkdir(exist_ok=True)
card_icon_dir.mkdir(exist_ok=True)
card_art_dir.mkdir(exist_ok=True)
for music in asset_manager.music_master.values():
for chart in music.charts.values():
try:
chart_hash = hash_master(chart)
chart_path = chart.image_path
target_path = chart_dir / f'{chart_path.stem}_{chart_hash}{chart_path.suffix}'
shutil.copy(chart_path, target_path)
except FileNotFoundError:
pass
for card in asset_manager.card_master.values():
card_hash = hash_master(card)
try:
for lb in range(2):
art_path = card.art_path(lb)
art_target = card_art_dir / f'{art_path.stem}_{card_hash}{art_path.suffix}'
icon_path = card.icon_path(lb)
icon_target = card_icon_dir / f'{icon_path.stem}_{card_hash}{icon_path.suffix}'
shutil.copy(art_path, art_target)
shutil.copy(icon_path, icon_target)
except FileNotFoundError:
pass
if __name__ == '__main__':
main()

@ -17,6 +17,7 @@ from miyu_bot.commands.common.argument_parsing import parse_arguments, ArgumentE
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.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
@ -166,7 +167,8 @@ class Music(commands.Cog):
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)
difficulty = arguments.repeatable(['difficulty', 'diff', 'level'], is_list=True, converter=difficulty_converter) difficulty = arguments.repeatable(['difficulty', 'diff', 'level'], is_list=True,
converter=difficulty_converter)
arguments.require_all_arguments_used() arguments.require_all_arguments_used()
except ArgumentError as e: except ArgumentError as e:
await ctx.send(str(e)) await ctx.send(str(e))
@ -201,17 +203,19 @@ class Music(commands.Cog):
try: try:
thumb = discord.File(song.jacket_path, filename='jacket.png') thumb = discord.File(song.jacket_path, filename='jacket.png')
except FileNotFoundError: except FileNotFoundError:
# dig delight is just a fallback # fallback
thumb = discord.File(masters.music.get('110001', None).jacket_path, filename='jacket.png') thumb = discord.File(asset_manager.path / 'ondemand/stamp/stamp_10006.png', filename='jacket.png')
files = [thumb] files = [thumb]
for difficulty in [ChartDifficulty.Easy, ChartDifficulty.Normal, ChartDifficulty.Hard, ChartDifficulty.Expert]: for difficulty in [ChartDifficulty.Easy, ChartDifficulty.Normal, ChartDifficulty.Hard, ChartDifficulty.Expert]:
chart = song.charts[difficulty] chart = song.charts[difficulty]
chart_hash = hash_master(chart)
chart_path = chart.image_path
embed = discord.Embed(title=f'{song.name} [{chart.difficulty.name}]') embed = discord.Embed(title=f'{song.name} [{chart.difficulty.name}]')
embed.set_thumbnail(url=f'attachment://jacket.png') embed.set_thumbnail(url=f'attachment://jacket.png')
embed.set_image( embed.set_image(
url=f'https://qwewqa.github.io/d4dj-dumps/{chart.image_path.relative_to(asset_manager.path).as_posix()}' url=f'https://qwewqa.github.io/d4dj-dumps/music/charts/{chart_path.stem}_{chart_hash}{chart_path.suffix}'
) )
chart_data = chart.load_chart_data() chart_data = chart.load_chart_data()

@ -1,8 +1,9 @@
import hashlib
from functools import lru_cache from functools import lru_cache
from typing import Callable, Any, Optional from typing import Callable, Any, Optional
from d4dj_utils.manager.asset_manager import AssetManager from d4dj_utils.manager.asset_manager import AssetManager
from d4dj_utils.master.master_asset import MasterDict from d4dj_utils.master.master_asset import MasterDict, MasterAsset
from discord.ext import commands from discord.ext import commands
from miyu_bot.commands.common.fuzzy_matching import FuzzyFilteredMap from miyu_bot.commands.common.fuzzy_matching import FuzzyFilteredMap
@ -34,54 +35,67 @@ class MasterFilterManager:
dt.timezone.utc) + dt.timedelta(hours=12), dt.timezone.utc) + dt.timedelta(hours=12),
) )
@property
@lru_cache(None)
def cards(self):
return MasterFilter(
self.manager.card_master,
naming_function=lambda c: c.name,
filter_function=lambda c: c.is_released,
)
class MasterFilter: class MasterFilter:
def __init__(self, masters: MasterDict, naming_function: Callable[[Any], str], filter_function=lambda _: True, def __init__(self, masters: MasterDict, naming_function: Callable[[Any], str], filter_function=lambda _: True,
fallback_naming_function: Optional[Callable[[Any], str]] = None): fallback_naming_function: Optional[Callable[[Any], str]] = None):
self.masters = masters self.masters = masters
self.fuzzy_map = FuzzyFilteredMap(filter_function) self.default_filter = FuzzyFilteredMap(filter_function)
self.unfiltered_fuzzy_map = FuzzyFilteredMap() self.unrestricted_filter = FuzzyFilteredMap()
for master in masters.values(): for master in masters.values():
name = naming_function(master) name = naming_function(master)
if self.fuzzy_map.has_exact(name) and fallback_naming_function: if self.default_filter.has_exact(name) and fallback_naming_function:
name = fallback_naming_function(master) name = fallback_naming_function(master)
if self.fuzzy_map.has_exact(name): if self.default_filter.has_exact(name):
continue continue
self.fuzzy_map[name] = master self.default_filter[name] = master
self.unfiltered_fuzzy_map[name] = master self.unrestricted_filter[name] = master
def get(self, name_or_id: str, ctx: Optional[commands.Context]): def get(self, name_or_id: str, ctx: Optional[commands.Context]):
if ctx and ctx.channel.id in no_filter_channels: if ctx and ctx.channel.id in no_filter_channels:
try: try:
return self.masters[int(name_or_id)] return self.masters[int(name_or_id)]
except (KeyError, ValueError): except (KeyError, ValueError):
return self.unfiltered_fuzzy_map[name_or_id] return self.unrestricted_filter[name_or_id]
else: else:
try: try:
master = self.masters[int(name_or_id)] master = self.masters[int(name_or_id)]
if master not in self.fuzzy_map.values(): if master not in self.default_filter.values():
master = self.fuzzy_map[name_or_id] master = self.default_filter[name_or_id]
return master return master
except (KeyError, ValueError): except (KeyError, ValueError):
return self.fuzzy_map[name_or_id] return self.default_filter[name_or_id]
def get_sorted(self, name: str, ctx: commands.Context): def get_sorted(self, name: str, ctx: commands.Context):
if name: if name:
if ctx.channel.id in no_filter_channels: if ctx.channel.id in no_filter_channels:
return self.unfiltered_fuzzy_map.get_sorted(name) return self.unrestricted_filter.get_sorted(name)
else: else:
return self.fuzzy_map.get_sorted(name) return self.default_filter.get_sorted(name)
else: else:
if ctx.channel.id in no_filter_channels: if ctx.channel.id in no_filter_channels:
return list(self.unfiltered_fuzzy_map.values()) return list(self.unrestricted_filter.values())
else: else:
return list(self.fuzzy_map.values()) return list(self.default_filter.values())
def values(self, ctx: commands.Context): def values(self, ctx: commands.Context):
if ctx.channel.id in no_filter_channels: if ctx.channel.id in no_filter_channels:
return self.unfiltered_fuzzy_map.values() return self.unrestricted_filter.values()
else: else:
return self.fuzzy_map.values() return self.default_filter.values()
def hash_master(master: MasterAsset):
return hashlib.md5(master.extended_description().encode('utf-8')).hexdigest()
no_filter_channels = {790033228600705048, 790033272376918027, 795640603114864640} no_filter_channels = {790033228600705048, 790033272376918027, 795640603114864640}

Loading…
Cancel
Save