mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -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>
429 lines
13 KiB
Python
429 lines
13 KiB
Python
from collections import namedtuple
|
|
from enum import Enum, unique
|
|
from typing import List, Optional, Union
|
|
|
|
import discord
|
|
import lavalink
|
|
|
|
from redbot.core import Config, commands
|
|
from redbot.core.bot import Red
|
|
from redbot.core.i18n import Translator
|
|
from redbot.core.utils.chat_formatting import humanize_list
|
|
from .errors import InvalidPlaylistScope, MissingAuthor, MissingGuild, NotAllowed
|
|
|
|
_config = None
|
|
_bot = None
|
|
|
|
__all__ = [
|
|
"Playlist",
|
|
"PlaylistScope",
|
|
"get_playlist",
|
|
"get_all_playlist",
|
|
"create_playlist",
|
|
"reset_playlist",
|
|
"delete_playlist",
|
|
"humanize_scope",
|
|
"standardize_scope",
|
|
"FakePlaylist",
|
|
]
|
|
|
|
FakePlaylist = namedtuple("Playlist", "author scope")
|
|
|
|
_ = Translator("Audio", __file__)
|
|
|
|
|
|
@unique
|
|
class PlaylistScope(Enum):
|
|
GLOBAL = "GLOBALPLAYLIST"
|
|
GUILD = "GUILDPLAYLIST"
|
|
USER = "USERPLAYLIST"
|
|
|
|
def __str__(self):
|
|
return "{0}".format(self.value)
|
|
|
|
@staticmethod
|
|
def list():
|
|
return list(map(lambda c: c.value, PlaylistScope))
|
|
|
|
|
|
def _pass_config_to_playlist(config: Config, bot: Red):
|
|
global _config, _bot
|
|
if _config is None:
|
|
_config = config
|
|
if _bot is None:
|
|
_bot = bot
|
|
|
|
|
|
def standardize_scope(scope) -> str:
|
|
scope = scope.upper()
|
|
valid_scopes = ["GLOBAL", "GUILD", "AUTHOR", "USER", "SERVER", "MEMBER", "BOT"]
|
|
|
|
if scope in PlaylistScope.list():
|
|
return scope
|
|
elif scope not in valid_scopes:
|
|
raise InvalidPlaylistScope(
|
|
f'"{scope}" is not a valid playlist scope.'
|
|
f" Scope needs to be one of the following: {humanize_list(valid_scopes)}"
|
|
)
|
|
|
|
if scope in ["GLOBAL", "BOT"]:
|
|
scope = PlaylistScope.GLOBAL.value
|
|
elif scope in ["GUILD", "SERVER"]:
|
|
scope = PlaylistScope.GUILD.value
|
|
elif scope in ["USER", "MEMBER", "AUTHOR"]:
|
|
scope = PlaylistScope.USER.value
|
|
|
|
return scope
|
|
|
|
|
|
def humanize_scope(scope, ctx=None, the=None):
|
|
|
|
if scope == PlaylistScope.GLOBAL.value:
|
|
return ctx or _("the ") if the else "" + "Global"
|
|
elif scope == PlaylistScope.GUILD.value:
|
|
return ctx.name if ctx else _("the ") if the else "" + "Server"
|
|
elif scope == PlaylistScope.USER.value:
|
|
return str(ctx) if ctx else _("the ") if the else "" + "User"
|
|
|
|
|
|
def _prepare_config_scope(
|
|
scope, author: Union[discord.abc.User, int] = None, guild: discord.Guild = None
|
|
):
|
|
scope = standardize_scope(scope)
|
|
|
|
if scope == PlaylistScope.GLOBAL.value:
|
|
config_scope = [PlaylistScope.GLOBAL.value]
|
|
elif scope == PlaylistScope.USER.value:
|
|
if author is None:
|
|
raise MissingAuthor("Invalid author for user scope.")
|
|
config_scope = [PlaylistScope.USER.value, str(getattr(author, "id", author))]
|
|
else:
|
|
if guild is None:
|
|
raise MissingGuild("Invalid guild for guild scope.")
|
|
config_scope = [PlaylistScope.GUILD.value, str(getattr(guild, "id", guild))]
|
|
return config_scope
|
|
|
|
|
|
class Playlist:
|
|
"""A single playlist."""
|
|
|
|
def __init__(
|
|
self,
|
|
bot: Red,
|
|
scope: str,
|
|
author: int,
|
|
playlist_id: int,
|
|
name: str,
|
|
playlist_url: Optional[str] = None,
|
|
tracks: Optional[List[dict]] = None,
|
|
guild: Union[discord.Guild, int, None] = None,
|
|
):
|
|
self.bot = bot
|
|
self.guild = guild
|
|
self.scope = standardize_scope(scope)
|
|
self.config_scope = _prepare_config_scope(self.scope, author, guild)
|
|
self.author = author
|
|
self.guild_id = (
|
|
getattr(guild, "id", guild) if self.scope == PlaylistScope.GLOBAL.value else None
|
|
)
|
|
self.id = playlist_id
|
|
self.name = name
|
|
self.url = playlist_url
|
|
self.tracks = tracks or []
|
|
self.tracks_obj = [lavalink.Track(data=track) for track in self.tracks]
|
|
|
|
async def edit(self, data: dict):
|
|
"""
|
|
Edits a Playlist.
|
|
Parameters
|
|
----------
|
|
data: dict
|
|
The attributes to change.
|
|
"""
|
|
# Disallow ID editing
|
|
if "id" in data:
|
|
raise NotAllowed("Playlist ID cannot be edited.")
|
|
|
|
for item in list(data.keys()):
|
|
setattr(self, item, data[item])
|
|
|
|
await _config.custom(*self.config_scope, str(self.id)).set(self.to_json())
|
|
|
|
def to_json(self) -> dict:
|
|
"""Transform the object to a dict.
|
|
Returns
|
|
-------
|
|
dict
|
|
The playlist in the form of a dict.
|
|
"""
|
|
data = dict(
|
|
id=self.id,
|
|
author=self.author,
|
|
guild=self.guild_id,
|
|
name=self.name,
|
|
playlist_url=self.url,
|
|
tracks=self.tracks,
|
|
)
|
|
|
|
return data
|
|
|
|
@classmethod
|
|
async def from_json(cls, bot: Red, scope: str, playlist_number: int, data: dict, **kwargs):
|
|
"""Get a Playlist object from the provided information.
|
|
Parameters
|
|
----------
|
|
bot: Red
|
|
The bot's instance. Needed to get the target user.
|
|
scope:str
|
|
The custom config scope. One of 'GLOBALPLAYLIST', 'GUILDPLAYLIST' or 'USERPLAYLIST'.
|
|
playlist_number: int
|
|
The playlist's number.
|
|
data: dict
|
|
The JSON representation of the playlist to be gotten.
|
|
**kwargs
|
|
Extra attributes for the Playlist instance which override values
|
|
in the data dict. These should be complete objects and not
|
|
IDs, where possible.
|
|
Returns
|
|
-------
|
|
Playlist
|
|
The playlist object for the requested playlist.
|
|
Raises
|
|
------
|
|
`InvalidPlaylistScope`
|
|
Passing a scope that is not supported.
|
|
`MissingGuild`
|
|
Trying to access the Guild scope without a guild.
|
|
`MissingAuthor`
|
|
Trying to access the User scope without an user id.
|
|
"""
|
|
guild = data.get("guild") or kwargs.get("guild")
|
|
author = data.get("author")
|
|
playlist_id = data.get("id") or playlist_number
|
|
name = data.get("name", "Unnamed")
|
|
playlist_url = data.get("playlist_url", None)
|
|
tracks = data.get("tracks", [])
|
|
|
|
return cls(
|
|
bot=bot,
|
|
guild=guild,
|
|
scope=scope,
|
|
author=author,
|
|
playlist_id=playlist_id,
|
|
name=name,
|
|
playlist_url=playlist_url,
|
|
tracks=tracks,
|
|
)
|
|
|
|
|
|
async def get_playlist(
|
|
playlist_number: int,
|
|
scope: str,
|
|
bot: Red,
|
|
guild: Union[discord.Guild, int] = None,
|
|
author: Union[discord.abc.User, int] = None,
|
|
) -> Playlist:
|
|
"""
|
|
Gets the playlist with the associated playlist number.
|
|
Parameters
|
|
----------
|
|
playlist_number: int
|
|
The playlist number for the playlist to get.
|
|
scope: str
|
|
The custom config scope. One of 'GLOBALPLAYLIST', 'GUILDPLAYLIST' or 'USERPLAYLIST'.
|
|
guild: discord.Guild
|
|
The guild to get the playlist from if scope is GUILDPLAYLIST.
|
|
author: int
|
|
The ID of the user to get the playlist from if scope is USERPLAYLIST.
|
|
bot: Red
|
|
The bot's instance.
|
|
Returns
|
|
-------
|
|
Playlist
|
|
The playlist associated with the playlist number.
|
|
Raises
|
|
------
|
|
`RuntimeError`
|
|
If there is no playlist for the specified number.
|
|
`InvalidPlaylistScope`
|
|
Passing a scope that is not supported.
|
|
`MissingGuild`
|
|
Trying to access the Guild scope without a guild.
|
|
`MissingAuthor`
|
|
Trying to access the User scope without an user id.
|
|
"""
|
|
playlist_data = await _config.custom(
|
|
*_prepare_config_scope(scope, author, guild), str(playlist_number)
|
|
).all()
|
|
if not playlist_data["id"]:
|
|
raise RuntimeError(f"That playlist does not exist for the following scope: {scope}")
|
|
return await Playlist.from_json(
|
|
bot, scope, playlist_number, playlist_data, guild=guild, author=author
|
|
)
|
|
|
|
|
|
async def get_all_playlist(
|
|
scope: str,
|
|
bot: Red,
|
|
guild: Union[discord.Guild, int] = None,
|
|
author: Union[discord.abc.User, int] = None,
|
|
specified_user: bool = False,
|
|
) -> List[Playlist]:
|
|
"""
|
|
Gets all playlist for the specified scope.
|
|
Parameters
|
|
----------
|
|
scope: str
|
|
The custom config scope. One of 'GLOBALPLAYLIST', 'GUILDPLAYLIST' or 'USERPLAYLIST'.
|
|
guild: discord.Guild
|
|
The guild to get the playlist from if scope is GUILDPLAYLIST.
|
|
author: int
|
|
The ID of the user to get the playlist from if scope is USERPLAYLIST.
|
|
bot: Red
|
|
The bot's instance
|
|
specified_user:bool
|
|
Whether or not user ID was passed as an argparse.
|
|
Returns
|
|
-------
|
|
list
|
|
A list of all playlists for the specified scope
|
|
Raises
|
|
------
|
|
`InvalidPlaylistScope`
|
|
Passing a scope that is not supported.
|
|
`MissingGuild`
|
|
Trying to access the Guild scope without a guild.
|
|
`MissingAuthor`
|
|
Trying to access the User scope without an user id.
|
|
"""
|
|
playlists = await _config.custom(*_prepare_config_scope(scope, author, guild)).all()
|
|
if specified_user:
|
|
user_id = getattr(author, "id", author)
|
|
return [
|
|
await Playlist.from_json(
|
|
bot, scope, playlist_number, playlist_data, guild=guild, author=author
|
|
)
|
|
for playlist_number, playlist_data in playlists.items()
|
|
if user_id == playlist_data.get("author")
|
|
]
|
|
else:
|
|
return [
|
|
await Playlist.from_json(
|
|
bot, scope, playlist_number, playlist_data, guild=guild, author=author
|
|
)
|
|
for playlist_number, playlist_data in playlists.items()
|
|
]
|
|
|
|
|
|
async def create_playlist(
|
|
ctx: commands.Context,
|
|
scope: str,
|
|
playlist_name: str,
|
|
playlist_url: Optional[str] = None,
|
|
tracks: Optional[List[dict]] = None,
|
|
author: Optional[discord.User] = None,
|
|
guild: Optional[discord.Guild] = None,
|
|
) -> Optional[Playlist]:
|
|
"""
|
|
Creates a new Playlist.
|
|
|
|
Parameters
|
|
----------
|
|
ctx: commands.Context
|
|
The context in which the play list is being created.
|
|
scope: str
|
|
The custom config scope. One of 'GLOBALPLAYLIST', 'GUILDPLAYLIST' or 'USERPLAYLIST'.
|
|
playlist_name: str
|
|
The name of the new playlist.
|
|
playlist_url:str
|
|
the url of the new playlist.
|
|
tracks: List[dict]
|
|
A list of tracks to add to the playlist.
|
|
author: discord.User
|
|
The Author of the playlist.
|
|
If provided it will create a playlist under this user.
|
|
This is only required when creating a playlist in User scope.
|
|
guild: discord.Guild
|
|
The guild to create this playlist under.
|
|
This is only used when creating a playlist in the Guild scope
|
|
|
|
Raises
|
|
------
|
|
`InvalidPlaylistScope`
|
|
Passing a scope that is not supported.
|
|
`MissingGuild`
|
|
Trying to access the Guild scope without a guild.
|
|
`MissingAuthor`
|
|
Trying to access the User scope without an user id.
|
|
"""
|
|
|
|
playlist = Playlist(
|
|
ctx.bot, scope, author.id, ctx.message.id, playlist_name, playlist_url, tracks, ctx.guild
|
|
)
|
|
|
|
await _config.custom(*_prepare_config_scope(scope, author, guild), str(ctx.message.id)).set(
|
|
playlist.to_json()
|
|
)
|
|
return playlist
|
|
|
|
|
|
async def reset_playlist(
|
|
scope: str,
|
|
guild: Union[discord.Guild, int] = None,
|
|
author: Union[discord.abc.User, int] = None,
|
|
) -> None:
|
|
"""
|
|
Wipes all playlists for the specified scope.
|
|
|
|
Parameters
|
|
----------
|
|
scope: str
|
|
The custom config scope. One of 'GLOBALPLAYLIST', 'GUILDPLAYLIST' or 'USERPLAYLIST'.
|
|
guild: discord.Guild
|
|
The guild to get the playlist from if scope is GUILDPLAYLIST.
|
|
author: int
|
|
The ID of the user to get the playlist from if scope is USERPLAYLIST.
|
|
|
|
Raises
|
|
------
|
|
`InvalidPlaylistScope`
|
|
Passing a scope that is not supported.
|
|
`MissingGuild`
|
|
Trying to access the Guild scope without a guild.
|
|
`MissingAuthor`
|
|
Trying to access the User scope without an user id.
|
|
"""
|
|
await _config.custom(*_prepare_config_scope(scope, author, guild)).clear()
|
|
|
|
|
|
async def delete_playlist(
|
|
scope: str,
|
|
playlist_id: Union[str, int],
|
|
guild: discord.Guild,
|
|
author: Union[discord.abc.User, int] = None,
|
|
) -> None:
|
|
"""
|
|
Deletes the specified playlist.
|
|
|
|
Parameters
|
|
----------
|
|
scope: str
|
|
The custom config scope. One of 'GLOBALPLAYLIST', 'GUILDPLAYLIST' or 'USERPLAYLIST'.
|
|
playlist_id: Union[str, int]
|
|
The ID of the playlist.
|
|
guild: discord.Guild
|
|
The guild to get the playlist from if scope is GUILDPLAYLIST.
|
|
author: int
|
|
The ID of the user to get the playlist from if scope is USERPLAYLIST.
|
|
|
|
Raises
|
|
------
|
|
`InvalidPlaylistScope`
|
|
Passing a scope that is not supported.
|
|
`MissingGuild`
|
|
Trying to access the Guild scope without a guild.
|
|
`MissingAuthor`
|
|
Trying to access the User scope without an user id.
|
|
"""
|
|
await _config.custom(*_prepare_config_scope(scope, author, guild), str(playlist_id)).clear()
|