Plex-Bot-Music/PlexBot/bot.py
Joshua Arulsamy 4c75d4c27f 🐛 Polished queue issues
Queue now actually works, async callback is properly awaited.
2020-08-04 03:59:48 -06:00

140 lines
4.3 KiB
Python

import logging
from queue import Queue
import discord
from discord import FFmpegPCMAudio
from discord.ext import commands
from discord.ext.commands import command
from fuzzywuzzy import fuzz
from plexapi.exceptions import Unauthorized
from plexapi.server import PlexServer
logger = logging.getLogger("PlexBot")
class General(commands.Cog):
def __init__(self, bot):
self.bot = bot
@command()
async def kill(self, ctx):
await ctx.send(f"Stopping upon the request of {ctx.author.mention}")
await self.bot.close()
logger.info(f"Stopping upon the request of {ctx.author.mention}")
class Plex(commands.Cog):
def __init__(self, bot, base_url, plex_token, lib_name) -> None:
self.bot = bot
self.base_url = base_url
self.plex_token = plex_token
self.library_name = lib_name
try:
self.pms = PlexServer(self.base_url, self.plex_token)
except Unauthorized:
logger.fatal("Invalid Plex token, stopping...")
raise Unauthorized("Invalid Plex token")
self.music = self.pms.library.section(self.library_name)
self.vc = None
self.current_track = None
self.play_queue = Queue()
logger.info("Started bot successfully")
def _search_tracks(self, title):
tracks = self.music.searchTracks()
score = [None, -1]
for i in tracks:
s = fuzz.ratio(title.lower(), i.title.lower())
if s > score[1]:
score[0] = i
score[1] = s
elif s == score[1]:
score[0] = i
return score[0]
@command()
async def hello(self, ctx, *, member: discord.member = None):
member = member or ctx.author
await ctx.send(f"Hello {member}")
async def _after_callback(self, error=None):
logger.debug("After callbacked")
if self.play_queue.empty():
self.current_track = None
logger.debug("No tracks left in queue, returning")
else:
track = self.play_queue.get()
audio_stream = FFmpegPCMAudio(track.getStreamURL())
self.current_track = track
logger.debug(f"Started playing next song in queue: {track.title}")
self.vc.play(audio_stream)
await self.callback_ctx.send(f"Playing {track.title}")
@command()
async def play(self, ctx, *args):
if not len(args):
await ctx.send(f"Usage: {BOT_PREFIX}play TITLE_OF_SONG")
return
title = " ".join(args)
track = self._search_tracks(title)
if track:
track_url = track.getStreamURL()
if not ctx.author.voice:
await ctx.send("Join a voice channel first!")
return
if not self.vc:
self.vc = await ctx.author.voice.channel.connect()
logger.debug("Connected to vc.")
if self.vc.is_playing():
self.play_queue.put(track)
self.callback_ctx = ctx
await ctx.send(f"Added {track.title} to queue.")
logger.debug(f"Added {track.title} to queue.")
else:
audio_stream = FFmpegPCMAudio(track_url)
self.vc.play(audio_stream, after=self._after_callback)
self.current_track = track
logger.debug(f"Playing {track.title}")
await ctx.send(f"Playing {track.title}")
else:
logger.debug(f"{title} was not found.")
await ctx.send(f"{title} was not found.")
@command()
async def stop(self, ctx):
if self.vc:
self.vc.stop()
await self.vc.disconnect()
self.vc = None
await ctx.send("Stopped")
@command()
async def pause(self, ctx):
if self.vc:
await self.vc.pause()
await ctx.send("Paused")
@command()
async def resume(self, ctx):
if self.vc:
await self.vc.resume()
await ctx.send("Resumed")
@command()
async def skip(self, ctx):
logger.debug("Skip")
if self.vc:
self.vc.stop()
await self._after_callback()
@command()
async def np(self, ctx):
await ctx.send(f"Currently playing: {self.current_track.title}")