mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-23 11:13:51 -05:00
[3.2][Audio] Part 6 (Last? maybe?) (#3244)
* Removes `MAX_BALANCE` from bank, user `bank.get_max_balance()` now `[p]bankset maxbal` can be used to set the maximum bank balance Signed-off-by: Guy <guyreis96@gmail.com> * Initial Commit Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com> * I need to make sure I keep aika on her toes. Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com> * Fixes a few missing kwargs and case consistency Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com> * Fixes a few missing kwargs and case consistency v2 and typos Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com> * Reset cooldowns + add changelogs Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com> * Add 3 extra file formats. Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com> * IRDUMB - fix capitalization. Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com> * Fix a silent error, and some incorrect messages. Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com> * Remove unnecessary emojis from queue when they are not needed Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com> * Remove duplicated call in `[p]playlist update` Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com> * Remove duplicated call in `[p]playlist update` Signed-off-by: guyre <27962761+drapersniper@users.noreply.github.com> * Resolve conflicts Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com> * Bring all files up to date + Black Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com> * Facepalm Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com> * *Sigh* Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com> * *Sigh* 2.0 Signed-off-by: Draper <27962761+Drapersniper@users.noreply.github.com> * Merge branch 'V3/develop' of https://github.com/Cog-Creators/Red-DiscordBot into audio-misc-pt1 Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> # Resolve Conflicts: # redbot/cogs/audio/audio.py # redbot/cogs/audio/utils.py * Import missing Typecheck Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Fix Broken docstrings Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Sort Local Tracks Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * 🤦 Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Reorder the sorting of local tracks, `alphanumerical lower then alphanumerical upper` `a comes before A, but B comes after A` Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Black formatting Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Make the local file sorting case insensitive Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Add global blacklist/whitelist + fix some issues with original server based whitelist/blacklist Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Remove the pre-commit yaml Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Nottin to see Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Further improvement to the blacklists Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Further improvement to the blacklists Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Fix the __str__ method on LocalTracks Object * Rename LocalTracks.to_string_hidden() to LocalTracks.to_string_user() To keep it inline with the Query object * Remove encoding pragmas + a few typo fixes * Update some typehints + fix some typos * Remove this duplicate call * Black * fix capitalization * Address preda's review Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Remove the API from the audio cog - Is in direct conflict with goals stated in #2804 - Features this was intended to enable can be enabled in other more appropriate ways later on * changelog * Address Aika's review * Black * *sigh* dont use github web ui * Fuck windows Long live linux... *sigh* no lets ensure windows users can still use local tracks * Merge branch 'V3/develop' of https://github.com/Cog-Creators/Red-DiscordBot into refactoring Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> # Conflicts: # redbot/cogs/audio/audio.py * 👀 + chore Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * facepalm Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * facepalm... again y u h8 me bruh Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * fuk this fuk u tube fuck python fuck all Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * awyehfqwajefhnqeffawefqa eqewarfqaesf qwef qaf qwfr Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * fuck everything Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * oh lord saviour resus i love you just make this work Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Change logic to be no errors within last 10 seconds... this should be a valid work around discord ratelimits caused by the spam * Remove auto deletion Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * See I did a ting Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * irdumb Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * black Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Add an is_url attribute to Query objects * chore Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Black * Address Aikas review Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Hyperlink Playlist names Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Make shit bold Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * why was this here Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * why was this here Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Initial commit * Workinnng Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Improve SQL Statements + migrate from SQL Alchemy + Databases to APSW Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * apsw tested and working Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * chose Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Migrate Playlist to DB 3 TODO 1 Migrate Config to Schema 3 without playlists and update get_playlist methods Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Revert "Migrate Playlist to DB 3 TODO 1 Migrate Config to Schema 3 without playlists and update get_playlist methods" This reverts commit4af33cffSigned-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Implement schema migration * Lets not touch the deps since #3192 is already adding them * chore * *sigh* Black * Follow the existing logic and always default Playlist to guild scope * wghqjegqf black * Update usage of last_fetched and last_updated to be Ints... However column migration still pending * Some bug fixes * Update usage of last_fetched and last_updated to be Ints... However column migration still pending * working Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * partial match Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * better partial match Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * black Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * I thought i done this before * Delete 3195.misc.1.rst Wrong PR * Thanks Sinbad Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Thanks Sinbad Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Log Errors in init ... Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Update error logs. Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Create index Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * :Drapersweat: Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Chore Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Revert "Chore" This reverts commitedcc9a9fUGHHHH Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Allow removing tracks from queue by URL Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Words matter Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * *sigh* Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * chore Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * arghhh CONFLICTS Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Review sinbads latest comment .. ToDo.. Nuke existing playlist - check version and set version Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * migrate the DB schema to v3 (to keep in line with the schema visioning of Config * Add a Todo * *sigh* conflicts and black * *sigh* black * Passively delete playlist deletion mechanism * Delete Old entries on startup * Since we are dropping the table mightaware make these into JSON for future proofing * Don't Dump strings in JSON field ? :think: * Move some things around to make easier to use 1 connection to the Audio DB * Move some things around to make easier to use 1 connection to the Audio DB * *sigh* * Clean up api * *sigh* black * Red + reorder some variables * 🤦 * how could i forget this ....... * Black Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Black Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Black Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * #automagically Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * FINAFUCKINGLY Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * FINAFUCKINGLY Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Remove unused config default Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Remove the API from the audio Cog (Properly) Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Missed these changes Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * ARGHHH Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Some fixes I've noticed while running through the code line by line Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Translation + UX (show playlist author ID if can't find user) Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * *sigh* missed this one Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * this is no longer needed .... Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * 🤦 Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * fix new lines in error messages Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Black * Sinbads Review Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Sinbads Review Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * *sigh* copy paste Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * imrpove backups Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Im a fucking idiot Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Fix #3238 Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * chore Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * humans Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * humans Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * add play alias to playlists Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Im dumb ... Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Im dumb ... Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * fix new line Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * fix new line Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * show playlist count on playlist picker Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * DJ/Vote system fixes Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * DJ/Vote system fixes Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * *sigh* fix currency check Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * show playlist count on playlist picker Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * DJ/Vote system fixes Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * DJ/Vote system fixes Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * *sigh* fix currency check Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Fix duplicate messages on timeout Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * fix SQL Statement logic Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * fix SQL Statement logic Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Markdown escape Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Markdown escape Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Markdown escape fix Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Markdown escape fix Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * clean up local cache more frequently Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * clean up db more frequently Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Await in hell Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * *sigh* im dumb Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * *sigh* im dumb Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Black cuz I hate red Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Black cuz I hate red Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * StringIO to ByteIO Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * StringIO to ByteIO Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * *sigh* im dumb Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * :Facepalm: the whole purpose of this is so its offline so this can be backed up without being blocking Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Run write queries on ThreadPoolExecutor Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Backup Audio.db Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * *sigh* im dumb Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * blaaaack Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * *sigh* Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * formatting Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * remove duplicated string of code Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * ffs awaits Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> Co-authored-by: Michael H <michael@michaelhall.tech>
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
from collections import namedtuple
|
||||
from enum import Enum, unique
|
||||
from typing import List, Optional, Union
|
||||
from typing import List, MutableMapping, Optional, Union, TYPE_CHECKING
|
||||
|
||||
import discord
|
||||
import lavalink
|
||||
@@ -9,22 +8,33 @@ 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
|
||||
from .databases import PlaylistFetchResult, PlaylistInterface
|
||||
from .errors import InvalidPlaylistScope, MissingAuthor, MissingGuild, NotAllowed
|
||||
from .utils import PlaylistScope
|
||||
|
||||
if TYPE_CHECKING:
|
||||
database: PlaylistInterface
|
||||
_bot: Red
|
||||
_config: Config
|
||||
else:
|
||||
database = None
|
||||
_bot = None
|
||||
_config = None
|
||||
|
||||
__all__ = [
|
||||
"Playlist",
|
||||
"PlaylistScope",
|
||||
"get_playlist",
|
||||
"get_all_playlist",
|
||||
"create_playlist",
|
||||
"reset_playlist",
|
||||
"delete_playlist",
|
||||
"humanize_scope",
|
||||
"standardize_scope",
|
||||
"FakePlaylist",
|
||||
"get_all_playlist_for_migration23",
|
||||
"database",
|
||||
"get_all_playlist_converter",
|
||||
"get_playlist_database",
|
||||
]
|
||||
|
||||
FakePlaylist = namedtuple("Playlist", "author scope")
|
||||
@@ -32,29 +42,22 @@ 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
|
||||
global _config, _bot, database
|
||||
if _config is None:
|
||||
_config = config
|
||||
if _bot is None:
|
||||
_bot = bot
|
||||
if database is None:
|
||||
database = PlaylistInterface()
|
||||
|
||||
|
||||
def standardize_scope(scope) -> str:
|
||||
def get_playlist_database() -> Optional[PlaylistInterface]:
|
||||
global database
|
||||
return database
|
||||
|
||||
|
||||
def standardize_scope(scope: str) -> str:
|
||||
scope = scope.upper()
|
||||
valid_scopes = ["GLOBAL", "GUILD", "AUTHOR", "USER", "SERVER", "MEMBER", "BOT"]
|
||||
|
||||
@@ -76,17 +79,25 @@ def standardize_scope(scope) -> str:
|
||||
return scope
|
||||
|
||||
|
||||
def humanize_scope(scope, ctx=None, the=None):
|
||||
def _prepare_config_scope(
|
||||
scope, author: Union[discord.abc.User, int] = None, guild: Union[discord.Guild, int] = None
|
||||
):
|
||||
scope = standardize_scope(scope)
|
||||
|
||||
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"
|
||||
config_scope = [PlaylistScope.GLOBAL.value, _bot.user.id]
|
||||
elif scope == PlaylistScope.USER.value:
|
||||
return str(ctx) if ctx else _("the ") if the else "" + "User"
|
||||
if author is None:
|
||||
raise MissingAuthor("Invalid author for user scope.")
|
||||
config_scope = [PlaylistScope.USER.value, int(getattr(author, "id", author))]
|
||||
else:
|
||||
if guild is None:
|
||||
raise MissingGuild("Invalid guild for guild scope.")
|
||||
config_scope = [PlaylistScope.GUILD.value, int(getattr(guild, "id", guild))]
|
||||
return config_scope
|
||||
|
||||
|
||||
def _prepare_config_scope(
|
||||
def _prepare_config_scope_for_migration23( # TODO: remove me in a future version ?
|
||||
scope, author: Union[discord.abc.User, int] = None, guild: discord.Guild = None
|
||||
):
|
||||
scope = standardize_scope(scope)
|
||||
@@ -104,6 +115,146 @@ def _prepare_config_scope(
|
||||
return config_scope
|
||||
|
||||
|
||||
class PlaylistMigration23: # TODO: remove me in a future version ?
|
||||
"""A single playlist."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
scope: str,
|
||||
author: int,
|
||||
playlist_id: int,
|
||||
name: str,
|
||||
playlist_url: Optional[str] = None,
|
||||
tracks: Optional[List[MutableMapping]] = None,
|
||||
guild: Union[discord.Guild, int, None] = None,
|
||||
):
|
||||
self.guild = guild
|
||||
self.scope = standardize_scope(scope)
|
||||
self.author = author
|
||||
self.id = playlist_id
|
||||
self.name = name
|
||||
self.url = playlist_url
|
||||
self.tracks = tracks or []
|
||||
|
||||
@classmethod
|
||||
async def from_json(
|
||||
cls, scope: str, playlist_number: int, data: MutableMapping, **kwargs
|
||||
) -> "PlaylistMigration23":
|
||||
"""Get a Playlist object from the provided information.
|
||||
Parameters
|
||||
----------
|
||||
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: int = data.get("author") or 0
|
||||
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(
|
||||
guild=guild,
|
||||
scope=scope,
|
||||
author=author,
|
||||
playlist_id=playlist_id,
|
||||
name=name,
|
||||
playlist_url=playlist_url,
|
||||
tracks=tracks,
|
||||
)
|
||||
|
||||
async def save(self):
|
||||
"""Saves a Playlist to SQL."""
|
||||
scope, scope_id = _prepare_config_scope(self.scope, self.author, self.guild)
|
||||
database.upsert(
|
||||
scope,
|
||||
playlist_id=int(self.id),
|
||||
playlist_name=self.name,
|
||||
scope_id=scope_id,
|
||||
author_id=self.author,
|
||||
playlist_url=self.url,
|
||||
tracks=self.tracks,
|
||||
)
|
||||
|
||||
|
||||
async def get_all_playlist_for_migration23( # TODO: remove me in a future version ?
|
||||
scope: str, guild: Union[discord.Guild, int] = None
|
||||
) -> List[PlaylistMigration23]:
|
||||
"""
|
||||
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.
|
||||
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(scope).all()
|
||||
if scope == PlaylistScope.GLOBAL.value:
|
||||
return [
|
||||
await PlaylistMigration23.from_json(
|
||||
scope,
|
||||
playlist_number,
|
||||
playlist_data,
|
||||
guild=guild,
|
||||
author=int(playlist_data.get("author", 0)),
|
||||
)
|
||||
for playlist_number, playlist_data in playlists.items()
|
||||
]
|
||||
elif scope == PlaylistScope.USER.value:
|
||||
return [
|
||||
await PlaylistMigration23.from_json(
|
||||
scope, playlist_number, playlist_data, guild=guild, author=int(user_id)
|
||||
)
|
||||
for user_id, scopedata in playlists.items()
|
||||
for playlist_number, playlist_data in scopedata.items()
|
||||
]
|
||||
else:
|
||||
return [
|
||||
await PlaylistMigration23.from_json(
|
||||
scope,
|
||||
playlist_number,
|
||||
playlist_data,
|
||||
guild=int(guild_id),
|
||||
author=int(playlist_data.get("author", 0)),
|
||||
)
|
||||
for guild_id, scopedata in playlists.items()
|
||||
for playlist_number, playlist_data in scopedata.items()
|
||||
]
|
||||
|
||||
|
||||
class Playlist:
|
||||
"""A single playlist."""
|
||||
|
||||
@@ -115,14 +266,16 @@ class Playlist:
|
||||
playlist_id: int,
|
||||
name: str,
|
||||
playlist_url: Optional[str] = None,
|
||||
tracks: Optional[List[dict]] = None,
|
||||
tracks: Optional[List[MutableMapping]] = 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.scope_id = self.config_scope[-1]
|
||||
self.author = author
|
||||
self.author_id = getattr(self.author, "id", self.author)
|
||||
self.guild_id = (
|
||||
getattr(guild, "id", guild) if self.scope == PlaylistScope.GLOBAL.value else None
|
||||
)
|
||||
@@ -132,7 +285,14 @@ class Playlist:
|
||||
self.tracks = tracks or []
|
||||
self.tracks_obj = [lavalink.Track(data=track) for track in self.tracks]
|
||||
|
||||
async def edit(self, data: dict):
|
||||
def __repr__(self):
|
||||
return (
|
||||
f"Playlist(name={self.name}, id={self.id}, scope={self.scope}, "
|
||||
f"scope_id={self.scope_id}, author={self.author_id}, "
|
||||
f"tracks={len(self.tracks)}, url={self.url})"
|
||||
)
|
||||
|
||||
async def edit(self, data: MutableMapping):
|
||||
"""
|
||||
Edits a Playlist.
|
||||
Parameters
|
||||
@@ -146,10 +306,23 @@ class Playlist:
|
||||
|
||||
for item in list(data.keys()):
|
||||
setattr(self, item, data[item])
|
||||
await self.save()
|
||||
return self
|
||||
|
||||
await _config.custom(*self.config_scope, str(self.id)).set(self.to_json())
|
||||
async def save(self):
|
||||
"""Saves a Playlist."""
|
||||
scope, scope_id = self.config_scope
|
||||
database.upsert(
|
||||
scope,
|
||||
playlist_id=int(self.id),
|
||||
playlist_name=self.name,
|
||||
scope_id=scope_id,
|
||||
author_id=self.author_id,
|
||||
playlist_url=self.url,
|
||||
tracks=self.tracks,
|
||||
)
|
||||
|
||||
def to_json(self) -> dict:
|
||||
def to_json(self) -> MutableMapping:
|
||||
"""Transform the object to a dict.
|
||||
Returns
|
||||
-------
|
||||
@@ -158,7 +331,7 @@ class Playlist:
|
||||
"""
|
||||
data = dict(
|
||||
id=self.id,
|
||||
author=self.author,
|
||||
author=self.author_id,
|
||||
guild=self.guild_id,
|
||||
name=self.name,
|
||||
playlist_url=self.url,
|
||||
@@ -168,7 +341,9 @@ class Playlist:
|
||||
return data
|
||||
|
||||
@classmethod
|
||||
async def from_json(cls, bot: Red, scope: str, playlist_number: int, data: dict, **kwargs):
|
||||
async def from_json(
|
||||
cls, bot: Red, scope: str, playlist_number: int, data: PlaylistFetchResult, **kwargs
|
||||
) -> "Playlist":
|
||||
"""Get a Playlist object from the provided information.
|
||||
Parameters
|
||||
----------
|
||||
@@ -197,12 +372,12 @@ class Playlist:
|
||||
`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", [])
|
||||
guild = data.scope_id if scope == PlaylistScope.GUILD.value else kwargs.get("guild")
|
||||
author = data.author_id
|
||||
playlist_id = data.playlist_id or playlist_number
|
||||
name = data.playlist_name
|
||||
playlist_url = data.playlist_url
|
||||
tracks = data.tracks
|
||||
|
||||
return cls(
|
||||
bot=bot,
|
||||
@@ -252,13 +427,13 @@ async def get_playlist(
|
||||
`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"]:
|
||||
scope_standard, scope_id = _prepare_config_scope(scope, author, guild)
|
||||
playlist_data = database.fetch(scope_standard, playlist_number, scope_id)
|
||||
|
||||
if not (playlist_data and playlist_data.playlist_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
|
||||
bot, scope_standard, playlist_number, playlist_data, guild=guild, author=author
|
||||
)
|
||||
|
||||
|
||||
@@ -296,23 +471,65 @@ async def get_all_playlist(
|
||||
`MissingAuthor`
|
||||
Trying to access the User scope without an user id.
|
||||
"""
|
||||
playlists = await _config.custom(*_prepare_config_scope(scope, author, guild)).all()
|
||||
scope_standard, scope_id = _prepare_config_scope(scope, author, guild)
|
||||
|
||||
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")
|
||||
]
|
||||
playlists = await database.fetch_all(scope_standard, scope_id, author_id=user_id)
|
||||
else:
|
||||
return [
|
||||
await Playlist.from_json(
|
||||
bot, scope, playlist_number, playlist_data, guild=guild, author=author
|
||||
)
|
||||
for playlist_number, playlist_data in playlists.items()
|
||||
]
|
||||
playlists = await database.fetch_all(scope_standard, scope_id)
|
||||
return [
|
||||
await Playlist.from_json(
|
||||
bot, scope, playlist.playlist_id, playlist, guild=guild, author=author
|
||||
)
|
||||
for playlist in playlists
|
||||
]
|
||||
|
||||
|
||||
async def get_all_playlist_converter(
|
||||
scope: str,
|
||||
bot: Red,
|
||||
arg: str,
|
||||
guild: Union[discord.Guild, int] = None,
|
||||
author: Union[discord.abc.User, int] = None,
|
||||
) -> 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
|
||||
arg:str
|
||||
The value to lookup.
|
||||
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.
|
||||
"""
|
||||
scope_standard, scope_id = _prepare_config_scope(scope, author, guild)
|
||||
playlists = await database.fetch_all_converter(
|
||||
scope_standard, playlist_name=arg, playlist_id=arg
|
||||
)
|
||||
return [
|
||||
await Playlist.from_json(
|
||||
bot, scope, playlist.playlist_id, playlist, guild=guild, author=author
|
||||
)
|
||||
for playlist in playlists
|
||||
]
|
||||
|
||||
|
||||
async def create_playlist(
|
||||
@@ -320,12 +537,11 @@ async def create_playlist(
|
||||
scope: str,
|
||||
playlist_name: str,
|
||||
playlist_url: Optional[str] = None,
|
||||
tracks: Optional[List[dict]] = None,
|
||||
tracks: Optional[List[MutableMapping]] = None,
|
||||
author: Optional[discord.User] = None,
|
||||
guild: Optional[discord.Guild] = None,
|
||||
) -> Optional[Playlist]:
|
||||
"""
|
||||
Creates a new Playlist.
|
||||
"""Creates a new Playlist.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -337,7 +553,7 @@ async def create_playlist(
|
||||
The name of the new playlist.
|
||||
playlist_url:str
|
||||
the url of the new playlist.
|
||||
tracks: List[dict]
|
||||
tracks: List[MutableMapping]
|
||||
A list of tracks to add to the playlist.
|
||||
author: discord.User
|
||||
The Author of the playlist.
|
||||
@@ -358,12 +574,16 @@ async def create_playlist(
|
||||
"""
|
||||
|
||||
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()
|
||||
ctx.bot,
|
||||
scope,
|
||||
author.id if author else None,
|
||||
ctx.message.id,
|
||||
playlist_name,
|
||||
playlist_url,
|
||||
tracks,
|
||||
guild or ctx.guild,
|
||||
)
|
||||
await playlist.save()
|
||||
return playlist
|
||||
|
||||
|
||||
@@ -372,8 +592,7 @@ async def reset_playlist(
|
||||
guild: Union[discord.Guild, int] = None,
|
||||
author: Union[discord.abc.User, int] = None,
|
||||
) -> None:
|
||||
"""
|
||||
Wipes all playlists for the specified scope.
|
||||
"""Wipes all playlists for the specified scope.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
@@ -393,7 +612,9 @@ async def reset_playlist(
|
||||
`MissingAuthor`
|
||||
Trying to access the User scope without an user id.
|
||||
"""
|
||||
await _config.custom(*_prepare_config_scope(scope, author, guild)).clear()
|
||||
scope, scope_id = _prepare_config_scope(scope, author, guild)
|
||||
database.drop(scope)
|
||||
database.create_table(scope)
|
||||
|
||||
|
||||
async def delete_playlist(
|
||||
@@ -402,27 +623,27 @@ async def delete_playlist(
|
||||
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.
|
||||
"""
|
||||
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()
|
||||
scope, scope_id = _prepare_config_scope(scope, author, guild)
|
||||
database.delete(scope, int(playlist_id), scope_id)
|
||||
|
||||
Reference in New Issue
Block a user