mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 11:18:54 -05:00
* More changes
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixed auto play defaulting to playlist
Signed-off-by: Guy <guyreis96@gmail.com>
* Localtrack fix
Signed-off-by: Guy <guyreis96@gmail.com>
* Updated deps .. since for some reason aiosqlite is not being auto installed for everyone
Signed-off-by: Guy <guyreis96@gmail.com>
* Yupo
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixed a crash in [p]now
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixed crash on playlist save
Signed-off-by: Guy <guyreis96@gmail.com>
* Debugging Commit
Signed-off-by: Guy <guyreis96@gmail.com>
* Yet more prints
Signed-off-by: Guy <guyreis96@gmail.com>
* Even more spammy debug
Signed-off-by: Guy <guyreis96@gmail.com>
* Debugging commit + NEw Dispatches
Signed-off-by: Guy <guyreis96@gmail.com>
* Debugging commit + NEw Dispatches
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixed localpath checks
Signed-off-by: Guy <guyreis96@gmail.com>
* more fixes for Localpaths
Signed-off-by: Guy <guyreis96@gmail.com>
* Spelling mistake on method
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixed Crash on event handler
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixed Crash on local search
Signed-off-by: Guy <guyreis96@gmail.com>
* Reduced fuzzy match percentage threshold for local tracks to account for nested folders
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixed a crash on queue end
Signed-off-by: Guy <guyreis96@gmail.com>
* Sigh ... Removed a duplicate dispatch
Signed-off-by: Guy <guyreis96@gmail.com>
* Sigh i removed this before ...
Signed-off-by: Guy <guyreis96@gmail.com>
* Reorder dispatch signatures so all 3 new dispatch have matching signature
Signed-off-by: Guy <guyreis96@gmail.com>
* Formatting
Signed-off-by: Guy <guyreis96@gmail.com>
* Edited Error Event to support localtracks
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix a Crash on track crash :awesome:
Signed-off-by: Guy <guyreis96@gmail.com>
* Yikes soo much spam
Signed-off-by: Guy <guyreis96@gmail.com>
* Remove spam and improve existance check
Signed-off-by: Guy <guyreis96@gmail.com>
* Repeat and Auto-play are mutually exclusive now
Signed-off-by: Guy <guyreis96@gmail.com>
* DEBUGS for Preda
Signed-off-by: Guy <guyreis96@gmail.com>
* Vimeo tracks can be from both these domains "vimeo.com", "beam.pro"
Signed-off-by: Guy <guyreis96@gmail.com>
* I mean Mixer can be from those 2 domains ....
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixed `search sc` command
Signed-off-by: Guy <guyreis96@gmail.com>
* Run everything though lints.
rename localtracks module to dataclasses
Clear lock on errors
Signed-off-by: Draper <guyreis96@gmail.com>
* Try to speed up long playlist loading
Signed-off-by: Draper <guyreis96@gmail.com>
* Im an idiot
Signed-off-by: Draper <guyreis96@gmail.com>
* Im an idiot
Signed-off-by: Draper <guyreis96@gmail.com>
* Added logging for writes
Signed-off-by: Draper <guyreis96@gmail.com>
* Fix crash on cog reload
Signed-off-by: Draper <guyreis96@gmail.com>
* Fix for runtimewarning ?
Signed-off-by: Draper <guyreis96@gmail.com>
* Fix for Local Track cache
Signed-off-by: Draper <guyreis96@gmail.com>
* Remove broken tracks from queue on exception
Theoretically do not auto play if track stop reason is Stopped or cleanup
Signed-off-by: Draper <guyreis96@gmail.com>
* Previous commit was a fluke ... ignore it
Signed-off-by: Draper <guyreis96@gmail.com>
* Change from cleanup to Replaced
Signed-off-by: Draper <guyreis96@gmail.com>
* Fixed AttributeError: 'Track' object has no attribute 'info'.
[p]skip will only work for autoplay is there a track being played.
Fixed Console spam if query saving failed in the background while reloading bot.
Autoplay now respect [p]stop command
Signed-off-by: Guy <guyreis96@gmail.com>
* Black formatting
Fix Issue with auto play working when there is songs in the queue
Stop notifying queue ended if autoplay is on
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixed a crash on track load timeout
Signed-off-by: Guy <guyreis96@gmail.com>
* [p]playlist start will now show the playlist name in embed body
Improved Logic for handling broken tracks when repeat is on.
Signed-off-by: Draper <guyreis96@gmail.com>
* Enqueue tracks as soon as we have the youtube URL ....
This basically changes how spotify urls are handled
Need to test saving spotify playlist
Need to test loading a spotify playlist from file
Need to test enqueuing a spotify playlist
Signed-off-by: Draper <guyreis96@gmail.com>
* Updated a track whrn enqueuing spotify playlist
Signed-off-by: Draper <guyreis96@gmail.com>
* Debug
Signed-off-by: Draper <guyreis96@gmail.com>
* Debug
Signed-off-by: Draper <guyreis96@gmail.com>
* Debug
Signed-off-by: Draper <guyreis96@gmail.com>
* Debug
Signed-off-by: Draper <guyreis96@gmail.com>
* Debug
Signed-off-by: Draper <guyreis96@gmail.com>
* Debug
Signed-off-by: Draper <guyreis96@gmail.com>
* Debug
Signed-off-by: Draper <guyreis96@gmail.com>
* Debug
Signed-off-by: Draper <guyreis96@gmail.com>
* Debug
Signed-off-by: Draper <guyreis96@gmail.com>
* Debug
Signed-off-by: Draper <guyreis96@gmail.com>
* Revert spotify_enqueue changes
Signed-off-by: Draper <guyreis96@gmail.com>
* Revert spotify_enqueue changes
Signed-off-by: Draper <guyreis96@gmail.com>
* Allow to set Lavalink jar version from Environment vars
Signed-off-by: Draper <guyreis96@gmail.com>
* Allow to set Lavalink jar version from Environment vars
Signed-off-by: Draper <guyreis96@gmail.com>
* Fix for a crash on Equalizer, Merge Spotify_enqueue changes and revert manager changes
Signed-off-by: Draper <guyreis96@gmail.com>
* Break playlist enqueue after 10 consecutive failures
Signed-off-by: Draper <guyreis96@gmail.com>
* Auto DC, is not compatible with Auto Play
Signed-off-by: Draper <guyreis96@gmail.com>
* Make notifier aware of guild its being called for
Signed-off-by: Draper <guyreis96@gmail.com>
* Type checking
Signed-off-by: Draper <guyreis96@gmail.com>
* Remove lock from 2 exits that i didn't before
Signed-off-by: Draper <guyreis96@gmail.com>
* Fixed TypeError: spotify_enqueue() got an unexpected keyword argument 'notify'
Signed-off-by: Guy <guyreis96@gmail.com>
* Reorder toggles to alphabetical order
Signed-off-by: Guy <guyreis96@gmail.com>
* Update Query to handle spotify URIs
Signed-off-by: Guy <guyreis96@gmail.com>
* update database
Signed-off-by: Guy <guyreis96@gmail.com>
* Dont say tracks enqued on invalid link
Make autop lay a mod only setting
Signed-off-by: Draper <guyreis96@gmail.com>
* Dont say tracks enqued on invalid spotify link
Signed-off-by: Draper <guyreis96@gmail.com>
* Set default age to 365 days
Signed-off-by: Draper <guyreis96@gmail.com>
* Allow Audio mods to set auto play playlists.
Save playlists songs to cache when migrating
Signed-off-by: Guy <guyreis96@gmail.com>
* Black formatting
Signed-off-by: Guy <guyreis96@gmail.com>
* [p]eq cooldown is not triggered is player check fails (i.e if nothing is currently playing)
Adding and removing reaction is no longer a blocking action
Signed-off-by: Guy <guyreis96@gmail.com>
* changelog for non blocking reaction handles
Signed-off-by: Guy <guyreis96@gmail.com>
* Show auto dc and auto play settings by default
Signed-off-by: Guy <guyreis96@gmail.com>
* lint is being a bitch
Signed-off-by: Guy <guyreis96@gmail.com>
* lint changes
Signed-off-by: Draper <guyreis96@gmail.com>
* stop caching local tracks
Signed-off-by: Draper <guyreis96@gmail.com>
* List of Lavalink.Tracks natively added to Playlist Objects
Signed-off-by: Draper <guyreis96@gmail.com>
* Fix UX changes and should fix autoplay
Signed-off-by: Draper <guyreis96@gmail.com>
* Fixed Skip x number of tracks
Signed-off-by: Draper <guyreis96@gmail.com>
* Lint changes
Signed-off-by: Draper <guyreis96@gmail.com>
* Remvoe dead code
Signed-off-by: Draper <guyreis96@gmail.com>
* Update playlist embed formatting to reflect Preda's suggestions
Signed-off-by: Draper <guyreis96@gmail.com>
* Update change logs
Signed-off-by: Draper <guyreis96@gmail.com>
* Add `async with ctx.typing():` to queue and to local folder
Signed-off-by: Draper <guyreis96@gmail.com>
* Stop queuing now when queue is empty with [p]queue
Signed-off-by: Draper <guyreis96@gmail.com>
* fix ctx.typing()
Signed-off-by: Draper <guyreis96@gmail.com>
* fix ctx.typing()
Signed-off-by: Draper <guyreis96@gmail.com>
* Part 1
Signed-off-by: Draper <guyreis96@gmail.com>
* Dont check local track author and name if title is Unknown
Signed-off-by: Guy <guyreis96@gmail.com>
* Makes auto play more random
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixes local play
Fixed missing format
Signed-off-by: Guy <guyreis96@gmail.com>
* Query.process_input accept lavalink.Track objects
Signed-off-by: Draper <guyreis96@gmail.com>
* docstrings
Signed-off-by: Draper <guyreis96@gmail.com>
* Add TODO for timestamp support
Signed-off-by: Draper <guyreis96@gmail.com>
* Improve autoplay from cache logic (possibly slightly slower but more efficient overall)
Signed-off-by: Draper <guyreis96@gmail.com>
* Add My Lavalink PR as a dependency
Remember to remove this .... The PR will bump it to 0.3.2
Signed-off-by: Draper <guyreis96@gmail.com>
* Add My Lavalink PR as a dependency
Remember to remove this .... The PR will bump it to 0.3.2
Signed-off-by: Draper <guyreis96@gmail.com>
* Add My Lavalink PR as a dependency
Remember to remove this .... The PR will bump it to 0.3.2
Signed-off-by: Draper <guyreis96@gmail.com>
* Compile all regex at runtime
Signed-off-by: Draper <guyreis96@gmail.com>
* Fixes local play
Fixed missing format
Signed-off-by: Guy <guyreis96@gmail.com>
* Revert Dep error
Signed-off-by: Guy <guyreis96@gmail.com>
* black
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixed attribute error
Signed-off-by: Guy <guyreis96@gmail.com>
* add `self.bot.dispatch("audio_disconnect", ctx.guild)` dispatch when the player is disconnected
Signed-off-by: Guy <guyreis96@gmail.com>
* Removed shuffle lock on skip
Signed-off-by: Guy <guyreis96@gmail.com>
* Better logic for auto seek (timestamps)
Signed-off-by: Guy <guyreis96@gmail.com>
* Better logic for auto seek (timestamps)
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixes timestamps on spotify tracks
Signed-off-by: Guy <guyreis96@gmail.com>
* Add ctx typing to playlist enqueue
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix Deps
Signed-off-by: Guy <guyreis96@gmail.com>
* Black formatting + Using new lavalink methods for shuffling
Signed-off-by: Guy <guyreis96@gmail.com>
* remove ctx.typing from playlist start
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixes typerror when enqueuing spotify playlists
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix keyerror
Signed-off-by: Guy <guyreis96@gmail.com>
* black formatting, + embed for [p]audioset cache as I forgot it before
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix Error on playlist upload
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix Text help for bump
Signed-off-by: Guy <guyreis96@gmail.com>
* Allow track bumping while shuffle is on
Signed-off-by: Guy <guyreis96@gmail.com>
* Edit bump embed to be consistent with other embed
Hyperlink tracks and removed dynamic title
Signed-off-by: Guy <guyreis96@gmail.com>
* Black
Signed-off-by: Guy <guyreis96@gmail.com>
* Errors not printing fix?
Signed-off-by: Guy <guyreis96@gmail.com>
* Errors not printing fix?
Signed-off-by: Guy <guyreis96@gmail.com>
* Track enqueued footer now shows correct track position when shuffle is on
Signed-off-by: Guy <guyreis96@gmail.com>
* Update changelogs
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix is_owner check in audioset settings
Signed-off-by: Guy <guyreis96@gmail.com>
* Changelogs
Signed-off-by: Guy <guyreis96@gmail.com>
* Dont store searches with no results in cache, fix malformated playlist to cache upon settings migration
Signed-off-by: Guy <guyreis96@gmail.com>
* _clear_lock_on_error > Needs to be reviewed to see if it has been done correctly
Signed-off-by: Guy <guyreis96@gmail.com>
* _clear_lock_on_error > Needs to be reviewed to see if it has been done correctly
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix Query search so that it works with absolute paths for localtracks
Signed-off-by: Guy <guyreis96@gmail.com>
* Extra error if lavalink is set to external and the query is a localtrack and nothing is found
Signed-off-by: Guy <guyreis96@gmail.com>
* Black
Signed-off-by: Guy <guyreis96@gmail.com>
* More detailed error message
Signed-off-by: Guy <guyreis96@gmail.com>
* [p]seek and [p]skip can be used by user if they are the song requester while DJ mode is enabled, if votes are disabled. , [p]queue shuffle can be used to shuffle the queue manually. and [p]queue clean self can be used to remove all songs you requested from the queue.
Signed-off-by: Guy <guyreis96@gmail.com>
* black
Signed-off-by: Guy <guyreis96@gmail.com>
* All the fixes + a `should_auto_play` dispatch for the tech savy peeps
Signed-off-by: Guy <guyreis96@gmail.com>
* Spellchecker + Pythonic changes
Signed-off-by: Guy <guyreis96@gmail.com>
* NO spam for logs
Signed-off-by: Guy <guyreis96@gmail.com>
* Pass Current voice channel to `red_audio_should_auto_play` dispatch
Signed-off-by: Guy <guyreis96@gmail.com>
* Black
Signed-off-by: Guy <guyreis96@gmail.com>
* playlist upload also updates cache in the background
Signed-off-by: Guy <guyreis96@gmail.com>
* playlist upload also updates cache in the background
Signed-off-by: Guy <guyreis96@gmail.com>
* Add scope to playlist picker
Signed-off-by: Guy <guyreis96@gmail.com>
* Delete Playlist picker message once something is selected
Signed-off-by: Guy <guyreis96@gmail.com>
* OCD Fix
Signed-off-by: Guy <guyreis96@gmail.com>
* Facepalm
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix a Potential crash
Signed-off-by: Guy <guyreis96@gmail.com>
* Update my stupidity
Signed-off-by: Guy <guyreis96@gmail.com>
* Auto Pause + Skip tracks already in playlist upon playlist append + a command to remove duplicated tracks from playlist
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix DJ mode when Role is deleted - Credits go to Neuro Assassin#4779
Fix an issue where auto play MAY not trigger
Signed-off-by: Guy <guyreis96@gmail.com>
* Change log to Neuro Assassin#4779 fix
Signed-off-by: Guy <guyreis96@gmail.com>
* Black
Signed-off-by: Guy <guyreis96@gmail.com>
* Dont auto pause manual pauses
Signed-off-by: Guy <guyreis96@gmail.com>
* Adds `[p]autoplay` that can be run by mods or higher
Signed-off-by: Guy <guyreis96@gmail.com>
* 🤦
Signed-off-by: Guy <guyreis96@gmail.com>
* 2x 🤦
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixed wrong import
Signed-off-by: Guy <guyreis96@gmail.com>
* Added Autoplay notify
Signed-off-by: Guy <guyreis96@gmail.com>
* Added Autoplay notify
Signed-off-by: Guy <guyreis96@gmail.com>
* Black
Signed-off-by: Guy <guyreis96@gmail.com>
* Store Track object as prev song instead of URI
Signed-off-by: Guy <guyreis96@gmail.com>
* Black why do u hate me
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix command name
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix Autoplay notify
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix missing await and TypeError, Thanks Flame
Signed-off-by: Guy <guyreis96@gmail.com>
* Add a list of tracks to show as a menu
Signed-off-by: Guy <guyreis96@gmail.com>
* adds the `[p]genre` command which uses the Spotify and Youtube API
Signed-off-by: Guy <guyreis96@gmail.com>
* Enqueue Playlists from genre command
Signed-off-by: Guy <guyreis96@gmail.com>
* Pretify `[p]genre`
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix a Typo and correct jukebox charge order
Signed-off-by: Guy <guyreis96@gmail.com>
* Add genre command to error handling
Signed-off-by: Guy <guyreis96@gmail.com>
* Type checking
Signed-off-by: Guy <guyreis96@gmail.com>
* Update naming scheme for `[p]genre`
Signed-off-by: Guy <guyreis96@gmail.com>
* Black why do you hate me
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixed `[p]local start`
Playlist picker auto selects if theres just 1 playlist found
`[p]queue cleanself` added
Signed-off-by: Guy <guyreis96@gmail.com>
* *sigh* back compatibility with old localtrack paths
Signed-off-by: Guy <guyreis96@gmail.com>
* *sigh* back compatibility with old localtrack paths, even more
Signed-off-by: Guy <guyreis96@gmail.com>
* *sigh* back compatibility with old localtrack paths Even more
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixes localtracks in playlist info command
Signed-off-by: Guy <guyreis96@gmail.com>
* Debug Local Strings
Signed-off-by: Guy <guyreis96@gmail.com>
* Debug Local Strings
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixes `[p]playlist info` for local tracks + fixed error in `[p]remove`
Signed-off-by: Guy <guyreis96@gmail.com>
* Black
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixes formatting in `[p]playlist info`
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix an issue with User Scope playlists were not being deleted
Signed-off-by: Guy <guyreis96@gmail.com>
* Typechecking
Signed-off-by: Guy <guyreis96@gmail.com>
* Black
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix the logic of `delegate_autoplay`
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix a Crash on Load due to type hinting
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix a Crash on Load due to type hintingBlack + fix order of `red_audio_should_auto_play`
Signed-off-by: Guy <guyreis96@gmail.com>
* Add `red_audio_initialized` dispatch so that ownership of auto play can be maintained after a reload
Signed-off-by: Guy <guyreis96@gmail.com>
* Check if the current owner is loaded before raising an error
Signed-off-by: Guy <guyreis96@gmail.com>
* Fixes the Existence Check in `delegate_autoplay`
Signed-off-by: Guy <guyreis96@gmail.com>
* Turns `own_autoplay` in a property of Audio and improves `delegate_autoplay` Thanks Sinbad!
Signed-off-by: Guy <guyreis96@gmail.com>
* Fix for Localtracks playlists
Signed-off-by: Guy <guyreis96@gmail.com>
* When disconnecting send `Disconnecting...`
Fix Stop after a skip
Fix UX discrepancy on Playlist IDs
Fixed Exception when theres a track error
Signed-off-by: Guy <guyreis96@gmail.com>
* add `on_red_audio_unload` dispatch
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Fix a crash on track start where `player.current` can be none?
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Missing new line
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Allow `--author` for playlist to be used to filter playlist for an specific author.
Plus a few bugfixes for UX
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Rename `remdupe` to `dedupe`
Make global scope always be referenced as Global
add missing backwards quotes around the Playlist ID for 1 string
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Towncrier entries for dep changes
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Remove track index when shuffle is on
Fix Progress bar for livestreams
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Trigger autoplay on `QUEUE_END` event instead of `TRACK_END`
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Can't reproduce Ians bug but here a safeguard agaisnt it just in case
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Fixes 2 Messages that had the wrong formatting
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* standerdize playlist naming scheme
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Fix `[p]autoplay` message when Notify is enabled
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* y u h8 me black
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Fix an issue with `[p]audioset localpath` where the localtracks folder was incorrect
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Pythonic formatting
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Ugh
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Fix a typo
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Silently try to delete messages + fixes error Ian found with `[p]genre`
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* sigh black
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Add humanize_number usage correctly
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Bump RLL to 0.4.0
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Update changelog entries
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Change `bot.db` to new API's added by #2967
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Additional reformatting
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Remove PyCharm noise + Fixes a few Pycharm warnings
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Rework `index` parsing for youtube urls
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Addess Aika's review
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Fix a potential crash, saves guild ID to playlists to avoid an scheme change in the future
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Add handling for Python installs without sqlite3.
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Address Flame's review
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Fix ma stupidity
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Address Aika's latest review.
1. Update docstring for `[p]playlist rename`.
2. Fix punctuation for playlist matching.
3. `[p]playlist update` now respect playlist management perms
4. Playlist management errors now shows playlist name, id and scope where possible
5. Remove duplicated code and dead code.
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
* Pluralize string
Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com>
274 lines
10 KiB
Python
274 lines
10 KiB
Python
import asyncio
|
|
import asyncio.subprocess # disables for # https://github.com/PyCQA/pylint/issues/1469
|
|
import itertools
|
|
import logging
|
|
import pathlib
|
|
import platform
|
|
import re
|
|
import shutil
|
|
import sys
|
|
import tempfile
|
|
import time
|
|
from typing import ClassVar, List, Optional, Tuple
|
|
|
|
import aiohttp
|
|
from tqdm import tqdm
|
|
|
|
from redbot.core import data_manager
|
|
from .errors import LavalinkDownloadFailed
|
|
|
|
JAR_VERSION = "3.2.1"
|
|
JAR_BUILD = 823
|
|
LAVALINK_DOWNLOAD_URL = (
|
|
f"https://github.com/Cog-Creators/Lavalink-Jars/releases/download/{JAR_VERSION}_{JAR_BUILD}/"
|
|
f"Lavalink.jar"
|
|
)
|
|
LAVALINK_DOWNLOAD_DIR = data_manager.cog_data_path(raw_name="Audio")
|
|
LAVALINK_JAR_FILE = LAVALINK_DOWNLOAD_DIR / "Lavalink.jar"
|
|
|
|
BUNDLED_APP_YML = pathlib.Path(__file__).parent / "data" / "application.yml"
|
|
LAVALINK_APP_YML = LAVALINK_DOWNLOAD_DIR / "application.yml"
|
|
|
|
READY_LINE_RE = re.compile(rb"Started Launcher in \S+ seconds")
|
|
BUILD_LINE_RE = re.compile(rb"Build:\s+(?P<build>\d+)")
|
|
|
|
log = logging.getLogger("red.audio.manager")
|
|
|
|
|
|
class ServerManager:
|
|
|
|
_java_available: ClassVar[Optional[bool]] = None
|
|
_java_version: ClassVar[Optional[Tuple[int, int]]] = None
|
|
_up_to_date: ClassVar[Optional[bool]] = None
|
|
_blacklisted_archs = []
|
|
|
|
def __init__(self) -> None:
|
|
self.ready = asyncio.Event()
|
|
|
|
self._proc: Optional[asyncio.subprocess.Process] = None # pylint:disable=no-member
|
|
self._monitor_task: Optional[asyncio.Task] = None
|
|
self._shutdown: bool = False
|
|
|
|
async def start(self) -> None:
|
|
arch_name = platform.machine()
|
|
if arch_name in self._blacklisted_archs:
|
|
raise asyncio.CancelledError(
|
|
"You are attempting to run Lavalink audio on an unsupported machine architecture."
|
|
)
|
|
|
|
if self._proc is not None:
|
|
if self._proc.returncode is None:
|
|
raise RuntimeError("Internal Lavalink server is already running")
|
|
else:
|
|
raise RuntimeError("Server manager has already been used - create another one")
|
|
|
|
await self.maybe_download_jar()
|
|
|
|
# Copy the application.yml across.
|
|
# For people to customise their Lavalink server configuration they need to run it
|
|
# externally
|
|
shutil.copyfile(BUNDLED_APP_YML, LAVALINK_APP_YML)
|
|
|
|
args = await self._get_jar_args()
|
|
self._proc = await asyncio.subprocess.create_subprocess_exec( # pylint:disable=no-member
|
|
*args,
|
|
cwd=str(LAVALINK_DOWNLOAD_DIR),
|
|
stdout=asyncio.subprocess.PIPE,
|
|
stderr=asyncio.subprocess.STDOUT,
|
|
)
|
|
|
|
log.info("Internal Lavalink server started. PID: %s", self._proc.pid)
|
|
|
|
try:
|
|
await asyncio.wait_for(self._wait_for_launcher(), timeout=120)
|
|
except asyncio.TimeoutError:
|
|
log.warning("Timeout occurred whilst waiting for internal Lavalink server to be ready")
|
|
|
|
self._monitor_task = asyncio.create_task(self._monitor())
|
|
|
|
@classmethod
|
|
async def _get_jar_args(cls) -> List[str]:
|
|
java_available, java_version = await cls._has_java()
|
|
if not java_available:
|
|
raise RuntimeError("You must install Java 1.8+ for Lavalink to run.")
|
|
|
|
if java_version == (1, 8):
|
|
extra_flags = ["-Dsun.zip.disableMemoryMapping=true"]
|
|
elif java_version >= (11, 0):
|
|
extra_flags = ["-Djdk.tls.client.protocols=TLSv1.2"]
|
|
else:
|
|
extra_flags = []
|
|
|
|
return ["java", *extra_flags, "-jar", str(LAVALINK_JAR_FILE)]
|
|
|
|
@classmethod
|
|
async def _has_java(cls) -> Tuple[bool, Optional[Tuple[int, int]]]:
|
|
if cls._java_available is not None:
|
|
# Return cached value if we've checked this before
|
|
return cls._java_available, cls._java_version
|
|
java_available = shutil.which("java") is not None
|
|
if not java_available:
|
|
cls.java_available = False
|
|
cls.java_version = None
|
|
else:
|
|
cls._java_version = version = await cls._get_java_version()
|
|
cls._java_available = (2, 0) > version >= (1, 8) or version >= (8, 0)
|
|
return cls._java_available, cls._java_version
|
|
|
|
@staticmethod
|
|
async def _get_java_version() -> Tuple[int, int]:
|
|
"""
|
|
This assumes we've already checked that java exists.
|
|
"""
|
|
_proc: asyncio.subprocess.Process = await asyncio.create_subprocess_exec( # pylint:disable=no-member
|
|
"java", "-version", stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
|
)
|
|
# java -version outputs to stderr
|
|
_, err = await _proc.communicate()
|
|
|
|
version_info: str = err.decode("utf-8")
|
|
# We expect the output to look something like:
|
|
# $ java -version
|
|
# ...
|
|
# ... version "MAJOR.MINOR.PATCH[_BUILD]" ...
|
|
# ...
|
|
# We only care about the major and minor parts though.
|
|
version_line_re = re.compile(
|
|
r'version "(?P<major>\d+).(?P<minor>\d+).\d+(?:_\d+)?(?:-[A-Za-z0-9]+)?"'
|
|
)
|
|
short_version_re = re.compile(r'version "(?P<major>\d+)"')
|
|
|
|
lines = version_info.splitlines()
|
|
for line in lines:
|
|
match = version_line_re.search(line)
|
|
short_match = short_version_re.search(line)
|
|
if match:
|
|
return int(match["major"]), int(match["minor"])
|
|
elif short_match:
|
|
return int(short_match["major"]), 0
|
|
|
|
raise RuntimeError(
|
|
"The output of `java -version` was unexpected. Please report this issue on Red's "
|
|
"issue tracker."
|
|
)
|
|
|
|
async def _wait_for_launcher(self) -> None:
|
|
log.debug("Waiting for Lavalink server to be ready")
|
|
lastmessage = 0
|
|
for i in itertools.cycle(range(50)):
|
|
line = await self._proc.stdout.readline()
|
|
if READY_LINE_RE.search(line):
|
|
self.ready.set()
|
|
break
|
|
if self._proc.returncode is not None and lastmessage + 2 < time.time():
|
|
# Avoid Console spam only print once every 2 seconds
|
|
lastmessage = time.time()
|
|
log.critical("Internal lavalink server exited early")
|
|
if i == 49:
|
|
# Sleep after 50 lines to prevent busylooping
|
|
await asyncio.sleep(0.1)
|
|
|
|
async def _monitor(self) -> None:
|
|
while self._proc.returncode is None:
|
|
await asyncio.sleep(0.5)
|
|
|
|
# This task hasn't been cancelled - Lavalink was shut down by something else
|
|
log.info("Internal Lavalink jar shutdown unexpectedly")
|
|
if not self._has_java_error():
|
|
log.info("Restarting internal Lavalink server")
|
|
await self.start()
|
|
else:
|
|
log.critical(
|
|
"Your Java is borked. Please find the hs_err_pid%d.log file"
|
|
" in the Audio data folder and report this issue.",
|
|
self._proc.pid,
|
|
)
|
|
|
|
def _has_java_error(self) -> bool:
|
|
poss_error_file = LAVALINK_DOWNLOAD_DIR / "hs_err_pid{}.log".format(self._proc.pid)
|
|
return poss_error_file.exists()
|
|
|
|
async def shutdown(self) -> None:
|
|
if self._shutdown is True or self._proc is None:
|
|
# For convenience, calling this method more than once or calling it before starting it
|
|
# does nothing.
|
|
return
|
|
log.info("Shutting down internal Lavalink server")
|
|
if self._monitor_task is not None:
|
|
self._monitor_task.cancel()
|
|
self._proc.terminate()
|
|
await self._proc.wait()
|
|
self._shutdown = True
|
|
|
|
@staticmethod
|
|
async def _download_jar() -> None:
|
|
log.info("Downloading Lavalink.jar...")
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.get(LAVALINK_DOWNLOAD_URL) as response:
|
|
if response.status == 404:
|
|
# A 404 means our LAVALINK_DOWNLOAD_URL is invalid, so likely the jar version
|
|
# hasn't been published yet
|
|
raise LavalinkDownloadFailed(
|
|
f"Lavalink jar version {JAR_VERSION}_{JAR_BUILD} hasn't been published "
|
|
f"yet",
|
|
response=response,
|
|
should_retry=False,
|
|
)
|
|
elif 400 <= response.status < 600:
|
|
# Other bad responses should be raised but we should retry just incase
|
|
raise LavalinkDownloadFailed(response=response, should_retry=True)
|
|
fd, path = tempfile.mkstemp()
|
|
file = open(fd, "wb")
|
|
nbytes = 0
|
|
with tqdm(
|
|
desc="Lavalink.jar",
|
|
total=response.content_length,
|
|
file=sys.stdout,
|
|
unit="B",
|
|
unit_scale=True,
|
|
miniters=1,
|
|
dynamic_ncols=True,
|
|
leave=False,
|
|
) as progress_bar:
|
|
try:
|
|
chunk = await response.content.read(1024)
|
|
while chunk:
|
|
chunk_size = file.write(chunk)
|
|
nbytes += chunk_size
|
|
progress_bar.update(chunk_size)
|
|
chunk = await response.content.read(1024)
|
|
file.flush()
|
|
finally:
|
|
file.close()
|
|
|
|
shutil.move(path, str(LAVALINK_JAR_FILE), copy_function=shutil.copyfile)
|
|
|
|
log.info("Successfully downloaded Lavalink.jar (%s bytes written)", format(nbytes, ","))
|
|
|
|
@classmethod
|
|
async def _is_up_to_date(cls):
|
|
if cls._up_to_date is True:
|
|
# Return cached value if we've checked this before
|
|
return True
|
|
args = await cls._get_jar_args()
|
|
args.append("--version")
|
|
_proc = await asyncio.subprocess.create_subprocess_exec( # pylint:disable=no-member
|
|
*args,
|
|
cwd=str(LAVALINK_DOWNLOAD_DIR),
|
|
stdout=asyncio.subprocess.PIPE,
|
|
stderr=asyncio.subprocess.STDOUT,
|
|
)
|
|
stdout = (await _proc.communicate())[0]
|
|
match = BUILD_LINE_RE.search(stdout)
|
|
if not match:
|
|
# Output is unexpected, suspect corrupted jarfile
|
|
return False
|
|
build = int(match["build"])
|
|
cls._up_to_date = build >= JAR_BUILD
|
|
return cls._up_to_date
|
|
|
|
@classmethod
|
|
async def maybe_download_jar(cls):
|
|
if not (LAVALINK_JAR_FILE.exists() and await cls._is_up_to_date()):
|
|
await cls._download_jar()
|