import time from core.decorators import instance from core.dict_object import DictObject from core.logger import Logger from modules.core.accounting.services.account_service import AccountService @instance() class BanService: BAN_ADDED_EVENT = "ban_added" BAN_REMOVED_EVENT = "ban_removed" def __init__(self): self.logger = Logger(__name__) def inject(self, registry): self.db = registry.get_instance("db") self.event_service = registry.get_instance("event_service") self.command_service = registry.get_instance("command_service") self.account_service: AccountService = registry.get_instance("account_service") def pre_start(self): self.db.exec("CREATE TABLE IF NOT EXISTS ban_list (char_id INT NOT NULL, " "sender_char_id INT NOT NULL, " "created_at INT NOT NULL, " "finished_at INT NOT NULL, " "reason VARCHAR(255) NOT NULL, " "ended_early SMALLINT NOT NULL, " "INDEX `char_id` (`char_id`) USING BTREE, " "INDEX `sender_char_id` (`sender_char_id`) USING BTREE)") self.db.exec("CREATE TABLE IF NOT EXISTS ban_org_list (org_id INT NOT NULL, " "sender_char_id INT NOT NULL, " "created_at INT NOT NULL, " "finished_at INT NOT NULL, " "reason VARCHAR(255) NOT NULL, " "ended_early SMALLINT NOT NULL, " "INDEX `org_id` (`org_id`) USING BTREE, " "INDEX `sender_char_id` (`sender_char_id`) USING BTREE)") self.event_service.register_event_type(self.BAN_ADDED_EVENT) self.event_service.register_event_type(self.BAN_REMOVED_EVENT) def start(self): self.command_service.register_command_pre_processor(self.check_for_banned) def add_ban(self, char_id, sender_char_id, duration=None, reason=None): reason = reason or "" t = int(time.time()) if duration: finished_at = t + duration else: finished_at = -1 num_rows = self.db.exec("INSERT INTO ban_list (char_id, sender_char_id, created_at, " "finished_at, reason, ended_early) VALUES (?, ?, ?, ?, ?, 0)", [char_id, sender_char_id, t, finished_at, reason]) if num_rows: self.account_service.create_users([(char_id, char_id, 0, time.time(), time.time())]) self.db.exec("UPDATE account set disabled=1 where main=(SELECT main from account where char_id=?)", [char_id]) self.event_service.fire_event(self.BAN_ADDED_EVENT, DictObject({"char_id": char_id, "sender_char_id": sender_char_id, "duration": duration, "reason": reason})) return num_rows def remove_ban(self, char_id): 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 num_rows: self.db.exec("UPDATE account SET disabled = 0 " "WHERE main = (SELECT main from account where char_id=?)", [char_id]) self.event_service.fire_event(self.BAN_REMOVED_EVENT, DictObject({"char_id": char_id})) return num_rows def get_ban(self, char_id): return self.db.query_single("SELECT * FROM account " "WHERE char_id = (SELECT main from account where char_id=?) and disabled=1", [char_id]) def get_ban_list(self): 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]) 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)) return False else: return True