diff --git a/core/setting_types.py b/core/setting_types.py index f3b9f49..19484a2 100644 --- a/core/setting_types.py +++ b/core/setting_types.py @@ -121,7 +121,6 @@ class HiddenSettingType(TextSettingType): else: return "<empty>" - @property def get_display(self): text = Registry.get_instance("text") diff --git a/modules/core/accounting/services/account_service.py b/modules/core/accounting/services/account_service.py index 9e0040f..7baf844 100644 --- a/modules/core/accounting/services/account_service.py +++ b/modules/core/accounting/services/account_service.py @@ -323,6 +323,20 @@ class AccountService: return self.orgs return self.orgs + def get_org_names(self) -> list: + if not hasattr(self, "org_names"): + try: + def del_orgs(_): + del self.org_names + self.orgs = [x["org_name"] for x in self.db.query("SELECT * from orgs o " + "LEFT JOIN all_orgs a on o.org_id = ao.org_id", [])] + self.bot.job_scheduler.delayed_job(del_orgs, 60) + return self.org_names + except SqlException: + self.org_names = [self.bot.public_channel_service.org_name] + return self.org_names + return self.org_names + def create_users(self, users, disable=False) -> int: # Default preferences pref_autoinvite = self.setting_service.get_value("pref_autoinvite") diff --git a/modules/core/discord/discord_controller.py b/modules/core/discord/discord_controller.py index 407f5a3..4caaa8e 100644 --- a/modules/core/discord/discord_controller.py +++ b/modules/core/discord/discord_controller.py @@ -108,7 +108,7 @@ class DiscordController: def pre_start(self): self.setting_service.register(self.module_name, "discord_token", "", HiddenSettingType(allow_empty=True), - "Enter your Discord token her") + "Enter your Discord token here") def get_name(self, discord_id): data = self.db.query_single( @@ -181,7 +181,7 @@ class DiscordController: @event(event_type="connect", description="Connects the Discord client automatically on startup, if a token exists") def handle_connect_event(self, _, _1): token = self.setting_discord_token().get_value() - if token == "None": + if token.lower() in ["none", "", "null"]: return # noinspection PyTypeChecker @@ -193,7 +193,7 @@ class DiscordController: @event(event_type=BanService.BAN_ADDED_EVENT, description="Ban user from Discord") def ban_added_event(self, _, event_data): token = self.setting_discord_token().get_value() - if token == "None": + if token.lower() in ["none", "", "null"]: return account = self.account_service.get_account(event_data.char_id) if account.discord_joined == 1 and account.discord_id != "": @@ -204,7 +204,7 @@ class DiscordController: @event(event_type=BanService.BAN_REMOVED_EVENT, description="Remove Discord ban") def ban_removed_event(self, _, event_data): token = self.setting_discord_token().get_value() - if token == "None": + if token.lower() in ["none", "", "null"]: return account = self.account_service.get_account(event_data.char_id) if account.discord_id != "": @@ -288,7 +288,7 @@ class DiscordController: @timerevent(budatime="1h", description="Verify Discord members", run_at_startup=True) def timer_check_discord_members(self, event_type, event_data): token = self.setting_discord_token().get_value() - if token in ["None", "", "NULL", None]: + if token.lower() in ["none", "", "null"]: return if not self.bot.is_ready(): return diff --git a/modules/orgbot/org/org_roster_controller.py b/modules/orgbot/org/org_roster_controller.py index 0bd56e8..0ab533e 100644 --- a/modules/orgbot/org/org_roster_controller.py +++ b/modules/orgbot/org/org_roster_controller.py @@ -202,6 +202,8 @@ class OrgRosterController: self.process_org_msg(ext_msg.params[0], self.MODE_REM_MANUAL) elif [ext_msg.category_id, ext_msg.instance_id] == self.JOINED_ORG: self.process_org_msg(ext_msg.params[0], self.MODE_ADD_MANUAL) + # This just writes everything to the log.... also tower messages, and so on. mainly for debugging reasons, + # may change in the future. # noinspection SqlInsertValues self.db.exec("INSERT INTO org_activity (message, time) VALUES(?, ?)", [ext_msg.get_message(), time.time()]) diff --git a/modules/raidbot/tower/tower_attack_controller.py b/modules/raidbot/tower/tower_attack_controller.py index 7de7c83..236151d 100644 --- a/modules/raidbot/tower/tower_attack_controller.py +++ b/modules/raidbot/tower/tower_attack_controller.py @@ -2,11 +2,12 @@ import time from core.chat_blob import ChatBlob from core.command_param_types import Const, Int, NamedParameters -from core.decorators import instance, command, event +from core.decorators import instance, command, event, setting from core.job_scheduler import JobScheduler from core.logger import Logger from core.public_channel_service import PublicChannelService from core.setting_service import SettingService +from core.setting_types import BooleanSettingType from core.text import Text from core.igncore import Tyrbot from modules.core.accounting.services.account_service import AccountService @@ -14,6 +15,9 @@ from modules.raidbot.tower.tower_controller import TowerController from modules.raidbot.tower.tower_service import TowerService from modules.standard.helpbot.playfield_controller import PlayfieldController +# TODO: This module should get split again in the future, allowing tower-tracking in orgbots, or other types. +# + @instance() class TowerAttackController: @@ -144,9 +148,9 @@ class TowerAttackController: blob += " " + self.format_timestamp(row.created_at, t) blob += "\n" - return ChatBlob("Battle Info %d" % battle_id, blob) + return ChatBlob(f"Battle Info {battle_id}", blob) - @event(event_type=TowerController.TOWER_ATTACK_EVENT, description="Warn on Tower attacks", is_hidden=True) + @event(event_type=TowerController.TOWER_ATTACK_EVENT, description="Create logentries for tower attacks", is_hidden=True) def tower_attack_event(self, _, event_data): t = int(time.time()) site_number = self.find_closest_site_number(event_data.location.playfield.id, event_data.location.x_coord, @@ -167,8 +171,15 @@ class TowerAttackController: attacker.get("ai_level", 0), attacker.get("profession", ""), event_data.location.x_coord, event_data.location.y_coord, 0, battle.id, t]) - @event(event_type=TowerController.TOWER_ATTACK_EVENT, description="Notify Tower attacks on own org") + @setting(name="tower_notify_type", value=False, description="Only notify when our orgs are involved") + def tower_notify_type(self) -> BooleanSettingType: + return BooleanSettingType() + + @event(event_type=TowerController.TOWER_ATTACK_EVENT, description="Notify whenever a tower attack happens") def tower_def_event(self, _, event_data): + if self.tower_notify_type().get_value(): + if not (event_data.attacker.get("org_name", None) in self.account_service.get_org_names() or event_data.defender.org_name in self.account_service.get_org_names()): + return if event_data.attacker.get("name", None) is not None: field_id = self.find_closest_site_number(event_data.location.playfield.id, event_data.location.x_coord, event_data.location.y_coord) @@ -176,12 +187,12 @@ class TowerAttackController: "SELECT t.*, p.short_name, p.long_name FROM tower_site t " "JOIN playfields p ON t.playfield_id = p.id WHERE t.playfield_id = ? AND site_number = ?", [event_data.location.playfield.id, field_id]) - lca = self.text.format_page("%s - %d" % (event_data.location.playfield.long_name, field_id), + lca = self.text.format_page(f"{event_data.location.playfield.long_name} - {field_id:d}", self.tower.format_site_info(row)) attacker = self.text.format_char_info(event_data.attacker) add = "" if account := self.account_service.get_account(event_data.attacker.char_id): - if account.disabled == 0 and account.member != 0: + if self.account_service.simple_checks(account): add = " :: He's a Raider!" self.bot.send_private_channel_message( f"[NW] " @@ -235,12 +246,11 @@ class TowerAttackController: raise Exception("Unknown victory event type: '%s'" % event_data.type) def format_attacker(self, row): - level = ("%d/%d" % ( - row.att_level, row.att_ai_level)) if row.att_ai_level > 0 else "%d" % row.att_level + level = f"{row.att_level}/{row.att_ai_level}" if row.att_ai_level > 0 else f"{row.att_level}" org = row.att_org_name + " " if row.att_org_name else "" victor = " - Winner!" if row.is_victory else "" - return "%s (%s %s) %s(%s)%s" % ( - row.att_char_name or "Unknown attacker", level, row.att_profession, org, row.att_faction, victor) + return f"{row.att_char_name or 'Unknown attacker'} ({level} {row.att_profession})" \ + f" {org}({row.att_faction}){victor}" def find_closest_site_number(self, playfield_id, x_coord, y_coord): # noinspection SqlUnused @@ -301,8 +311,7 @@ class TowerAttackController: "INSERT INTO tower_battle (playfield_id, site_number, def_org_name, def_faction, " "is_finished, battle_type, last_updated) VALUES (?, ?, ?, ?, ?, ?, ?)", [playfield_id, site_number, org_name, faction, is_finished, battle_type, t]) - time.sleep(0.5) - return self.db.query_single("SELECT * FROM tower_battle WHERE id = ?", [self.db.last_insert_id()]) + return self.db.query_single(sql, [playfield_id, site_number, is_finished, org_name, faction, last_updated]) def get_last_attack(self, att_faction, att_org_name, def_faction, def_org_name, playfield_id, t): last_updated = t - (8 * 3600) diff --git a/modules/raidbot/tower/tower_hot_controller.py b/modules/raidbot/tower/tower_hot_controller.py index 700b705..1d255a7 100644 --- a/modules/raidbot/tower/tower_hot_controller.py +++ b/modules/raidbot/tower/tower_hot_controller.py @@ -87,7 +87,7 @@ class TowerHotController(BaseModule): description="Shows hot playfields by level") def free(self, _, ): blob = "" - towers = [x for x in self.towercache.get_free() if x.short_name not in ['AND', 'GTC']] + towers = self.towercache.get_free() for row in towers: blob += self.towercache.format_entry(row, len(towers)) diff --git a/modules/raidbot/tower/tower_service.py b/modules/raidbot/tower/tower_service.py index 151c531..2a1026a 100644 --- a/modules/raidbot/tower/tower_service.py +++ b/modules/raidbot/tower/tower_service.py @@ -7,11 +7,13 @@ from requests import Session from conf.config import BotConfig from core.aochat.BaseModule import BaseModule from core.db import DB -from core.decorators import instance, timerevent, event +from core.decorators import instance, timerevent, event, setting from core.job_scheduler import JobScheduler +from core.setting_types import BooleanSettingType from core.text import Text from core.igncore import Tyrbot from core.util import Util +from modules.core.accounting.services.account_service import AccountService from modules.raidbot.tower.tower_controller import TowerController from modules.standard.helpbot.playfield_controller import PlayfieldController @@ -30,6 +32,7 @@ class TowerService(BaseModule): self.text: Text = registry.get_instance("text") self.playfield_controller: PlayfieldController = registry.get_instance("playfield_controller") self.job_scheduler: JobScheduler = registry.get_instance("job_scheduler") + self.account_service: AccountService = registry.get_instance("account_service") mod = __import__(f'conf.{sys.argv[1]}', fromlist=['BotConfig']) config: BotConfig = getattr(mod, 'BotConfig') @@ -61,10 +64,18 @@ class TowerService(BaseModule): if event_data.attacker.get("org_id", None): self.attack_hot.append({'org_name': event_data.attacker.org_name, 'hot': time.time() + 60 * 60}) + @setting(name="tower_notify_type", value=False, description="Only notify when our orgs are involved") + def tower_notify_type(self) -> BooleanSettingType: + return BooleanSettingType() + @event(event_type=TowerController.TOWER_VICTORY_EVENT, description="Send NW warnings") def victory(self, _, event_data): t = int(time.time()) if event_data.type == "attack": + if self.tower_notify_type().get_value(): + if not (event_data.winner.get("org_name", None) in self.account_service.get_org_names() + or event_data.loser.org_name in self.account_service.get_org_names()): + return row = self.get_last_attack(event_data.winner.faction, event_data.winner.org_name, event_data.loser.faction, event_data.loser.org_name, event_data.location.playfield.id, t) self.send_nw_warn(0, diff --git a/modules/standard/track/track_controller.py b/modules/standard/track/track_controller.py index 04a74f2..54781da 100644 --- a/modules/standard/track/track_controller.py +++ b/modules/standard/track/track_controller.py @@ -48,12 +48,12 @@ class TrackController(BaseModule): self.event_service.register_event_type("track_logon") self.event_service.register_event_type("track_logoff") self.setting_service.register(self.module_name, "track_on_color", "#FF0000", ColorSettingType(), - "Color for Track logon") + "Color for Track logon") self.setting_service.register(self.module_name, "track_off_color", "#00FF00", ColorSettingType(), - "Color for Track logoff") + "Color for Track logoff") self.setting_service.register(self.module_name, "autotrack", 'none', TextSettingType(['omni', 'clan', 'neutral', "none"]), - "Autotrack all players initiating tower attacks towards this faction:") + "Autotrack all players initiating tower attacks towards this faction:") self.db.exec( "CREATE TABLE IF NOT EXISTS track(" "char_id int not null primary key, " @@ -85,23 +85,25 @@ class TrackController(BaseModule): def track_fire_logoff(self, _1, event_data): if buddy := self.buddy_service.get_buddy(event_data.char_id): if "track" in buddy["types"]: - self.event_service.fire_event("track_logoff", self.db.query_single("SELECT * from player where char_id=?", - [event_data.char_id])) - self.db.exec("DELETE FROM online where char_id=? and bot=?", [event_data.char_id, self.bot.get_char_id()]) + self.event_service.fire_event("track_logoff", + self.db.query_single("SELECT * from player where char_id=?", + [event_data.char_id])) + self.db.exec("DELETE FROM online where char_id=? and bot=?", + [event_data.char_id, self.bot.get_char_id()]) - @event(event_type="track_logon", description="Fire tracker events", is_hidden=True) + @event(event_type="track_logon", description="Fire tracker logon events") def track_logon(self, _1, user): if self.bot.is_ready(): color = self.setting_service.get("track_on_color").format_text("ON") self.send_t_warn(0, f'{color} :: {self.text.format_char_info(user)}') - @event(event_type="track_logoff", description="Fire tracker events", is_hidden=True) + @event(event_type="track_logoff", description="Fire tracker logoff events") def track_logoff(self, _1, user): if self.bot.is_ready(): color = self.setting_service.get("track_off_color").format_text("OFF") self.send_t_warn(0, f'{color} :: {self.text.format_char_info(user)}') - @event(event_type=TowerController.TOWER_ATTACK_EVENT, description="Warn on Tower attacks", is_hidden=True) + @event(event_type=TowerController.TOWER_ATTACK_EVENT, description="Autottrack players attacking our faction") def tower_attack_event(self, _, event_data): attacker = event_data.attacker if event_data.defender.faction.lower() == self.setting_service.get_value("autotrack"):