import time from typing import List from core.chat_blob import ChatBlob from core.db import DB from core.dict_object import DictObject from core.text import Text from core.util import Util class OnlineDisplay: def __init__(self, text, util, db, afk_list={}): self.text: Text = text self.util: Util = util self.db: DB = db self.afk_list = afk_list def get_online_players(self, order, group="", params=None): return self.db.query(f"SELECT r.*, " f"CASE WHEN r.rank = 'admin' then 1 " f"WHEN r.rank = 'moderator' then 2 " f"WHEN r.rank = 'council' then 3 " f"WHEN r.rank = 'leader' then 4 " f"else 5 END as r_id, " f"CASE WHEN o.channel = 'org' then 1 " f"WHEN o.channel = ? then 2 " f"WHEN o.channel = 'notify' then 3 " f"else 4 END as channel_id, o.channel, " f"p.*, a.main as main_id, p2.name as main_name, o.bot from online o " f"left join player p on o.char_id = p.char_id " f"left join account a on o.char_id = a.char_id " f"left join player p2 on a.main = p2.char_id " f"left join ranks r on a.main = r.main " f"{group} HAVING bot=? {order}", params) def format_blob(self, online, title="Online Players"): blob, org, priv, notify = online postfix = [] if org > 0: postfix.append(f"Org: {org}") if priv > 0: postfix.append(f"Priv: {priv}") if notify > 0: postfix.append(f"Buddylist: {notify}") blob = ChatBlob(title, blob, suffix=f" ({f', '.join(postfix)})") return blob if (org+priv+notify) != 0 else "There's nobody online." def format_by_channel_main(self, query, params): query += "order by channel_id, main_name, p.name=main_name, p.name, r_id" players = self.get_online_players(query, params=params) channel_id = 0 main_id = 0 blob = "" in_org_priv = [] org, priv, notify = 0, 0, 0 previous = DictObject({'char_id': 0}) for player in players: if player.faction == "": player.faction = "unknown" rank = "" if 'rank' in player: rank = f" [{player.rank[:1].upper()}]" if player.rank else "" if previous.char_id == player.char_id: continue previous = player if player.char_id in in_org_priv: continue if player.channel_id != channel_id: channel_id = player.channel_id blob += f"\n\n.::
{self.get_channel_name(channel_id)}
::.
" main_id = 0 in_org_priv.append(player.char_id) afk = self.afk_list.get(player.char_id, None) if main_id != player.main_id: main_id = player.main_id afk = "" if not afk else f" [{afk.message} - since {self.util.time_to_readable(int(time.time() - afk.time))}]" style = "style='text-decoration:none'" blob += f"\n{self.text.make_tellcmd(player.main_name, f'alts {player.main_name}', style=style)}{rank}:{afk}\n" if channel_id == 1: org += 1 elif channel_id == 2: priv += 1 elif channel_id == 3: notify += 1 if channel_id == 1: blob += self.format_org(player) elif channel_id == 2: blob += self.format_priv(player) elif channel_id == 3: blob += self.format_notify(player) return blob, org, priv, notify def format_by_channel_prof(self, query, params): query += "order by channel_id, profession, level desc, r_id" players = self.get_online_players(query, params=params) channel_id = 0 profession = 0 blob = "" in_org_priv = [] org, priv, notify = 0, 0, 0 previous = DictObject({'char_id': 0}) for player in players: if player.faction == "": player.faction = "unknown" rank = "" if player.char_id in in_org_priv: continue if 'rank' in player: rank = f"[{player.rank[:1].upper()}] " if player.rank else "" if previous.char_id == player.char_id: continue previous = player if player.channel_id != channel_id: channel_id = player.channel_id blob += f"\n\n.::
{self.get_channel_name(channel_id)}
::.
" profession = 0 in_org_priv.append(player.char_id) afk = self.afk_list.get(player.char_id, None) afk = "" if not afk else f" [{afk.message} - since {self.util.time_to_readable(int(time.time() - afk.time))}]" if profession != player.profession: profession = player.profession blob += f"\n{player.profession}:\n" if channel_id == 1: blob += self.format_org(player, rank, afk, main_order=True) org += 1 elif channel_id == 2: blob += self.format_priv(player, rank, afk, main_order=True) priv += 1 elif channel_id == 3: blob += self.format_notify(player, rank, afk, main_order=True) notify += 1 return blob, org, priv, notify def format_by_org(self, query, params): blob = "" query += " and org_id IN (SELECT org_id from orgs) and channel_id = 3 " \ "ORDER BY p.org_name, p.name, p.org_rank_id" query = self.get_online_players(query, params=params) org_id = 0 temp_blob = { } last = 0 for user in query: if user.faction == "": user.faction = "unknown" if last == user.char_id: continue last = user.char_id if user.org_name not in temp_blob: temp_blob[user.org_name] = {"name": user.org_name, "id": user.org_id, "online": []} temp_blob[user.org_name]["online"].extend([user]) for key in sorted(temp_blob): if len(temp_blob[key]['online']) == 0: continue for user in temp_blob[key]['online']: if org_id != temp_blob[key]["id"]: org_id = temp_blob[key]["id"] blob += f"\n{temp_blob[key]['name']}" \ f"
({len(temp_blob[key]['online']): >3} " \ f"| {len(temp_blob[key]['online']) / len(query) * 100:.2f}%)
\n" blob += self.format_org(user) return blob, 0, 0, len(query) def get_channel_name(self, c_id): if c_id == 1: return "Org Channel" elif c_id == 2: return "Private Channel" elif c_id == 3: return "Buddylist" def format_org(self, player, rank="", afk="", main_order=False): main = f"[{self.text.make_tellcmd(player.main_name, f'alts {player.main_name}')}]" if main_order else "" org = f"({player.org_rank_name}) " if player.org_rank_name else "(Applicant)" return f" {self.util.get_prof_icon(player.profession)} {rank}" \ f"{self.text.zfill(player.level, 220)}/{self.text.zfill(player.ai_level, 30)} " \ f"<{player.faction.lower()}>{player.name} {org}{afk} {main}\n" def format_priv(self, player, rank="", afk="", main_order=False): main = f"[{self.text.make_tellcmd(player.main_name, f'alts {player.main_name}')}]" if main_order else "" org = f"({player.org_name}|{player.org_rank_name}) " if player.org_name else "" return f" {self.util.get_prof_icon(player.profession)} {rank}" \ f"{self.text.zfill(player.level, 220)}/{self.text.zfill(player.ai_level, 30)} " \ f"<{player.faction.lower()}>{player.name} " \ f"{org}{afk} {main}\n" def format_notify(self, player, rank="", afk="", main_order=False): main = f"[{self.text.make_tellcmd(player.main_name, f'alts {player.main_name}')}]" if main_order else "" org = f"({player.org_name}|{player.org_rank_name}) " if player.org_name else "" return f" {self.util.get_prof_icon(player.profession)} {rank}" \ f"{self.text.zfill(player.level, 220)}/{self.text.zfill(player.ai_level, 30)} " \ f"<{player.faction.lower()}>{player.name} " \ f"{org}{afk} {main}\n" def count_prof(self, query, params, filters): if filters: filters = self.util.get_profession(filters) params.append(filters) if not filters: return "Unknown profession" query += "and profession = ? ORDER BY p.profession " previous = [] data = [] for x in self.get_online_players(query, params=params): if x.char_id in previous: continue data.append(f"{x.name} [{x.level}/{x.ai_level}]") previous.append(x.char_id) return f"""{filters}'s: {", ".join(data)}""" else: query += "ORDER BY p.profession " data = self.get_online_players(query, params=params) profs = {} previous = [] for user in data: if user.char_id in previous: continue previous.append(user.char_id) if user.profession not in profs: profs[user.profession] = 0 profs[user.profession] += 1 blob = [] for key, value in profs.items(): blob.append(f"[{self.util.get_profession(key, long=False)}: {value}]") return ", ".join(blob) def count_org(self, query, params, search): if search: filters = self.db.query_single("SELECT * from all_orgs where org_id = ? OR org_name = ?", [search, search]) if not filters: return f"Could not find org {search}" params.append(filters.org_id) query += "and p.org_id=? ORDER BY p.profession, p.name, p.level " previous = [] data = [] for x in self.get_online_players(query, params=params): if x.char_id in previous: continue data.append(self.format_org(x)) previous.append(x.char_id) return ChatBlob(f"Online Players ({filters.org_name} - {len(data)})", "".join(data)) else: query += "ORDER BY p.org_name " data = self.get_online_players(query, params=params) orgs = {} count = 0 previous = [] for user in data: if user.char_id in previous: continue previous.append(user.char_id) if user.org_name not in orgs: orgs[user.org_name] = 0 orgs[user.org_name] += 1 count += 1 blob = [] for key, value in orgs.items(): blob.append( f"[{key}: {value} - {value / count * 100:.2f}%] " f"[{self.text.make_tellcmd('Show', f'count org {key}')}]") return ChatBlob(f"Online Organisations ({len(blob)})", "\n ".join(blob)) def count_tl(self, query, params: List, search): if search: min_level, max_level = self.util.get_level_range_tl(search) if min_level == 0 and max_level == 0: return f" Title level out of range: {search}" params.extend([min_level, max_level]) query += "and p.level > ? and p.level < ? ORDER BY p.level desc " previous = [] data = [] for x in self.get_online_players(query, params=params): if x.char_id in previous: continue data.append(self.format_priv(x)) previous.append(x.char_id) return ChatBlob(f"Online Players TL{search} ({len(data)})", "".join(data)) else: query += "ORDER BY p.level " tls = {} previous = [] for user in self.get_online_players(query, params=params): if user.char_id in previous: continue tl = self.util.get_title_level(user.level) if tl not in tls: tls[tl] = 0 tls[tl] += 1 previous.append(user.char_id) blob = [] for key, value in tls.items(): blob.append(f"[TL{key}: {value}]") return ", ".join(blob)