Files
igncore/modules/standard/track/track_controller.py
T
Minidodo 9f1da9a00d Fixed warnings caused by non-existing messagehub channels.
Changed the setting registration, removed the warnings.
Loot roll messages are more obvious now.
Superadmins are meant to stay mostily hidden, but are being exposed in !system again.
2021-08-29 17:54:18 +02:00

229 lines
13 KiB
Python

import math
from core.aochat.BaseModule import BaseModule
from core.aochat.server_packets import BuddyAdded
from core.buddy_service import BuddyService
from core.chat_blob import ChatBlob
from core.command_param_types import Character, Options, Const, Any, NamedParameters
from core.db import DB
from core.decorators import instance, command, event
from core.dict_object import DictObject
from core.event_service import EventService
from core.job_scheduler import JobScheduler
from core.lookup.pork_service import PorkService
from core.message_hub_service import MessageHubService
from core.private_channel_service import PrivateChannelService
from core.setting_service import SettingService
from core.setting_types import TextSettingType, ColorSettingType
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
# noinspection DuplicatedCode,SqlCaseVsIf
@instance()
class TrackController(BaseModule):
PRIVATE_CHANNEL_PREFIX = "[Priv]"
PAGE_SIZE = 20
MESSAGE_SOURCE = "track_log"
def inject(self, registry):
self.bot: Tyrbot = registry.get_instance("bot")
self.util: Util = registry.get_instance("util")
self.pork: PorkService = registry.get_instance("pork_service")
self.job_scheduler: JobScheduler = registry.get_instance("job_scheduler")
self.text: Text = registry.get_instance("text")
self.event_service: EventService = registry.get_instance("event_service")
self.setting_service: SettingService = registry.get_instance("setting_service")
self.buddy_service: BuddyService = registry.get_instance("buddy_service")
self.account_service: AccountService = registry.get_instance("account_service")
self.db: DB = registry.get_instance("db")
self.priv: PrivateChannelService = registry.get_instance("private_channel_service")
self.tower: TowerController = registry.get_instance("tower_controller")
self.message_hub_service: MessageHubService = registry.get_instance("message_hub_service")
def pre_start(self):
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")
self.setting_service.register(self.module_name, "track_off_color", "#00FF00", ColorSettingType(),
"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:")
self.db.exec(
"CREATE TABLE IF NOT EXISTS track("
"char_id int not null primary key, "
"initiator int not null, "
"reason varchar(255))")
self.message_hub_service.register_message_source(self.MESSAGE_SOURCE)
@event(event_type="connect", description="Autoadd tracked players on connect", is_hidden=True)
def connect_add(self, _1, _2):
query = self.db.query("SELECT * from track")
for user in query:
self.buddy_service.add_buddy(user.char_id, "track")
@event(event_type="buddy_logon", description="Fire tracker events", is_hidden=True)
def track_fire_logon(self, _, event_data):
if self.bot.is_ready():
if "track" in (self.buddy_service.get_buddy(event_data.char_id) or {'types': []})["types"]:
if type(event_data) == BuddyAdded:
self.event_service.fire_event("track_logon",
self.db.query_single("SELECT * from player where char_id=?",
[event_data.char_id]))
self.db.exec("INSERT IGNORE INTO online VALUES(?, ?, ?)",
[event_data.char_id, 'track', self.bot.get_char_id()])
else:
self.job_scheduler.delayed_job(self.track_fire_logon, 10,
DictObject({'char_id': event_data.char_id, 'repeat': True}))
@event(event_type="buddy_logoff", description="Fire tracker events", is_hidden=True)
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()])
@event(event_type="track_logon", description="Fire tracker events", is_hidden=True)
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)
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)
def tower_attack_event(self, _, event_data):
attacker = event_data.attacker
if event_data.defender.faction.lower() == self.setting_service.get_value("autotrack"):
if not self.buddy_service.get_buddy(attacker.char_id):
if self.buddy_service.add_buddy(attacker.char_id, "track"):
self.send_t_warn(0,
f"Now tracking: "
f"<{attacker.faction.lower()}>{attacker.name}</{attacker.faction.lower()}>")
self.db.exec("INSERT IGNORE INTO track VALUES(?, ?, ?)",
[attacker.char_id, self.bot.get_char_id(), "attacked us"])
def send_t_warn(self, _, msg):
self.message_hub_service.send_message(self.MESSAGE_SOURCE, None, "[T] " + msg, "[<cyan>T</cyan>] " + msg)
def get_tracked(self, order, online):
where = "where o.char_id IS NOT NULL" if online else ""
return self.db.query(f"SELECT p.name, p.level, p.ai_level, p.org_name, p.profession, p.faction, "
f"p2.name as initiator, "
f"CASE WHEN o.char_id IS NOT NULL THEN 1 ELSE 0 END AS online, "
f"t.reason from track t "
f"left join player p on p.char_id = t.char_id "
f"left join player p2 on p2.char_id = t.initiator "
f"left join online o on o.char_id = t.char_id {where} group by t.char_id order by {order}")
@command(command="track", params=[Const('add'), Character("character"), Any('reason')], access_level="leader",
description="Initiate tracking for the character", sub_command="add")
def track_add(self, request, _, user, reason):
if not user.char_id:
return f"Character <highlight>{user.name}</highlight> not found."
self.pork.load_character_info(user.char_id, user.name)
if acc := self.account_service.get_account(request.sender.char_id):
if "track" in (self.buddy_service.get_buddy(user.char_id) or {'types': []})["types"]:
return f"Character <highlight>{user.name}</highlight> is already being tracked."
else:
self.pork.load_character_info(user.char_id, user.name)
self.send_t_warn(0, f'Tracking initiated: {user.name} by {acc.name}')
self.buddy_service.add_buddy(user.char_id, 'track')
self.db.exec("INSERT IGNORE INTO track VALUES(?, ?, ?)",
[user.char_id, acc.main, reason])
@command(command="track", params=[Const('rem'), Character("character")], access_level="moderator",
description="Remove character from the tracking", sub_command="rem")
def track_rem(self, request, _, user):
if not user.char_id:
return f"Character <highlight>{user.name}</highlight> not found."
if acc := self.account_service.get_account(request.sender.char_id):
if self.buddy_service.remove_buddy(user.char_id, "track"):
self.db.exec("DELETE FROM track where char_id=?", [user.char_id])
self.send_t_warn(0, f'Tracking stopped: {user.name} by {acc.name}')
return f"Character <highlight>{user.name}</highlight> is nolonger being tracked."
else:
return f"Character <highlight>{user.name}</highlight> is not being tracked."
@command(command="track",
params=[Const('list', is_optional=True), Options(["org", "prof", "tl"], is_optional=True),
NamedParameters(["page"])],
access_level="member",
description="Shows tracked players")
def track_list(self, _, const, group, named_params):
page = int(named_params.page or "1")
offset = (page - 1) * self.PAGE_SIZE
if group is None:
group = 'tl'
if group == "org":
players = self.get_tracked('p.org_name, p.profession, p.level desc, p.name', False if const else True)
return self.format_page(players, "org", offset, page, f"Tracklist by Organisation ({len(players)})",
'No tracked users online', f"track {const or ''} {group or ''}")
elif group == "prof":
players = self.get_tracked('p.profession, p.level desc, p.name', False if const else True)
return self.format_page(players, "prof", offset, page, f"Tracklist by Profession ({len(players)})",
'No tracked users online', f"track {const or ''} {group or ''}")
elif group == "tl":
players = self.get_tracked('p.level desc, p.profession, p.name', False if const else True)
return self.format_page(players, "tl", offset, page, f"Tracklist by Titlelevel ({len(players)})",
'No tracked users online', f"track {const or ''} {group or ''}")
def format_row(self, user):
org = f"[<{user.faction.lower()}>{user.org_name}</{user.faction.lower()}>] " if user.org_name else ""
return f"<tab>{self.util.get_prof_icon(user.profession)} " \
f"{self.text.zfill(user.level, 220)}:<green>{self.text.zfill(user.ai_level, 220)}</green> " \
f"<{user.faction.lower()}>{user.name}</{user.faction.lower()}>" \
f" {org}init by <highlight>{user.initiator}</highlight>: {user.reason} " \
f"{'[<red>ONLINE</red>]' if user.online == 1 else ''}\n"
def format_page(self, tracked, order, offset, page, title, nullmsg, cmd):
selected = tracked[offset:offset + self.PAGE_SIZE]
count = len(selected)
pages = ""
if page > 1:
pages += "Pages: " + self.text.make_tellcmd("«« Page %d" % (page - 1), f'{cmd} --page={page - 1}')
if offset + self.PAGE_SIZE < len(tracked):
pages += f" Page {page}/{math.ceil(len(tracked) / self.PAGE_SIZE)}"
pages += " " + self.text.make_tellcmd("Page %d »»" % (page + 1), f'{cmd} --page={page + 1}')
pages += "\n"
if count == 0:
return nullmsg
else:
blob = "\n\n" + pages + "<font color=CCInfoText>"
if order == "prof":
prof = ""
for player in selected:
if player.profession != prof:
prof = player.profession
blob += f"\n<pagebreak><header>{player.profession}</header>\n"
blob += self.format_row(player)
elif order == "tl":
tl = ""
for player in selected:
titlelevel = self.util.get_title_level(player.level)
if titlelevel != tl:
tl = titlelevel
blob += f"\n<pagebreak><header>TL{titlelevel}</header>\n"
blob += self.format_row(player)
elif order == "org":
org_name = ""
for player in selected:
if player.org_name != org_name:
org_name = player.org_name
blob += f"\n<pagebreak><header>{player.org_name}</header>\n"
blob += self.format_row(player)
blob += "</font>\n" + pages
return ChatBlob(title, blob)