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>
426 lines
12 KiB
Python
426 lines
12 KiB
Python
import asyncio
|
|
import contextlib
|
|
import os
|
|
import re
|
|
import time
|
|
from typing import NoReturn
|
|
from urllib.parse import urlparse
|
|
|
|
import discord
|
|
import lavalink
|
|
|
|
from redbot.core import Config, commands
|
|
from redbot.core.bot import Red
|
|
from . import dataclasses
|
|
|
|
from .converters import _pass_config_to_converters
|
|
|
|
from .playlists import _pass_config_to_playlist
|
|
|
|
__all__ = [
|
|
"pass_config_to_dependencies",
|
|
"track_limit",
|
|
"queue_duration",
|
|
"draw_time",
|
|
"dynamic_time",
|
|
"match_url",
|
|
"clear_react",
|
|
"match_yt_playlist",
|
|
"remove_react",
|
|
"get_description",
|
|
"track_creator",
|
|
"time_convert",
|
|
"url_check",
|
|
"userlimit",
|
|
"is_allowed",
|
|
"CacheLevel",
|
|
"Notifier",
|
|
]
|
|
_re_time_converter = re.compile(r"(?:(\d+):)?([0-5]?[0-9]):([0-5][0-9])")
|
|
re_yt_list_playlist = re.compile(
|
|
r"^(https?://)?(www\.)?(youtube\.com|youtu\.?be)(/playlist\?).*(list=)(.*)(&|$)"
|
|
)
|
|
|
|
_config = None
|
|
_bot = None
|
|
|
|
|
|
def pass_config_to_dependencies(config: Config, bot: Red, localtracks_folder: str):
|
|
global _bot, _config
|
|
_bot = bot
|
|
_config = config
|
|
_pass_config_to_playlist(config, bot)
|
|
_pass_config_to_converters(config, bot)
|
|
dataclasses._pass_config_to_dataclasses(config, bot, localtracks_folder)
|
|
|
|
|
|
def track_limit(track, maxlength):
|
|
try:
|
|
length = round(track.length / 1000)
|
|
except AttributeError:
|
|
length = round(track / 1000)
|
|
|
|
if maxlength < length <= 900000000000000: # livestreams return 9223372036854775807ms
|
|
return False
|
|
return True
|
|
|
|
|
|
async def is_allowed(guild: discord.Guild, query: str):
|
|
query = query.lower().strip()
|
|
whitelist = set(await _config.guild(guild).url_keyword_whitelist())
|
|
if whitelist:
|
|
return any(i in query for i in whitelist)
|
|
blacklist = set(await _config.guild(guild).url_keyword_blacklist())
|
|
return not any(i in query for i in blacklist)
|
|
|
|
|
|
async def queue_duration(ctx):
|
|
player = lavalink.get_player(ctx.guild.id)
|
|
duration = []
|
|
for i in range(len(player.queue)):
|
|
if not player.queue[i].is_stream:
|
|
duration.append(player.queue[i].length)
|
|
queue_dur = sum(duration)
|
|
if not player.queue:
|
|
queue_dur = 0
|
|
try:
|
|
if not player.current.is_stream:
|
|
remain = player.current.length - player.position
|
|
else:
|
|
remain = 0
|
|
except AttributeError:
|
|
remain = 0
|
|
queue_total_duration = remain + queue_dur
|
|
return queue_total_duration
|
|
|
|
|
|
async def draw_time(ctx):
|
|
player = lavalink.get_player(ctx.guild.id)
|
|
paused = player.paused
|
|
pos = player.position
|
|
dur = player.current.length
|
|
sections = 12
|
|
loc_time = round((pos / dur) * sections)
|
|
bar = "\N{BOX DRAWINGS HEAVY HORIZONTAL}"
|
|
seek = "\N{RADIO BUTTON}"
|
|
if paused:
|
|
msg = "\N{DOUBLE VERTICAL BAR}"
|
|
else:
|
|
msg = "\N{BLACK RIGHT-POINTING TRIANGLE}"
|
|
for i in range(sections):
|
|
if i == loc_time:
|
|
msg += seek
|
|
else:
|
|
msg += bar
|
|
return msg
|
|
|
|
|
|
def dynamic_time(seconds):
|
|
m, s = divmod(seconds, 60)
|
|
h, m = divmod(m, 60)
|
|
d, h = divmod(h, 24)
|
|
|
|
if d > 0:
|
|
msg = "{0}d {1}h"
|
|
elif d == 0 and h > 0:
|
|
msg = "{1}h {2}m"
|
|
elif d == 0 and h == 0 and m > 0:
|
|
msg = "{2}m {3}s"
|
|
elif d == 0 and h == 0 and m == 0 and s > 0:
|
|
msg = "{3}s"
|
|
else:
|
|
msg = ""
|
|
return msg.format(d, h, m, s)
|
|
|
|
|
|
def match_url(url):
|
|
try:
|
|
query_url = urlparse(url)
|
|
return all([query_url.scheme, query_url.netloc, query_url.path])
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def match_yt_playlist(url):
|
|
if re_yt_list_playlist.match(url):
|
|
return True
|
|
return False
|
|
|
|
|
|
async def remove_react(message, react_emoji, react_user):
|
|
with contextlib.suppress(discord.HTTPException):
|
|
await message.remove_reaction(react_emoji, react_user)
|
|
|
|
|
|
async def clear_react(bot: Red, message: discord.Message, emoji: dict = None):
|
|
try:
|
|
await message.clear_reactions()
|
|
except discord.Forbidden:
|
|
if not emoji:
|
|
return
|
|
with contextlib.suppress(discord.HTTPException):
|
|
for key in emoji.values():
|
|
await asyncio.sleep(0.2)
|
|
await message.remove_reaction(key, bot.user)
|
|
except discord.HTTPException:
|
|
return
|
|
|
|
|
|
async def get_description(track):
|
|
if any(x in track.uri for x in [f"{os.sep}localtracks", f"localtracks{os.sep}"]):
|
|
local_track = dataclasses.LocalPath(track.uri)
|
|
if track.title != "Unknown title":
|
|
return "**{} - {}**\n{}".format(
|
|
track.author, track.title, local_track.to_string_hidden()
|
|
)
|
|
else:
|
|
return local_track.to_string_hidden()
|
|
else:
|
|
return "**[{}]({})**".format(track.title, track.uri)
|
|
|
|
|
|
def track_creator(player, position=None, other_track=None):
|
|
if position == "np":
|
|
queued_track = player.current
|
|
elif position is None:
|
|
queued_track = other_track
|
|
else:
|
|
queued_track = player.queue[position]
|
|
track_keys = queued_track._info.keys()
|
|
track_values = queued_track._info.values()
|
|
track_id = queued_track.track_identifier
|
|
track_info = {}
|
|
for k, v in zip(track_keys, track_values):
|
|
track_info[k] = v
|
|
keys = ["track", "info"]
|
|
values = [track_id, track_info]
|
|
track_obj = {}
|
|
for key, value in zip(keys, values):
|
|
track_obj[key] = value
|
|
return track_obj
|
|
|
|
|
|
def time_convert(length):
|
|
match = re.compile(_re_time_converter).match(length)
|
|
if match is not None:
|
|
hr = int(match.group(1)) if match.group(1) else 0
|
|
mn = int(match.group(2)) if match.group(2) else 0
|
|
sec = int(match.group(3)) if match.group(3) else 0
|
|
pos = sec + (mn * 60) + (hr * 3600)
|
|
return pos
|
|
else:
|
|
try:
|
|
return int(length)
|
|
except ValueError:
|
|
return 0
|
|
|
|
|
|
def url_check(url):
|
|
valid_tld = [
|
|
"youtube.com",
|
|
"youtu.be",
|
|
"soundcloud.com",
|
|
"bandcamp.com",
|
|
"vimeo.com",
|
|
"beam.pro",
|
|
"mixer.com",
|
|
"twitch.tv",
|
|
"spotify.com",
|
|
"localtracks",
|
|
]
|
|
query_url = urlparse(url)
|
|
url_domain = ".".join(query_url.netloc.split(".")[-2:])
|
|
if not query_url.netloc:
|
|
url_domain = ".".join(query_url.path.split("/")[0].split(".")[-2:])
|
|
return True if url_domain in valid_tld else False
|
|
|
|
|
|
def userlimit(channel):
|
|
if channel.user_limit == 0 or channel.user_limit > len(channel.members) + 1:
|
|
return False
|
|
return True
|
|
|
|
|
|
class CacheLevel:
|
|
__slots__ = ("value",)
|
|
|
|
def __init__(self, level=0):
|
|
if not isinstance(level, int):
|
|
raise TypeError(
|
|
f"Expected int parameter, received {level.__class__.__name__} instead."
|
|
)
|
|
elif level < 0:
|
|
level = 0
|
|
elif level > 0b11111:
|
|
level = 0b11111
|
|
|
|
self.value = level
|
|
|
|
def __eq__(self, other):
|
|
return isinstance(other, CacheLevel) and self.value == other.value
|
|
|
|
def __ne__(self, other):
|
|
return not self.__eq__(other)
|
|
|
|
def __hash__(self):
|
|
return hash(self.value)
|
|
|
|
def __add__(self, other):
|
|
return CacheLevel(self.value + other.value)
|
|
|
|
def __radd__(self, other):
|
|
return CacheLevel(other.value + self.value)
|
|
|
|
def __sub__(self, other):
|
|
return CacheLevel(self.value - other.value)
|
|
|
|
def __rsub__(self, other):
|
|
return CacheLevel(other.value - self.value)
|
|
|
|
def __str__(self):
|
|
return "{0:b}".format(self.value)
|
|
|
|
def __format__(self, format_spec):
|
|
return "{r:{f}}".format(r=self.value, f=format_spec)
|
|
|
|
def __repr__(self):
|
|
return f"<CacheLevel value={self.value}>"
|
|
|
|
def is_subset(self, other):
|
|
"""Returns ``True`` if self has the same or fewer caching levels as other."""
|
|
return (self.value & other.value) == self.value
|
|
|
|
def is_superset(self, other):
|
|
"""Returns ``True`` if self has the same or more caching levels as other."""
|
|
return (self.value | other.value) == self.value
|
|
|
|
def is_strict_subset(self, other):
|
|
"""Returns ``True`` if the caching level on other are a strict subset of those on self."""
|
|
return self.is_subset(other) and self != other
|
|
|
|
def is_strict_superset(self, other):
|
|
"""Returns ``True`` if the caching level on
|
|
other are a strict superset of those on self."""
|
|
return self.is_superset(other) and self != other
|
|
|
|
__le__ = is_subset
|
|
__ge__ = is_superset
|
|
__lt__ = is_strict_subset
|
|
__gt__ = is_strict_superset
|
|
|
|
@classmethod
|
|
def all(cls):
|
|
"""A factory method that creates a :class:`CacheLevel` with max caching level."""
|
|
return cls(0b11111)
|
|
|
|
@classmethod
|
|
def none(cls):
|
|
"""A factory method that creates a :class:`CacheLevel` with no caching."""
|
|
return cls(0)
|
|
|
|
@classmethod
|
|
def set_spotify(cls):
|
|
"""A factory method that creates a :class:`CacheLevel` with Spotify caching level."""
|
|
return cls(0b00011)
|
|
|
|
@classmethod
|
|
def set_youtube(cls):
|
|
"""A factory method that creates a :class:`CacheLevel` with YouTube caching level."""
|
|
return cls(0b00100)
|
|
|
|
@classmethod
|
|
def set_lavalink(cls):
|
|
"""A factory method that creates a :class:`CacheLevel` with lavalink caching level."""
|
|
return cls(0b11000)
|
|
|
|
def _bit(self, index):
|
|
return bool((self.value >> index) & 1)
|
|
|
|
def _set(self, index, value):
|
|
if value is True:
|
|
self.value |= 1 << index
|
|
elif value is False:
|
|
self.value &= ~(1 << index)
|
|
else:
|
|
raise TypeError("Value to set for CacheLevel must be a bool.")
|
|
|
|
@property
|
|
def lavalink(self):
|
|
""":class:`bool`: Returns ``True`` if a user can deafen other users."""
|
|
return self._bit(4)
|
|
|
|
@lavalink.setter
|
|
def lavalink(self, value):
|
|
self._set(4, value)
|
|
|
|
@property
|
|
def youtube(self):
|
|
""":class:`bool`: Returns ``True`` if a user can move users between other voice
|
|
channels."""
|
|
return self._bit(2)
|
|
|
|
@youtube.setter
|
|
def youtube(self, value):
|
|
self._set(2, value)
|
|
|
|
@property
|
|
def spotify(self):
|
|
""":class:`bool`: Returns ``True`` if a user can use voice activation in voice channels."""
|
|
return self._bit(1)
|
|
|
|
@spotify.setter
|
|
def spotify(self, value):
|
|
self._set(1, value)
|
|
|
|
|
|
class Notifier:
|
|
def __init__(self, ctx: commands.Context, message: discord.Message, updates: dict, **kwargs):
|
|
self.context = ctx
|
|
self.message = message
|
|
self.updates = updates
|
|
self.color = None
|
|
self.last_msg_time = 0
|
|
self.cooldown = 5
|
|
|
|
async def notify_user(
|
|
self,
|
|
current: int = None,
|
|
total: int = None,
|
|
key: str = None,
|
|
seconds_key: str = None,
|
|
seconds: str = None,
|
|
) -> NoReturn:
|
|
"""
|
|
This updates an existing message.
|
|
Based on the message found in :variable:`Notifier.updates` as per the `key` param
|
|
"""
|
|
if self.last_msg_time + self.cooldown > time.time() and not current == total:
|
|
return
|
|
if self.color is None:
|
|
self.color = await self.context.embed_colour()
|
|
embed2 = discord.Embed(
|
|
colour=self.color,
|
|
title=self.updates.get(key).format(num=current, total=total, seconds=seconds),
|
|
)
|
|
if seconds and seconds_key:
|
|
embed2.set_footer(text=self.updates.get(seconds_key).format(seconds=seconds))
|
|
try:
|
|
await self.message.edit(embed=embed2)
|
|
self.last_msg_time = time.time()
|
|
except discord.errors.NotFound:
|
|
pass
|
|
|
|
async def update_text(self, text: str) -> NoReturn:
|
|
embed2 = discord.Embed(colour=self.color, title=text)
|
|
try:
|
|
await self.message.edit(embed=embed2)
|
|
except discord.errors.NotFound:
|
|
pass
|
|
|
|
async def update_embed(self, embed: discord.Embed) -> NoReturn:
|
|
try:
|
|
await self.message.edit(embed=embed)
|
|
self.last_msg_time = time.time()
|
|
except discord.errors.NotFound:
|
|
pass
|