mirror of
https://github.com/RafaelSolVargas/Vulkan.git
synced 2025-10-29 16:57:23 +00:00
Refactoring some code and modifying variables and class names
This commit is contained in:
parent
ca75e1823f
commit
7a5d76ffd3
@ -1,4 +1,3 @@
|
|||||||
import os
|
|
||||||
from decouple import config
|
from decouple import config
|
||||||
from Config.Singleton import Singleton
|
from Config.Singleton import Singleton
|
||||||
from Config.Folder import Folder
|
from Config.Folder import Folder
|
||||||
@ -10,6 +9,9 @@ class VConfigs(Singleton):
|
|||||||
# You can change this boolean to False if you want to prevent the Bot from auto disconnecting
|
# You can change this boolean to False if you want to prevent the Bot from auto disconnecting
|
||||||
# Resolution for the issue: https://github.com/RafaelSolVargas/Vulkan/issues/33
|
# Resolution for the issue: https://github.com/RafaelSolVargas/Vulkan/issues/33
|
||||||
self.SHOULD_AUTO_DISCONNECT_WHEN_ALONE = False
|
self.SHOULD_AUTO_DISCONNECT_WHEN_ALONE = False
|
||||||
|
# Recommended to be True, except in cases when your Bot is present in thousands servers, in that case
|
||||||
|
# the delay to start a new Python process for the playback is too much, and to avoid that you set as False
|
||||||
|
self.SONG_PLAYBACK_IN_SEPARATE_PROCESS = False
|
||||||
|
|
||||||
self.BOT_PREFIX = '!'
|
self.BOT_PREFIX = '!'
|
||||||
try:
|
try:
|
||||||
@ -44,8 +46,8 @@ class VConfigs(Singleton):
|
|||||||
self.MY_ERROR_BAD_COMMAND = 'This string serves to verify if some error was raised by myself on purpose'
|
self.MY_ERROR_BAD_COMMAND = 'This string serves to verify if some error was raised by myself on purpose'
|
||||||
self.INVITE_URL = 'https://discordapp.com/oauth2/authorize?client_id={}&scope=bot'
|
self.INVITE_URL = 'https://discordapp.com/oauth2/authorize?client_id={}&scope=bot'
|
||||||
|
|
||||||
def getProcessManager(self):
|
def getPlayersManager(self):
|
||||||
return self.__manager
|
return self.__manager
|
||||||
|
|
||||||
def setProcessManager(self, newManager):
|
def setPlayersManager(self, newManager):
|
||||||
self.__manager = newManager
|
self.__manager = newManager
|
||||||
|
|||||||
@ -38,7 +38,7 @@ class MusicCog(Cog):
|
|||||||
def __init__(self, bot: VulkanBot) -> None:
|
def __init__(self, bot: VulkanBot) -> None:
|
||||||
self.__bot: VulkanBot = bot
|
self.__bot: VulkanBot = bot
|
||||||
self.__embeds = VEmbeds()
|
self.__embeds = VEmbeds()
|
||||||
VConfigs().setProcessManager(ProcessManager(bot))
|
VConfigs().setPlayersManager(ProcessManager(bot))
|
||||||
|
|
||||||
@command(name="play", help=helper.HELP_PLAY, description=helper.HELP_PLAY_LONG, aliases=['p', 'tocar'])
|
@command(name="play", help=helper.HELP_PLAY, description=helper.HELP_PLAY_LONG, aliases=['p', 'tocar'])
|
||||||
async def play(self, ctx: Context, *args) -> None:
|
async def play(self, ctx: Context, *args) -> None:
|
||||||
|
|||||||
@ -4,7 +4,8 @@ from discord.ext.commands import Context
|
|||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
from Handlers.AbstractHandler import AbstractHandler
|
from Handlers.AbstractHandler import AbstractHandler
|
||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
from Parallelism.ProcessInfo import ProcessInfo
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
|
from Parallelism.ProcessInfo import PlayerInfo
|
||||||
|
|
||||||
|
|
||||||
class ClearHandler(AbstractHandler):
|
class ClearHandler(AbstractHandler):
|
||||||
@ -13,8 +14,8 @@ class ClearHandler(AbstractHandler):
|
|||||||
|
|
||||||
async def run(self) -> HandlerResponse:
|
async def run(self) -> HandlerResponse:
|
||||||
# Get the current process of the guild
|
# Get the current process of the guild
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo: ProcessInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if processInfo:
|
if processInfo:
|
||||||
# Clear the playlist
|
# Clear the playlist
|
||||||
playlist = processInfo.getPlaylist()
|
playlist = processInfo.getPlaylist()
|
||||||
|
|||||||
@ -2,6 +2,7 @@ from discord.ext.commands import Context
|
|||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
from Handlers.AbstractHandler import AbstractHandler
|
from Handlers.AbstractHandler import AbstractHandler
|
||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
from Utils.Utils import Utils
|
from Utils.Utils import Utils
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from discord import Interaction
|
from discord import Interaction
|
||||||
@ -13,7 +14,7 @@ class HistoryHandler(AbstractHandler):
|
|||||||
|
|
||||||
async def run(self) -> HandlerResponse:
|
async def run(self) -> HandlerResponse:
|
||||||
# Get the current process of the guild
|
# Get the current process of the guild
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if processInfo:
|
if processInfo:
|
||||||
processLock = processInfo.getLock()
|
processLock = processInfo.getLock()
|
||||||
|
|||||||
@ -6,6 +6,7 @@ from discord import Interaction
|
|||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
from Music.Playlist import Playlist
|
from Music.Playlist import Playlist
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
from Parallelism.Commands import VCommands, VCommandsType
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
|
|
||||||
|
|
||||||
@ -16,7 +17,7 @@ class JumpMusicHandler(AbstractHandler):
|
|||||||
super().__init__(ctx, bot)
|
super().__init__(ctx, bot)
|
||||||
|
|
||||||
async def run(self, musicPos: str) -> HandlerResponse:
|
async def run(self, musicPos: str) -> HandlerResponse:
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if not processInfo:
|
if not processInfo:
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
|
|||||||
@ -6,6 +6,8 @@ from Config.Exceptions import BadCommandUsage
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
from discord import Interaction
|
from discord import Interaction
|
||||||
|
|
||||||
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
|
|
||||||
|
|
||||||
class LoopHandler(AbstractHandler):
|
class LoopHandler(AbstractHandler):
|
||||||
def __init__(self, ctx: Union[Context, Interaction], bot: VulkanBot) -> None:
|
def __init__(self, ctx: Union[Context, Interaction], bot: VulkanBot) -> None:
|
||||||
@ -13,7 +15,7 @@ class LoopHandler(AbstractHandler):
|
|||||||
|
|
||||||
async def run(self, args: str) -> HandlerResponse:
|
async def run(self, args: str) -> HandlerResponse:
|
||||||
# Get the current process of the guild
|
# Get the current process of the guild
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if not processInfo:
|
if not processInfo:
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
|
|||||||
@ -7,6 +7,7 @@ from Config.Exceptions import BadCommandUsage, VulkanError, InvalidInput, Number
|
|||||||
from Music.Playlist import Playlist
|
from Music.Playlist import Playlist
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from discord import Interaction
|
from discord import Interaction
|
||||||
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
|
|
||||||
|
|
||||||
class MoveHandler(AbstractHandler):
|
class MoveHandler(AbstractHandler):
|
||||||
@ -14,7 +15,7 @@ class MoveHandler(AbstractHandler):
|
|||||||
super().__init__(ctx, bot)
|
super().__init__(ctx, bot)
|
||||||
|
|
||||||
async def run(self, pos1: str, pos2: str) -> HandlerResponse:
|
async def run(self, pos1: str, pos2: str) -> HandlerResponse:
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if not processInfo:
|
if not processInfo:
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
|
|||||||
@ -2,6 +2,7 @@ from discord.ext.commands import Context
|
|||||||
from Handlers.AbstractHandler import AbstractHandler
|
from Handlers.AbstractHandler import AbstractHandler
|
||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
from Utils.Cleaner import Cleaner
|
from Utils.Cleaner import Cleaner
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from discord import Interaction
|
from discord import Interaction
|
||||||
@ -14,7 +15,7 @@ class NowPlayingHandler(AbstractHandler):
|
|||||||
|
|
||||||
async def run(self) -> HandlerResponse:
|
async def run(self) -> HandlerResponse:
|
||||||
# Get the current process of the guild
|
# Get the current process of the guild
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if not processInfo:
|
if not processInfo:
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
from discord.ext.commands import Context
|
from discord.ext.commands import Context
|
||||||
from Handlers.AbstractHandler import AbstractHandler
|
from Handlers.AbstractHandler import AbstractHandler
|
||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
from Parallelism.Commands import VCommands, VCommandsType
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
from Parallelism.ProcessInfo import ProcessInfo, ProcessStatus
|
from Parallelism.ProcessInfo import PlayerInfo, ProcessStatus
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from discord import Interaction
|
from discord import Interaction
|
||||||
@ -13,8 +14,8 @@ class PauseHandler(AbstractHandler):
|
|||||||
super().__init__(ctx, bot)
|
super().__init__(ctx, bot)
|
||||||
|
|
||||||
async def run(self) -> HandlerResponse:
|
async def run(self) -> HandlerResponse:
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo: ProcessInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if processInfo:
|
if processInfo:
|
||||||
if processInfo.getStatus() == ProcessStatus.SLEEPING:
|
if processInfo.getStatus() == ProcessStatus.SLEEPING:
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
|
|||||||
@ -9,7 +9,8 @@ from Handlers.HandlerResponse import HandlerResponse
|
|||||||
from Music.Downloader import Downloader
|
from Music.Downloader import Downloader
|
||||||
from Music.Searcher import Searcher
|
from Music.Searcher import Searcher
|
||||||
from Music.Song import Song
|
from Music.Song import Song
|
||||||
from Parallelism.ProcessInfo import ProcessInfo
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
|
from Parallelism.ProcessInfo import PlayerInfo
|
||||||
from Parallelism.Commands import VCommands, VCommandsType
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
from typing import Union
|
from typing import Union
|
||||||
@ -37,7 +38,7 @@ class PlayHandler(AbstractHandler):
|
|||||||
raise InvalidInput(self.messages.INVALID_INPUT, self.messages.ERROR_TITLE)
|
raise InvalidInput(self.messages.INVALID_INPUT, self.messages.ERROR_TITLE)
|
||||||
|
|
||||||
# Get the process context for the current guild
|
# Get the process context for the current guild
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo = processManager.getOrCreatePlayerInfo(self.guild, self.ctx)
|
processInfo = processManager.getOrCreatePlayerInfo(self.guild, self.ctx)
|
||||||
playlist: Playlist = processInfo.getPlaylist()
|
playlist: Playlist = processInfo.getPlaylist()
|
||||||
process = processInfo.getProcess()
|
process = processInfo.getProcess()
|
||||||
@ -109,7 +110,7 @@ class PlayHandler(AbstractHandler):
|
|||||||
|
|
||||||
return HandlerResponse(self.ctx, embed, error)
|
return HandlerResponse(self.ctx, embed, error)
|
||||||
|
|
||||||
async def __downloadSongsAndStore(self, songs: List[Song], processInfo: ProcessInfo) -> None:
|
async def __downloadSongsAndStore(self, songs: List[Song], processInfo: PlayerInfo) -> None:
|
||||||
playlist = processInfo.getPlaylist()
|
playlist = processInfo.getPlaylist()
|
||||||
queue = processInfo.getQueueToPlayer()
|
queue = processInfo.getQueueToPlayer()
|
||||||
playCommand = VCommands(VCommandsType.PLAY, None)
|
playCommand = VCommands(VCommandsType.PLAY, None)
|
||||||
@ -126,7 +127,7 @@ class PlayHandler(AbstractHandler):
|
|||||||
tasks.append(task)
|
tasks.append(task)
|
||||||
|
|
||||||
# In the original order, await for the task and then, if successfully downloaded, add to the playlist
|
# In the original order, await for the task and then, if successfully downloaded, add to the playlist
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
for index, task in enumerate(tasks):
|
for index, task in enumerate(tasks):
|
||||||
await task
|
await task
|
||||||
song = songs[index]
|
song = songs[index]
|
||||||
|
|||||||
@ -2,6 +2,7 @@ from discord.ext.commands import Context
|
|||||||
from Handlers.AbstractHandler import AbstractHandler
|
from Handlers.AbstractHandler import AbstractHandler
|
||||||
from Config.Exceptions import BadCommandUsage, ImpossibleMove
|
from Config.Exceptions import BadCommandUsage, ImpossibleMove
|
||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
from Parallelism.Commands import VCommands, VCommandsType
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
from typing import Union
|
from typing import Union
|
||||||
@ -18,7 +19,7 @@ class PrevHandler(AbstractHandler):
|
|||||||
embed = self.embeds.NO_CHANNEL()
|
embed = self.embeds.NO_CHANNEL()
|
||||||
return HandlerResponse(self.ctx, embed, error)
|
return HandlerResponse(self.ctx, embed, error)
|
||||||
|
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo = processManager.getOrCreatePlayerInfo(self.guild, self.ctx)
|
processInfo = processManager.getOrCreatePlayerInfo(self.guild, self.ctx)
|
||||||
if not processInfo:
|
if not processInfo:
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
|
|||||||
@ -4,6 +4,7 @@ from Handlers.AbstractHandler import AbstractHandler
|
|||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
from Handlers.JumpMusicHandler import JumpMusicHandler
|
from Handlers.JumpMusicHandler import JumpMusicHandler
|
||||||
from Messages.MessagesCategory import MessagesCategory
|
from Messages.MessagesCategory import MessagesCategory
|
||||||
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
from UI.Views.BasicView import BasicView
|
from UI.Views.BasicView import BasicView
|
||||||
from Utils.Utils import Utils
|
from Utils.Utils import Utils
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
@ -22,7 +23,7 @@ class QueueHandler(AbstractHandler):
|
|||||||
|
|
||||||
async def run(self, pageNumber=0) -> HandlerResponse:
|
async def run(self, pageNumber=0) -> HandlerResponse:
|
||||||
# Retrieve the process of the guild
|
# Retrieve the process of the guild
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if not processInfo: # If no process return empty list
|
if not processInfo: # If no process return empty list
|
||||||
embed = self.embeds.EMPTY_QUEUE()
|
embed = self.embeds.EMPTY_QUEUE()
|
||||||
|
|||||||
@ -4,7 +4,8 @@ from Handlers.HandlerResponse import HandlerResponse
|
|||||||
from Config.Exceptions import BadCommandUsage, VulkanError, ErrorRemoving, InvalidInput, NumberRequired
|
from Config.Exceptions import BadCommandUsage, VulkanError, ErrorRemoving, InvalidInput, NumberRequired
|
||||||
from Music.Playlist import Playlist
|
from Music.Playlist import Playlist
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
from Parallelism.ProcessInfo import ProcessInfo
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
|
from Parallelism.ProcessInfo import PlayerInfo
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from discord import Interaction
|
from discord import Interaction
|
||||||
|
|
||||||
@ -15,8 +16,8 @@ class RemoveHandler(AbstractHandler):
|
|||||||
|
|
||||||
async def run(self, position: str) -> HandlerResponse:
|
async def run(self, position: str) -> HandlerResponse:
|
||||||
# Get the current process of the guild
|
# Get the current process of the guild
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo: ProcessInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if not processInfo:
|
if not processInfo:
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
error = BadCommandUsage()
|
error = BadCommandUsage()
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
from discord.ext.commands import Context
|
from discord.ext.commands import Context
|
||||||
from Handlers.AbstractHandler import AbstractHandler
|
from Handlers.AbstractHandler import AbstractHandler
|
||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
from Parallelism.ProcessInfo import ProcessInfo, ProcessStatus
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
|
from Parallelism.ProcessInfo import PlayerInfo, ProcessStatus
|
||||||
from Parallelism.Commands import VCommands, VCommandsType
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
from typing import Union
|
from typing import Union
|
||||||
@ -14,8 +15,8 @@ class ResetHandler(AbstractHandler):
|
|||||||
|
|
||||||
async def run(self) -> HandlerResponse:
|
async def run(self) -> HandlerResponse:
|
||||||
# Get the current process of the guild
|
# Get the current process of the guild
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo: ProcessInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if processInfo:
|
if processInfo:
|
||||||
if processInfo.getStatus() == ProcessStatus.SLEEPING:
|
if processInfo.getStatus() == ProcessStatus.SLEEPING:
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
from discord.ext.commands import Context
|
from discord.ext.commands import Context
|
||||||
from Handlers.AbstractHandler import AbstractHandler
|
from Handlers.AbstractHandler import AbstractHandler
|
||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
from Parallelism.ProcessInfo import ProcessInfo, ProcessStatus
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
|
from Parallelism.ProcessInfo import PlayerInfo, ProcessStatus
|
||||||
from Parallelism.Commands import VCommands, VCommandsType
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
from typing import Union
|
from typing import Union
|
||||||
@ -13,8 +14,8 @@ class ResumeHandler(AbstractHandler):
|
|||||||
super().__init__(ctx, bot)
|
super().__init__(ctx, bot)
|
||||||
|
|
||||||
async def run(self) -> HandlerResponse:
|
async def run(self) -> HandlerResponse:
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo: ProcessInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if processInfo:
|
if processInfo:
|
||||||
if processInfo.getStatus() == ProcessStatus.SLEEPING:
|
if processInfo.getStatus() == ProcessStatus.SLEEPING:
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
|
|||||||
@ -6,13 +6,15 @@ from Music.VulkanBot import VulkanBot
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
from discord import Interaction
|
from discord import Interaction
|
||||||
|
|
||||||
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
|
|
||||||
|
|
||||||
class ShuffleHandler(AbstractHandler):
|
class ShuffleHandler(AbstractHandler):
|
||||||
def __init__(self, ctx: Union[Context, Interaction], bot: VulkanBot) -> None:
|
def __init__(self, ctx: Union[Context, Interaction], bot: VulkanBot) -> None:
|
||||||
super().__init__(ctx, bot)
|
super().__init__(ctx, bot)
|
||||||
|
|
||||||
async def run(self) -> HandlerResponse:
|
async def run(self) -> HandlerResponse:
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if processInfo:
|
if processInfo:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -3,7 +3,8 @@ from Handlers.AbstractHandler import AbstractHandler
|
|||||||
from Config.Exceptions import BadCommandUsage, ImpossibleMove
|
from Config.Exceptions import BadCommandUsage, ImpossibleMove
|
||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
from Parallelism.ProcessInfo import ProcessInfo, ProcessStatus
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
|
from Parallelism.ProcessInfo import PlayerInfo, ProcessStatus
|
||||||
from Parallelism.Commands import VCommands, VCommandsType
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from discord import Interaction
|
from discord import Interaction
|
||||||
@ -19,8 +20,8 @@ class SkipHandler(AbstractHandler):
|
|||||||
embed = self.embeds.NO_CHANNEL()
|
embed = self.embeds.NO_CHANNEL()
|
||||||
return HandlerResponse(self.ctx, embed, error)
|
return HandlerResponse(self.ctx, embed, error)
|
||||||
|
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo: ProcessInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if processInfo: # Verify if there is a running process
|
if processInfo: # Verify if there is a running process
|
||||||
if processInfo.getStatus() == ProcessStatus.SLEEPING:
|
if processInfo.getStatus() == ProcessStatus.SLEEPING:
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
|
|||||||
@ -2,7 +2,8 @@ from discord.ext.commands import Context
|
|||||||
from Handlers.AbstractHandler import AbstractHandler
|
from Handlers.AbstractHandler import AbstractHandler
|
||||||
from Handlers.HandlerResponse import HandlerResponse
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
from Parallelism.ProcessInfo import ProcessInfo, ProcessStatus
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
|
from Parallelism.ProcessInfo import PlayerInfo, ProcessStatus
|
||||||
from Parallelism.Commands import VCommands, VCommandsType
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from discord import Interaction
|
from discord import Interaction
|
||||||
@ -13,8 +14,8 @@ class StopHandler(AbstractHandler):
|
|||||||
super().__init__(ctx, bot)
|
super().__init__(ctx, bot)
|
||||||
|
|
||||||
async def run(self) -> HandlerResponse:
|
async def run(self) -> HandlerResponse:
|
||||||
processManager = self.config.getProcessManager()
|
processManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
processInfo: ProcessInfo = processManager.getRunningPlayerInfo(self.guild)
|
processInfo = processManager.getRunningPlayerInfo(self.guild)
|
||||||
if processInfo:
|
if processInfo:
|
||||||
if processInfo.getStatus() == ProcessStatus.SLEEPING:
|
if processInfo.getStatus() == ProcessStatus.SLEEPING:
|
||||||
embed = self.embeds.NOT_PLAYING()
|
embed = self.embeds.NOT_PLAYING()
|
||||||
|
|||||||
31
Parallelism/AbstractProcessManager.py
Normal file
31
Parallelism/AbstractProcessManager.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import Union
|
||||||
|
from discord.ext.commands import Context
|
||||||
|
from discord import Guild, Interaction
|
||||||
|
from Music.Song import Song
|
||||||
|
from Parallelism.ProcessInfo import PlayerInfo
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractPlayersManager(ABC):
|
||||||
|
def __init__(self, bot) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def setPlayerInfo(self, guild: Guild, info: PlayerInfo):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def getOrCreatePlayerInfo(self, guild: Guild, context: Union[Context, Interaction]) -> PlayerInfo:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def resetProcess(self, guild: Guild, context: Context) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def getRunningPlayerInfo(self, guild: Guild) -> PlayerInfo:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
async def showNowPlaying(self, guildID: int, song: Song) -> None:
|
||||||
|
pass
|
||||||
@ -2,19 +2,17 @@ import asyncio
|
|||||||
from time import sleep, time
|
from time import sleep, time
|
||||||
from urllib.parse import parse_qs, urlparse
|
from urllib.parse import parse_qs, urlparse
|
||||||
from Music.VulkanInitializer import VulkanInitializer
|
from Music.VulkanInitializer import VulkanInitializer
|
||||||
from discord import User, Member, Message, VoiceClient
|
from discord import Member, VoiceClient
|
||||||
from asyncio import AbstractEventLoop, Semaphore, Queue
|
from asyncio import AbstractEventLoop, Semaphore, Queue
|
||||||
from multiprocessing import Process, RLock, Lock, Queue
|
from multiprocessing import Process, RLock, Lock, Queue
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from typing import Callable, List
|
from typing import Callable, List
|
||||||
from discord import Guild, FFmpegPCMAudio, VoiceChannel, TextChannel
|
from discord import Guild, FFmpegPCMAudio, VoiceChannel
|
||||||
from Music.Playlist import Playlist
|
from Music.Playlist import Playlist
|
||||||
from Music.Song import Song
|
from Music.Song import Song
|
||||||
from Config.Configs import VConfigs
|
from Config.Configs import VConfigs
|
||||||
from Config.Messages import Messages
|
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
from Music.Downloader import Downloader
|
from Music.Downloader import Downloader
|
||||||
from Config.Embeds import VEmbeds
|
|
||||||
from Parallelism.Commands import VCommands, VCommandsType
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
|
|
||||||
|
|
||||||
@ -57,14 +55,7 @@ class PlayerProcess(Process):
|
|||||||
self.__bot: VulkanBot = None
|
self.__bot: VulkanBot = None
|
||||||
self.__voiceChannel: VoiceChannel = None
|
self.__voiceChannel: VoiceChannel = None
|
||||||
self.__voiceClient: VoiceClient = None
|
self.__voiceClient: VoiceClient = None
|
||||||
self.__textChannel: TextChannel = None
|
|
||||||
self.__author: User = None
|
|
||||||
self.__botMember: Member = None
|
|
||||||
|
|
||||||
self.__configs: VConfigs = None
|
|
||||||
self.__embeds: VEmbeds = None
|
|
||||||
self.__messages: Messages = None
|
|
||||||
self.__messagesToDelete: List[Message] = []
|
|
||||||
self.__playing = False
|
self.__playing = False
|
||||||
self.__forceStop = False
|
self.__forceStop = False
|
||||||
self.FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
|
self.FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
|
||||||
@ -78,9 +69,6 @@ class PlayerProcess(Process):
|
|||||||
self.__loop = asyncio.get_event_loop_policy().new_event_loop()
|
self.__loop = asyncio.get_event_loop_policy().new_event_loop()
|
||||||
asyncio.set_event_loop(self.__loop)
|
asyncio.set_event_loop(self.__loop)
|
||||||
|
|
||||||
self.__configs = VConfigs()
|
|
||||||
self.__messages = Messages()
|
|
||||||
self.__embeds = VEmbeds()
|
|
||||||
self.__downloader = Downloader()
|
self.__downloader = Downloader()
|
||||||
|
|
||||||
self.__semStopPlaying = Semaphore(0)
|
self.__semStopPlaying = Semaphore(0)
|
||||||
|
|||||||
365
Parallelism/PlayerThread.py
Normal file
365
Parallelism/PlayerThread.py
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
import asyncio
|
||||||
|
from time import sleep, time
|
||||||
|
from urllib.parse import parse_qs, urlparse
|
||||||
|
from Music.VulkanInitializer import VulkanInitializer
|
||||||
|
from discord import Member, VoiceClient
|
||||||
|
from asyncio import AbstractEventLoop, Semaphore
|
||||||
|
from threading import RLock, Thread
|
||||||
|
from multiprocessing import Lock
|
||||||
|
from typing import Callable, List
|
||||||
|
from discord import Guild, FFmpegPCMAudio, VoiceChannel
|
||||||
|
from Music.Playlist import Playlist
|
||||||
|
from Music.Song import Song
|
||||||
|
from Config.Configs import VConfigs
|
||||||
|
from Music.VulkanBot import VulkanBot
|
||||||
|
from Music.Downloader import Downloader
|
||||||
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
|
|
||||||
|
|
||||||
|
class TimeoutClock:
|
||||||
|
def __init__(self, callback: Callable, loop: asyncio.AbstractEventLoop):
|
||||||
|
self.__callback = callback
|
||||||
|
self.__task = loop.create_task(self.__executor())
|
||||||
|
|
||||||
|
async def __executor(self):
|
||||||
|
await asyncio.sleep(VConfigs().VC_TIMEOUT)
|
||||||
|
await self.__callback()
|
||||||
|
|
||||||
|
def cancel(self):
|
||||||
|
self.__task.cancel()
|
||||||
|
|
||||||
|
|
||||||
|
class PlayerThread(Thread):
|
||||||
|
"""Player Thread to control the song playback in the same Process of the Main Process"""
|
||||||
|
|
||||||
|
def __init__(self, bot: VulkanBot, guild: Guild, name: str, voiceChannel: VoiceChannel, playlist: Playlist, lock: Lock, guildID: int, textID: int, voiceID: int, authorID: int) -> None:
|
||||||
|
Thread.__init__(self, name=name, group=None, target=None, args=(), kwargs={})
|
||||||
|
# Synchronization objects
|
||||||
|
self.__playlist: Playlist = playlist
|
||||||
|
self.__playlistLock: Lock = lock
|
||||||
|
self.__loop: AbstractEventLoop = None
|
||||||
|
self.__playerLock: RLock = RLock()
|
||||||
|
# Discord context ID
|
||||||
|
self.__guildID = guildID
|
||||||
|
self.__voiceChannelID = voiceID
|
||||||
|
self.__guild: Guild = guild
|
||||||
|
self.__bot: VulkanBot = bot
|
||||||
|
self.__voiceChannel: VoiceChannel = voiceChannel
|
||||||
|
self.__voiceClient: VoiceClient = None
|
||||||
|
|
||||||
|
self.__downloader = Downloader()
|
||||||
|
|
||||||
|
self.__playing = False
|
||||||
|
self.__forceStop = False
|
||||||
|
self.FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
|
||||||
|
'options': '-vn'}
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
"""This method is called automatically when the Thread starts"""
|
||||||
|
try:
|
||||||
|
print(f'Starting Player Thread for Guild {self.name}')
|
||||||
|
self.__loop = asyncio.get_event_loop_policy().new_event_loop()
|
||||||
|
asyncio.set_event_loop(self.__loop)
|
||||||
|
self.__loop.run_until_complete(self._run())
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[Error in Process {self.name}] -> {e}')
|
||||||
|
|
||||||
|
async def _run(self) -> None:
|
||||||
|
# Connect to voice Channel
|
||||||
|
await self.__connectToVoiceChannel()
|
||||||
|
# Start the timeout function
|
||||||
|
self.__timer = TimeoutClock(self.__timeoutHandler, self.__loop)
|
||||||
|
# Start a Task to play songs
|
||||||
|
self.__loop.create_task(self.__playPlaylistSongs())
|
||||||
|
|
||||||
|
def __verifyIfIsPlaying(self) -> bool:
|
||||||
|
if self.__voiceClient is None:
|
||||||
|
return False
|
||||||
|
if not self.__voiceClient.is_connected():
|
||||||
|
return False
|
||||||
|
return self.__voiceClient.is_playing() or self.__voiceClient.is_paused()
|
||||||
|
|
||||||
|
async def __playPlaylistSongs(self) -> None:
|
||||||
|
"""If the player is not running trigger to play a new song"""
|
||||||
|
self.__playing = self.__verifyIfIsPlaying()
|
||||||
|
if not self.__playing:
|
||||||
|
song = None
|
||||||
|
with self.__playlistLock:
|
||||||
|
with self.__playerLock:
|
||||||
|
song = self.__playlist.next_song()
|
||||||
|
|
||||||
|
if song is not None:
|
||||||
|
self.__loop.create_task(self.__playSong(song), name=f'Song {song.identifier}')
|
||||||
|
self.__playing = True
|
||||||
|
|
||||||
|
async def __playSong(self, song: Song) -> None:
|
||||||
|
"""Function that will trigger the player to play the song"""
|
||||||
|
try:
|
||||||
|
self.__playerLock.acquire()
|
||||||
|
if song is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if song.source is None:
|
||||||
|
return self.__playNext(None)
|
||||||
|
|
||||||
|
# If not connected, connect to bind channel
|
||||||
|
if self.__voiceClient is None:
|
||||||
|
await self.__connectToVoiceChannel()
|
||||||
|
|
||||||
|
# If the voice channel disconnect for some reason
|
||||||
|
if not self.__voiceClient.is_connected():
|
||||||
|
print('[VOICE CHANNEL NOT NULL BUT DISCONNECTED, CONNECTING AGAIN]')
|
||||||
|
await self.__connectToVoiceChannel()
|
||||||
|
# If the player is connected and playing return the song to the playlist
|
||||||
|
elif self.__voiceClient.is_playing():
|
||||||
|
print('[SONG ALREADY PLAYING, RETURNING]')
|
||||||
|
self.__playlist.add_song_start(song)
|
||||||
|
return
|
||||||
|
|
||||||
|
songStillAvailable = self.__verifyIfSongAvailable(song)
|
||||||
|
if not songStillAvailable:
|
||||||
|
print('[SONG NOT AVAILABLE ANYMORE, DOWNLOADING AGAIN]')
|
||||||
|
song = self.__downloadSongAgain(song)
|
||||||
|
|
||||||
|
self.__playing = True
|
||||||
|
self.__songPlaying = song
|
||||||
|
|
||||||
|
player = FFmpegPCMAudio(song.source, **self.FFMPEG_OPTIONS)
|
||||||
|
self.__voiceClient.play(player, after=lambda e: self.__playNext(e))
|
||||||
|
|
||||||
|
self.__timer.cancel()
|
||||||
|
self.__timer = TimeoutClock(self.__timeoutHandler, self.__loop)
|
||||||
|
|
||||||
|
nowPlayingCommand = VCommands(VCommandsType.NOW_PLAYING, song)
|
||||||
|
self.__queueSend.put(nowPlayingCommand)
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[ERROR IN PLAY SONG FUNCTION] -> {e}, {type(e)}')
|
||||||
|
self.__playNext(None)
|
||||||
|
finally:
|
||||||
|
self.__playerLock.release()
|
||||||
|
|
||||||
|
def __playNext(self, error) -> None:
|
||||||
|
if error is not None:
|
||||||
|
print(f'[ERROR PLAYING SONG] -> {error}')
|
||||||
|
with self.__playlistLock:
|
||||||
|
with self.__playerLock:
|
||||||
|
if self.__forceStop: # If it's forced to stop player
|
||||||
|
self.__forceStop = False
|
||||||
|
return None
|
||||||
|
|
||||||
|
song = self.__playlist.next_song()
|
||||||
|
|
||||||
|
if song is not None:
|
||||||
|
self.__loop.create_task(self.__playSong(song), name=f'Song {song.identifier}')
|
||||||
|
else:
|
||||||
|
self.__playlist.loop_off()
|
||||||
|
self.__songPlaying = None
|
||||||
|
self.__playing = False
|
||||||
|
# Send a command to the main process put this one to sleep
|
||||||
|
sleepCommand = VCommands(VCommandsType.SLEEPING)
|
||||||
|
self.__queueSend.put(sleepCommand)
|
||||||
|
# Release the semaphore to finish the process
|
||||||
|
self.__semStopPlaying.release()
|
||||||
|
|
||||||
|
def __verifyIfSongAvailable(self, song: Song) -> bool:
|
||||||
|
"""Verify the song source to see if it's already expired"""
|
||||||
|
try:
|
||||||
|
parsedUrl = urlparse(song.source)
|
||||||
|
|
||||||
|
if 'expire' not in parsedUrl.query:
|
||||||
|
# If already passed 5 hours since the download
|
||||||
|
if song.downloadTime + 18000 < int(time()):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
# If the current time plus the song duration plus 10min exceeds the expirationValue
|
||||||
|
expireValue = parse_qs(parsedUrl.query)['expire'][0]
|
||||||
|
if int(time()) + song.duration + 600 > int(str(expireValue)):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[ERROR VERIFYING SONG AVAILABILITY] -> {e}')
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __downloadSongAgain(self, song: Song) -> Song:
|
||||||
|
"""Force a download to be executed again, one use case is when the song.source expired and needs to refresh"""
|
||||||
|
return self.__downloader.finish_one_song(song)
|
||||||
|
|
||||||
|
async def __playPrev(self, voiceChannelID: int) -> None:
|
||||||
|
with self.__playlistLock:
|
||||||
|
song = self.__playlist.prev_song()
|
||||||
|
|
||||||
|
with self.__playerLock:
|
||||||
|
if song is not None:
|
||||||
|
# If not connect, connect to the user voice channel, may change the channel
|
||||||
|
if self.__voiceClient is None or not self.__voiceClient.is_connected():
|
||||||
|
self.__voiceChannelID = voiceChannelID
|
||||||
|
self.__voiceChannel = self.__guild.get_channel(self.__voiceChannelID)
|
||||||
|
await self.__connectToVoiceChannel()
|
||||||
|
|
||||||
|
# If already playing, stop the current play
|
||||||
|
if self.__verifyIfIsPlaying():
|
||||||
|
# Will forbidden next_song to execute after stopping current player
|
||||||
|
self.__forceStop = True
|
||||||
|
self.__voiceClient.stop()
|
||||||
|
self.__playing = False
|
||||||
|
|
||||||
|
self.__loop.create_task(self.__playSong(song), name=f'Song {song.identifier}')
|
||||||
|
|
||||||
|
async def __restartCurrentSong(self) -> None:
|
||||||
|
song = self.__playlist.getCurrentSong()
|
||||||
|
if song is None:
|
||||||
|
song = self.__playlist.next_song()
|
||||||
|
if song is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.__loop.create_task(self.__playSong(song), name=f'Song {song.identifier}')
|
||||||
|
|
||||||
|
async def receiveCommand(self, command: VCommands) -> None:
|
||||||
|
type = command.getType()
|
||||||
|
args = command.getArgs()
|
||||||
|
print(f'Player Thread {self.__guild.name} received command {type}')
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.__playerLock.acquire()
|
||||||
|
if type == VCommandsType.PAUSE:
|
||||||
|
self.__pause()
|
||||||
|
elif type == VCommandsType.RESUME:
|
||||||
|
await self.__resume()
|
||||||
|
elif type == VCommandsType.SKIP:
|
||||||
|
await self.__skip()
|
||||||
|
elif type == VCommandsType.PLAY:
|
||||||
|
await self.__playPlaylistSongs()
|
||||||
|
elif type == VCommandsType.PREV:
|
||||||
|
await self.__playPrev(args)
|
||||||
|
elif type == VCommandsType.RESET:
|
||||||
|
await self.__reset()
|
||||||
|
elif type == VCommandsType.STOP:
|
||||||
|
await self.__stop()
|
||||||
|
else:
|
||||||
|
print(f'[ERROR] -> Unknown Command Received: {command}')
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[ERROR IN COMMAND RECEIVER] -> {type} - {e}')
|
||||||
|
finally:
|
||||||
|
self.__playerLock.release()
|
||||||
|
|
||||||
|
def __pause(self) -> None:
|
||||||
|
if self.__voiceClient is not None:
|
||||||
|
if self.__voiceClient.is_connected():
|
||||||
|
if self.__voiceClient.is_playing():
|
||||||
|
self.__voiceClient.pause()
|
||||||
|
|
||||||
|
async def __reset(self) -> None:
|
||||||
|
if self.__voiceClient is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not self.__voiceClient.is_connected():
|
||||||
|
await self.__connectToVoiceChannel()
|
||||||
|
if self.__songPlaying is not None:
|
||||||
|
await self.__restartCurrentSong()
|
||||||
|
|
||||||
|
async def __stop(self) -> None:
|
||||||
|
if self.__voiceClient is not None:
|
||||||
|
if self.__voiceClient.is_connected():
|
||||||
|
with self.__playlistLock:
|
||||||
|
self.__playlist.loop_off()
|
||||||
|
self.__playlist.clear()
|
||||||
|
|
||||||
|
self.__voiceClient.stop()
|
||||||
|
await self.__voiceClient.disconnect()
|
||||||
|
|
||||||
|
self.__songPlaying = None
|
||||||
|
self.__playing = False
|
||||||
|
self.__voiceClient = None
|
||||||
|
# If the voiceClient is not None we finish things
|
||||||
|
else:
|
||||||
|
await self.__forceBotDisconnectAndStop()
|
||||||
|
|
||||||
|
async def __resume(self) -> None:
|
||||||
|
# Lock to work with Player
|
||||||
|
with self.__playerLock:
|
||||||
|
if self.__voiceClient is not None:
|
||||||
|
# If the player is paused then return to play
|
||||||
|
if self.__voiceClient.is_paused():
|
||||||
|
return self.__voiceClient.resume()
|
||||||
|
# If there is a current song but the voice client is not playing
|
||||||
|
elif self.__songPlaying is not None and not self.__voiceClient.is_playing():
|
||||||
|
await self.__playSong(self.__songPlaying)
|
||||||
|
|
||||||
|
async def __skip(self) -> None:
|
||||||
|
self.__playing = self.__verifyIfIsPlaying()
|
||||||
|
# Lock to work with Player
|
||||||
|
with self.__playerLock:
|
||||||
|
if self.__playing:
|
||||||
|
self.__playing = False
|
||||||
|
self.__voiceClient.stop()
|
||||||
|
# If for some reason the Bot has disconnect but there is still songs to play
|
||||||
|
elif len(self.__playlist.getSongs()) > 0:
|
||||||
|
print('[RESTARTING CURRENT SONG]')
|
||||||
|
await self.__restartCurrentSong()
|
||||||
|
|
||||||
|
async def __forceBotDisconnectAndStop(self) -> None:
|
||||||
|
# Lock to work with Player
|
||||||
|
with self.__playerLock:
|
||||||
|
if self.__voiceClient is None:
|
||||||
|
return
|
||||||
|
self.__playing = False
|
||||||
|
self.__songPlaying = None
|
||||||
|
try:
|
||||||
|
self.__voiceClient.stop()
|
||||||
|
await self.__voiceClient.disconnect(force=True)
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[ERROR FORCING BOT TO STOP] -> {e}')
|
||||||
|
finally:
|
||||||
|
self.__voiceClient = None
|
||||||
|
with self.__playlistLock:
|
||||||
|
self.__playlist.clear()
|
||||||
|
self.__playlist.loop_off()
|
||||||
|
|
||||||
|
async def __timeoutHandler(self) -> None:
|
||||||
|
try:
|
||||||
|
if self.__voiceClient is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# If the bot should not disconnect when alone
|
||||||
|
if not VConfigs().SHOULD_AUTO_DISCONNECT_WHEN_ALONE:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.__voiceClient.is_connected():
|
||||||
|
if self.__voiceClient.is_playing() or self.__voiceClient.is_paused():
|
||||||
|
if not self.__isBotAloneInChannel(): # If bot is not alone continue to play
|
||||||
|
self.__timer = TimeoutClock(self.__timeoutHandler, self.__loop)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Finish the process
|
||||||
|
with self.__playerLock:
|
||||||
|
with self.__playlistLock:
|
||||||
|
self.__playlist.loop_off()
|
||||||
|
await self.__forceBotDisconnectAndStop()
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[ERROR IN TIMEOUT] -> {e}')
|
||||||
|
|
||||||
|
def __isBotAloneInChannel(self) -> bool:
|
||||||
|
try:
|
||||||
|
if len(self.__voiceClient.channel.members) <= 1:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[ERROR IN CHECK BOT ALONE] -> {e}')
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def __connectToVoiceChannel(self) -> bool:
|
||||||
|
try:
|
||||||
|
print('[CONNECTING TO VOICE CHANNEL]')
|
||||||
|
if self.__voiceClient is not None:
|
||||||
|
try:
|
||||||
|
await self.__voiceClient.disconnect(force=True)
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[ERROR FORCING DISCONNECT] -> {e}')
|
||||||
|
self.__voiceClient = await self.__voiceChannel.connect(reconnect=True, timeout=None)
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[ERROR CONNECTING TO VC] -> {e}')
|
||||||
|
return False
|
||||||
@ -4,7 +4,7 @@ from discord.ui import View
|
|||||||
from Config.Emojis import VEmojis
|
from Config.Emojis import VEmojis
|
||||||
from Messages.MessagesCategory import MessagesCategory
|
from Messages.MessagesCategory import MessagesCategory
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
from Parallelism.ProcessInfo import ProcessInfo
|
from Parallelism.ProcessInfo import PlayerInfo
|
||||||
from Config.Messages import Messages
|
from Config.Messages import Messages
|
||||||
from Music.Song import Song
|
from Music.Song import Song
|
||||||
from Config.Embeds import VEmbeds
|
from Config.Embeds import VEmbeds
|
||||||
@ -29,7 +29,7 @@ class ProcessCommandsExecutor:
|
|||||||
self.__embeds = VEmbeds()
|
self.__embeds = VEmbeds()
|
||||||
self.__emojis = VEmojis()
|
self.__emojis = VEmojis()
|
||||||
|
|
||||||
async def sendNowPlaying(self, processInfo: ProcessInfo, song: Song) -> None:
|
async def sendNowPlaying(self, processInfo: PlayerInfo, song: Song) -> None:
|
||||||
# Get the lock of the playlist
|
# Get the lock of the playlist
|
||||||
playlist = processInfo.getPlaylist()
|
playlist = processInfo.getPlaylist()
|
||||||
if playlist.isLoopingOne():
|
if playlist.isLoopingOne():
|
||||||
|
|||||||
@ -9,9 +9,9 @@ class ProcessStatus(Enum):
|
|||||||
SLEEPING = 'Sleeping'
|
SLEEPING = 'Sleeping'
|
||||||
|
|
||||||
|
|
||||||
class ProcessInfo:
|
class PlayerInfo:
|
||||||
"""
|
"""
|
||||||
Class to store the reference to all structures to maintain a player process
|
Class to store the reference to all structures to maintain a song player
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, process: Process, queueToPlayer: Queue, queueToMain: Queue, playlist: Playlist, lock: Lock, textChannel: TextChannel) -> None:
|
def __init__(self, process: Process, queueToPlayer: Queue, queueToMain: Queue, playlist: Playlist, lock: Lock, textChannel: TextChannel) -> None:
|
||||||
|
|||||||
@ -7,19 +7,20 @@ from typing import Dict, Tuple, Union
|
|||||||
from Config.Singleton import Singleton
|
from Config.Singleton import Singleton
|
||||||
from discord import Guild, Interaction
|
from discord import Guild, Interaction
|
||||||
from discord.ext.commands import Context
|
from discord.ext.commands import Context
|
||||||
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
from Parallelism.ProcessExecutor import ProcessCommandsExecutor
|
from Parallelism.ProcessExecutor import ProcessCommandsExecutor
|
||||||
from Music.Song import Song
|
from Music.Song import Song
|
||||||
from Parallelism.PlayerProcess import PlayerProcess
|
from Parallelism.PlayerProcess import PlayerProcess
|
||||||
from Music.Playlist import Playlist
|
from Music.Playlist import Playlist
|
||||||
from Parallelism.ProcessInfo import ProcessInfo, ProcessStatus
|
from Parallelism.ProcessInfo import PlayerInfo, ProcessStatus
|
||||||
from Parallelism.Commands import VCommands, VCommandsType
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
|
|
||||||
|
|
||||||
class ProcessManager(Singleton):
|
class ProcessManager(Singleton, AbstractPlayersManager):
|
||||||
"""
|
"""
|
||||||
Manage all running player process, creating and storing them for future calls
|
Manage all running player process, creating and storing them for future calls
|
||||||
Deal with the creation of shared memory
|
Deals with the creation of shared memory
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, bot: VulkanBot = None) -> None:
|
def __init__(self, bot: VulkanBot = None) -> None:
|
||||||
@ -28,14 +29,14 @@ class ProcessManager(Singleton):
|
|||||||
VManager.register('Playlist', Playlist)
|
VManager.register('Playlist', Playlist)
|
||||||
self.__manager = VManager()
|
self.__manager = VManager()
|
||||||
self.__manager.start()
|
self.__manager.start()
|
||||||
self.__playersProcess: Dict[int, ProcessInfo] = {}
|
self.__playersProcess: Dict[int, PlayerInfo] = {}
|
||||||
self.__playersListeners: Dict[int, Tuple[Thread, bool]] = {}
|
self.__playersListeners: Dict[int, Tuple[Thread, bool]] = {}
|
||||||
self.__playersCommandsExecutor: Dict[int, ProcessCommandsExecutor] = {}
|
self.__playersCommandsExecutor: Dict[int, ProcessCommandsExecutor] = {}
|
||||||
|
|
||||||
def setPlayerInfo(self, guild: Guild, info: ProcessInfo):
|
def setPlayerInfo(self, guild: Guild, info: PlayerInfo):
|
||||||
self.__playersProcess[guild.id] = info
|
self.__playersProcess[guild.id] = info
|
||||||
|
|
||||||
def getOrCreatePlayerInfo(self, guild: Guild, context: Union[Context, Interaction]) -> ProcessInfo:
|
def getOrCreatePlayerInfo(self, guild: Guild, context: Union[Context, Interaction]) -> PlayerInfo:
|
||||||
"""Return the process info for the guild, the user in context must be connected to a voice_channel"""
|
"""Return the process info for the guild, the user in context must be connected to a voice_channel"""
|
||||||
try:
|
try:
|
||||||
if guild.id not in self.__playersProcess.keys():
|
if guild.id not in self.__playersProcess.keys():
|
||||||
@ -62,7 +63,7 @@ class ProcessManager(Singleton):
|
|||||||
newProcessInfo.getQueueToPlayer().put(playCommand)
|
newProcessInfo.getQueueToPlayer().put(playCommand)
|
||||||
self.__playersProcess[guild.id] = newProcessInfo
|
self.__playersProcess[guild.id] = newProcessInfo
|
||||||
|
|
||||||
def getRunningPlayerInfo(self, guild: Guild) -> ProcessInfo:
|
def getRunningPlayerInfo(self, guild: Guild) -> PlayerInfo:
|
||||||
"""Return the process info for the guild, if not, return None"""
|
"""Return the process info for the guild, if not, return None"""
|
||||||
if guild.id not in self.__playersProcess.keys():
|
if guild.id not in self.__playersProcess.keys():
|
||||||
print('Process Info not found')
|
print('Process Info not found')
|
||||||
@ -70,7 +71,7 @@ class ProcessManager(Singleton):
|
|||||||
|
|
||||||
return self.__playersProcess[guild.id]
|
return self.__playersProcess[guild.id]
|
||||||
|
|
||||||
def __createProcessInfo(self, guild: Guild, context: Context) -> ProcessInfo:
|
def __createProcessInfo(self, guild: Guild, context: Context) -> PlayerInfo:
|
||||||
guildID: int = context.guild.id
|
guildID: int = context.guild.id
|
||||||
textID: int = context.channel.id
|
textID: int = context.channel.id
|
||||||
voiceID: int = context.author.voice.channel.id
|
voiceID: int = context.author.voice.channel.id
|
||||||
@ -82,7 +83,7 @@ class ProcessManager(Singleton):
|
|||||||
queueToSend = Queue()
|
queueToSend = Queue()
|
||||||
process = PlayerProcess(context.guild.name, playlist, lock, queueToSend,
|
process = PlayerProcess(context.guild.name, playlist, lock, queueToSend,
|
||||||
queueToListen, guildID, textID, voiceID, authorID)
|
queueToListen, guildID, textID, voiceID, authorID)
|
||||||
processInfo = ProcessInfo(process, queueToSend, queueToListen,
|
processInfo = PlayerInfo(process, queueToSend, queueToListen,
|
||||||
playlist, lock, context.channel)
|
playlist, lock, context.channel)
|
||||||
|
|
||||||
# Create a Thread to listen for the queue coming from the Player Process, this will redirect the Queue to a async
|
# Create a Thread to listen for the queue coming from the Player Process, this will redirect the Queue to a async
|
||||||
@ -110,7 +111,7 @@ class ProcessManager(Singleton):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'[ERROR STOPPING PROCESS] -> {e}')
|
print(f'[ERROR STOPPING PROCESS] -> {e}')
|
||||||
|
|
||||||
def __recreateProcess(self, guild: Guild, context: Union[Context, Interaction]) -> ProcessInfo:
|
def __recreateProcess(self, guild: Guild, context: Union[Context, Interaction]) -> PlayerInfo:
|
||||||
"""Create a new process info using previous playlist"""
|
"""Create a new process info using previous playlist"""
|
||||||
self.__stopPossiblyRunningProcess(guild)
|
self.__stopPossiblyRunningProcess(guild)
|
||||||
|
|
||||||
@ -129,7 +130,7 @@ class ProcessManager(Singleton):
|
|||||||
queueToSend = Queue()
|
queueToSend = Queue()
|
||||||
process = PlayerProcess(context.guild.name, playlist, lock, queueToSend,
|
process = PlayerProcess(context.guild.name, playlist, lock, queueToSend,
|
||||||
queueToListen, guildID, textID, voiceID, authorID)
|
queueToListen, guildID, textID, voiceID, authorID)
|
||||||
processInfo = ProcessInfo(process, queueToSend, queueToListen,
|
processInfo = PlayerInfo(process, queueToSend, queueToListen,
|
||||||
playlist, lock, context.channel)
|
playlist, lock, context.channel)
|
||||||
|
|
||||||
# Create a Thread to listen for the queue coming from the Player Process, this will redirect the Queue to a async
|
# Create a Thread to listen for the queue coming from the Player Process, this will redirect the Queue to a async
|
||||||
|
|||||||
199
Parallelism/ThreadManager.py
Normal file
199
Parallelism/ThreadManager.py
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
import asyncio
|
||||||
|
from multiprocessing import Lock, Queue
|
||||||
|
from multiprocessing.managers import BaseManager, NamespaceProxy
|
||||||
|
from queue import Empty
|
||||||
|
from threading import Thread
|
||||||
|
from typing import Dict, Tuple, Union
|
||||||
|
from Config.Singleton import Singleton
|
||||||
|
from discord import Guild, Interaction
|
||||||
|
from discord.ext.commands import Context
|
||||||
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
|
from Parallelism.ProcessExecutor import ProcessCommandsExecutor
|
||||||
|
from Music.Song import Song
|
||||||
|
from Parallelism.PlayerProcess import PlayerProcess
|
||||||
|
from Music.Playlist import Playlist
|
||||||
|
from Parallelism.ProcessInfo import PlayerInfo, ProcessStatus
|
||||||
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
|
from Music.VulkanBot import VulkanBot
|
||||||
|
|
||||||
|
|
||||||
|
class ThreadManager(Singleton, AbstractPlayersManager):
|
||||||
|
"""
|
||||||
|
Manage all running player threads, creating and storing them for future calls
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, bot: VulkanBot = None) -> None:
|
||||||
|
if not super().created:
|
||||||
|
self.__bot = bot
|
||||||
|
self.__playersProcess: Dict[int, Thread] = {}
|
||||||
|
|
||||||
|
def setPlayerInfo(self, guild: Guild, info: PlayerInfo):
|
||||||
|
self.__playersProcess[guild.id] = info
|
||||||
|
|
||||||
|
def getOrCreatePlayerInfo(self, guild: Guild, context: Union[Context, Interaction]) -> PlayerInfo:
|
||||||
|
"""Return the process info for the guild, the user in context must be connected to a voice_channel"""
|
||||||
|
try:
|
||||||
|
if guild.id not in self.__playersProcess.keys():
|
||||||
|
self.__playersProcess[guild.id] = self.__createProcessInfo(guild, context)
|
||||||
|
else:
|
||||||
|
# If the process has ended create a new one
|
||||||
|
if not self.__playersProcess[guild.id].getProcess().is_alive():
|
||||||
|
self.__playersProcess[guild.id] = self.__recreateProcess(guild, context)
|
||||||
|
|
||||||
|
return self.__playersProcess[guild.id]
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[Error In GetPlayerContext] -> {e}')
|
||||||
|
|
||||||
|
def resetProcess(self, guild: Guild, context: Context) -> None:
|
||||||
|
"""Restart a running process, already start it to return to play"""
|
||||||
|
if guild.id not in self.__playersProcess.keys():
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Recreate the process keeping the playlist
|
||||||
|
newProcessInfo = self.__recreateProcess(guild, context)
|
||||||
|
newProcessInfo.getProcess().start() # Start the process
|
||||||
|
# Send a command to start the play again
|
||||||
|
playCommand = VCommands(VCommandsType.PLAY)
|
||||||
|
newProcessInfo.getQueueToPlayer().put(playCommand)
|
||||||
|
self.__playersProcess[guild.id] = newProcessInfo
|
||||||
|
|
||||||
|
def getRunningPlayerInfo(self, guild: Guild) -> PlayerInfo:
|
||||||
|
"""Return the process info for the guild, if not, return None"""
|
||||||
|
if guild.id not in self.__playersProcess.keys():
|
||||||
|
print('Process Info not found')
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.__playersProcess[guild.id]
|
||||||
|
|
||||||
|
def __createProcessInfo(self, guild: Guild, context: Context) -> PlayerInfo:
|
||||||
|
guildID: int = context.guild.id
|
||||||
|
textID: int = context.channel.id
|
||||||
|
voiceID: int = context.author.voice.channel.id
|
||||||
|
authorID: int = context.author.id
|
||||||
|
|
||||||
|
playlist: Playlist = self.__manager.Playlist()
|
||||||
|
lock = Lock()
|
||||||
|
queueToListen = Queue()
|
||||||
|
queueToSend = Queue()
|
||||||
|
process = PlayerProcess(context.guild.name, playlist, lock, queueToSend,
|
||||||
|
queueToListen, guildID, textID, voiceID, authorID)
|
||||||
|
processInfo = PlayerInfo(process, queueToSend, queueToListen,
|
||||||
|
playlist, lock, context.channel)
|
||||||
|
|
||||||
|
# Create a Thread to listen for the queue coming from the Player Process, this will redirect the Queue to a async
|
||||||
|
thread = Thread(target=self.__listenToCommands,
|
||||||
|
args=(queueToListen, guild), daemon=True)
|
||||||
|
self.__playersListeners[guildID] = (thread, False)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
# Create a Message Controller for this player
|
||||||
|
self.__playersCommandsExecutor[guildID] = ProcessCommandsExecutor(self.__bot, guildID)
|
||||||
|
|
||||||
|
return processInfo
|
||||||
|
|
||||||
|
def __stopPossiblyRunningProcess(self, guild: Guild):
|
||||||
|
try:
|
||||||
|
if guild.id in self.__playersProcess.keys():
|
||||||
|
playerProcess = self.__playersProcess[guild.id]
|
||||||
|
process = playerProcess.getProcess()
|
||||||
|
process.close()
|
||||||
|
process.kill()
|
||||||
|
playerProcess.getQueueToMain().close()
|
||||||
|
playerProcess.getQueueToMain().join_thread()
|
||||||
|
playerProcess.getQueueToPlayer().close()
|
||||||
|
playerProcess.getQueueToPlayer().join_thread()
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[ERROR STOPPING PROCESS] -> {e}')
|
||||||
|
|
||||||
|
def __recreateProcess(self, guild: Guild, context: Union[Context, Interaction]) -> PlayerInfo:
|
||||||
|
"""Create a new process info using previous playlist"""
|
||||||
|
self.__stopPossiblyRunningProcess(guild)
|
||||||
|
|
||||||
|
guildID: int = context.guild.id
|
||||||
|
textID: int = context.channel.id
|
||||||
|
if isinstance(context, Interaction):
|
||||||
|
authorID: int = context.user.id
|
||||||
|
voiceID: int = context.user.voice.channel.id
|
||||||
|
else:
|
||||||
|
authorID: int = context.author.id
|
||||||
|
voiceID: int = context.author.voice.channel.id
|
||||||
|
|
||||||
|
playlist: Playlist = self.__playersProcess[guildID].getPlaylist()
|
||||||
|
lock = Lock()
|
||||||
|
queueToListen = Queue()
|
||||||
|
queueToSend = Queue()
|
||||||
|
process = PlayerProcess(context.guild.name, playlist, lock, queueToSend,
|
||||||
|
queueToListen, guildID, textID, voiceID, authorID)
|
||||||
|
processInfo = PlayerInfo(process, queueToSend, queueToListen,
|
||||||
|
playlist, lock, context.channel)
|
||||||
|
|
||||||
|
# Create a Thread to listen for the queue coming from the Player Process, this will redirect the Queue to a async
|
||||||
|
thread = Thread(target=self.__listenToCommands,
|
||||||
|
args=(queueToListen, guild), daemon=True)
|
||||||
|
self.__playersListeners[guildID] = (thread, False)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
return processInfo
|
||||||
|
|
||||||
|
def __listenToCommands(self, queue: Queue, guild: Guild) -> None:
|
||||||
|
guildID = guild.id
|
||||||
|
while True:
|
||||||
|
shouldEnd = self.__playersListeners[guildID][1]
|
||||||
|
if shouldEnd:
|
||||||
|
break
|
||||||
|
|
||||||
|
try:
|
||||||
|
command: VCommands = queue.get(timeout=5)
|
||||||
|
commandType = command.getType()
|
||||||
|
args = command.getArgs()
|
||||||
|
|
||||||
|
print(f'Process {guild.name} sended command {commandType}')
|
||||||
|
if commandType == VCommandsType.NOW_PLAYING:
|
||||||
|
asyncio.run_coroutine_threadsafe(self.showNowPlaying(
|
||||||
|
guild.id, args), self.__bot.loop)
|
||||||
|
elif commandType == VCommandsType.TERMINATE:
|
||||||
|
# Delete the process elements and return, to finish task
|
||||||
|
self.__terminateProcess(guildID)
|
||||||
|
return
|
||||||
|
elif commandType == VCommandsType.SLEEPING:
|
||||||
|
# The process might be used again
|
||||||
|
self.__sleepingProcess(guildID)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
print(f'[ERROR] -> Unknown Command Received from Process: {commandType}')
|
||||||
|
except Empty:
|
||||||
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[ERROR IN LISTENING PROCESS] -> {guild.name} - {e}')
|
||||||
|
|
||||||
|
def __terminateProcess(self, guildID: int) -> None:
|
||||||
|
# Delete all structures associated with the Player
|
||||||
|
del self.__playersProcess[guildID]
|
||||||
|
del self.__playersCommandsExecutor[guildID]
|
||||||
|
threadListening = self.__playersListeners[guildID]
|
||||||
|
threadListening._stop()
|
||||||
|
del self.__playersListeners[guildID]
|
||||||
|
|
||||||
|
def __sleepingProcess(self, guildID: int) -> None:
|
||||||
|
# Disable all process structures, except Playlist
|
||||||
|
queue1 = self.__playersProcess[guildID].getQueueToMain()
|
||||||
|
queue2 = self.__playersProcess[guildID].getQueueToPlayer()
|
||||||
|
queue1.close()
|
||||||
|
queue1.join_thread()
|
||||||
|
queue2.close()
|
||||||
|
queue2.join_thread()
|
||||||
|
# Set the status of this process as sleeping, only the playlist object remains
|
||||||
|
self.__playersProcess[guildID].setStatus(ProcessStatus.SLEEPING)
|
||||||
|
|
||||||
|
async def showNowPlaying(self, guildID: int, song: Song) -> None:
|
||||||
|
commandExecutor = self.__playersCommandsExecutor[guildID]
|
||||||
|
processInfo = self.__playersProcess[guildID]
|
||||||
|
await commandExecutor.sendNowPlaying(processInfo, song)
|
||||||
|
|
||||||
|
|
||||||
|
class VManager(BaseManager):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class VProxy(NamespaceProxy):
|
||||||
|
_exposed_ = ('__getattribute__', '__setattr__', '__delattr__')
|
||||||
Loading…
x
Reference in New Issue
Block a user