Exemplo n.º 1
0
    def __init__(self, *args, **kwargs):
        self.logger = FakeLogger()
        self.config: dict = {}
        self.reload_config()
        #activity = discord.Game(self.config["bot"]["playing"])
        self.current_event: Events = Events.CALM
        activity = discord.Game(self.current_event.value[0])
        super().__init__(*args,
                         command_prefix=get_prefix,
                         activity=activity,
                         case_insensitive=self.config["bot"]
                         ["commands_are_case_insensitive"],
                         **kwargs)
        self.commands_used = collections.Counter()
        self.uptime = datetime.datetime.utcnow()
        self.shards_ready = set()
        self._client_session: Optional[aiohttp.ClientSession] = None
        self.ducks_spawned: collections.defaultdict[
            discord.TextChannel,
            collections.deque['Duck']] = collections.defaultdict(
                collections.deque)
        self.enabled_channels: typing.Dict[discord.TextChannel, int] = {}
        self.concurrency = MaxConcurrency(number=1,
                                          per=BucketType.channel,
                                          wait=True)

        asyncio.ensure_future(self.async_setup())
Exemplo n.º 2
0
 def __init__(self, *args, **kwargs):
     self.logger = FakeLogger()
     self.config: dict = {}
     self.reload_config()
     activity = discord.Game(self.config["bot"]["playing"])
     super().__init__(*args,
                      command_prefix=get_prefix,
                      activity=activity,
                      case_insensitive=self.config["bot"]
                      ["commands_are_case_insensitive"],
                      **kwargs)
     self.commands_used = collections.Counter()
     self.uptime = datetime.datetime.utcnow()
     self.shards_ready = set()
     self._worldometers_api = covid19api.Covid19StatsWorldometers()
     self._vaccine_api = covid19api.VaccineStats()
     self._jhucsse_api = covid19api.Covid19JHUCSSEStats()
     self.news_api = news.NewsAPI(self.config["auth"]["news_api"]["token"])
     self._owid_api = covid19api.OWIDData()
     self.custom_updater_helper: Optional[CustomUpdater] = None
     self._client_session: Optional[aiohttp.ClientSession] = None
     self.basic_process_pool = concurrent.futures.ProcessPoolExecutor(2)
     self.premium_process_pool = concurrent.futures.ProcessPoolExecutor(4)
     self.statcord: Optional[statcord.Client] = None
     self.maps_api: Optional[MapGetter] = None
     self.support_server_invite = "https://discord.gg/myJh5hkjpS"
     self.autoupdater_dump: asyncio.Queue = asyncio.Queue(maxsize=1)
     self.blackfire: bool = blackfire
     self.sync_queue: Optional[Queue] = None
     self.task_processors: Optional[List[Process]] = None
     asyncio.ensure_future(self.async_setup())
Exemplo n.º 3
0
    def __init__(self, *args, **kwargs):
        self.logger = FakeLogger()
        self.logger.debug("Running sync init")
        self.config: dict = {}
        self.reload_config()
        #activity = discord.Game(self.config["bot"]["playing"])
        self.current_event: Events = Events.CALM
        activity = discord.Game(self.current_event.value[0])
        super().__init__(*args,
                         command_prefix=get_prefix,
                         activity=activity,
                         case_insensitive=self.config["bot"]
                         ["commands_are_case_insensitive"],
                         **kwargs)
        self.commands_used = collections.Counter()
        self.top_users = collections.Counter()
        self.uptime = datetime.datetime.utcnow()
        self.shards_ready = set()
        self._client_session: Optional[aiohttp.ClientSession] = None
        self.ducks_spawned: collections.defaultdict[
            discord.TextChannel,
            collections.deque['Duck']] = collections.defaultdict(
                collections.deque)
        self.enabled_channels: typing.Dict[discord.TextChannel, DucksLeft] = {}
        self.concurrency = MaxConcurrency(number=1,
                                          per=BucketType.channel,
                                          wait=True)
        self.allow_ducks_spawning = True

        self._duckhunt_public_log = None

        self.loop.run_until_complete(self.async_setup())
        self.logger.debug("End of init, bot object is ready")
Exemplo n.º 4
0
 def __init__(self, *args, **kwargs):
     self.logger = FakeLogger()
     self.config: dict = {}
     self.reload_config()
     activity = discord.Game(self.config["bot"]["playing"])
     super().__init__(*args, command_prefix=get_prefix, activity=activity, case_insensitive=self.config["bot"]["commands_are_case_insensitive"], **kwargs)
     self.commands_used = collections.Counter()
     self.uptime = datetime.datetime.utcnow()
     self.shards_ready = set()
     self._client_session: Optional[aiohttp.ClientSession] = None
     asyncio.ensure_future(self.async_setup())
Exemplo n.º 5
0
 def __init__(self, *args, **kwargs):
     self.logger = FakeLogger()
     self.config:dict = {}
     self.reload_config()
     activity = discord.Game(self.config["bot"]["playing"])
     super().__init__(*args, command_prefix=get_prefix, activity=activity, case_insensitive=self.config["bot"]["commands_are_case_insensitive"], **kwargs)
     self.commands_used = collections.Counter()
     self.uptime = datetime.datetime.utcnow()
     self.shards_ready = set()
     db_config = self.config['database']
     self.db = Database(self)
     asyncio.ensure_future(self.db.init(f"postgres://{db_config['username']}:{db_config['password']}@{db_config['host']}:{db_config['port']}/{db_config['database']}"))
Exemplo n.º 6
0
class MyBot(AutoShardedBot):
    def __init__(self, *args, **kwargs):
        self.logger = FakeLogger()
        self.config:dict = {}
        self.reload_config()
        activity = discord.Game(self.config["bot"]["playing"])
        super().__init__(*args, command_prefix=get_prefix, activity=activity, case_insensitive=self.config["bot"]["commands_are_case_insensitive"], **kwargs)
        self.commands_used = collections.Counter()
        self.uptime = datetime.datetime.utcnow()
        self.shards_ready = set()
        db_config = self.config['database']
        self.db = Database(self)
        asyncio.ensure_future(self.db.init(f"postgres://{db_config['username']}:{db_config['password']}@{db_config['host']}:{db_config['port']}/{db_config['database']}"))

    def reload_config(self):
        self.config = config.load_config()

    async def on_message(self, message):
        if not self.is_ready():
            return  # Ignoring messages when not ready

        #if message.author.bot:
        #    return  # ignore messages from other bots

        ctx = await self.get_context(message, cls=MyContext)
        if ctx.prefix is not None:
            await self.invoke(ctx)

    async def on_command(self, ctx: MyContext):
        self.commands_used[ctx.command.name] += 1
        ctx.logger.info(f"{ctx.message.clean_content}")

    async def on_shard_ready(self, shard_id):
        self.shards_ready.add(shard_id)

    async def on_disconnect(self):
        self.shards_ready = set()

    async def on_ready(self):
        messages = ["-----------", f"The bot is ready.", f"Logged in as {self.user.name} ({self.user.id})."]
        total_members = len(self.users)
        messages.append(f"I see {len(self.guilds)} guilds, and {total_members} members.")
        messages.append(f"To invite your bot to your server, use the following link: https://discordapp.com/api/oauth2/authorize?client_id={self.user.id}&scope=bot&permissions=0")
        cogs_count = len(self.cogs)
        messages.append(f"{cogs_count} cogs are loaded")
        messages.append("-----------")
        for message in messages:
            self.logger.info(message)

        for message in messages:
            print(message)
Exemplo n.º 7
0
    def __init__(self,
                 command_prefix: typing.Union[str, typing.Callable[
                     [discord.Message], typing.Awaitable]] = None,
                 **options):
        if not command_prefix:
            command_prefix = get_prefix

        super().__init__(command_prefix, **options)
        self.config = Config()
        self.logger = FakeLogger()
        self.db = Storage(self)
        self.commands_used = collections.Counter()

        with open("credentials.json", "r") as f:
            credentials = json.load(f)

        self.token = credentials["discord_token"]
        self.uptime = datetime.datetime.utcnow()
        self.loop.set_debug(True)
Exemplo n.º 8
0
class CustomBot(commands.AutoShardedBot):
    def __init__(self,
                 command_prefix: typing.Union[str, typing.Callable[
                     [discord.Message], typing.Awaitable]] = None,
                 **options):
        if not command_prefix:
            command_prefix = get_prefix

        super().__init__(command_prefix, **options)
        self.config = Config()
        self.logger = FakeLogger()
        self.db = Storage(self)
        self.commands_used = collections.Counter()

        with open("credentials.json", "r") as f:
            credentials = json.load(f)

        self.token = credentials["discord_token"]
        self.uptime = datetime.datetime.utcnow()
        self.loop.set_debug(True)

    async def on_message(self, message):
        if message.author.bot:
            return  # ignore messages from other bots

        ctx = await self.get_context(message, cls=context.CustomContext)
        if ctx.prefix is not None:
            await self.invoke(ctx)

    async def on_command(self, ctx):
        self.commands_used[ctx.command.name] += 1
        ctx.logger.info(f"<{ctx.author.name}> {ctx.message.clean_content}")

    async def on_ready(self):
        game = discord.Activity(type=discord.ActivityType.watching,
                                name=self.user.name)
        await self.change_presence(status=discord.Status.online, activity=game)
        self.logger.info("We are all set, on_ready was fired! Yeah!")
        total_members = len(self.users)
        self.logger.info(
            f"I see {len(self.guilds)} guilds, and {total_members} members")
Exemplo n.º 9
0
class MyBot(AutoShardedBot):
    def __init__(self, *args, **kwargs):
        self.logger = FakeLogger()
        self.config: dict = {}
        self.reload_config()
        activity = discord.Game(self.config["bot"]["playing"])
        super().__init__(*args,
                         command_prefix=get_prefix,
                         activity=activity,
                         case_insensitive=self.config["bot"]
                         ["commands_are_case_insensitive"],
                         **kwargs)
        self.commands_used = collections.Counter()
        self.uptime = datetime.datetime.utcnow()
        self.shards_ready = set()
        self._worldometers_api = covid19api.Covid19StatsWorldometers()
        self._vaccine_api = covid19api.VaccineStats()
        self._jhucsse_api = covid19api.Covid19JHUCSSEStats()
        self.news_api = news.NewsAPI(self.config["auth"]["news_api"]["token"])
        self._owid_api = covid19api.OWIDData()
        self.custom_updater_helper: Optional[CustomUpdater] = None
        self._client_session: Optional[aiohttp.ClientSession] = None
        self.basic_process_pool = concurrent.futures.ProcessPoolExecutor(2)
        self.premium_process_pool = concurrent.futures.ProcessPoolExecutor(4)
        self.statcord: Optional[statcord.Client] = None
        self.maps_api: Optional[MapGetter] = None
        self.support_server_invite = "https://discord.gg/myJh5hkjpS"
        self.autoupdater_dump: asyncio.Queue = asyncio.Queue(maxsize=1)
        self.blackfire: bool = blackfire
        self.sync_queue: Optional[Queue] = None
        self.task_processors: Optional[List[Process]] = None
        asyncio.ensure_future(self.async_setup())

    @property
    def client_session(self):
        if self._client_session:
            return self._client_session
        else:
            raise _runtime_error

    @property
    def worldometers_api(self):
        if self._worldometers_api.data_is_valid:
            return self._worldometers_api
        else:
            raise _runtime_error

    @property
    def vaccine_api(self):
        if self._vaccine_api.data_is_valid:
            return self._vaccine_api
        else:
            raise _runtime_error

    @property
    def jhucsse_api(self):
        if self._jhucsse_api.data_is_valid:
            return self._jhucsse_api
        else:
            raise _runtime_error

    @property
    def owid_api(self):
        if self._owid_api.data_is_valid:
            return self._owid_api
        else:
            raise _runtime_error

    def reload_config(self):
        self.config = config.load_config()

    async def async_setup(self):
        """
        This funtcion is run once, and is used to setup the bot async features, like the ClientSession from aiohttp.
        """
        if self._client_session is None:
            self._client_session = aiohttp.ClientSession(
            )  # There is no need to call __aenter__, since that does
            # nothing in this case
        try:
            await self._worldometers_api.update_covid_19_virus_stats()
            await self._vaccine_api.update_covid_19_vaccine_stats()
            await self._jhucsse_api.update_covid_19_virus_stats()
            await self._owid_api.update_covid_19_owid_data()
        except RuntimeError as e:
            self.logger.exception(
                "Fatal RuntimeError while running initial update!", exc_info=e)
        except Exception as e:
            self.logger.exception(
                "Fatal general error while running initial update!",
                exc_info=e)
        try:
            if not self.maps_api:
                self.maps_api = MapGetter("/home/pi/covid_bot_beta/maps")
                await wrap_in_async(self.maps_api.initalize_firefox,
                                    thread_pool=True)
        except Exception as e:
            self.logger.exception("Fatal error while initializing Firefox!",
                                  exc_info=e)
        try:
            self.custom_updater_helper = CustomUpdater(self)
            await self.custom_updater_helper.setup()
        except Exception as e:
            self.logger.exception(
                "Fatal error while initializing the custom updater!",
                exc_info=e)

    async def on_message(self, message: discord.Message):
        if not self.is_ready():
            return  # Ignoring messages when not ready

        if message.author.bot:
            return  # ignore messages from other bots

        ctx: MyContext = await self.get_context(message, cls=MyContext)
        if self.user.mentioned_in(message) and ctx.prefix is None and str(
                self.user.id) in message.content:
            _ = await ctx.get_translate_function()
            await ctx.send(
                _("Hi there! I'm a bot for giving live stats on the COVID-19 pandemic. My default prefix is "
                  "`c!`. This can be changed with `c!settings prefix <new prefix>`, replacing <new prefix> "
                  "with the prefix you want. For a list of my commands, run `c!help`."
                  ))
        elif ctx.valid:
            try:
                async with ctx.typing():
                    await self.invoke(ctx)
            except discord.Forbidden:
                await self.invoke(ctx)

    async def on_command(self, ctx: MyContext):
        if self.blackfire:
            probe.add_marker(f"Command {ctx.command} {ctx.invoked_subcommand}")
        self.commands_used[ctx.command.name] += 1
        self.statcord.command_run(ctx)
        ctx.logger.info(f"{ctx.message.clean_content}")

    async def on_shard_ready(self, shard_id):
        self.shards_ready.add(shard_id)

    async def on_disconnect(self):
        self.shards_ready = set()

    async def on_ready(self):
        messages = [
            "-----------", f"The bot is ready.",
            f"Logged in as {self.user.name} ({self.user.id})."
        ]
        total_members = len(self.users)
        messages.append(
            f"I see {len(self.guilds)} guilds, and {total_members} members.")
        messages.append(
            f"To invite your bot to your server, use the following link: "
            f"https://discord.com/api/oauth2/authorize?client_id={self.user.id}&scope=bot&permissions=0"
        )
        cogs_count = len(self.cogs)
        messages.append(f"{cogs_count} cogs are loaded")
        messages.append("-----------")
        for message in messages:
            self.logger.info(message)

        for message in messages:
            print(message)
Exemplo n.º 10
0
class MyBot(AutoShardedBot):
    def __init__(self, *args, **kwargs):
        self.logger = FakeLogger()
        self.config: dict = {}
        self.reload_config()
        # noinspection PyArgumentList
        activity = discord.Game(self.config["bot"]["playing"])
        super().__init__(*args,
                         command_prefix=get_prefix,
                         activity=activity,
                         case_insensitive=self.config["bot"]
                         ["commands_are_case_insensitive"],
                         **kwargs)
        self.commands_used = collections.Counter()
        self.uptime = datetime.datetime.utcnow()
        self.shards_ready = set()
        self._client_session: Optional[aiohttp.ClientSession] = None
        asyncio.ensure_future(self.async_setup())

    @property
    def client_session(self):
        if self._client_session:
            return self._client_session
        else:
            raise RuntimeError(
                "The bot haven't been setup yet. Ensure you call bot.async_setup asap."
            )

    def reload_config(self):
        self.config = config.load_config()

    async def async_setup(self):
        """
        This function is run once, and is used to setup the bot async features, like the ClientSession from aiohttp.
        """
        # There is no need to call __aenter__, since that does nothing in this case
        self._client_session = aiohttp.ClientSession()

    async def on_message(self, message):
        if not self.is_ready():
            return  # Ignoring messages when not ready

        if message.author.bot:
            return  # ignore messages from other bots

        ctx = await self.get_context(message, cls=MyContext)
        if ctx.prefix is not None:
            await self.invoke(ctx)

    async def on_command(self, ctx: MyContext):
        self.commands_used[ctx.command.name] += 1
        ctx.logger.info(f"{ctx.message.clean_content}")

    async def on_shard_ready(self, shard_id):
        self.shards_ready.add(shard_id)

    async def on_disconnect(self):
        self.shards_ready = set()

    async def on_ready(self):
        messages = [
            "-----------", f"The bot is ready.",
            f"Logged in as {self.user.name} ({self.user.id})."
        ]
        total_members = len(self.users)
        messages.append(
            f"I see {len(self.guilds)} guilds, and {total_members} members.")
        messages.append(
            f"To invite your bot to your server, use the following link: https://discordapp.com/api/oauth2/"
            f"authorize?client_id={self.user.id}&scope=bot&permissions=0")
        cogs_count = len(self.cogs)
        messages.append(f"{cogs_count} cogs are loaded")
        messages.append("-----------")
        for message in messages:
            self.logger.info(message)

        for message in messages:
            print(message)
Exemplo n.º 11
0
class MyBot(AutoShardedBot):
    def __init__(self, *args, **kwargs):
        self.logger = FakeLogger()
        self.config: dict = {}
        self.reload_config()
        #activity = discord.Game(self.config["bot"]["playing"])
        self.current_event: Events = Events.CALM
        activity = discord.Game(self.current_event.value[0])
        super().__init__(*args,
                         command_prefix=get_prefix,
                         activity=activity,
                         case_insensitive=self.config["bot"]
                         ["commands_are_case_insensitive"],
                         **kwargs)
        self.commands_used = collections.Counter()
        self.uptime = datetime.datetime.utcnow()
        self.shards_ready = set()
        self._client_session: Optional[aiohttp.ClientSession] = None
        self.ducks_spawned: collections.defaultdict[
            discord.TextChannel,
            collections.deque['Duck']] = collections.defaultdict(
                collections.deque)
        self.enabled_channels: typing.Dict[discord.TextChannel, int] = {}
        self.concurrency = MaxConcurrency(number=1,
                                          per=BucketType.channel,
                                          wait=True)

        asyncio.ensure_future(self.async_setup())

    @property
    def client_session(self):
        if self._client_session:
            return self._client_session
        else:
            raise RuntimeError(
                "The bot haven't been setup yet. Ensure you call bot.async_setup asap."
            )

    def reload_config(self):
        self.config = config.load_config()

    async def async_setup(self):
        """
        This funtcion is run once, and is used to setup the bot async features, like the ClientSession from aiohttp.
        """
        self._client_session = aiohttp.ClientSession(
        )  # There is no need to call __aenter__, since that does nothing in that case

    async def on_message(self, message):
        if not self.is_ready():
            return  # Ignoring messages when not ready

        if message.author.bot:
            return  # ignore messages from other bots

        ctx = await self.get_context(message, cls=MyContext)
        if ctx.prefix is not None:
            db_user = await get_from_db(ctx.author)

            access = db_user.get_access_level()

            if access != AccessLevel.BANNED:
                await self.concurrency.acquire(message)
                await self.invoke(ctx)
                await self.concurrency.release(message)

    async def on_command(self, ctx: MyContext):
        db_user = await get_from_db(ctx.author, as_user=True)
        if db_user.first_use:
            _ = await ctx.get_translate_function(user_language=True)

            ctx.logger.info(
                f"It's the first time that {ctx.author.name}#{ctx.author.discriminator} is intreracting with us. Sending welcome DM."
            )

            await ctx.author.send(
                _(
                    "Hello! The following message (written by the owner of DuckHunt) will give you a brief introduction to the bot, "
                    "and also provide you with links to the DuckHunt wiki.\n"
                    "First of all, thank you for using my bot! If you have any unanswered questions after reading this message and the wiki, "
                    "you are more than welcome to ask for help in the support channels at <{support_server_link}>.\n\n"
                    "When a duck spawns you shoot at it by using the `dh!bang` command.\n"
                    "However, if the duck says **COIN** it's a **baby duck** and you should hug it with `dh!hug`.\n"
                    "You can reload your ammunition with `dh!reload` and buy new magazines with `dh!shop magazine` or `dh!shop 2`.\n"
                    "If you want to learn more about the game, use the wiki! <{wiki_link}>",
                    support_server_link=_("https://discord.gg/G4skWae"),
                    wiki_link=
                    _("https://duckhunt.me/docs/players-guide/players-quickstart"
                      ),
                ))

            db_user.first_use = False
            await db_user.save()

        self.commands_used[ctx.command.name] += 1
        ctx.logger.info(f"{ctx.message.clean_content}")

    async def on_shard_ready(self, shard_id):
        self.shards_ready.add(shard_id)

    async def on_disconnect(self):
        self.shards_ready = set()

    async def on_ready(self):
        messages = [
            "-----------", f"The bot is ready.",
            f"Logged in as {self.user.name} ({self.user.id})."
        ]
        total_members = len(self.users)
        messages.append(
            f"I see {len(self.guilds)} guilds, and {total_members} members.")
        messages.append(
            f"To invite your bot to your server, use the following link: https://discordapp.com/api/oauth2/authorize?client_id={self.user.id}&scope=bot&permissions=0"
        )
        cogs_count = len(self.cogs)
        messages.append(f"{cogs_count} cogs are loaded")
        messages.append("-----------")
        for message in messages:
            self.logger.info(message)

        for message in messages:
            print(message)
Exemplo n.º 12
0
class MyBot(AutoShardedBot):
    def __init__(self, *args, **kwargs):
        self.logger = FakeLogger()
        self.config: dict = {}
        self.reload_config()
        activity = discord.Activity(type=discord.ActivityType.playing,
                                    name=self.config["bot"]["playing"])
        super().__init__(*args,
                         command_prefix=get_prefix,
                         activity=activity,
                         case_insensitive=self.config["bot"]
                         ["commands_are_case_insensitive"],
                         **kwargs)
        self.commands_used = collections.Counter()
        self.uptime = datetime.datetime.utcnow()
        self.shards_ready = set()
        self._client_session: Optional[aiohttp.ClientSession] = None
        asyncio.ensure_future(self.async_setup())

    @property
    def client_session(self):
        if self._client_session:
            return self._client_session
        else:
            raise RuntimeError(
                "The bot haven't been setup yet. Ensure you call bot.async_setup asap."
            )

    def reload_config(self):
        self.config = config.load_config()

    async def async_setup(self):
        """
        This funtcion is run once, and is used to setup the bot async features, like the ClientSession from aiohttp.
        """
        self._client_session = aiohttp.ClientSession(
        )  # There is no need to call __aenter__, since that does nothing in that case

    async def on_message(self, message):
        if not self.is_ready():
            return  # Ignoring messages when not ready

        if message.author.bot:
            return  # ignore messages from other bots

        ctx = await self.get_context(message, cls=MyContext)
        if self.user.mentioned_in(message) and ctx.prefix is None and str(
                self.user.id) in message.content:
            _ = await ctx.get_translate_function()
            await ctx.send(
                _("Hello! I'm SupportBunny, your easy-to-use ticket management bot in Discord! My default prefix is `.`. To change my prefix, do `.settings prefix <your preferred prefix>`. For help, type `.help`"
                  ))
        if ctx.prefix is not None:
            await self.invoke(ctx)

    async def on_command(self, ctx: MyContext):
        self.commands_used[ctx.command.name] += 1
        ctx.logger.info(f"{ctx.message.clean_content}")

    async def on_shard_ready(self, shard_id):
        self.shards_ready.add(shard_id)

    async def on_disconnect(self):
        self.shards_ready = set()

    async def on_ready(self):
        messages = [
            "-----------", f"The bot is ready.",
            f"Logged in as {self.user.name} ({self.user.id})."
        ]
        total_members = len(self.users)
        messages.append(
            f"I see {len(self.guilds)} guilds, and {total_members} members.")
        messages.append(
            f"To invite your bot to your server, use the following link: https://discordapp.com/api/oauth2/authorize?client_id={self.user.id}&scope=bot&permissions=0"
        )
        cogs_count = len(self.cogs)
        messages.append(f"{cogs_count} cogs are loaded")
        messages.append("-----------")
        for message in messages:
            self.logger.info(message)

        for message in messages:
            print(message)

    async def on_guild_join(self, ctx: MyContext, guild):
        owner = ctx.guild.owner_id
        owner = self.fetch_user(owner)
        await owner.send(
            f'Hey!\n\nThank you for using SupportBunny! Please initialize your server with `.initialize` so that you can start accepting tickets!\n\nThanks,\n\nSupportBunny Team'
        )
Exemplo n.º 13
0
class MyBot(AutoShardedBot):
    def __init__(self, *args, **kwargs):
        self.logger = FakeLogger()
        self.logger.debug("Running sync init")
        self.config: dict = {}
        self.reload_config()
        #activity = discord.Game(self.config["bot"]["playing"])
        self.current_event: Events = Events.CALM
        activity = discord.Game(self.current_event.value[0])
        super().__init__(*args,
                         command_prefix=get_prefix,
                         activity=activity,
                         case_insensitive=self.config["bot"]
                         ["commands_are_case_insensitive"],
                         **kwargs)
        self.commands_used = collections.Counter()
        self.top_users = collections.Counter()
        self.uptime = datetime.datetime.utcnow()
        self.shards_ready = set()
        self._client_session: Optional[aiohttp.ClientSession] = None
        self.ducks_spawned: collections.defaultdict[
            discord.TextChannel,
            collections.deque['Duck']] = collections.defaultdict(
                collections.deque)
        self.enabled_channels: typing.Dict[discord.TextChannel, DucksLeft] = {}
        self.concurrency = MaxConcurrency(number=1,
                                          per=BucketType.channel,
                                          wait=True)
        self.allow_ducks_spawning = True

        self._duckhunt_public_log = None

        self.loop.run_until_complete(self.async_setup())
        self.logger.debug("End of init, bot object is ready")

    @property
    def client_session(self):
        if self._client_session:
            return self._client_session
        else:
            raise RuntimeError(
                "The bot haven't been setup yet. Ensure you call bot.async_setup asap."
            )

    @property
    def available_guilds(self) -> typing.Iterable[Guild]:
        return filter(lambda g: not g.unavailable, self.guilds)

    def reload_config(self):
        self.config = config.load_config()

    async def async_setup(self):
        """
        This function is run once, and is used to setup the bot async features, like the ClientSession from aiohttp.
        """
        self.logger.debug("Running async init")

        self._client_session = aiohttp.ClientSession(
        )  # There is no need to call __aenter__, since that does nothing in that case

        if self.config['database']['enable']:
            await init_db_connection(self.config['database'])

    def get_logging_channel(self):
        if not self._duckhunt_public_log:
            config = self.config['duckhunt_public_log']
            self._duckhunt_public_log = self.get_guild(
                config['server_id']).get_channel(config['channel_id'])

        return self._duckhunt_public_log

    async def log_to_channel(self, *args, **kwargs):
        channel = self.get_logging_channel()
        message = await channel.send(*args, **kwargs)
        try:
            await message.publish()
            return True
        except discord.Forbidden:
            self.logger.warning(
                "Couldn't publish message to announcement channel, I don't have the required permissions"
            )
            return False
        except discord.HTTPException as e:
            self.logger.exception(
                f"Couldn't publish message to announcement channel: {e}. "
                f"Too many messages published recently ?")
            return False

    async def on_message(self, message):
        if not self.is_ready():
            return  # Ignoring messages when not ready

        if message.author.bot:
            return  # ignore messages from other bots

        ctx = await self.get_context(message, cls=MyContext)
        if ctx.prefix is not None:
            db_user = await get_from_db(ctx.author)

            access = db_user.get_access_level()

            if access != AccessLevel.BANNED:
                if ctx.command:
                    callback = ctx.command.callback
                else:
                    callback = None
                if callback:
                    should_block = getattr(ctx.command.callback,
                                           "block_concurrency", True)
                else:
                    should_block = True

                if should_block:
                    await self.concurrency.acquire(message)

                await self.invoke(ctx)

                if should_block:
                    await self.concurrency.release(message)

    async def on_command(self, ctx: MyContext):
        db_user = await get_from_db(ctx.author, as_user=True)
        if db_user.first_use and "help" not in ctx.command.name:
            _ = await ctx.get_translate_function(user_language=True)

            ctx.logger.info(
                f"It's the first time that {ctx.author.name}#{ctx.author.discriminator} is intreracting with us. Sending welcome DM."
            )
            try:
                await ctx.author.send(
                    _(
                        "Hello! The following message (written by the owner of DuckHunt) will give you a brief introduction to the bot, "
                        "and also provide you with links to the DuckHunt wiki.\n"
                        "First of all, thank you for using my bot! If you have any unanswered questions after reading this message and the wiki, "
                        "you are more than welcome to ask for help in the support channels at <{support_server_link}>.\n\n"
                        "When a duck spawns you shoot at it by using the `dh!bang` command.\n"
                        "You can reload your ammunition with `dh!reload` and buy new magazines with `dh!shop magazine` or `dh!shop 2`.\n"
                        "Your scores and channel leaderboards are available online (click the title in `dh!me` after playing for a while), and on Discord."
                        "If you want to learn more about the game, use the wiki! <{wiki_link}>\n"
                        "We also monitor the bot DMs, so if you have further questions, just answer this message!",
                        support_server_link=_("https://duckhunt.me/support"),
                        wiki_link=
                        _("https://duckhunt.me/docs/players-guide/players-quickstart"
                          ),
                    ))
            except discord.Forbidden:
                ctx.logger.debug(f"Couldn't send the welcome DM, forbidden.")

            db_user.first_use = False
            await db_user.save()

        self.commands_used[ctx.command.qualified_name] += 1
        self.top_users[ctx.author.id] += 1
        ctx.logger.info(f"{ctx.message.clean_content}")

    async def on_shard_ready(self, shard_id):
        self.shards_ready.add(shard_id)

    async def on_disconnect(self):
        self.shards_ready = set()

    async def on_ready(self):
        messages = [
            "-----------", f"The bot is ready.",
            f"Logged in as {self.user.name} ({self.user.id})."
        ]
        total_members = len(self.users)
        messages.append(
            f"I see {len(self.guilds)} guilds, and {total_members} members.")
        messages.append(
            f"To invite your bot to your server, use the following link: https://discord.com/oauth2/authorize?client_id=187636051135823872&scope=bot&permissions=741735489"
        )
        cogs_count = len(self.cogs)
        messages.append(f"{cogs_count} cogs are loaded")
        messages.append("-----------")
        for message in messages:
            self.logger.info(message)

        for message in messages:
            print(message)