Initial Release of IGNCore version 2.5
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
import inspect
|
||||
from typing import List
|
||||
|
||||
from core.decorators import instance
|
||||
from core.logger import Logger
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
@instance()
|
||||
class AccessService:
|
||||
def __init__(self):
|
||||
self.access_levels = [
|
||||
{"label": "none", "level": 0, "handler": self.no_access},
|
||||
{"label": "all", "level": 100, "handler": self.all_access}]
|
||||
self.logger = Logger(__name__)
|
||||
|
||||
def inject(self, registry):
|
||||
self.character_service = registry.get_instance("character_service")
|
||||
self.account_service = registry.get_instance("account_service")
|
||||
|
||||
def register_access_level(self, label, level, handler):
|
||||
"""
|
||||
Call during pre_start
|
||||
|
||||
Args:
|
||||
label: str
|
||||
level: int
|
||||
handler: (char_id: Int) -> bool
|
||||
"""
|
||||
|
||||
if len(inspect.signature(handler).parameters) != 1:
|
||||
raise Exception(
|
||||
"Incorrect number of arguments for handler '%s.%s()'" % (handler.__module__, handler.__name__))
|
||||
|
||||
self.logger.debug("Registering access level %d with label '%s'" % (level, label))
|
||||
self.access_levels.append({"label": label.lower(), "level": level, "handler": handler})
|
||||
self.access_levels = sorted(self.access_levels, key=lambda k: k["level"])
|
||||
|
||||
def get_access_levels(self) -> List[dict]:
|
||||
return self.access_levels
|
||||
|
||||
def get_access_level(self, char_id) -> dict:
|
||||
account = self.account_service.get_main(char_id)
|
||||
if account:
|
||||
al = self.get_single_access_level(account.char_id)
|
||||
if al["label"] == "all":
|
||||
al = self.get_single_access_level(char_id)
|
||||
return al
|
||||
else:
|
||||
return self.get_single_access_level(char_id)
|
||||
# access_level1 = self.get_single_access_level(char_id)
|
||||
#
|
||||
# alts = self.account_service.get_alts(char_id)
|
||||
# if not alts:
|
||||
# return access_level1
|
||||
#
|
||||
# main = alts[0]
|
||||
# if main.char_id == char_id:
|
||||
# return access_level1
|
||||
# else:
|
||||
# access_level2 = self.get_single_access_level(main.char_id)
|
||||
# if access_level1["level"] < access_level2["level"]:
|
||||
# return access_level1
|
||||
# else:
|
||||
# return access_level2
|
||||
|
||||
def compare_access_levels(self, access_level1, access_level2) -> int:
|
||||
"""
|
||||
Returns a positive number if the access_level1 is greater than access_level2,
|
||||
a negative number if access_level1 is less than access_level2,
|
||||
and 0 if the access levels are equal.
|
||||
|
||||
:param access_level1:
|
||||
:param access_level2:
|
||||
:return: int
|
||||
"""
|
||||
a1 = self.get_access_level_by_label(access_level1)
|
||||
a2 = self.get_access_level_by_label(access_level2)
|
||||
|
||||
return a2["level"] - a1["level"]
|
||||
|
||||
def has_sufficient_access_level(self, char_id1, char_id2) -> bool:
|
||||
"""
|
||||
Returns True if char1 has a higher access level than char2
|
||||
or if char1 is a verified alt of char2, and False otherwise.
|
||||
|
||||
:param char_id1:
|
||||
:param char_id2:
|
||||
:return:
|
||||
"""
|
||||
|
||||
# return True if char_ids are the same
|
||||
if char_id1 == char_id2:
|
||||
return True
|
||||
|
||||
# return True if both chars have the same main
|
||||
if self.account_service.get_main(char_id1).char_id == (self.account_service.get_main(char_id2) or {}).get(
|
||||
"char_id", 0):
|
||||
return True
|
||||
|
||||
a1 = self.get_access_level(char_id1)
|
||||
a2 = self.get_access_level(char_id2)
|
||||
|
||||
return a2["level"] - a1["level"] > 0
|
||||
|
||||
def get_single_access_level(self, char) -> dict:
|
||||
char_id = self.character_service.resolve_char_to_id(char)
|
||||
for access_level in self.access_levels:
|
||||
if access_level["handler"](char_id):
|
||||
return access_level
|
||||
|
||||
def get_access_level_by_level(self, level) -> dict or bool:
|
||||
for access_level in self.access_levels:
|
||||
if access_level["level"] == level:
|
||||
return access_level
|
||||
return False
|
||||
|
||||
def get_access_level_by_label(self, label) -> dict or bool:
|
||||
label = label.lower()
|
||||
for access_level in self.access_levels:
|
||||
if access_level["label"] == label:
|
||||
return access_level
|
||||
return False
|
||||
|
||||
def check_access(self, char, access_level_label) -> bool:
|
||||
char_id = self.character_service.resolve_char_to_id(char)
|
||||
if not char_id:
|
||||
return False
|
||||
# noinspection LongLine
|
||||
return (self.get_access_level(char) or {}).get("level", 100) <= \
|
||||
self.get_access_level_by_label(access_level_label)["level"]
|
||||
|
||||
def no_access(self, char_id) -> bool:
|
||||
return False
|
||||
|
||||
def all_access(self, char_id) -> bool:
|
||||
return True
|
||||
@@ -0,0 +1,568 @@
|
||||
import time
|
||||
from typing import List
|
||||
|
||||
from core.buddy_service import BuddyService
|
||||
from core.db import DB, SqlException
|
||||
from core.decorators import instance, timerevent, event
|
||||
from core.dict_object import DictObject
|
||||
from core.logger import Logger
|
||||
from core.lookup.character_service import CharacterService
|
||||
from core.lookup.pork_service import PorkService
|
||||
from core.setting_service import SettingService
|
||||
from core.setting_types import BooleanSettingType
|
||||
from core.text import Text
|
||||
from core.tyrbot import Tyrbot
|
||||
from modules.core.accounting.services.access_service import AccessService
|
||||
|
||||
|
||||
# noinspection SqlCaseVsIf,SqlResolve,PyMethodMayBeStatic
|
||||
@instance()
|
||||
class AccountService:
|
||||
MAIN_CHANGED_EVENT_TYPE = "main_changed"
|
||||
MEMBER_LOGON = "member_logon"
|
||||
MEMBER_LOGOFF = "member_logoff"
|
||||
|
||||
def __init__(self):
|
||||
self.logger = Logger("Accounting")
|
||||
|
||||
# noinspection PyAttributeOutsideInit
|
||||
def inject(self, registry):
|
||||
self.bot: Tyrbot = registry.get_instance("bot")
|
||||
self.buddy_service: BuddyService = registry.get_instance("buddy_service")
|
||||
self.util = registry.get_instance("util")
|
||||
self.character_service: CharacterService = registry.get_instance("character_service")
|
||||
self.access_service: AccessService = registry.get_instance("access_service")
|
||||
self.db: DB = registry.get_instance("db")
|
||||
self.event_service = registry.get_instance("event_service")
|
||||
self.pork: PorkService = registry.get_instance("pork_service")
|
||||
self.setting_service: SettingService = registry.get_instance("setting_service")
|
||||
self.text: Text = registry.get_instance("text")
|
||||
|
||||
def pre_start(self):
|
||||
self.db.exec("CREATE TABLE IF NOT EXISTS account ("
|
||||
"char_id int(11) NOT NULL,"
|
||||
"points int(11) NOT NULL default 0,"
|
||||
"member int(2) NOT NULL DEFAULT 0,"
|
||||
"created int(255) NOT NULL DEFAULT 0,"
|
||||
"disabled int(2) NOT NULL DEFAULT 0,"
|
||||
"main int(11) NOT NULL DEFAULT char_id,"
|
||||
"subtile_spam int(2) NOT NULL DEFAULT 0,"
|
||||
"auto_invite int(2) NOT NULL DEFAULT 0,"
|
||||
"raid_invite int(2) NOT NULL DEFAULT 1,"
|
||||
"raid_spam int(2) NOT NULL DEFAULT 1,"
|
||||
"news_spam int(2) NOT NULL DEFAULT 1,"
|
||||
"discord_id bigint(30) UNSIGNED NULL DEFAULT 0,"
|
||||
"discord_handle varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',"
|
||||
"discord_invite text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',"
|
||||
"discord_joined int(2) NOT NULL DEFAULT 0,"
|
||||
"logon text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',"
|
||||
"logoff text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',"
|
||||
"last_seen int(11) NOT NULL DEFAULT 0,"
|
||||
"last_updated int(11) NOT NULL DEFAULT 0,"
|
||||
"PRIMARY KEY (char_id) USING BTREE,"
|
||||
"INDEX char_id(char_id) USING BTREE,"
|
||||
"INDEX main(main) USING BTREE,"
|
||||
"INDEX disabled(disabled) USING BTREE,"
|
||||
"INDEX char_id_2(char_id, disabled) USING BTREE,"
|
||||
"INDEX discord_id(discord_id) USING BTREE)")
|
||||
|
||||
self.db.exec(
|
||||
"CREATE TABLE IF NOT EXISTS raid_log ("
|
||||
"raid_id INT PRIMARY KEY AUTO_INCREMENT, "
|
||||
"raid_name VARCHAR(255) NOT NULL, "
|
||||
"started_by BIGINT NOT NULL, "
|
||||
"raid_start INT NOT NULL, "
|
||||
"raid_end INT NOT NULL)")
|
||||
|
||||
self.db.exec(
|
||||
"CREATE TABLE IF NOT EXISTS raid_log_participants ("
|
||||
"raid_id INT NOT NULL, "
|
||||
"raider_id BIGINT NOT NULL, "
|
||||
"accumulated_points INT DEFAULT 0, "
|
||||
"left_raid INT, "
|
||||
"was_kicked INT, "
|
||||
"was_kicked_reason VARCHAR(500))")
|
||||
|
||||
self.db.exec("CREATE TABLE IF NOT EXISTS points_presets ("
|
||||
"preset_id INT PRIMARY KEY AUTO_INCREMENT, "
|
||||
"name VARCHAR(50) NOT NULL, "
|
||||
"points INT DEFAULT 1, "
|
||||
"UNIQUE(name));")
|
||||
self.db.exec("CREATE TABLE IF NOT EXISTS pending_accounts ("
|
||||
"main INT(11) NOT NULL, "
|
||||
"alt INT(11) NOT NULL, "
|
||||
"reason TEXT DEFAULT '', "
|
||||
"recommender INT(11) NOT NULL , "
|
||||
"time int(255) NOT NULL,"
|
||||
"answered int(2) default 0 not null);")
|
||||
|
||||
self.db.exec("CREATE TABLE IF NOT EXISTS account_log ("
|
||||
"log_id INTEGER PRIMARY KEY AUTO_INCREMENT, "
|
||||
"char_id BIGINT NOT NULL, "
|
||||
"type VARCHAR(32), "
|
||||
"delta INT NOT NULL DEFAULT 0, "
|
||||
"leader_id BIGINT NOT NULL, "
|
||||
"reason VARCHAR(255), "
|
||||
"created_at INTEGER NOT NULL, "
|
||||
"INDEX char_id (char_id), "
|
||||
"INDEX leader (leader_id), "
|
||||
"INDEX created(created_at));")
|
||||
|
||||
self.db.exec("CREATE TABLE IF NOT EXISTS ranks ("
|
||||
"main int(11) NOT NULL, "
|
||||
"`rank` varchar(32) not null, "
|
||||
"INDEX main(main, `rank`) USING BTREE)")
|
||||
|
||||
self.db.exec("CREATE TABLE IF NOT EXISTS org_bots(char_id int primary key not null, org_id int not null)")
|
||||
|
||||
self.event_service.register_event_type(self.MAIN_CHANGED_EVENT_TYPE)
|
||||
self.event_service.register_event_type(self.MEMBER_LOGON)
|
||||
self.event_service.register_event_type(self.MEMBER_LOGOFF)
|
||||
self.setting_service.register_new(self.module_name, "is_alliance_bot", False, BooleanSettingType(),
|
||||
"Is this bot used as an alliancebot")
|
||||
self.setting_service.register_new(self.module_name, "alt_verification", False, BooleanSettingType(),
|
||||
"alts require admin verification")
|
||||
|
||||
if self.setting_service.get_value("is_alliance_bot") == "1":
|
||||
self.access_service.register_access_level("officer", 80, self.check_officer)
|
||||
self.access_service.register_access_level("general", 70, self.check_general)
|
||||
self.access_service.register_access_level("president", 60, self.check_president)
|
||||
self.access_service.register_access_level("council", 40, self.check_council)
|
||||
self.access_service.register_access_level("moderator", 30, self.check_moderator)
|
||||
self.access_service.register_access_level("member", 90, self.check_member)
|
||||
self.access_service.register_access_level("admin", 20, self.check_admin)
|
||||
self.access_service.register_access_level("leader", 50, self.check_leader)
|
||||
self.access_service.register_access_level("superadmin", 10, self.check_superadmin)
|
||||
|
||||
def get_main(self, char_id) -> DictObject:
|
||||
alts = self.get_alts(char_id)
|
||||
return alts[0] if alts else self.db.query_single("select * from player where char_id=?", [char_id])
|
||||
|
||||
def get_alts(self, char_id) -> List[DictObject]:
|
||||
return self.db.query(
|
||||
"SELECT p.*, a.* from account a left join player p on a.char_id = p.char_id where "
|
||||
"main=(SELECT main from account where char_id=?) ORDER BY a.main = a.char_id desc, p.level, p.name DESC",
|
||||
[char_id])
|
||||
|
||||
acc_cache = {}
|
||||
|
||||
def get_account(self, char_id) -> DictObject:
|
||||
|
||||
if char_id not in self.acc_cache.keys():
|
||||
out = self.db.query_single(
|
||||
"SELECT a.*, p.* from account a left join player p on a.char_id = p.char_id where "
|
||||
"a.char_id=(SELECT main from account where char_id=?) "
|
||||
"and a.char_id not in (SELECT char_id from org_bots)",
|
||||
[char_id]) or DictObject({})
|
||||
self.acc_cache[char_id] = out
|
||||
self.bot.job_scheduler.delayed_job(lambda x: self.acc_cache.pop(char_id), 5)
|
||||
else:
|
||||
out = self.acc_cache.get(char_id)
|
||||
return out
|
||||
|
||||
def get_entry(self, char_id) -> DictObject:
|
||||
return self.db.query_single("SELECT a.*, p.* from account a left join player p on a.char_id = p.char_id "
|
||||
"where a.char_id=? and a.char_id not in (SELECT char_id from org_bots)",
|
||||
[char_id]) or DictObject({})
|
||||
|
||||
def add_pending_alt(self, main, alt) -> [str, bool]:
|
||||
data = self.check_alt(alt)
|
||||
if data:
|
||||
return data
|
||||
acc = self.get_account(main)
|
||||
if acc:
|
||||
main = acc.main
|
||||
self.pork.load_character_info(alt, skeleton_only=True)
|
||||
self.db.exec("INSERT INTO pending_accounts(main, alt, recommender, time) VALUES(?, ?, ?, ?)",
|
||||
[acc.main, alt, acc.main, time.time()])
|
||||
self.add_log(main, 'system',
|
||||
f'Requested to add <highlight>{self.character_service.resolve_char_to_name(alt)}</highlight>'
|
||||
f' as an alt',
|
||||
acc.main)
|
||||
return ["success", True]
|
||||
|
||||
def add_pending_account(self, main, user, reason) -> [str, bool]:
|
||||
data = self.check_alt(user)
|
||||
if data:
|
||||
return data
|
||||
acc = self.get_account(main)
|
||||
if acc:
|
||||
main = acc.main
|
||||
self.pork.load_character_info(user, skeleton_only=True)
|
||||
self.db.exec("INSERT INTO pending_accounts(main, alt, recommender, reason, time) VALUES(?, ?, ?, ?, ?)",
|
||||
[user, user, acc.main, reason, time.time()])
|
||||
self.add_log(main, 'system',
|
||||
f'Recommended <highlight>{self.character_service.resolve_char_to_name(user)}</highlight>'
|
||||
f' as raider, reason: {reason}',
|
||||
acc.main)
|
||||
return ["success", True]
|
||||
|
||||
def check_alt(self, alt):
|
||||
alt_alts = self.get_alts(alt) or []
|
||||
if len(alt_alts) > 1:
|
||||
for alts in alt_alts:
|
||||
if alts.char_id == alt:
|
||||
if alts.main != alts.char_id:
|
||||
return ["another_main", False]
|
||||
alt_main = self.get_account(alt)
|
||||
if alt_main:
|
||||
if alt_main.main != alt:
|
||||
return ["already_main", False]
|
||||
if self.is_pending(alt):
|
||||
return ['pending_alt', False]
|
||||
|
||||
def is_pending(self, char_id) -> DictObject or bool:
|
||||
return self.db.query_single("SELECT * from pending_accounts where alt=? and answered = 0", [char_id]) or False
|
||||
|
||||
def add_alt(self, sender, alt, approve=False) -> [str, bool]:
|
||||
alt_alts = self.get_alts(alt) or []
|
||||
if alt_alts:
|
||||
if len(alt_alts) > 1:
|
||||
return ["another_main", False]
|
||||
if alt_main := alt_alts[0]:
|
||||
if alt_main.main != alt:
|
||||
return ["already_main", False]
|
||||
acc = self.get_account(sender)
|
||||
if acc:
|
||||
main = acc.main
|
||||
self.pork.load_character_info(alt, skeleton_only=True)
|
||||
member = -1 if acc.disabled == 1 or acc.member == -1 else 0
|
||||
if self.db.exec("INSERT IGNORE INTO account(char_id, main, created, member) VALUES(?, ?, ?, ?)",
|
||||
[alt, main, time.time(), member]) == 0:
|
||||
self.db.exec("UPDATE account set main=?, created=? where char_id=?", [main, time.time(), alt])
|
||||
self.event_service.fire_event(self.MAIN_CHANGED_EVENT_TYPE,
|
||||
DictObject({"old_main_id": alt, "new_main_id": main}))
|
||||
if not approve:
|
||||
self.add_log(sender, 'system',
|
||||
f'Added <highlight>{self.character_service.resolve_char_to_name(alt)}</highlight>'
|
||||
f' as an alt',
|
||||
acc.main)
|
||||
# Only add as member if he's neither banned, nor unregistered
|
||||
if member != -1:
|
||||
self.buddy_service.add_buddy(alt, "member")
|
||||
return ["success", True]
|
||||
self.db.exec("INSERT IGNORE INTO account(char_id, main, created, member) VALUES(?, ?, ?, ?)",
|
||||
[sender, sender, time.time(), -1])
|
||||
self.db.exec("INSERT INTO account(char_id, main, created, member) VALUES(?, ?, ?, ?) ON DUPLICATE KEY UPDATE "
|
||||
"main=VALUE(main), discord_id=0, discord_handle='', discord_invite='', discord_joined=0",
|
||||
[alt, sender, time.time(), -1])
|
||||
if not approve:
|
||||
self.add_log(sender, 'system',
|
||||
f'Added <highlight>{self.character_service.resolve_char_to_name(alt)}</highlight> as an alt',
|
||||
sender)
|
||||
# Main does not exist, do not add as member
|
||||
# self.buddy_service.add_buddy(alt, "member")
|
||||
return ["success", True]
|
||||
|
||||
def remove_alt(self, sender, alt) -> [str, bool]:
|
||||
if not self.db.query(
|
||||
"SELECT * FROM account where char_id=? and main=(SELECT main from account where char_id=?)",
|
||||
[alt, sender]):
|
||||
return ["not_alt", False]
|
||||
alts = self.get_alts(sender)
|
||||
for row in alts:
|
||||
if row.char_id == alt and row.main == alt:
|
||||
return ["remove_main", False]
|
||||
if row.char_id == alt and row.main == alts[0].char_id:
|
||||
self.db.exec("UPDATE account set main=? where char_id=?", [alt, alt])
|
||||
self.add_log(sender, 'system',
|
||||
f'Removed <highlight>{self.character_service.resolve_char_to_name(alt)}</highlight>'
|
||||
f' from his alts.',
|
||||
sender)
|
||||
return ["success", True]
|
||||
else:
|
||||
return [""]
|
||||
|
||||
def set_as_main(self, sender) -> [str, bool]:
|
||||
alts = self.get_alts(sender)
|
||||
|
||||
if len(alts) < 2:
|
||||
return ["not_an_alt", False]
|
||||
elif alts[0].char_id == sender:
|
||||
return ["already_main", False]
|
||||
else:
|
||||
self.db.exec("UPDATE account set main=? where main=(SELECT main from account where char_id=?)",
|
||||
[sender, sender])
|
||||
self.event_service.fire_event(self.MAIN_CHANGED_EVENT_TYPE,
|
||||
DictObject({"old_main_id": alts[0].char_id,
|
||||
"new_main_id": sender}))
|
||||
return ["success", True]
|
||||
|
||||
def get_orgs(self) -> list:
|
||||
try:
|
||||
return [x["org_id"] for x in self.db.query("SELECT * from orgs", [])]
|
||||
except SqlException:
|
||||
return [self.bot.public_channel_service.org_id]
|
||||
|
||||
def create_users(self, users, disable=False) -> int:
|
||||
if type(users) == list and len(users) > 0:
|
||||
with self.db.pool.get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
if disable:
|
||||
cur.executemany(
|
||||
"INSERT IGNORE INTO account(char_id, main, member, disabled, last_updated, created) "
|
||||
"VALUES(?, ?, ?, 1, ?, ?) ON DUPLICATE KEY UPDATE "
|
||||
"member=VALUE(member), last_updated=VALUE(last_updated), disabled=1",
|
||||
users)
|
||||
return cur.rowcount
|
||||
cur.executemany(
|
||||
"INSERT IGNORE INTO account(char_id, main, member, last_updated, created) "
|
||||
"VALUES(?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE "
|
||||
"member=VALUE(member), last_updated=VALUE(last_updated)",
|
||||
users)
|
||||
return cur.rowcount
|
||||
|
||||
def account_disable(self, char_id) -> bool:
|
||||
return True if self.db.exec(
|
||||
"UPDATE account set disabled=1 where main in (SELECT main from account where char_id=?)",
|
||||
[char_id]) else False
|
||||
|
||||
def account_enable(self, char_id) -> bool:
|
||||
return True if self.db.exec(
|
||||
"UPDATE account set disabled=0 where main in (SELECT main from account where char_id=?)",
|
||||
[char_id]) else False
|
||||
|
||||
def remove_members(self, users) -> None:
|
||||
if type(users) == list and len(users) > 0:
|
||||
with self.db.pool.get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.executemany("UPDATE account set member=-1 where char_id=? and ?", users)
|
||||
|
||||
def check_member(self, char_id) -> bool:
|
||||
account = self.get_account(char_id) or {}
|
||||
if account.get('disabled', 1) == 1:
|
||||
return False
|
||||
if account.get('member', -1) == -1:
|
||||
return False
|
||||
if self.setting_service.get_value("is_alliance_bot") == "0":
|
||||
return True
|
||||
if account.get('org_id', 0) not in self.get_orgs():
|
||||
return False
|
||||
return True
|
||||
|
||||
def check_president(self, char_id) -> bool:
|
||||
if self.setting_service.get_value("is_alliance_bot") == "0":
|
||||
return False
|
||||
account = self.get_account(char_id) or {}
|
||||
if not self.simple_checks(account):
|
||||
return False
|
||||
if account.get('org_rank_id', -1) == 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def check_general(self, char_id) -> bool:
|
||||
if self.setting_service.get_value("is_alliance_bot") == "0":
|
||||
return False
|
||||
account = self.get_account(char_id) or {}
|
||||
if not self.simple_checks(account):
|
||||
return False
|
||||
if self.get_rank_count(char_id) != 7:
|
||||
return False
|
||||
if account.get('org_rank_id', -1) <= 1:
|
||||
return True
|
||||
return False
|
||||
|
||||
def check_officer(self, char_id) -> bool:
|
||||
if self.setting_service.get_value("is_alliance_bot") == "0":
|
||||
return False
|
||||
account = self.get_account(char_id) or {}
|
||||
if not self.simple_checks(account):
|
||||
return False
|
||||
if self.get_rank_count(char_id) != 7:
|
||||
return False
|
||||
if account.get('org_rank_id', -1) <= 2:
|
||||
return True
|
||||
return False
|
||||
|
||||
def check_council(self, char_id) -> bool:
|
||||
if self.setting_service.get_value("is_alliance_bot") == "0":
|
||||
return False
|
||||
if self.simple_checks(self.get_account(char_id)):
|
||||
return "council" in self.get_ranks(char_id)
|
||||
|
||||
def check_leader(self, char_id) -> bool:
|
||||
if self.simple_checks(self.get_account(char_id)):
|
||||
return "leader" in self.get_ranks(char_id)
|
||||
|
||||
def check_moderator(self, char_id) -> bool:
|
||||
if self.simple_checks(self.get_account(char_id)):
|
||||
return "moderator" in self.get_ranks(char_id)
|
||||
|
||||
def check_admin(self, char_id) -> bool:
|
||||
if self.simple_checks(self.get_account(char_id)):
|
||||
return "admin" in self.get_ranks(char_id)
|
||||
|
||||
def check_superadmin(self, char_id) -> int:
|
||||
return char_id in self.bot.superadmin
|
||||
|
||||
def get_ranks(self, char_id) -> List[DictObject]:
|
||||
return [x["rank"] for x in
|
||||
self.db.query(" SELECT rank FROM ranks where main = (SELECT main from account where char_id=? limit 1)",
|
||||
[char_id])] or []
|
||||
|
||||
def get_all_admins(self) -> List[DictObject]:
|
||||
return self.get_by_group("admin")
|
||||
|
||||
def get_all_moderators(self) -> List[DictObject]:
|
||||
return self.get_by_group("moderator")
|
||||
|
||||
def get_all_councils(self) -> List[DictObject]:
|
||||
return self.get_by_group("council")
|
||||
|
||||
def get_all_leaders(self) -> List[DictObject]:
|
||||
return self.get_by_group("leader")
|
||||
|
||||
def get_all_members(self, online_only=False) -> List[DictObject]:
|
||||
return self.db.query(
|
||||
f"SELECT p.*, a.*, CASE when o.char_id IS NOT NULL then 1 ELSE 0 end as online from account a "
|
||||
f"LEFT JOIN player p ON a.char_id=p.char_id "
|
||||
f"LEFT JOIN (SELECT * FROM online WHERE bot=?) o ON a.char_id=o.char_id "
|
||||
f"WHERE a.char_id NOT IN (SELECT char_id from org_bots) "
|
||||
f"and a.disabled = 0 {'and o.char_id is not null' if online_only else ''} "
|
||||
f"order by a.main, a.main=a.char_id desc, p.level desc, p.ai_level desc",
|
||||
[self.bot.get_char_id()])
|
||||
|
||||
def get_by_group(self, group) -> List[DictObject]:
|
||||
return self.db.query("""SELECT CASE when rank = 'admin' then 0
|
||||
when rank = 'moderator' then 1
|
||||
when rank = 'council' then 2
|
||||
when rank = 'leader' then 3
|
||||
ELSE 99 END AS rank_id,
|
||||
CASE when o.char_id IS NOT NULL
|
||||
then 1
|
||||
ELSE 0 end as online,
|
||||
p.*, a.* FROM ranks r
|
||||
LEFT JOIN account a ON r.main=a.main
|
||||
LEFT JOIN player p ON a.char_id=p.char_id
|
||||
LEFT JOIN online o ON a.char_id=o.char_id
|
||||
WHERE r.rank=?
|
||||
ORDER BY rank_id, a.main desc, a.main=a.char_id DESC, p.name """, [group])
|
||||
|
||||
def get_group_tag(self, string) -> str or bool:
|
||||
string = string.lower()
|
||||
if string in ["adm", "admins", "admin", "administrator", "administrators"]:
|
||||
return "admin"
|
||||
elif string in ["mod", "mods", "moderator", "moderators"]:
|
||||
return "moderator"
|
||||
elif string in ["cnc", "council", "councilors"]:
|
||||
return "council"
|
||||
elif string in ["rl", "leader", "leaders", "raidleader", "raidleaders", "rls"]:
|
||||
return "leader"
|
||||
elif string in ["all", "full", "everyone"]:
|
||||
return "all"
|
||||
else:
|
||||
return False
|
||||
|
||||
def add_log(self, char_id, log_type, message, leader, delta=0) -> None:
|
||||
main = self.get_main(char_id).char_id
|
||||
self.db.exec("INSERT INTO account_log(char_id, type, delta, leader_id, reason, created_at) "
|
||||
"VALUES (?, ?, ?, ?, ?, ?)",
|
||||
[main, log_type, delta, leader, message, time.time()])
|
||||
|
||||
def get_logs(self, user, log_type=None, limit=25) -> List[DictObject]:
|
||||
if not log_type:
|
||||
return self.db.query("SELECT * FROM account_log "
|
||||
"where char_id=? and type != 'admin' order by log_id desc LIMIT ? ", [user, limit])
|
||||
|
||||
else:
|
||||
return self.db.query("SELECT * FROM account_log "
|
||||
"where char_id=? and type=? order by log_id desc LIMIT ?", [user, log_type, limit])
|
||||
|
||||
def get_log_by_id(self, log_id) -> DictObject:
|
||||
return self.db.query_single("SELECT * FROM account_log where log_id=? ", [log_id])
|
||||
|
||||
def format_entry(self, entry) -> str:
|
||||
msg = f"<grey>[{self.util.format_datetime(entry.created_at)}] " \
|
||||
f"[{self.text.make_tellcmd('D', f'account log id {entry.log_id}')}]</grey> "
|
||||
entry.type = entry.type.lower()
|
||||
if entry.type == "points":
|
||||
entry.reason = entry.reason.replace('"', "'")
|
||||
msg += f"<white>{f'<green>+{entry.delta}P</green>' if entry.delta >= 0 else f'<red>{entry.delta}P</red>'}" \
|
||||
f" by <notice>{self.character_service.resolve_char_to_name(entry.leader_id)}</notice>" \
|
||||
f" for <notice>{entry.reason}</notice></white>"
|
||||
elif entry.type == "loot":
|
||||
msg += f"<white>Won Item: {entry.reason}</white>"
|
||||
elif entry.type == "raid":
|
||||
msg += f"<white>{entry.reason}</white>"
|
||||
elif entry.type == "public":
|
||||
msg += f"<white>{entry.reason}</white>"
|
||||
elif entry.type == "admin":
|
||||
msg += f"<white>Notice from " \
|
||||
f"<notice>{self.character_service.resolve_char_to_name(entry.leader_id)}</notice>: " \
|
||||
f"{entry.reason}</white>"
|
||||
elif entry.type == "system":
|
||||
msg += f"<yellow>{entry.reason}</yellow>"
|
||||
|
||||
return msg + "\n"
|
||||
|
||||
def add_pts(self, char_id, points, reason, leader) -> None:
|
||||
self.db.exec("UPDATE account set points = points+? where char_id=(select main from account where char_id=?)",
|
||||
[points, char_id])
|
||||
self.add_log(char_id, 'points', reason, leader, delta=points)
|
||||
|
||||
def rem_pts(self, char_id, points, reason, leader) -> None:
|
||||
if points < 0:
|
||||
points = -points
|
||||
self.db.exec("UPDATE account set points = points-? where char_id=(select main from account where char_id=?)",
|
||||
[points, char_id])
|
||||
self.add_log(char_id, 'points', reason, leader, delta=-points)
|
||||
|
||||
def add_rank(self, char_id, rank) -> int:
|
||||
return self.db.exec("INSERT INTO ranks(main, `rank`) VALUES(?, ?)", [char_id, rank])
|
||||
|
||||
def del_rank(self, char_id, rank) -> int:
|
||||
return self.db.exec("DELETE FROM ranks where main=? and rank =?", [char_id, rank])
|
||||
|
||||
@timerevent(budatime="12h", description="Delete dead ranks")
|
||||
def clear_raid(self, _, _1):
|
||||
count = self.db.exec("DELETE FROM ranks where main not in (SELECT main from account)")
|
||||
if count > 0:
|
||||
self.logger.info(f"Purged {count} dead ranks")
|
||||
count = self.db.exec(
|
||||
"delete from ranks where main in(select r.main from ranks r "
|
||||
"left join account a on r.main=a.char_id "
|
||||
"where a.member=-1)")
|
||||
if count > 0:
|
||||
self.logger.info(f"Purged {count} ranks; caused by: main no longer in the alliance")
|
||||
|
||||
@event(event_type="main_changed", description="Fix ranks")
|
||||
def fix_ranks(self, _, data):
|
||||
self.db.exec("UPDATE ranks set main=? where main=?", [data.new_main_id, data.old_main_id])
|
||||
self.db.exec("UPDATE account_log set char_id=? where char_id=?", [data.new_main_id, data.old_main_id])
|
||||
self.db.exec("UPDATE account_log set leader_id=? where leader_id=?", [data.new_main_id, data.old_main_id])
|
||||
|
||||
@event(event_type="buddy_logon", description="Member logon manager")
|
||||
def member_login(self, _, data):
|
||||
buddy = self.buddy_service.get_buddy(data.char_id)
|
||||
if buddy:
|
||||
if self.bot.is_ready():
|
||||
if "member" in buddy['types'] or "org_member" in buddy['types']:
|
||||
if main := self.get_account(data.char_id):
|
||||
self.event_service.fire_event(self.MEMBER_LOGON, DictObject({'account': main, 'packet': data}))
|
||||
else:
|
||||
if main := self.get_account(data.char_id):
|
||||
self.event_service.fire_event(self.MEMBER_LOGON, DictObject({'account': main, 'packet': data}))
|
||||
|
||||
@event(event_type="buddy_logoff", description="Member logoff manager")
|
||||
def member_logout(self, _, data):
|
||||
if self.bot.is_ready():
|
||||
buddy = self.buddy_service.get_buddy(data.char_id)
|
||||
if buddy:
|
||||
if "member" in buddy['types'] or "org_member" in buddy['types']:
|
||||
if main := self.get_account(data.char_id):
|
||||
self.event_service.fire_event(self.MEMBER_LOGOFF, DictObject({'account': main, 'packet': data}))
|
||||
|
||||
def get_rank_count(self, char_id):
|
||||
return self.db.query_single(
|
||||
"SELECT MAX(org_rank_id)+1 AS count FROM player WHERE org_id=(SELECT org_id FROM player where char_id=?)",
|
||||
[char_id]).count
|
||||
|
||||
def simple_checks(self, account):
|
||||
if account.get('disabled', 1) == 1:
|
||||
return False
|
||||
if account.get('member', -1) == -1:
|
||||
return False
|
||||
if self.setting_service.get_value("is_alliance_bot") == "1":
|
||||
if account.get('org_id', 0) not in self.get_orgs():
|
||||
return False
|
||||
return True
|
||||
Reference in New Issue
Block a user