From 963f0bf5f510daeb1972877175445cca7edd036f Mon Sep 17 00:00:00 2001 From: Ev-1 <33662061+Ev-1@users.noreply.github.com> Date: Sun, 17 Feb 2019 12:11:18 +0100 Subject: [PATCH 1/8] Locale specific command aliases --- bot.py | 26 ++++++++++++++++++++-- cogs/utils/alias.py | 39 +++++++++++++++++++++++++++++++++ cogs/utils/context.py | 9 ++++++++ localization/en_en/aliases.yaml | 27 +++++++++++++++++++++++ 4 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 cogs/utils/alias.py create mode 100644 cogs/utils/context.py create mode 100644 localization/en_en/aliases.yaml diff --git a/bot.py b/bot.py index ba60708..d5c325f 100644 --- a/bot.py +++ b/bot.py @@ -8,6 +8,9 @@ import yaml from discord.ext import commands from cogs.utils.settings import Settings from cogs.utils.localizer import Localizer +from cogs.utils.localizer import LocalizerWrapper +from cogs.utils.alias import Aliaser +from cogs.utils.context import Context initial_extensions = [ @@ -35,6 +38,7 @@ class Bot(commands.Bot): self.settings = Settings(**conf['default server settings']) self.localizer = Localizer(conf.get('locale path', "./localization"), conf.get('locale', 'en_en')) + self.aliaser = Aliaser(conf.get('locale path', "./localization"), conf.get('locale', 'en_en')) self.debug = debug for extension in initial_extensions: @@ -61,9 +65,7 @@ class Bot(commands.Bot): pass elif isinstance(err, commands.NoPrivateMessage): - # Todo, fix, use default bot lang. await ctx.send('That command is not available in DMs') - #await ctx.send(self.localizer.format_str("{commands.not_available_dm}", self.settings.get(ctx.guild, 'locale', 'default_locale'))) elif isinstance(err, commands.CheckFailure): pass @@ -75,6 +77,26 @@ class Bot(commands.Bot): traceback.print_tb(tb) print(err) + + async def on_message(self, message): + if message.author.bot: + return + await self.process_commands(message) + + async def process_commands(self, message): + ctx = await self.get_context(message, cls=Context) + if not ctx.command: + command = self.aliaser.get_command(ctx.locale, ctx.invoked_with) + if command is not None: + ctx.command = self.get_command(command) + + if ctx.command and ctx.command.cog_name: + ctx.localizer = LocalizerWrapper(self.localizer, ctx.locale, ctx.command.cog_name.lower()) + else: + ctx.localizer = LocalizerWrapper(self.localizer, ctx.locale, None) + + await self.invoke(ctx) + async def on_ready(self): if not hasattr(self, 'uptime'): self.uptime = time.time() diff --git a/cogs/utils/alias.py b/cogs/utils/alias.py new file mode 100644 index 0000000..252c011 --- /dev/null +++ b/cogs/utils/alias.py @@ -0,0 +1,39 @@ +import yaml +from glob import glob +from os import path + +class Aliaser: + def __init__(self, localization_folder, default_lang): + self.localization_folder = path.realpath(localization_folder) + self.default_lang = default_lang + self.index_localizations() + self.load_localizations() + + def _invert(self, d): + inverted = {} + for command in d: + for alias in d[command]: + inverted[alias] = command + return inverted + + def index_localizations(self): + self.localization_table = {} + for folder in glob(path.join(self.localization_folder, "*/")): + if 'global' in folder: + continue + folder_base = path.basename(path.dirname(folder)) + self.localization_table[folder_base] = False + + def load_localizations(self): + for lang in self.localization_table.keys(): + with open(path.join(self.localization_folder, lang, "aliases.yaml"), "r", encoding='utf-8') as f: + data = yaml.load(f) + self.localization_table[lang] = {'aliases': data, 'commands': self._invert(data)} + + def get_command(self, locale, alias): + locale = self.localization_table[locale] + return locale['commands'].get(alias, None) + + def get_alias(self, locale, command): + locale = self.localization_table[locale] + return locale['aliases'].get(command, []) \ No newline at end of file diff --git a/cogs/utils/context.py b/cogs/utils/context.py new file mode 100644 index 0000000..632ba0c --- /dev/null +++ b/cogs/utils/context.py @@ -0,0 +1,9 @@ +from discord.ext import commands + +class Context(commands.Context): + def __init__(self, **kwargs): + super().__init__(**kwargs) + if self.message.guild: + self.locale = self.bot.settings.get(self.message.guild, 'locale', 'default_locale') + else: + self.locale = self.bot.settings.default_locale \ No newline at end of file diff --git a/localization/en_en/aliases.yaml b/localization/en_en/aliases.yaml new file mode 100644 index 0000000..d190bc1 --- /dev/null +++ b/localization/en_en/aliases.yaml @@ -0,0 +1,27 @@ + +# Music aliases +play: [p] +now: [np, nowplaying] +queue: [q] +myqueue: [mq] +seek: [] +skip: [] +skipto: [forceskip] +stop: [] +pause: [resume] +shuffle: [] +move: [m] +remvove: [rem] +DJremove: [djremove] +removeuser: [] +search: [s] +disconnect: [dc] +volume: [v, vol] +normalize: [normal] +boost: [bassboost] +history: [h] +scrub: [] + +# Other +info: [] +musicinfo: [] From ad407d63ba53956a3597dfaf6531a509d06b8a39 Mon Sep 17 00:00:00 2001 From: Ev-1 <33662061+Ev-1@users.noreply.github.com> Date: Sun, 17 Feb 2019 12:12:05 +0100 Subject: [PATCH 2/8] localizer in context, locale as yaml instead of json. --- cogs/misc.py | 35 +++--- cogs/music.py | 203 ++++++++++++++----------------- cogs/utils/localizer.py | 9 +- localization/en_en/commands.json | 3 - localization/en_en/info.json | 18 --- localization/en_en/misc.yaml | 20 +++ localization/en_en/music.json | 90 -------------- localization/en_en/music.yaml | 73 +++++++++++ localization/nb_no/aliases.yaml | 27 ++++ localization/nb_no/commands.json | 3 - localization/nb_no/info.json | 18 --- localization/nb_no/misc.yaml | 20 +++ localization/nb_no/music.json | 90 -------------- localization/nb_no/music.yaml | 73 +++++++++++ localization/nn_no/aliases.yaml | 27 ++++ localization/nn_no/commands.json | 3 - localization/nn_no/info.json | 18 --- localization/nn_no/misc.yaml | 20 +++ localization/nn_no/music.json | 90 -------------- localization/nn_no/music.yaml | 73 +++++++++++ 20 files changed, 447 insertions(+), 466 deletions(-) delete mode 100644 localization/en_en/commands.json delete mode 100644 localization/en_en/info.json create mode 100644 localization/en_en/misc.yaml delete mode 100644 localization/en_en/music.json create mode 100644 localization/en_en/music.yaml create mode 100644 localization/nb_no/aliases.yaml delete mode 100644 localization/nb_no/commands.json delete mode 100644 localization/nb_no/info.json create mode 100644 localization/nb_no/misc.yaml delete mode 100644 localization/nb_no/music.json create mode 100644 localization/nb_no/music.yaml create mode 100644 localization/nn_no/aliases.yaml delete mode 100644 localization/nn_no/commands.json delete mode 100644 localization/nn_no/info.json create mode 100644 localization/nn_no/misc.yaml delete mode 100644 localization/nn_no/music.json create mode 100644 localization/nn_no/music.yaml diff --git a/cogs/misc.py b/cogs/misc.py index 4f24f25..e1ed385 100644 --- a/cogs/misc.py +++ b/cogs/misc.py @@ -45,18 +45,17 @@ class Misc: """ Info om musikkspilleren """ - embed = discord.Embed(title='{info.music.title}', color=ctx.me.color) + embed = discord.Embed(title='{music.title}', color=ctx.me.color) lavalink = self.bot.lavalink listeners = 0 for guild, player in lavalink.players: listeners += len(player.listeners) - embed.add_field(name='{info.music.players}', value=f'{len(lavalink.players)}') - embed.add_field(name='{info.music.listeners}', value=f'{listeners}') - embed = self.bot.localizer.format_embed(embed, self.bot.settings.get(ctx.guild, 'locale', 'default_locale')) + embed.add_field(name='{music.players}', value=f'{len(lavalink.players)}') + embed.add_field(name='{music.listeners}', value=f'{listeners}') + embed = ctx.localizer.format_embed(embed) await ctx.send(embed=embed) - @commands.command(name="reloadlocale") @@ -65,6 +64,12 @@ class Misc: self.bot.localizer.load_localizations() await ctx.send("Localizations reloaded.") + @commands.command(name="reloadalias") + async def reload_alias(self, ctx): + self.bot.aliaser.index_localizations() + self.bot.aliaser.load_localizations() + await ctx.send("Aliases reloaded.") + @commands.command() async def info(self, ctx): """ @@ -93,19 +98,18 @@ class Misc: embed.set_author(name=self.bot.user.name, icon_url=avatar) embed.set_thumbnail(url=avatar) embed.set_image(url='https://cdn.discordapp.com/attachments/298524946454282250/368118192251469835/vintage1turntable.png') - embed.add_field(name="{info.bot.what}", - value='{info.bot.infotext}', inline=False) + embed.add_field(name="{bot.what}", + value='{bot.infotext}', inline=False) embed.set_footer(icon_url="https://cdn.discordapp.com/icons/532176350019321917/92f43a1f67308a99a30c169db4b671dd.png?size=64", - text="{info.bot.footer_text}") - embed.add_field(name="{info.bot.how}", - value='{info.bot.spectext}') - embed.add_field(name="{info.bot.how_many}", - value='{info.bot.stattext}') - embed.add_field(name="{info.bot.how_long}", + text="{bot.footer_text}") + embed.add_field(name="{bot.how}", + value='{bot.spectext}') + embed.add_field(name="{bot.how_many}", + value='{bot.stattext}') + embed.add_field(name="{bot.how_long}", value=uptimetext) - embed = self.bot.localizer.format_embed(embed, - self.bot.settings.get(ctx.guild, 'locale', 'default_locale'), + embed = ctx.localizer.format_embed(embed, _python_v=platform.python_version(), _discord_v=discord.__version__, _lavalink_v=LavalinkVersion, @@ -117,6 +121,7 @@ class Misc: @commands.command() @checks.is_even() async def only_me(self, ctx): + print(ctx.localizer.format_str("{nothing_found}")) await ctx.send('Only you!') diff --git a/cogs/music.py b/cogs/music.py index ef98542..3211f08 100644 --- a/cogs/music.py +++ b/cogs/music.py @@ -35,17 +35,14 @@ class Music: bot.lavalink.add_node(**conf['lavalink nodes']['main']) bot.add_listener(bot.lavalink.voice_update_handler, 'on_socket_response') - def getLocalizer(self, guild): - lang = self.bot.settings.get(guild, 'locale', 'default_locale') - return LocalizerWrapper(self.bot.localizer, lang, "music.response") - async def __local_check(self, ctx): """ Ensures the commands are used in the correct channels """ + if not ctx.guild: + raise commands.NoPrivateMessage textchannels = self.bot.settings.get(ctx.guild, 'channels.text', []) if textchannels: if ctx.channel.id not in textchannels: - localizer = self.getLocalizer(ctx.guild) - response = localizer.format_str('{settings_check.textchannel}') + response = ctx.localizer.format_str('{settings_check.textchannel}') for channel_id in textchannels: response += f'<#{channel_id}>, ' await ctx.send(response[:-2]) @@ -72,11 +69,10 @@ class Music: ws = self.bot._connection._get_websocket(guild_id) await ws.voice_state(str(guild_id), channel_id) - @commands.command(name='play', aliases=['p','spill','s','spel']) + @commands.command(name='play') async def _play(self, ctx, *, query: str): """ Searches and plays a song from a given query. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) query = query.strip('<>') if not url_rx.match(query): @@ -85,7 +81,7 @@ class Music: results = await player.node.get_tracks(query) if not results or not results['tracks']: - return await ctx.send(localizer.format_str("{nothing_found}")) + return await ctx.send(ctx.localizer.format_str("{nothing_found}")) embed = discord.Embed(color=ctx.me.color) @@ -106,33 +102,32 @@ class Music: embed.title = '{playlist_enqued}' embed.description = f'{results["playlistInfo"]["name"]} - {numtracks} {{tracks}}' - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) await ctx.send(embed=embed) else: track = results['tracks'][0] await self.enqueue(ctx, track, embed) - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) await ctx.send(embed=embed) if not player.is_playing: await player.play() - @commands.command(name='seek', aliases=['spol']) + @commands.command(name='seek') @checks.DJ_or(alone=True) async def _seek(self, ctx, *, time: str): """ Seeks to a given position in a track. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if not player.is_playing: - return await ctx.send(localizer.format_str("{not_playing}")) + return await ctx.send(ctx.localizer.format_str("{not_playing}")) if ctx.author not in player.listeners: - return await ctx.send(localizer.format_str("{have_to_listen}")) + return await ctx.send(ctx.localizer.format_str("{have_to_listen}")) seconds = time_rx.search(time) if not seconds: - return await ctx.send(localizer.format_str("{seek.missing_amount}")) + return await ctx.send(ctx.localizer.format_str("{seek.missing_amount}")) seconds = int(seconds.group()) * 1000 if time.startswith('-'): @@ -140,17 +135,16 @@ class Music: track_time = player.position + seconds await player.seek(track_time) - msg = localizer.format_str("{seek.track_moved}", _position=timeformatter.format(track_time)) + msg = ctx.localizer.format_str("{seek.track_moved}", _position=timeformatter.format(track_time)) await ctx.send(msg) - @commands.command(name='skip', aliases=['hopp']) + @commands.command(name='skip') async def _skip(self, ctx): """ Skips the current track. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if not player.is_playing: - return await ctx.send(localizer.format_str("{not_playing}")) + return await ctx.send(ctx.localizer.format_str("{not_playing}")) player.add_skipper(ctx.author) total = len(player.listeners) @@ -159,56 +153,53 @@ class Music: if skips/total >= threshold/100 or player.current.requester == ctx.author.id: await player.skip() - await ctx.send(localizer.format_str("{skip.skipped}")) + await ctx.send(ctx.localizer.format_str("{skip.skipped}")) else: if skips != 0: needed = math.ceil(total*threshold/100) - msg = localizer.format_str("{skip.require_vote}", _skips=skips, _total=needed) + msg = ctx.localizer.format_str("{skip.require_vote}", _skips=skips, _total=needed) await ctx.send(msg) - @commands.command(name='skipto', aliases=['forceskip','hopptil','tvinghopp']) + @commands.command(name='skipto') @checks.DJ_or(alone=True) async def _skip_to(self, ctx, pos: int=1): """ Plays the queue from a specific point. Disregards tracks before the pos. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if ctx.author not in player.listeners: - return await ctx.send(localizer.format_str("{have_to_listen}")) + return await ctx.send(ctx.localizer.format_str("{have_to_listen}")) if pos < 1: - return await ctx.send(localizer.format_str("{skip_to.invalid_pos}")) + return await ctx.send(ctx.localizer.format_str("{skip_to.invalid_pos}")) if len(player.queue) < pos: - return await ctx.send(localizer.format_str("{skip_to.exceeds_queue}")) + return await ctx.send(ctx.localizer.format_str("{skip_to.exceeds_queue}")) await player.skip(pos - 1) - msg = localizer.format_str("{skip_to.skipped_to}", _title=player.current.title, _pos=pos) + msg = ctx.localizer.format_str("{skip_to.skipped_to}", _title=player.current.title, _pos=pos) await ctx.send(msg) - @commands.command(name='stop', aliases=['stopp']) + @commands.command(name='stop') @checks.DJ_or(alone=True) async def _stop(self, ctx): """ Stops the player and clears its queue. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if ctx.author not in player.listeners: - return await ctx.send(localizer.format_str("{have_to_listen}")) + return await ctx.send(ctx.localizer.format_str("{have_to_listen}")) if not player.is_playing: - return await ctx.send(localizer.format_str("{not_playing}")) + return await ctx.send(ctx.localizer.format_str("{not_playing}")) player.queue.clear() await player.stop() - await ctx.send(localizer.format_str("{stop}")) + await ctx.send(ctx.localizer.format_str("{stop}")) - @commands.command(name='now', aliases=['np','current', 'nå', 'nåspilles', 'gjeldende', 'spillernå','spelarno','nospelar']) + @commands.command(name='now') async def _now(self, ctx): """ Shows some stats about the currently playing song. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if not player.current: - return await ctx.send(localizer.format_str("{not_playing}")) + return await ctx.send(ctx.localizer.format_str("{not_playing}")) position = timeformatter.format(player.position) if player.current.stream: @@ -219,7 +210,7 @@ class Music: member = ctx.guild.get_member(player.current.requester) embed = discord.Embed(color=ctx.me.color, description=song, title='{now}') - thumbnail_url = await RoxUtils.ThumbNailer.identify(self,player.current.identifier, player.current.uri) + thumbnail_url = await RoxUtils.ThumbNailer.identify(self, player.current.identifier, player.current.uri) if thumbnail_url: embed.set_thumbnail(url=thumbnail_url) @@ -229,100 +220,94 @@ class Music: member_identifier = member.name embed.set_footer(text=f'{{requested_by}} {member_identifier}', icon_url=member.avatar_url) - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) await ctx.send(embed=embed) - @commands.command(name='queue', aliases=['q', 'kø']) + @commands.command(name='queue') async def _queue(self, ctx, user: discord.Member=None): """ Shows the player's queue. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if player.queue.empty: - return await ctx.send(localizer.format_str("{queue.empty}")) + return await ctx.send(ctx.localizer.format_str("{queue.empty}")) if user is None: queue = player.global_queue() - scroller = QueueScroller(ctx, queue, localizer, lines_per_page=10) + scroller = QueueScroller(ctx, queue, ctx.localizer, lines_per_page=10) await scroller.start_scrolling() else: user_queue = player.user_queue(user.id, dual=True) if not user_queue: - return await ctx.send(localizer.format_str("{queue.empty}", _user=user.name)) + return await ctx.send(ctx.localizer.format_str("{queue.empty}", _user=user.name)) - scroller = QueueScroller(ctx, user_queue, localizer, lines_per_page=10, user_name=user.name) + scroller = QueueScroller(ctx, user_queue, ctx.localizer, lines_per_page=10, user_name=user.name) await scroller.start_scrolling() - @commands.command(name='myqueue', aliases=['mq','minkø','mk']) + @commands.command(name='myqueue') async def _myqueue(self, ctx): """ Shows your queue. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) user_queue = player.user_queue(ctx.author.id, dual=True) if not user_queue: - return await ctx.send(localizer.format_str("{my_queue}")) + return await ctx.send(ctx.localizer.format_str("{my_queue}")) - scroller = QueueScroller(ctx, user_queue, localizer, lines_per_page=10, user_name=ctx.author.name) + scroller = QueueScroller(ctx, user_queue, ctx.localizer, lines_per_page=10, user_name=ctx.author.name) await scroller.start_scrolling() - @commands.command(name='pause', aliases=['resume','gjenoppta']) + @commands.command(name='pause') @checks.DJ_or(alone=True) async def _pause(self, ctx): """ Pauses/Resumes the current track. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if not player.is_playing: - return await ctx.send(localizer.format_str("{not_playing}")) + return await ctx.send(ctx.localizer.format_str("{not_playing}")) if player.paused: await player.set_pause(False) - await ctx.send(localizer.format_str("{resume.resumed}")) + await ctx.send(ctx.localizer.format_str("{resume.resumed}")) else: await player.set_pause(True) - await ctx.send(localizer.format_str("{resume.paused}")) + await ctx.send(ctx.localizer.format_str("{resume.paused}")) - @commands.command(name='shuffle', aliases=['stokk']) + @commands.command(name='shuffle') async def _shuffle(self, ctx): """ Shuffles your queue. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) user_queue = player.user_queue(ctx.author.id) if not user_queue: - return await ctx.send(localizer.format_str("{my_queue}")) + return await ctx.send(ctx.localizer.format_str("{my_queue}")) player.shuffle_user_queue(ctx.author.id) - await ctx.send(localizer.format_str("{shuffle}")) + await ctx.send(ctx.localizer.format_str("{shuffle}")) - @commands.command(name='move', aliases=['m', 'flytt','f']) + @commands.command(name='move') async def _move(self, ctx, from_pos: int, to_pos: int): """ Moves a song in your queue. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) user_queue = player.user_queue(ctx.author.id) if not user_queue: - return await ctx.send(localizer.format_str("{my_queue}")) + return await ctx.send(ctx.localizer.format_str("{my_queue}")) if not all(x in range(1,len(user_queue) + 1) for x in [from_pos, to_pos]): - return await ctx.send(localizer.format_str("{out_of_range}", _len=len(user_queue))) + return await ctx.send(ctx.localizer.format_str("{out_of_range}", _len=len(user_queue))) moved = player.move_user_track(ctx.author.id, from_pos - 1, to_pos - 1) if moved is None: - return await ctx.send(localizer.format_str("{move.not_in_queue}")) + return await ctx.send(ctx.localizer.format_str("{move.not_in_queue}")) - msg = localizer.format_str("{move.moved_to}", _title=moved.title, _from=from_pos, _to=to_pos) + msg = ctx.localizer.format_str("{move.moved_to}", _title=moved.title, _from=from_pos, _to=to_pos) await ctx.send(msg) - @commands.command(name='remove', aliases=['rem', 'fjern']) + @commands.command(name='remove') async def _remove(self, ctx, pos: int): """ Removes an item from the player's queue with the given pos. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if player.queue.empty: return @@ -332,29 +317,28 @@ class Music: return if pos > len(user_queue) or pos < 1: - return await ctx.send(localizer.format_str("{out_of_range}", _len=len(user_queue))) + return await ctx.send(ctx.localizer.format_str("{out_of_range}", _len=len(user_queue))) removed = player.remove_user_track(ctx.author.id, pos - 1) - await ctx.send(localizer.format_str("{remove}", _title=removed.title)) + await ctx.send(ctx.localizer.format_str("{remove}", _title=removed.title)) - @commands.command(name="DJremove", aliases=['DJfjern','djfjern']) + @commands.command(name="DJremove") @checks.DJ_or() async def _djremove(self, ctx, pos: int, user: discord.Member=None): """ Remove a song from either the global queue or a users queue""" player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if user is None: if player.queue.empty: return if pos > len(player.queue) or pos < 1: - return await ctx.send(localizer.format_str("{out_of_range}", _len=len(player.queue))) + return await ctx.send(ctx.localizer.format_str("{out_of_range}", _len=len(player.queue))) removed = player.remove_global_track(pos - 1) requester = self.bot.get_user(removed.requester) - await ctx.send(localizer.format_str("{dj_removed}", _title=removed.title, _user=requester.name)) + await ctx.send(ctx.localizer.format_str("{dj_removed}", _title=removed.title, _user=requester.name)) else: if player.queue.empty: @@ -365,17 +349,16 @@ class Music: return if pos > len(user_queue) or pos < 1: - return await ctx.send(localizer.format_str("{out_of_range}", _len=len(user_queue))) + return await ctx.send(ctx.localizer.format_str("{out_of_range}", _len=len(user_queue))) removed = player.remove_user_track(user.id, pos - 1) - await ctx.send(localizer.format_str("{dj_removed}", _title=removed.title, _user=requester.name)) + await ctx.send(ctx.localizer.format_str("{dj_removed}", _title=removed.title, _user=requester.name)) - @commands.command(name='removeuser', aliases=['fjernbruker','fjernbrukar']) + @commands.command(name='removeuser') @checks.DJ_or(alone=True) async def _user_queue_remove(self, ctx, user: discord.Member): """ Remove a song from either the global queue or a users queue""" player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if player.queue.empty: return @@ -388,15 +371,14 @@ class Music: embed = discord.Embed(color=ctx.me.color) embed.description = "{dj_remove_user}" - embed = localizer.format_embed(embed, _id=user.id) + embed = ctx.localizer.format_embed(embed, _id=user.id) await ctx.send(embed=embed) - @commands.command(name='search', aliases=['søk','finn']) + @commands.command(name='search') async def _search(self, ctx, *, query): """ Lists the first 10 search results from a given query. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if not query.startswith('ytsearch:') and not query.startswith('scsearch:'): query = 'ytsearch:' + query @@ -405,7 +387,7 @@ class Music: embed = discord.Embed(description='{nothing_found}', color=0x36393F) if not results or not results['tracks']: - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) return await ctx.send(embed=embed) tracks = results['tracks'] @@ -447,7 +429,7 @@ class Music: return False embed.description = '{search}' - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) result_msg = await ctx.send(embed=embed) for emoji, index in choices[:result_count]: @@ -458,7 +440,7 @@ class Music: embed.title = '{results}' embed.color = ctx.me.color - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) await result_msg.edit(embed=embed) @@ -470,7 +452,7 @@ class Music: await result_msg.clear_reactions() embed.title = '' embed.description='{time_expired}' - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) await result_msg.edit(embed=embed) await asyncio.sleep(5) await result_msg.delete() @@ -481,37 +463,35 @@ class Music: await result_msg.clear_reactions() track = tracks[choice - 1] await self.enqueue(ctx, track, embed) - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) await result_msg.edit(embed=embed) if not player.is_playing: await player.play() - @commands.command(name='disconnect', aliases=['dc','kf','koblefra','koblefrå']) + @commands.command(name='disconnect') @checks.DJ_or(alone=True) async def _disconnect(self, ctx): """ Disconnects the player from the voice channel and clears its queue. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if not player.is_connected: - return await ctx.send(localizer.format_str("{not_connected}")) + return await ctx.send(ctx.localizer.format_str("{not_connected}")) if not ctx.author.voice or (player.is_connected and ctx.author.voice.channel.id != int(player.channel_id)): - return await ctx.send(localizer.format_str("{disconnect.not_in_voice}")) + return await ctx.send(ctx.localizer.format_str("{disconnect.not_in_voice}")) player.queue.clear() await player.stop() await self.connect_to(ctx.guild.id, None) embed = discord.Embed(description='{disconnect.disconnected}', color=ctx.me.color) - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) await ctx.send(embed=embed) - @commands.command(name='volume', aliases=['vol', 'volum', 'lydstyrke']) + @commands.command(name='volume') @checks.DJ_or(alone=True, current=True) async def _volume(self, ctx, volume: int = None): """ Changes the player's volume. Must be between 0 and 1000. Error Handling for that is done by Lavalink. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if not volume: return await ctx.send(f'🔈 | {player.volume}%') @@ -520,36 +500,34 @@ class Music: is_admin = getattr(ctx.author.guild_permissions, 'administrator', None) == True if int(player.current.requester) == ctx.author.id and not is_dj and not is_admin: if not 50 <= volume <= 125: - return await ctx.send(localizer.format_str("{volume.out_of_range}")) + return await ctx.send(ctx.localizer.format_str("{volume.out_of_range}")) await player.set_volume(volume) embed = discord.Embed(color=ctx.me.color) embed.description = "{volume.set_to}" - embed = localizer.format_embed(embed, _volume=player.volume) + embed = ctx.localizer.format_embed(embed, _volume=player.volume) await ctx.send(embed=embed) - @commands.command(name='normalize', aliases=['normal','nl','normaliser']) + @commands.command(name='normalize') @checks.DJ_or(alone=True) async def _normalize(self, ctx): """ Reset the equalizer and """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) await player.set_volume(100) await player.bassboost(False) embed = discord.Embed(color=ctx.me.color) embed.description = '{volume.reset}' - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) await ctx.send(embed=embed) - @commands.command(name='boost', aliases=['boo','bassforsterker','bassforsterkar']) + @commands.command(name='boost') @checks.DJ_or(alone=True) async def _boost(self, ctx, boost: bool=None): """ Set the equalizer to bass boost the music """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) if boost is not None: await player.bassboost(boost) @@ -561,43 +539,41 @@ class Music: else: embed.description = '{boost.off}' - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) await ctx.send(embed=embed) - @commands.command(name='history', aliases=['h','hist','historie']) + @commands.command(name='history') async def _history(self, ctx): """ Show the last 10 songs played """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) history = player.get_history() if not history: - return await ctx.send(localizer.format_str("{history.empty}")) + return await ctx.send(ctx.localizer.format_str("{history.empty}")) track = history[0] - description = localizer.format_str("{history.current}", _title=track.title, _uri=track.uri,_id=track.requester) + '\n\n' - description += localizer.format_str("{history.previous}", _len=len(history)-1) + '\n' + description = ctx.localizer.format_str("{history.current}", _title=track.title, _uri=track.uri,_id=track.requester) + '\n\n' + description += ctx.localizer.format_str("{history.previous}", _len=len(history)-1) + '\n' thumb_url = await RoxUtils.ThumbNailer.identify(self, track.identifier, track.uri) for index, track in enumerate(history[1:], start=1): - description += localizer.format_str("{history.track}",_index=-index, _title=track.title, _uri=track.uri, _id=track.requester) + '\n' + description += ctx.localizer.format_str("{history.track}",_index=-index, _title=track.title, _uri=track.uri, _id=track.requester) + '\n' - embed = discord.Embed(title=localizer.format_str('{history.title}'), color=ctx.me.color, description=description) + embed = discord.Embed(title=ctx.localizer.format_str('{history.title}'), color=ctx.me.color, description=description) if thumb_url: embed.set_thumbnail(url=thumb_url) await ctx.send(embed=embed) - @commands.command(name='scrub', aliases=['kontrol','konsoll']) + @commands.command(name='scrub') @checks.DJ_or(alone=True) async def _scrub(self, ctx): """ Lists the first 10 search results from a given query. """ player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) controls = '{scrub.controls}' embed = discord.Embed(description='{nothing_playing}', color=ctx.me.color) - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) if player.current is None: return await ctx.send(embed=embed) @@ -631,14 +607,14 @@ class Music: return False embed.description = '{scrub.add}' - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) msg = await ctx.send(embed=embed) for (emoji, _, _) in scrubber: await msg.add_reaction(emoji) embed.description = controls - embed = localizer.format_embed(embed) + embed = ctx.localizer.format_embed(embed) await msg.edit(embed=embed) scrubbing = True while scrubbing: @@ -694,8 +670,8 @@ class Music: if voice_channels: if voice_channel.id not in voice_channels: - localizer = self.getLocalizer(ctx.guild) - response = localizer.format_str('{settings_check.voicechannel}') + ctx.localizer = self.getLocalizer(ctx.guild) + response = ctx.localizer.format_str('{settings_check.voicechannel}') for channel_id in voice_channels: channel = ctx.guild.get_channel(channel_id) if channel is not None: @@ -713,11 +689,10 @@ class Music: async def enqueue(self, ctx, track, embed): player = self.bot.lavalink.players.get(ctx.guild.id) - localizer = self.getLocalizer(ctx.guild) maxlength = self.max_track_length(ctx.guild, player) if maxlength and track['info']['length'] > maxlength: - embed.description = localizer.format_str("{enqueue.toolong}", + embed.description = ctx.localizer.format_str("{enqueue.toolong}", _length=timeformatter.format(track['info']['length']), _max=timeformatter.format(maxlength)) return diff --git a/cogs/utils/localizer.py b/cogs/utils/localizer.py index c4e27cc..578aa67 100644 --- a/cogs/utils/localizer.py +++ b/cogs/utils/localizer.py @@ -5,10 +5,9 @@ import re from cogs.utils.dict_utils import flatten, SafeDict -import json +import yaml import copy - from discord import Embed """ @@ -52,10 +51,12 @@ class Localizer: elif localization is False: self.localization_table[lang] = {} l_table = self.localization_table[lang] - for file in glob(path.join(self.localization_folder, lang, "*.json")): + for file in glob(path.join(self.localization_folder, lang, "*.yaml")): + if 'aliases' in file: + continue file_base = path.basename(file).split(".")[0] with open(file, "r", encoding='utf-8') as f: - data = json.load(f) + data = yaml.load(f) l_table[file_base] = data diff --git a/localization/en_en/commands.json b/localization/en_en/commands.json deleted file mode 100644 index 0f031d3..0000000 --- a/localization/en_en/commands.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "not_available_dm": "This command is not available in DMs" -} \ No newline at end of file diff --git a/localization/en_en/info.json b/localization/en_en/info.json deleted file mode 100644 index 401507f..0000000 --- a/localization/en_en/info.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "bot": { - "name": "What?", - "infotext": "Music bot written for use on /r/Norge's Discord Servers. It's open source! You can find it [HERE]({global.vars.repo})", - "spectext": "**Python:** [{_python_v}](https://www.python.org/)\n**Discord.py:** [{_discord_v}](https://github.com/Rapptz/discord.py/tree/rewrite)\n**Lavalink:** [{_lavalink_v}](https://github.com/Devoxin/Lavalink.py)", - "stattext": "**Guilds:** {_guilds}\n**Users:** {_members}", - "what": "What?", - "how": "How?", - "how_many": "How many?", - "how_long": "How long?", - "footer_text": "Made by /r/Norge, for /r/Norge" - }, - "music": { - "title": "Music info", - "players": "Players", - "listeners": "Listeners" - } -} \ No newline at end of file diff --git a/localization/en_en/misc.yaml b/localization/en_en/misc.yaml new file mode 100644 index 0000000..ac183c7 --- /dev/null +++ b/localization/en_en/misc.yaml @@ -0,0 +1,20 @@ +bot: + name: What? + infotext: Music bot written for use on /r/Norge's Discord Servers. It's open source! + You can find it [HERE]({global.vars.repo}) + spectext: |- + **Python:** [{_python_v}](https://www.python.org/) + **Discord.py:** [{_discord_v}](https://github.com/Rapptz/discord.py/tree/rewrite) + **Lavalink:** [{_lavalink_v}](https://github.com/Devoxin/Lavalink.py) + stattext: |- + **Guilds:** {_guilds} + **Users:** {_members} + what: What? + how: How? + how_many: How many? + how_long: How long? + footer_text: Made by /r/Norge +music: + title: Music info + players: Players + listeners: Listeners diff --git a/localization/en_en/music.json b/localization/en_en/music.json deleted file mode 100644 index 27b8748..0000000 --- a/localization/en_en/music.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "response": { - "nothing_found": "Nothing found!", - "not_playing": "Not playing.", - "nothing_playing": "Nothing playing", - "have_to_listen": "You have to be listening to the bot", - "playlist_enqued": "Playlist Enqueued!", - "requested_by": "Requested by", - "tracks": "tracks", - "seek": { - "missing_amount": "You need to specify the amount of seconds to skip!", - "track_moved": "Moved track to **{_position}**" - }, - "skip": { - "skipped": "Skipped.", - "require_vote": "{_skips} out of {_total} required haters have voted to skip." - }, - "skip_to": { - "invalid_pos": "Invalid specified position.", - "exceeds_queue": "The position exceeds the queue\\'s length.", - "skipped_to": "skipped to `{_title}` at position `{_pos}`" - }, - "stop": "⏹ | Stopped.", - "live": "🔴 LIVE", - "now": "Now Playing", - "queue": { - "empty": "The queue is empty", - "user_empty": "{_user}'s queue is empty", - "length": "**Queue** `{_length} songs`", - "userqueue": "**{_user}\\'s queue** `{_length}`", - "globaltrack":"`{_index}.` **[{_title}]({_uri})** _by <@{_user_id}>_\n", - "usertrack":"`{_index}({_globalindex}).` **[{_title}]({_uri})**\n", - "pageindicator":"Viewing page {_current}/{_total}" - }, - "my_queue": "Your queue is empty", - "resume": { - "resumed": "⏯ | Resumed", - "paused": "⏯ | Paused" - }, - "shuffle": "Your queue has been shuffled", - "out_of_range": "Positions must be between 1 and {_len}", - "move": { - "not_in_queue": "Check that the positions exist in your queue", - "moved_to": "{_title} moved from position {_from} to {_to} in your queue" - }, - "remove": "**{_title}** removed.", - "dj_removed": "**{_title}** queued by {_user} removed.", - "dj_remove_user": "Removed all songs queued by <@{_id}>.", - "search": "searching", - "results": "Results", - "time_expired": "Timer Expired", - "disconnect": { - "not_in_voice": "You\\'re not in my voicechannel!", - "disconnected": "Disconnected" - }, - "not_connected": "Not connected.", - "volume": { - "set_to": "Volume set to {_volume}", - "reset": "Volume and equalizer reset", - "out_of_range": "you can only set the volume between 50 and 125" - }, - "boost": { - "on": "Bass boost is on", - "off": "'Bass boost is off" - }, - "scrub": { - "add": "Adding controls", - "controls": "{music_controls}", - "_comment_controls": "scrub.controls read from music_controls.txt" - }, - "enqueue": { - "position": "position", - "playing_in": "Playing in", - "enqueued": "Song enqueued", - "estimated": "estimated", - "toolong": "Track too long. `{_length}>{_max}`" - }, - "history": { - "title": "Track history", - "current": "`Current` **[{_title}]({_uri})** _by <@{_id}>_", - "track": "`{_index}.` **[{_title}]({_uri})** _by <@{_id}>_", - "previous": "**{_len} Previous songs:**", - "empty": "There are no tracks in the history" - }, - "settings_check": { - "textchannel": "You can't use music commands in this channel.\nTry in: ", - "voicechannel": "I can only play music in: " - } - } -} \ No newline at end of file diff --git a/localization/en_en/music.yaml b/localization/en_en/music.yaml new file mode 100644 index 0000000..08aa8e8 --- /dev/null +++ b/localization/en_en/music.yaml @@ -0,0 +1,73 @@ +nothing_found: Nothing found! +not_playing: Not playing. +nothing_playing: Nothing playing +have_to_listen: You have to be listening to the bot +playlist_enqued: Playlist Enqueued! +requested_by: Requested by +tracks: tracks +seek: + missing_amount: You need to specify the amount of seconds to skip! + track_moved: Moved track to **{_position}** +skip: + skipped: Skipped. + require_vote: "{_skips} out of {_total} required haters have voted to skip." +skip_to: + invalid_pos: Invalid specified position. + exceeds_queue: The position exceeds the queue\'s length. + skipped_to: skipped to `{_title}` at position `{_pos}` +stop: "⏹ | Stopped." +live: "\U0001F534 LIVE" +now: Now Playing +queue: + empty: The queue is empty + user_empty: "{_user}'s queue is empty" + length: "**Queue** `{_length} songs`" + userqueue: "**{_user}\\'s queue** `{_length}`" + globaltrack: "`{_index}.` **[{_title}]({_uri})** _by <@{_user_id}>_\n" + usertrack: "`{_index}({_globalindex}).` **[{_title}]({_uri})**\n" + pageindicator: Viewing page {_current}/{_total} +my_queue: Your queue is empty +resume: + resumed: "⏯ | Resumed" + paused: "⏯ | Paused" +shuffle: Your queue has been shuffled +out_of_range: Positions must be between 1 and {_len} +move: + not_in_queue: Check that the positions exist in your queue + moved_to: "{_title} moved from position {_from} to {_to} in your queue" +remove: "**{_title}** removed." +dj_removed: "**{_title}** queued by {_user} removed." +dj_remove_user: Removed all songs queued by <@{_id}>. +search: searching +results: Results +time_expired: Timer Expired +disconnect: + not_in_voice: You\'re not in my voicechannel! + disconnected: Disconnected +not_connected: Not connected. +volume: + set_to: Volume set to {_volume} + reset: Volume and equalizer reset + out_of_range: you can only set the volume between 50 and 125 +boost: + 'on': Bass boost is on + 'off': Bass boost is off +scrub: + add: Adding controls + controls: "{music_controls}" + _comment_controls: scrub.controls read from music_controls.txt +enqueue: + position: position + playing_in: Playing in + enqueued: Song enqueued + estimated: estimated + toolong: Track too long. `{_length}>{_max}` +history: + title: Track history + current: "`Current` **[{_title}]({_uri})** _by <@{_id}>_" + track: "`{_index}.` **[{_title}]({_uri})** _by <@{_id}>_" + previous: "**{_len} Previous songs:**" + empty: There are no tracks in the history +settings_check: + textchannel: "You can't use music commands in this channel.\nTry in: " + voicechannel: 'I can only play music in: ' diff --git a/localization/nb_no/aliases.yaml b/localization/nb_no/aliases.yaml new file mode 100644 index 0000000..c109d6b --- /dev/null +++ b/localization/nb_no/aliases.yaml @@ -0,0 +1,27 @@ + +# Music aliases +play: [p, spill, s] +now: [np, nå] +queue: [q, kø, k] +myqueue: [mq, minkø, mk] +seek: [spol] +skip: [hopp] +skipto: [forceskip, hopptil, tvinghopp] +stop: [stopp] +pause: [resume, gjenoppta] +shuffle: [stokk] +move: [m, flytt, f] +remvove: [rem, fjern] +DJremove: [DJfjern, djfjern] +removeuser: [fjernbruker] +search: [søk, finn] +disconnect: [dc, kf, koblefra] +volume: [vol, volum, lydstyrke, lyd] +normalize: [normal, nl, normaliser] +boost: [bassboost, bassforsterker] +history: [h, hist, historie] +scrub: [kontroller, konsoll] + +# Other +info: [informasjon] +musicinfo: [musikkinfo, musikkinformasjon] diff --git a/localization/nb_no/commands.json b/localization/nb_no/commands.json deleted file mode 100644 index ee4ff4a..0000000 --- a/localization/nb_no/commands.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "not_available_dm": "Denne kommandoen er ikke tilgjengelig i DMs" -} \ No newline at end of file diff --git a/localization/nb_no/info.json b/localization/nb_no/info.json deleted file mode 100644 index 2b5d35b..0000000 --- a/localization/nb_no/info.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "bot": { - "name": "hva?", - "infotext": "Musikkbot skrevet for bruk på /r/Norge sine Discord Servere. Kildekoden er åpen! Den kan du finne [HER]({global.vars.repo})", - "spectext": "**Python:** [{_python_v}](https://www.python.org/)\n**Discord.py:** [{_discord_v}](https://github.com/Rapptz/discord.py/tree/rewrite)\n**Lavalink:** [{_lavalink_v}](https://github.com/Devoxin/Lavalink.py)", - "stattext": "**Tenarar:** {_guilds}\n**Brukere:** {_members}", - "what": "Hva?", - "how": "Hvordan?", - "how_many": "Hvor mange?", - "how_long": "Hvor lenge?", - "footer_text": "Laget av /r/Norge, for /r/Norge" - }, - "music": { - "title": "Musikkinfo", - "players": "Spillere", - "listeners": "Lyttere" - } -} \ No newline at end of file diff --git a/localization/nb_no/misc.yaml b/localization/nb_no/misc.yaml new file mode 100644 index 0000000..e17b8d4 --- /dev/null +++ b/localization/nb_no/misc.yaml @@ -0,0 +1,20 @@ +bot: + name: hva? + infotext: Musikkbot skrevet for bruk på /r/Norge sine Discord Servere. Kildekoden + er åpen! Den kan du finne [HER]({global.vars.repo}) + spectext: |- + **Python:** [{_python_v}](https://www.python.org/) + **Discord.py:** [{_discord_v}](https://github.com/Rapptz/discord.py/tree/rewrite) + **Lavalink:** [{_lavalink_v}](https://github.com/Devoxin/Lavalink.py) + stattext: |- + **Tenarar:** {_guilds} + **Brukere:** {_members} + what: Hva? + how: Hvordan? + how_many: Hvor mange? + how_long: Hvor lenge? + footer_text: Laget av /r/Norge, for /r/Norge +music: + title: Musikkinfo + players: Spillere + listeners: Lyttere diff --git a/localization/nb_no/music.json b/localization/nb_no/music.json deleted file mode 100644 index c0592c9..0000000 --- a/localization/nb_no/music.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "response": { - "nothing_found": "Kunne ikke finne sangen!", - "not_playing": "Spiller ikke av noe.", - "nothing_playing": "Ingenting spiller av", - "have_to_listen": "Du må høre på botten", - "playlist_enqued": "Spilleliste ble lagt til i køen!", - "requested_by": "Etterspurt av", - "tracks": "spor", - "seek": { - "missing_amount": "Du må spesifisere antall sekunder å spole!", - "track_moved": "Flyttet spor til **{_position}**" - }, - "skip": { - "skipped": "Hoppet over.", - "require_vote": "{_skips} av {_total} hatere må stemme for å hoppe over." - }, - "skip_to": { - "invalid_pos": "Ugyldig køposisjon.", - "exceeds_queue": "Posisjonen overgår køens lengde.", - "skipped_to": "hoppet til `{_title}` i posisjon `{_pos}`" - }, - "stop": "⏹ | Stoppet avspillingen.", - "live": "🔴 DIREKTE", - "now": "Spiller nå", - "queue": { - "empty": "Køen er tom", - "user_empty": "{_user} sin kø er tom", - "length": "**Kø** `{_length} sanger`", - "userqueue": "**{_user} sin kø** `{_length}` sanger", - "globaltrack":"`{_index}.` **[{_title}]({_uri})** _av <@{_user_id}>_\n", - "usertrack":"`{_index}({_globalindex}).` **[{_title}]({_uri})**\n", - "pageindicator":"Viser side {_current}/{_total}" - }, - "my_queue": "Din kø er tom", - "resume": { - "resumed": "⏯ | Avspilling gjenopptatt", - "paused": "⏯ | Pauset avspillingen" - }, - "shuffle": "Køen din har blitt omstokket", - "out_of_range": "Posisjonene må være mellom 1 og {_len}", - "move": { - "not_in_queue": "Sjekk at posisjonen eksisterer i køen din", - "moved_to": "`{_title}` flyttet fra plass `{_from}` til `{_to}` i køen din" - }, - "remove": "**{_title}** ble fjernet fra køen.", - "dj_removed": "**{_title}** som ble lagt til i køen av {_user}, ble fjernet.", - "dj_remove_user": "Fjernet alle sanger lagt til i køen av <@{_id}>.", - "search": "søker", - "results": "Resultater", - "time_expired": "Tid utgått", - "disconnect": { - "not_in_voice": "Du må være koblet til samme talekanal som meg!", - "disconnected": "Frakoblet" - }, - "not_connected": "Du er ikke koblet til en talekanal.", - "volume": { - "set_to": "Volum satt til {_volume}", - "reset": "Volum og equalizer resatt!", - "out_of_range": "Du må sette volumet til et tall mellom 50 og 125" - }, - "boost": { - "on": "Bassforsterkeren er på", - "off": "Bassforsterkeren er av" - }, - "scrub": { - "add": "Legger til kontrollere", - "controls": "{music_controls}", - "_comment_controls": "scrub.controls read from music_controls.txt" - }, - "enqueue": { - "position": "Køposisjon", - "playing_in": "Spiller av om", - "enqueued": "Ny sang lagt til i køen", - "estimated": "estimert", - "toolong": "Sang for lang. `{_length}>{_max}`" - }, - "history": { - "title": "Avspillingshistorikk", - "current": "`Spiller nå` **[{_title}]({_uri})** _av <@{_id}>_", - "track": "`{_index}.` **[{_title}]({_uri})** _av <@{_id}>_", - "previous": "**Tidligere sanger ({_len}):**", - "empty": "Ingen tidligere spilte sanger" - }, - "settings_check": { - "textchannel": "Du kan ikke bruke musikkommandoer i denne kanalen.\nPrøv i: ", - "voicechannel": "Jeg kan bare spille musikk i: " - } - } -} \ No newline at end of file diff --git a/localization/nb_no/music.yaml b/localization/nb_no/music.yaml new file mode 100644 index 0000000..0a7cce3 --- /dev/null +++ b/localization/nb_no/music.yaml @@ -0,0 +1,73 @@ +nothing_found: Kunne ikke finne sangen! +not_playing: Spiller ikke av noe. +nothing_playing: Ingenting spiller av +have_to_listen: Du må høre på botten +playlist_enqued: Spilleliste ble lagt til i køen! +requested_by: Etterspurt av +tracks: spor +seek: + missing_amount: Du må spesifisere antall sekunder å spole! + track_moved: Flyttet spor til **{_position}** +skip: + skipped: Hoppet over. + require_vote: "{_skips} av {_total} hatere må stemme for å hoppe over." +skip_to: + invalid_pos: Ugyldig køposisjon. + exceeds_queue: Posisjonen overgår køens lengde. + skipped_to: hoppet til `{_title}` i posisjon `{_pos}` +stop: "⏹ | Stoppet avspillingen." +live: "\U0001F534 DIREKTE" +now: Spiller nå +queue: + empty: Køen er tom + user_empty: "{_user} sin kø er tom" + length: "**Kø** `{_length} sanger`" + userqueue: "**{_user} sin kø** `{_length}` sanger" + globaltrack: "`{_index}.` **[{_title}]({_uri})** _av <@{_user_id}>_\n" + usertrack: "`{_index}({_globalindex}).` **[{_title}]({_uri})**\n" + pageindicator: Viser side {_current}/{_total} +my_queue: Din kø er tom +resume: + resumed: "⏯ | Avspilling gjenopptatt" + paused: "⏯ | Pauset avspillingen" +shuffle: Køen din har blitt omstokket +out_of_range: Posisjonene må være mellom 1 og {_len} +move: + not_in_queue: Sjekk at posisjonen eksisterer i køen din + moved_to: "`{_title}` flyttet fra plass `{_from}` til `{_to}` i køen din" +remove: "**{_title}** ble fjernet fra køen." +dj_removed: "**{_title}** som ble lagt til i køen av {_user}, ble fjernet." +dj_remove_user: Fjernet alle sanger lagt til i køen av <@{_id}>. +search: søker +results: Resultater +time_expired: Tid utgått +disconnect: + not_in_voice: Du må være koblet til samme talekanal som meg! + disconnected: Frakoblet +not_connected: Du er ikke koblet til en talekanal. +volume: + set_to: Volum satt til {_volume} + reset: Volum og equalizer resatt! + out_of_range: Du må sette volumet til et tall mellom 50 og 125 +boost: + 'on': Bassforsterkeren er på + 'off': Bassforsterkeren er av +scrub: + add: Legger til kontrollere + controls: "{music_controls}" + _comment_controls: scrub.controls read from music_controls.txt +enqueue: + position: Køposisjon + playing_in: Spiller av om + enqueued: Ny sang lagt til i køen + estimated: estimert + toolong: Sang for lang. `{_length}>{_max}` +history: + title: Avspillingshistorikk + current: "`Spiller nå` **[{_title}]({_uri})** _av <@{_id}>_" + track: "`{_index}.` **[{_title}]({_uri})** _av <@{_id}>_" + previous: "**Tidligere sanger ({_len}):**" + empty: Ingen tidligere spilte sanger +settings_check: + textchannel: "Du kan ikke bruke musikkommandoer i denne kanalen.\nPrøv i: " + voicechannel: 'Jeg kan bare spille musikk i: ' diff --git a/localization/nn_no/aliases.yaml b/localization/nn_no/aliases.yaml new file mode 100644 index 0000000..cfdaaec --- /dev/null +++ b/localization/nn_no/aliases.yaml @@ -0,0 +1,27 @@ + +# Music aliases +play: [p, spel, s] +now: [np, 'no'] +queue: [q, kø, k] +myqueue: [mq, minkø, mk] +seek: [spol] +skip: [hopp] +skipto: [forceskip, hopptil, tvinghopp] +stop: [stopp] +pause: [resume, gjenoppta] +shuffle: [stokk] +move: [m, flytt, f] +remvove: [rem, fjern] +DJremove: [DJfjern, djfjern] +removeuser: [fjernbruker] +search: [søk, finn] +disconnect: [dc, kf, koblefrå] +volume: [vol, volum, lydstyrke, lyd] +normalize: [normal, nl, normaliser] +boost: [bassboost, bassforsterkar] +history: [h, hist, historie] +scrub: [kontroller, konsoll] + +# Other +info: [informasjon] +musicinfo: [musikkinfo, musikkinformasjon] diff --git a/localization/nn_no/commands.json b/localization/nn_no/commands.json deleted file mode 100644 index 1a2c83c..0000000 --- a/localization/nn_no/commands.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "not_available_dm": "Denna kommandoa er ikkje tilgjengeleg i direkte meldingar DMs" -} \ No newline at end of file diff --git a/localization/nn_no/info.json b/localization/nn_no/info.json deleted file mode 100644 index a579c6e..0000000 --- a/localization/nn_no/info.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "bot": { - "name": "Kva?", - "infotext": "Musikkbot skreve til bruk på /r/Norge sine Discord Serverar. Kjeldekoda er ope! Dei kan du finna [HER]({global.vars.repo})", - "spectext": "**Python:** [{_python_v}](https://www.python.org/)\n**Discord.py:** [{_discord_v}](https://github.com/Rapptz/discord.py/tree/rewrite)\n**Lavalink:** [{_lavalink_v}](https://github.com/Devoxin/Lavalink.py)", - "stattext": "**Tenarar:** {_guilds}\n**Brukarar:** {_members}", - "what": "Kva?", - "how": "Korleis?", - "how_many": "Kor mange?", - "how_long": "Kor lengje?", - "footer_text": "Laga av /r/Norge, for /r/Norge" - }, - "music": { - "title": "Musikkinformasjon", - "players": "Spelarar", - "listeners": "Lyttarar" - } -} \ No newline at end of file diff --git a/localization/nn_no/misc.yaml b/localization/nn_no/misc.yaml new file mode 100644 index 0000000..8d2d0f6 --- /dev/null +++ b/localization/nn_no/misc.yaml @@ -0,0 +1,20 @@ +bot: + name: Kva? + infotext: Musikkbot skreve til bruk på /r/Norge sine Discord Serverar. Kjeldekoda + er ope! Dei kan du finna [HER]({global.vars.repo}) + spectext: |- + **Python:** [{_python_v}](https://www.python.org/) + **Discord.py:** [{_discord_v}](https://github.com/Rapptz/discord.py/tree/rewrite) + **Lavalink:** [{_lavalink_v}](https://github.com/Devoxin/Lavalink.py) + stattext: |- + **Tenarar:** {_guilds} + **Brukarar:** {_members} + what: Kva? + how: Korleis? + how_many: Kor mange? + how_long: Kor lengje? + footer_text: Laga av /r/Norge, for /r/Norge +music: + title: Musikkinformasjon + players: Spelarar + listeners: Lyttarar diff --git a/localization/nn_no/music.json b/localization/nn_no/music.json deleted file mode 100644 index 788c1cf..0000000 --- a/localization/nn_no/music.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "response": { - "nothing_found": "Orsak, kunne ikkje finna songen!", - "not_playing": "Spelar ikkje noko.", - "nothing_playing": "Ingenting speles av", - "have_to_listen": "Dykk må høyra på botten", - "playlist_enqued": "Spellista vart lagt til i køen!", - "requested_by": "Etterspurd av", - "tracks": "spor", - "seek": { - "missing_amount": "Dykk må klargjera antal sekundar å spola!", - "track_moved": "Flytta spor til **{_position}**" - }, - "skip": { - "skipped": "Hoppa over.", - "require_vote": "{_skips} av {_total} hatarar må stemma for å hoppa over." - }, - "skip_to": { - "invalid_pos": "Ugild køposisjon.", - "exceeds_queue": "Posisjona overgår køas lengde.", - "skipped_to": "hoppa til `{_title}` i posisjon `{_pos}`" - }, - "stop": "⏹ | Stoppa avspelinga.", - "live": "🔴 DIREKTE", - "now": "Spelar no", - "queue": { - "empty": "Køa er tom", - "user_empty": "{_user} sin kø er tom", - "length": "**Kø** `{_length} songar`", - "userqueue": "Køen til **{_user}** `{_length}` songar", - "globaltrack":"`{_index}.` **[{_title}]({_uri})** _av <@{_user_id}>_\n", - "usertrack":"`{_index}({_globalindex}).` **[{_title}]({_uri})**\n", - "pageindicator":"Viser side {_current}/{_total}" - }, - "my_queue": "Din kø er tom", - "resume": { - "resumed": "⏯ | Avspeling oppattatt", - "paused": "⏯ | Pauset avspeling" - }, - "shuffle": "Køa di har vorte omstokka", - "out_of_range": "Posisjonane må væra millom 1 og {_len}", - "move": { - "not_in_queue": "Kontrollar at posisjona eksisterar i køa di", - "moved_to": "`{_title}` flytta frå plass `{_from}` til `{_to}` i køa di" - }, - "remove": "**{_title}** vart fjerna frå køa.", - "dj_removed": "**{_title}** som vart lagt til i køa av {_user}, vart fjerna.", - "dj_remove_user": "Fjerna alle songar lagt til i køa av <@{_id}>.", - "search": "søkjar", - "results": "Resultatar", - "time_expired": "Tid utgått", - "disconnect": { - "not_in_voice": "Dykk må være tilkopla same talekanal som meg!", - "disconnected": "Fråkopla" - }, - "not_connected": "Dykk er ikkje kopla til ein talekanal.", - "volume": { - "set_to": "Volum satt til {_volume}", - "reset": "Volum og utjevnar igjensatt!", - "out_of_range": "Du må setja volumet til eit tal mellom femti og hundreogtjuefem" - }, - "boost": { - "on": "Bassforsterkaren er på", - "off": "Bassforsterkaren er av" - }, - "scrub": { - "add": "Legjar til kontrollera", - "controls": "{music_controls}", - "_comment_controls": "scrub.controls read from music_controls.txt" - }, - "enqueue": { - "position": "Køposisjon", - "playing_in": "Spelar av om", - "enqueued": "Ny song lagt til i køa", - "estimated": "estimert", - "toolong": "Song for lang. `{_length}>{_max}`" - }, - "history": { - "title": "Avspelingshistorikk", - "current": "`Spelar no` **[{_title}]({_uri})** _av <@{_id}>_", - "track": "`{_index}.` **[{_title}]({_uri})** _av <@{_id}>_", - "previous": "**Tidlegare songar ({_len}):**", - "empty": "Ingen tidlegare spelte songar" - }, - "settings_check": { - "textchannel": "Du kan ikkje bruke musikkommandoar i denne kanalen.\nPrøv i: ", - "voicechannel": "Eg kan berre spele musikk i: " - } - } -} \ No newline at end of file diff --git a/localization/nn_no/music.yaml b/localization/nn_no/music.yaml new file mode 100644 index 0000000..d30191a --- /dev/null +++ b/localization/nn_no/music.yaml @@ -0,0 +1,73 @@ +nothing_found: Orsak, kunne ikkje finna songen! +not_playing: Spelar ikkje noko. +nothing_playing: Ingenting speles av +have_to_listen: Dykk må høyra på botten +playlist_enqued: Spellista vart lagt til i køen! +requested_by: Etterspurd av +tracks: spor +seek: + missing_amount: Dykk må klargjera antal sekundar å spola! + track_moved: Flytta spor til **{_position}** +skip: + skipped: Hoppa over. + require_vote: "{_skips} av {_total} hatarar må stemma for å hoppa over." +skip_to: + invalid_pos: Ugild køposisjon. + exceeds_queue: Posisjona overgår køens lengde. + skipped_to: hoppa til `{_title}` i posisjon `{_pos}` +stop: "⏹ | Stoppa avspelinga." +live: "\U0001F534 DIREKTE" +now: Spelar no +queue: + empty: Køa er tom + user_empty: "{_user} sin kø er tom" + length: "**Kø** `{_length} songar`" + userqueue: Køen til **{_user}** `{_length}` songar + globaltrack: "`{_index}.` **[{_title}]({_uri})** _av <@{_user_id}>_\n" + usertrack: "`{_index}({_globalindex}).` **[{_title}]({_uri})**\n" + pageindicator: Viser side {_current}/{_total} +my_queue: Din kø er tom +resume: + resumed: "⏯ | Avspeling oppattatt" + paused: "⏯ | Pauset avspeling" +shuffle: Køa di har vorte omstokka +out_of_range: Posisjonane må væra millom 1 og {_len} +move: + not_in_queue: Kontrollar at posisjona eksisterar i køen din + moved_to: "`{_title}` flytta frå plass `{_from}` til `{_to}` i køen din" +remove: "**{_title}** vart fjerna frå køen." +dj_removed: "**{_title}** som vart lagt til i køen av {_user}, vart fjerna." +dj_remove_user: Fjerna alle songar lagt til i køen av <@{_id}>. +search: søkjar +results: Resultatar +time_expired: Tid utgått +disconnect: + not_in_voice: Dykk må være tilkopla same talekanal som meg! + disconnected: Fråkopla +not_connected: Dykk er ikkje kopla til ein talekanal. +volume: + set_to: Volum satt til {_volume} + reset: Volum og utjevnar igjensatt! + out_of_range: Du må setja volumet til eit tal mellom femti og hundreogtjuefem +boost: + 'on': Bassforsterkaren er på + 'off': Bassforsterkaren er av +scrub: + add: Legjar til kontrollera + controls: "{music_controls}" + _comment_controls: scrub.controls read from music_controls.txt +enqueue: + position: Køposisjon + playing_in: Spelar av om + enqueued: Ny song lagt til i køen + estimated: estimert + toolong: Song for lang. `{_length}>{_max}` +history: + title: Avspelingshistorikk + current: "`Spelar no` **[{_title}]({_uri})** _av <@{_id}>_" + track: "`{_index}.` **[{_title}]({_uri})** _av <@{_id}>_" + previous: "**Tidlegare songar ({_len}):**" + empty: Ingen tidlegare spelte songar +settings_check: + textchannel: "Du kan ikkje bruke musikkommandoar i denne kanalen.\nPrøv i: " + voicechannel: 'Eg kan berre spele musikk i: ' From 2fa254af7fbfdb5e3effbb7c12888743ec268c2d Mon Sep 17 00:00:00 2001 From: Ev-1 <33662061+Ev-1@users.noreply.github.com> Date: Sun, 17 Feb 2019 13:50:41 +0100 Subject: [PATCH 3/8] Load lavalink cogs separately --- bot.py | 20 ++++++++++++++------ cogs/misc.py | 6 ------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/bot.py b/bot.py index d5c325f..c4db334 100644 --- a/bot.py +++ b/bot.py @@ -13,6 +13,10 @@ from cogs.utils.alias import Aliaser from cogs.utils.context import Context +with codecs.open("data/config.yaml", 'r', encoding='utf8') as f: + conf = yaml.safe_load(f) + + initial_extensions = [ 'cogs.cogs', 'cogs.botsettings', @@ -20,8 +24,10 @@ initial_extensions = [ ] -with codecs.open("data/config.yaml", 'r', encoding='utf8') as f: - conf = yaml.safe_load(f) +on_ready_extensions = [ + 'cogs.music', + 'cogs.musicevents' +] def _get_prefix(bot, message): @@ -77,7 +83,6 @@ class Bot(commands.Bot): traceback.print_tb(tb) print(err) - async def on_message(self, message): if message.author.bot: return @@ -103,13 +108,16 @@ class Bot(commands.Bot): if self.debug: print('\n\nDebug mode') + for extension in on_ready_extensions: + try: + self.load_extension(extension) + except Exception as e: + print(e) + print(f'\nLogged in as: {self.user.name}' + f' in {len(self.guilds)} servers.') print(f'Version: {discord.__version__}\n') - self.load_extension('cogs.music') - self.load_extension('cogs.musicevents') - await self.change_presence(activity=discord.Game(type=0, name=conf["bot"]["playing status"]), status=discord.Status.online) diff --git a/cogs/misc.py b/cogs/misc.py index e1ed385..22aa746 100644 --- a/cogs/misc.py +++ b/cogs/misc.py @@ -118,12 +118,6 @@ class Misc: ) await ctx.send(embed=embed) - @commands.command() - @checks.is_even() - async def only_me(self, ctx): - print(ctx.localizer.format_str("{nothing_found}")) - await ctx.send('Only you!') - def setup(bot): bot.add_cog(Misc(bot)) From 4a374bcd2a75e4c4f64eff4f1999c090e36fb9a8 Mon Sep 17 00:00:00 2001 From: Ev-1 <33662061+Ev-1@users.noreply.github.com> Date: Thu, 21 Feb 2019 14:48:19 +0100 Subject: [PATCH 4/8] Aliases for subcommands started --- bot.py | 11 ++++++---- cogs/utils/alias.py | 49 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/bot.py b/bot.py index c4db334..4073a19 100644 --- a/bot.py +++ b/bot.py @@ -6,6 +6,7 @@ import traceback import yaml from discord.ext import commands +from discord.ext.commands.view import StringView from cogs.utils.settings import Settings from cogs.utils.localizer import Localizer from cogs.utils.localizer import LocalizerWrapper @@ -90,11 +91,13 @@ class Bot(commands.Bot): async def process_commands(self, message): ctx = await self.get_context(message, cls=Context) - if not ctx.command: - command = self.aliaser.get_command(ctx.locale, ctx.invoked_with) - if command is not None: - ctx.command = self.get_command(command) + # Replace aliases with commands + ctx = self.aliaser.get_command(ctx) + if ctx.command and isinstance(ctx.command, commands.GroupMixin): + ctx = self.aliaser.subcommand_from_alias(ctx, ctx.command) + + # Add the localizer if ctx.command and ctx.command.cog_name: ctx.localizer = LocalizerWrapper(self.localizer, ctx.locale, ctx.command.cog_name.lower()) else: diff --git a/cogs/utils/alias.py b/cogs/utils/alias.py index 252c011..c5cf2fe 100644 --- a/cogs/utils/alias.py +++ b/cogs/utils/alias.py @@ -1,7 +1,11 @@ +import discord import yaml + from glob import glob from os import path +from discord.ext import commands + class Aliaser: def __init__(self, localization_folder, default_lang): self.localization_folder = path.realpath(localization_folder) @@ -30,10 +34,49 @@ class Aliaser: data = yaml.load(f) self.localization_table[lang] = {'aliases': data, 'commands': self._invert(data)} - def get_command(self, locale, alias): + def cmd_from_alias(self, locale, alias, default=None): locale = self.localization_table[locale] - return locale['commands'].get(alias, None) + return locale['commands'].get(alias, default) def get_alias(self, locale, command): locale = self.localization_table[locale] - return locale['aliases'].get(command, []) \ No newline at end of file + return locale['aliases'].get(command, []) + + def get_command(self, ctx): + ctx.view.undo() + alias = ctx.view.get_word() + command = self.cmd_from_alias(ctx.locale, alias, alias) + ctx.invoked_with = command + ctx.command = ctx.bot.all_commands.get(command) + return ctx + + def subcommand_from_alias(self, ctx, group): + """ Recursicely replaces all subcommand aliases with subcommands.""" + view = ctx.view + prev = view.previous + idx = view.index + + # get the alias used + view.skip_ws() + alias = view.get_word() + subcmd = self.cmd_from_alias(ctx.locale, alias, alias) + + # Replace the alias in the command + view.buffer = view.buffer.replace(alias, subcmd) + + # Update the view to account for difference in length + strdiff = len(subcmd) - len(alias) + view.end += strdiff + view.index += strdiff + + # Get the subcommand + sub = group.all_commands.get(subcmd, None) + + # Translate any subsubcommands + if sub and isinstance(sub, commands.GroupMixin): + self.subcommand_from_alias(ctx, sub) + + # Reset the view indexes + view.index = idx + view.previous = prev + return ctx \ No newline at end of file From 6f6d751c83997a29fd0d3eb346b6a9596701d1eb Mon Sep 17 00:00:00 2001 From: Ev-1 <33662061+Ev-1@users.noreply.github.com> Date: Fri, 22 Feb 2019 17:11:19 +0100 Subject: [PATCH 5/8] Localized per guild aliases for subcommands --- bot.py | 6 +- cogs/music.py | 3 +- cogs/{botsettings.py => settings.py} | 6 +- cogs/utils/alias.py | 56 +++++++++++++++---- .../utils/{settings.py => settingsmanager.py} | 0 localization/en_en/aliases.yaml | 46 +++++++++++++-- localization/nb_no/aliases.yaml | 18 +++++- localization/nn_no/aliases.yaml | 2 +- 8 files changed, 111 insertions(+), 26 deletions(-) rename cogs/{botsettings.py => settings.py} (99%) rename cogs/utils/{settings.py => settingsmanager.py} (100%) diff --git a/bot.py b/bot.py index 4073a19..d362a97 100644 --- a/bot.py +++ b/bot.py @@ -7,7 +7,7 @@ import yaml from discord.ext import commands from discord.ext.commands.view import StringView -from cogs.utils.settings import Settings +from cogs.utils.settingsmanager import Settings from cogs.utils.localizer import Localizer from cogs.utils.localizer import LocalizerWrapper from cogs.utils.alias import Aliaser @@ -20,7 +20,7 @@ with codecs.open("data/config.yaml", 'r', encoding='utf8') as f: initial_extensions = [ 'cogs.cogs', - 'cogs.botsettings', + 'cogs.settings', 'cogs.misc' ] @@ -95,7 +95,7 @@ class Bot(commands.Bot): # Replace aliases with commands ctx = self.aliaser.get_command(ctx) if ctx.command and isinstance(ctx.command, commands.GroupMixin): - ctx = self.aliaser.subcommand_from_alias(ctx, ctx.command) + ctx = self.aliaser.get_subcommand(ctx, ctx.command, [str(ctx.command)]) # Add the localizer if ctx.command and ctx.command.cog_name: diff --git a/cogs/music.py b/cogs/music.py index 3211f08..7bcccf1 100644 --- a/cogs/music.py +++ b/cogs/music.py @@ -16,7 +16,7 @@ from typing import Optional from .utils import checks, RoxUtils, timeformatter from .utils.mixplayer import MixPlayer from .utils.embedscroller import QueueScroller -from .utils.localizer import LocalizerWrapper + time_rx = re.compile('[0-9]+') url_rx = re.compile('https?:\\/\\/(?:www\\.)?.+') @@ -670,7 +670,6 @@ class Music: if voice_channels: if voice_channel.id not in voice_channels: - ctx.localizer = self.getLocalizer(ctx.guild) response = ctx.localizer.format_str('{settings_check.voicechannel}') for channel_id in voice_channels: channel = ctx.guild.get_channel(channel_id) diff --git a/cogs/botsettings.py b/cogs/settings.py similarity index 99% rename from cogs/botsettings.py rename to cogs/settings.py index 9d8ff21..d8b1497 100644 --- a/cogs/botsettings.py +++ b/cogs/settings.py @@ -5,7 +5,7 @@ import codecs from discord.ext import commands from cogs.utils import checks -class BotSettings: +class Settings: def __init__(self, bot): self.bot = bot self.settings = self.bot.settings @@ -19,7 +19,7 @@ class BotSettings: return formatted[:-2] @checks.is_admin() - @commands.group(name='set', hidden=True) + @commands.group(name='settings', hidden=True) async def _set(self, ctx): if ctx.invoked_subcommand is None: await self.current_settings.invoke(ctx) @@ -227,4 +227,4 @@ class BotSettings: def setup(bot): - bot.add_cog(BotSettings(bot)) + bot.add_cog(Settings(bot)) diff --git a/cogs/utils/alias.py b/cogs/utils/alias.py index c5cf2fe..8593d81 100644 --- a/cogs/utils/alias.py +++ b/cogs/utils/alias.py @@ -13,11 +13,20 @@ class Aliaser: self.index_localizations() self.load_localizations() - def _invert(self, d): + def _gen_alias_dict(self, commands): + """ Reverses the direction of a dict of commans→aliases to be alias→command. """ inverted = {} - for command in d: - for alias in d[command]: - inverted[alias] = command + subcommands = {} + for cmd, properties in commands.items(): + if isinstance(properties, list): + for alias in properties: + inverted[alias] = cmd + else: + for alias in properties['aliases']: + inverted[alias] = cmd + if properties.get('sub_commands', None): + subcommands[cmd] = self._gen_alias_dict(properties['sub_commands']) + inverted['sub_commands'] = subcommands return inverted def index_localizations(self): @@ -32,25 +41,48 @@ class Aliaser: for lang in self.localization_table.keys(): with open(path.join(self.localization_folder, lang, "aliases.yaml"), "r", encoding='utf-8') as f: data = yaml.load(f) - self.localization_table[lang] = {'aliases': data, 'commands': self._invert(data)} + self.localization_table[lang] = {'aliases': data, 'commands': self._gen_alias_dict(data)} - def cmd_from_alias(self, locale, alias, default=None): + def convert_alias(self, locale, alias, default=None, parents=[]): locale = self.localization_table[locale] - return locale['commands'].get(alias, default) + + # Traverse through the alias tree as dictated by the parents list + def traverse(alias_tree, parents, alias): + # Return the command when no more parents exist + if not parents: + return alias_tree.get(alias, None) + parent = parents.pop(0) + sub_commands = alias_tree.get('sub_commands', None) + if not sub_commands: + return None + alias_tree = sub_commands.get(parent, None) + if not alias_tree: + return None + return traverse(alias_tree, parents, alias) + + alias_tree = locale['commands'] + command = traverse(alias_tree, parents, default) + if command: + return command + return default def get_alias(self, locale, command): locale = self.localization_table[locale] return locale['aliases'].get(command, []) def get_command(self, ctx): + """ Get a top level command. """ + if not ctx.prefix: + ctx.command = None + return ctx ctx.view.undo() alias = ctx.view.get_word() - command = self.cmd_from_alias(ctx.locale, alias, alias) + command = self.convert_alias(ctx.locale, alias, alias) ctx.invoked_with = command ctx.command = ctx.bot.all_commands.get(command) return ctx - def subcommand_from_alias(self, ctx, group): + def get_subcommand(self, ctx, group, parents=[]): """ Recursicely replaces all subcommand aliases with subcommands.""" view = ctx.view prev = view.previous @@ -59,7 +91,9 @@ class Aliaser: # get the alias used view.skip_ws() alias = view.get_word() - subcmd = self.cmd_from_alias(ctx.locale, alias, alias) + + subcmd = self.convert_alias(ctx.locale, alias, alias, parents.copy()) + parents.append(subcmd) # Replace the alias in the command view.buffer = view.buffer.replace(alias, subcmd) @@ -74,7 +108,7 @@ class Aliaser: # Translate any subsubcommands if sub and isinstance(sub, commands.GroupMixin): - self.subcommand_from_alias(ctx, sub) + self.get_subcommand(ctx, sub, parents) # Reset the view indexes view.index = idx diff --git a/cogs/utils/settings.py b/cogs/utils/settingsmanager.py similarity index 100% rename from cogs/utils/settings.py rename to cogs/utils/settingsmanager.py diff --git a/localization/en_en/aliases.yaml b/localization/en_en/aliases.yaml index d190bc1..08eeb6a 100644 --- a/localization/en_en/aliases.yaml +++ b/localization/en_en/aliases.yaml @@ -1,5 +1,9 @@ +# Aliases for each of the commands in the the bot(except the forgotten onces.) +# Aliases without subcommands don't need to have "aliases:", specified. +# For commands with subcommands you need to have one subcategory called aliases and one called subcommands. -# Music aliases + +# Music play: [p] now: [np, nowplaying] queue: [q] @@ -11,7 +15,7 @@ stop: [] pause: [resume] shuffle: [] move: [m] -remvove: [rem] +remove: [rem] DJremove: [djremove] removeuser: [] search: [s] @@ -22,6 +26,38 @@ boost: [bassboost] history: [h] scrub: [] -# Other -info: [] -musicinfo: [] +# Misc +info: [] +musicinfo: [] +uptime: [] +ping: [] +guilds: [] +reloadlocale: [] +reloadalias: [] + +# Settings +settings: + aliases: [set] + sub_commands: + current: [show] + serverlocale: [lang] + djroles: [] + dynamicmax: [] + musicchannels: [vc] + listenchannels: [] + textchannels: [tc] + maxduration: [] + modrole: [] + resetprefix: [] + serverprefix: [] + threshold: [] + +# Cogs +cogs: + aliases: [] + sub_commands: + load: [] + unload: [] + reload: [] + reloadall: [] + shutdown: [] \ No newline at end of file diff --git a/localization/nb_no/aliases.yaml b/localization/nb_no/aliases.yaml index c109d6b..994e3b9 100644 --- a/localization/nb_no/aliases.yaml +++ b/localization/nb_no/aliases.yaml @@ -11,7 +11,7 @@ stop: [stopp] pause: [resume, gjenoppta] shuffle: [stokk] move: [m, flytt, f] -remvove: [rem, fjern] +remove: [rem, fjern] DJremove: [DJfjern, djfjern] removeuser: [fjernbruker] search: [søk, finn] @@ -25,3 +25,19 @@ scrub: [kontroller, konsoll] # Other info: [informasjon] musicinfo: [musikkinfo, musikkinformasjon] + +settings: + aliases: [innstillinger] + sub_commands: + serverlocale: [språk] + current: [gjeldende] + djroles: [djroller] + dynamicmax: [dynamiskmaks] + listenchannels: [] + maxduration: [maksvarighet] + modrole: [modrolle] + musicchannels: [musikkanaler] + resetprefix: [] + serverprefix: [serverprefiks] + textchannels: [tekstkanaler] + threshold: [grense] \ No newline at end of file diff --git a/localization/nn_no/aliases.yaml b/localization/nn_no/aliases.yaml index cfdaaec..bf694eb 100644 --- a/localization/nn_no/aliases.yaml +++ b/localization/nn_no/aliases.yaml @@ -11,7 +11,7 @@ stop: [stopp] pause: [resume, gjenoppta] shuffle: [stokk] move: [m, flytt, f] -remvove: [rem, fjern] +remove: [rem, fjern] DJremove: [DJfjern, djfjern] removeuser: [fjernbruker] search: [søk, finn] From c25c495f7fd35aec1a64df60c421151931d6b708 Mon Sep 17 00:00:00 2001 From: Ev-1 <33662061+Ev-1@users.noreply.github.com> Date: Fri, 22 Feb 2019 17:49:46 +0100 Subject: [PATCH 6/8] Partial translation of settings --- cogs/settings.py | 23 ++++++++++++----------- localization/en_en/settings.yaml | 12 ++++++++++++ localization/nb_no/settings.yaml | 12 ++++++++++++ localization/nn_no/settings.yaml | 12 ++++++++++++ 4 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 localization/en_en/settings.yaml create mode 100644 localization/nb_no/settings.yaml create mode 100644 localization/nn_no/settings.yaml diff --git a/cogs/settings.py b/cogs/settings.py index d8b1497..d9af0b9 100644 --- a/cogs/settings.py +++ b/cogs/settings.py @@ -178,50 +178,51 @@ class Settings: @commands.guild_only() @_set.command(name='current') async def current_settings(self, ctx): - embed = discord.Embed(title='Settings', color=ctx.me.color) - embed.description = f'Current settings for {ctx.guild.name}' + embed = discord.Embed(title='{current.title}', color=ctx.me.color) + embed.description = '{current.description}' embed.set_thumbnail(url=ctx.guild.icon_url) prefixes = self.bot.settings.get(ctx.guild, 'prefixes', 'default_prefix') - embed.add_field(name='Prefix', value=self.format_prefixes(prefixes)) + embed.add_field(name='{current.prefix}', value=self.format_prefixes(prefixes)) locale = f"{self.bot.settings.get(ctx.guild, 'locale', 'default_locale')}" - embed.add_field(name='Locale', value=locale) + embed.add_field(name='{current.locale}', value=locale) threshold = self.bot.settings.get(ctx.guild, 'vote_threshold', 50) - embed.add_field(name='Vote threshold', value=f'{threshold}%') + embed.add_field(name='{current.threshold}', value=f'{threshold}%') is_dynamic = self.bot.settings.get(ctx.guild, 'duration.is_dynamic', 'default_is_dynamic') - embed.add_field(name='Dynamic max duration', value=is_dynamic) + embed.add_field(name='{current.dynamicmax}', value=is_dynamic) duration = self.bot.settings.get(ctx.guild, 'maxduration') if duration: - embed.add_field(name='Max track duration', value=f'{duration} minutes') + embed.add_field(name='{current.maxduration}', value=f'{duration} minutes') textchannels = self.bot.settings.get(ctx.guild, 'channels.text') if textchannels: channels = [ctx.guild.get_channel(channel) for channel in textchannels] mentioned = [channel.mention for channel in channels if channel is not None] - embed.add_field(name='Text channels', value='\n'.join(mentioned)) + embed.add_field(name='{current.textchannels}', value='\n'.join(mentioned)) voicechannels = self.bot.settings.get(ctx.guild, 'channels.music') if voicechannels: channels = [ctx.guild.get_channel(channel) for channel in voicechannels] mentioned = [channel.name for channel in channels if channel is not None] - embed.add_field(name='Music channels', value='\n'.join(mentioned)) + embed.add_field(name='{current.musicchannels}', value='\n'.join(mentioned)) listenchannels = self.bot.settings.get(ctx.guild, 'channels.listen_only') if listenchannels: channels = [ctx.guild.get_channel(channel) for channel in listenchannels] mentioned = [channel.name for channel in channels if channel is not None] - embed.add_field(name='Listen only channels', value='\n'.join(mentioned)) + embed.add_field(name='{current.listenchannels}', value='\n'.join(mentioned)) djroles = self.bot.settings.get(ctx.guild, 'roles.dj') if djroles: roles = [ctx.guild.get_role(role) for role in djroles] mentioned = [role.name for role in roles if role is not None] - embed.add_field(name='Dj roles', value=', '.join(mentioned)) + embed.add_field(name='{current.djroles}', value=', '.join(mentioned)) + embed = ctx.localizer.format_embed(embed, _guild=ctx.guild.name) msg = await ctx.send(embed=embed) return msg diff --git a/localization/en_en/settings.yaml b/localization/en_en/settings.yaml new file mode 100644 index 0000000..38a0d8e --- /dev/null +++ b/localization/en_en/settings.yaml @@ -0,0 +1,12 @@ +current: + title: Settings + description: Current settings for {_guild} + prefix: Prefix + locale: Locale + threshold: Vote threshold + dynamicmax: Dynamic max duration + maxduration: Max track duration + textchannels: Text channels + musicchannels: Music channels + listenchannels: Listen only channels + djroles: DJ roles diff --git a/localization/nb_no/settings.yaml b/localization/nb_no/settings.yaml new file mode 100644 index 0000000..52da183 --- /dev/null +++ b/localization/nb_no/settings.yaml @@ -0,0 +1,12 @@ +current: + title: Innstillinger + description: Gjeldende innstillinger for {_guild} + prefix: Prefiks + locale: Språk + threshold: Stemmegrense + dynamicmax: Dynamisk maksvarighet + maxduration: Maks sanglengde + textchannels: Tekstkanaler + musicchannels: Musikkanaler + listenchannels: Kun lyd-kanaler + djroles: DJroller diff --git a/localization/nn_no/settings.yaml b/localization/nn_no/settings.yaml new file mode 100644 index 0000000..18180f9 --- /dev/null +++ b/localization/nn_no/settings.yaml @@ -0,0 +1,12 @@ +current: + title: Innstillingar + description: Gjeldande innstillingar for {_guild} + prefix: Prefiks + locale: Språk + threshold: Stemmegrense + dynamicmax: Dynamisk maksvarigskap + maxduration: Maks songlengde + textchannels: Tekstkanalar + musicchannels: Musikkanalar + listenchannels: Kun lyd-kanalar + djroles: DJroller From 612de1a450dd32360c4dcd2549f806a198fe3638 Mon Sep 17 00:00:00 2001 From: Ev-1 <33662061+Ev-1@users.noreply.github.com> Date: Sat, 23 Feb 2019 11:57:12 +0100 Subject: [PATCH 7/8] Fixed quotes in yaml --- localization/nb_no/settings.yaml | 2 +- localization/nn_no/settings.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/localization/nb_no/settings.yaml b/localization/nb_no/settings.yaml index 52da183..cd28f11 100644 --- a/localization/nb_no/settings.yaml +++ b/localization/nb_no/settings.yaml @@ -8,5 +8,5 @@ current: maxduration: Maks sanglengde textchannels: Tekstkanaler musicchannels: Musikkanaler - listenchannels: Kun lyd-kanaler + listenchannels: '"Kun lyd"-kanaler' djroles: DJroller diff --git a/localization/nn_no/settings.yaml b/localization/nn_no/settings.yaml index 18180f9..056364b 100644 --- a/localization/nn_no/settings.yaml +++ b/localization/nn_no/settings.yaml @@ -8,5 +8,5 @@ current: maxduration: Maks songlengde textchannels: Tekstkanalar musicchannels: Musikkanalar - listenchannels: Kun lyd-kanalar + listenchannels: '"Kun lyd"-kanalar' djroles: DJroller From a224033b66e2f5e9b2e8aeb6094849651e895639 Mon Sep 17 00:00:00 2001 From: Ev-1 <33662061+Ev-1@users.noreply.github.com> Date: Sat, 23 Feb 2019 12:31:57 +0100 Subject: [PATCH 8/8] fix to local check. --- cogs/music.py | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/cogs/music.py b/cogs/music.py index 7bcccf1..21a78f4 100644 --- a/cogs/music.py +++ b/cogs/music.py @@ -35,8 +35,7 @@ class Music: bot.lavalink.add_node(**conf['lavalink nodes']['main']) bot.add_listener(bot.lavalink.voice_update_handler, 'on_socket_response') - async def __local_check(self, ctx): - """ Ensures the commands are used in the correct channels """ + async def __before_invoke(self, ctx): if not ctx.guild: raise commands.NoPrivateMessage textchannels = self.bot.settings.get(ctx.guild, 'channels.text', []) @@ -45,25 +44,11 @@ class Music: response = ctx.localizer.format_str('{settings_check.textchannel}') for channel_id in textchannels: response += f'<#{channel_id}>, ' - await ctx.send(response[:-2]) - return False + return await ctx.send(response[:-2]) + + await self.ensure_voice(ctx) return True - async def __before_invoke(self, ctx): - # TODO: rewrite this thing. Probably remove ensure_voice. - - guild_check = ctx.guild is not None - # This is essentially the same as `@commands.guild_only()` - # except it saves us repeating ourselves (and also a few lines). - - if guild_check: - await self.ensure_voice(ctx) - # Ensure that the bot and command author share a mutual voicechannel. - else: - raise commands.NoPrivateMessage - - return guild_check - async def connect_to(self, guild_id: int, channel_id: str): """ Connects to the given voicechannel ID. A channel_id of `None` means disconnect. """ ws = self.bot._connection._get_websocket(guild_id) @@ -229,7 +214,9 @@ class Music: player = self.bot.lavalink.players.get(ctx.guild.id) if player.queue.empty: - return await ctx.send(ctx.localizer.format_str("{queue.empty}")) + embed = discord.Embed(description='{queue.empty}', color=ctx.me.color) + embed = ctx.localizer.format_embed(embed) + return await ctx.send(embed=embed) if user is None: queue = player.global_queue() @@ -548,7 +535,9 @@ class Music: player = self.bot.lavalink.players.get(ctx.guild.id) history = player.get_history() if not history: - return await ctx.send(ctx.localizer.format_str("{history.empty}")) + embed = discord.Embed(description='{history.empty}', color=ctx.me.color) + embed = ctx.localizer.format_embed(embed) + return await ctx.send(embed=embed) track = history[0] description = ctx.localizer.format_str("{history.current}", _title=track.title, _uri=track.uri,_id=track.requester) + '\n\n' description += ctx.localizer.format_str("{history.previous}", _len=len(history)-1) + '\n'