mirror of
https://github.com/RafaelSolVargas/Vulkan.git
synced 2025-10-29 16:57:23 +00:00
Adapting History, Loop, Now Playing, Remove, Shuffle and Reset commands to work with process
This commit is contained in:
parent
3eab6176c3
commit
7efed8ab89
@ -16,7 +16,7 @@ class Configs(Singleton):
|
||||
'[ERROR] -> You must create and .env file with all required fields, see documentation for help')
|
||||
|
||||
self.CLEANER_MESSAGES_QUANT = 5
|
||||
self.COMMANDS_PATH = 'Commands'
|
||||
self.COMMANDS_PATH = 'DiscordCogs'
|
||||
self.VC_TIMEOUT = 600
|
||||
|
||||
self.MAX_PLAYLIST_LENGTH = 50
|
||||
|
||||
@ -42,6 +42,8 @@ class Messages(Singleton):
|
||||
self.LOOP_DISABLE = '➡️ Loop disabled'
|
||||
self.LOOP_ALREADY_DISABLE = '❌ Loop is already disabled'
|
||||
self.LOOP_ON = f'❌ This command cannot be invoked with any loop activated. Use {configs.BOT_PREFIX}loop off to disable loop'
|
||||
self.BAD_USE_OF_LOOP = f"""❌ Invalid arguments of Loop command. Use {configs.BOT_PREFIX}help loop to more information.
|
||||
-> Available Arguments: ["all", "off", "one", ""]"""
|
||||
|
||||
self.SONGS_SHUFFLED = '🔀 Songs shuffled successfully'
|
||||
self.ERROR_SHUFFLING = '❌ Error while shuffling the songs'
|
||||
|
||||
@ -21,7 +21,6 @@ from Handlers.QueueHandler import QueueHandler
|
||||
from Handlers.LoopHandler import LoopHandler
|
||||
from Views.EmoteView import EmoteView
|
||||
from Views.EmbedView import EmbedView
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
|
||||
helper = Helper()
|
||||
|
||||
@ -120,7 +119,7 @@ class MusicCog(commands.Cog):
|
||||
await view1.run()
|
||||
await view2.run()
|
||||
|
||||
@commands.command(name='history', help=helper.HELP_HISTORY, description=helper.HELP_HISTORY_LONG, aliases=['historico', 'h'])
|
||||
@commands.command(name='history', help=helper.HELP_HISTORY, description=helper.HELP_HISTORY_LONG, aliases=['historico', 'anteriores', 'hist'])
|
||||
async def history(self, ctx: Context) -> None:
|
||||
controller = HistoryHandler(ctx, self.__bot)
|
||||
|
||||
@ -158,7 +157,7 @@ class MusicCog(commands.Cog):
|
||||
await view1.run()
|
||||
await view2.run()
|
||||
|
||||
@commands.command(name='shuffle', help=helper.HELP_SHUFFLE, description=helper.HELP_SHUFFLE_LONG, aliases=['aleatorio'])
|
||||
@commands.command(name='shuffle', help=helper.HELP_SHUFFLE, description=helper.HELP_SHUFFLE_LONG, aliases=['aleatorio', 'misturar'])
|
||||
async def shuffle(self, ctx: Context) -> None:
|
||||
controller = ShuffleHandler(ctx, self.__bot)
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ class RandomCog(Cog):
|
||||
def __init__(self, bot: Client):
|
||||
self.__embeds = Embeds()
|
||||
|
||||
@command(name='random', help=helper.HELP_RANDOM, description=helper.HELP_RANDOM_LONG, aliases=['rand', 'aleatorio'])
|
||||
@command(name='random', help=helper.HELP_RANDOM, description=helper.HELP_RANDOM_LONG, aliases=['rand'])
|
||||
async def random(self, ctx: Context, arg: str) -> None:
|
||||
try:
|
||||
arg = int(arg)
|
||||
|
||||
@ -3,6 +3,7 @@ from discord import Client
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Utils.Utils import Utils
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
|
||||
|
||||
class HistoryHandler(AbstractHandler):
|
||||
@ -10,11 +11,18 @@ class HistoryHandler(AbstractHandler):
|
||||
super().__init__(ctx, bot)
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
history = self.player.playlist.getSongsHistory()
|
||||
# Get the current process of the guild
|
||||
processManager = ProcessManager()
|
||||
processContext = processManager.getRunningPlayerContext(self.guild)
|
||||
if processContext:
|
||||
with processContext.getLock():
|
||||
playlist = processContext.getPlaylist()
|
||||
history = playlist.getSongsHistory()
|
||||
else:
|
||||
history = []
|
||||
|
||||
if len(history) == 0:
|
||||
text = self.messages.HISTORY_EMPTY
|
||||
|
||||
else:
|
||||
text = f'\n📜 History Length: {len(history)} | Max: {self.config.MAX_SONGS_HISTORY}\n'
|
||||
for pos, song in enumerate(history, start=1):
|
||||
|
||||
@ -3,6 +3,7 @@ from discord import Client
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Config.Exceptions import BadCommandUsage
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
|
||||
|
||||
class LoopHandler(AbstractHandler):
|
||||
@ -10,30 +11,41 @@ class LoopHandler(AbstractHandler):
|
||||
super().__init__(ctx, bot)
|
||||
|
||||
async def run(self, args: str) -> HandlerResponse:
|
||||
if args == '' or args is None:
|
||||
self.player.playlist.loop_all()
|
||||
embed = self.embeds.LOOP_ALL_ACTIVATED()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
|
||||
args = args.lower()
|
||||
if self.player.playlist.getCurrentSong() is None:
|
||||
# Get the current process of the guild
|
||||
processManager = ProcessManager()
|
||||
processContext = processManager.getRunningPlayerContext(self.guild)
|
||||
if not processContext:
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
error = BadCommandUsage()
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
|
||||
if args == 'one':
|
||||
self.player.playlist.loop_one()
|
||||
embed = self.embeds.LOOP_ONE_ACTIVATED()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
elif args == 'all':
|
||||
self.player.playlist.loop_all()
|
||||
embed = self.embeds.LOOP_ALL_ACTIVATED()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
elif args == 'off':
|
||||
self.player.playlist.loop_off()
|
||||
embed = self.embeds.LOOP_DISABLE()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
else:
|
||||
error = BadCommandUsage()
|
||||
embed = self.embeds.BAD_LOOP_USE()
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
playlist = processContext.getPlaylist()
|
||||
|
||||
with processContext.getLock():
|
||||
if args == '' or args is None:
|
||||
playlist.loop_all()
|
||||
embed = self.embeds.LOOP_ALL_ACTIVATED()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
|
||||
args = args.lower()
|
||||
if playlist.getCurrentSong() is None:
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
error = BadCommandUsage()
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
|
||||
if args == 'one':
|
||||
playlist.loop_one()
|
||||
embed = self.embeds.LOOP_ONE_ACTIVATED()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
elif args == 'all':
|
||||
playlist.loop_all()
|
||||
embed = self.embeds.LOOP_ALL_ACTIVATED()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
elif args == 'off':
|
||||
playlist.loop_off()
|
||||
embed = self.embeds.LOOP_DISABLE()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
else:
|
||||
error = BadCommandUsage()
|
||||
embed = self.embeds.BAD_LOOP_USE()
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
|
||||
@ -3,6 +3,7 @@ from discord import Client
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Utils.Cleaner import Cleaner
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
|
||||
|
||||
class NowPlayingHandler(AbstractHandler):
|
||||
@ -11,16 +12,24 @@ class NowPlayingHandler(AbstractHandler):
|
||||
self.__cleaner = Cleaner()
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
if not self.player.playing:
|
||||
# Get the current process of the guild
|
||||
processManager = ProcessManager()
|
||||
processContext = processManager.getRunningPlayerContext(self.guild)
|
||||
if not processContext:
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
|
||||
if self.player.playlist.isLoopingOne():
|
||||
playlist = processContext.getPlaylist()
|
||||
if playlist.getCurrentSong() is None:
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
|
||||
if playlist.isLoopingOne():
|
||||
title = self.messages.ONE_SONG_LOOPING
|
||||
else:
|
||||
title = self.messages.SONG_PLAYING
|
||||
await self.__cleaner.clean_messages(self.ctx, self.config.CLEANER_MESSAGES_QUANT)
|
||||
|
||||
info = self.player.playlist.getCurrentSong().info
|
||||
info = playlist.getCurrentSong().info
|
||||
embed = self.embeds.SONG_INFO(info, title)
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
|
||||
@ -58,7 +58,7 @@ class PlayHandler(AbstractHandler):
|
||||
response = HandlerResponse(self.ctx, embed)
|
||||
|
||||
# Get the process context for the current guild
|
||||
manager = ProcessManager(self.bot)
|
||||
manager = ProcessManager()
|
||||
processContext = manager.getPlayerContext(self.guild, self.ctx)
|
||||
# Add the downloaded song to the process playlist
|
||||
# All access to shared memory should be protect by acquire the Lock
|
||||
|
||||
@ -4,6 +4,8 @@ from discord import Client
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Config.Exceptions import BadCommandUsage, VulkanError, ErrorRemoving, InvalidInput, NumberRequired
|
||||
from Music.Playlist import Playlist
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
|
||||
|
||||
class RemoveHandler(AbstractHandler):
|
||||
@ -11,24 +13,34 @@ class RemoveHandler(AbstractHandler):
|
||||
super().__init__(ctx, bot)
|
||||
|
||||
async def run(self, position: str) -> HandlerResponse:
|
||||
if not self.player.playlist:
|
||||
# Get the current process of the guild
|
||||
processManager = ProcessManager()
|
||||
processContext = processManager.getRunningPlayerContext(self.guild)
|
||||
if not processContext:
|
||||
# Clear the playlist
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
error = BadCommandUsage()
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
|
||||
error = self.__validate_input(position)
|
||||
playlist = processContext.getPlaylist()
|
||||
if playlist.getCurrentSong() is None:
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
error = BadCommandUsage()
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
|
||||
error = self.__validateInput(position)
|
||||
if error:
|
||||
embed = self.embeds.ERROR_EMBED(error.message)
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
|
||||
position = self.__sanitize_input(position)
|
||||
if not self.player.playlist.validate_position(position):
|
||||
position = self.__sanitizeInput(playlist, position)
|
||||
if not playlist.validate_position(position):
|
||||
error = InvalidInput()
|
||||
embed = self.embeds.PLAYLIST_RANGE_ERROR()
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
|
||||
try:
|
||||
song = self.player.playlist.remove_song(position)
|
||||
song = playlist.remove_song(position)
|
||||
name = song.title if song.title else song.identifier
|
||||
|
||||
embed = self.embeds.SONG_REMOVED(name)
|
||||
@ -38,15 +50,15 @@ class RemoveHandler(AbstractHandler):
|
||||
embed = self.embeds.ERROR_REMOVING()
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
|
||||
def __validate_input(self, position: str) -> Union[VulkanError, None]:
|
||||
def __validateInput(self, position: str) -> Union[VulkanError, None]:
|
||||
try:
|
||||
position = int(position)
|
||||
except:
|
||||
return NumberRequired(self.messages.ERROR_NUMBER)
|
||||
|
||||
def __sanitize_input(self, position: str) -> int:
|
||||
def __sanitizeInput(self, playlist: Playlist, position: str) -> int:
|
||||
position = int(position)
|
||||
|
||||
if position == -1:
|
||||
position = len(self.player.playlist)
|
||||
position = len(playlist)
|
||||
return position
|
||||
|
||||
@ -2,19 +2,21 @@ from discord.ext.commands import Context
|
||||
from discord import Client
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Handlers.PlayersController import PlayersController
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
from Parallelism.Commands import VCommands, VCommandsType
|
||||
|
||||
|
||||
class ResetHandler(AbstractHandler):
|
||||
def __init__(self, ctx: Context, bot: Client) -> None:
|
||||
super().__init__(ctx, bot)
|
||||
self.__controller = PlayersController(self.bot)
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
try:
|
||||
await self.player.force_stop()
|
||||
await self.bot_member.move_to(None)
|
||||
self.__controller.reset_player(self.guild)
|
||||
return HandlerResponse(self.ctx)
|
||||
except Exception as e:
|
||||
print(f'DEVELOPER NOTE -> Reset Error: {e}')
|
||||
# Get the current process of the guild
|
||||
processManager = ProcessManager()
|
||||
processContext = processManager.getRunningPlayerContext(self.guild)
|
||||
if processContext:
|
||||
command = VCommands(VCommandsType.RESET, None)
|
||||
queue = processContext.getQueue()
|
||||
queue.put(command)
|
||||
|
||||
return HandlerResponse(self.ctx)
|
||||
|
||||
@ -1,27 +1,33 @@
|
||||
import asyncio
|
||||
from discord.ext.commands import Context
|
||||
from discord import Client
|
||||
from Handlers.AbstractHandler import AbstractHandler
|
||||
from Handlers.HandlerResponse import HandlerResponse
|
||||
from Config.Exceptions import UnknownError
|
||||
from Music.Downloader import Downloader
|
||||
from Parallelism.ProcessManager import ProcessManager
|
||||
|
||||
|
||||
class ShuffleHandler(AbstractHandler):
|
||||
def __init__(self, ctx: Context, bot: Client) -> None:
|
||||
super().__init__(ctx, bot)
|
||||
self.__down = Downloader()
|
||||
|
||||
async def run(self) -> HandlerResponse:
|
||||
try:
|
||||
self.player.playlist.shuffle()
|
||||
songs = self.player.playlist.getSongsToPreload()
|
||||
processManager = ProcessManager()
|
||||
processContext = processManager.getRunningPlayerContext(self.guild)
|
||||
if processContext:
|
||||
try:
|
||||
with processContext.getLock():
|
||||
playlist = processContext.getPlaylist()
|
||||
playlist.shuffle()
|
||||
|
||||
asyncio.create_task(self.__down.preload(songs))
|
||||
embed = self.embeds.SONGS_SHUFFLED()
|
||||
embed = self.embeds.SONGS_SHUFFLED()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
|
||||
except Exception as e:
|
||||
print(f'DEVELOPER NOTE -> Error Shuffling: {e}')
|
||||
error = UnknownError()
|
||||
embed = self.embeds.ERROR_SHUFFLING()
|
||||
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
else:
|
||||
embed = self.embeds.NOT_PLAYING()
|
||||
return HandlerResponse(self.ctx, embed)
|
||||
except Exception as e:
|
||||
print(f'DEVELOPER NOTE -> Error Shuffling: {e}')
|
||||
error = UnknownError()
|
||||
embed = self.embeds.ERROR_SHUFFLING()
|
||||
return HandlerResponse(self.ctx, embed, error)
|
||||
|
||||
@ -10,6 +10,7 @@ class VCommandsType(Enum):
|
||||
CONTEXT = 'Context'
|
||||
PLAY = 'Play'
|
||||
STOP = 'Stop'
|
||||
RESET = 'Reset'
|
||||
|
||||
|
||||
class VCommands:
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import asyncio
|
||||
from os import listdir
|
||||
from discord import Intents, User
|
||||
from discord import Intents, User, Member
|
||||
from asyncio import AbstractEventLoop, Semaphore
|
||||
from multiprocessing import Process, Queue
|
||||
from threading import Lock, Thread
|
||||
from typing import Callable
|
||||
from typing import Callable, List
|
||||
from discord import Client, Guild, FFmpegPCMAudio, VoiceChannel, TextChannel
|
||||
from discord.ext.commands import Context
|
||||
from Music.Playlist import Playlist
|
||||
@ -53,6 +53,7 @@ class PlayerProcess(Process):
|
||||
self.__voiceChannel: VoiceChannel = None
|
||||
self.__textChannel: TextChannel = None
|
||||
self.__author: User = None
|
||||
self.__botMember: Member = None
|
||||
|
||||
self.__configs: Configs = None
|
||||
self.__playing = False
|
||||
@ -79,6 +80,7 @@ class PlayerProcess(Process):
|
||||
self.__voiceChannel = self.__bot.get_channel(self.__voiceChannelID)
|
||||
self.__textChannel = self.__bot.get_channel(self.__textChannelID)
|
||||
self.__author = self.__bot.get_channel(self.__authorID)
|
||||
self.__botMember = self.__getBotMember()
|
||||
# Connect to voice Channel
|
||||
await self.__connectToVoiceChannel()
|
||||
|
||||
@ -93,6 +95,8 @@ class PlayerProcess(Process):
|
||||
# Try to acquire a semaphore, it'll be release when timeout function trigger, we use the Semaphore
|
||||
# from the asyncio lib to not block the event loop
|
||||
await self.__semStopPlaying.acquire()
|
||||
# In this point the process should finalize
|
||||
self.__timer.cancel()
|
||||
|
||||
async def __playPlaylistSongs(self) -> None:
|
||||
print(f'Playing: {self.__playing}')
|
||||
@ -153,6 +157,8 @@ class PlayerProcess(Process):
|
||||
self.__resume()
|
||||
elif type == VCommandsType.SKIP:
|
||||
self.__skip()
|
||||
elif type == VCommandsType.RESET:
|
||||
self.__loop.create_task(self.__reset())
|
||||
elif type == VCommandsType.STOP:
|
||||
self.__loop.create_task(self.__stop())
|
||||
else:
|
||||
@ -163,6 +169,18 @@ class PlayerProcess(Process):
|
||||
if self.__guild.voice_client.is_playing():
|
||||
self.__guild.voice_client.pause()
|
||||
|
||||
async def __reset(self) -> None:
|
||||
if self.__guild.voice_client is None:
|
||||
return
|
||||
# Reset the bot
|
||||
self.__guild.voice_client.stop()
|
||||
await self.__guild.voice_client.disconnect()
|
||||
self.__playlist.clear()
|
||||
self.__playlist.loop_off()
|
||||
await self.__botMember.move_to(None)
|
||||
# Release semaphore to finish the current player process
|
||||
self.__semStopPlaying.release()
|
||||
|
||||
async def __stop(self) -> None:
|
||||
if self.__guild.voice_client is not None:
|
||||
if self.__guild.voice_client.is_connected():
|
||||
@ -236,15 +254,12 @@ class PlayerProcess(Process):
|
||||
try:
|
||||
print('TimeoutHandler')
|
||||
if self.__guild.voice_client is None:
|
||||
print('return')
|
||||
return
|
||||
|
||||
if self.__guild.voice_client.is_playing() or self.__guild.voice_client.is_paused():
|
||||
print('Resetting')
|
||||
self.__timer = TimeoutClock(self.__timeoutHandler, self.__loop)
|
||||
|
||||
elif self.__guild.voice_client.is_connected():
|
||||
print('Finish')
|
||||
with self.__lock:
|
||||
self.__playlist.clear()
|
||||
self.__playlist.loop_off()
|
||||
@ -270,3 +285,9 @@ class PlayerProcess(Process):
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def __getBotMember(self) -> Member:
|
||||
guild_members: List[Member] = self.__guild.members
|
||||
for member in guild_members:
|
||||
if member.id == self.__bot.user.id:
|
||||
return member
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user