Merge remote-tracking branch 'release/V3/develop' into V3/develop

This commit is contained in:
palmtree5 2019-12-14 23:28:31 -09:00
commit 9a82830f13
12 changed files with 105 additions and 11 deletions

View File

@ -0,0 +1 @@
Add ``redbot --debuginfo`` flag that shows useful information for debugging.

View File

@ -0,0 +1 @@
Add Python executable field to `[p]debuginfo` command.

View File

@ -0,0 +1 @@
update windows docs with up to date dependency instructions

View File

@ -0,0 +1 @@
Added an early exist to the `while` loop in the autoplay method, this is to that if a service is blacklisted it doesn't infinitely loop causing heartbeats.

View File

@ -0,0 +1 @@
``[p]cog uninstall`` now fully unloads cog - bot will not try to load it on next startup.

View File

@ -27,15 +27,30 @@ Then run each of the following commands:
Set-ExecutionPolicy Bypass -Scope Process -Force Set-ExecutionPolicy Bypass -Scope Process -Force
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
choco install git --params "/GitOnlyOnPath /WindowsTerminal" -y choco install git --params "/GitOnlyOnPath /WindowsTerminal" -y
choco install jre8 python -y; exit choco install visualstudio2019-workload-vctools -y
choco install python3 --version=3.7.5 -y
From here, continue onto `installing Red <installing-red-windows>`. For Audio support, you should also run the following command before exiting:
.. code-block:: none
choco install adoptopenjdk11jre -y
From here, exit the prompt then continue onto `installing Red <installing-red-windows>`.
******************************** ********************************
Manually installing dependencies Manually installing dependencies
******************************** ********************************
* `Python <https://www.python.org/downloads/>`_ - Red needs Python 3.7.0 or greater .. attention:: There are additional configuration steps required which are
not documented for installing dependencies manually.
These dependencies are only listed seperately here for
reference purposes.
* `MSVC Build tools <https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2019>`_
* `Python <https://www.python.org/downloads/>`_ - Red needs Python 3.7.2 or greater
.. attention:: Please make sure that the box to add Python to PATH is CHECKED, otherwise .. attention:: Please make sure that the box to add Python to PATH is CHECKED, otherwise
you may run into issues when trying to run Red. you may run into issues when trying to run Red.
@ -44,9 +59,8 @@ Manually installing dependencies
.. attention:: Please choose the option to "Git from the command line and also from 3rd-party software" in Git's setup. .. attention:: Please choose the option to "Git from the command line and also from 3rd-party software" in Git's setup.
* `Java <https://java.com/en/download/manual.jsp>`_ - needed for Audio * `Java <https://adoptopenjdk.net/?variant=openjdk11&jvmVariant=hotspot>`_ - needed for Audio
.. attention:: Please choose the "Windows Online" installer.
.. _installing-red-windows: .. _installing-red-windows:

View File

@ -3,9 +3,12 @@
# Discord Version check # Discord Version check
import asyncio import asyncio
import getpass
import json import json
import logging import logging
import os import os
import pip
import platform
import shutil import shutil
import sys import sys
from copy import deepcopy from copy import deepcopy
@ -16,7 +19,7 @@ import discord
# Set the event loop policies here so any subsequent `get_event_loop()` # Set the event loop policies here so any subsequent `get_event_loop()`
# calls, in particular those as a result of the following imports, # calls, in particular those as a result of the following imports,
# return the correct loop object. # return the correct loop object.
from redbot import _update_event_loop_policy from redbot import _update_event_loop_policy, __version__
_update_event_loop_policy() _update_event_loop_policy()
@ -73,6 +76,44 @@ def list_instances():
sys.exit(0) sys.exit(0)
def debug_info():
"""Shows debug information useful for debugging."""
if sys.platform == "linux":
import distro # pylint: disable=import-error
IS_WINDOWS = os.name == "nt"
IS_MAC = sys.platform == "darwin"
IS_LINUX = sys.platform == "linux"
pyver = sys.version
pipver = pip.__version__
redver = __version__
dpy_version = discord.__version__
if IS_WINDOWS:
os_info = platform.uname()
osver = "{} {} (version {})".format(os_info.system, os_info.release, os_info.version)
elif IS_MAC:
os_info = platform.mac_ver()
osver = "Mac OSX {} {}".format(os_info[0], os_info[2])
else:
os_info = distro.linux_distribution()
osver = "{} {}".format(os_info[0], os_info[1]).strip()
user_who_ran = getpass.getuser()
info = (
"Debug Info for Red\n\n"
+ "Red version: {}\n".format(redver)
+ "Python version: {}\n".format(pyver)
+ "Python executable: {}\n".format(sys.executable)
+ "Discord.py version: {}\n".format(dpy_version)
+ "Pip version: {}\n".format(pipver)
+ "OS version: {}\n".format(osver)
+ "System arch: {}\n".format(platform.machine())
+ "User: {}\n".format(user_who_ran)
)
print(info)
sys.exit(0)
def edit_instance(red, cli_flags): def edit_instance(red, cli_flags):
no_prompt = cli_flags.no_prompt no_prompt = cli_flags.no_prompt
token = cli_flags.token token = cli_flags.token
@ -231,6 +272,8 @@ def main():
print(description) print(description)
print("Current Version: {}".format(__version__)) print("Current Version: {}".format(__version__))
sys.exit(0) sys.exit(0)
elif cli_flags.debuginfo:
debug_info()
elif not cli_flags.instance_name and (not cli_flags.no_instance or cli_flags.edit): elif not cli_flags.instance_name and (not cli_flags.no_instance or cli_flags.edit):
print("Error: No instance name was provided!") print("Error: No instance name was provided!")
sys.exit(1) sys.exit(1)

View File

@ -33,7 +33,7 @@ from redbot.core import Config, commands
from redbot.core.bot import Red from redbot.core.bot import Red
from redbot.core.i18n import Translator, cog_i18n from redbot.core.i18n import Translator, cog_i18n
from . import audio_dataclasses from . import audio_dataclasses
from .errors import InvalidTableError, SpotifyFetchError, YouTubeApiError from .errors import InvalidTableError, SpotifyFetchError, YouTubeApiError, DatabaseError
from .playlists import get_playlist from .playlists import get_playlist
from .utils import CacheLevel, Notifier, is_allowed, queue_duration, track_limit from .utils import CacheLevel, Notifier, is_allowed, queue_duration, track_limit
@ -1098,10 +1098,14 @@ class MusicCache:
track = tracks[0] track = tracks[0]
valid = not multiple valid = not multiple
tries = len(tracks)
while valid is False and multiple: while valid is False and multiple:
tries -= 1
if tries <= 0:
raise DatabaseError("No valid entry found")
track = random.choice(tracks) track = random.choice(tracks)
query = audio_dataclasses.Query.process_input(track) query = audio_dataclasses.Query.process_input(track)
await asyncio.sleep(0.001)
if not query.valid: if not query.valid:
continue continue
if query.is_local and not query.track.exists(): if query.is_local and not query.track.exists():

View File

@ -39,7 +39,13 @@ from .apis import MusicCache, HAS_SQL, _ERROR
from .checks import can_have_caching from .checks import can_have_caching
from .converters import ComplexScopeParser, ScopeParser, get_lazy_converter, get_playlist_converter from .converters import ComplexScopeParser, ScopeParser, get_lazy_converter, get_playlist_converter
from .equalizer import Equalizer from .equalizer import Equalizer
from .errors import LavalinkDownloadFailed, MissingGuild, SpotifyFetchError, TooManyMatches from .errors import (
DatabaseError,
LavalinkDownloadFailed,
MissingGuild,
SpotifyFetchError,
TooManyMatches,
)
from .manager import ServerManager from .manager import ServerManager
from .playlists import ( from .playlists import (
FakePlaylist, FakePlaylist,
@ -448,7 +454,16 @@ class Audio(commands.Cog):
) )
if autoplay and not player.queue and player.fetch("playing_song") is not None: if autoplay and not player.queue and player.fetch("playing_song") is not None:
if self.owns_autoplay is None: if self.owns_autoplay is None:
await self.music_cache.autoplay(player) try:
await self.music_cache.autoplay(player)
except DatabaseError:
notify_channel = player.fetch("channel")
if notify_channel:
notify_channel = self.bot.get_channel(notify_channel)
await self._embed_msg(
notify_channel, _("Autoplay: Couldn't get a valid track.")
)
return
else: else:
self.bot.dispatch( self.bot.dispatch(
"red_audio_should_auto_play", "red_audio_should_auto_play",
@ -2725,7 +2740,16 @@ class Audio(commands.Cog):
if not await self._currency_check(ctx, guild_data["jukebox_price"]): if not await self._currency_check(ctx, guild_data["jukebox_price"]):
return return
if self.owns_autoplay is None: if self.owns_autoplay is None:
await self.music_cache.autoplay(player) try:
await self.music_cache.autoplay(player)
except DatabaseError:
notify_channel = player.fetch("channel")
if notify_channel:
notify_channel = self.bot.get_channel(notify_channel)
await self._embed_msg(
notify_channel, _("Autoplay: Couldn't get a valid track.")
)
return
else: else:
self.bot.dispatch( self.bot.dispatch(
"red_audio_should_auto_play", "red_audio_should_auto_play",

View File

@ -647,6 +647,7 @@ class Downloader(commands.Cog):
if poss_installed_path.exists(): if poss_installed_path.exists():
with contextlib.suppress(commands.ExtensionNotLoaded): with contextlib.suppress(commands.ExtensionNotLoaded):
ctx.bot.unload_extension(real_name) ctx.bot.unload_extension(real_name)
await ctx.bot.remove_loaded_package(real_name)
await self._delete_cog(poss_installed_path) await self._delete_cog(poss_installed_path)
uninstalled_cogs.append(inline(real_name)) uninstalled_cogs.append(inline(real_name))
else: else:

View File

@ -73,6 +73,7 @@ def parse_cli_flags(args):
description="Red - Discord Bot", usage="redbot <instance_name> [arguments]" description="Red - Discord Bot", usage="redbot <instance_name> [arguments]"
) )
parser.add_argument("--version", "-V", action="store_true", help="Show Red's current version") parser.add_argument("--version", "-V", action="store_true", help="Show Red's current version")
parser.add_argument("--debuginfo", action="store_true", help="Show debug information.")
parser.add_argument( parser.add_argument(
"--list-instances", "--list-instances",
action="store_true", action="store_true",

View File

@ -1592,12 +1592,14 @@ class Core(commands.Cog, CoreLogic):
e.add_field(name="System arch", value=platform.machine(), inline=True) e.add_field(name="System arch", value=platform.machine(), inline=True)
e.add_field(name="User", value=user_who_ran, inline=True) e.add_field(name="User", value=user_who_ran, inline=True)
e.add_field(name="OS version", value=osver, inline=False) e.add_field(name="OS version", value=osver, inline=False)
e.add_field(name="Python executable", value=sys.executable, inline=False)
await ctx.send(embed=e) await ctx.send(embed=e)
else: else:
info = ( info = (
"Debug Info for Red\n\n" "Debug Info for Red\n\n"
+ "Red version: {}\n".format(redver) + "Red version: {}\n".format(redver)
+ "Python version: {}\n".format(pyver) + "Python version: {}\n".format(pyver)
+ "Python executable: {}\n".format(sys.executable)
+ "Discord.py version: {}\n".format(dpy_version) + "Discord.py version: {}\n".format(dpy_version)
+ "Pip version: {}\n".format(pipver) + "Pip version: {}\n".format(pipver)
+ "System arch: {}\n".format(platform.machine()) + "System arch: {}\n".format(platform.machine())