Compare commits

..

No commits in common. "master" and "v0.0.3" have entirely different histories.

16 changed files with 162 additions and 1180 deletions

View File

@ -1,13 +1,11 @@
FROM python:3.7-slim # Python 3.7
FROM python:3.7
LABEL maintainer="Joshua Arulsamy <joshua.gf.arul@gmail.com>"
# Update system
RUN apt-get -y update
RUN apt-get -y upgrade
# Install ffmpeg # Install ffmpeg
RUN apt-get -y update && \ RUN apt-get install -y --no-install-recommends ffmpeg
apt-get install -y --no-install-recommends ffmpeg=7:4.1.6-1~deb10u1 && \
apt-get autoremove -y && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# All source code # All source code
WORKDIR /src WORKDIR /src
@ -16,10 +14,11 @@ WORKDIR /src
COPY requirements.txt . COPY requirements.txt .
# Install all dependencies. # Install all dependencies.
RUN pip install --no-cache-dir -r requirements.txt RUN pip install -r requirements.txt
# Copy PlexBot over to src. # Copy PlexBot over to src.
COPY PlexBot/ PlexBot COPY PlexBot/ PlexBot
# Run the bot # Run the bot
CMD ["python", "-OO", "-m", "PlexBot"] # CMD ["python", "-OO", "-m", "PlexBot"]
CMD ["python", "-m", "PlexBot"]

15
Jenkinsfile vendored
View File

@ -25,7 +25,6 @@ pipeline {
sh ''' conda create --yes -n ${BUILD_TAG} python sh ''' conda create --yes -n ${BUILD_TAG} python
source /var/lib/jenkins/miniconda3/etc/profile.d/conda.sh source /var/lib/jenkins/miniconda3/etc/profile.d/conda.sh
conda activate ${BUILD_TAG} conda activate ${BUILD_TAG}
pip install -r requirements.txt
pip install pylint pip install pylint
''' '''
} }
@ -48,12 +47,18 @@ pipeline {
} }
} }
steps { steps {
sh './deploy/build.sh' sh ''' source /var/lib/jenkins/miniconda3/etc/profile.d/conda.sh
conda activate ${BUILD_TAG}
docker build .
'''
} }
post {
always {
// Archive unit tests for the future
archiveArtifacts (allowEmptyArchive: true,
artifacts: 'dist/*whl',
fingerprint: true)
} }
stage('Push Image') {
steps {
sh './deploy/push.sh'
} }
} }
} }

View File

@ -1,17 +0,0 @@
.PHONY: help pull build clean
.DEFAULT_GOAL: build
help:
@echo "make pull"
@echo " Start docker container with pull"
@echo "make build"
@echo " Start docker container rebuilding container"
pull:
docker-compose up
build:
docker-compose -f docker-compose_dev.yml up --build
clean:
docker system prune -a

View File

@ -1,7 +1,3 @@
"""
Plex music bot for discord.
"""
import logging import logging
import sys import sys
from pathlib import Path from pathlib import Path
@ -12,33 +8,19 @@ import yaml
FORMAT = "%(asctime)s %(levelname)s: [%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s" FORMAT = "%(asctime)s %(levelname)s: [%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s"
logging.basicConfig(format=FORMAT) logging.basicConfig(format=FORMAT)
root_log = logging.getLogger() logger = logging.getLogger("PlexBot")
plex_log = logging.getLogger("Plex")
bot_log = logging.getLogger("Bot")
def load_config(basedir: str,filename: str) -> Dict[str, str]: def load_config(filename: str) -> Dict[str, str]:
"""Loads config from yaml file
Grabs key/value config pairs from a file.
Args:
filename: str path to yaml file.
Returns:
Dict[str, str] Values from config file.
Raises:
FileNotFound Configuration file not found.
"""
# All config files should be in /config # All config files should be in /config
# for docker deployment. # for docker deployment.
filename = Path(basedir, filename) filename = Path("/config", filename)
try: try:
with open(filename, "r") as config_file: with open(filename, "r") as f:
config = yaml.safe_load(config_file) config = yaml.safe_load(f)
except FileNotFoundError: except FileNotFoundError:
root_log.fatal("Configuration file not found at '"+str(filename)+"'.") logging.fatal("Configuration file not found.")
sys.exit(-1) sys.exit(-1)
# Convert str level type to logging constant # Convert str level type to logging constant
@ -49,12 +31,7 @@ def load_config(basedir: str,filename: str) -> Dict[str, str]:
"ERROR": logging.ERROR, "ERROR": logging.ERROR,
"CRITICAL": logging.CRITICAL, "CRITICAL": logging.CRITICAL,
} }
level = config["general"]["log_level"]
config["root"]["log_level"] = levels[config["root"]["log_level"].upper()] config["general"]["log_level"] = levels[level.upper()]
config["plex"]["log_level"] = levels[config["plex"]["log_level"].upper()]
config["discord"]["log_level"] = levels[config["discord"]["log_level"].upper()]
if config["lyrics"] and config["lyrics"]["token"].lower() == "none":
config["lyrics"] = None
return config return config

View File

@ -1,21 +1,14 @@
"""
Main entrypoint script.
Sets up loggers and initiates bot.
"""
import logging import logging
from discord.ext.commands import Bot from discord.ext.commands import Bot
from . import load_config from . import FORMAT
from .bot import General from .bot import General
from .bot import Plex from .bot import Plex
from PlexBot import load_config
# Load config from file # Load config from file
configdir = "config" config = load_config("config.yaml")
from os import geteuid
if geteuid() == 0:
configdir = "/config"
config = load_config(configdir,"config.yaml")
BOT_PREFIX = config["discord"]["prefix"] BOT_PREFIX = config["discord"]["prefix"]
TOKEN = config["discord"]["token"] TOKEN = config["discord"]["token"]
@ -23,30 +16,14 @@ TOKEN = config["discord"]["token"]
BASE_URL = config["plex"]["base_url"] BASE_URL = config["plex"]["base_url"]
PLEX_TOKEN = config["plex"]["token"] PLEX_TOKEN = config["plex"]["token"]
LIBRARY_NAME = config["plex"]["library_name"] LIBRARY_NAME = config["plex"]["library_name"]
LOG_LEVEL = config["general"]["log_level"]
if config["lyrics"]:
LYRICS_TOKEN = config["lyrics"]["token"]
else:
LYRICS_TOKEN = None
# Set appropiate log level # Set appropiate log level
root_log = logging.getLogger() logger = logging.getLogger("PlexBot")
plex_log = logging.getLogger("Plex") logging.basicConfig(format=FORMAT)
bot_log = logging.getLogger("Bot") logger.setLevel(LOG_LEVEL)
plex_log.setLevel(config["plex"]["log_level"])
bot_log.setLevel(config["discord"]["log_level"])
plex_args = {
"base_url": BASE_URL,
"plex_token": PLEX_TOKEN,
"lib_name": LIBRARY_NAME,
"lyrics_token": LYRICS_TOKEN,
}
bot = Bot(command_prefix=BOT_PREFIX) bot = Bot(command_prefix=BOT_PREFIX)
# Remove help command, we have our own custom one.
bot.remove_command("help")
bot.add_cog(General(bot)) bot.add_cog(General(bot))
bot.add_cog(Plex(bot, **plex_args)) bot.add_cog(Plex(bot, BASE_URL, PLEX_TOKEN, LIBRARY_NAME, BOT_PREFIX))
bot.run(TOKEN) bot.run(TOKEN)

View File

@ -1,5 +0,0 @@
"""Track version number of package."""
VERSION = "1.0.3"
if __name__ == "__main__":
print(VERSION)

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
class MediaNotFoundError(Exception):
"""Raised when a PlexAPI media resource cannot be found."""
pass
class VoiceChannelError(Exception):
"""Raised when user is not connected to a voice channel."""
pass

147
README.md
View File

@ -1,74 +1,28 @@
# Plex-Bot # Plex-Bot
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/c93b8ff976ce4205a95046487917476b)](https://app.codacy.com/manual/jarulsamy/Plex-Bot?utm_source=github.com&utm_medium=referral&utm_content=jarulsamy/Plex-Bot&utm_campaign=Badge_Grade_Dashboard)
[![GPLv3 license](https://img.shields.io/badge/License-GPLv3-blue.svg)](http://perso.crans.org/besson/LICENSE.html)
![docker pulls](https://img.shields.io/docker/pulls/jarulsamy/plex-bot)
![docker img size](https://img.shields.io/docker/image-size/jarulsamy/plex-bot)
![black badge](https://img.shields.io/badge/code%20style-black-000000.svg)
A Python-based Plex music bot for discord. A Python-based Plex music bot for discord.
![screenshot](assets/screenshot.png)
## Setup ## Setup
Plex-Bot runs entirely in a Docker container. Ensure you have Docker and docker-compose installed according to the official Docker [documentation](https://docs.docker.com/get-docker/). Plex-Bot runs entirely in a Docker container. Ensure you have Docker and docker-compose installed according to the official Docker [documentation](https://docs.docker.com/get-docker/).
1. Create a new folder and `cd` into it: 1. Clone the repository and `cd` into it:
```bash ```
mkdir Plex-Bot $ git clone https://github.com/jarulsamy/Plex-Bot
cd Plex-Bot $ cd Plex-Bot
``` ```
2. Make a `docker-compose.yml` file or use this sample: 2. Create a configuration folder:
```yml Create a new `config` folder and copy the sample config file into it:
version: "3"
services:
plex-bot:
container_name: "PlexBot"
image: jarulsamy/plex-bot:latest
environment:
- PUID=1000
- PGID=1000
- TZ=America/Denver
# Required dir for configuration files
volumes:
- "./config:/config:ro"
restart: "unless-stopped"
```
3. Create a new `config` folder and create a config file like this:: ```
$ mkdir config
$ cp sample-config.yaml config/config.yaml
```
```bash 3. Create a Discord bot application:
mkdir config
cd config
touch config.yaml
```
```yml
# Create a file called config.yaml with the following contents
root:
log_level: "info"
discord:
prefix: "?"
token: "<BOT_TOKEN>"
log_level: "debug"
plex:
base_url: "<BASE_URL>"
token: "<PLEX_TOKEN>"
library_name: "<LIBRARY_NAME>"
log_level: "debug"
lyrics:
token: "none" # Add your token here if you enable lyrics
```
4. Create a Discord bot application:
1. Go to the Discord developer portal, [here](https://discord.com/developers/applications). 1. Go to the Discord developer portal, [here](https://discord.com/developers/applications).
@ -84,69 +38,44 @@ Plex-Bot runs entirely in a Docker container. Ensure you have Docker and docker-
6. Click Create Bot User 6. Click Create Bot User
This will provide you with your bot Username and Token This will provide you with your bot Username and Token
7. Fill in the bot token in `config/config.yaml` 7. Fill in all the necessary numbers in `config/config.yaml`
5. Get your plex token: 4. Get your plex token:
* Refer to the official [plex documentation](https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/). Refer to the official [plex documentation](https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/).
* Add it to `config/config.yaml` in the appropiate spot. Add it to `config/config.yaml` in the appropiate spot.
6. Get your Lyrics Genius token (Optional): 5. Start the service:
If you would like to enable the lyrics feature of the bot, you need to signup for a free GeniusLyrics account, [here](https://genius.com/api-clients). ```
$ docker-compose up --build
After you make an account:
1. Click New API Client
2. Set the app website url to: `https://github.com/jarulsamy/Plex-Bot`
3. Set the redirect url to: `http://localhost`
4. Copy the **Client Access Token** and replace `None` with your token in `config/config.yaml`
7. Customize remaining settings
Set any remaining settings in the config file that you would like. Such as music library, and base url of the Plex server.
8. Start the service:
```bash
docker-compose up -d
```
## Logs
You can view the logs with the following command
```bash
docker-compose logs -f CONTAINER_NAME_OR_ID
# For example
docker-compose logs -f PlexBot
``` ```
## Usage ## Usage
```text ```
General: General:
kill [silent] - Halt the bot [silently]. kill - Stop the bot.
help - Print this help message.
cleanup - Delete old messages from the bot.
Plex: Plex:
play <SONG_NAME> - Play a song from the plex server. np - View currently playing song.
album <ALBUM_NAME> - Queue an entire album to play. pause - Pause currently playing song.
playlist <PLAYLIST_NAME> - Queue an entire playlist to play. play - Play a song from the Plex library.
lyrics - Print the lyrics of the song (Requires Genius API) resume - Resume a paused song.
np - Print the current playing song. skip - Skip a song.
stop - Halt playback and leave vc. stop - Stop playing.
pause - Pause playback. No Category:
resume - Resume playback. help Shows this message
clear - Clear play queue.
[] - Optional args. Type ?help command for more info on a command.
You can also type ?help category for more info on a category.
``` ```
## Support
Reach out to me at one of the following places!
- Email (Best) at joshua.gf.arul@gmail.com
- Twitter at <a href="http://twitter.com/jarulsamy_" target="_blank">`@jarulsamy_`</a>
* * * * * *

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,14 +0,0 @@
#!/usr/bin/env bash
VERSION=$(python PlexBot/__version__.py)
docker build -t "jarulsamy/plex-bot:$VERSION" .
if [ $? -eq 0 ]
then
echo "Successfully build docker image."
exit 0
else
echo "Failed to build docker image." >&2
exit 1
fi

View File

@ -1,14 +0,0 @@
#!/usr/bin/env bash
VERSION=$(python PlexBot/__version__.py)
docker push "jarulsamy/plex-bot:$VERSION"
if [ $? -eq 0 ]
then
echo "Successfully pushed docker image."
exit 0
else
echo "Failed to push docker image." >&2
exit 1
fi

View File

@ -2,7 +2,7 @@ version: "3"
services: services:
plex-bot: plex-bot:
container_name: "PlexBot" container_name: "PlexBot"
image: jarulsamy/plex-bot:latest build: .
environment: environment:
- PUID=1000 - PUID=1000
- PGID=1000 - PGID=1000
@ -10,4 +10,4 @@ services:
# Required dir for configuration files # Required dir for configuration files
volumes: volumes:
- "./config:/config:ro" - "./config:/config:ro"
restart: "unless-stopped" restart: "no"

View File

@ -1,13 +0,0 @@
version: "3"
services:
plex-bot:
container_name: "PlexBot"
build: .
environment:
- PUID=1000
- PGID=1000
- TZ=America/Denver
# Required dir for configuration files
volumes:
- "./config:/config:ro"
restart: "no"

View File

@ -1,7 +1,7 @@
discord.py==1.4.1 discord.py==1.3.4
PlexAPI==4.0.0 PlexAPI==4.0.0
fuzzywuzzy==0.18.0 fuzzywuzzy==0.18.0
python-Levenshtein==0.12.0
pynacl==1.4.0 pynacl==1.4.0
ffmpeg==1.4 ffmpeg==1.4
PyYAML==5.3.1 PyYAML==5.3.1
lyricsgenius==2.0.0

View File

@ -1,16 +1,12 @@
root: general:
# Options: debug, info, warning, error, critical
log_level: "info" log_level: "info"
discord: discord:
prefix: "?" prefix: "?"
token: "<BOT_TOKEN>" token: "<BOT_TOKEN>"
log_level: "debug"
plex: plex:
base_url: "<BASE_URL>" base_url: "<BASE_URL>"
token: "<PLEX_TOKEN>" token: "<PLEX_TOKEN>"
library_name: "<LIBRARY_NAME>" library_name: "<LIBRARY_NAME>"
log_level: "debug"
lyrics:
token: <CLIENT_ACCESS_TOKEN>