181 lines
8.3 KiB
Python
181 lines
8.3 KiB
Python
import time
|
|
from functools import partial
|
|
|
|
from core.aochat.server_packets import BuddyAdded, CharacterName
|
|
from core.chat_blob import ChatBlob
|
|
from core.command_param_types import Character, Const, Int
|
|
from core.command_request import CommandRequest
|
|
from core.db import DB
|
|
from core.decorators import instance, command, timerevent
|
|
from core.dict_object import DictObject
|
|
from core.lookup.pork_service import PorkService
|
|
from core.text import Text
|
|
from core.igncore import IgnCore
|
|
|
|
|
|
@instance()
|
|
class CharacterInfoController:
|
|
BUDDY_IS_ONLINE_TYPE = "is_online"
|
|
|
|
def __init__(self):
|
|
self.name_history = []
|
|
self.waiting_for_update = {}
|
|
|
|
def inject(self, registry):
|
|
self.bot: IgnCore = registry.get_instance("bot")
|
|
self.db: DB = registry.get_instance("db")
|
|
self.text: Text = registry.get_instance("text")
|
|
self.pork_service: PorkService = registry.get_instance("pork_service")
|
|
self.command_alias_service = registry.get_instance("command_alias_service")
|
|
self.util = registry.get_instance("util")
|
|
self.account_service = registry.get_instance("account_service")
|
|
self.buddy_service = registry.get_instance("buddy_service")
|
|
self.alts_controller = registry.get_instance("alts_controller")
|
|
|
|
def pre_start(self):
|
|
self.bot.register_packet_handler(CharacterName.id, self.character_name_update)
|
|
|
|
def start(self):
|
|
self.db.exec("CREATE TABLE IF NOT EXISTS name_history ("
|
|
"char_id INT NOT NULL, "
|
|
"name VARCHAR(20) NOT NULL, "
|
|
"created_at INT NOT NULL, "
|
|
"PRIMARY KEY (char_id, name))")
|
|
self.db.create_view("name_history")
|
|
self.command_alias_service.add_alias("w", "whois")
|
|
self.command_alias_service.add_alias("lookup", "whois")
|
|
self.command_alias_service.add_alias("is", "whois")
|
|
|
|
@command(command="whois",
|
|
params=[Character("character"),
|
|
Int("server_num", is_optional=True),
|
|
Const("forceupdate", is_optional=True)],
|
|
access_level="member",
|
|
description="Get whois information for a character",
|
|
extended_description="Use server_num 6 for RK2019 and server_num 5 for live")
|
|
def whois_cmd(self, request, char, dimension, force_update):
|
|
|
|
dimension = dimension or self.bot.dimension
|
|
|
|
if dimension == self.bot.dimension and char.char_id:
|
|
online_status = self.buddy_service.is_online(char.char_id)
|
|
if online_status is None:
|
|
self.bot.register_packet_handler(BuddyAdded.id, self.handle_buddy_status)
|
|
self.waiting_for_update[char.char_id] = \
|
|
DictObject({"char_id": char.char_id, "name": char.name,
|
|
"callback": partial(self.show_output, char, dimension, force_update, request)})
|
|
self.buddy_service.add_buddy(char.char_id, self.BUDDY_IS_ONLINE_TYPE)
|
|
else:
|
|
self.show_output(char, dimension, force_update, request, online_status)
|
|
else:
|
|
self.show_output(char, dimension, force_update, request, None)
|
|
|
|
def show_output(self, char, dimension, force_update, request: CommandRequest, online_status):
|
|
max_cache_age = 0 if force_update else 86400
|
|
|
|
if dimension != self.bot.dimension:
|
|
char_info = self.pork_service.request_char_info(char.name, dimension)
|
|
else:
|
|
char_info = self.pork_service.get_character_info(char.name, max_cache_age)
|
|
|
|
if char_info and char_info.source != "chat_server":
|
|
blob = "Name: %s (%s)\n" % (self.get_full_name(char_info),
|
|
self.text.make_tellcmd("History",
|
|
f"history {char_info.name} {char_info.dimension}"))
|
|
blob += f"Character Id: {char_info.char_id:d}\n"
|
|
blob += f"Profession: {char_info.profession}\n"
|
|
blob += f"Faction: {self.text.get_formatted_faction(char_info.faction)}\n"
|
|
blob += f"Breed: {char_info.breed}\n"
|
|
blob += f"Gender: {char_info.gender}\n"
|
|
blob += f"Level: {char_info.level:d}\n"
|
|
blob += f"AI Level: <green>{char_info.ai_level:d}</green>\n"
|
|
if char_info.org_id:
|
|
blob += f"Org: <highlight>{char_info.org_name}</highlight> ({char_info.org_id:d})\n"
|
|
blob += f"Org Rank: {char_info.org_rank_name} ({char_info.org_rank_id:d})\n"
|
|
else:
|
|
blob += "Org: <None>\n"
|
|
blob += "Org Rank: <None>\n"
|
|
blob += f"Source: {self.format_source(char_info, max_cache_age)}\n"
|
|
blob += f"Dimension: {char_info.dimension}\n"
|
|
|
|
if dimension == self.bot.dimension:
|
|
blob += f"Status: {'<green>Active</green>' if char.char_id else '<red>Inactive</red>'}\n"
|
|
|
|
blob += self.get_name_history(char.char_id)
|
|
alts = self.account_service.get_alts(char.char_id)
|
|
if len(alts) > 1:
|
|
blob += f"\n<header2>Alts ({len(alts):d})</header2>\n"
|
|
blob += self.alts_controller.format_alt_list(alts)
|
|
|
|
more_info = self.text.paginate_single(ChatBlob("More Info", blob))
|
|
|
|
msg = self.text.format_char_info(char_info, online_status, True) + " " + more_info
|
|
elif char.char_id:
|
|
blob = "<notice>Note: Could not retrieve detailed info for character.</notice>\n\n"
|
|
blob += f"Name: <highlight>{char.name}</highlight>\n"
|
|
blob += f"Character ID: <highlight>{char.char_id:d}</highlight>\n"
|
|
if online_status is not None:
|
|
blob += f"Online status: {'<green>Online</green>' if online_status else '<red>Offline</red>'}\n"
|
|
blob += self.get_name_history(char.char_id)
|
|
msg = ChatBlob(f"Basic Info for {char.name}", blob)
|
|
else:
|
|
msg = f"Could not find character <highlight>{char.name}</highlight> on RK{dimension:d}."
|
|
if request.channel == "msg":
|
|
self.bot.send_mass_message(request.sender.char_id, msg)
|
|
else:
|
|
request.reply(msg)
|
|
|
|
def get_name_history(self, char_id):
|
|
blob = "\n<header2>Name History</header2>\n"
|
|
data = self.db.query("SELECT name, created_at FROM name_history "
|
|
"WHERE char_id = ? ORDER BY created_at DESC",
|
|
[char_id])
|
|
for row in data:
|
|
blob += f"[{self.util.format_date(row.created_at)}] {row.name}\n"
|
|
return blob
|
|
|
|
@timerevent(budatime="1min", description="Save name history", is_hidden=True)
|
|
def save_name_history_event(self, _, _1):
|
|
if not self.name_history:
|
|
return
|
|
|
|
with self.db.pool.get_connection() as conn:
|
|
with conn.cursor() as cur:
|
|
cur.executemany("INSERT IGNORE INTO name_history (char_id, name, created_at) "
|
|
"VALUES (?, ?, ?)",
|
|
self.name_history)
|
|
self.name_history = []
|
|
|
|
def get_full_name(self, char_info):
|
|
name = ""
|
|
if char_info.first_name:
|
|
name += char_info.first_name + " "
|
|
|
|
name += "\"<highlight>" + char_info.name + "</highlight>\""
|
|
|
|
if char_info.last_name:
|
|
name += " " + char_info.last_name
|
|
|
|
return name
|
|
|
|
def format_source(self, char_info, max_cache_age):
|
|
if char_info.cache_age == 0:
|
|
return char_info.source
|
|
elif char_info.cache_age < max_cache_age:
|
|
return f"{char_info.source} (cache; {self.util.time_to_readable(char_info.cache_age)} old)"
|
|
elif char_info.cache_age > max_cache_age:
|
|
return f"{char_info.source} (old cache; {self.util.time_to_readable(char_info.cache_age)} old)"
|
|
|
|
def handle_buddy_status(self, _, packet):
|
|
obj = self.waiting_for_update.get(packet.char_id)
|
|
if obj:
|
|
self.buddy_service.remove_buddy(packet.char_id, self.BUDDY_IS_ONLINE_TYPE)
|
|
del self.waiting_for_update[packet.char_id]
|
|
if not self.waiting_for_update:
|
|
self.bot.remove_packet_handler(BuddyAdded.id, self.handle_buddy_status)
|
|
|
|
obj.callback(packet.online == 1)
|
|
|
|
def character_name_update(self, _, packet):
|
|
self.name_history.append((packet.char_id, packet.name, time.time()))
|