Esempio n. 1
0
async def unmuteTask(modcog: Moderation):
    GearbotLogging.info("Started unmute background task")
    skips = []
    updated = False
    while modcog.running:
        userid = 0
        guildid = 0
        try:
            guildstoremove = []
            for guildid, list in modcog.mutes.items():
                guild: discord.Guild = modcog.bot.get_guild(int(guildid))
                toremove = []
                if Configuration.getConfigVar(int(guildid), "MUTE_ROLE") is 0:
                    guildstoremove.append(guildid)
                for userid, until in list.items():
                    if time.time() > until and userid not in skips:
                        member = guild.get_member(int(userid))
                        role = discord.utils.get(guild.roles, id=Configuration.getConfigVar(int(guildid), "MUTE_ROLE"))
                        if guild.me.guild_permissions.manage_roles:
                            await member.remove_roles(role, reason="Mute expired")
                            await GearbotLogging.logToModLog(guild,
                                                             f"<:gearInnocent:465177981287923712> {member.name}#{member.discriminator} (`{member.id}`) has automaticaly been unmuted")
                        else:
                            await GearbotLogging.logToModLog(guild,
                                                             f":no_entry: ERROR: {member.name}#{member.discriminator} (`{member.id}`) was muted earlier but I no longer have the permissions needed to unmute this person, please remove the role manually!")
                        updated = True
                        toremove.append(userid)
                for todo in toremove:
                    del list[todo]
                await asyncio.sleep(0)
            if updated:
                Utils.saveToDisk("mutes", modcog.mutes)
                updated = False
            for id in guildstoremove:
                del modcog.mutes[id]
            await asyncio.sleep(10)
        except CancelledError:
            pass  # bot shutdown
        except Exception as ex:
            GearbotLogging.error("Something went wrong in the unmute task")
            GearbotLogging.error(traceback.format_exc())
            skips.append(userid)
            embed = discord.Embed(colour=discord.Colour(0xff0000),
                                  timestamp=datetime.datetime.utcfromtimestamp(time.time()))

            embed.set_author(name="Something went wrong in the unmute task:")
            embed.add_field(name="Current guildid", value=guildid)
            embed.add_field(name="Current userid", value=userid)
            embed.add_field(name="Exception", value=ex)
            v = ""
            for line in traceback.format_exc().splitlines():
                if len(v) + len(line) > 1024:
                    embed.add_field(name="Stacktrace", value=v)
                    v = ""
                v = f"{v}\n{line}"
            if len(v) > 0:
                embed.add_field(name="Stacktrace", value=v)
            await GearbotLogging.logToBotlog(embed=embed)
            await asyncio.sleep(10)
    GearbotLogging.info("Unmute background task terminated")
Esempio n. 2
0
def load_config(guild):
    from Bot.TheRealGearBot import handle_exception
    global SERVER_CONFIGS
    try:
        config = Utils.fetch_from_disk(f'config/{guild}')
    except JSONDecodeError as e:
        GearbotLogging.error(f"Failed to deserialize config! {e}")
        asyncio.create_task(handle_exception("loading config", BOT, e))
        config = Utils.fetch_from_disk("template")
    if len(config.keys()) != 0 and "VERSION" not in config and len(
            config) < 15:
        GearbotLogging.info(
            f"The config for {guild} is to old to migrate, resetting")
        config = dict()
    elif len(config.keys()) != 0:
        if "VERSION" not in config:
            config["VERSION"] = 0
        SERVER_CONFIGS[guild] = update_config(guild, config)
    if len(config.keys()) == 0:
        GearbotLogging.info(
            f"No config available for {guild}, creating a blank one.")
        SERVER_CONFIGS[guild] = Utils.fetch_from_disk("template")
        save(guild)
    validate_config(guild)
    Features.check_server(guild)
Esempio n. 3
0
async def handle_database_error(bot):
    GearbotLogging.error(traceback.format_exc())
    # database trouble, notify bot owner
    message = f"{Emoji.get_chat_emoji('WARNING')} Peewee exception caught! attempting to reconnect to the database!"
    await GearbotLogging.message_owner(bot, message)
    await GearbotLogging.logToBotlog(message)

    try:
        DatabaseConnector.init()
        bot.database_connection = DatabaseConnector.connection
    except:
        # fail, trying again in 10 just in case the database is rebooting
        time.sleep(15)
        try:
            DatabaseConnector.init()
            bot.database_connection = DatabaseConnector.connection
        except:
            if os.path.isfile('stage_2.txt'):
                message = f"{Emoji.get_chat_emoji('NO')} VM reboot did not fix the problem, shutting down completely for fixes"
                await bot.get_user(bot.owner_id).dm_channel.send(message)
                await GearbotLogging.logToBotlog(message)
                with open("stage_3.txt", "w") as file:
                    file.write("stage_3")
                os.kill(os.getpid(), 9)
            elif os.path.isfile('stage_1.txt'):
                with open("stage_2.txt", "w") as file:
                    file.write("stage_2")
                message = f"{Emoji.get_chat_emoji('NO')} Reconnecting and bot rebooting failed, escalating to VM reboot"
                await GearbotLogging.message_owner(bot, message)
                await GearbotLogging.logToBotlog(message)
                data = {'type': 'reboot'}
                async with aiohttp.ClientSession(
                        headers=
                    {
                        'Content-Type':
                        'application/json',
                        'Authorization':
                        f'Bearer {Configuration.getMasterConfigVar("DO_TOKEN")}'
                    }) as session:
                    await session.post(
                        f'https://api.digitalocean.com/v2/droplets/{Configuration.getMasterConfigVar("DO_ID")}/actions',
                        data=json.dumps(data),
                        timeout=30)
                time.sleep(60)

            else:
                message = f"{Emoji.get_chat_emoji('NO')} Reconnecting failed, escalating to reboot"
                await GearbotLogging.message_owner(bot, message)
                await GearbotLogging.logToBotlog(message)
                with open("stage_1.txt", "w") as file:
                    file.write("stage_1")
                os.kill(os.getpid(), 9)
        else:
            message = f"{Emoji.get_chat_emoji('YES')} 2nd reconnection attempt successfully connected!"
            await GearbotLogging.message_owner(bot, message)
            await GearbotLogging.logToBotlog(message)
    else:
        message = f"{Emoji.get_chat_emoji('YES')} 1st reconnection attempt successfully connected!"
        await GearbotLogging.message_owner(bot, message)
        await GearbotLogging.logToBotlog(message)
Esempio n. 4
0
async def on_command_error(bot, ctx: commands.Context, error):
    if isinstance(error, NotCachedException):
        if bot.loading_task is not None:
            if bot.initial_fill_complete:
                await ctx.send(
                    f"{Emoji.get_chat_emoji('CLOCK')} Due to a earlier connection failure the cached data for this guild is no longer up to date and is being rebuild. Please try again in a few minutes."
                )
            else:
                await ctx.send(
                    f"{Emoji.get_chat_emoji('CLOCK')} GearBot is in the process of starting up and has not received the member info for this guild. Please try again in a few minutes."
                )
        else:
            await ctx.send(
                f"{Emoji.get_chat_emoji('CLOCK')} GearBot only just joined this guild and is still receiving the initial member info for this guild, please try again in a few seconds"
            )
    if isinstance(error, commands.BotMissingPermissions):
        GearbotLogging.error(
            f"Encountered a permission error while executing {ctx.command}: {error}"
        )
        await ctx.send(error)
    elif isinstance(error, commands.CheckFailure):
        if ctx.command.qualified_name is not "latest" and ctx.guild is not None and Configuration.get_var(
                ctx.guild.id, "GENERAL", "PERM_DENIED_MESSAGE"):
            await MessageUtils.send_to(ctx, 'LOCK', 'permission_denied')
    elif isinstance(error, commands.CommandOnCooldown):
        await ctx.send(error)
    elif isinstance(error, commands.MissingRequiredArgument):
        param = list(ctx.command.params.values())[min(
            len(ctx.args) + len(ctx.kwargs), len(ctx.command.params))]
        bot.help_command.context = ctx
        await ctx.send(
            f"{Emoji.get_chat_emoji('NO')} {Translator.translate('missing_arg', ctx, arg=param._name, error=Utils.replace_lookalikes(str(error)))}\n{Emoji.get_chat_emoji('WRENCH')} {Translator.translate('command_usage', ctx, usage=bot.help_command.get_command_signature(ctx.command))}"
        )
    elif isinstance(error, PostParseError):
        bot.help_command.context = ctx
        await ctx.send(
            f"{Emoji.get_chat_emoji('NO')} {Translator.translate('bad_argument', ctx, type=error.type, error=Utils.replace_lookalikes(str(error.error)))}\n{Emoji.get_chat_emoji('WRENCH')} {Translator.translate('command_usage', ctx, usage=bot.help_command.get_command_signature(ctx.command))}"
        )
    elif isinstance(error, commands.BadArgument):
        param = list(ctx.command.params.values())[min(
            len(ctx.args) + len(ctx.kwargs), len(ctx.command.params))]
        bot.help_command.context = ctx
        await ctx.send(
            f"{Emoji.get_chat_emoji('NO')} {Translator.translate('bad_argument', ctx, type=param._name, error=Utils.replace_lookalikes(str(error)))}\n{Emoji.get_chat_emoji('WRENCH')} {Translator.translate('command_usage', ctx, usage=bot.help_command.get_command_signature(ctx.command))}"
        )
    elif isinstance(error, commands.CommandNotFound):
        return

    else:
        await handle_exception(
            "Command execution failed",
            bot,
            error.original if hasattr(error, "original") else error,
            ctx=ctx)
        # notify caller
        e = Emoji.get_chat_emoji('BUG')
        if ctx.channel.permissions_for(ctx.me).send_messages:
            await ctx.send(
                f"{e} Something went wrong while executing that command. If this keeps happening please report it on support server (DM me ``!about`` or check the website for an invite) {e}"
            )
Esempio n. 5
0
def translate(key, location, **kwargs):
    lid = None
    if location is not None:
        if hasattr(location, "guild"):
            location = location.guild
        if location is not None and hasattr(location, "id"):
            lid = location.id
        else:
            lid = location

    if lid is None:
        lang_key = "en_US"
    else:
        lang_key = Configuration.get_var(lid, "LANG")
    translated = key
    if key not in LANGS[lang_key]:
        if key not in untranlatable:
            BOT.loop.create_task(tranlator_log('WARNING', f'Untranslatable string detected: {key}\n'))
            untranlatable.add(key)
        return key if key not in LANGS["en_US"] else format(LANGS['en_US'][key], kwargs, 'en_US')
    try:
        translated = format(LANGS[lang_key][key], kwargs, lang_key)
    except (KeyError, ValueError, ParseError, VisitationError) as ex:
        BOT.loop.create_task(tranlator_log('NO', f'Corrupt translation detected!\n**Lang code:** {lang_key}\n**Translation key:** {key}\n```\n{LANGS[lang_key][key]}```'))
        GearbotLogging.exception("Corrupt translation", ex)
        GearbotLogging.error(ex)
        if key in LANGS["en_US"].keys():
            try:
                translated = format(LANGS['en_US'][key], kwargs, 'en_US')
            except (KeyError, ValueError, ParseError, VisitationError) as ex:
                BOT.loop.create_task(tranlator_log('NO', f'Corrupt English source string detected!\n**Translation key:** {key}\n```\n{LANGS["en_US"][key]}```'))
                GearbotLogging.error(ex)
    return translated
Esempio n. 6
0
async def on_command_error(bot, ctx: commands.Context, error):
    if isinstance(error, commands.BotMissingPermissions):
        GearbotLogging.error(f"Encountered a permission error while executing {ctx.command}: {error}")
        await ctx.send(error)
    elif isinstance(error, commands.CheckFailure):
        if ctx.command.qualified_name is not "latest" and ctx.guild is not None and Configuration.get_var(ctx.guild.id, "GENERAL", "PERM_DENIED_MESSAGE"):
            await MessageUtils.send_to(ctx, 'LOCK', 'permission_denied')
    elif isinstance(error, commands.CommandOnCooldown):
        await ctx.send(error)
    elif isinstance(error, commands.MissingRequiredArgument):
        param = list(ctx.command.params.values())[min(len(ctx.args) + len(ctx.kwargs), len(ctx.command.params))]
        bot.help_command.context = ctx
        await ctx.send(
            f"{Emoji.get_chat_emoji('NO')} {Translator.translate('missing_arg', ctx, arg=param._name, error=Utils.replace_lookalikes(str(error)))}\n{Emoji.get_chat_emoji('WRENCH')} {Translator.translate('command_usage', ctx, usage=bot.help_command.get_command_signature(ctx.command))}")
    elif isinstance(error, PostParseError):
        bot.help_command.context = ctx
        await ctx.send(f"{Emoji.get_chat_emoji('NO')} {Translator.translate('bad_argument', ctx, type=error.type, error=Utils.replace_lookalikes(str(error.error)))}\n{Emoji.get_chat_emoji('WRENCH')} {Translator.translate('command_usage', ctx, usage=bot.help_command.get_command_signature(ctx.command))}")
    elif isinstance(error, commands.BadArgument):
        param = list(ctx.command.params.values())[min(len(ctx.args) + len(ctx.kwargs), len(ctx.command.params))]
        bot.help_command.context = ctx
        await ctx.send(f"{Emoji.get_chat_emoji('NO')} {Translator.translate('bad_argument', ctx, type=param._name, error=Utils.replace_lookalikes(str(error)))}\n{Emoji.get_chat_emoji('WRENCH')} {Translator.translate('command_usage', ctx, usage=bot.help_command.get_command_signature(ctx.command))}")
    elif isinstance(error, commands.CommandNotFound):
        return
    elif isinstance(error, PeeweeException):
        await handle_database_error(bot)

    else:
        await handle_exception("Command execution failed", bot, error.original if hasattr(error, "original") else error, ctx=ctx)
        # notify caller
        e = Emoji.get_chat_emoji('BUG')
        if ctx.channel.permissions_for(ctx.me).send_messages:
            await ctx.send(f"{e} Something went wrong while executing that command {e}")
Esempio n. 7
0
async def translation_task(bot):
    while not bot.is_closed():
        try:
            await Translator.update()
        except Exception as ex:
            GearbotLogging.error(
                "Something went wrong during translation updates")
            GearbotLogging.error(traceback.format_exc())
            embed = Embed(colour=Colour(0xff0000),
                          timestamp=datetime.utcfromtimestamp(time.time()))
            embed.set_author(
                name="Something went wrong during translation updates")
            embed.add_field(name="Exception", value=str(ex))
            v = ""
            for line in traceback.format_exc().splitlines():
                if len(v) + len(line) >= 1024:
                    embed.add_field(name="Stacktrace", value=v)
                    v = ""
                v = f"{v}\n{line}"
            if len(v) > 0:
                embed.add_field(name="Stacktrace", value=v)
            await GearbotLogging.bot_log(embed=embed)

        try:
            await asyncio.sleep(6 * 60 * 60)
        except asyncio.CancelledError:
            pass  # bot shutting down
Esempio n. 8
0
async def initialize(bot):
    #lock event handling while we get ready
    bot.locked = True
    try:
        #database
        GearbotLogging.info("Connecting to the database.")
        DatabaseConnector.init()
        bot.database_connection = DatabaseConnector.connection
        GearbotLogging.info("Database connection established.")

        GearbotLogging.initialize_pump(bot)
        Emoji.initialize(bot)
        Pages.initialize(bot)
        Utils.initialize(bot)
        Translator.initialize(bot)
        InfractionUtils.initialize(bot)
        bot.data = {
            "forced_exits": set(),
            "unbans": set(),
            "message_deletes": set()
        }
        await GearbotLogging.initialize(
            bot, Configuration.get_master_var("BOT_LOG_CHANNEL"))

        if bot.redis_pool is None or not hasattr(
                bot, 'redis_raid_pool') or bot.redis_raid_pool is None:
            try:
                bot.redis_pool = await aioredis.create_redis_pool(
                    (Configuration.get_master_var('REDIS_HOST', "localhost"),
                     Configuration.get_master_var('REDIS_PORT', 6379)),
                    encoding="utf-8",
                    db=0)
                bot.redis_raid_pool = await aioredis.create_redis_pool(
                    (Configuration.get_master_var('REDIS_HOST', "localhost"),
                     Configuration.get_master_var('REDIS_PORT', 6379)),
                    encoding="utf-8",
                    db=1)
            except OSError:
                GearbotLogging.error(
                    "==============Failed to connect to redis==============")
                await GearbotLogging.bot_log(
                    f"{Emoji.get_chat_emoji('NO')} Failed to connect to redis, caching and anti-raid connections unavailable"
                )
            else:
                GearbotLogging.info("Redis connection established")
                await GearbotLogging.bot_log(
                    f"{Emoji.get_chat_emoji('YES')} Redis connection established, caching and anti-raid connections established"
                )

        if bot.aiosession is None:
            bot.aiosession = aiohttp.ClientSession()
        bot.being_cleaned.clear()
        await Configuration.initialize(bot)
    except Exception as ex:
        #make sure we always unlock, even when something went wrong!
        bot.locked = False
        raise ex
    bot.locked = False
Esempio n. 9
0
    async def fetch_info(self, project_name):
        session: aiohttp.ClientSession = self.bot.aiosession
        async with session.get(f"https://api.cfwidget.com/mc-mods/minecraft/{project_name}") as reply:
            if reply.status is 200:  # all good, we can parse it
                parsed = json.loads(await reply.text())
                p_type = parsed["type"]
                info = {
                    "title": parsed["title"],
                    "type": f'{parsed["game"]} {p_type[:-1] if p_type.endswith("s") else p_type}',
                    "updated": parsed["last_fetch"],
                    "categories": parsed["categories"],
                    "links": dict(),
                    "thumbnail": parsed["thumbnail"],
                    "downloads": parsed["downloads"]["total"]
                }

                for link in parsed["links"]:
                    info["links"][link["title"]] = link["href"]

                mc_versions = []
                for k, v in parsed["versions"].items():
                    if "Java" not in k:
                        mc_versions.append(k)
                sorted = VersionInfo.getSortedVersions(mc_versions)
                map = OrderedDict()
                for version in sorted:
                    mod_versions_unsorted = dict()
                    mod_versions = OrderedDict()
                    version_list = []
                    for v2 in parsed["versions"][version]:
                        mod_versions_unsorted[v2["id"]] = v2
                        version_list.append(v2["id"])

                    version_list.sort()
                    version_list.reverse()
                    for v3 in version_list:
                        mod_versions[v3] = mod_versions_unsorted[v3]

                    map[version] = mod_versions
                info["versions"] = map
                return info

            elif reply.status is 202:  # New project, wait for the api to fetch it
                GearbotLogging.info(f"Info for {project_name} not available yet, trying again in 10 seconds.")
                await asyncio.sleep(10)
                return await self.fetch_info(project_name)
            elif reply.status in (400, 404):
                return None
            elif reply.status is 500:
                GearbotLogging.error(f"Fetching info for {project_name} failed.")
                return False
            else:
                GearbotLogging.error(
                    f"Got unexpected response code ({reply.status}) when fetching info for {project_name}.")
                return None  # TODO: handle failure
Esempio n. 10
0
def loadGlobalConfig():
    global MASTER_CONFIG, master_loaded
    try:
        with open('config/master.json', 'r') as jsonfile:
            MASTER_CONFIG = json.load(jsonfile)
            master_loaded = True
    except FileNotFoundError:
        GearbotLogging.error("Unable to load config, running with defaults.")
    except Exception as e:
        GearbotLogging.error("Failed to parse configuration.")
        print(e)
        raise e
Esempio n. 11
0
def gen_command_listing(command):
    try:
        listing = f"|{command.qualified_name}|{Permissioncheckers.get_perm_dict(command.qualified_name.split(' '), command.instance.permissions)['required']}|{Translator.translate(command.short_doc, None)}|\n"
    except Exception as ex:
        GearbotLogging.error(command.qualified_name)
        raise ex
    else:
        if isinstance(command, GroupMixin) and hasattr(command,
                                                       "all_commands"):
            for c in command.all_commands.values():
                listing += gen_command_listing(c)
        return listing
Esempio n. 12
0
async def initialize(bot, startup=False):
    #lock event handling while we get ready
    bot.locked = True
    try:
        #database
        GearbotLogging.info("Connecting to the database.")
        DatabaseConnector.init()
        bot.database_connection = DatabaseConnector.connection
        GearbotLogging.info("Database connection established.")

        Emoji.initialize(bot)
        Utils.initialize(bot)
        InfractionUtils.initialize(bot)
        bot.data = {
            "forced_exits": set(),
            "unbans": set(),
            "message_deletes": set(),
            "nickname_changes": set()
        }
        await GearbotLogging.initialize(bot, Configuration.get_master_var("BOT_LOG_CHANNEL"))
        if startup:
            c = await Utils.get_commit()
            bot.version = c
            GearbotLogging.info(f"GearBot spinning up version {c}")
            await GearbotLogging.bot_log(f"{Emoji.get_chat_emoji('ALTER')} GearBot spinning up version {c}")

        if bot.redis_pool is None:
            try:
                socket = Configuration.get_master_var("REDIS_SOCKET", "")
                if socket == "":
                    bot.redis_pool = await aioredis.create_redis_pool((Configuration.get_master_var('REDIS_HOST', "localhost"), Configuration.get_master_var('REDIS_PORT', 6379)), encoding="utf-8", db=0)
                else:
                    bot.redis_pool = await aioredis.create_redis_pool(socket, encoding="utf-8", db=0)
            except OSError:
                GearbotLogging.error("==============Failed to connect to redis==============")
                await GearbotLogging.bot_log(f"{Emoji.get_chat_emoji('NO')} Failed to connect to redis, caching unavailable")
            else:
                GearbotLogging.info("Redis connection established")
                await GearbotLogging.bot_log(f"{Emoji.get_chat_emoji('YES')} Redis connection established, let's go full speed!")

        if bot.aiosession is None:
            bot.aiosession = aiohttp.ClientSession()

        await Translator.initialize(bot)
        bot.being_cleaned.clear()
        await Configuration.initialize(bot)
        DashConfig.initialize(bot)
    except Exception as ex:
        #make sure we always unlock, even when something went wrong!
        bot.locked = False
        raise ex
    bot.locked = False
Esempio n. 13
0
    async def dash_monitor(self):
        DASH_OUTAGE_INFO: dict = Configuration.get_master_var("DASH_OUTAGE")
        DASH_OUTAGE_CHANNEl = DASH_OUTAGE_INFO["dash_outage_channel"]
        MAX_WARNINGS = DASH_OUTAGE_INFO["max_bot_outage_warnings"]
        BOT_OUTAGE_PINGED_ROLES = DASH_OUTAGE_INFO["dash_outage_pinged_roles"]

        while True:
            if (time.time() - self.last_dash_heartbeat[0]) > 5:
                self.last_dash_heartbeat[1] += 1

                if self.last_dash_heartbeat[
                        1] >= 3 and self.last_dash_heartbeat[2] < MAX_WARNINGS:
                    print(
                        "The dashboard API keepalive hasn't responded in over 3 minutes!"
                    )

                    self.last_dash_heartbeat[2] += 1
                    self.last_dash_heartbeat[1] = 0

                    if DASH_OUTAGE_CHANNEl:
                        outage_message = DASH_OUTAGE_INFO["dash_outage_embed"]

                        # Apply the timestamp
                        outage_message["timestamp"] = datetime.now().isoformat(
                        )

                        # Set the color to the format Discord understands
                        outage_message["color"] = outage_message["color"]

                        # Generate the custom message and role pings
                        notify_message = DASH_OUTAGE_INFO[
                            "dash_outage_message"]
                        if BOT_OUTAGE_PINGED_ROLES:
                            pinged_roles = []
                            for role_id in BOT_OUTAGE_PINGED_ROLES:
                                pinged_roles.append(f"<@&{role_id}>")

                            notify_message += f" Pinging: {', '.join(pinged_roles)}"

                        try:
                            outage_channel = self.bot.get_channel(
                                DASH_OUTAGE_CHANNEl)
                            await outage_channel.send(
                                notify_message,
                                embed=Embed.from_dict(outage_message))
                        except Forbidden:
                            GearbotLogging.error(
                                "We couldn't access the specified channel, the notification will not be sent!"
                            )

            # Wait a little bit longer so the dashboard has a chance to update before we check
            await asyncio.sleep(65)
Esempio n. 14
0
async def versionChecker(checkcog:BCVersionChecker):
    GearbotLogging.info("Started BC version checking background task")
    session:aiohttp.ClientSession = checkcog.bot.aiosession
    reply:aiohttp.ClientResponse
    lastUpdate = 0
    while checkcog.running:
        try:
            async with session.get('https://www.mod-buildcraft.com/build_info_full/last_change.txt') as reply:
                stamp = await reply.text()
                stamp = int(stamp[:-1])
                if stamp > lastUpdate:
                    GearbotLogging.info("New BC version somewhere!")
                    lastUpdate = stamp
                    checkcog.BC_VERSION_LIST = await getList(session, "BuildCraft")
                    checkcog.BCC_VERSION_LIST = await getList(session, "BuildCraftCompat")
                    highestMC = VersionInfo.getLatest(checkcog.BC_VERSION_LIST.keys())
                    latestBC = VersionInfo.getLatest(checkcog.BC_VERSION_LIST[highestMC])
                    generalID = 309218657798455298
                    channel:discord.TextChannel = checkcog.bot.get_channel(generalID)
                    if channel is not None and latestBC not in channel.topic:
                        info = await checkcog.getVersionDetails("BuildCraft", latestBC)
                        newTopic = f"General discussions about BuildCraft.\n" \
                                   f"Latest version: {latestBC}\n" \
                                   f"Full changelog and download: {info['blog_entry']}"
                        await channel.edit(topic=newTopic)
                    pass
                pass
        except CancelledError:
            pass  # bot shutdown
        except Exception as ex:
            checkcog.bot.errors = checkcog.bot.errors + 1
            GearbotLogging.error("Something went wrong in the BC version checker task")
            GearbotLogging.error(traceback.format_exc())
            embed = discord.Embed(colour=discord.Colour(0xff0000),
                                  timestamp=datetime.datetime.utcfromtimestamp(time.time()))
            embed.set_author(name="Something went wrong in the BC version checker task:")
            embed.add_field(name="Exception", value=str(ex))
            v = ""
            for line in traceback.format_exc().splitlines():
                if len(v) + len(line) >= 1024:
                    embed.add_field(name="Stacktrace", value=v)
                    v = ""
                v = f"{v}\n{line}"
            if len(v) > 0:
                embed.add_field(name="Stacktrace", value=v)
            await GearbotLogging.bot_log(embed=embed)
        for i in range(1,60):
            if checkcog.force or not checkcog.running:
                break
            await asyncio.sleep(10)

    GearbotLogging.info("BC version checking background task terminated")
Esempio n. 15
0
def gen_command_listing(bot, cog, command, code):
    try:
        perm_lvl = Permissioncheckers.get_perm_dict(
            command.qualified_name.split(' '), cog.permissions)['required']
        listing = f"| | | {Translator.translate_by_code(command.short_doc, code)} |\n"
        listing += f"|{command.qualified_name}|{Translator.translate_by_code(f'perm_lvl_{perm_lvl}', code)} ({perm_lvl})| |\n"
        signature = bot.help_command.get_command_signature(command).replace(
            "|", "ǀ")
        listing += f"| | |{Translator.translate_by_code('example', code)}: ``{signature}``|\n"
    except Exception as ex:
        GearbotLogging.error(command.qualified_name)
        raise ex
    return listing
Esempio n. 16
0
async def on_command_error(bot, ctx: commands.Context, error):
    if isinstance(error, commands.NoPrivateMessage):
        await ctx.send("This command cannot be used in private messages.")
    elif isinstance(error, commands.BotMissingPermissions):
        GearbotLogging.error(
            f"Encountered a permission error while executing {ctx.command}: {error}"
        )
        await ctx.send(error)
    elif isinstance(error, commands.DisabledCommand):
        await ctx.send("Sorry. This command is disabled and cannot be used.")
    elif isinstance(error, commands.CheckFailure):
        if ctx.command.qualified_name is not "latest" and ctx.guild is not None and Configuration.get_var(
                ctx.guild.id, "PERM_DENIED_MESSAGE"):
            await ctx.send(
                ":lock: You do not have the required permissions to run this command"
            )
    elif isinstance(error, commands.CommandOnCooldown):
        await ctx.send(error)
    elif isinstance(error, commands.MissingRequiredArgument):
        param = list(ctx.command.params.values())[min(
            len(ctx.args) + len(ctx.kwargs), len(ctx.command.params))]
        await ctx.send(
            f"{Emoji.get_chat_emoji('NO')} {Translator.translate('missing_arg', ctx, arg=param._name, error=error)}\n{Emoji.get_chat_emoji('WRENCH')} {Translator.translate('command_usage', ctx, usage=ctx.prefix.replace(ctx.me.mention, f'@{ctx.me.name}') + ctx.command.signature)}"
        )
    elif isinstance(error, commands.BadArgument):
        param = list(ctx.command.params.values())[min(
            len(ctx.args) + len(ctx.kwargs), len(ctx.command.params))]
        await ctx.send(
            f"{Emoji.get_chat_emoji('NO')} {Translator.translate('bad_argument', ctx, type=param._name, error=error)}\n{Emoji.get_chat_emoji('WRENCH')} {Translator.translate('command_usage', ctx, usage=ctx.prefix.replace(ctx.me.mention, f'@{ctx.me.name}') + ctx.command.signature)}"
        )
    elif isinstance(error, commands.CommandNotFound):
        return
    elif isinstance(error, PeeweeException):
        await handle_database_error(bot)

    else:
        await handle_exception("Command execution failed",
                               bot,
                               error.original,
                               ctx=ctx)
        # notify caller
        await ctx.send(
            ":rotating_light: Something went wrong while executing that command :rotating_light:"
        )
Esempio n. 17
0
def gen_command_listing2(bot, cog, command):
    command_listing = dict()
    try:
        perm_lvl = Permissioncheckers.get_perm_dict(
            command.qualified_name.split(' '), cog.permissions)['required']
        command_listing["commandlevel"] = perm_lvl
        command_listing["description"] = command.short_doc
        command_listing["aliases"] = command.aliases
        example = bot.help_command.get_command_signature(command).strip()
        parts = str(example).split(' ')
        parts[0] = ''.join(parts[0][1:])
        for i in range(0, len(parts)):
            if "[" == parts[i][0] and "|" in parts[i]:
                parts[i] = ''.join(parts[i].split('|')[0][1:])
        command_listing["example"] = '!' + ' '.join(parts)
        command_listing["subcommands"] = {}
        return command_listing
    except Exception as ex:
        GearbotLogging.error(command.qualified_name)
        raise ex
Esempio n. 18
0
async def on_error(bot, event, *args, **kwargs):
    type, exception, info = sys.exc_info()
    if isinstance(exception, PeeweeException):
        await handle_database_error(bot)
    try:
        # something went wrong and it might have been in on_command_error, make sure we log to the log file first
        bot.errors = bot.errors + 1
        GearbotLogging.error(f"error in {event}\n{args}\n{kwargs}")
        embed = discord.Embed(colour=discord.Colour(0xff0000),
                              timestamp=datetime.datetime.utcfromtimestamp(
                                  time.time()))

        embed.set_author(name=f"Caught an error in {event}:")

        embed.add_field(name="args", value=str(args))
        embed.add_field(name="kwargs", value=str(kwargs))
        embed.add_field(name="cause message", value=traceback._cause_message)
        v = ""
        for line in traceback.format_exc():
            if len(v) + len(line) > 1024:
                embed.add_field(name="Stacktrace", value=v)
                v = ""
            v = f"{v}{line}"
        if len(v) > 0:
            embed.add_field(name="Stacktrace", value=v)
            # try logging to botlog, wrapped in an try catch as there is no higher lvl catching to prevent taking donwn the bot (and if we ended here it might have even been due to trying to log to botlog
        await GearbotLogging.logToBotlog(embed=embed)
    except Exception as ex:
        GearbotLogging.error(
            f"Failed to log to botlog, either Discord broke or something is seriously wrong!\n{ex}"
        )
        GearbotLogging.error(traceback.format_exc())
Esempio n. 19
0
def translate(key, location, **kwargs):
    lid = None
    if location is not None:
        if hasattr(location, "guild"):
            location = location.guild
        if location is not None and hasattr(location, "id"):
            lid = location.id
        else:
            lid = location

    if lid is None:
        lang_key = "en_US"
    else:
        lang_key = Configuration.get_var(lid, "LANG")
    if key in LANGS[lang_key].keys():
        try:
            return LANGS[lang_key][key].format(**kwargs)
        except (KeyError, ValueError):
            GearbotLogging.error(
                f"Corrupt translation detected in {lang_key}: {key}\n```\n{LANGS[lang_key][key]}```"
            )
    if key in LANGS["en_US"].keys():
        return LANGS["en_US"][key].format(**kwargs)
    return key
Esempio n. 20
0
async def handle_exception(exception_type,
                           bot,
                           exception,
                           event=None,
                           message=None,
                           ctx=None,
                           *args,
                           **kwargs):
    if bot is not None:
        bot.errors = bot.errors + 1
    with sentry_sdk.push_scope() as scope:
        embed = Embed(colour=Colour(0xff0000),
                      timestamp=datetime.utcfromtimestamp(time.time()))

        # something went wrong and it might have been in on_command_error, make sure we log to the log file first
        lines = [
            "\n===========================================EXCEPTION CAUGHT, DUMPING ALL AVAILABLE INFO===========================================",
            f"Type: {exception_type}"
        ]

        arg_info = ""
        for arg in list(args):
            arg_info += extract_info(arg) + "\n"
        if arg_info == "":
            arg_info = "No arguments"

        kwarg_info = ""
        for name, arg in kwargs.items():
            kwarg_info += "{}: {}\n".format(name, extract_info(arg))
        if kwarg_info == "":
            kwarg_info = "No keyword arguments"

        lines.append("======================Exception======================")
        lines.append(f"{str(exception)} ({type(exception)})")

        lines.append("======================ARG INFO======================")
        lines.append(arg_info)
        sentry_sdk.add_breadcrumb(category='arg info',
                                  message=arg_info,
                                  level='info')

        lines.append("======================KWARG INFO======================")
        lines.append(kwarg_info)
        sentry_sdk.add_breadcrumb(category='kwarg info',
                                  message=kwarg_info,
                                  level='info')

        lines.append("======================STACKTRACE======================")
        tb = "".join(traceback.format_tb(exception.__traceback__))
        lines.append(tb)

        if message is None and event is not None and hasattr(event, "message"):
            message = event.message

        if message is None and ctx is not None:
            message = ctx.message

        if message is not None and hasattr(message, "content"):
            lines.append(
                "======================ORIGINAL MESSAGE======================")
            lines.append(message.content)
            if message.content is None or message.content == "":
                content = "<no content>"
            else:
                content = message.content
            scope.set_tag('message content', content)
            embed.add_field(name="Original message",
                            value=Utils.trim_message(content, 1000),
                            inline=False)

            lines.append(
                "======================ORIGINAL MESSAGE (DETAILED)======================"
            )
            lines.append(extract_info(message))

        if event is not None:
            lines.append(
                "======================EVENT NAME======================")
            lines.append(event)
            scope.set_tag('event name', event)
            embed.add_field(name="Event", value=event)

        if ctx is not None:
            lines.append(
                "======================COMMAND INFO======================")

            lines.append(f"Command: {ctx.command.name}")
            embed.add_field(name="Command", value=ctx.command.name)
            scope.set_tag('command', ctx.command.name)

            channel_name = 'Private Message' if isinstance(
                ctx.channel,
                PrivateChannel) else f"{ctx.channel.name} (`{ctx.channel.id}`)"
            lines.append(f"Channel: {channel_name}")
            embed.add_field(name="Channel", value=channel_name, inline=False)
            scope.set_tag('channel', channel_name)

            sender = f"{str(ctx.author)} (`{ctx.author.id}`)"
            scope.user = dict(id=ctx.author.id, username=str(ctx.author))
            lines.append(f"Sender: {sender}")
            embed.add_field(name="Sender", value=sender, inline=False)

        lines.append(
            "===========================================DATA DUMP COMPLETE==========================================="
        )
        GearbotLogging.error("\n".join(lines))

        for t in [ConnectionClosed, ClientOSError, ServerDisconnectedError]:
            if isinstance(exception, t):
                return
        #nice embed for info on discord

        embed.set_author(name=exception_type)
        embed.add_field(name="Exception",
                        value=f"{str(exception)} (`{type(exception)}`)",
                        inline=False)
        parts = Pages.paginate(tb, max_chars=1024)
        num = 1
        for part in parts:
            embed.add_field(name=f"Traceback {num}/{len(parts)}", value=part)
            num += 1
        sentry_sdk.capture_exception(exception)
    # try logging to botlog, wrapped in an try catch as there is no higher lvl catching to prevent taking down the bot (and if we ended here it might have even been due to trying to log to botlog
    try:
        await GearbotLogging.bot_log(embed=embed)
    except Exception as ex:
        GearbotLogging.error(
            f"Failed to log to botlog, either Discord broke or something is seriously wrong!\n{ex}"
        )
        GearbotLogging.error(traceback.format_exc())
Esempio n. 21
0
async def updater(cog: BCVersionChecker):
    GearbotLogging.info("Started BC version checking background task")
    session: aiohttp.ClientSession = cog.bot.aiosession
    lastUpdate = 0
    while cog.running:
        try:
            # check for a newer bc version
            async with session.get(
                    'https://www.mod-buildcraft.com/build_info_full/last_change.txt'
            ) as reply:
                stamp = await reply.text()
                stamp = int(stamp[:-1])
                if stamp > lastUpdate:
                    GearbotLogging.info("New BC version somewhere!")
                    lastUpdate = stamp
                    cog.BC_VERSION_LIST = await getList(session, "BuildCraft")
                    cog.BCC_VERSION_LIST = await getList(
                        session, "BuildCraftCompat")
                    highestMC = VersionInfo.getLatest(
                        cog.BC_VERSION_LIST.keys())
                    latestBC = VersionInfo.getLatest(
                        cog.BC_VERSION_LIST[highestMC])
                    generalID = 309218657798455298
                    channel: discord.TextChannel = cog.bot.get_channel(
                        generalID)
                    old_latest = Configuration.get_persistent_var(
                        "latest_bc", "0.0.0")
                    Configuration.set_persistent_var(
                        "latest_bc", latestBC
                    )  # save already so we don't get stuck and keep trying over and over if something goes wrong
                    if channel is not None and latestBC != old_latest:
                        GearbotLogging.info(
                            f"New BuildCraft version found: {latestBC}")
                        notify_channel = cog.bot.get_channel(
                            349517224320565258)
                        await notify_channel.send(
                            f"{Emoji.get_chat_emoji('WRENCH')} New BuildCraft version detected ({latestBC})"
                        )
                        GearbotLogging.info(
                            f"Fetching metadata for BuildCraft {latestBC}")
                        message = await notify_channel.send(
                            f"{Emoji.get_chat_emoji('REFRESH')} Fetching metadata..."
                        )
                        info = await cog.getVersionDetails(
                            "BuildCraft", latestBC)
                        GearbotLogging.info(f"Metadata acquired: {info}")
                        await message.edit(
                            content=
                            f"{Emoji.get_chat_emoji('YES')} Metadata acquired")
                        if 'blog_entry' in info:
                            message = await notify_channel.send(
                                f"{Emoji.get_chat_emoji('REFRESH')} Updating general topic..."
                            )
                            newTopic = f"General discussions about BuildCraft.\n" \
                                f"Latest version: {latestBC}\n" \
                                f"Full changelog and download: {info['blog_entry']}"
                            await channel.edit(topic=newTopic)
                            await message.edit(
                                content=
                                f"{Emoji.get_chat_emoji('YES')} Topic updated")
                        else:
                            notify_channel.send(
                                f"{Emoji.get_chat_emoji('WARNING')} No blog post data found, notifying <@180057061353193472>"
                            )

                        # message = await notify_channel.send(f"{Emoji.get_chat_emoji('REFRESH')} Uploading files to CurseForge...")
                        # code, output, errors = await Utils.execute(f'cd BuildCraft/uploader && gradle curseforge -Pnew_version="{latestBC}"')
                        # GearbotLogging.info(f"Upload to CF complete\n)------stdout------\n{output}\n------stderr------\n{errors}")
                        # if code is 0:
                        #     content = f"{Emoji.get_chat_emoji('YES')} All archives successfully uploaded"
                        #     await message.edit(content=content)
                        # else:
                        #     content = f"{Emoji.get_chat_emoji('NO')} Upload failed with code {code}, notifying <@106354106196570112>"
                        #     await notify_channel.send(content)

            # update FAQs if needed
            async with session.get(
                    'https://mod-buildcraft.com/website_src/faq.md') as reply:
                data = await reply.text()
                h = hashlib.md5(data.encode('utf-8')).hexdigest()
                old = Configuration.get_persistent_var("BCFAQ", "")
                channel = cog.bot.get_channel(361557801492938762)  # FAQs
                if channel is not None and h != old:
                    Configuration.set_persistent_var("BCFAQ", h)
                    #clean the old stuff
                    await channel.purge()

                    #send banner
                    with open("BuildCraft/FAQs.png", "rb") as file:
                        await channel.send(file=File(file, filename="FAQs.png")
                                           )
                    #send content
                    out = ""
                    parts = [
                        d.strip("#").strip() for d in data.split("##")[1:]
                    ]
                    for part in parts:
                        lines = part.splitlines()
                        content = '\n'.join(lines[1:])
                        out += f"**```{lines[0].strip()}```**{content}\n"
                    for page in Pages.paginate(out,
                                               max_chars=2048,
                                               max_lines=50):
                        embed = Embed(description=page)
                        await channel.send(embed=embed)

                pass
        except CancelledError:
            pass  # bot shutdown
        except Exception as ex:
            cog.bot.errors = cog.bot.errors + 1
            GearbotLogging.error(
                "Something went wrong in the BC version checker task")
            GearbotLogging.error(traceback.format_exc())
            embed = discord.Embed(colour=discord.Colour(0xff0000),
                                  timestamp=datetime.datetime.utcfromtimestamp(
                                      time.time()))
            embed.set_author(
                name="Something went wrong in the BC version checker task:")
            embed.add_field(name="Exception", value=str(ex))
            v = ""
            for line in traceback.format_exc().splitlines():
                if len(v) + len(line) >= 1024:
                    embed.add_field(name="Stacktrace", value=v)
                    v = ""
                v = f"{v}\n{line}"
            if len(v) > 0:
                embed.add_field(name="Stacktrace", value=v)
            await GearbotLogging.bot_log(embed=embed)
        for i in range(1, 60):
            if cog.force or not cog.running:
                break
            await asyncio.sleep(10)

    GearbotLogging.info("BC version checking background task terminated")
Esempio n. 22
0
async def on_command_error(bot, ctx: commands.Context, error):
    if isinstance(error, commands.NoPrivateMessage):
        await ctx.send("This command cannot be used in private messages.")
    elif isinstance(error, commands.BotMissingPermissions):
        GearbotLogging.error(
            f"Encountered a permission error while executing {ctx.command}.")
        await ctx.send(error)
    elif isinstance(error, commands.DisabledCommand):
        await ctx.send("Sorry. This command is disabled and cannot be used.")
    elif isinstance(error, commands.CheckFailure):
        if ctx.command.qualified_name is not "latest" and ctx.guild is not None and Configuration.getConfigVar(
                ctx.guild.id, "PERM_DENIED_MESSAGE"):
            await ctx.send(
                ":lock: You do not have the required permissions to run this command"
            )
    elif isinstance(error, commands.CommandOnCooldown):
        await ctx.send(error)
    elif isinstance(error, commands.MissingRequiredArgument):
        await ctx.send(
            f"You are missing a required argument! (See {ctx.prefix}help {ctx.command.qualified_name} for info on how to use this command)."
        )
    elif isinstance(error, commands.BadArgument):
        await ctx.send(
            f"Invalid argument given! (See {ctx.prefix}help {ctx.command.qualified_name} for info on how to use this commmand)."
        )
    elif isinstance(error, commands.CommandNotFound):
        return
    elif isinstance(error, PeeweeException):
        await handle_database_error(bot)

    else:
        bot.errors = bot.errors + 1
        # log to logger first just in case botlog logging fails as well
        GearbotLogging.exception(
            f"Command execution failed:\n"
            f"    Command: {ctx.command}\n"
            f"    Message: {ctx.message.content}\n"
            f"    Channel: {'Private Message' if isinstance(ctx.channel, abc.PrivateChannel) else ctx.channel.name}\n"
            f"    Sender: {ctx.author.name}#{ctx.author.discriminator}\n"
            f"    Exception: {error}", error.original)
        # notify caller
        await ctx.send(
            ":rotating_light: Something went wrong while executing that command :rotating_light:"
        )

        embed = discord.Embed(colour=discord.Colour(0xff0000),
                              timestamp=datetime.datetime.utcfromtimestamp(
                                  time.time()))

        embed.set_author(name="Command execution failed:")
        embed.add_field(name="Command", value=ctx.command)
        embed.add_field(name="Original message",
                        value=Utils.trim_message(ctx.message.content, 1024))
        embed.add_field(name="Channel",
                        value='Private Message' if isinstance(
                            ctx.channel, abc.PrivateChannel) else
                        f"{ctx.channel.name} ({ctx.channel.id})")
        embed.add_field(name="Sender",
                        value=f"{ctx.author.name}#{ctx.author.discriminator}")
        embed.add_field(name="Exception", value=error.original)
        v = ""
        for line in traceback.format_tb(error.original.__traceback__):
            if len(v) + len(line) > 1024:
                embed.add_field(name="Stacktrace", value=v)
                v = ""
            v = f"{v}\n{line}"
        if len(v) > 0:
            embed.add_field(name="Stacktrace", value=v)
        await GearbotLogging.logToBotlog(embed=embed)