diff --git a/djs-bot/.env.example b/djs-bot/.env.example index 29a18b2cd..c5a721f29 100644 --- a/djs-bot/.env.example +++ b/djs-bot/.env.example @@ -4,11 +4,13 @@ # Discord configuration -TOKEN=abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 +# https://discord.com/developers/applications/YOUR_CLIENTID/bot +TOKEN=your_token +# https://discord.com/developers/applications/YOUR_CLIENTID/oauth2 CLIENTID=0123456789012345678 CLIENTSECRET=abcdefghijklmnopqrstuvwxyz123456 DEVUID=012345678901234567 -JWT_SECRET_KEY=secretkey +JWT_SECRET_KEY=some_secretkey # This was inserted by `prisma init`: # Environment variables declared in this file are automatically made available to Prisma. @@ -17,11 +19,15 @@ JWT_SECRET_KEY=secretkey # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. # See the documentation for all the connection string options: https://pris.ly/d/connection-strings # Options: postgresql, mongodb, mysql, sqlite -DATABASE="" +DATABASE="postgresql" # I don't recommend changing this unless you know what you're doing. # To get rid of the DB entirely, remove this line completely. -DATABASE_URL="postgresql://root:root@postgres-db:5432/base?schema=public" +POSTGRES_USER=your_username +POSTGRES_PASSWORD=your_pg_pswd +POSTGRES_DB=your_db_name +PGPORT=5432 +DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres-db:${PGPORT}/${POSTGRES_DB}?schema=public" # Backend configuration API_PORT=8080 diff --git a/djs-bot/config.js b/djs-bot/config.js index 94d93a9a6..e50ae8810 100644 --- a/djs-bot/config.js +++ b/djs-bot/config.js @@ -1,17 +1,17 @@ // Allows for .env files to be imported and used -require('dotenv').config() +require("dotenv").config(); // exporting the module allows for other files to see all the properties in this file as a single object module.exports = { /** - * Name of the bot + * Name of the bot * @type {string} */ name: "InsertNameHereBot", /** * Database option (mongodb, postgresql) https://www.prisma.io/docs/reference/database-reference/connection-urls * @type {string} */ database: process.env.DATABASE || "postgresql", - /** + /** * URL to the preferred database (Prisma ORM) * @type {string} */ db_url: process.env.DATABASE_URL || "", @@ -20,18 +20,18 @@ module.exports = { * Secret information, use the ENV file to store these values if possible */ /** - * UID for the Admin(s) of the bot + * UID for the Admin(s) of the bot * @type {string | string[]} */ ownerId: process.env.DEVUID || ["AdminID"], - /** + /** * Token for bot login * @type {string} */ token: process.env.TOKEN || "", - /** + /** * ID of the bot * @type {string} */ clientId: process.env.CLIENTID || "", - /** + /** * Secret Token for bot login * @type {string} */ clientSecret: process.env.CLIENTSECRET || "", @@ -62,20 +62,20 @@ module.exports = { // Lavalink server; optional public lavalink -> https://lavalink-list.darrennathanael.com/ // Or host one yourself -> https://github.com/lavalink-devs/Lavalink //--> https://blog.darrennathanael.com/post/how-to-lavalink/ - /** + /** * Music engine to use * @type {keyof typeof import("./lib/clients/MusicClient").Engine} */ musicEngine: "Erela", - /** + /** * Nodes to connect to * @type {import("erela.js").Node[]} */ nodes: [ { identifier: "DockerNode", // log id string host: "docker.lavalink", - port: 2333, - password: "youshallnotpass", + port: parseInt(process.env.SERVER_PORT) || 2333, + password: process.env.LAVALINK_SERVER_PASSWORD || "youshallnotpass", retryAmount: 15, // for lavalink connection attempts retryDelay: 6000, // Delay between reconnect attempts if connection is lost. secure: false, // if lavalink is running SSL @@ -91,34 +91,34 @@ module.exports = { }, ], - /** + /** * Invite URL parameters */ - /** + /** * Scopes to request for the bot * @type {import("discord.js").OAuth2Scopes[]} */ scopes: ["bot", "applications.commands"], - /** + /** * Bot oauth scopes * @type {import("discord.js").OAuth2Scopes[]} */ oauth2Scopes: ["identify", "guilds"], - /** - * Permissions to request for the bot - * @type {import("discord.js").PermissionResolvable | bigint} - * @see https://discord.com/developers/docs/topics/permissions#permissions - */ + /** + * Permissions to request for the bot + * @type {import("discord.js").PermissionResolvable | bigint} + * @see https://discord.com/developers/docs/topics/permissions#permissions + */ permissions: 0, // 8 = Administrator, 0 = Doesn't need permissions (uses slash commands) /** * Other parameters used variously throughout the bot - */ - /** + */ + /** * Debug mode for the bot - * + * * 0 = No debug logging (production), 1 = Standard Logging (debug info), 2 = Development (everything) * @type {number} */ OPLevel: 1, @@ -128,11 +128,11 @@ module.exports = { * @type {import('discord.js').ColorResolvable} */ embedColor: "Random", - /** + /** * PresenceData object | https://discord.js.org/#/docs/main/stable/typedef/PresenceData */ presence: { - /** + /** * online, idle, dnd, invisible, ... * @type {import("discord.js").PresenceStatus} */ status: "online", @@ -151,17 +151,17 @@ module.exports = { data: (client) => { return { someVariable: client.guilds.cache.size, - } - } + }; + }, }, { name: "Music", type: "LISTENING", - } + }, ], }, - /** + /** * This icon will be in every embed's author field, if you don't want it, just leave it blank or "undefined" * @type {string} */ iconURL: undefined, @@ -172,5 +172,5 @@ module.exports = { autoPause: true, autoQueue: false, history: false, - } + }, }; diff --git a/docker/.gitignore b/docker/.gitignore index 4c49bd78f..83bd2a6b8 100644 --- a/docker/.gitignore +++ b/docker/.gitignore @@ -1 +1,2 @@ .env +lavalink.env diff --git a/docker/djs-bot/Dockerfile b/docker/djs-bot/Dockerfile index ff81e9e5a..1bfd9e07a 100644 --- a/docker/djs-bot/Dockerfile +++ b/docker/djs-bot/Dockerfile @@ -1,11 +1,13 @@ FROM node:20 as builder RUN apt-get update -y && \ - apt-get install -y \ - build-essential \ - libpango1.0-dev \ - libcairo2-dev \ - librsvg2-dev \ - libjpeg-dev \ - libgif-dev \ - fonts-noto-cjk fonts-noto \ + apt-get install -y \ + build-essential \ + libpango1.0-dev \ + libcairo2-dev \ + librsvg2-dev \ + libjpeg-dev \ + libgif-dev \ + fonts-noto-cjk fonts-noto +RUN npm config set audit false +RUN npm config set fund false diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 7ebc31911..69d7bf6b6 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: djs-bot: container_name: djs-bot @@ -18,11 +16,17 @@ services: tty: true volumes: - ../djs-bot:/djs-bot + depends_on: + - postgres-db + - lavalink ports: - "8080:8080" - "3001:3001" working_dir: /djs-bot - command: ["npm", "run", "${ENABLE:-start}"] + command: ["npm", "run", "${ENABLE:-start}", "--loglevel=error"] + env_file: + - .env + - lavalink.env dashboard: container_name: dashboard @@ -33,33 +37,40 @@ services: tty: true volumes: - ../dashboard:/dashboard + depends_on: + - postgres-db + - lavalink ports: - "3000:3000" working_dir: /dashboard - command: ["npm", "run", "build-and-start"] + command: sh -c " + npm config set fund false && + npm config set audit false && + npm run build-and-start + " postgres-db: - image: postgres:15.2-alpine + image: postgres:16.4-alpine container_name: postgres restart: unless-stopped - environment: - POSTGRES_PASSWORD: root - POSTGRES_USER: root - POSTGRES_DB: base - PGPORT: 5432 volumes: - postgres_data:/var/lib/postgresql/data + env_file: + - .env lavalink: image: fredboat/lavalink:3.7.12 container_name: lavalink restart: unless-stopped hostname: docker.lavalink + user: root volumes: - ./lavalink/application.yml:/opt/Lavalink/application.yml - ./lavalink/plugins/:/opt/Lavalink/plugins ports: - 2333:2333 + env_file: + - lavalink.env volumes: postgres_data: diff --git a/docker/docker-compose_traefik.yml b/docker/docker-compose_traefik.yml new file mode 100644 index 000000000..e4821121f --- /dev/null +++ b/docker/docker-compose_traefik.yml @@ -0,0 +1,131 @@ +services: + djs-bot: + container_name: djs-bot + build: + context: .. + dockerfile: ./docker/djs-bot/Dockerfile + restart: "unless-stopped" + healthcheck: + test: "curl --fail http://127.0.0.1:8080 || exit 1" + start_period: 30s + interval: 30s + retries: 5 + timeout: 10s + init: true + environment: + - TOKEN=${TOKEN} + - CLIENTID=${CLIENTID} + - CLIENTSECRET=${CLIENTSECRET} + - DEVUID=${DEVUID} + - JWT_SECRET_KEY=${JWT_SECRET_KEY} + stdin_open: true + tty: true + volumes: + - ../djs-bot:/djs-bot + depends_on: + - postgres-db + - lavalink + networks: + - tfproxy + - default + working_dir: /djs-bot + command: ["npm", "run", "${ENABLE:-start}", "--loglevel=error"] + env_file: + - .env + - lavalink.env + labels: + - "traefik.enable=true" + - "traefik.http.routers.dmb_papi.entrypoints=websecure" + - "traefik.http.routers.dmb_papi.tls=true" + - "traefik.http.routers.dmb_papi.rule=Host(`dmb-papi.example.com`)" + - "traefik.http.routers.dmb_papi.service=dmb_papi" + - "traefik.http.services.dmb_papi.loadbalancer.server.port=8080" + - "traefik.http.routers.dmb_pws.entrypoints=websecure" + - "traefik.http.routers.dmb_pws.tls=true" + - "traefik.http.routers.dmb_pws.rule=Host(`dmb-pws.example.com`)" + - "traefik.http.routers.dmb_pws.service=dmb_pws" + - "traefik.http.services.dmb_pws.loadbalancer.server.port=3001" + - "traefik.http.middlewares.cors.headers.accessControlAllowMethods=PUT,GET,OPTIONS" + - "traefik.http.middlewares.cors.headers.accessControlAllowHeaders=*" + - "traefik.http.middlewares.cors.headers.accessControlAllowOriginList=https://dmb.example.com" + - "traefik.http.middlewares.cors.headers.accessControlMaxAge=100" + - "traefik.http.middlewares.cors.headers.addVaryHeader=true" + - "traefik.http.middlewares.cors.headers.contentTypeNosniff=true" + - "traefik.http.middlewares.cors.headers.referrerPolicy=origin-when-cross-origin" + - "traefik.http.routers.dmb_papi.middlewares=cors" + - "traefik.http.routers.dmb_pws.middlewares=cors" + + dashboard: + container_name: dashboard + image: node:latest + restart: "unless-stopped" + healthcheck: + test: "curl --fail http://127.0.0.1:3000 || exit 1" + start_period: 40s + interval: 30s + retries: 5 + timeout: 10s + init: true + stdin_open: true + tty: true + volumes: + - ../dashboard:/dashboard + depends_on: + - postgres-db + - lavalink + networks: + - tfproxy + - default + working_dir: /dashboard + command: sh -c " + npm config set fund false && + npm config set audit false && + npm run build-and-start + " + labels: + - "traefik.enable=true" + - "traefik.http.routers.dmb.entrypoints=websecure" + - "traefik.http.routers.dmb.tls=true" + - "traefik.http.routers.dmb.rule=Host(`dmb.example.com`)" + - "traefik.http.services.dmb.loadbalancer.server.port=3000" + + postgres-db: + image: postgres:16.4-alpine + container_name: postgres + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 5s + volumes: + - postgres_data:/var/lib/postgresql/data + env_file: + - .env + + lavalink: + image: fredboat/lavalink:3.7.12 + container_name: dmb_lavalink + restart: unless-stopped + hostname: docker.lavalink + user: root + healthcheck: + test: 'curl -H "Authorization: $${LAVALINK_SERVER_PASSWORD}" -s http://127.0.0.1:$${SERVER_PORT}/version' + start_period: 20s + interval: 30s + retries: 5 + timeout: 10s + volumes: + - ./lavalink/application.yml:/opt/Lavalink/application.yml + - ./lavalink/plugins/:/opt/Lavalink/plugins + env_file: + - lavalink.env + +volumes: + postgres_data: + +# Make the network frist: `docker network create -d bridge tfproxy` +networks: + tfproxy: + external: true diff --git a/docker/lavalink.env.example b/docker/lavalink.env.example new file mode 100644 index 000000000..82f8e4357 --- /dev/null +++ b/docker/lavalink.env.example @@ -0,0 +1,64 @@ +# lavalink env var +# https://lavalink.dev/configuration/#example-applicationyml +# NOTE: You can delete unused env var and use the default value in application.yml, +# env var in lavalink.env will overwrite the value in application.yml. +# Check the link above if you need more info. +SERVER_PORT=2333 +SERVER_ADDRESS=0.0.0.0 +SERVER_HTTP2_ENABLED=false + +LAVALINK_PLUGINS_0_DEPENDENCY="dev.lavalink.youtube:youtube-plugin:1.7.2" +LAVALINK_PLUGINS_0_REPOSITORY="https://maven.lavalink.dev/releases" +PLUGINS_YOUTUBE_ENABLED=true +PLUGINS_YOUTUBE_OAUTH_ENABLED=true +PLUGINS_YOUTUBE_OAUTH_SKIP_INITIALIZATION=true +PLUGINS_YOUTUBE_OAUTH_REFRESH_TOKEN="your_youtube_oauth_token" + +LAVALINK_PLUGINS_1_DEPENDENCY="com.github.TopiSenpai.LavaSrc:lavasrc-plugin:3.2.10" +LAVALINK_PLUGINS_1_REPOSITORY="https://maven.topi.wtf/releases" +PLUGINS_LAVASRC_PROVIDERS_0='ytsearch:"%ISRC%"' +PLUGINS_LAVASRC_PROVIDERS_1="ytsearch:%QUERY%" +PLUGINS_LAVASRC_SOURCES_SPOTIFY=true +PLUGINS_LAVASRC_SOURCES_APPLEMUSIC=false +PLUGINS_LAVASRC_SOURCES_DEEZER=false +PLUGINS_LAVASRC_SOURCES_YANDEXMUSIC=false +# https://developer.spotify.com/dashboard +PLUGINS_LAVASRC_SPOTIFY_CLIENT_ID=your_client_id +PLUGINS_LAVASRC_SPOTIFY_CLIENT_SECRET=your_client_secret +PLUGINS_LAVASRC_SPOTIFY_COUNTRY_CODE="US" +PLUGINS_LAVASRC_SPOTIFY_PLAYLIST_LOAD_LIMIT=6 +PLUGINS_LAVASRC_SPOTIFY_ALBUM_LOAD_LIMIT=6 + +LAVALINK_SERVER_PASSWORD= +LAVALINK_SERVER_SOURCES_YOUTUBE=false # deprecated in lavalink v3.7.12 +LAVALINK_SERVER_SOURCES_BANDCAMP= +LAVALINK_SERVER_SOURCES_SOUNDCLOUD= +LAVALINK_SERVER_SOURCES_TWITCH= +LAVALINK_SERVER_SOURCES_VIMEO= +LAVALINK_SERVER_SOURCES_HTTP= +LAVALINK_SERVER_SOURCES_NICO= +LAVALINK_SERVER_SOURCES_LOCAL= + +LAVALINK_SERVER_FILTERS_VOLUME= +LAVALINK_SERVER_FILTERS_EQUALIZER= +LAVALINK_SERVER_FILTERS_KARAOKE= +LAVALINK_SERVER_FILTERS_TIMESCALE= +LAVALINK_SERVER_FILTERS_TREMOLO= +LAVALINK_SERVER_FILTERS_VIBRATO= +LAVALINK_SERVER_FILTERS_DISTORTION= +LAVALINK_SERVER_FILTERS_ROTATION= +LAVALINK_SERVER_FILTERS_CHANNEL_MIX= +LAVALINK_SERVER_FILTERS_LOW_PASS= + +LAVALINK_SERVER_BUFFER_DURATION_MS= +LAVALINK_SERVER_FRAME_BUFFER_DURATION_MS= +LAVALINK_SERVER_OPUS_ENCODING_QUALITY= +LAVALINK_SERVER_RESAMPLING_QUALITY= +LAVALINK_SERVER_TRACK_STUCK_THRESHOLD_MS= +LAVALINK_SERVER_USE_SEEK_GHOSTING= + +# NOTE: You can comment below two settings once you got PLUGINS_YOUTUBE_OAUTH_REFRESH_TOKEN +LAVALINK_SERVER_YOUTUBE_CONFIG_EMAIL= +LAVALINK_SERVER_YOUTUBE_CONFIG_PASSWORD= + +# vim: set ft=sh : diff --git a/docker/lavalink/plugins/.gitkeep b/docker/lavalink/plugins/.gitkeep deleted file mode 100644 index e69de29bb..000000000