Files
igncore/modules/standard/online/online_controller.py
T
Minidodo d0c8c1744c Fixed bidding, while not being in raid (Nolonger throws an error)
Added default alias !list for !loot (bebot like)
Changed the layout of !notes, its more compact now.
fixed !count in the rare case of an empty private channel
2021-08-15 15:47:06 +02:00

137 lines
6.1 KiB
Python

import time
from threading import Thread
from core.bot_status import BotStatus
from core.buddy_service import BuddyService
from core.command_alias_service import CommandAliasService
from core.command_param_types import Int, Any, Const, Options
from core.db import DB
from core.decorators import instance, event, command
from core.fifo_queue import FifoQueue
from core.logger import Logger
from core.private_channel_service import PrivateChannelService
from core.setting_service import SettingService
from core.text import Text
from core.tyrbot import Tyrbot
from core.util import Util
from modules.standard.online.online_display import OnlineDisplay
class User:
def __init__(self, char_id, loggedin=True):
self.char_id = char_id
self.logged = loggedin
@instance()
class OnlineController:
def __init__(self):
self.assist = []
self.awaiting_data = FifoQueue()
def inject(self, registry):
self.logger = Logger(__name__)
self.bot: Tyrbot = registry.get_instance("bot")
self.db: DB = registry.get_instance("db")
self.text: Text = registry.get_instance("text")
self.util: Util = registry.get_instance("util")
self.command_alias_service: CommandAliasService = registry.get_instance("command_alias_service")
self.buddy_service: BuddyService = registry.get_instance("buddy_service")
self.setting_service: SettingService = registry.get_instance("setting_service")
self.priv: PrivateChannelService = registry.get_instance("private_channel_service")
self.online_display: OnlineDisplay = OnlineDisplay(self.text, self.util, self.db)
def pre_start(self):
self.db.exec("DROP TABLE IF EXISTS online")
self.db.shared.exec(
"CREATE TABLE IF NOT EXISTS online (char_id BIGINT NOT NULL primary key, "
"channel varchar(32) not null default 'notify', "
"bot BIGINT not null, "
"index bot(bot)) ENGINE MEMORY")
self.db.create_view("online")
self.command_alias_service.add_alias("o", "online")
@event(event_type="connect", description="Start online watcher")
def startup(self, _, _1):
self.db.exec("DELETE from online where bot=?", [self.bot.get_char_id()])
self.watchdog = Thread(name="watchdog", target=self.buddy_handler, daemon=True)
self.watchdog.start()
@event(event_type="private_channel_joined", description="Change online channel", is_hidden=True)
def priv_join(self, _, event_data):
self.db.exec("insert ignore into online(channel, char_id, bot) VALUES (?, ?, ?)",
[self.bot.name, event_data.char_id, self.bot.get_char_id()])
@event(event_type="private_channel_left", description="Change online channel", is_hidden=True)
def priv_leave(self, _, event_data):
self.db.exec("delete from online where char_id = ? and bot = ? and channel=?",
[event_data.char_id, self.bot.get_char_id(), self.bot.name])
@event(event_type="member_logon", description="declare players as online")
def logon(self, _, event_data):
self.awaiting_data.put([event_data, 'notify', True])
@event(event_type="member_logoff", description="declare players as offline")
def logoff(self, _, event_data):
if self.bot.is_ready():
self.awaiting_data.put([event_data, 'notify', False])
def buddy_handler(self):
while self.bot.status != BotStatus.SHUTDOWN:
data, channel, logged = self.awaiting_data.get()
buddy = (self.buddy_service.get_buddy(data.packet.char_id) or {}).get("types", [])
if ("org_member" in buddy) or ("member" in buddy):
if logged:
self.db.exec("INSERT IGNORE INTO online VALUES(?, ?, ?)",
[data.packet.char_id, channel, self.bot.get_char_id()])
self.db.exec("UPDATE account set last_seen=? where char_id=?", [time.time(), data.packet.char_id])
else:
self.db.exec("DELETE FROM online where char_id=? and bot=?",
[data.packet.char_id, self.bot.get_char_id()])
self.db.exec("UPDATE account set last_seen=? where char_id=?", [time.time(), data.packet.char_id])
@command(command="online", params=[Const('all', is_optional=True),
Int("min_level", is_optional=True),
Any("profession", is_optional=True)],
description="shows online players",
access_level="member")
def online_all_cmd(self, _, const_all, min_level, profession):
query = ""
params = [self.bot.name, self.bot.get_char_id()]
if const_all:
query += "and channel_id IN (1, 2, 3) "
else:
query += "and channel_id IN (1, 2) "
if min_level:
query += "and p.level >= ? "
params.append(min_level)
if profession:
query += "and p.profession = ? "
params.append(self.util.get_profession(profession))
blob = self.online_display.format_by_channel_main(query, params)
_.reply(self.online_display.format_blob(blob))
@command(command="count",
params=[Options(["org", "prof", "tl"], is_optional=True), Any("filter", is_optional=True)],
description="Counts online players",
access_level="member")
def count(self, _, option, filters):
query = "and channel_id IN (1, 2) "
params = [self.bot.name, self.bot.get_char_id()]
if not option:
option = "prof"
output = ""
if option == "prof":
output = self.online_display.count_prof(query, params, filters)
elif option == "org":
output = self.online_display.count_org(query, params, filters)
elif option == "tl":
if filters:
try:
filters = int(filters)
except ValueError:
return f"Invalid Title level: {filters}"
output = self.online_display.count_tl(query, params, filters)
return output if output != "" else "Nobody is in my private channel, sorry..."