Skip to content

Commit

Permalink
Merge branch 'dev' into update-option-rename
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasPlacentino authored Apr 1, 2024
2 parents fa88dd7 + 755f8d1 commit 0097784
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ repos:
hooks:
- id: black
language: python
types: [python]
types: [python3]
args: ["--line-length=120"]

- repo: https://github.com/PyCQA/autoflake
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ To see the bot logs when running with docker in detached mode (`-d`), use the [d
Once the ULB role is set, when a new user joins the server, either they are already registered (from another of your servers) in which case they will get the `@ULB` role and get renamed, or they are not registered yet and will receive a DM message with the instructions to register themselves using the `/ulb` command.
* `/feedback`
Send a feedback directly from discord.
### Admin server
* `/user add`
Expand All @@ -224,6 +228,14 @@ Edit info of a user.
Delete a user.
* `/server info`
Get information about a guild (ULB role, number of registered members, ...)
* `/stats`
Get statistics about the bot usage (nombre of configured servers, number of registered users, ...)
* `/update`
This forces a total update of the database and of all the servers. Since the bot already does this automatically at startup and after each reconnection, the only normal usecase for this would be if you manually add an entry (server or user) to the google sheet instead of using the `/user add` command above, we don't recommend manually editing the google sheet.
Expand Down
28 changes: 20 additions & 8 deletions bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,24 @@ def load_commands(self) -> None:
)
self.cog_not_loaded.append(extension)

async def send_error_log(self, interaction: ApplicationCommandInteraction, error: Exception):
async def send_error_log(self, tb: str):

n = len(tb) // 4050

#Logs need to be diveded into multiple embed due to size limitation
# TODO Check if we can use a list of embeds and one message
# TODO Make it dynamic base on the message size from the lib (check library version, maybe need to upgrade)
for i in range(n):
await self.log_channel.send(embed=disnake.Embed(description=f"```python\n{tb[4050*i:4050*(i+1)]}```"))
await self.log_channel.send(embed=disnake.Embed(description=f"```python\n{tb[4050*n:]}```"))

async def send_cmd_error_log(self, interaction: ApplicationCommandInteraction, error: Exception):
tb = self.tracebackEx(error)
logging.error(
f"{error} raised on command /{interaction.application_command.name} from {interaction.guild.name+'#'+interaction.channel.name if interaction.guild else 'DM'} by {interaction.author.name}.\n{tb}"
)

#Send error msg to the user
await interaction.send(
content=self.owner.mention,
embed=disnake.Embed(
Expand All @@ -110,17 +123,16 @@ async def send_error_log(self, interaction: ApplicationCommandInteraction, error
),
delete_after=10,
)

#Send logs to admins
await self.log_channel.send(
embed=disnake.Embed(title=f":x: __** ERROR**__ :x:", description=f"```{error}```").add_field(
name=f"Raised on command :",
value=f"**/{interaction.application_command.name}:{interaction.id}** from {interaction.guild.name+'#'+interaction.channel.name if interaction.guild else 'DM'} by {interaction.author.mention} at {interaction.created_at} with options\n```{interaction.filled_options}```"
+ (f" and target\n``'{interaction.target}``'." if interaction.target else "."),
)
)
n = len(tb) // 4050
for i in range(n):
await self.log_channel.send(embed=disnake.Embed(description=f"```python\n{tb[4050*i:4050*(i+1)]}```"))
await self.log_channel.send(embed=disnake.Embed(description=f"```python\n{tb[4050*n:]}```"))
await self.send_error_log(tb)

async def on_slash_command(self, interaction: disnake.ApplicationCommandInteraction) -> None:
logging.trace(
Expand All @@ -138,13 +150,13 @@ async def on_message_command(self, interaction: disnake.MessageCommandInteractio
)

async def on_slash_command_error(self, interaction: ApplicationCommandInteraction, error: Exception) -> None:
await self.send_error_log(interaction, error)
await self.send_cmd_error_log(interaction, error)

async def on_user_command_error(self, interaction: disnake.UserCommandInteraction, error: Exception) -> None:
await self.send_error_log(interaction, error)
await self.send_cmd_error_log(interaction, error)

async def on_message_command_error(self, interaction: disnake.MessageCommandInteraction, error: Exception) -> None:
await self.send_error_log(interaction, error)
await self.send_cmd_error_log(interaction, error)

async def on_slash_command_completion(self, interaction: disnake.ApplicationCommandInteraction) -> None:
logging.trace(
Expand Down
56 changes: 30 additions & 26 deletions classes/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def loaded(cls) -> bool:
return cls._loaded

@classmethod
def load(cls, bot: Bot) -> None:
async def load(cls, bot: Bot) -> bool:
"""Load the data from the google sheet.
Returns
Expand All @@ -104,31 +104,35 @@ def load(cls, bot: Bot) -> None:
- Guild: `Dict[disnake.Guild, disnake.Role]`
- Users: `Dict[disnake.User, UlbUser]]`
"""
# First time this is call, we need to load the credentials and the sheet
if not cls._sheet:
cred_dict = {}
cred_dict["type"] = os.getenv("GS_TYPE")
cred_dict["project_id"] = os.getenv("GS_PROJECT_ID")
cred_dict["auth_uri"] = os.getenv("GS_AUTHOR_URI")
cred_dict["token_uri"] = os.getenv("GS_TOKEN_URI")
cred_dict["auth_provider_x509_cert_url"] = os.getenv("GS_AUTH_PROV")
cred_dict["client_x509_cert_url"] = os.getenv("GS_CLIENT_CERT_URL")
cred_dict["private_key"] = os.getenv("GS_PRIVATE_KEY").replace(
"\\n", "\n"
) # Python add a '\' before any '\n' when loading a str
cred_dict["private_key_id"] = os.getenv("GS_PRIVATE_KEY_ID")
cred_dict["client_email"] = os.getenv("GS_CLIENT_EMAIL")
cred_dict["client_id"] = int(os.getenv("GS_CLIENT_ID"))
creds = ServiceAccountCredentials.from_json_keyfile_dict(cred_dict, cls._scope)
cls._client = gspread.authorize(creds)
logging.info("[Database] Google sheet credentials loaded.")

# Open google sheet
cls._sheet = cls._client.open_by_url(os.getenv("GOOGLE_SHEET_URL"))
cls._users_ws = cls._sheet.worksheet("users")
cls._guilds_ws = cls._sheet.worksheet("guilds")

logging.info("[Database] Spreadsheed loaded")
try:
# First time this is call, we need to load the credentials and the sheet
if not cls._sheet:
cred_dict = {}
cred_dict["type"] = os.getenv("GS_TYPE")
cred_dict["project_id"] = os.getenv("GS_PROJECT_ID")
cred_dict["auth_uri"] = os.getenv("GS_AUTHOR_URI")
cred_dict["token_uri"] = os.getenv("GS_TOKEN_URI")
cred_dict["auth_provider_x509_cert_url"] = os.getenv("GS_AUTH_PROV")
cred_dict["client_x509_cert_url"] = os.getenv("GS_CLIENT_CERT_URL")
cred_dict["private_key"] = os.getenv("GS_PRIVATE_KEY").replace(
"\\n", "\n"
) # Python add a '\' before any '\n' when loading a str
cred_dict["private_key_id"] = os.getenv("GS_PRIVATE_KEY_ID")
cred_dict["client_email"] = os.getenv("GS_CLIENT_EMAIL")
cred_dict["client_id"] = int(os.getenv("GS_CLIENT_ID"))
creds = ServiceAccountCredentials.from_json_keyfile_dict(cred_dict, cls._scope)
cls._client = gspread.authorize(creds)
logging.info("[Database] Google sheet credentials loaded.")

# Open google sheet
cls._sheet = cls._client.open_by_url(os.getenv("GOOGLE_SHEET_URL"))
cls._users_ws = cls._sheet.worksheet("users")
cls._guilds_ws = cls._sheet.worksheet("guilds")

logging.info("[Database] Spreadsheed loaded")
except (ValueError, gspread.exceptions.SpreadsheetNotFound, gspread.exceptions.WorksheetNotFound) as err:
await bot.send_error_log(bot.tracebackEx(err))
return

logging.info("[Database] Loading data...")

Expand Down
9 changes: 5 additions & 4 deletions cogs/Ulb.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ def __init__(self, bot: Bot):

@commands.Cog.listener("on_ready")
async def on_ready(self):
Database.load(self.bot)
Registration.setup(self)
logging.info("[Cog:Ulb] Ready !")
await utils.update_all_guilds()
await Database.load(self.bot)
if (Database.loaded):
Registration.setup(self)
logging.info("[Cog:Ulb] Ready !")
await utils.update_all_guilds()

async def wait_setup(self, inter: disnake.ApplicationCommandInteraction) -> None:
"""Async sleep until GoogleSheet is loaded and RegistrationForm is set"""
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ services:
volumes:
- ./:/usr/src/ulbdiscordbot
restart: always # or unless-stopped
mem_limit: 1g # memory limit for the container
# cpus: 0.5 # cpu limit for the container

0 comments on commit 0097784

Please sign in to comment.