From 28f0e66394f8eb80344f4a302ff1bd520f56ce5f Mon Sep 17 00:00:00 2001 From: Minidodo Date: Tue, 9 Aug 2022 17:09:52 +0200 Subject: [PATCH] Fixed temporary bans, and added an option to exclude discord from banning. changed the color of "Time is UP!" in the roll results, as requested. --- core/igncore.py | 2 +- modules/core/accounting/account_controller.py | 2 +- modules/core/ban/ban_controller.py | 65 +++++++++++++++---- modules/core/ban/ban_service.py | 24 ++++--- .../core/discord/discord_command_handler.py | 7 ++ modules/core/discord/discord_controller.py | 8 ++- modules/standard/loot/loot_controller.py | 2 +- 7 files changed, 84 insertions(+), 26 deletions(-) diff --git a/core/igncore.py b/core/igncore.py index c3ba636..a3b258e 100644 --- a/core/igncore.py +++ b/core/igncore.py @@ -48,7 +48,7 @@ class IgnCore: self.last_timer_event = 0 self.start_time = int(time.time()) self.major_version = "IGNCore v2.9" - self.minor_version = "7" + self.minor_version = "8" self.incoming_queue = FifoQueue() self.mass_message_queue = None self.conns = DictObject() diff --git a/modules/core/accounting/account_controller.py b/modules/core/accounting/account_controller.py index 9a428e3..c81e139 100644 --- a/modules/core/accounting/account_controller.py +++ b/modules/core/accounting/account_controller.py @@ -136,7 +136,7 @@ class AccountController: self.account_service.add_log(user.char_id, "system", f"Account disabled by {request.sender.name}.", request.sender.char_id) - return f"Character {user.name}'s Account has been disabled!" + return f"Character {user.name}'s Account has been disabled permanently!" else: return f"There's no active account for character {user.name}." diff --git a/modules/core/ban/ban_controller.py b/modules/core/ban/ban_controller.py index 219a71c..718a0a2 100644 --- a/modules/core/ban/ban_controller.py +++ b/modules/core/ban/ban_controller.py @@ -1,14 +1,21 @@ +import time +import typing + import hjson from core.aochat.BaseModule import BaseModule from core.chat_blob import ChatBlob from core.command_param_types import Any, Const, Options, Time, Character from core.db import DB -from core.decorators import instance, command -from core.lookup.character_service import CharacterService -from core.translation_service import TranslationService +from core.decorators import instance, command, timerevent + from core.igncore import IgnCore -from modules.core.ban.ban_service import BanService + +if typing.TYPE_CHECKING: + from modules.core.accounting.services.account_service import AccountService + from modules.core.ban.ban_service import BanService + from core.lookup.character_service import CharacterService + from core.translation_service import TranslationService @instance() @@ -19,6 +26,7 @@ class BanController(BaseModule): self.db: DB = registry.get_instance("db") self.text = registry.get_instance("text") self.util = registry.get_instance("util") + self.account_service: AccountService = registry.get_instance("account_service") self.ban_service: BanService = registry.get_instance("ban_service") self.command_alias_service = registry.get_instance("command_alias_service") self.ts: TranslationService = registry.get_instance("translation_service") @@ -36,12 +44,13 @@ class BanController(BaseModule): @command(command="ban", params=[Const("list", is_optional=True)], access_level="moderator", description="Show the ban list") def ban_list_cmd(self, _, _1): - query = self.db.query("SELECT a.*, p.*, b.reason, b.finished_at, b.created_at, b.sender_char_id from account a " - "left join player p on a.char_id = p.char_id " - "left join ban_list b on a.char_id = b.char_id " - "where main=a.char_id " - "and disabled=1 " - "and p.org_id NOT IN (SELECT org_id from ban_org_list)") + # query = self.db.query("SELECT a.*, p.*, b.reason, b.finished_at, b.created_at, b.sender_char_id from account a " + # "left join player p on a.char_id = p.char_id " + # "left join ban_list b on a.char_id = b.char_id " + # "where main=a.char_id " + # "and (disabled=1 or b.ended_early < 1)" + # "and p.org_id NOT IN (SELECT org_id from ban_org_list)") + query = self.ban_service.get_ban_list() blob = "" for row in query: ends = "never" if (row.finished_at or -1) == -1 else self.util.format_datetime(row.finished_at) @@ -56,13 +65,19 @@ class BanController(BaseModule): @command(command="ban", params=[Options(["rem", "remove"]), Character("character")], access_level="moderator", description="Remove a character from the ban list") - def ban_remove_cmd(self, _, _1, char): + def ban_remove_cmd(self, request, _1, char): if not char.char_id: return self.getresp("global", "char_not_found", {"char": char.name}) elif not self.ban_service.get_ban(char.char_id): return self.getresp("module/ban", "not_banned", {"char": char.name}) else: self.ban_service.remove_ban(char.char_id) + self.account_service.add_log(char.char_id, 'admin', + 'Ban has been lifted.', + request.sender.char_id) + self.account_service.add_log(request.sender.char_id, 'admin', + f'lifted active ban for {char.name}', + self.bot.get_char_id()) return self.getresp("module/ban", "unbanned_self", {"char": char.name}) @command(command="ban", @@ -75,5 +90,33 @@ class BanController(BaseModule): elif self.ban_service.get_ban(char.char_id): return f"{char.name} is already banned." else: + if not duration: + duration = -1 + if not reason: + reason = 'No reason given.' + else: + reason = f"Reason: {reason}" + self.account_service.add_log(char.char_id, 'admin', f'{"Banned permanently. " if duration < 0 else f"Banned for {self.util.time_to_readable(duration)}."} {reason}', request.sender.char_id) + self.account_service.add_log(request.sender.char_id, 'admin', + f' {char.name} has been {"banned permanently. " if duration < 0 else f"banned for {self.util.time_to_readable(duration)}."} {reason}', + request.sender.char_id) + self.ban_service.add_ban(char.char_id, request.sender.char_id, duration, reason) request.reply(f"{char.name} has been added to the ban list.") + + @timerevent(budatime="1h", description="lift expired temporary bans") + def fix_bans(self, _, _1): + d = self.db.query( + f"SELECT b.*, COALESCE(p1.name, b.char_id) AS name, p2.name AS sender_name FROM ban_list b " + f"LEFT JOIN player p1 ON b.char_id = p1.char_id " + f"LEFT JOIN player p2 ON b.sender_char_id = p2.char_id " + f"WHERE ended_early < 1 AND (finished_at < ?) " + f"ORDER BY b.created_at DESC", [time.time()]) + + for active in d: + dur = time.time() - active.created_at + self.ban_service.remove_ban(active.char_id, True) + self.account_service.add_log(active.char_id, "admin", f"Temporary ban lifted after a duration of {self.util.time_to_readable(dur)}. {active.reason}", self.bot.get_char_id()) + for still_active in self.ban_service.get_ban_list(): + self.account_service.account_disable(still_active.char_id) + diff --git a/modules/core/ban/ban_service.py b/modules/core/ban/ban_service.py index 77e51a7..b5f9a6a 100644 --- a/modules/core/ban/ban_service.py +++ b/modules/core/ban/ban_service.py @@ -67,10 +67,14 @@ class BanService: return num_rows - def remove_ban(self, char_id): + def remove_ban(self, char_id, tmp=False): t = int(time.time()) - num_rows = self.db.exec("UPDATE ban_list SET ended_early = 1 " - "WHERE char_id = ? AND (finished_at > ? OR finished_at = -1)", [char_id, t]) + if not tmp: + num_rows = self.db.exec("UPDATE ban_list SET ended_early = 1 " + "WHERE char_id = ? and ended_early = 0", [char_id]) + else: + num_rows = self.db.exec("UPDATE ban_list SET ended_early = 2 " + "WHERE char_id = ? AND (finished_at < ?)", [char_id, t]) if num_rows: self.db.exec("UPDATE account SET disabled = 0 " "WHERE main = (SELECT main from account where char_id=?)", [char_id]) @@ -83,19 +87,19 @@ class BanService: "WHERE char_id = (SELECT main from account where char_id=?) and disabled=1", [char_id]) - def get_ban_list(self): + def get_ban_list(self, full=True) -> list[DictObject]: t = int(time.time()) - return self.db.query("SELECT b.*, COALESCE(p1.name, b.char_id) AS name, p2.name AS sender_name FROM ban_list b " - "LEFT JOIN player p1 ON b.char_id = p1.char_id " - "LEFT JOIN player p2 ON b.sender_char_id = p2.char_id " - "WHERE ended_early != 1 AND (finished_at > ? OR finished_at = -1) " - "ORDER BY b.created_at DESC", [t]) + return self.db.query(f"SELECT b.*, COALESCE(p1.name, b.char_id) AS name, p2.name AS sender_name FROM ban_list b " + f"LEFT JOIN player p1 ON b.char_id = p1.char_id " + f"LEFT JOIN player p2 ON b.sender_char_id = p2.char_id " + f"WHERE ended_early < 1 AND (finished_at > ? {'OR finished_at = -1' if full else ''}) " + f"ORDER BY b.created_at DESC", [t]) def check_for_banned(self, context): char_id = context.char_id if self.get_ban(char_id): # do nothing if character is banned - self.logger.info("ignoring banned character %d for command '%s'" % (char_id, context.message)) + self.logger.info(f"ignoring banned character {self.account_service.character_service.resolve_char_to_name(char_id, default=str(char_id))} for command '{context.message}'") return False else: return True diff --git a/modules/core/discord/discord_command_handler.py b/modules/core/discord/discord_command_handler.py index e2b4ab4..e17d3ea 100644 --- a/modules/core/discord/discord_command_handler.py +++ b/modules/core/discord/discord_command_handler.py @@ -16,12 +16,14 @@ from core.db import DB from core.decorators import instance, command, event, timerevent from core.dict_object import DictObject from core.logger import Logger +from core.setting_types import BooleanSettingType from modules.core.ban.ban_service import BanService if TYPE_CHECKING: from modules.core.discord.discord_controller import DiscordController from core.message_hub_service import MessageHubService from core.command_service import CommandService + from core.setting_service import SettingService @instance() @@ -37,9 +39,12 @@ class DiscordCommandHandler(BaseModule): self.db: DB = registry.get_instance("db") self.relay_hub_service: MessageHubService = registry.get_instance("message_hub_service") self.command_service: CommandService = registry.get_instance("command_service") + self.setting_service: SettingService = registry.get_instance("setting_service") def pre_start(self): self.command_service.register_command_channel("Discord", self.DISCORD_CHANNEL) + self.setting_service.register(self.module_name, "include_discord_ban", True, BooleanSettingType(), + "Should chatbot bans be extended to discord (Ban from the discord server!):") @event("discord_command", "should the bot take care of discord commands", False) def discord_command_handler(self, _, event_data): @@ -251,6 +256,8 @@ class DiscordCommandHandler(BaseModule): token = self.discord.setting_discord_token().get_value() if token.lower() in ["none", "", "null"]: return + if not self.setting_service.get("include_discord_ban").get_value(): + return account = self.discord.account_service.get_account(event_data.char_id) if account.discord_joined == 1 and account.discord_id != "": member = self.discord.guild.get_member(int(account.discord_id)) diff --git a/modules/core/discord/discord_controller.py b/modules/core/discord/discord_controller.py index e636d0d..6c70245 100644 --- a/modules/core/discord/discord_controller.py +++ b/modules/core/discord/discord_controller.py @@ -210,7 +210,7 @@ class DiscordController: await invite.delete() async def discord_banlist(self): - return await self.guild.bans() + return [entry async for entry in self.guild.bans(limit=2000)] async def discord_ban_user(self, user, reason=""): await self.guild.ban(user, reason=reason) @@ -239,6 +239,10 @@ class DiscordController: addroles.append(failed) remroles = discord_user.roles else: + # if bans are not transferred to discord, just freeze the member role. + ignore = (not self.setting_service.get("include_discord_ban").get_value()) and account.disabled + if ignore: + self.logger.warning(f"Frozen Account: {account.name}") # Superadmin if access_level["level"] in [10, 20]: if self.get_role(self.discord_roles.admin, discord_user.roles) is None: @@ -255,7 +259,7 @@ class DiscordController: rank = self.get_role(self.discord_roles.member, self.guild.roles) or None if rank is not None: addroles.append(rank) - else: + elif not ignore: rank = self.get_role(self.discord_roles.member, self.guild.roles) or None if rank is not None: remroles.append(rank) diff --git a/modules/standard/loot/loot_controller.py b/modules/standard/loot/loot_controller.py index 59c6d36..0f9b847 100644 --- a/modules/standard/loot/loot_controller.py +++ b/modules/standard/loot/loot_controller.py @@ -237,7 +237,7 @@ class LootController: for i in remove: self.loot_list.pop(i) - msg = ChatBlob("Roll results", blob, "\n________________\n\nTime is UP!\n", "\n________________") + msg = ChatBlob("Roll results", blob, "\n________________\n\nTime is UP!\n", "\n________________") self.bot.send_private_channel_message(msg if len(blob) > 0 else "No one was added to any loot") if self.loot_list: count = 1