mirror of
https://github.com/UiO-Gaming/ShiteMusicBot.git
synced 2026-11-05 13:56:51 +01:00
Merge branch 'feature/cmdaliases' into 'dev'
Per locale/server aliases for commands and subcommands. Move to YAML. See merge request Ev-1/shite-music-bot!14
This commit is contained in:
commit
eb0e0889ec
29 files changed
+755
-518
No files matched your search
@@ -6,21 +6,31 @@ import traceback
|
||||
import yaml
|
||||
|
||||
from discord.ext import commands
|
||||
from cogs.utils.settings import Settings
|
||||
from discord.ext.commands.view import StringView
|
||||
from cogs.utils.settingsmanager import Settings
|
||||
from cogs.utils.localizer import Localizer
|
||||
|
||||
|
||||
initial_extensions = [
|
||||
'cogs.cogs',
|
||||
'cogs.botsettings',
|
||||
'cogs.misc'
|
||||
]
|
||||
from cogs.utils.localizer import LocalizerWrapper
|
||||
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.settings',
|
||||
'cogs.misc'
|
||||
]
|
||||
|
||||
|
||||
on_ready_extensions = [
|
||||
'cogs.music',
|
||||
'cogs.musicevents'
|
||||
]
|
||||
|
||||
|
||||
def _get_prefix(bot, message):
|
||||
if not message.guild:
|
||||
return bot.settings.default_prefix
|
||||
@@ -35,6 +45,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 +72,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,19 +84,43 @@ 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)
|
||||
|
||||
# Replace aliases with commands
|
||||
ctx = self.aliaser.get_command(ctx)
|
||||
if ctx.command and isinstance(ctx.command, commands.GroupMixin):
|
||||
ctx = self.aliaser.get_subcommand(ctx, ctx.command, [str(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:
|
||||
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()
|
||||
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)
|
||||
|
||||
+19
-20
@@ -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,
|
||||
@@ -114,11 +118,6 @@ class Misc:
|
||||
)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command()
|
||||
@checks.is_even()
|
||||
async def only_me(self, ctx):
|
||||
await ctx.send('Only you!')
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Misc(bot))
|
||||
+97
-134
@@ -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\\.)?.+')
|
||||
@@ -35,48 +35,29 @@ 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 """
|
||||
async def __before_invoke(self, ctx):
|
||||
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])
|
||||
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)
|
||||
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 +66,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 +87,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 +120,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 +138,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 +195,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 +205,96 @@ 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}"))
|
||||
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()
|
||||
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 +304,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 +336,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 +358,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 +374,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 +416,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 +427,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 +439,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 +450,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 +487,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 +526,43 @@ 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}"))
|
||||
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 = 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 +596,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 +659,7 @@ 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}')
|
||||
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 +677,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
|
||||
|
||||
@@ -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)
|
||||
@@ -178,53 +178,54 @@ class BotSettings:
|
||||
@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
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(BotSettings(bot))
|
||||
bot.add_cog(Settings(bot))
|
||||
@@ -0,0 +1,116 @@
|
||||
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)
|
||||
self.default_lang = default_lang
|
||||
self.index_localizations()
|
||||
self.load_localizations()
|
||||
|
||||
def _gen_alias_dict(self, commands):
|
||||
""" Reverses the direction of a dict of commans→aliases to be alias→command. """
|
||||
inverted = {}
|
||||
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):
|
||||
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._gen_alias_dict(data)}
|
||||
|
||||
def convert_alias(self, locale, alias, default=None, parents=[]):
|
||||
locale = self.localization_table[locale]
|
||||
|
||||
# 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.convert_alias(ctx.locale, alias, alias)
|
||||
ctx.invoked_with = command
|
||||
ctx.command = ctx.bot.all_commands.get(command)
|
||||
return ctx
|
||||
|
||||
def get_subcommand(self, ctx, group, parents=[]):
|
||||
""" 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.convert_alias(ctx.locale, alias, alias, parents.copy())
|
||||
parents.append(subcmd)
|
||||
|
||||
# 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.get_subcommand(ctx, sub, parents)
|
||||
|
||||
# Reset the view indexes
|
||||
view.index = idx
|
||||
view.previous = prev
|
||||
return ctx
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,63 @@
|
||||
# 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
|
||||
play: [p]
|
||||
now: [np, nowplaying]
|
||||
queue: [q]
|
||||
myqueue: [mq]
|
||||
seek: []
|
||||
skip: []
|
||||
skipto: [forceskip]
|
||||
stop: []
|
||||
pause: [resume]
|
||||
shuffle: []
|
||||
move: [m]
|
||||
remove: [rem]
|
||||
DJremove: [djremove]
|
||||
removeuser: []
|
||||
search: [s]
|
||||
disconnect: [dc]
|
||||
volume: [v, vol]
|
||||
normalize: [normal]
|
||||
boost: [bassboost]
|
||||
history: [h]
|
||||
scrub: []
|
||||
|
||||
# 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: []
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"not_available_dm": "This command is not available in DMs"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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: "
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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: '
|
||||
@@ -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
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
# 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]
|
||||
remove: [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]
|
||||
|
||||
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]
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"not_available_dm": "Denne kommandoen er ikke tilgjengelig i DMs"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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: "
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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: '
|
||||
@@ -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
|
||||
@@ -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]
|
||||
remove: [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]
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"not_available_dm": "Denna kommandoa er ikkje tilgjengeleg i direkte meldingar DMs"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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: "
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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: '
|
||||
@@ -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
|
||||
Reference in new issue
Block a user