Skip to content
This repository has been archived by the owner on Jan 20, 2024. It is now read-only.

Commit

Permalink
Merge pull request #170 from karyeet/Dockerfile
Browse files Browse the repository at this point in the history
Merge Dockerfile into main
  • Loading branch information
karyeet authored Jun 25, 2023
2 parents 3a15950 + f68b357 commit a71be53
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 19 deletions.
86 changes: 86 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: Build

# Controls when the workflow will run
on:
workflow_dispatch:
push:
branches:
- 'main'
- 'Dockerfile'
release:
types:
- created


jobs:
build-matrix:
strategy:
matrix:
os: [buildjet-2vcpu-ubuntu-2204-arm, ubuntu-latest]

runs-on: ${{ matrix.os }}
steps:
# Get the repository's code
- name: Checkout
uses: actions/checkout@v2

# https://github.com/docker/setup-buildx-action
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2

- name: Login to Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Cache NPM
uses: buildjet/setup-node@v3
with:
node-version: 16
cache: npm

- name: Determine Platform
run: |
if [[ "${{ runner.arch }}" == "X64" ]]; then
echo "Runner is amd64"
echo "PLATFORM=amd64" >> $GITHUB_ENV
elif [[ "${{ runner.arch }}" == "ARM64" ]]; then
echo "Runner is arm64"
echo "PLATFORM=arm64" >> $GITHUB_ENV
fi
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
platforms: linux/${{ env.PLATFORM }}
push: ${{ github.event_name != 'pull_request' }}
tags: karyeet/mandarine:${{ env.PLATFORM }}-${{ github.ref_name }}
cache-from: type=gha
cache-to: type=gha,mode=max

build-docker-multiarch:
runs-on: ubuntu-latest
needs: [build-matrix]
steps:
- name: Login to Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Create and push multiarch image
run: |
docker buildx imagetools create -t karyeet/mandarine:${GITHUB_REF_NAME} \
karyeet/mandarine:arm64-${GITHUB_REF_NAME} \
karyeet/mandarine:amd64-${GITHUB_REF_NAME}
- name: Push to latest
if: github.event_name == 'release'
run: |
echo "Pushing to latest tag"
docker buildx imagetools create -t karyeet/mandarine:latest \
karyeet/mandarine:arm64-${GITHUB_REF_NAME} \
karyeet/mandarine:amd64-${GITHUB_REF_NAME}
1 change: 1 addition & 0 deletions Docker/authorize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require("play-dl").authorization();
82 changes: 82 additions & 0 deletions Docker/deezerConfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"downloadLocation": "music",
"tracknameTemplate": "%artist% - %title%",
"albumTracknameTemplate": "%tracknumber% - %title%",
"playlistTracknameTemplate": "%position% - %artist% - %title%",
"createPlaylistFolder": true,
"playlistNameTemplate": "%playlist%",
"createArtistFolder": false,
"artistNameTemplate": "%artist%",
"createAlbumFolder": true,
"albumNameTemplate": "%artist% - %album%",
"createCDFolder": true,
"createStructurePlaylist": false,
"createSingleFolder": false,
"padTracks": true,
"paddingSize": "0",
"illegalCharacterReplacer": "_",
"queueConcurrency": 3,
"maxBitrate": "1",
"feelingLucky": false,
"fallbackBitrate": true,
"fallbackSearch": false,
"fallbackISRC": false,
"logErrors": false,
"logSearched": false,
"overwriteFile": "n",
"createM3U8File": false,
"playlistFilenameTemplate": "playlist",
"syncedLyrics": false,
"embeddedArtworkSize": 800,
"embeddedArtworkPNG": false,
"localArtworkSize": 1400,
"localArtworkFormat": "jpg",
"saveArtwork": false,
"coverImageTemplate": "cover",
"saveArtworkArtist": false,
"artistImageTemplate": "folder",
"jpegImageQuality": 90,
"dateFormat": "Y-M-D",
"albumVariousArtists": true,
"removeAlbumVersion": false,
"removeDuplicateArtists": true,
"featuredToTitle": "0",
"titleCasing": "nothing",
"artistCasing": "nothing",
"executeCommand": "",
"tags": {
"title": true,
"artist": true,
"artists": true,
"album": true,
"cover": true,
"trackNumber": true,
"trackTotal": false,
"discNumber": true,
"discTotal": false,
"albumArtist": true,
"genre": true,
"year": true,
"date": true,
"explicit": true,
"isrc": true,
"length": true,
"barcode": true,
"bpm": true,
"replayGain": false,
"label": true,
"lyrics": false,
"syncedLyrics": false,
"copyright": false,
"composer": false,
"involvedPeople": false,
"source": false,
"rating": false,
"savePlaylistAsCompilation": false,
"useNullSeparator": false,
"saveID3v1": true,
"multiArtistSeparator": "default",
"singleAlbumArtist": false,
"coverDescriptionUTF8": false
}
}
20 changes: 20 additions & 0 deletions Docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

#run authorize() for play-dl
# sudo docker run -it --rm -v "./playdlData:/.data" karyeet/mandarine:latest /bin/ash -c "node /Mandarine/Docker/authorize.js"

version: "3"

services:
mandarine:
container_name: mandarine_music_bot
image: karyeet/mandarine:latest
volumes:
- ./config/config.json:/Mandarine/config.json:ro
- ./config/models/:/Mandarine/voice/models:ro
- ./mandarineFiles:/root/mandarineFiles
- ./playdlData:/.data
environment:
- "arl=5a2e"
- "runIndexer=True"
restart: unless-stopped

21 changes: 21 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM --platform=$BUILDPLATFORM node:16-alpine

LABEL maintainer="https://github.com/karyeet"

COPY . /Mandarine/

RUN apk add python3\
&& apk add --no-cache --virtual .gyp \
make \
g++ \
py3-pip\
&& npm install --prefix Mandarine \
&& python3 -m pip install deemix\
&& apk del .gyp

RUN mkdir ~/config \
&& mv /Mandarine/Docker/deezerConfig.json ~/config/config.json \
&& touch ~/config/.arl

CMD echo $arl >> ~/config/.arl \
&& npm start --prefix Mandarine
49 changes: 47 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,60 @@ Mandarine was created as a personal Music Bot in lieu of Rythm Bot (RIP).
- [x] Spotify playlist support
- [x] Partial support for voice commands
- [x] Help command
- [x] Docker image

#### Planned Features:
- [ ] Docker image

- [ ] Deezer Playlist support
- [ ] Multi-threaded streaming
- [ ] Prefix command & other customizations
- [ ] Volume
- [ ] Preload next song for seamless playing
- [ ] Voice recognition for play command

## Deployment
## Docker Deployment (Preferred)
[Create a discord bot](https://discord.com/developers/applications)
then [add the bot to your server](https://help.pebblehost.com/en/article/how-to-invite-your-bot-to-a-discord-server-1asdlyg/).

In the discord developer dashboard, toggle on:
- PRESENCE INTENT
- SERVER MEMBERS INTENT
- MESSAGE CONTENT INTENT

Example docker-compose.yml:

```
version: "3"
services:
mandarine:
container_name: mandarine_music_bot
image: karyeet/mandarine:latest
volumes:
- ./config/config.json:/Mandarine/config.json:ro
- ./config/models/:/Mandarine/voice/models:ro
- ./mandarineFiles:/root/mandarineFiles
- ./playdlData:/.data
environment:
- "arl=5a2e"
- "runIndexer=True"
restart: unless-stopped
```

Create a folder and create your docker-compose.yml inside it.
In the same folder create a folder called config, within this folder paste your config.json. An example config can be found in the repository.
If you want to use the picovoice backed voice commands, paste your models within a folder called models within the config folder.

To use >music, you must provide your deezer arl token to the environment. Replace "5a2e" with your full arl token in the docker-compose.yml file.

To authorize play-dl with spotify or youtube, run this command while inside the same folder as your docker-compose.yml. Specify that you would like to save to file:

`
sudo docker run -it --rm -v "./playdlData:/.data" karyeet/mandarine:Dockerfile /bin/ash -c "node /Mandarine/Docker/authorize.js"
`


## Normal Deployment
Before anything, install [Node v16 LTS](https://nodejs.org/en/)
and [create a discord bot](https://discord.com/developers/applications)
then [add the bot to your server](https://help.pebblehost.com/en/article/how-to-invite-your-bot-to-a-discord-server-1asdlyg/).
Expand All @@ -51,6 +94,8 @@ then

To make use of the >music command, deemix must be installed via `python3 -m pip install deemix`

To support spotify links, play-dl must have spotify authorization. Check the wiki.

To automatically add local tagged mp3s to the localLibrary.json, add the files to the music folder (`$home$/mandarineFiles`) and run the indexer.js file found in `./music/indexer.js` using node.

### Check out the [wiki](https://github.com/karyeet/Mandarine/wiki) for commands and more help.
19 changes: 15 additions & 4 deletions general.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

const playdl = require("play-dl");
const { createAudioResource, StreamType } = require("@discordjs/voice");
const { createReadStream } = require("fs");
const { createReadStream, existsSync } = require("fs");
const path = require("path");

const reactions = {
"positive":"🍊",
Expand Down Expand Up @@ -120,14 +121,24 @@ async function setScClientId() {
}

async function refreshSpotifyToken() {
console.log("Refreshing spotify token");
if (playdl.is_expired()) {
await playdl.refreshToken();
const dataFolderPath = path.join(__dirname, ".data");
const spotifyFilePath = path.join(dataFolderPath, "spotify.data");
if (existsSync(dataFolderPath) && existsSync(spotifyFilePath)) {
console.log("Refreshing spotify token");
if (playdl.is_expired()) {
await playdl.refreshToken();
}
}
else {
console.log("Spotify not yet configured, skipping refresh.");
}
}

setScClientId();


refreshSpotifyToken();

// set sc id every 10 minutes
setInterval(setScClientId, 10 * 60 * 1000);
// refresh spotify token every 55 minutes
Expand Down
15 changes: 2 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
// bind to a port if available in env, for heroku, replit, etc..
// set env variable dontBind to true if you want Mandarine not to bind.
if (process.env.PORT && !process.env.dontBind) {

const http = require("http");

const requestListener = function(req, res) {
res.writeHead(200);
res.end("https://github.com/karyeet/Mandarine");
};

const server = http.createServer(requestListener);
server.listen(process.env.PORT);
if (process.env.runIndexer === "True") {
require("./music/indexer.js");
}

const { Intents, Client } = require("discord.js");
Expand Down

0 comments on commit a71be53

Please sign in to comment.