Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an Auto Config system and have a default config file. #73

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .env-example
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
TOKEN="your bot token here" # here is a tutorial on how to get setup a bot and get this
PREFIX="!" # the prefix the bot should use, will default to "!" if this is not present
CHANNEL_DEVALERTS=""
CHANNEL_DEVLOG=""
Guild_ID = #your guild id here
4 changes: 1 addition & 3 deletions bot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ def should_rotate(message: loguru.Message, file: typing.TextIO) -> bool:
max_time = 7 * 24 * 60 * 60 # 1 week in seconds
if file.tell() + len(message) > 5 * (2 ** 20): # if greater than size 5 MB
return True
if now - creation > max_time:
return True
return False
return now - creation > max_time


logger.add(LOG_FILE, rotation=should_rotate)
Expand Down
16 changes: 8 additions & 8 deletions bot/bot.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import os

from bot.constants import Channels, EXTENSIONS, Gurkbot

from discord import Embed
from discord.ext import commands
from loguru import logger

from . import constants


class Bot(commands.Bot):
"""The core of the bot."""

def __init__(self) -> None:
super().__init__(command_prefix=constants.PREFIX)
super().__init__(command_prefix=Gurkbot.prefix)
self.load_extensions()

def load_extensions(self) -> None:
"""Load all the extensions in the exts/ folder."""
logger.info("Start loading extensions from ./exts/")
for extension in constants.EXTENSIONS.glob("*/*.py"):
for extension in EXTENSIONS.glob("*/*.py"):
if extension.name.startswith("_"):
continue # ignore files starting with _
dot_path = str(extension).replace(os.sep, ".")[:-3] # remove the .py
Expand All @@ -28,11 +28,11 @@ def load_extensions(self) -> None:
def run(self) -> None:
"""Run the bot with the token in constants.py/.env ."""
logger.info("Starting bot")
if constants.TOKEN is None:
if Gurkbot.token is None:
raise EnvironmentError(
"token value is None. Make sure you have configured the TOKEN field in .env"
)
super().run(constants.TOKEN)
super().run(Gurkbot.token)

async def on_ready(self) -> None:
"""Ran when the bot has connected to discord and is ready."""
Expand All @@ -44,7 +44,7 @@ async def startup_greeting(self) -> None:
embed = Embed(description="Connected!")
embed.set_author(
name="Gurkbot",
url=constants.BOT_REPO_URL,
url=Gurkbot.repo_url,
icon_url=self.user.avatar_url,
)
await self.get_channel(constants.Channels.devlog).send(embed=embed)
await self.get_channel(Channels().dev_log).send(embed=embed)
17 changes: 17 additions & 0 deletions bot/config/config-list.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Auto-config: False

Roles:
Boosters:
optional: False

Contributors:
optional: False

Channels:

Dev_Polls:
optional: False

Polls:
optional: False

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the un-optional channels here too, and when the bot goes over them, it asks the user whether they want to create the un-optional channels or not.
Same for the roles.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is pretty obvious that the channels and roles that have not been marked as optional are mandatory.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But, to test the github category we need the dev categories, so hence we need them.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need them hence it's set to false.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And if we require them to be mandatory then we could just completely remove them from the config-list.yaml

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need them hence it's set to false.

the dev-gurkbot, etc. are required for github category and I don't see them here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well they aren't needed for the bot as of now. So....

36 changes: 36 additions & 0 deletions bot/config/default-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Guild_ID: 789192517375623228
Guild_Invite": "https://discord.gg/W9DSfryp8Y"
Guild_Name: "Gurkult"

Bot:
ID : 793935699308052511
Name : "Gurkbot"
Prefix : "!"

Roles:
Supreme_Cucumber: 789196598508650527
Steering_Council: 789213682332598302
Gurkult_Lords: 789197216869777440
Gurkans: 789195552121290823
Announcements: 789978290844598272
Polls: 790043110360350740
Muted: 796379764805599283
Contributors: 789222836643299398
Boosters: 792069114569949206

Channels:
Polls : 790043296579452930
Bot_Commands : 793570459945926717
Dev_log : 789431367167377448
Dev_Alerts : 796695123177766982
Dev_Polls : 789475074746744863

Emojis:
questionmark : "<:questionmark:795305037475610625>"
info : "<:Info:795305070593310730>"
pr_open : "<:PROpen:794834041416187935>"
pr_merged : "<:PRMerged:794834041173704744>"
pr_closed : "<:PRClosed:794834041073172501>"
issue_open : "<:IssueOpen:794834041450266624>"
issue_closed : "<:IssueClosed:794834041240289321>"
trash : "<:trash:798179380626587658>"
100 changes: 83 additions & 17 deletions bot/constants.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,99 @@
import os
import pathlib

from collections import namedtuple
from enum import Enum
from typing import NamedTuple

import yaml
from loguru import logger

# env vars
PREFIX = os.getenv("PREFIX") or "!"
TOKEN = os.getenv("TOKEN")
BOT_REPO_URL = "https://github.com/gurkult/gurkbot"

# paths
EXTENSIONS = pathlib.Path("bot/exts/")
LOG_FILE = pathlib.Path("log/gurkbot.log")
if os.path.exists(f'bot/config/config.yaml'):
logger.inof(f'Found config.yaml file, setting the constants from there.')
with open('bot/config/config.yaml') as f:
config = yaml.safe_load(f)
else:
logger.info('Could not find config.yaml, loading the constants from default config.')
with open('bot/config/default-confi.yaml') as f:
config = yaml.safe_load(f)


class Colours:
class Colour(Enum):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use NamedTuple

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enum is more suited for this rather than named tuple.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And named tuple aren't iterable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, enums are suited for this role.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, alright.

green = 0x1F8B4C
yellow = 0xF1C502
soft_red = 0xCD6D6D


class Channels(NamedTuple):
devalerts = int(os.getenv("CHANNEL_DEVALERTS", 796695123177766982))
devlog = int(os.getenv("CHANNEL_DEVLOG", 789431367167377448))
class Gurkbot:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
class Gurkbot:
class Client:

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having the class as the bot's name would make more sense IMO.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the name of the bot changes in future?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we change the name of the class.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this class? Is it related to how auto-config works?
Gurkbot doesn't feel like an apt name.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean would it not make sense to have the tokens and prefix of the bot in a single class?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it would keep the client constants together

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Client can mean many things.

prefix = config['Bot']['Prefix']
repo_url = "https://github.com/gurkult/gurkbot"
token = os.getenv('TOKEN')


Channels = namedtuple(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a class for this looks better and more readable and easier to understand.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use a class then we would have to insert them again. But we shouldn't have to do that because it already exists in the config, file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using namedtuple, why not pick them like we did for the environment variables?

Copy link
Author

@Inheritanc-e Inheritanc-e Jan 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean?
Namedtuple is perfect for storing constants.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this one, chief.
We should discuss this on the server. Readability is lost.
Btw, you can use typing.NamedTuple to create a named tuple and I feel that'd produce more readable code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I agree with @codephile1221, the readability is lost, @gustavwilliam whats your say on this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH, readability doesn't matter much since you can look at the original config file.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is readability lost?
This is very much understandable, the first parameter of named tuples are keys and the default keyword takes a tuple which are the values for those keys going from left to right.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which is easier to understand, the former way or the yours?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mine is very much understandable, if you wish to see the ids then the config file exists for that, and you would not understand mine only if you don't know how namedtuple works.

'Channels',
[channel.lower() for channel in config['Channels'].keys()],
defaults=iter(config['Channels'].values()),
)


Roles = namedtuple(
'Roles',
[role.lower() for role in config['Roles'].keys()],
defaults=iter(config['Roles'].values()),
)

# Bot replies
with pathlib.Path("bot/resources/bot_replies.yml").open(encoding="utf8") as file:
bot_replies = yaml.safe_load(file)
ERROR_REPLIES = bot_replies["ERROR_REPLIES"]
POSITIVE_REPLIES = bot_replies["POSITIVE_REPLIES"]
NEGATIVE_REPLIES = bot_replies["NEGATIVE_REPLIES"]
ERROR_REPLIES = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did u shift the error replies to constants.py from the yaml file?
See fisher's comments on Error Handler Pr

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha.

"Please don't do that.",
"You have to stop.",
"Do you mind?",
"In the future, don't do that.",
"That was a mistake.",
"You blew it.",
"You're bad at computers.",
"Are you trying to kill me?",
"Noooooo!!",
"I can't believe you've done this"
]

NEGATIVE_REPLIES = [
"Noooooo!!",
"Nope.",
"I'm sorry Gurk, I'm afraid I can't do that.",
"I don't think so., Not gonna happen.",
"Out of the question.",
"Huh? No.",
"Nah.",
"Naw.",
"Not likely.",
"Not in a million years.",
"Fat chance.",
"Certainly not.",
"NEGATORY.",
"Nuh-uh.",
"Not in my house!"
]

POSITIVE_REPLIES = [
"Yep., Absolutely!",
"Can do!",
"Affirmative!",
"Yeah okay.",
"Sure.",
"Sure thing!",
"You're the boss!",
"Okay.",
"No problem.",
"I got you.",
"Alright.",
"You got it!",
"ROGER THAT",
"Of course!",
"Aye aye, cap'n!",
"I'll allow it."
]

# paths
EXTENSIONS = pathlib.Path("bot/exts/")
LOG_FILE = pathlib.Path("log/gurkbot.log")
Loading