mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
parent
dae75521d3
commit
889fa63aff
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@ -18,7 +18,6 @@ redbot/core/i18n.py @tekulvw
|
|||||||
redbot/core/json_io.py @tekulvw
|
redbot/core/json_io.py @tekulvw
|
||||||
redbot/core/modlog.py @palmtree5
|
redbot/core/modlog.py @palmtree5
|
||||||
redbot/core/rpc.py @tekulvw
|
redbot/core/rpc.py @tekulvw
|
||||||
redbot/core/sentry_setup.py @Kowlin @tekulvw
|
|
||||||
redbot/core/utils/chat_formatting.py @tekulvw
|
redbot/core/utils/chat_formatting.py @tekulvw
|
||||||
redbot/core/utils/mod.py @palmtree5
|
redbot/core/utils/mod.py @palmtree5
|
||||||
redbot/core/utils/data_converter.py @mikeshardmind
|
redbot/core/utils/data_converter.py @mikeshardmind
|
||||||
|
|||||||
28
Pipfile.lock
generated
28
Pipfile.lock
generated
@ -251,20 +251,6 @@
|
|||||||
],
|
],
|
||||||
"version": "==3.13"
|
"version": "==3.13"
|
||||||
},
|
},
|
||||||
"raven": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:3fa6de6efa2493a7c827472e984ce9b020797d0da16f1db67197bcc23c8fae54",
|
|
||||||
"sha256:44a13f87670836e153951af9a3c80405d36b43097db869a36e92809673692ce4"
|
|
||||||
],
|
|
||||||
"version": "==6.10.0"
|
|
||||||
},
|
|
||||||
"raven-aiohttp": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:1444a49c93a85b8bb57c6ee649e512368dce7a26ad64ac3a01d86aa5669d77f3",
|
|
||||||
"sha256:6a34b6a9841ad0fd827eeb158edb5826c5c5bd7babe2cde2a3f23eb85313af04"
|
|
||||||
],
|
|
||||||
"version": "==0.7.0"
|
|
||||||
},
|
|
||||||
"red-discordbot": {
|
"red-discordbot": {
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"extras": [
|
"extras": [
|
||||||
@ -683,20 +669,6 @@
|
|||||||
],
|
],
|
||||||
"version": "==3.13"
|
"version": "==3.13"
|
||||||
},
|
},
|
||||||
"raven": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:3fa6de6efa2493a7c827472e984ce9b020797d0da16f1db67197bcc23c8fae54",
|
|
||||||
"sha256:44a13f87670836e153951af9a3c80405d36b43097db869a36e92809673692ce4"
|
|
||||||
],
|
|
||||||
"version": "==6.10.0"
|
|
||||||
},
|
|
||||||
"raven-aiohttp": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:1444a49c93a85b8bb57c6ee649e512368dce7a26ad64ac3a01d86aa5669d77f3",
|
|
||||||
"sha256:6a34b6a9841ad0fd827eeb158edb5826c5c5bd7babe2cde2a3f23eb85313af04"
|
|
||||||
],
|
|
||||||
"version": "==0.7.0"
|
|
||||||
},
|
|
||||||
"red-discordbot": {
|
"red-discordbot": {
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"extras": [
|
"extras": [
|
||||||
|
|||||||
@ -10,7 +10,7 @@ from redbot.core.data_manager import create_temp_config, load_basic_configuratio
|
|||||||
from redbot.core.json_io import JsonIO
|
from redbot.core.json_io import JsonIO
|
||||||
from redbot.core.global_checks import init_global_checks
|
from redbot.core.global_checks import init_global_checks
|
||||||
from redbot.core.events import init_events
|
from redbot.core.events import init_events
|
||||||
from redbot.core.cli import interactive_config, confirm, parse_cli_flags, ask_sentry
|
from redbot.core.cli import interactive_config, confirm, parse_cli_flags
|
||||||
from redbot.core.core_commands import Core
|
from redbot.core.core_commands import Core
|
||||||
from redbot.core.dev_commands import Dev
|
from redbot.core.dev_commands import Dev
|
||||||
from redbot.core import __version__
|
from redbot.core import __version__
|
||||||
@ -77,11 +77,7 @@ def init_loggers(cli_flags):
|
|||||||
logger.addHandler(fhandler)
|
logger.addHandler(fhandler)
|
||||||
logger.addHandler(stdout_handler)
|
logger.addHandler(stdout_handler)
|
||||||
|
|
||||||
# Sentry stuff
|
return logger
|
||||||
sentry_logger = logging.getLogger("red.sentry")
|
|
||||||
sentry_logger.setLevel(logging.WARNING)
|
|
||||||
|
|
||||||
return logger, sentry_logger
|
|
||||||
|
|
||||||
|
|
||||||
async def _get_prefix_and_token(red, indict):
|
async def _get_prefix_and_token(red, indict):
|
||||||
@ -92,7 +88,6 @@ async def _get_prefix_and_token(red, indict):
|
|||||||
"""
|
"""
|
||||||
indict["token"] = await red.db.token()
|
indict["token"] = await red.db.token()
|
||||||
indict["prefix"] = await red.db.prefix()
|
indict["prefix"] = await red.db.prefix()
|
||||||
indict["enable_sentry"] = await red.db.enable_sentry()
|
|
||||||
|
|
||||||
|
|
||||||
def list_instances():
|
def list_instances():
|
||||||
@ -136,7 +131,7 @@ def main():
|
|||||||
cli_flags.instance_name = "temporary_red"
|
cli_flags.instance_name = "temporary_red"
|
||||||
create_temp_config()
|
create_temp_config()
|
||||||
load_basic_configuration(cli_flags.instance_name)
|
load_basic_configuration(cli_flags.instance_name)
|
||||||
log, sentry_log = init_loggers(cli_flags)
|
log = init_loggers(cli_flags)
|
||||||
red = Red(cli_flags=cli_flags, description=description, pm_help=None)
|
red = Red(cli_flags=cli_flags, description=description, pm_help=None)
|
||||||
init_global_checks(red)
|
init_global_checks(red)
|
||||||
init_events(red, cli_flags)
|
init_events(red, cli_flags)
|
||||||
@ -166,8 +161,6 @@ def main():
|
|||||||
if cli_flags.dry_run:
|
if cli_flags.dry_run:
|
||||||
loop.run_until_complete(red.http.close())
|
loop.run_until_complete(red.http.close())
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
if tmp_data["enable_sentry"]:
|
|
||||||
red.enable_sentry()
|
|
||||||
try:
|
try:
|
||||||
loop.run_until_complete(red.start(token, bot=True))
|
loop.run_until_complete(red.start(token, bot=True))
|
||||||
except discord.LoginFailure:
|
except discord.LoginFailure:
|
||||||
@ -184,7 +177,6 @@ def main():
|
|||||||
red._shutdown_mode = ExitCodes.SHUTDOWN
|
red._shutdown_mode = ExitCodes.SHUTDOWN
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.critical("Fatal exception", exc_info=e)
|
log.critical("Fatal exception", exc_info=e)
|
||||||
sentry_log.critical("Fatal Exception", exc_info=e)
|
|
||||||
loop.run_until_complete(red.logout())
|
loop.run_until_complete(red.logout())
|
||||||
finally:
|
finally:
|
||||||
pending = asyncio.Task.all_tasks(loop=red.loop)
|
pending = asyncio.Task.all_tasks(loop=red.loop)
|
||||||
|
|||||||
@ -16,7 +16,6 @@ from . import Config, i18n, commands, errors
|
|||||||
from .cog_manager import CogManager
|
from .cog_manager import CogManager
|
||||||
from .help_formatter import Help, help as help_
|
from .help_formatter import Help, help as help_
|
||||||
from .rpc import RPCMixin
|
from .rpc import RPCMixin
|
||||||
from .sentry import SentryManager
|
|
||||||
from .utils import common_filters
|
from .utils import common_filters
|
||||||
|
|
||||||
|
|
||||||
@ -47,7 +46,6 @@ class RedBase(commands.GroupMixin, commands.bot.BotBase, RPCMixin):
|
|||||||
owner=None,
|
owner=None,
|
||||||
whitelist=[],
|
whitelist=[],
|
||||||
blacklist=[],
|
blacklist=[],
|
||||||
enable_sentry=None,
|
|
||||||
locale="en",
|
locale="en",
|
||||||
embeds=True,
|
embeds=True,
|
||||||
color=15158332,
|
color=15158332,
|
||||||
@ -120,23 +118,8 @@ class RedBase(commands.GroupMixin, commands.bot.BotBase, RPCMixin):
|
|||||||
|
|
||||||
self.add_command(help_)
|
self.add_command(help_)
|
||||||
|
|
||||||
self._sentry_mgr = None
|
|
||||||
self._permissions_hooks: List[commands.CheckPredicate] = []
|
self._permissions_hooks: List[commands.CheckPredicate] = []
|
||||||
|
|
||||||
def enable_sentry(self):
|
|
||||||
"""Enable Sentry logging for Red."""
|
|
||||||
if self._sentry_mgr is None:
|
|
||||||
sentry_log = logging.getLogger("red.sentry")
|
|
||||||
sentry_log.setLevel(logging.WARNING)
|
|
||||||
self._sentry_mgr = SentryManager(sentry_log)
|
|
||||||
self._sentry_mgr.enable()
|
|
||||||
|
|
||||||
def disable_sentry(self):
|
|
||||||
"""Disable Sentry logging for Red."""
|
|
||||||
if self._sentry_mgr is None:
|
|
||||||
return
|
|
||||||
self._sentry_mgr.disable()
|
|
||||||
|
|
||||||
async def _dict_abuse(self, indict):
|
async def _dict_abuse(self, indict):
|
||||||
"""
|
"""
|
||||||
Please blame <@269933075037814786> for this.
|
Please blame <@269933075037814786> for this.
|
||||||
@ -516,8 +499,6 @@ class Red(RedBase, discord.AutoShardedClient):
|
|||||||
|
|
||||||
async def logout(self):
|
async def logout(self):
|
||||||
"""Logs out of Discord and closes all connections."""
|
"""Logs out of Discord and closes all connections."""
|
||||||
if self._sentry_mgr:
|
|
||||||
await self._sentry_mgr.close()
|
|
||||||
|
|
||||||
await super().logout()
|
await super().logout()
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from redbot.core.bot import Red
|
|
||||||
|
|
||||||
|
|
||||||
def confirm(m=""):
|
def confirm(m=""):
|
||||||
return input(m).lower().strip() in ("y", "yes")
|
return input(m).lower().strip() in ("y", "yes")
|
||||||
@ -42,26 +40,9 @@ def interactive_config(red, token_set, prefix_set):
|
|||||||
if prefix:
|
if prefix:
|
||||||
loop.run_until_complete(red.db.prefix.set([prefix]))
|
loop.run_until_complete(red.db.prefix.set([prefix]))
|
||||||
|
|
||||||
ask_sentry(red)
|
|
||||||
|
|
||||||
return token
|
return token
|
||||||
|
|
||||||
|
|
||||||
def ask_sentry(red: Red):
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
print(
|
|
||||||
"\nThank you for installing Red V3! Red is constantly undergoing\n"
|
|
||||||
" improvements, and we would like to ask if you are comfortable with\n"
|
|
||||||
" the bot automatically submitting fatal error logs to the development\n"
|
|
||||||
' team. If you wish to opt into the process please type "yes":\n'
|
|
||||||
)
|
|
||||||
if not confirm("> "):
|
|
||||||
loop.run_until_complete(red.db.enable_sentry.set(False))
|
|
||||||
else:
|
|
||||||
loop.run_until_complete(red.db.enable_sentry.set(True))
|
|
||||||
print("\nThank you for helping us with the development process!")
|
|
||||||
|
|
||||||
|
|
||||||
def parse_cli_flags(args):
|
def parse_cli_flags(args):
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="Red - Discord Bot", usage="redbot <instance_name> [arguments]"
|
description="Red - Discord Bot", usage="redbot <instance_name> [arguments]"
|
||||||
|
|||||||
@ -1015,23 +1015,6 @@ class Core(commands.Cog, CoreLogic):
|
|||||||
|
|
||||||
await ctx.send(_("Locale has been set."))
|
await ctx.send(_("Locale has been set."))
|
||||||
|
|
||||||
@_set.command()
|
|
||||||
@checks.is_owner()
|
|
||||||
async def sentry(self, ctx: commands.Context, on_or_off: bool):
|
|
||||||
"""Enable or disable Sentry logging.
|
|
||||||
|
|
||||||
Sentry is the service Red uses to manage error reporting. This should
|
|
||||||
be disabled if you have made your own modifications to the redbot
|
|
||||||
package.
|
|
||||||
"""
|
|
||||||
await ctx.bot.db.enable_sentry.set(on_or_off)
|
|
||||||
if on_or_off:
|
|
||||||
ctx.bot.enable_sentry()
|
|
||||||
await ctx.send(_("Done. Sentry logging is now enabled."))
|
|
||||||
else:
|
|
||||||
ctx.bot.disable_sentry()
|
|
||||||
await ctx.send(_("Done. Sentry logging is now disabled."))
|
|
||||||
|
|
||||||
@_set.command()
|
@_set.command()
|
||||||
@checks.is_owner()
|
@checks.is_owner()
|
||||||
async def custominfo(self, ctx: commands.Context, *, text: str = None):
|
async def custominfo(self, ctx: commands.Context, *, text: str = None):
|
||||||
|
|||||||
@ -19,34 +19,18 @@ from .utils.chat_formatting import inline, bordered, format_perms_list
|
|||||||
from .utils import fuzzy_command_search, format_fuzzy_results
|
from .utils import fuzzy_command_search, format_fuzzy_results
|
||||||
|
|
||||||
log = logging.getLogger("red")
|
log = logging.getLogger("red")
|
||||||
sentry_log = logging.getLogger("red.sentry")
|
|
||||||
init()
|
init()
|
||||||
|
|
||||||
INTRO = """
|
INTRO = """
|
||||||
______ _ ______ _ _ ______ _
|
______ _ ______ _ _ ______ _
|
||||||
| ___ \ | | | _ (_) | | | ___ \ | |
|
| ___ \ | | | _ (_) | | | ___ \ | |
|
||||||
| |_/ /___ __| | ______ | | | |_ ___ ___ ___ _ __ __| | | |_/ / ___ | |_
|
| |_/ /___ __| | ______ | | | |_ ___ ___ ___ _ __ __| | | |_/ / ___ | |_
|
||||||
| // _ \/ _` | |______| | | | | / __|/ __/ _ \| '__/ _` | | ___ \/ _ \| __|
|
| // _ \/ _` | |______| | | | | / __|/ __/ _ \| '__/ _` | | ___ \/ _ \| __|
|
||||||
| |\ \ __/ (_| | | |/ /| \__ \ (_| (_) | | | (_| | | |_/ / (_) | |_
|
| |\ \ __/ (_| | | |/ /| \__ \ (_| (_) | | | (_| | | |_/ / (_) | |_
|
||||||
\_| \_\___|\__,_| |___/ |_|___/\___\___/|_| \__,_| \____/ \___/ \__|
|
\_| \_\___|\__,_| |___/ |_|___/\___\___/|_| \__,_| \____/ \___/ \__|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def should_log_sentry(exception) -> bool:
|
|
||||||
e = exception
|
|
||||||
while e.__cause__ is not None:
|
|
||||||
e = e.__cause__
|
|
||||||
|
|
||||||
tb = e.__traceback__
|
|
||||||
tb_frame = None
|
|
||||||
while tb is not None:
|
|
||||||
tb_frame = tb.tb_frame
|
|
||||||
tb = tb.tb_next
|
|
||||||
|
|
||||||
module = tb_frame.f_globals.get("__name__")
|
|
||||||
return module is not None and module.startswith("redbot")
|
|
||||||
|
|
||||||
|
|
||||||
def init_events(bot, cli_flags):
|
def init_events(bot, cli_flags):
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_connect():
|
async def on_connect():
|
||||||
@ -142,7 +126,6 @@ def init_events(bot, cli_flags):
|
|||||||
)
|
)
|
||||||
INFO2 = []
|
INFO2 = []
|
||||||
|
|
||||||
sentry = await bot.db.enable_sentry()
|
|
||||||
mongo_enabled = storage_type() != "JSON"
|
mongo_enabled = storage_type() != "JSON"
|
||||||
reqs_installed = {"docs": None, "test": None}
|
reqs_installed = {"docs": None, "test": None}
|
||||||
for key in reqs_installed.keys():
|
for key in reqs_installed.keys():
|
||||||
@ -155,7 +138,6 @@ def init_events(bot, cli_flags):
|
|||||||
reqs_installed[key] = True
|
reqs_installed[key] = True
|
||||||
|
|
||||||
options = (
|
options = (
|
||||||
("Error Reporting", sentry),
|
|
||||||
("MongoDB", mongo_enabled),
|
("MongoDB", mongo_enabled),
|
||||||
("Voice", True),
|
("Voice", True),
|
||||||
("Docs", reqs_installed["docs"]),
|
("Docs", reqs_installed["docs"]),
|
||||||
@ -177,10 +159,6 @@ def init_events(bot, cli_flags):
|
|||||||
|
|
||||||
bot.color = discord.Colour(await bot.db.color())
|
bot.color = discord.Colour(await bot.db.color())
|
||||||
|
|
||||||
@bot.event
|
|
||||||
async def on_error(event_method, *args, **kwargs):
|
|
||||||
sentry_log.exception("Exception in {}".format(event_method))
|
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_command_error(ctx, error):
|
async def on_command_error(ctx, error):
|
||||||
if isinstance(error, commands.MissingRequiredArgument):
|
if isinstance(error, commands.MissingRequiredArgument):
|
||||||
@ -201,11 +179,6 @@ def init_events(bot, cli_flags):
|
|||||||
"Exception in command '{}'".format(ctx.command.qualified_name),
|
"Exception in command '{}'".format(ctx.command.qualified_name),
|
||||||
exc_info=error.original,
|
exc_info=error.original,
|
||||||
)
|
)
|
||||||
if should_log_sentry(error):
|
|
||||||
sentry_log.exception(
|
|
||||||
"Exception in command '{}'".format(ctx.command.qualified_name),
|
|
||||||
exc_info=error.original,
|
|
||||||
)
|
|
||||||
|
|
||||||
message = "Error in command '{}'. Check your console or logs for details.".format(
|
message = "Error in command '{}'. Check your console or logs for details.".format(
|
||||||
ctx.command.qualified_name
|
ctx.command.qualified_name
|
||||||
@ -245,13 +218,6 @@ def init_events(bot, cli_flags):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
log.exception(type(error).__name__, exc_info=error)
|
log.exception(type(error).__name__, exc_info=error)
|
||||||
try:
|
|
||||||
sentry_error = error.original
|
|
||||||
except AttributeError:
|
|
||||||
sentry_error = error
|
|
||||||
|
|
||||||
if should_log_sentry(sentry_error):
|
|
||||||
sentry_log.exception("Unhandled command error.", exc_info=sentry_error)
|
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_message(message):
|
async def on_message(message):
|
||||||
|
|||||||
@ -1,41 +0,0 @@
|
|||||||
import asyncio
|
|
||||||
import logging
|
|
||||||
from raven import Client
|
|
||||||
from raven.handlers.logging import SentryHandler
|
|
||||||
from raven_aiohttp import AioHttpTransport
|
|
||||||
|
|
||||||
from redbot.core import __version__
|
|
||||||
|
|
||||||
__all__ = ("SentryManager",)
|
|
||||||
|
|
||||||
|
|
||||||
class SentryManager:
|
|
||||||
"""Simple class to manage sentry logging for Red."""
|
|
||||||
|
|
||||||
def __init__(self, logger: logging.Logger):
|
|
||||||
self.client = Client(
|
|
||||||
dsn=(
|
|
||||||
"https://62402161d4cd4ef18f83b16f3e22a020:9310ef55a502442598203205a84da2bb@"
|
|
||||||
"sentry.io/253983"
|
|
||||||
),
|
|
||||||
release=__version__,
|
|
||||||
include_paths=["redbot"],
|
|
||||||
enable_breadcrumbs=False,
|
|
||||||
transport=AioHttpTransport,
|
|
||||||
)
|
|
||||||
self.handler = SentryHandler(self.client)
|
|
||||||
self.logger = logger
|
|
||||||
|
|
||||||
def enable(self):
|
|
||||||
"""Enable error reporting for Sentry."""
|
|
||||||
self.logger.addHandler(self.handler)
|
|
||||||
|
|
||||||
def disable(self):
|
|
||||||
"""Disable error reporting for Sentry."""
|
|
||||||
self.logger.removeHandler(self.handler)
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
loop.create_task(self.close())
|
|
||||||
|
|
||||||
async def close(self):
|
|
||||||
"""Wait for the Sentry client to send pending messages and shut down."""
|
|
||||||
await self.client.remote.get_transport().close()
|
|
||||||
@ -4,7 +4,6 @@ from pathlib import Path
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
from raven.versioning import fetch_git_sha
|
|
||||||
|
|
||||||
from redbot.pytest.downloader import *
|
from redbot.pytest.downloader import *
|
||||||
|
|
||||||
@ -60,18 +59,6 @@ async def test_current_branch(bot_repo):
|
|||||||
assert branch not in ("WRONG", "")
|
assert branch not in ("WRONG", "")
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_current_hash(bot_repo):
|
|
||||||
branch = await bot_repo.current_branch()
|
|
||||||
bot_repo.branch = branch
|
|
||||||
|
|
||||||
commit = await bot_repo.current_commit()
|
|
||||||
|
|
||||||
sentry_sha = fetch_git_sha(str(bot_repo.folder_path))
|
|
||||||
|
|
||||||
assert sentry_sha == commit
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_existing_repo(repo_manager):
|
async def test_existing_repo(repo_manager):
|
||||||
repo_manager.does_repo_exist = MagicMock(return_value=True)
|
repo_manager.does_repo_exist = MagicMock(return_value=True)
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
import logging
|
|
||||||
|
|
||||||
from redbot.core import sentry
|
|
||||||
|
|
||||||
|
|
||||||
def test_sentry_capture(red):
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
mgr = sentry.SentryManager(log)
|
|
||||||
|
|
||||||
assert mgr.client is not None
|
|
||||||
|
|
||||||
mgr.client.captureMessage("Message from test_sentry module.")
|
|
||||||
Loading…
x
Reference in New Issue
Block a user