16 Commits

Author SHA1 Message Date
7d6060ed15 🔖 Bump version 2020-09-23 22:40:20 -06:00
d6f5174d20 🐛 Bump discord version
Remedies a seemingly random socketio error:

```
    future: <Task finished coro=<VoiceClient._create_socket() done, defined at /usr/local/lib/python3.7/site-packages/discord/voice_client.py:172>
    exception=gaierror(-2, 'Name or service not known')>

    Traceback (most recent call last):
    File "/usr/local/lib/python3.7/site-packages/discord/voice_client.py", line 191, in _create_socket
    self.endpoint_ip = socket.gethostbyname(self.endpoint) socket.gaierror: [Errno -2] Name or service not known
```
2020-09-23 22:36:47 -06:00
151f650bb2 Merge pull request #13 from jarulsamy/dev
v1.0.2
2020-09-06 15:39:10 -06:00
5eceab7a22 📝 Add lyrics updates 2020-09-06 15:33:25 -06:00
545654f9a7 Add lyrics command
Optionally grab lyrics of a song using the
lyrics command. Required LyricsGenius API token.
2020-09-06 15:32:40 -06:00
57490cdf17 Merge pull request #12 from jarulsamy/dev
v1.0.1
2020-08-29 20:09:14 -06:00
a6be6eac37 Merge branch 'master' into dev 2020-08-29 20:08:38 -06:00
5ba7d751d0 👥 Add label of maintainer 2020-08-14 20:57:03 -06:00
d0b6c25359 Pinned dependencies 2020-08-13 03:21:00 -06:00
db188d968b 🎨 Static methods 2020-08-13 03:20:41 -06:00
b05dd0598b Merge pull request #11 from jarulsamy/dev
v1.0.1
2020-08-13 02:53:46 -06:00
cf2bc24f8a 🐛 Fix always skip push 2020-08-10 03:03:54 -06:00
1839cc5d03 Merge pull request #10 from codacy-badger/codacy-badge
Add a Codacy badge to README.md
2020-08-10 02:42:52 -06:00
e6c4b84538 Add Codacy badge 2020-08-10 08:42:13 +00:00
c1cba637b8 Merge pull request #9 from jarulsamy/dev
v1.0.0
2020-08-10 02:37:42 -06:00
3e90c9e9ef Merge pull request #8 from jarulsamy/dev
Docs Overhaul
2020-08-09 15:26:54 -06:00
9 changed files with 121 additions and 25 deletions

View File

@ -1,8 +1,10 @@
FROM python:3.7-slim FROM python:3.7-slim
LABEL maintainer="Joshua Arulsamy <joshua.gf.arul@gmail.com>"
# Install ffmpeg # Install ffmpeg
RUN apt-get -y update && \ RUN apt-get -y update && \
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 autoremove -y && \
apt-get clean && \ apt-get clean && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*

11
Jenkinsfile vendored
View File

@ -25,6 +25,7 @@ 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
''' '''
} }
@ -47,18 +48,10 @@ pipeline {
} }
} }
steps { steps {
sh ''' source /var/lib/jenkins/miniconda3/etc/profile.d/conda.sh sh './deploy/build.sh'
conda activate ${BUILD_TAG}
./deploy/build.sh
'''
} }
} }
stage('Push Image') { stage('Push Image') {
when {
expression {
currentBuild.result == 'SUCCESS'
}
}
steps { steps {
sh './deploy/push.sh' sh './deploy/push.sh'
} }

View File

@ -56,4 +56,7 @@ def load_config(filename: str) -> Dict[str, str]:
config["plex"]["log_level"] = levels[config["plex"]["log_level"].upper()] config["plex"]["log_level"] = levels[config["plex"]["log_level"].upper()]
config["discord"]["log_level"] = levels[config["discord"]["log_level"].upper()] config["discord"]["log_level"] = levels[config["discord"]["log_level"].upper()]
if config["lyrics"]["token"].lower() == "none":
config["lyrics"]["token"] = None
return config return config

View File

@ -20,6 +20,8 @@ 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"]
LYRICS_TOKEN = config["lyrics"]["token"]
# Set appropiate log level # Set appropiate log level
root_log = logging.getLogger() root_log = logging.getLogger()
plex_log = logging.getLogger("Plex") plex_log = logging.getLogger("Plex")
@ -28,9 +30,16 @@ bot_log = logging.getLogger("Bot")
plex_log.setLevel(config["plex"]["log_level"]) plex_log.setLevel(config["plex"]["log_level"])
bot_log.setLevel(config["discord"]["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. # Remove help command, we have our own custom one.
bot.remove_command("help") bot.remove_command("help")
bot.add_cog(General(bot)) bot.add_cog(General(bot))
bot.add_cog(Plex(bot, BASE_URL, PLEX_TOKEN, LIBRARY_NAME, BOT_PREFIX)) bot.add_cog(Plex(bot, **plex_args))
bot.run(TOKEN) bot.run(TOKEN)

View File

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

View File

@ -5,6 +5,7 @@ import logging
from urllib.request import urlopen from urllib.request import urlopen
import discord import discord
import lyricsgenius
from async_timeout import timeout from async_timeout import timeout
from discord import FFmpegPCMAudio from discord import FFmpegPCMAudio
from discord.ext import commands from discord.ext import commands
@ -28,6 +29,7 @@ General:
Plex: Plex:
play <SONG_NAME> - Play a song from the plex server. play <SONG_NAME> - Play a song from the plex server.
album <ALBUM_NAME> - Queue an entire album to play. album <ALBUM_NAME> - Queue an entire album to play.
lyrics - Print the lyrics of the song (Requires Genius API)
np - Print the current playing song. np - Print the current playing song.
stop - Halt playback and leave vc. stop - Halt playback and leave vc.
pause - Pause playback. pause - Pause playback.
@ -119,6 +121,15 @@ class General(commands.Cog):
except (discord.Forbidden, discord.NotFound, discord.HTTPException): except (discord.Forbidden, discord.NotFound, discord.HTTPException):
pass pass
async for i in channel.history(limit=limit):
if i.author == ctx.message.author and i.content.startswith(
self.bot.command_prefix
):
try:
await i.delete()
except (discord.Forbidden, discord.NotFound, discord.HTTPException):
pass
except discord.Forbidden: except discord.Forbidden:
bot_log.info("Unable to delete messages, insufficient permissions.") bot_log.info("Unable to delete messages, insufficient permissions.")
await ctx.send("I don't have the necessary permissions to delete messages.") await ctx.send("I don't have the necessary permissions to delete messages.")
@ -136,9 +147,7 @@ class Plex(commands.Cog):
# All are necessary to detect global interactions # All are necessary to detect global interactions
# within the bot. # within the bot.
def __init__( def __init__(self, bot, **kwargs):
self, bot, base_url: str, plex_token: str, lib_name: str, bot_prefix: str
):
"""Initializes Plex resources """Initializes Plex resources
Connects to Plex library and sets up Connects to Plex library and sets up
@ -149,7 +158,6 @@ class Plex(commands.Cog):
base_url: str url to Plex server base_url: str url to Plex server
plex_token: str X-Token of Plex server plex_token: str X-Token of Plex server
lib_name: str name of Plex library to search through lib_name: str name of Plex library to search through
bot_prefix: str prefix used to interact with bots
Raises: Raises:
plexapi.exceptions.Unauthorized: Invalid Plex token plexapi.exceptions.Unauthorized: Invalid Plex token
@ -159,10 +167,16 @@ class Plex(commands.Cog):
""" """
self.bot = bot self.bot = bot
self.base_url = base_url self.base_url = kwargs["base_url"]
self.plex_token = plex_token self.plex_token = kwargs["plex_token"]
self.library_name = lib_name self.library_name = kwargs["lib_name"]
self.bot_prefix = bot_prefix self.bot_prefix = bot.command_prefix
if kwargs["lyrics_token"]:
self.genius = lyricsgenius.Genius(kwargs["lyrics_token"])
else:
plex_log.warning("No lyrics token specified, lyrics disabled")
self.genius = None
# Log fatal invalid plex token # Log fatal invalid plex token
try: try:
@ -303,7 +317,8 @@ class Plex(commands.Cog):
self.current_track = None self.current_track = None
self.bot.loop.call_soon_threadsafe(self.play_next_event.set) self.bot.loop.call_soon_threadsafe(self.play_next_event.set)
def _build_embed_track(self, track, type_="play"): @staticmethod
def _build_embed_track(track, type_="play"):
"""Creates a pretty embed card for tracks """Creates a pretty embed card for tracks
Builds a helpful status embed with the following info: Builds a helpful status embed with the following info:
@ -350,7 +365,8 @@ class Plex(commands.Cog):
return embed, art_file return embed, art_file
def _build_embed_album(self, album): @staticmethod
def _build_embed_album(album):
"""Creates a pretty embed card for albums """Creates a pretty embed card for albums
Builds a helpful status embed with the following info: Builds a helpful status embed with the following info:
@ -616,3 +632,54 @@ class Plex(commands.Cog):
self.play_queue = asyncio.Queue() self.play_queue = asyncio.Queue()
bot_log.debug("Cleared queue") bot_log.debug("Cleared queue")
await ctx.send(":boom: Queue cleared.") await ctx.send(":boom: Queue cleared.")
@command()
async def lyrics(self, ctx):
"""User command to get lyrics of a song.
Args:
ctx: discord.ext.commands.Context message context from command
Returns:
None
Raises:
None
"""
if not self.current_track:
plex_log.info("No song currently playing")
return
if self.genius:
plex_log.info(
"Searching for %s, %s",
self.current_track.title,
self.current_track.artist().title,
)
try:
song = self.genius.search_song(
self.current_track.title, self.current_track.artist().title
)
except TypeError:
self.genius = None
plex_log.error("Invalid genius token, disabling lyrics")
return
try:
lyrics = song.lyrics
# Split into 1950 char chunks
# Discord max message length is 2000
lines = [(lyrics[i : i + 1950]) for i in range(0, len(lyrics), 1950)]
for i in lines:
if i == "":
continue
# Apply code block format
i = f"```{i}```"
await ctx.send(i)
except (IndexError, TypeError):
plex_log.info("Could not find lyrics")
await ctx.send("Can't find lyrics for this song.")
else:
plex_log.warning("Attempted lyrics without valid token")

View File

@ -1,5 +1,6 @@
# 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) [![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 pulls](https://img.shields.io/docker/pulls/jarulsamy/plex-bot)
![docker img size](https://img.shields.io/docker/image-size/jarulsamy/plex-bot) ![docker img size](https://img.shields.io/docker/image-size/jarulsamy/plex-bot)
@ -88,11 +89,27 @@ Plex-Bot runs entirely in a Docker container. Ensure you have Docker and docker-
* Add it to `config/config.yaml` in the appropiate spot. * Add it to `config/config.yaml` in the appropiate spot.
6. Customize remaining settings 6. Get your Lyrics Genius token (Optional):
If you wanty to disable this feature, set token to `None` in `config/config.yaml`
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).
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** to `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. Set any remaining settings in the config file that you would like. Such as music library, and base url of the Plex server.
7. Start the service: 8. Start the service:
```bash ```bash
docker-compose up -d docker-compose up -d
@ -120,6 +137,7 @@ General:
Plex: Plex:
play <SONG_NAME> - Play a song from the plex server. play <SONG_NAME> - Play a song from the plex server.
album <ALBUM_NAME> - Queue an entire album to play. album <ALBUM_NAME> - Queue an entire album to play.
lyrics - Print the lyrics of the song (Requires Genius API)
np - Print the current playing song. np - Print the current playing song.
stop - Halt playback and leave vc. stop - Halt playback and leave vc.
pause - Pause playback. pause - Pause playback.

View File

@ -1,6 +1,7 @@
discord.py==1.3.4 discord.py==1.4.1
PlexAPI==4.0.0 PlexAPI==4.0.0
fuzzywuzzy==0.18.0 fuzzywuzzy==0.18.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

@ -11,3 +11,6 @@ plex:
token: "<PLEX_TOKEN>" token: "<PLEX_TOKEN>"
library_name: "<LIBRARY_NAME>" library_name: "<LIBRARY_NAME>"
log_level: "debug" log_level: "debug"
lyrics:
token: <CLIENT_ACCESS_TOKEN>