mirror of
https://github.com/RafaelSolVargas/Vulkan.git
synced 2025-10-29 16:57:23 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50363cd630 | ||
|
|
d605e6a5a8 | ||
|
|
b3a9920037 | ||
|
|
6be5c0d27b | ||
|
|
e3e7f2048a | ||
|
|
634e6560c6 | ||
|
|
582e35bce1 | ||
|
|
a82bf7950b | ||
|
|
aa5649bcdc | ||
|
|
6cfd188c3b | ||
|
|
83a864725d | ||
|
|
f336df43ee | ||
|
|
d86f014a3a | ||
|
|
219fef7daa | ||
|
|
45d27b4c47 | ||
|
|
2114f15840 |
7
.env.example
Normal file
7
.env.example
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
BOT_TOKEN=Your_Own_Bot_Token
|
||||||
|
# If you do not want to use spotify, remove the 2 following lines
|
||||||
|
SPOTIFY_ID=Your_Own_Spotify_ID
|
||||||
|
SPOTIFY_SECRET=Your_Own_Spotify_Secret
|
||||||
|
BOT_PREFIX=Your_Wanted_Prefix_For_Vulkan
|
||||||
|
SHOULD_AUTO_DISCONNECT_WHEN_ALONE=True #all settings can be set like this
|
||||||
|
#etc... All settings can be set this way
|
||||||
33
.github/Docs/DOCKER.md
vendored
Normal file
33
.github/Docs/DOCKER.md
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<h1 align="center">Docker</h1>
|
||||||
|
|
||||||
|
This bot can be easily deployed using Docker.
|
||||||
|
|
||||||
|
## **Requirements**
|
||||||
|
To run this project in a Docker container you must have Docker and Docker Compose installed in your machine. Find how to install Docker in your machine [here](https://docs.docker.com/get-docker/) and find how to install Docker Compose in your machine [here](https://docs.docker.com/compose/install/).
|
||||||
|
|
||||||
|
Once you have Docker and Docker Compose installed in your machine, clone or download this repository and follow the instructions below.
|
||||||
|
|
||||||
|
## **Running the Bot**
|
||||||
|
To run the bot in a Docker container, you must first create a `.env` file in the root of the project if there isn't one already. You will need to change the parameters in the `.env` file to your own parameters. You can find an example of a `.env` file [here](.env.example). You will also be able to change the settings in that environment file as explained in the [Settings page](.github/Docs/SETTINGS.md).
|
||||||
|
|
||||||
|
**If any of the following commands fail, try without a dash between docker and compose.**
|
||||||
|
|
||||||
|
To run the bot, simply execute the following command in the root of the project:
|
||||||
|
```bash
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
This will build the Docker image and run the bot in a Docker container. The `-d` flag is used to run the container in detached mode, which means that the container will run in the background. If you want to see the logs of the container, you can run the following command:
|
||||||
|
```bash
|
||||||
|
docker-compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
To stop the container, run the following command:
|
||||||
|
```bash
|
||||||
|
docker-compose down
|
||||||
|
```
|
||||||
|
## **Updating the Bot**
|
||||||
|
To update the bot, you must first stop the container as explained in the previous section. Then, you must pull the latest changes from the repository, in any way you want. Finally, you must build the Docker image again and run the container again. To do this, run the following commands:
|
||||||
|
```bash
|
||||||
|
docker-compose build
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
23
.github/Docs/SETTINGS.md
vendored
23
.github/Docs/SETTINGS.md
vendored
@@ -8,31 +8,40 @@
|
|||||||
- Maximum songs downloading at a time
|
- Maximum songs downloading at a time
|
||||||
- Maximum songs in a Queue Page
|
- Maximum songs in a Queue Page
|
||||||
|
|
||||||
All parameters can be modified in the Configs.py file that are located in the Config folder
|
All parameters can be modified in the .env file or in an environment variable.
|
||||||
> The path to the file is ./Config/Configs.py
|
Here is a sample of the .env file:
|
||||||
|
|
||||||
|
```env
|
||||||
|
BOT_TOKEN=Your_Own_Bot_Token
|
||||||
|
SPOTIFY_ID=Your_Own_Spotify_ID
|
||||||
|
SPOTIFY_SECRET=Your_Own_Spotify_Secret
|
||||||
|
BOT_PREFIX=Your_Wanted_Prefix_For_Vulkan
|
||||||
|
SHOULD_AUTO_DISCONNECT_WHEN_ALONE=True #all settings can be set like this
|
||||||
|
#etc... All settings can be set this way
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### **Bot Prefix**
|
### **Bot Prefix**
|
||||||
The Bot Prefix is just a string that must be passed as prefix when calling any Bot command from the Discord.
|
The Bot Prefix is just a string that must be passed as prefix when calling any Bot command from the Discord.
|
||||||
To change that you must: <br>
|
To change that you must: <br>
|
||||||
- Change the property BOT_PREFIX of the VConfigs class to what prefix you want to.
|
- Change the property BOT_PREFIX in the .env file or in an environment variable to what you want to.
|
||||||
|
|
||||||
### **Auto Disconnect**
|
### **Auto Disconnect**
|
||||||
As a result of the [Issue 33](https://github.com/RafaelSolVargas/Vulkan/issues/33) you can configure if the Bot will auto disconnect when being alone in the voice channel. The default configuration is to disconnect within 300 seconds if it finds out no one is currently listing to it.
|
As a result of the [Issue 33](https://github.com/RafaelSolVargas/Vulkan/issues/33) you can configure if the Bot will auto disconnect when being alone in the voice channel. The default configuration is to disconnect within 300 seconds if it finds out no one is currently listing to it.
|
||||||
To change that you must: <br>
|
To change that you must: <br>
|
||||||
- Change the property SHOULD_AUTO_DISCONNECT_WHEN_ALONE of the VConfigs class to False
|
- Change the property SHOULD_AUTO_DISCONNECT_WHEN_ALONE in the .env file or in an environment variable to False
|
||||||
|
|
||||||
### **Multiprocessing or Threading**
|
### **Multiprocessing or Threading**
|
||||||
As a result of the [Issue 35](https://github.com/RafaelSolVargas/Vulkan/issues/35) you can configure if the Bot will create a specific Python Process for each Player (Guild) that he is playing songs or all will happen in the Main Process. The Default behavior is to create a new process.
|
As a result of the [Issue 35](https://github.com/RafaelSolVargas/Vulkan/issues/35) you can configure if the Bot will create a specific Python Process for each Player (Guild) that he is playing songs or all will happen in the Main Process. The Default behavior is to create a new process.
|
||||||
To change that you must: <br>
|
To change that you must: <br>
|
||||||
- Change the property SONG_PLAYBACK_IN_SEPARATE_PROCESS of the VConfigs class to False
|
- Change the property SONG_PLAYBACK_IN_SEPARATE_PROCESS in the .env file or in an environment variable to False
|
||||||
|
|
||||||
### **Maximum Downloading Quant**
|
### **Maximum Downloading Quant**
|
||||||
The download of songs can be very fast or very slow, the faster it is the slower the response time for any command (during the download) is higher, (including the playback quality), because there will be a Task for each song. But it's possible to set up this variable to slow the download and keep the response time better.
|
The download of songs can be very fast or very slow, the faster it is the slower the response time for any command (during the download) is higher, (including the playback quality), because there will be a Task for each song. But it's possible to set up this variable to slow the download and keep the response time better.
|
||||||
To change that you must: <br>
|
To change that you must: <br>
|
||||||
- Change the property MAX_DOWNLOAD_SONGS_AT_A_TIME of the VConfigs class to what you want to.
|
- Change the property MAX_DOWNLOAD_SONGS_AT_A_TIME in the .env file or in an environment variable to what you want to.
|
||||||
|
|
||||||
### **Maximum Songs In Queue Page**
|
### **Maximum Songs In Queue Page**
|
||||||
When the ```Queue``` command is called, the current song playlist is presented in the Discord, you can configure how many songs you will want to show in each page.
|
When the ```Queue``` command is called, the current song playlist is presented in the Discord, you can configure how many songs you will want to show in each page.
|
||||||
To change that you must: <br>
|
To change that you must: <br>
|
||||||
- Change the property MAX_SONGS_IN_PAGE of the VConfigs class to what you want to.
|
- Change the property MAX_SONGS_IN_PAGE in the .env file or in an environment variable to what you want to.
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 83 KiB |
@@ -1,54 +1,71 @@
|
|||||||
from decouple import config
|
import os
|
||||||
|
from dotenv import load_dotenv
|
||||||
from Config.Singleton import Singleton
|
from Config.Singleton import Singleton
|
||||||
from Config.Folder import Folder
|
from Config.Folder import Folder
|
||||||
|
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
class VConfigs(Singleton):
|
class VConfigs(Singleton):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
if not super().created:
|
if not super().created:
|
||||||
# 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 = os.getenv('SHOULD_AUTO_DISCONNECT_WHEN_ALONE') == 'True'
|
||||||
|
|
||||||
# Recommended to be True, except in cases when your Bot is present in thousands servers, in that case
|
# 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
|
# the delay to start a new Python process for the playback is too much, and to avoid that you set as False
|
||||||
# This feature is for now in testing period, for a more stable version, keep this boolean = True
|
# This feature is for now in testing period, for a more stable version, keep this boolean = Trued
|
||||||
self.SONG_PLAYBACK_IN_SEPARATE_PROCESS = True
|
self.SONG_PLAYBACK_IN_SEPARATE_PROCESS = os.getenv('SONG_PLAYBACK_IN_SEPARATE_PROCESS', 'True') == 'True'
|
||||||
|
|
||||||
# Maximum of songs that will be downloaded at once, the higher this number is, the faster the songs will be all available
|
# Maximum of songs that will be downloaded at once, the higher this number is, the faster the songs will be all available
|
||||||
# but the slower will be the others commands of the Bot during the downloading time, for example, the playback quality
|
# but the slower will be the others commands of the Bot during the downloading time, for example, the playback quality
|
||||||
self.MAX_DOWNLOAD_SONGS_AT_A_TIME = 5
|
self.MAX_DOWNLOAD_SONGS_AT_A_TIME = int(os.getenv('MAX_DOWNLOAD_SONGS_AT_A_TIME', 5))
|
||||||
|
|
||||||
self.BOT_PREFIX = '!'
|
self.BOT_PREFIX = os.getenv('BOT_PREFIX', '!')
|
||||||
try:
|
|
||||||
self.BOT_TOKEN = config('BOT_TOKEN')
|
|
||||||
self.SPOTIFY_ID = config('SPOTIFY_ID')
|
|
||||||
self.SPOTIFY_SECRET = config('SPOTIFY_SECRET')
|
|
||||||
self.BOT_PREFIX = config('BOT_PREFIX')
|
|
||||||
except:
|
|
||||||
print(
|
|
||||||
'[ERROR] -> You must create and .env file with all required fields, see documentation for help')
|
|
||||||
|
|
||||||
self.CLEANER_MESSAGES_QUANT = 5
|
if self.BOT_PREFIX == 'Your_Wanted_Prefix_For_Vulkan':
|
||||||
self.ACQUIRE_LOCK_TIMEOUT = 10
|
self.BOT_PREFIX = '!'
|
||||||
self.QUEUE_VIEW_TIMEOUT = 120
|
|
||||||
self.COMMANDS_FOLDER_NAME = 'DiscordCogs'
|
self.BOT_TOKEN = os.getenv('BOT_TOKEN')
|
||||||
|
if self.BOT_TOKEN is None:
|
||||||
|
raise ValueError('No token was given')
|
||||||
|
|
||||||
|
self.SPOTIFY_ID = os.getenv('SPOTIFY_ID')
|
||||||
|
self.SPOTIFY_SECRET = os.getenv('SPOTIFY_SECRET')
|
||||||
|
|
||||||
|
if self.SPOTIFY_ID == "Your_Own_Spotify_ID":
|
||||||
|
self.SPOTIFY_ID = None
|
||||||
|
|
||||||
|
if self.SPOTIFY_SECRET == "Your_Own_Spotify_Secret":
|
||||||
|
self.SPOTIFY_SECRET = None
|
||||||
|
|
||||||
|
if self.SPOTIFY_ID is None or self.SPOTIFY_SECRET is None:
|
||||||
|
print('Spotify will not work')
|
||||||
|
|
||||||
|
self.CLEANER_MESSAGES_QUANT = int(os.getenv('CLEANER_MESSAGES_QUANT', 5))
|
||||||
|
self.ACQUIRE_LOCK_TIMEOUT = int(os.getenv('ACQUIRE_LOCK_TIMEOUT', 10))
|
||||||
|
self.QUEUE_VIEW_TIMEOUT = int(os.getenv('QUEUE_VIEW_TIMEOUT', 120))
|
||||||
|
|
||||||
|
self.COMMANDS_FOLDER_NAME = os.getenv('COMMANDS_FOLDER_NAME', 'DiscordCogs')
|
||||||
self.COMMANDS_PATH = f'{Folder().rootFolder}{self.COMMANDS_FOLDER_NAME}'
|
self.COMMANDS_PATH = f'{Folder().rootFolder}{self.COMMANDS_FOLDER_NAME}'
|
||||||
self.VC_TIMEOUT = 300
|
self.VC_TIMEOUT = int(os.getenv('VC_TIMEOUT', 300))
|
||||||
|
|
||||||
self.CHANCE_SHOW_PROJECT = 15
|
self.CHANCE_SHOW_PROJECT = int(os.getenv('CHANCE_SHOW_PROJECT', 15))
|
||||||
self.PROJECT_URL = 'https://github.com/RafaelSolVargas/Vulkan'
|
self.PROJECT_URL = os.getenv('PROJECT_URL', 'https://github.com/RafaelSolVargas/Vulkan')
|
||||||
self.SUPPORTING_ICON = 'https://i.pinimg.com/originals/d6/05/b4/d605b4f8c5d1c6ae20dc353ef9f091bd.png'
|
self.SUPPORTING_ICON = os.getenv('SUPPORTING_ICON', 'https://i.pinimg.com/originals/d6/05/b4/d605b4f8c5d1c6ae20dc353ef9f091bd.png')
|
||||||
|
|
||||||
self.MAX_PLAYLIST_LENGTH = 50
|
self.MAX_PLAYLIST_LENGTH = int(os.getenv('MAX_PLAYLIST_LENGTH', 50))
|
||||||
self.MAX_PLAYLIST_FORCED_LENGTH = 5
|
self.MAX_PLAYLIST_FORCED_LENGTH = int(os.getenv('MAX_PLAYLIST_FORCED_LENGTH', 5))
|
||||||
self.MAX_SONGS_IN_PAGE = 10
|
self.MAX_SONGS_IN_PAGE = int(os.getenv('MAX_SONGS_IN_PAGE', 10))
|
||||||
self.MAX_PRELOAD_SONGS = 15
|
self.MAX_PRELOAD_SONGS = int(os.getenv('MAX_PRELOAD_SONGS', 15))
|
||||||
self.MAX_SONGS_HISTORY = 15
|
self.MAX_SONGS_HISTORY = int(os.getenv('MAX_SONGS_HISTORY', 15))
|
||||||
|
|
||||||
self.INVITE_MESSAGE = """To invite Vulkan to your own server, click [here]({}).
|
self.INVITE_MESSAGE = os.getenv('INVITE_MESSAGE', """To invite Vulkan to your own server, click [here]({}).
|
||||||
Or use this direct URL: {}"""
|
Or use this direct URL: {}""")
|
||||||
|
|
||||||
self.MY_ERROR_BAD_COMMAND = 'This string serves to verify if some error was raised by myself on purpose'
|
self.MY_ERROR_BAD_COMMAND = os.getenv('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 = os.getenv('INVITE_URL', 'https://discordapp.com/oauth2/authorize?client_id={}&permissions=8&scope=bot')
|
||||||
|
|
||||||
def getPlayersManager(self):
|
def getPlayersManager(self):
|
||||||
return self.__manager
|
return self.__manager
|
||||||
|
|||||||
@@ -343,6 +343,13 @@ class VEmbeds:
|
|||||||
description=self.__messages.PLAYER_NOT_PLAYING,
|
description=self.__messages.PLAYER_NOT_PLAYING,
|
||||||
colour=self.__colors.BLUE)
|
colour=self.__colors.BLUE)
|
||||||
return embed
|
return embed
|
||||||
|
|
||||||
|
def VOLUME_CHANGED(self, volume: float) -> Embed:
|
||||||
|
embed = Embed(
|
||||||
|
title=self.__messages.SONG_PLAYER,
|
||||||
|
description=self.__messages.VOLUME_CHANGED.format(volume),
|
||||||
|
colour=self.__colors.BLUE)
|
||||||
|
return embed
|
||||||
|
|
||||||
def QUEUE(self, title: str, description: str) -> Embed:
|
def QUEUE(self, title: str, description: str) -> Embed:
|
||||||
embed = Embed(
|
embed = Embed(
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ class Helper(Singleton):
|
|||||||
self.HELP_PREV_LONG = 'Play the previous song. If playing, the current song will return to queue.\n\nRequire: Loop to be disable.\nArguments: None.'
|
self.HELP_PREV_LONG = 'Play the previous song. If playing, the current song will return to queue.\n\nRequire: Loop to be disable.\nArguments: None.'
|
||||||
self.HELP_SHUFFLE = 'Shuffle the songs playing.'
|
self.HELP_SHUFFLE = 'Shuffle the songs playing.'
|
||||||
self.HELP_SHUFFLE_LONG = 'Randomly shuffle the songs in the queue.\n\nArguments: None.'
|
self.HELP_SHUFFLE_LONG = 'Randomly shuffle the songs in the queue.\n\nArguments: None.'
|
||||||
self.HELP_PLAY = 'Plays a song from URL'
|
self.HELP_PLAY = 'Plays a song from URL.'
|
||||||
|
self.CHANGE_VOLUME = 'Set the volume of the song.'
|
||||||
|
self.CHANGE_VOLUME_LONG = 'Change the volume of the song, expect a number from 0 to 100.'
|
||||||
self.HELP_PLAY_LONG = 'Play a song in discord. \n\nRequire: You to be connected to a voice channel.\nArguments: Youtube, Spotify or Deezer song/playlist link or the title of the song to be searched in Youtube.'
|
self.HELP_PLAY_LONG = 'Play a song in discord. \n\nRequire: You to be connected to a voice channel.\nArguments: Youtube, Spotify or Deezer song/playlist link or the title of the song to be searched in Youtube.'
|
||||||
self.HELP_HISTORY = f'Show the history of played songs.'
|
self.HELP_HISTORY = f'Show the history of played songs.'
|
||||||
self.HELP_HISTORY_LONG = f'Show the last {config.MAX_SONGS_HISTORY} played songs'
|
self.HELP_HISTORY_LONG = f'Show the last {config.MAX_SONGS_HISTORY} played songs'
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class Messages(Singleton):
|
|||||||
self.SONGINFO_REQUESTER = 'Requester: '
|
self.SONGINFO_REQUESTER = 'Requester: '
|
||||||
self.SONGINFO_POSITION = 'Position: '
|
self.SONGINFO_POSITION = 'Position: '
|
||||||
|
|
||||||
|
self.VOLUME_CHANGED = 'Song volume changed to `{}`%'
|
||||||
self.SONGS_ADDED = 'Downloading `{}` songs to add to the queue'
|
self.SONGS_ADDED = 'Downloading `{}` songs to add to the queue'
|
||||||
self.SONG_ADDED = 'Downloading the song `{}` to add to the queue'
|
self.SONG_ADDED = 'Downloading the song `{}` to add to the queue'
|
||||||
self.SONG_ADDED_TWO = f'{self.__emojis.MUSIC} Song added to the queue'
|
self.SONG_ADDED_TWO = f'{self.__emojis.MUSIC} Song added to the queue'
|
||||||
@@ -56,6 +57,7 @@ class Messages(Singleton):
|
|||||||
self.ERROR_MOVING = f'{self.__emojis.ERROR} Error while moving the songs'
|
self.ERROR_MOVING = f'{self.__emojis.ERROR} Error while moving the songs'
|
||||||
self.LENGTH_ERROR = f'{self.__emojis.ERROR} Numbers must be between 1 and queue length, use -1 for the last song'
|
self.LENGTH_ERROR = f'{self.__emojis.ERROR} Numbers must be between 1 and queue length, use -1 for the last song'
|
||||||
self.ERROR_NUMBER = f'{self.__emojis.ERROR} This command require a number'
|
self.ERROR_NUMBER = f'{self.__emojis.ERROR} This command require a number'
|
||||||
|
self.ERROR_VOLUME_NUMBER = f'{self.__emojis.ERROR} This command require a number between 0 and 100'
|
||||||
self.ERROR_PLAYING = f'{self.__emojis.ERROR} Error while playing songs'
|
self.ERROR_PLAYING = f'{self.__emojis.ERROR} Error while playing songs'
|
||||||
self.COMMAND_NOT_FOUND = f'{self.__emojis.ERROR} Command not found, type {configs.BOT_PREFIX}help to see all commands'
|
self.COMMAND_NOT_FOUND = f'{self.__emojis.ERROR} Command not found, type {configs.BOT_PREFIX}help to see all commands'
|
||||||
self.UNKNOWN_ERROR = f'{self.__emojis.ERROR} Unknown Error, if needed, use {configs.BOT_PREFIX}reset to reset the player of your server'
|
self.UNKNOWN_ERROR = f'{self.__emojis.ERROR} Unknown Error, if needed, use {configs.BOT_PREFIX}reset to reset the player of your server'
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class ControlCog(Cog):
|
|||||||
'MUSIC': ['resume', 'pause', 'loop', 'stop',
|
'MUSIC': ['resume', 'pause', 'loop', 'stop',
|
||||||
'skip', 'play', 'queue', 'clear',
|
'skip', 'play', 'queue', 'clear',
|
||||||
'np', 'shuffle', 'move', 'remove',
|
'np', 'shuffle', 'move', 'remove',
|
||||||
'reset', 'prev', 'history'],
|
'reset', 'prev', 'history', 'volume'],
|
||||||
'RANDOM': ['choose', 'cara', 'random']
|
'RANDOM': ['choose', 'cara', 'random']
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ from Handlers.ResumeHandler import ResumeHandler
|
|||||||
from Handlers.HistoryHandler import HistoryHandler
|
from Handlers.HistoryHandler import HistoryHandler
|
||||||
from Handlers.QueueHandler import QueueHandler
|
from Handlers.QueueHandler import QueueHandler
|
||||||
from Handlers.LoopHandler import LoopHandler
|
from Handlers.LoopHandler import LoopHandler
|
||||||
|
from Handlers.VolumeHandler import VolumeHandler
|
||||||
from Messages.MessagesCategory import MessagesCategory
|
from Messages.MessagesCategory import MessagesCategory
|
||||||
from Messages.Responses.EmoteCogResponse import EmoteCommandResponse
|
from Messages.Responses.EmoteCogResponse import EmoteCommandResponse
|
||||||
from Messages.Responses.EmbedCogResponse import EmbedCommandResponse
|
from Messages.Responses.EmbedCogResponse import EmbedCommandResponse
|
||||||
@@ -64,6 +65,25 @@ class MusicCog(Cog):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'[ERROR IN COG] -> {e}')
|
print(f'[ERROR IN COG] -> {e}')
|
||||||
|
|
||||||
|
@command(name="volume", help=helper.CHANGE_VOLUME, description=helper.CHANGE_VOLUME_LONG, aliases=['v'])
|
||||||
|
async def volume(self, ctx: Context, *args) -> None:
|
||||||
|
try:
|
||||||
|
controller = VolumeHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
if len(args) > 1:
|
||||||
|
track = " ".join(args)
|
||||||
|
else:
|
||||||
|
track = args[0]
|
||||||
|
|
||||||
|
response = await controller.run(track)
|
||||||
|
if response is not None:
|
||||||
|
cogResponser1 = EmbedCommandResponse(response, MessagesCategory.PLAYER)
|
||||||
|
cogResponser2 = EmoteCommandResponse(response, MessagesCategory.PLAYER)
|
||||||
|
await cogResponser1.run()
|
||||||
|
await cogResponser2.run()
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[ERROR IN COG] -> {e}')
|
||||||
|
|
||||||
@command(name="queue", help=helper.HELP_QUEUE, description=helper.HELP_QUEUE_LONG, aliases=['q', 'fila', 'musicas'])
|
@command(name="queue", help=helper.HELP_QUEUE, description=helper.HELP_QUEUE_LONG, aliases=['q', 'fila', 'musicas'])
|
||||||
async def queue(self, ctx: Context, *args) -> None:
|
async def queue(self, ctx: Context, *args) -> None:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from Handlers.ResumeHandler import ResumeHandler
|
|||||||
from Handlers.HistoryHandler import HistoryHandler
|
from Handlers.HistoryHandler import HistoryHandler
|
||||||
from Handlers.QueueHandler import QueueHandler
|
from Handlers.QueueHandler import QueueHandler
|
||||||
from Handlers.LoopHandler import LoopHandler
|
from Handlers.LoopHandler import LoopHandler
|
||||||
|
from Handlers.VolumeHandler import VolumeHandler
|
||||||
from Messages.MessagesCategory import MessagesCategory
|
from Messages.MessagesCategory import MessagesCategory
|
||||||
from Messages.Responses.SlashEmbedResponse import SlashEmbedResponse
|
from Messages.Responses.SlashEmbedResponse import SlashEmbedResponse
|
||||||
from Music.VulkanBot import VulkanBot
|
from Music.VulkanBot import VulkanBot
|
||||||
@@ -237,6 +238,22 @@ class SlashCommands(Cog):
|
|||||||
except Exception:
|
except Exception:
|
||||||
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
|
@slash_command(name='volume', description=helper.CHANGE_VOLUME_LONG)
|
||||||
|
async def move(self, ctx: ApplicationContext,
|
||||||
|
volume: Option(float, "The new volume of the song", min_value=1, default= 100)) -> None:
|
||||||
|
if not self.__bot.listingSlash:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await ctx.defer()
|
||||||
|
|
||||||
|
controller = VolumeHandler(ctx, self.__bot)
|
||||||
|
|
||||||
|
response = await controller.run(f'{volume}')
|
||||||
|
cogResponser = SlashEmbedResponse(response, ctx, MessagesCategory.PLAYER)
|
||||||
|
await cogResponser.run()
|
||||||
|
except Exception:
|
||||||
|
print(f'[ERROR IN SLASH COMMAND] -> {traceback.format_exc()}')
|
||||||
|
|
||||||
@slash_command(name='remove', description=helper.HELP_REMOVE)
|
@slash_command(name='remove', description=helper.HELP_REMOVE)
|
||||||
async def remove(self, ctx: ApplicationContext,
|
async def remove(self, ctx: ApplicationContext,
|
||||||
position: Option(int, "The song position to remove", min_value=1)) -> None:
|
position: Option(int, "The song position to remove", min_value=1)) -> None:
|
||||||
|
|||||||
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
FROM python:3.10.0
|
||||||
|
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
RUN git clone https://github.com/RafaelSolVargas/Vulkan.git /app
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
RUN apt-get update && apt-get install -y software-properties-common && apt-get install -y ffmpeg
|
||||||
|
RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
|
||||||
|
USER appuser
|
||||||
|
CMD ["python", "main.py"]
|
||||||
62
Handlers/VolumeHandler.py
Normal file
62
Handlers/VolumeHandler.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
from Config.Exceptions import BadCommandUsage, NumberRequired, VulkanError
|
||||||
|
from Parallelism.AbstractProcessManager import AbstractPlayersManager
|
||||||
|
from Parallelism.Commands import VCommands, VCommandsType
|
||||||
|
from Handlers.AbstractHandler import AbstractHandler
|
||||||
|
from Handlers.HandlerResponse import HandlerResponse
|
||||||
|
from discord.ext.commands import Context
|
||||||
|
from Music.VulkanBot import VulkanBot
|
||||||
|
from discord import Interaction
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
|
class VolumeHandler(AbstractHandler):
|
||||||
|
def __init__(self, ctx: Union[Context, Interaction], bot: VulkanBot) -> None:
|
||||||
|
super().__init__(ctx, bot)
|
||||||
|
|
||||||
|
async def run(self, args: str) -> HandlerResponse:
|
||||||
|
if args is None or args.strip() == '':
|
||||||
|
error = BadCommandUsage()
|
||||||
|
return HandlerResponse(self.ctx, embed, error)
|
||||||
|
|
||||||
|
error = self.__validateInput(args)
|
||||||
|
if error:
|
||||||
|
embed = self.embeds.ERROR_EMBED(error.message)
|
||||||
|
return HandlerResponse(self.ctx, embed, error)
|
||||||
|
|
||||||
|
playersManager: AbstractPlayersManager = self.config.getPlayersManager()
|
||||||
|
if not playersManager.verifyIfPlayerExists(self.guild):
|
||||||
|
embed = self.embeds.NOT_PLAYING()
|
||||||
|
error = BadCommandUsage()
|
||||||
|
return HandlerResponse(self.ctx, embed, error)
|
||||||
|
|
||||||
|
playerLock = playersManager.getPlayerLock(self.guild)
|
||||||
|
acquired = playerLock.acquire(timeout=self.config.ACQUIRE_LOCK_TIMEOUT)
|
||||||
|
volume = self.__convert_input_to_volume(args)
|
||||||
|
if acquired:
|
||||||
|
volumeCommand = VCommands(VCommandsType.VOLUME, volume)
|
||||||
|
await playersManager.sendCommandToPlayer(volumeCommand, self.guild, self.ctx)
|
||||||
|
|
||||||
|
playerLock.release()
|
||||||
|
|
||||||
|
embed = self.embeds.VOLUME_CHANGED(volume)
|
||||||
|
return HandlerResponse(self.ctx, embed)
|
||||||
|
else:
|
||||||
|
playersManager.resetPlayer(self.guild, self.ctx)
|
||||||
|
|
||||||
|
embed = self.embeds.PLAYER_RESTARTED()
|
||||||
|
return HandlerResponse(self.ctx, embed)
|
||||||
|
|
||||||
|
def __convert_input_to_volume(self, input_volume: str) -> float:
|
||||||
|
volume = float(input_volume)
|
||||||
|
if volume < 0:
|
||||||
|
volume = 0
|
||||||
|
if volume > 100:
|
||||||
|
volume = 100
|
||||||
|
|
||||||
|
return volume
|
||||||
|
|
||||||
|
def __validateInput(self, volume: str) -> Union[VulkanError, None]:
|
||||||
|
try:
|
||||||
|
_ = float(volume)
|
||||||
|
except:
|
||||||
|
return NumberRequired(self.messages.ERROR_VOLUME_NUMBER)
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
from Config.Exceptions import DeezerError, InvalidInput, SpotifyError, VulkanError, YoutubeError
|
from Config.Exceptions import DeezerError, InvalidInput, SpotifyError, VulkanError, YoutubeError
|
||||||
from Music.Downloader import Downloader
|
|
||||||
from Music.Types import Provider
|
|
||||||
from Music.SpotifySearcher import SpotifySearch
|
from Music.SpotifySearcher import SpotifySearch
|
||||||
from Music.DeezerSearcher import DeezerSearcher
|
from Music.DeezerSearcher import DeezerSearcher
|
||||||
from Utils.Utils import Utils
|
|
||||||
from Utils.UrlAnalyzer import URLAnalyzer
|
from Utils.UrlAnalyzer import URLAnalyzer
|
||||||
from Config.Messages import SearchMessages
|
from Config.Messages import SearchMessages
|
||||||
|
from Music.Downloader import Downloader
|
||||||
|
from Music.Types import Provider
|
||||||
|
from Utils.Utils import Utils
|
||||||
|
|
||||||
|
|
||||||
class Searcher():
|
class Searcher:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.__spotify = SpotifySearch()
|
self.__spotify = SpotifySearch()
|
||||||
self.__deezer = DeezerSearcher()
|
self.__deezer = DeezerSearcher()
|
||||||
@@ -35,8 +35,7 @@ class Searcher():
|
|||||||
try:
|
try:
|
||||||
musics = self.__spotify.search(track)
|
musics = self.__spotify.search(track)
|
||||||
if musics == None or len(musics) == 0:
|
if musics == None or len(musics) == 0:
|
||||||
raise SpotifyError(self.__messages.SPOTIFY_NOT_FOUND,
|
raise SpotifyError(self.__messages.SPOTIFY_NOT_FOUND, self.__messages.GENERIC_TITLE)
|
||||||
self.__messages.GENERIC_TITLE)
|
|
||||||
|
|
||||||
return musics
|
return musics
|
||||||
except SpotifyError as error:
|
except SpotifyError as error:
|
||||||
@@ -79,7 +78,7 @@ class Searcher():
|
|||||||
if not Utils.is_url(track):
|
if not Utils.is_url(track):
|
||||||
return Provider.Name
|
return Provider.Name
|
||||||
|
|
||||||
if "https://www.youtu" in track or "https://youtu.be" in track or "https://music.youtube" in track:
|
if "https://www.youtu" in track or "https://youtu.be" in track or "https://music.youtube" in track or "m.youtube" in track:
|
||||||
return Provider.YouTube
|
return Provider.YouTube
|
||||||
|
|
||||||
if "https://open.spotify.com" in track:
|
if "https://open.spotify.com" in track:
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ class VCommandsType(Enum):
|
|||||||
RESET = 'Reset'
|
RESET = 'Reset'
|
||||||
NOW_PLAYING = 'Now Playing'
|
NOW_PLAYING = 'Now Playing'
|
||||||
TERMINATE = 'Terminate'
|
TERMINATE = 'Terminate'
|
||||||
|
VOLUME = 'Volume'
|
||||||
SLEEPING = 'Sleeping'
|
SLEEPING = 'Sleeping'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ 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 VoiceClient
|
from discord import PCMVolumeTransformer, 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
|
||||||
@@ -54,6 +54,9 @@ class ProcessPlayer(Process):
|
|||||||
self.__voiceChannel: VoiceChannel = None
|
self.__voiceChannel: VoiceChannel = None
|
||||||
self.__voiceClient: VoiceClient = None
|
self.__voiceClient: VoiceClient = None
|
||||||
|
|
||||||
|
self.__songVolumeUsing = 1
|
||||||
|
self.__currentSongChangeVolume = False
|
||||||
|
|
||||||
self.__playing = False
|
self.__playing = False
|
||||||
self.__forceStop = False
|
self.__forceStop = False
|
||||||
self.__botCompletedLoad = False
|
self.__botCompletedLoad = False
|
||||||
@@ -98,6 +101,32 @@ class ProcessPlayer(Process):
|
|||||||
# In this point the process should finalize
|
# In this point the process should finalize
|
||||||
self.__timer.cancel()
|
self.__timer.cancel()
|
||||||
|
|
||||||
|
def __set_volume(self, volume: float) -> None:
|
||||||
|
"""Set the volume of the player, must be values between 0 and 100"""
|
||||||
|
try:
|
||||||
|
if self.__voiceClient is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not isinstance(volume, float):
|
||||||
|
print('[PROCESS ERROR] -> Volume instance must be float')
|
||||||
|
return
|
||||||
|
|
||||||
|
if volume < 0:
|
||||||
|
volume = 0
|
||||||
|
if volume > 100:
|
||||||
|
volume = 100
|
||||||
|
|
||||||
|
volume = volume / 100
|
||||||
|
|
||||||
|
if not self.__currentSongChangeVolume:
|
||||||
|
print('[PROCESS ERROR] -> Cannot change the volume of this song')
|
||||||
|
return
|
||||||
|
|
||||||
|
self.__songVolumeUsing = volume
|
||||||
|
self.__voiceClient.source.volume = volume
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
def __verifyIfIsPlaying(self) -> bool:
|
def __verifyIfIsPlaying(self) -> bool:
|
||||||
if self.__voiceClient is None:
|
if self.__voiceClient is None:
|
||||||
return False
|
return False
|
||||||
@@ -151,6 +180,10 @@ class ProcessPlayer(Process):
|
|||||||
self.__songPlaying = song
|
self.__songPlaying = song
|
||||||
|
|
||||||
player = FFmpegPCMAudio(song.source, **self.FFMPEG_OPTIONS)
|
player = FFmpegPCMAudio(song.source, **self.FFMPEG_OPTIONS)
|
||||||
|
if not player.is_opus():
|
||||||
|
player = PCMVolumeTransformer(player, self.__songVolumeUsing)
|
||||||
|
self.__currentSongChangeVolume = True
|
||||||
|
|
||||||
self.__voiceClient.play(player, after=lambda e: self.__playNext(e))
|
self.__voiceClient.play(player, after=lambda e: self.__playNext(e))
|
||||||
|
|
||||||
self.__timer.cancel()
|
self.__timer.cancel()
|
||||||
@@ -169,6 +202,8 @@ class ProcessPlayer(Process):
|
|||||||
print(f'[PROCESS PLAYER -> ERROR PLAYING SONG] -> {error}')
|
print(f'[PROCESS PLAYER -> ERROR PLAYING SONG] -> {error}')
|
||||||
with self.__playlistLock:
|
with self.__playlistLock:
|
||||||
with self.__playerLock:
|
with self.__playerLock:
|
||||||
|
self.__currentSongChangeVolume = False
|
||||||
|
|
||||||
if self.__forceStop: # If it's forced to stop player
|
if self.__forceStop: # If it's forced to stop player
|
||||||
self.__forceStop = False
|
self.__forceStop = False
|
||||||
return None
|
return None
|
||||||
@@ -271,6 +306,8 @@ class ProcessPlayer(Process):
|
|||||||
asyncio.run_coroutine_threadsafe(self.__reset(), self.__loop)
|
asyncio.run_coroutine_threadsafe(self.__reset(), self.__loop)
|
||||||
elif type == VCommandsType.STOP:
|
elif type == VCommandsType.STOP:
|
||||||
asyncio.run_coroutine_threadsafe(self.__stop(), self.__loop)
|
asyncio.run_coroutine_threadsafe(self.__stop(), self.__loop)
|
||||||
|
elif type == VCommandsType.VOLUME:
|
||||||
|
self.__set_volume(args)
|
||||||
else:
|
else:
|
||||||
print(f'[PROCESS PLAYER ERROR] -> Unknown Command Received: {command}')
|
print(f'[PROCESS PLAYER ERROR] -> Unknown Command Received: {command}')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
from time import time
|
from time import time
|
||||||
from urllib.parse import parse_qs, urlparse
|
from urllib.parse import parse_qs, urlparse
|
||||||
from discord import VoiceClient
|
from discord import PCMVolumeTransformer, VoiceClient
|
||||||
from asyncio import AbstractEventLoop
|
from asyncio import AbstractEventLoop
|
||||||
from threading import RLock, Thread
|
from threading import RLock, Thread
|
||||||
from multiprocessing import Lock
|
from multiprocessing import Lock
|
||||||
@@ -45,6 +45,9 @@ class ThreadPlayer(Thread):
|
|||||||
self.__voiceChannel: VoiceChannel = voiceChannel
|
self.__voiceChannel: VoiceChannel = voiceChannel
|
||||||
self.__voiceClient: VoiceClient = None
|
self.__voiceClient: VoiceClient = None
|
||||||
|
|
||||||
|
self.__currentSongChangeVolume = False
|
||||||
|
self.__songVolumeUsing = 1
|
||||||
|
|
||||||
self.__downloader = Downloader()
|
self.__downloader = Downloader()
|
||||||
self.__callback = callbackToSendCommand
|
self.__callback = callbackToSendCommand
|
||||||
self.__exitCB = exitCB
|
self.__exitCB = exitCB
|
||||||
@@ -56,6 +59,32 @@ class ThreadPlayer(Thread):
|
|||||||
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',
|
||||||
'options': '-vn'}
|
'options': '-vn'}
|
||||||
|
|
||||||
|
def __set_volume(self, volume: float) -> None:
|
||||||
|
"""Set the volume of the player, must be values between 0 and 100"""
|
||||||
|
try:
|
||||||
|
if self.__voiceClient is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not isinstance(volume, float):
|
||||||
|
print('[THREAD ERROR] -> Volume instance must be float')
|
||||||
|
return
|
||||||
|
|
||||||
|
if volume < 0:
|
||||||
|
volume = 0
|
||||||
|
if volume > 100:
|
||||||
|
volume = 100
|
||||||
|
|
||||||
|
volume = volume / 100
|
||||||
|
|
||||||
|
if not self.__currentSongChangeVolume:
|
||||||
|
print('[THREAD ERROR] -> Cannot change the volume of this song')
|
||||||
|
return
|
||||||
|
|
||||||
|
self.__songVolumeUsing = volume
|
||||||
|
self.__voiceClient.source.volume = volume
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
def __verifyIfIsPlaying(self) -> bool:
|
def __verifyIfIsPlaying(self) -> bool:
|
||||||
if self.__voiceClient is None:
|
if self.__voiceClient is None:
|
||||||
return False
|
return False
|
||||||
@@ -109,6 +138,9 @@ class ThreadPlayer(Thread):
|
|||||||
self.__songPlaying = song
|
self.__songPlaying = song
|
||||||
|
|
||||||
player = FFmpegPCMAudio(song.source, **self.FFMPEG_OPTIONS)
|
player = FFmpegPCMAudio(song.source, **self.FFMPEG_OPTIONS)
|
||||||
|
if not player.is_opus():
|
||||||
|
player = PCMVolumeTransformer(player, self.__songVolumeUsing)
|
||||||
|
self.__currentSongChangeVolume = True
|
||||||
self.__voiceClient.play(player, after=lambda e: self.__playNext(e))
|
self.__voiceClient.play(player, after=lambda e: self.__playNext(e))
|
||||||
|
|
||||||
self.__timer.cancel()
|
self.__timer.cancel()
|
||||||
@@ -127,6 +159,7 @@ class ThreadPlayer(Thread):
|
|||||||
print(f'[THREAD PLAYER -> ERROR PLAYING SONG] -> {error}')
|
print(f'[THREAD PLAYER -> ERROR PLAYING SONG] -> {error}')
|
||||||
with self.__playlistLock:
|
with self.__playlistLock:
|
||||||
with self.__playerLock:
|
with self.__playerLock:
|
||||||
|
self.__currentSongChangeVolume = False
|
||||||
if self.__forceStop: # If it's forced to stop player
|
if self.__forceStop: # If it's forced to stop player
|
||||||
self.__forceStop = False
|
self.__forceStop = False
|
||||||
return None
|
return None
|
||||||
@@ -217,6 +250,8 @@ class ThreadPlayer(Thread):
|
|||||||
await self.__reset()
|
await self.__reset()
|
||||||
elif type == VCommandsType.STOP:
|
elif type == VCommandsType.STOP:
|
||||||
await self.__stop()
|
await self.__stop()
|
||||||
|
elif type == VCommandsType.VOLUME:
|
||||||
|
self.__set_volume(args)
|
||||||
else:
|
else:
|
||||||
print(f'[THREAD PLAYER ERROR] -> Unknown Command Received: {command}')
|
print(f'[THREAD PLAYER ERROR] -> Unknown Command Received: {command}')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
11
README.md
11
README.md
@@ -18,6 +18,7 @@ Vulkan uses multiprocessing and asynchronous Python modules to maximize Music Pl
|
|||||||
- Support for the new Discord Slash commands.
|
- Support for the new Discord Slash commands.
|
||||||
- Search for all musics in Queue using buttons.
|
- Search for all musics in Queue using buttons.
|
||||||
- Shortcut the playing of one song using dropdown menu.
|
- Shortcut the playing of one song using dropdown menu.
|
||||||
|
- Manage the volume of the songs.
|
||||||
- Manage the loop of one or all playing musics.
|
- Manage the loop of one or all playing musics.
|
||||||
- Manage the order and remove musics from the queue.
|
- Manage the order and remove musics from the queue.
|
||||||
- Shuffle the musics queue order.
|
- Shuffle the musics queue order.
|
||||||
@@ -62,16 +63,17 @@ You can download the executables in this link `https://www.ffmpeg.org/download.h
|
|||||||
|
|
||||||
### **.Env File Example**
|
### **.Env File Example**
|
||||||
This is an example of how your .env file (located in root) should look like.
|
This is an example of how your .env file (located in root) should look like.
|
||||||
```
|
```env
|
||||||
BOT_TOKEN=Your_Own_Bot_Token
|
BOT_TOKEN=Your_Own_Bot_Token
|
||||||
SPOTIFY_ID=Your_Own_Spotify_ID
|
SPOTIFY_ID=Your_Own_Spotify_ID
|
||||||
SPOTIFY_SECRET=Your_Own_Spotify_Secret
|
SPOTIFY_SECRET=Your_Own_Spotify_Secret
|
||||||
BOT_PREFIX=Your_Wanted_Prefix_For_Vulkan
|
BOT_PREFIX=Your_Wanted_Prefix_For_Vulkan
|
||||||
|
SHOULD_AUTO_DISCONNECT_WHEN_ALONE=True #all settings can be set like this
|
||||||
|
#etc... All settings can be set this way
|
||||||
```
|
```
|
||||||
|
|
||||||
### **⚙️ Configs**
|
### **⚙️ Configs**
|
||||||
The config file is located at ```./config/Configs.py```, it doesn't require any change, but if you can change the values to the way you want. <br>
|
The bot's configuration is stored in the [.env](.env) file, you can change the prefix and the bot token there, as well as all the other configurations.
|
||||||
Take a look in the [Settings page](.github/Docs/SETTINGS.md) to personalize the Bot for you.
|
Take a look in the [Settings page](.github/Docs/SETTINGS.md) to personalize the Bot for you.
|
||||||
|
|
||||||
|
|
||||||
@@ -80,6 +82,9 @@ Take a look in the [Settings page](.github/Docs/SETTINGS.md) to personalize the
|
|||||||
- Run ```python main.py``` in console to start
|
- Run ```python main.py``` in console to start
|
||||||
- Give this project a nice 🌟
|
- Give this project a nice 🌟
|
||||||
|
|
||||||
|
### **🐳 Docker**
|
||||||
|
You can also run this project in a Docker container. You can find the instructions to run this project in a Docker container in the [Docker Instructions](.github/Docs/DOCKER.md) page.
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<hr>
|
<hr>
|
||||||
|
|||||||
8
docker-compose.yaml
Normal file
8
docker-compose.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
vulkan:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
Reference in New Issue
Block a user