Skip to content

Commit

Permalink
Merge pull request #138 from satisfactorymodding/bork-fixes
Browse files Browse the repository at this point in the history
2.22.5 - fixes, one potential fix, and more useful logging
  • Loading branch information
Borketh authored Sep 17, 2024
2 parents a86ec16 + af791b1 commit 2fcfda4
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 27 deletions.
15 changes: 12 additions & 3 deletions fred/cogs/levelling.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from datetime import *

from nextcord import DMChannel, Message, Guild
from nextcord.ext.commands import MemberNotFound

from .. import config
from ..libraries import common
Expand All @@ -20,7 +19,8 @@ def __init__(self, user_id: int, guild: Guild):
self.member = guild.get_member(user_id)
if self.member is None:
logger.warning(f"Unable to retrieve information about user {user_id}")
raise MemberNotFound(f"Unable to retrieve information about user {user_id}")
# Silencing error about this, Later™ problem -Borketh
# raise MemberNotFound(f"Unable to retrieve information about user {user_id}")

logger.info(f"Found member id {self.member}")

Expand Down Expand Up @@ -50,7 +50,15 @@ def xp_count(self, value: float):
self._xp_count = value
self.DB_user.xp_count = value

async def try_resolve_member(self):
if self.member is None:
if (member := await common.get_guild_member(self.guild, self.user_id)) is not None:
self.member = member
else:
logger.warning(f"Still unable to resolve user {self.user_id}")

async def validate_role(self):
await self.try_resolve_member()
if not self.member:
logger.info(
"Could not validate someone's level role because they aren't in the main guild",
Expand All @@ -69,7 +77,7 @@ async def validate_role(self):
self.DB_user.rank_role_id = role_id

# if not self.guild.get_channel(config.Misc.fetch("mod_channel")).permissions_for(self.member).send_messages:
if not common.permission_check(self.member, level=6):
if not await common.permission_check(self.member, level=6):
for member_role in self.member.roles:
if config.RankRoles.fetch_by_role(member_role.id) is not None: # i.e. member_role is a rank role
logpayload["role_id"] = member_role.id
Expand All @@ -80,6 +88,7 @@ async def validate_role(self):
await self.member.add_roles(role)

async def validate_level(self):
await self.try_resolve_member()
if not self.member:
logger.info(
"Could not validate someone's level because they aren't in the main guild",
Expand Down
2 changes: 1 addition & 1 deletion fred/cogs/webhooklistener.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def runServer(self, bot):
try:
server = HTTPServerV6((ip, port), MakeGithookHandler(bot))
server.serve_forever()
except PermissionError as pe:
except PermissionError:
logger.error(f"Cannot handle githooks! Permission denied to listen to {ip=} {port=}.")


Expand Down
11 changes: 9 additions & 2 deletions fred/fred.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from .fred_commands import Commands, FredHelpEmbed
from .libraries import createembed, common

__version__ = "2.22.4"
__version__ = "2.22.5"


class Bot(commands.Bot):
Expand Down Expand Up @@ -203,7 +203,14 @@ async def reply_to_msg(
self.logger.info("Replying to a message", extra=common.message_info(message))
# use this line if you're trying to debug discord throwing code 400s
# self.logger.debug(jsonpickle.dumps(dict(content=content, **kwargs), indent=2))
reference = (message.reference if propagate_reply else None) or message
if propagate_reply and message.reference is not None:
reference = message.reference
if (referenced_message := message.reference.cached_message) is not None:
if referenced_message.author == self.user:
reference = message
else:
reference = message

if self.owo and content is not None:
content = common.owoize(content)
if isinstance(reference, nextcord.MessageReference):
Expand Down
8 changes: 6 additions & 2 deletions fred/fred_commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
import io
import logging
import re
from os.path import split
from urllib.parse import urlparse

import nextcord
from algoliasearch.search_client import SearchClient
from nextcord import Attachment
from nextcord.ext.commands.view import StringView

from ._baseclass import BaseCmds, common, config, commands
Expand All @@ -26,7 +29,7 @@ class Commands(BotCmds, ChannelCmds, CommandCmds, CrashCmds, DialogflowCmds, EXP
@BaseCmds.listener()
async def on_command_error(self, ctx: commands.Context, error):
# We get an error about commands being found when using "runtime" commands, so we have to ignore that
self.logger.error(f"Caught {error!r}, {dir(error)}")
self.logger.error(f"Caught {error!r}")
if isinstance(error, commands.CommandNotFound):
command = ctx.message.content.lower().lstrip(self.bot.command_prefix).split(" ")[0]
if config.Commands.fetch(command) is not None:
Expand Down Expand Up @@ -86,7 +89,8 @@ async def on_message(self, message: nextcord.Message):
if (attachment := command["attachment"]) is not None:
async with self.bot.web_session.get(attachment) as resp:
buff = io.BytesIO(await resp.read())
attachment = nextcord.File(filename=attachment.split("/")[-1], fp=buff)
_, filename = split(urlparse(attachment).path)
attachment = nextcord.File(filename=filename, fp=buff)
args = []
view = StringView(message.content.lstrip(prefix))
view.get_word() # command name
Expand Down
9 changes: 6 additions & 3 deletions fred/fred_commands/dbcommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ async def add_command(self, ctx: commands.Context, command_name: str.lower, *, r
await self.bot.reply_to_msg(ctx.message, "This command name is reserved")
return

attachment = ctx.message.attachments[0].url if ctx.message.attachments else None
attachment = ctx.message.attachments[0] if ctx.message.attachments else None

if not response and not attachment:
response, attachment = await self.bot.reply_question(ctx.message, "What should the response be?")
Expand All @@ -38,9 +38,10 @@ async def add_command(self, ctx: commands.Context, command_name: str.lower, *, r
if not await self.bot.reply_yes_or_no(ctx.message, msg):
return

config.Commands(name=command_name, content=response, attachment=attachment)
config.Commands(name=command_name, content=response, attachment=attachment.url)

await self.bot.reply_to_msg(ctx.message, f"Command '{command_name}' added!")
self.logger.info("Command {command_name} added with response '{response}'")

@BaseCmds.remove.command(name="command")
async def remove_command(self, ctx: commands.Context, command_name: str.lower):
Expand All @@ -60,6 +61,7 @@ async def remove_command(self, ctx: commands.Context, command_name: str.lower):
config.Commands.deleteBy(name=command_name)

await self.bot.reply_to_msg(ctx.message, "Command removed!")
self.logger.info(f"Command {command_name} removed!")

@BaseCmds.modify.command(name="command")
async def modify_command(self, ctx: commands.Context, command_name: str.lower, *, new_response: str = None):
Expand Down Expand Up @@ -98,9 +100,10 @@ async def modify_command(self, ctx: commands.Context, command_name: str.lower, *

# this just works, don't touch it. trying to use config.Commands.fetch makes a duplicate command.
results[0].content = new_response
results[0].attachment = attachment.url if attachment else None
results[0].attachment = attachment and attachment.url

await self.bot.reply_to_msg(ctx.message, f"Command '{command_name}' modified!")
self.logger.info(f"Command {command_name} modified. New response: '{new_response}'")

@staticmethod
def _valid_aliases(target: str, aliases: list[str]) -> dict[str, list[str | tuple[str, str]]]:
Expand Down
44 changes: 29 additions & 15 deletions fred/libraries/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from functools import lru_cache, singledispatch
from typing import TYPE_CHECKING, Optional

from nextcord import User, Message, Member
from nextcord import User, Message, Member, Guild
from nextcord.ext import commands
from nextcord.ext.commands import Context

Expand Down Expand Up @@ -37,68 +37,82 @@ def __init__(self, bot: Bot):
self.logger.debug("Cog loaded.")


async def get_guild_member(guild: Guild, user_id: int) -> Member:
return guild.get_member(user_id) or await guild.fetch_member(user_id)


def is_bot_author(user_id: int) -> bool:
logger.info("Checking if someone is the author", extra={"user_id": user_id})
return user_id == 227473074616795137


async def l4_only(ctx: Context) -> bool:
logger.info("Checking if someone is a T3", extra=user_info(ctx.author))
return is_bot_author(ctx.author.id) or permission_check(ctx, level=4)
return is_bot_author(ctx.author.id) or await permission_check(ctx, level=4)


async def mod_only(ctx: Context) -> bool:
logger.info("Checking if someone is a Moderator", extra=user_info(ctx.author))
return is_bot_author(ctx.author.id) or permission_check(ctx, level=6)
return is_bot_author(ctx.author.id) or await permission_check(ctx, level=6)


@singledispatch
def permission_check(_, *, level: int) -> bool:
async def permission_check(_ctx_or_member, *, level: int) -> bool:
pass


@permission_check.register
def _permission_check_ctx(ctx: Context, *, level: int) -> bool:
async def _permission_check_ctx(ctx: Context, *, level: int) -> bool:
main_guild_id = config.Misc.fetch("main_guild_id")
main_guild = ctx.bot.get_guild(main_guild_id)
main_guild = await ctx.bot.fetch_guild(main_guild_id)

if main_guild is None:
raise LookupError(f"Unable to retrieve the guild {main_guild_id}. Is this the guild you meant?")

if (main_guild_member := main_guild.get_member(ctx.author.id)) is None:
if (main_guild_member := await get_guild_member(main_guild, ctx.author.id)) is None:
logger.warning(
"Checked permissions for someone but they weren't in the main guild", extra=user_info(ctx.author)
)
return False

return _permission_check_member(main_guild_member, level=level)
return await _permission_check_member(main_guild_member, threshold_level=level)


@permission_check.register
def _permission_check_member(member: Member, *, level: int) -> bool:
async def _permission_check_member(member: Member, *, threshold_level: int) -> bool:
"""Checks permissions for a member assuming they are in the main guild."""
logpayload = user_info(member)
logpayload["level"] = level
logpayload["level"] = threshold_level

if member.guild.id != config.Misc.fetch("main_guild_id"):
logger.warning("Checked permissions for a member of the wrong guild", extra=logpayload)
return False

logger.info("Checking permissions for someone", extra=logpayload)
perms = config.PermissionRoles.fetch_by_lvl(level)
logger.info(f"Checking permissions for {member.display_name} ({member.id})", extra=logpayload)
perms = config.PermissionRoles.fetch_by_lvl(threshold_level)

user_roles = [role.id for role in member.roles]
if (
# it shouldn't be possible to request a level above the defined levels but check anyway
role := next(
(permission for permission in perms if permission.perm_lvl >= level and permission.role_id in user_roles),
(
permission
for permission in perms
if permission.perm_lvl >= threshold_level and permission.role_id in user_roles
),
False,
) # checks for the first occurring, if any
):
logger.info(f"A permission check was positive with level {role.perm_lvl}", extra=logpayload)
logger.info(
f"Permission granted for {member.display_name} (lvl {role.perm_lvl}, threshold {threshold_level})",
extra=logpayload,
)
return True # user has a role that is above the requested level

logger.info(f"A permission check was negative with level less than required ({level})", extra=logpayload)
logger.info(
f"Permission denied for {member.display_name} (lvl {role.perm_lvl}, threshold {threshold_level})",
extra=logpayload,
)
return False


Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "fred"
version = "2.22.4"
version = "2.22.5"
description = "A Discord bot for the Satisfactory Modding Discord "
authors = ["Feyko <[email protected]>", "Mircea Roata <[email protected]>", "Borketh <[email protected]>"]
license = "MIT License"
Expand Down

0 comments on commit 2fcfda4

Please sign in to comment.