BonHowi/discordPogmareBot

View on GitHub
main.py

Summary

Maintainability
A
1 hr
Test Coverage
import json
import logging
import os
from datetime import datetime
from time import time

import discord
from discord.ext import commands, tasks
from discord_slash import SlashCommand, utils

from modules.get_settings import get_settings

# Create logger
logger = logging.getLogger('discord')
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(filename='discord.log', encoding='utf-8', mode='w')
handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
logger.addHandler(handler)

# Set bot privileges
intents = discord.Intents.all()


class MyBot(commands.Bot):

    def __init__(self):
        super().__init__(command_prefix="!", intents=intents)

        self.create_main_log_msg('\n --------------- STARTING BOT ---------------')
        self.create_main_log_msg('Init')
        self.create_main_log_msg(f"Rate limited: {self.is_ws_ratelimited()}")
        self.start_time = time()
        self.version = "1.2"

        self.guild = get_settings("guild")
        self.ch_admin_posting = get_settings("CH_ADMIN_POSTING")
        self.ch_role_request = get_settings("CH_ROLE_REQUEST")
        self.ch_total_members = get_settings("CH_TOTAL_MEMBERS")
        self.ch_nightmare_killed = get_settings("CH_NIGHTMARE_KILLED")
        self.ch_guides = get_settings("CH_GUIDES")

        self.ch_leaderboards = get_settings("CH_LEADERBOARDS")
        self.ch_leaderboards_common = get_settings("CH_LEADERBOARDS_COMMON")
        self.ch_leaderboards_event = get_settings("CH_LEADERBOARDS_EVENT")

        self.cat_spotting = get_settings("CAT_SPOTTING")
        self.ch_legendary_spot = get_settings("CH_LEGENDARY_SPOT")
        self.ch_legendary_nemeton = get_settings("CH_LEGENDARY_NEMETON")
        self.ch_rare_spot = get_settings("CH_RARE_SPOT")
        self.ch_rare_nemeton = get_settings("CH_RARE_NEMETON")
        self.ch_common = get_settings("CH_COMMON")
        self.ch_werewolf = get_settings("CH_WEREWOLF")
        self.ch_wraiths = get_settings("CH_WRAITHS")
        self.ch_nemeton = get_settings("CH_NEMETON")

        self.ch_logs = get_settings("CH_LOGS")
        self.ch_discussion_en = get_settings("CH_DISCUSSION_EN")
        self.ch_spotting_stats = get_settings("CH_SPOTTING_STATS")

        self.update_ch_commons_loop.start()

        with open('server_files/config.json', 'r', encoding='utf-8-sig') as fp:
            self.config = json.load(fp)

    def create_main_log_msg(self, message: str) -> None:
        dt_string = self.get_current_time()
        log: str = f"({dt_string}) [{self.__class__.__name__}]:\t\t{message}"
        print(log)
        logs_txt_dir: str = "logs/logs.txt"
        with open(logs_txt_dir, "a+") as file_object:
            file_object.write(f"{log}\n")

    # On bot ready
    async def on_ready(self) -> None:
        await MyBot.change_presence(self, activity=discord.Activity(type=discord.ActivityType.playing,
                                                                    name="The Witcher: Monster Slayer"))
        self.create_main_log_msg("Bot is ready")

    async def update_member_count(self, ctx) -> int:
        true_member_count = len([m for m in ctx.guild.members if not m.bot])
        new_name = f"Total members: {true_member_count}"
        channel_tm = self.get_channel(self.ch_total_members)
        await discord.VoiceChannel.edit(channel_tm, name=new_name)
        return true_member_count

    # On member join
    async def on_member_join(self, ctx) -> None:
        member_count = await self.update_member_count(ctx)
        self.create_main_log_msg(f"{ctx} joined")

        if (member_count % 100) == 0:
            channel = self.get_channel(self.ch_admin_posting)
            await channel.send(f"{member_count} members <:POGMARE:872496675434942484>")

    async def on_member_remove(self, ctx) -> None:
        await self.update_member_count(ctx)
        self.create_main_log_msg(f"{ctx} left")

    # Manage on message actions
    async def on_message(self, ctx) -> None:
        # If bot is the message author
        if ctx.author.id == self.user.id:
            return
        if isinstance(ctx.channel, discord.channel.DMChannel):
            await ctx.channel.send("If you have any questions please ask my creator - BonJowi#0119")
            return

        # If there is a message with "!" prefix
        if ctx.content.startswith("!") and "help" not in ctx.content:
            await ctx.channel.send(
                fr"{ctx.author.mention} Please use / instead of ! to use commands on this server!",
                delete_after=5.0)
            await ctx.delete()

    # Loop tasks
    # Update common spotting channel name
    async def update_ch_commons(self) -> None:
        with open('./server_files/commons.txt') as f:
            try:
                commons = f.read().splitlines()
            except ValueError:
                print(ValueError)

        new_name = f"common {commons[0]}"
        common_ch = self.get_channel(self.ch_common)
        await discord.TextChannel.edit(common_ch, name=new_name)
        self.create_main_log_msg(f"Common channel name updated: {commons[0]}")
        await common_ch.send(f"Common changed: **{commons[0]}**")

        commons.append(commons.pop(commons.index(commons[0])))
        with open('./server_files/commons.txt', 'w') as f:
            for item in commons:
                f.write("%s\n" % item)

    # Update commons channel name every day at 12:00
    @tasks.loop(minutes=60.0)
    async def update_ch_commons_loop(self) -> None:
        if datetime.utcnow().hour == 14:
            await self.update_ch_commons()

    @update_ch_commons_loop.before_loop
    async def before_update_ch_commons(self) -> None:
        await self.wait_until_ready()

    @staticmethod
    def get_current_time() -> str:
        now = datetime.utcnow()
        return now.strftime("%d/%m/%Y %H:%M:%S") + " UTC"


def main() -> None:
    pogmare = MyBot()

    # Allow slash commands
    slash = SlashCommand(pogmare, sync_commands=False, sync_on_cog_reload=False)

    # Load cogs
    for cog in os.listdir("./cogs"):
        if cog.endswith("cog.py"):
            try:
                cog = f"cogs.{cog.replace('.py', '')}"
                pogmare.load_extension(cog)
            except Exception as e:
                print(f"{cog} Could not be loaded")
                raise e

    pogmare.run(get_settings("token"))


if __name__ == "__main__":
    main()