diff --git a/.env Example b/.env Example index 93877a1..58a944f 100644 --- a/.env Example +++ b/.env Example @@ -1,7 +1,6 @@ TOKEN = YOUR_BOT_TOKEN CLIENT_ID = YOUR_BOT_CLIENT_ID CLIENT_SECRET_ID = YOUR_BOT_CLIENT_SECRET_ID -SECRET_KEY = DASHBOARD_SECRET_KEY BUG_REPORT_CHANNEL_ID = YOUR_DISCORD_CHANNEL_ID @@ -12,3 +11,8 @@ GENIUS_TOKEN = YOUR_GENIUS_TOKEN MONGODB_URL = YOUR_MONGODB_URL MONGODB_NAME = YOUR_MONGODB_DB_NAME + +DASHBOARD_HOST = 0.0.0.0 +DASHBOARD_PORT = 5555 +DASHBOARD_SERCET_KEY = DASHBOARD_SECRET_KEY +DASHBOARD_SECURE = False \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8c2cfa7..51c14c6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ Vocard.rar .env *.pyc -settings.json \ No newline at end of file +settings.json +logs \ No newline at end of file diff --git a/.replit b/.replit deleted file mode 100644 index d56db40..0000000 --- a/.replit +++ /dev/null @@ -1,89 +0,0 @@ -run = "python3 main.py" - -# The primary language of the repl. There can be others, though! -language = "python3" -# A list of globs that specify which files and directories should -# be hidden in the workspace. -hidden = ["venv", ".config", "**/__pycache__", "**/.mypy_cache", "**/*.pyc"] - -# Specifies which nix channel to use when building the environment. -[nix] -channel = "stable-22_11" - -[env] -VIRTUAL_ENV = "/home/runner/${REPL_SLUG}/venv" -PATH = "${VIRTUAL_ENV}/bin" -PYTHONPATH = "${VIRTUAL_ENV}/lib/python3.10/site-packages" -REPLIT_POETRY_PYPI_REPOSITORY = "https://package-proxy.replit.com/pypi/" -MPLBACKEND = "TkAgg" -POETRY_CACHE_DIR = "${HOME}/${REPL_SLUG}/.cache/pypoetry" - -# Enable unit tests. This is only supported for a few languages. -[unitTest] -language = "python3" - -# Add a debugger! -[debugger] -support = true - - # How to start the debugger. - [debugger.interactive] - transport = "localhost:0" - startCommand = ["dap-python", "main.py"] - - # How to communicate with the debugger. - [debugger.interactive.integratedAdapter] - dapTcpAddress = "localhost:0" - - # How to tell the debugger to start a debugging session. - [debugger.interactive.initializeMessage] - command = "initialize" - type = "request" - - [debugger.interactive.initializeMessage.arguments] - adapterID = "debugpy" - clientID = "replit" - clientName = "replit.com" - columnsStartAt1 = true - linesStartAt1 = true - locale = "en-us" - pathFormat = "path" - supportsInvalidatedEvent = true - supportsProgressReporting = true - supportsRunInTerminalRequest = true - supportsVariablePaging = true - supportsVariableType = true - - # How to tell the debugger to start the debuggee application. - [debugger.interactive.launchMessage] - command = "attach" - type = "request" - - [debugger.interactive.launchMessage.arguments] - logging = {} - -# Configures the packager. -[packager] -language = "python3" -ignoredPackages = ["unit_tests"] - - [packager.features] - enabledForHosting = false - # Enable searching packages from the sidebar. - packageSearch = true - # Enable guessing what packages are needed from the code. - guessImports = true - -# These are the files that need to be preserved when this -# language template is used as the base language template -# for Python repos imported from GitHub -[gitHubImport] -requiredFiles = [".replit", "replit.nix", ".config", "venv"] - -[languages] - -[languages.python3] -pattern = "**/*.py" - -[languages.python3.languageServer] -start = "pylsp" diff --git a/Dockerfile b/Dockerfile index 37223ce..d500667 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ # Use an official Python runtime as a base image FROM python:3.12-slim -# Install build dependencies -RUN apt-get update -y && apt-get install -y gcc python3-dev +# Install build dependencies and supervisor +RUN apt-get update -y && apt-get install -y gcc python3-dev supervisor # Set the working directory to /app WORKDIR /app @@ -13,5 +13,8 @@ COPY . /app # Install any needed packages specified in requirements.txt RUN pip install --no-cache-dir -r requirements.txt -# Run main.py when the container launches -CMD ["python", "-u", "main.py"] +# Copy the supervisor configuration file +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf + +# Run supervisor to manage both processes main.py and webapp.py +CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] \ No newline at end of file diff --git a/README.md b/README.md index efdec99..4d76fcc 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,8 @@ Click on the image below to watch the tutorial on Youtube. -## Run the Projects -[![Run on Repl.it](https://replit.com/badge/github/ChocoMeow/Vocard)](https://replit.com/new/github/ChocoMeow/Vocard) - ## Requirements * [Python 3.10+](https://www.python.org/downloads/) -* [Modules in requirements](https://github.com/ChocoMeow/Vocard/blob/main/requirements.txt) * [Lavalink Server (Requires 4.0.0+)](https://github.com/freyacodes/Lavalink) ## Quick Start @@ -42,161 +38,13 @@ git clone https://github.com/ChocoMeow/Vocard.git #Clone the repository cd Vocard #Go to the directory python -m pip install -r requirements.txt #Install required packages ``` -After installing all packages, you must configure the bot before to start! [How To Configure](https://github.com/ChocoMeow/Vocard#configuration)
+After installing all packages, you must configure the bot before to start! [How To Configure](https://docs.vocard.xyz/configuration/)
Start your bot with `python main.py` ## Configuration -1. **Rename `.env Example` to `.env` and fill all the values** -```sh -TOKEN = XXXXXXXXXXXXXXXXXXXXXXXX.XXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXX -CLIENT_ID = 123456789012345678 -CLIENT_SECRET_ID = XXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXX -SECRET_KEY = DASHBOARD_SECRET_KEY - -BUG_REPORT_CHANNEL_ID = 123456789012345678 - -SPOTIFY_CLIENT_ID = 0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -SPOTIFY_CLIENT_SECRET = 0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - -GENIUS_TOKEN = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - -MONGODB_URL = mongodb+srv://user:password@clusterURL -MONGODB_NAME = Vocard -``` -| Values | Description | -| --- | --- | -| TOKEN | Your Discord bot token [(Discord Portal)](https://discord.com/developers/applications) | -| CLIENT_ID | Your Discord bot client id [(Discord Portal)](https://discord.com/developers/applications) | -| CLIENT_SECRET_ID | Your Discord bot client secret id [(Discord Portal)](https://discord.com/developers/applications) ***(optional)*** | -| SECRET_KEY | Secret key for dashboard ***(optional)*** | -| BUG_REPORT_CHANNEL_ID | All the error messages will send to this text channel ***(optional)*** | -| SPOTIFY_CLIENT_ID | Your Spoity client id [(Spotify Portal)](https://developer.spotify.com/dashboard/applications) ***(optional)*** | -| SPOTIFY_CLIENT_SECRET | Your Spoity client sercret id [(Spotify Portal)](https://developer.spotify.com/dashboard/applications) ***(optional)*** | -| GENIUS_TOKEN | Your genius api key [(Genius Lyrics API)](https://genius.com/api-clients) ***(optional)*** | -| MONGODB_URL | Your Mongo datebase url [(Mongodb)](https://www.mongodb.com/) | -| MONGODB_NAME | The datebase name that you created on [Mongodb](https://www.mongodb.com/) | - -2. **Rename `settings Example.json` to `settings.json` and customize your settings** -***(Note: Do not change any keys from `settings.json`)*** -```json -{ - "nodes": { - "DEFAULT": { - "host": "127.0.0.1", - "port": 2333, - "password": "password", - "secure": false, - "identifier": "DEFAULT" - } - }, - "prefix": "?", - "activity":[ - {"listen": "/help"} - ], - "bot_access_user": [], - "embed_color":"0xb3b3b3", - "default_max_queue": 1000, - "lyrics_platform": "A_ZLyrics", - "ipc_server": { - "host": "127.0.0.1", - "port": 8000, - "enable": false - }, - "sources_settings": { - "youtube": { - "emoji": "<:youtube:826661982760992778>", - "color": "0xFF0000" - }, - "youtube music": { - "emoji": "<:youtube:826661982760992778>", - "color": "0xFF0000" - }, - "spotify": { - "emoji": "<:spotify:826661996615172146>", - "color": "0x1DB954" - }, - "soundcloud": { - "emoji": "<:soundcloud:852729280027033632>", - "color": "0xFF7700" - }, - "twitch": { - "emoji": "<:twitch:852729278285086741>", - "color": "0x9B4AFF" - }, - "bandcamp": { - "emoji": "<:bandcamp:864694003811221526>", - "color": "0x6F98A7" - }, - "vimeo": { - "emoji": "<:vimeo:864694001919721473>", - "color": "0x1ABCEA" - }, - "apple": { - "emoji": "<:applemusic:994844332374884413>", - "color": "0xE298C4" - }, - "reddit": { - "emoji": "<:reddit:996007566863773717>", - "color": "0xFF5700" - }, - "tiktok": { - "emoji": "<:tiktok:996007689798811698>", - "color": "0x74ECE9" - } - }, - "default_controller": { - "embeds": { - "active": { - "description": "**Now Playing: ```[@@track_name@@]```\nLink: [Click Me](@@track_url@@) | Requester: @@requester@@ | DJ: @@dj@@**", - "footer": { - "text": "Queue Length: @@queue_length@@ | Duration: @@track_duration@@ | Volume: @@volume@@% {{loop_mode != 'Off' ?? | Repeat: @@loop_mode@@}}" - }, - "image": "@@track_thumbnail@@", - "author": { - "name": "Music Controller | @@channel_name@@", - "icon_url": "@@bot_icon@@" - }, - "color": "@@track_color@@" - }, - "inactive": { - "header": { - "title": "There are no songs playing right now" - }, - "description": "[Support](@@server_invite_link@@) | [Invite](@@invite_link@@) | [Questionnaire](https://forms.gle/Qm8vjBfg2kp13YGD7)", - "image": "https://i.imgur.com/dIFBwU7.png", - "color": "@@default_embed_color@@" - } - }, - "default_buttons": [ - ["back", "resume", "skip", {"stop": "red"}, "add"], - ["tracks"] - ], - "disableButtonText": false - }, - "cooldowns": { - "connect": [2, 30], - "playlist view": [1, 30] - }, - "aliases": { - "connect": ["join"], - "leave": ["stop", "bye"], - "play": ["p"], - "view": ["v"] - } -} -``` -* For `nodes` you have to provide host, port, password and identifier of the [Lavalink Server](https://github.com/freyacodes/Lavalink) -* For `prefix` you can set the prefix of the bot. (If you don't provide any prefix, the bot will disable the message command). -* For `activity` you can set the activity of the bot. [Example Here](https://github.com/ChocoMeow/Vocard/blob/main/PLACEHOLDERS.md#bot-activity-activity-are-updated-every-10-minutes) -* For `bot_access_user` you can pass the [discord user id](https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-). Example: `[123456789012345678]` -* For `embed_color` you must pass a [Hexadecimal color code](https://htmlcolorcodes.com/) and add `0x` before the color code. Example: `"0xb3b3b3"` -* For `default_max_queue` you can set a default maximum number of tracks that can be added to the queue. -* For `lyrics_platform` you can set lyrics search engine (e.g. `A_ZLyrics`, `Genius`, `lyrist`)
**NOTE: If you are using Genius as your lyrics search engine, you must install the lyricsgenius module (`pip install lyricsgenius`)** -* For `ipc_server` you can set the host, password and enable of the ipc server. -* For `emoji_source_raw` you can change the source emoji of the track with discord emoji like `<:EMOJI_NAME:EMOJI_ID>` -* For `cooldowns` you can set a custom cooldown in the command. Example: `"command_name": [The total number of tokens available, The length of the cooldown period in seconds]` -* For `aliases` you can set custom aliases in the command. Example: `"command_name": [alias1, alias2, ...]` -* For `default_controller` you can set custom embeds and buttons in controller, [Example Here](https://github.com/ChocoMeow/Vocard/blob/main/PLACEHOLDERS.md#controller-embeds) +1. Rename `.env Example` to `.env` and [customize your env](https://docs.vocard.xyz/configuration/#settings-up-env). +2. Rename `settings Example.json` to `settings.json` and [customize your settings](https://docs.vocard.xyz/configuration/#settings-up-settingsjson). +3. Now, you can start your bot with `python main.py`. ## How to update? (For Windows and Linux) ***Note: Make sure there are no personal files in the directory! Otherwise it will be deleted.*** @@ -212,4 +60,4 @@ python update.py -v VERSION # Install the beta version python update.py -b -``` +``` \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index a4060f5..58601f9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,13 @@ services: environment: - _JAVA_OPTIONS=-Xmx1G - SERVER_PORT=2333 + - LAVALINK_SERVER_PASSWORD=youshallnotpass + healthcheck: + test: 'curl -H "Authorization: youshallnotpass" -s http://localhost:2333/version' + interval: 10s + timeout: 10s + retries: 5 + start_period: 10s volumes: - ./application.yml:/opt/Lavalink/application.yml networks: @@ -15,21 +22,21 @@ services: expose: - "2333" - mongo: - image: mongo:latest - container_name: mongo - restart: unless-stopped - volumes: - - ./data/mongo/db:/data/db - - ./data/mongo/conf:/data/configdb - environment: - - MONGO_INITDB_ROOT_USERNAME=admin - - MONGO_INITDB_ROOT_PASSWORD=admin - expose: - - "27017" - networks: - - local - command: ["mongod", "--oplogSize=1024", "--wiredTigerCacheSizeGB=1", "--auth", "--noscripting"] + # mongo: + # image: mongo:latest + # container_name: mongo + # restart: unless-stopped + # volumes: + # - ./data/mongo/db:/data/db + # - ./data/mongo/conf:/data/configdb + # environment: + # - MONGO_INITDB_ROOT_USERNAME=admin + # - MONGO_INITDB_ROOT_PASSWORD=admin + # expose: + # - "27017" + # networks: + # - local + # command: ["mongod", "--oplogSize=1024", "--wiredTigerCacheSizeGB=1", "--auth", "--noscripting"] vocard: image: vocard @@ -39,11 +46,14 @@ services: volumes: - ./settings.json:/app/settings.json - ./.env:/app/.env + - ./logs/supervisor/:/var/log depends_on: lavalink: - condition: service_started - mongo: - condition: service_started + condition: service_healthy + # mongo: + # condition: service_started + ports: + - "5555:5555" networks: - local diff --git a/requirements.txt b/requirements.txt index 41d4156..49db6db 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,4 @@ websockets==10.4 Flask==2.2.3 Flask-SocketIO==5.3.2 psutil==5.9.5 +werkzeug==2.2.2 diff --git a/settings Example.json b/settings Example.json index e3750ce..2920f03 100644 --- a/settings Example.json +++ b/settings Example.json @@ -1,9 +1,9 @@ { "nodes": { "DEFAULT": { - "host": "127.0.0.1", + "host": "lavalink", "port": 2333, - "password": "password", + "password": "youshallnotpass", "secure": false, "identifier": "DEFAULT" } diff --git a/supervisord.conf b/supervisord.conf new file mode 100644 index 0000000..3a75ad4 --- /dev/null +++ b/supervisord.conf @@ -0,0 +1,17 @@ +[supervisord] +nodaemon=true +user=root + +[program:main] +command=python -u /app/main.py +autostart=true +autorestart=true +stderr_logfile=/var/log/main.err.log +stdout_logfile=/var/log/main.out.log + +[program:webapp] +command=python -u /app/web/webapp.py +autostart=true +autorestart=true +stderr_logfile=/var/log/webapp.err.log +stdout_logfile=/var/log/webapp.out.log \ No newline at end of file diff --git a/update.py b/update.py index 2342263..482af02 100644 --- a/update.py +++ b/update.py @@ -2,7 +2,7 @@ import requests, zipfile, os, shutil, argparse from io import BytesIO ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) -__version__ = "v2.6.8" +__version__ = "v2.6.8a" GITHUB_API_URL = "https://api.github.com/repos/ChocoMeow/Vocard/releases/latest" VOCARD_URL = "https://github.com/ChocoMeow/Vocard/archive/" diff --git a/web/webapp.py b/web/webapp.py index 2d95bd2..835f498 100644 --- a/web/webapp.py +++ b/web/webapp.py @@ -1,4 +1,4 @@ -from flask import Flask, redirect, url_for, session, request, render_template, abort, Response, stream_with_context +from flask import Flask, redirect, url_for, session, request, render_template, Response, stream_with_context from flask_socketio import SocketIO, emit, join_room, leave_room, rooms, disconnect from ipc import IPCClient from objects import User @@ -14,13 +14,17 @@ import functools load_dotenv() app = Flask(__name__) -app.secret_key = os.getenv("SECRET_KEY") +app.secret_key = os.getenv("DASHBOARD_SERCET_KEY") socketio = SocketIO(app) # Discord OAuth2 credentials CLIENT_ID = os.getenv("CLIENT_ID") CLIENT_SECRET = os.getenv("CLIENT_SECRET_ID") -REDIRECT_URI = 'http://127.0.0.1:5000/callback' +HOST = os.getenv("DASHBOARD_HOST") +PORT = os.getenv("DASHBOARD_PORT") +IS_SECURE = os.getenv("DASHBOARD_SECURE", "False").lower() == "true" + +REDIRECT_URI = f'http{'s' if IS_SECURE else ''}://{HOST}:{PORT}/callback' DISCORD_API_BASE_URL = 'https://discord.com/api' USERS = {} @@ -208,4 +212,4 @@ def handle_message(user: User, msg): asyncio.run(ipc_client.send(msg, user)) if __name__ == '__main__': - socketio.run(app, host="127.0.0.1", port=5000) + socketio.run(app, host="0.0.0.0", port=PORT, allow_unsafe_werkzeug=True)