Ejemplo n.º 1
0
class BanController:
    def inject(self, registry):
        self.text = registry.get_instance("text")
        self.util = registry.get_instance("util")
        self.ban_service = registry.get_instance("ban_service")
        self.command_alias_service = registry.get_instance("command_alias_service")

    def start(self):
        self.command_alias_service.add_alias("unban", "ban rem")

    @command(command="ban", params=[Const("list", is_optional=True)], access_level="moderator",
             description="Show the ban list")
    def ban_list_cmd(self, request, _):
        t = int(time.time())
        data = self.ban_service.get_ban_list()
        blob = ""
        for row in data:
            ends = "never" if row.finished_at == -1 else self.util.format_timestamp(row.finished_at)
            time_left = "" if row.finished_at == -1 else " (%s left)" % self.util.time_to_readable(row.finished_at - t)

            blob += "<pagebreak>Name: <highlight>%s<end>\n" % row.name
            blob += "Added: <highlight>%s<end>\n" % self.util.format_timestamp(row.created_at)
            blob += "By: <highlight>%s<end>\n" % row.sender_name
            blob += "Ends: <highlight>%s<end>%s\n" % (ends, time_left)
            blob += "Reason: <highlight>%s<end>\n\n" % row.reason

        return ChatBlob("Ban List (%d)" % len(data), blob)

    @command(command="ban", params=[Options(["rem", "remove"]), Character("character")], access_level="moderator",
             description="Remove a character from the ban list")
    def ban_remove_cmd(self, request, _, char):
        if not char.char_id:
            return "Could not find <highlight>%s<end>." % char.name
        elif not self.ban_service.get_ban(char.char_id):
            return "<highlight>%s<end> is not banned." % char.name
        else:
            self.ban_service.remove_ban(char.char_id)
            return "<highlight>%s<end> has been removed from the ban list." % char.name

    @command(command="ban", params=[Const("add", is_optional=True), Character("character"), Time("duration", is_optional=True), Any("reason", is_optional=True)], access_level="moderator",
             description="Add a character to the ban list")
    def ban_add_cmd(self, request, _, char, duration, reason):
        reason = reason or ""

        if not char.char_id:
            return "Could not find <highlight>%s<end>." % char.name
        elif self.ban_service.get_ban(char.char_id):
            return "<highlight>%s<end> is already banned." % char.name
        else:
            self.ban_service.add_ban(char.char_id, request.sender.char_id, duration, reason)
            return "<highlight>%s<end> has been added to the ban list." % char.name
Ejemplo n.º 2
0
class RunasController:
    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.command_service = registry.get_instance("command_service")
        self.setting_service = registry.get_instance("setting_service")
        self.access_service = registry.get_instance("access_service")
        self.getresp = registry.get_instance(
            "translation_service").get_response

    @command(command="runas",
             params=[Character("character"),
                     Any("command")],
             access_level="superadmin",
             description="Run a command as another character")
    def shutdown_cmd(self, request, char, command_str):
        if command_str[0] == self.setting_service.get("symbol").get_value():
            command_str = command_str[1:]

        if not char.char_id:
            return self.getresp("global", "char_not_found",
                                {"char": char.name})
        elif not self.access_service.has_sufficient_access_level(
                request.sender.char_id, char.char_id):
            return self.getresp("module/system", "runas_fail",
                                {"char": char.name})
        else:
            self.command_service.process_command(command_str, request.channel,
                                                 char.char_id, request.reply)
Ejemplo n.º 3
0
    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.command_alias_service.add_alias("w", "whois")
        self.command_alias_service.add_alias("lookup", "whois")

        self.discord_controller.register_discord_command_handler(
            self.whois_discord_cmd, "whois", [Character("character")])
Ejemplo n.º 4
0
class LastSeenController:
    def __init__(self):
        self.logger = Logger(__name__)

    def inject(self, registry):
        self.db = registry.get_instance("db")
        self.util = registry.get_instance("util")

    def start(self):
        self.db.exec(
            "CREATE TABLE IF NOT EXISTS last_seen (char_id INT NOT NULL PRIMARY KEY, "
            "dt INT NOT NULL DEFAULT 0)")

    @command(
        command="lastseen",
        params=[Character("character")],
        access_level="org_member",
        description="Show the last time an org member was online (on any alt)")
    def lastseen_cmd(self, request, char):
        sql = "SELECT p.*, a.group_id, a.status, l.dt FROM player p " \
              "LEFT JOIN alts a ON p.char_id = a.char_id " \
              "LEFT JOIN last_seen l ON p.char_id = l.char_id " \
              "WHERE p.char_id = ? OR a.group_id = (SELECT group_id FROM alts WHERE char_id = ?) " \
              "ORDER BY a.status DESC, p.level DESC, p.name ASC"

        data = self.db.query(sql, [char.char_id, char.char_id])
        blob = ""
        if len(data) == 0:
            blob += f"Note: <highlight>{char.name}</highlight> must be on the buddylist in order for <highlight>lastseen</highlight> data to be recorded."
        else:
            for row in data:
                blob += f"<highlight>{row.name}</highlight>"
                if row.dt:
                    blob += " last seen at " + self.util.format_datetime(
                        row.dt)
                else:
                    blob += " unknown"
                blob += "\n\n"

        return ChatBlob("Last Seen for %s (%d)" % (char.name, len(data)), blob)

    @event(event_type=BuddyService.BUDDY_LOGON_EVENT,
           description="Record last seen info")
    def handle_buddy_logon_event(self, event_type, event_data):
        self.update_last_seen(event_data.char_id)

    def update_last_seen(self, char_id):
        t = int(time.time())
        if self.db.exec("UPDATE last_seen SET dt = ? WHERE char_id = ?",
                        [t, char_id]) == 0:
            self.db.exec(
                "INSERT IGNORE INTO last_seen (char_id, dt) VALUES (?, ?)",
                [char_id, t])

    def get_last_seen(self, char_id):
        return self.db.query_single(
            "SELECT dt FROM last_seen WHERE char_id = ?", [char_id])
Ejemplo n.º 5
0
    def start(self):
        self.db.exec(
            "CREATE TABLE IF NOT EXISTS discord_char_link (discord_id BIGINT NOT NULL, char_id INT NOT NULL)"
        )

        self.message_hub_service.register_message_destination(
            self.MESSAGE_SOURCE, self.handle_incoming_relay_message, [
                "private_channel", "org_channel", "websocket_relay",
                "tell_relay", "shutdown_notice"
            ], [self.MESSAGE_SOURCE])

        self.register_discord_command_handler(
            self.discord_link_cmd, "discord",
            [Const("link"), Character("ao_character")])
        self.register_discord_command_handler(self.discord_unlink_cmd,
                                              "discord", [Const("unlink")])

        self.ts.register_translation("module/discord", self.load_discord_msg)

        self.setting_service.register(self.module_name, "discord_enabled",
                                      False, BooleanSettingType(),
                                      "Enable the Discord relay")
        self.setting_service.register(self.module_name, "discord_bot_token",
                                      "", HiddenSettingType(allow_empty=True),
                                      "Discord bot token")
        self.setting_service.register(
            self.module_name, "discord_channel_id", "",
            TextSettingType(allow_empty=True),
            "Discord channel id for relaying messages to and from",
            "You can get the Discord channel ID by right-clicking on a channel name in Discord and then clicking \"Copy ID\""
        )
        self.setting_service.register(self.module_name, "discord_embed_color",
                                      "#00FF00", ColorSettingType(),
                                      "Discord embedded message color")
        self.setting_service.register(
            self.module_name, "relay_color_prefix", "#FCA712",
            ColorSettingType(),
            "Set the prefix color for messages coming from Discord")
        self.setting_service.register(
            self.module_name, "relay_color_name", "#808080",
            ColorSettingType(),
            "Set the color of the name for messages coming from Discord")
        self.setting_service.register(
            self.module_name, "relay_color_message", "#00DE42",
            ColorSettingType(),
            "Set the color of the content for messages coming from Discord")

        self.setting_service.register_change_listener(
            "discord_channel_id", self.update_discord_channel)
        self.setting_service.register_change_listener(
            "discord_enabled", self.update_discord_state)
Ejemplo n.º 6
0
class SendMessageController:
    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.command_service = registry.get_instance("command_service")
        self.getresp = registry.get_instance("translation_service").get_response

    @command(command="sendtell", params=[Character("character"), Any("message")], access_level="superadmin",
             description="Send a tell to another character from the bot")
    def sendtell_cmd(self, request, char, message):
        if char.char_id:
            self.bot.send_private_message(char.char_id, message, add_color=False, conn=request.conn)
            return self.getresp("module/system", "msg_sent")
        else:
            return self.getresp("global", "char_not_found", {"char": char.name})
Ejemplo n.º 7
0
class CharacterHistoryController:
    def __init__(self):
        pass

    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.util = registry.get_instance("util")
        self.character_history_service = registry.get_instance(
            "character_history_service")
        self.command_alias_service = registry.get_instance(
            "command_alias_service")

    def start(self):
        self.command_alias_service.add_alias("h", "history")

    @command(
        command="history",
        params=[Character("character"),
                Int("server_num", is_optional=True)],
        access_level="all",
        description="Get history of character")
    def handle_history_cmd1(self, request, char, server_num):
        server_num = server_num or self.bot.dimension

        data = self.character_history_service.get_character_history(
            char.name, server_num)
        if not data:
            return "Could not find history for <highlight>%s<end> on server <highlight>%d<end>." % (
                char.name, server_num)

        return ChatBlob("History of %s (RK%d)" % (char.name, server_num),
                        self.format_character_history(char.name, data))

    def format_character_history(self, name, history):
        blob = "Date           Level    AI     Faction    Breed        Guild (rank)\n"
        blob += "________________________________________________ \n"
        for row in history:
            if row.guild_name:
                org = "%s (%s)" % (row.guild_name, row.guild_rank_name)
            else:
                org = ""

            last_changed = self.util.format_date(int(float(row.last_changed)))

            blob += "%s |  %s  | <green>%s<end> | %s | %s | %s\n" % \
                    (last_changed, row.level, row.defender_rank or 0, row.faction, row.breed, org)

        blob += "\nHistory provided by Auno.org, Chrisax, and Athen Paladins"

        return blob
Ejemplo n.º 8
0
class LastSeenController:
    def __init__(self):
        self.logger = Logger(__name__)

    def inject(self, registry):
        self.db = registry.get_instance("db")
        self.util = registry.get_instance("util")
        self.character_service = registry.get_instance("character_service")
        self.public_channel_service = registry.get_instance(
            "public_channel_service")

    @command(
        command="lastseen",
        params=[Character("character")],
        access_level="admin",
        description="Show the last time an org member was online (on any alt)")
    def lastseen_cmd(self, request, char):
        if not self.public_channel_service.get_org_id:
            return "Error! Bot must be in an org in order to use this command."

        sql = """
            SELECT
                p.*,
                o.last_seen
            FROM
                player p
                LEFT JOIN alts a ON p.char_id = a.char_id
                JOIN org_member o ON p.char_id = o.char_id
            WHERE
                o.last_seen != 0 AND (
                    p.char_id = ?
                    OR a.group_id = (SELECT group_id FROM alts WHERE char_id = ?)
                )
            ORDER BY
                o.last_seen DESC,
                p.name ASC,
                p.level DESC
        """

        data = self.db.query(sql, [char.char_id, char.char_id])
        blob = ""
        if len(data) == 0:
            blob += "Note: <highlight>%s<end> must be in the same organization as the bot in order to track <highlight>lastseen<end> data." % char.name

        for row in data:
            blob += "<highlight>%s<end> last seen at %s\n" % (
                row.name, self.util.format_datetime(row.last_seen))

        return ChatBlob("Last Seen for %s (%d)" % (char.name, len(data)), blob)
Ejemplo n.º 9
0
class IsOnlineController:
    BUDDY_IS_ONLINE_TYPE = "is"

    def __init__(self):
        self.waiting_for_update = {}

    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.buddy_service = registry.get_instance("buddy_service")

    @command(command="is",
             params=[Character("character")],
             access_level="all",
             description="Show online status for a character")
    def is_cmd(self, request, char):
        if not char.char_id:
            return "Could not find <highlight>%s<end>." % char.name
        else:
            online_status = self.buddy_service.is_online(char.char_id)
            if online_status is None:
                self.bot.add_packet_handler(BuddyAdded.id,
                                            self.handle_buddy_status)
                self.waiting_for_update[char.char_id] = DictObject({
                    "char_id":
                    char.char_id,
                    "name":
                    char.name,
                    "reply":
                    request.reply
                })
                self.buddy_service.add_buddy(char.char_id,
                                             self.BUDDY_IS_ONLINE_TYPE)
            else:
                return self.format_message(char.name, online_status)

    def handle_buddy_status(self, packet):
        char = self.waiting_for_update.get(packet.char_id)
        if char:
            char.reply(self.format_message(char.name, packet.online))
            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)

    def format_message(self, char_name, online_status):
        return "%s is %s." % (char_name, "<green>online<end>"
                              if online_status else "<red>offline<end>")
Ejemplo n.º 10
0
class SendMessageController:
    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.command_service = registry.get_instance("command_service")

    @command(command="sendtell",
             params=[Character("character"),
                     Any("message")],
             access_level="superadmin",
             description="Send a tell to another character from the bot")
    def sendtell_cmd(self, request, char, message):
        if char.char_id:
            self.bot.send_private_message(char.char_id, message)
            return "Your message has been sent."
        else:
            return "Could not find character <highlight>%s<end>." % char.name
class LeaderController:
    def __init__(self):
        self.leader = None

    def inject(self, registry):
        self.db: DB = registry.get_instance("db")
        self.text: Text = registry.get_instance("text")
        self.access_service = registry.get_instance("access_service")
        self.character_service = registry.get_instance("character_service")

    @command(command="leader", params=[], access_level="all",
             description="Show the current raidleader")
    def leader_show_command(self, request):
        if self.leader:
            return "The current raidleader is <highlight>%s<end>." % self.character_service.resolve_char_to_name(self.leader)
        else:
            return "There is no current raidleader."

    @command(command="leader", params=[Const("set")], access_level="all",
             description="Set yourself as raidleader")
    def leader_set_self_command(self, request, _):
        if self.leader == request.sender.char_id:
            self.leader = None
            return "You have been removed as raidleader."
        elif not self.leader:
            self.leader = request.sender.char_id
            return "You have been set as raidleader."
        elif self.access_service.has_sufficient_access_level(request.sender.char_id, self.leader):
            self.leader = request.sender.char_id
            return "You have taken leader from <highlight>%s<end>." % self.character_service.resolve_char_to_name(self.leader)
        else:
            return "You do not have a high enough access level to take raidleader from <highlight>%s<end>." % self.character_service.resolve_char_to_name(self.leader)

    @command(command="leader", params=[Const("set", is_optional=True), Character("character")], access_level="all",
             description="Set another character as raidleader")
    def leader_set_other_command(self, request, _, char):
        if not char.char_id:
            return "Could not find <highlight>%s<end>." % char.name

        if not self.leader or self.access_service.has_sufficient_access_level(request.sender.char_id, self.leader):
            self.leader = char.char_id
            return "<highlight>%s<end> has been set as raidleader." % char.name
        else:
            return "You do not have a high enough access level to take raidleader from <highlight>%s<end>." % self.character_service.resolve_char_to_name(self.leader)
Ejemplo n.º 12
0
class SendMessageController:
    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.command_service = registry.get_instance("command_service")
        self.getresp = registry.get_instance(
            "translation_service").get_response

    @command(command="send",
             params=[Const("tell"),
                     Character("character"),
                     Any("message")],
             access_level="superadmin",
             description="Send a message to a character from the bot")
    def send_tell_cmd(self, request, _, char, message):
        if char.char_id:
            self.bot.send_private_message(char.char_id,
                                          message,
                                          add_color=False,
                                          conn=request.conn)
            return self.getresp("module/system", "msg_sent")
        else:
            return self.getresp("global", "char_not_found",
                                {"char": char.name})

    @command(command="send",
             params=[Const("org"), Any("message")],
             access_level="superadmin",
             description="Send a message to the org channel from the bot")
    def send_org_cmd(self, request, _, message):
        for _id, conn in self.bot.get_conns(lambda x: x.is_main):
            self.bot.send_org_message(message, add_color=False, conn=conn)
        return self.getresp("module/system", "msg_sent")

    @command(command="send",
             params=[Const("priv"), Any("message")],
             access_level="superadmin",
             description="Send a message to the private channel from the bot")
    def send_priv_cmd(self, request, _, message):
        self.bot.send_private_channel_message(message,
                                              add_color=False,
                                              conn=self.bot.get_primary_conn())
        return self.getresp("module/system", "msg_sent")
class RunasController:
    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.command_service = registry.get_instance("command_service")
        self.setting_service = registry.get_instance("setting_service")

    @command(command="runas",
             params=[Character("character"),
                     Any("command")],
             access_level="superadmin",
             description="Run a command as another character")
    def shutdown_cmd(self, request, char, command_str):
        if command_str[0] == self.setting_service.get("symbol").get_value():
            command_str = command_str[1:]

        if not char.char_id:
            return "Could not find character <highlight>%s<end>" % char.name
        else:
            self.command_service.process_command(command_str, request.channel,
                                                 char.char_id, request.reply)
Ejemplo n.º 14
0
class RunasController:
    def inject(self, registry):
        self.command_service = registry.get_instance("command_service")
        self.access_service = registry.get_instance("access_service")

    @command(command="runas",
             params=[Character("character"),
                     Any("command")],
             access_level="superadmin",
             description="Run a command as another character")
    def runas_cmd(self, request, char, command_str):
        if not char.char_id:
            return StandardMessage.char_not_found(char.name)
        elif not self.access_service.has_sufficient_access_level(
                request.sender.char_id, char.char_id):
            return f"Error! You must have a higher access level than <highlight>{char.name}</highlight>."
        else:
            command_str = self.command_service.trim_command_symbol(command_str)
            self.command_service.process_command(command_str, request.channel,
                                                 char.char_id, request.reply,
                                                 request.conn)
Ejemplo n.º 15
0
class CharacterHistoryController:
    def __init__(self):
        pass

    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.text = registry.get_instance("text")
        self.util = registry.get_instance("util")
        self.character_history_service = registry.get_instance(
            "character_history_service")
        self.command_alias_service = registry.get_instance(
            "command_alias_service")

    def start(self):
        self.command_alias_service.add_alias("h", "history")

    @command(
        command="history",
        params=[Character("character"),
                Int("server_num", is_optional=True)],
        access_level="guest",
        description="Get history of character",
        extended_description=
        "Use server_num 6 for RK2019 and server_num 5 for live")
    def handle_history_cmd1(self, request, char, server_num):
        server_num = server_num or self.bot.dimension

        data = self.character_history_service.get_character_history(
            char.name, server_num)
        if not data:
            return "Could not find history for <highlight>%s</highlight> on server <highlight>%d</highlight>." % (
                char.name, server_num)

        return ChatBlob(
            "History of %s (RK%d)" % (char.name, server_num),
            self.format_character_history(char.name, server_num, data))

    def format_character_history(self, name, server_num, history):
        col_separator = " | "

        rows = [[
            "Name", "Date", "Lvl", "AI", "Side", "Breed", "CharId",
            "Org (Rank)"
        ]]
        uniques = set()
        for row in history:
            if row.nickname and row.nickname != name:
                uniques.add(row.nickname)
            if row.char_id and row.char_id != name:
                uniques.add(row.char_id)

            if row.guild_name:
                org = "%s (%s)" % (row.guild_name, row.guild_rank_name)
            else:
                org = ""

            last_changed = self.util.format_date(int(float(row.last_changed)))
            current_row = [row.nickname, last_changed]

            if row.deleted == "1":  # This value is output as string
                current_row.append("<red>DELETED</red>")
            else:
                current_row.extend([
                    row.level,
                    "<green>%s</green>" % (row.defender_rank or "0"),
                    row.faction, row.breed, row.char_id, org
                ])

            rows.append(current_row)

        rows = self.text.pad_table(rows)
        blob = "  ".join(
            map(
                lambda x: "[" + self.text.make_tellcmd(
                    f"History {x}", f"history {x} {server_num}") + "]",
                uniques)) + "\n\n"

        blob += col_separator.join(rows[0]) + "\n"
        blob += "__________________________________________________________\n"
        for columns in rows[1:]:
            blob += col_separator.join(columns) + "\n"

        blob += "\nHistory provided by Auno.org, Chrisax, and Athen Paladins"
        return blob
Ejemplo n.º 16
0
class MemberController:
    MEMBER_BUDDY_TYPE = "member"

    MEMBER_LOGON_EVENT = "member_logon_event"
    MEMBER_LOGOFF_EVENT = "member_logoff_event"

    def inject(self, registry):
        self.db = registry.get_instance("db")
        self.private_channel_service = registry.get_instance("private_channel_service")
        self.buddy_service = registry.get_instance("buddy_service")
        self.bot = registry.get_instance("bot")
        self.access_service = registry.get_instance("access_service")
        self.command_alias_service = registry.get_instance("command_alias_service")
        self.event_service = registry.get_instance("event_service")

    def pre_start(self):
        self.access_service.register_access_level("member", 90, self.check_member)
        self.event_service.register_event_type(self.MEMBER_LOGON_EVENT)
        self.event_service.register_event_type(self.MEMBER_LOGOFF_EVENT)
        self.bot.add_packet_handler(BuddyAdded.id, self.handle_member_logon)

    def start(self):
        self.db.exec("CREATE TABLE IF NOT EXISTS members (char_id INT NOT NULL PRIMARY KEY, auto_invite INT DEFAULT 0);")
        self.command_alias_service.add_alias("adduser", "member add")
        self.command_alias_service.add_alias("remuser", "member rem")
        self.command_alias_service.add_alias("members", "member")

    @event(event_type="connect", description="Add members as buddies of the bot on startup")
    def handle_connect_event(self, event_type, event_data):
        for row in self.get_all_members():
            if row.auto_invite == 1:
                self.buddy_service.add_buddy(row.char_id, self.MEMBER_BUDDY_TYPE)

    @command(command="member", params=[Const("add"), Character("character")], access_level=OrgMemberController.ORG_ACCESS_LEVEL,
             description="Add a member")
    def member_add_cmd(self, request, _, char):
        if char.char_id:
            if self.get_member(char.char_id):
                return "<highlight>%s<end> is already a member." % char.name
            else:
                self.add_member(char.char_id)
                return "<highlight>%s<end> has been added as a member." % char.name
        else:
            return "Could not find character <highlight>%s<end>." % char.name

    @command(command="member", params=[Options(["rem", "remove"]), Character("character")], access_level=OrgMemberController.ORG_ACCESS_LEVEL,
             description="Remove a member")
    def member_remove_cmd(self, request, _, char):
        if char.char_id:
            if self.get_member(char.char_id):
                self.remove_member(char.char_id)
                return "<highlight>%s<end> has been removed as a member." % char.name
            else:
                return "<highlight>%s<end> is not a member." % char.name
        else:
            return "Could not find character <highlight>%s<end>." % char.name

    @command(command="member", params=[Const("list", is_optional=True)], access_level=OrgMemberController.ORG_ACCESS_LEVEL,
             description="List members")
    def member_list_cmd(self, request, _):
        data = self.get_all_members()
        count = len(data)
        blob = ""
        for row in data:
            blob += str(row.name) + "\n"
        return ChatBlob("Members (%d)" % count, blob)

    @command(command="autoinvite", params=[Options(["on", "off"])], access_level="all",
             description="Set your auto invite preference")
    def autoinvite_cmd(self, request, pref):
        pref = pref.lower()
        member = self.get_member(request.sender.char_id)
        if member:
            self.update_auto_invite(request.sender.char_id, 1 if pref == "on" else 0)
            return "Your auto invite preference has been set to <highlight>%s<end>." % pref
        else:
            return "You must be a member of this bot to set your auto invite preference."

    @event(event_type=MEMBER_LOGON_EVENT, description="Auto invite members to the private channel when they logon")
    def handle_buddy_logon(self, event_type, event_data):
        if event_data.auto_invite == 1:
            self.bot.send_private_message(event_data.char_id, "You have been auto-invited to the private channel.")
            self.private_channel_service.invite(event_data.char_id)

    @event(event_type=BanService.BAN_ADDED_EVENT, description="Remove characters as members when they are banned")
    def ban_added_event(self, event_type, event_data):
        self.remove_member(event_data.char_id)

    def handle_member_logon(self, packet: BuddyAdded):
        member = self.get_member(packet.char_id)
        if member:
            if packet.online:
                self.event_service.fire_event(self.MEMBER_LOGON_EVENT, member)
            else:
                self.event_service.fire_event(self.MEMBER_LOGOFF_EVENT, member)

    def add_member(self, char_id, auto_invite=1):
        self.buddy_service.add_buddy(char_id, self.MEMBER_BUDDY_TYPE)
        if not self.get_member(char_id):
            self.db.exec("INSERT INTO members (char_id, auto_invite) VALUES (?, ?)", [char_id, auto_invite])

    def remove_member(self, char_id):
        self.buddy_service.remove_buddy(char_id, self.MEMBER_BUDDY_TYPE)
        self.db.exec("DELETE FROM members WHERE char_id = ?", [char_id])

    def update_auto_invite(self, char_id, auto_invite):
        self.db.exec("UPDATE members SET auto_invite = ? WHERE char_id = ?", [auto_invite, char_id])

    def get_member(self, char_id):
        return self.db.query_single("SELECT char_id, auto_invite FROM members WHERE char_id = ?", [char_id])

    def get_all_members(self):
        return self.db.query("SELECT COALESCE(p.name, m.char_id) AS name, m.char_id, m.auto_invite FROM members m LEFT JOIN player p ON m.char_id = p.char_id ORDER BY p.name ASC")

    def check_member(self, char_id):
        return self.get_member(char_id) is not None
Ejemplo n.º 17
0
class AdminController:
    def __init__(self):
        pass

    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.admin_service = registry.get_instance("admin_service")
        self.pork_service = registry.get_instance("pork_service")
        self.command_alias_service = registry.get_instance(
            "command_alias_service")
        self.buddy_service = registry.get_instance("buddy_service")

    def start(self):
        self.command_alias_service.add_alias("adminlist", "admin")
        self.command_alias_service.add_alias("admins", "admin")

    @command(command="admin",
             params=[],
             access_level="all",
             description="Show the admin list")
    def admin_list_cmd(self, request):
        admins = self.admin_service.get_all()

        blob = ""
        current_access_level = ""
        for row in admins:
            if row.access_level != current_access_level:
                blob += "\n<header2>%s<end>\n" % row.access_level.capitalize()
                current_access_level = row.access_level

            blob += row.name
            if self.buddy_service.is_online(row.char_id):
                blob += " [<green>Online<end>]"
            blob += "\n"

        return ChatBlob("Admin List (%d)" % len(admins), blob)

    @command(command="admin",
             params=[Const("add"), Character("character")],
             access_level="superadmin",
             description="Add an admin",
             sub_command="modify")
    def admin_add_cmd(self, request, _, char):
        if not char.char_id:
            return "Could not find character <highlight>%s<end>." % char.name

        if self.admin_service.add(char.char_id, AdminService.ADMIN):
            return "Character <highlight>%s<end> added as <highlight>%s<end> successfully." % (
                char.name, AdminService.ADMIN)
        else:
            return "Could not add character <highlight>%s<end> as <highlight>%s<end>." % (
                char.name, AdminService.ADMIN)

    @command(command="admin",
             params=[Options(["remove", "rem"]),
                     Character("character")],
             access_level="superadmin",
             description="Remove an admin",
             sub_command="modify")
    def admin_remove_cmd(self, request, _, char):
        if not char.char_id:
            return "Could not find character <highlight>%s<end>." % char.name

        if self.admin_service.remove(char.char_id):
            return "Character <highlight>%s<end> removed as <highlight>%s<end> successfully." % (
                char.name, AdminService.ADMIN)
        else:
            return "Could not remove character <highlight>%s<end> as <highlight>%s<end>." % (
                char.name, AdminService.ADMIN)

    @command(command="moderator",
             params=[Const("add"), Character("character")],
             access_level="admin",
             description="Add a moderator",
             sub_command="modify")
    def moderator_add_cmd(self, request, _, char):
        if not char.char_id:
            return "Could not find character <highlight>%s<end>." % char.name

        if self.admin_service.add(char.char_id, AdminService.MODERATOR):
            return "Character <highlight>%s<end> added as <highlight>%s<end> successfully." % (
                char.name, AdminService.MODERATOR)
        else:
            return "Could not add character <highlight>%s<end> as <highlight>%s<end>." % (
                char.name, AdminService.MODERATOR)

    @command(command="moderator",
             params=[Options(["remove", "rem"]),
                     Character("character")],
             access_level="admin",
             description="Remove a moderator",
             sub_command="modify")
    def moderator_remove_cmd(self, request, _, char):
        if not char.char_id:
            return "Could not find character <highlight>%s<end>." % char.name

        if self.admin_service.remove(char.char_id):
            return "Character <highlight>%s<end> removed as <highlight>%s<end> successfully." % (
                char.name, AdminService.MODERATOR)
        else:
            return "Could not remove character <highlight>%s<end> as <highlight>%s<end>." % (
                char.name, AdminService.MODERATOR)
Ejemplo n.º 18
0
class AdminController:
    def __init__(self):
        pass

    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.admin_service = registry.get_instance("admin_service")
        self.pork_service = registry.get_instance("pork_service")
        self.command_alias_service = registry.get_instance(
            "command_alias_service")
        self.buddy_service = registry.get_instance("buddy_service")

    def start(self):
        self.command_alias_service.add_alias("adminlist", "admin")
        self.command_alias_service.add_alias("admins", "admin")

    @command(command="admin",
             params=[],
             access_level="all",
             description="Show the admin list")
    def admin_list_cmd(self, request):
        admins = self.admin_service.get_all()

        blob = ""
        current_access_level = ""
        for row in admins:
            if row.access_level != current_access_level:
                blob += "\n<header2>%s</header2>\n" % row.access_level.capitalize(
                )
                current_access_level = row.access_level

            if row.name:
                blob += row.name
            else:
                blob += "Unknown(%d)" % row.char_id

            if self.buddy_service.is_online(row.char_id):
                blob += " [<green>Online</green>]"
            blob += "\n"

        return ChatBlob("Admin List (%d)" % len(admins), blob)

    @command(command="admin",
             params=[Const("add"), Character("character")],
             access_level="superadmin",
             description="Add an admin",
             sub_command="modify")
    def admin_add_cmd(self, request, _, char):
        if not char.char_id:
            return StandardMessage.char_not_found(char.name)

        if self.admin_service.add(char.char_id, AdminService.ADMIN):
            return f"Character <highlight>{char.name}</highlight> added as <highlight>{AdminService.ADMIN}</highlight> successfully."
        else:
            return f"Could not add character <highlight>{char.name}</highlight> as <highlight>{AdminService.ADMIN}</highlight>."

    @command(command="admin",
             params=[Options(["remove", "rem"]),
                     Character("character")],
             access_level="superadmin",
             description="Remove an admin",
             sub_command="modify")
    def admin_remove_cmd(self, request, _, char):
        if not char.char_id:
            return StandardMessage.char_not_found(char.name)

        if self.admin_service.remove(char.char_id):
            return f"Character <highlight>{char.name}</highlight> removed as <highlight>{AdminService.ADMIN}</highlight> successfully."
        else:
            return f"Could not remove character <highlight>{char.name}</highlight> as <highlight>{AdminService.ADMIN}</highlight>."

    @command(command="moderator",
             params=[Const("add"), Character("character")],
             access_level="admin",
             description="Add a moderator",
             sub_command="modify")
    def moderator_add_cmd(self, request, _, char):
        if not char.char_id:
            return StandardMessage.char_not_found(char.name)

        if self.admin_service.add(char.char_id, AdminService.MODERATOR):
            return f"Character <highlight>{char.name}</highlight> added as <highlight>{AdminService.MODERATOR}</highlight> successfully."
        else:
            return f"Could not add character <highlight>{char.name}</highlight> as <highlight>{AdminService.MODERATOR}</highlight>."

    @command(command="moderator",
             params=[Options(["remove", "rem"]),
                     Character("character")],
             access_level="admin",
             description="Remove a moderator",
             sub_command="modify")
    def moderator_remove_cmd(self, request, _, char):
        if not char.char_id:
            return StandardMessage.char_not_found(char.name)

        if self.admin_service.remove(char.char_id):
            return f"Character <highlight>{char.name}</highlight> removed as <highlight>{AdminService.MODERATOR}</highlight> successfully."
        else:
            return f"Could not remove character <highlight>{char.name}</highlight> as <highlight>{AdminService.MODERATOR}</highlight>."

    @event(event_type="connect",
           description="Add admins as buddies",
           is_system=True)
    def connect_event(self, event_type, event_data):
        for row in self.admin_service.get_all():
            self.buddy_service.add_buddy(row.char_id, "admin")
Ejemplo n.º 19
0
class PointsController:
    def __init__(self):
        pass

    def inject(self, registry):
        self.bot: Tyrbot = registry.get_instance("bot")
        self.db: DB = registry.get_instance("db")
        self.text: Text = registry.get_instance("text")
        self.character_service: CharacterService = registry.get_instance(
            "character_service")
        self.util: Util = registry.get_instance("util")
        self.setting_service: SettingService = registry.get_instance(
            "setting_service")
        self.alts_service: AltsService = registry.get_instance("alts_service")

    def start(self):
        if self.db.query_single(
                "SELECT COUNT(*) AS count FROM points_presets").count < 1:
            # Populate with pre-made presets if empty
            presets = [
                "s13", "s28", "s35", "s42", "zodiac", "zod", "tnh", "beast",
                "12m", "tara", "pvp", "towers", "wipe", "clanwipe", "clan",
                "omniwipe", "omni", "bonus", "early"
            ]
            sql = "INSERT INTO points_presets (name) VALUES (?)"
            for preset in presets:
                self.db.exec(sql, [preset])

    @setting(name="initial_points_value",
             value="0",
             description="How many points new accounts start with")
    def initial_points_value(self):
        return NumberSettingType()

    @command(command="account",
             params=[Const("create"), Character("char")],
             access_level="moderator",
             description="Create a new account for given character name",
             sub_command="modify")
    def bank_create_cmd(self, request, _, char: SenderObj):
        alts_info = self.alts_service.get_alts(char.char_id)

        for alt in alts_info:
            sql = "SELECT char_id, disabled FROM points WHERE char_id = ? LIMIT 1"
            count = self.db.query_single(sql, [alt.char_id])

            if count:
                was_disabled = False

                if count.disabled == 1:
                    if self.db.exec(
                            "UPDATE points SET disabled = 0 WHERE char_id = ?",
                        [alt.char_id]):
                        was_disabled = True

                if alt.char_id == char.char_id:
                    if was_disabled:
                        if self.add_log_entry(
                                alt.char_id, request.sender.char_id,
                                "Account was re-enabled by %s" %
                                self.character_service.resolve_char_to_name(
                                    request.sender.char_id)):
                            return "<highlight>%s<end>'s account has been re-enabled." % char.name
                        else:
                            return "<highlight>%s<end> has an account, but failed to re-enable it." % char.name
                    else:
                        return "<highlight>%s<end> already has an account." % char.name
                else:
                    if was_disabled:
                        if self.add_log_entry(
                                alt.char_id, request.sender.char_id,
                                "Account was re-enabled by %s" %
                                self.character_service.resolve_char_to_name(
                                    request.sender.char_id)):
                            return "<highlight>%s<end>'s (%s) account has been re-enabled." % (
                                char.name,
                                self.character_service.resolve_char_to_name(
                                    alt.char_id))
                        else:
                            return "<highlight>%s<end> (%s) has an account, but failed to re-enable it." % (
                                char.name,
                                self.character_service.resolve_char_to_name(
                                    alt.char_id))
                    else:
                        return "<highlight>%s<end> (%s) already has an account." % (
                            char.name,
                            self.character_service.resolve_char_to_name(
                                alt.char_id))

        main_info = alts_info.pop(0)
        changed_to_main = main_info.char_id == char.char_id

        initial_points = self.setting_service.get(
            "initial_points_value").get_value()

        sql = "INSERT INTO points (char_id, points, created) VALUES (?,?,?)"
        if self.db.exec(sql,
                        [main_info.char_id, initial_points,
                         int(time.time())]) < 1:
            return "Failed to create an account for <highlight>%s<end>." % char.name

        if not self.add_log_entry(
                main_info.char_id, request.sender.char_id,
                "Account opened by %s" % request.sender.name):
            sql = "DELETE FROM points WHERE char_id = ?"
            self.db.exec(sql, [main_info.char_id])
            return "Failed to create an account for <highlight>%s<end>." % char.name

        name_reference = "%s (%s)" % (
            char.name,
            self.character_service.resolve_char_to_name(
                main_info.char_id)) if changed_to_main else char.name
        return "A new account has been created for <highlight>%s<end>." % name_reference

    @command(command="account",
             params=[Const("close"), Character("char")],
             access_level="moderator",
             description="Close the account for given character name",
             sub_command="modify")
    def close_account_cmd(self, request, _, char: SenderObj):
        main_id = self.alts_service.get_main(char.char_id)

        sql = "UPDATE points SET disabled = 1 WHERE char_id = ?"
        if self.db.exec(sql, [main_id.char_id]) > 0:
            reason = "Account was closed by %s" % self.character_service.resolve_char_to_name(
                request.sender.char_id)
            if self.add_log_entry(main_id.char_id, request.sender.char_id,
                                  reason):
                name_reference = "%s (%s)" % (
                    char.name,
                    self.character_service.resolve_char_to_name(
                        main_id.char_id)
                ) if main_id.char_id != char.char_id else char.name
                return "<highlight>%s<end> has had their account disabled. Logs have been preserved." % name_reference

        return "<highlight>%s<end> does not have an open account." % char.name

    @command(command="account",
             params=[],
             access_level="all",
             description="Look up your account")
    def account_self_cmd(self, request):
        return self.get_account_display(request.sender)

    @command(command="account",
             params=[Const("logentry"), Int("log_id")],
             access_level="moderator",
             description="Look up specific log entry",
             sub_command="modify")
    def account_log_entry_cmd(self, _1, _2, log_id: int):
        log_entry = self.db.query_single(
            "SELECT * FROM points_log WHERE log_id = ?", [log_id])

        if log_entry:
            char_name = self.character_service.resolve_char_to_name(
                log_entry.char_id)
            leader_name = self.character_service.resolve_char_to_name(
                log_entry.leader_id)

            blob = "Log entry ID: <highlight>%d<end>\n" % log_id
            blob += "Affecting account: <highlight>%s<end>\n" % char_name
            blob += "Action by: <highlight>%s<end>\n" % leader_name
            blob += "Type: <highlight>%s<end>\n" % (
                "Management" if log_entry.audit == 0 else "Altering of points")
            blob += "Reason: <highlight>%s<end>\n" % log_entry.reason
            action_links = None
            if log_entry.audit == 0:
                if "closed" in log_entry.reason:
                    action_links = self.text.make_chatcmd(
                        "Open the account",
                        "/tell <myname> account create %s" % char_name)
                elif "re-enabled" in log_entry.reason:
                    action_links = self.text.make_chatcmd(
                        "Close the account",
                        "/tell <myname> account close %s" % char_name)
            else:
                if log_entry.audit < 0:
                    reason = "Points from event (%d) has been retracted, %d points have been added." \
                             % (log_id, (-1*log_entry.audit))
                    action_links = self.text.make_chatcmd(
                        "Retract", "/tell <myname> bank give %d %s %s" %
                        ((-1 * log_entry.audit), char_name, reason))
                else:
                    reason = "Points from event (%d) has been retracted, %d points have been deducted." \
                             % (log_id, log_entry.audit)
                    action_links = self.text.make_chatcmd(
                        "Retract", "/tell <myname> bank take %d %s %s" %
                        (log_entry.audit, char_name, reason))

            blob += "Actions available: [%s]\n" % (action_links
                                                   if action_links is not None
                                                   else "No actions available")

            return ChatBlob("Log entry (%d)" % log_id, blob)

        return "No log entry with given ID <highlight>%d<end>." % log_id

    @command(command="account",
             params=[
                 Options(["give", "take"]),
                 Int("amount"),
                 Character("char"),
                 Any("reason")
             ],
             access_level="moderator",
             description="Give or take points from character account",
             sub_command="modify")
    def account_give_take_cmd(self, request, action: str, amount: int,
                              char: SenderObj, reason: str):
        main_id = self.alts_service.get_main(char.char_id)

        sql = "SELECT * FROM points WHERE char_id = ?"
        points = self.db.query_single(sql, [main_id.char_id])

        if points:
            if points.disabled == 1:
                return "<highlight>%s<end>'s account is disabled, altering the account is not possible." % char.name

            if points.points == 0 and action == "take":
                return "<highlight>%s<end> has 0 points - can't have less than 0 points." % char.name

            if amount > points.points and action == "take":
                amount = points.points

            new_points = amount if action == "give" else 0 - amount

            if not self.alter_points(points.points, main_id.char_id,
                                     new_points, request.sender.char_id,
                                     reason):
                return "Failed to alter <highlight>%s<end>'s account." % char.name

            action = "taken from" if action == "take" else "added to"
            return "<highlight>%s<end> has had <highlight>%d<end> points %s their account." % (
                char.name, amount, action)

        return "<highlight>%s<end> does not have an account." % char.name

    @command(command="account",
             params=[Character("char")],
             access_level="moderator",
             description="Look up account of another char",
             sub_command="modify")
    def account_other_cmd(self, request, char: SenderObj):
        return self.get_account_display(char)

    @command(command="presets",
             params=[Const("add"), Any("name"),
                     Int("points")],
             access_level="admin",
             description="Add new points preset")
    def presets_add_cmd(self, _1, _2, name: str, points: int):
        count = self.db.query_single(
            "SELECT COUNT(*) AS count FROM points_presets WHERE name = ?",
            [name]).count

        if count > 0:
            return "A preset already exists with the name <highlight>%s<end>." % name

        sql = "INSERT INTO points_presets (name, points) VALUES (?,?)"
        if self.db.exec(sql, [name, points]) > 0:
            return "A preset with the name <highlight>%s<end> was added, worth <green>%d<end> points." % (
                name, points)

        return "Failed to insert new preset in DB."

    @command(command="presets",
             params=[Const("rem"), Int("preset_id")],
             access_level="admin",
             description="Delete preset")
    def presets_rem_cmd(self, _1, _2, preset_id: int):
        if self.db.exec("DELETE FROM points_presets WHERE preset_id = ?",
                        [preset_id]) > 0:
            return "Successfully removed preset with ID <highlight>%d<end>." % preset_id

        return "No preset with given ID <highlight>%d<end>." % preset_id

    @command(command="presets",
             params=[Const("alter"),
                     Int("preset_id"),
                     Int("new_points")],
             access_level="admin",
             description="Alter the points dished out by given preset")
    def presets_alter_cmd(self, _1, _2, preset_id: int, new_points: int):
        preset = self.db.query_single(
            "SELECT * FROM points_presets WHERE preset_id = ?", [preset_id])

        if preset:
            if self.db.exec(
                    "UPDATE points_presets SET points = ? WHERE preset_id = ?",
                [new_points, preset_id]) > 0:
                return "Successfully updated the preset, <highlight>%s<end>, to dish out " \
                       "<green>%d<end> points instead of <red>%d<end>." % (preset.name, new_points, preset.points)

            return "Failed to update preset with ID <highlight>%d<end>." % preset_id

    @command(command="presets",
             params=[],
             access_level="admin",
             description="See list of points presets")
    def presets_cmd(self, _):
        return ChatBlob("Points presets", self.build_preset_list())

    def build_preset_list(self):
        presets = self.db.query(
            "SELECT * FROM points_presets ORDER BY name ASC, points DESC")

        if presets:
            blob = ""

            for preset in presets:
                add_points_link = self.text.make_chatcmd(
                    "Add pts", "/tell <myname> raid addpts %s" % preset.name)
                delete_link = self.text.make_chatcmd(
                    "Delete",
                    "/tell <myname> presets rem %d" % preset.preset_id)
                blob += "<highlight>%s<end> worth <green>%d<end> points [id: %d]\n | [%s] [%s]\n\n" \
                        % (preset.name, preset.points, preset.preset_id, add_points_link, delete_link)

            return blob

        return "No presets available. To add new presets use <highlight><symbol>presets add preset_name preset_points<end>."

    def add_log_entry(self,
                      char_id: int,
                      leader_id: int,
                      reason: str,
                      amount=0):
        sql = "INSERT INTO points_log (char_id, audit, leader_id, reason, time) VALUES (?,?,?,?,?)"
        return self.db.exec(
            sql, [char_id, amount, leader_id, reason,
                  int(time.time())]) > 0

    def alter_points(self, current_points: int, char_id: int, amount: int,
                     leader_id: int, reason: str):
        sql = "UPDATE points SET points = points + ? WHERE char_id = ?"
        if self.db.exec(sql, [amount, char_id]) < 1:
            return False

        if not self.add_log_entry(char_id, leader_id, reason, amount):
            sql = "UPDATE points p SET p.points = ? WHERE p.char_id = ?"
            self.db.exec(sql, [current_points, char_id])
            return False

        return True

    def get_account(self, main_id):
        sql = "SELECT p.char_id, p.points, p.disabled FROM points p WHERE p.char_id = ?"
        return self.db.query_single(sql, [main_id])

    def get_account_display(self, char: SenderObj):
        main = self.alts_service.get_main(char.char_id)
        if not main:
            return "Could not find character <highlight>%s<end>." % char.name

        points_log = self.db.query(
            "SELECT * FROM points_log WHERE char_id = ? ORDER BY time DESC LIMIT 50",
            [main.char_id])
        points = self.db.query_single(
            "SELECT points, disabled FROM points WHERE char_id = ?",
            [main.char_id])
        if not points:
            return "Could not find raid account for <highlight>%s<end>." % char.name

        alts_link = self.text.make_chatcmd(
            "Alts", "/tell <myname> alts %s" % main.name)
        blob = ""
        blob += "Holder of account: %s [%s]\n" % (main.name, alts_link)
        blob += "Points: %d\n" % points.points
        blob += "Status: %s\n\n" % ("<green>Open<end>" if points.disabled == 0
                                    else "<red>Disabled<end>")

        blob += "<header2>Account log<end>\n"
        if points_log is None:
            blob += "No entries in log."
        else:
            for entry in points_log:
                name_reference = "<highlight>%s<end>" % char.name

                if entry.audit == 0:
                    # If points is 0, then it's a general case log
                    blob += "<grey>[%s]<end> <orange>\"%s\"<end>" % (
                        self.util.format_datetime(entry.time), entry.reason)
                elif entry.audit > 0:
                    pts = "<green>%d<end>" % entry.audit
                    blob += "<grey>[%s]<end> %s points were added to %s account " \
                            "by <highlight>%s<end> with reason <orange>%s<end>" \
                            % (self.util.format_datetime(entry.time),
                               pts, name_reference,
                               self.character_service.resolve_char_to_name(entry.leader_id), entry.reason)
                elif entry.audit < 0:
                    pts = "<red>%d<end>" % (-1 * entry.audit)
                    blob += "<grey>[%s]<end> %s points were taken from %s account " \
                            "by <highlight>%s<end> with reason <orange>%s<end>" \
                            % (self.util.format_datetime(entry.time),
                               pts, name_reference,
                               self.character_service.resolve_char_to_name(entry.leader_id),
                               entry.reason)

                log_entry_link = self.text.make_chatcmd(
                    "%d" % entry.log_id,
                    "/tell <myname> account logentry %d" % entry.log_id)
                blob += " [%s]\n" % log_entry_link

        return ChatBlob("%s Account" % char.name, blob)
Ejemplo n.º 20
0
class AltsController:
    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.alts_service = registry.get_instance("alts_service")
        self.buddy_service = registry.get_instance("buddy_service")
        self.ts: TranslationService = registry.get_instance("translation_service")
        self.getresp = self.ts.get_response

    def start(self):
        self.ts.register_translation("module/alts", self.load_alts_msg)

    def load_alts_msg(self):
        with open("modules/core/alts/alts.msg", mode="r", encoding="UTF-8") as f:
            return hjson.load(f)

    @command(command="alts", params=[], access_level="all",
             description="Show your alts")
    def alts_list_cmd(self, request):
        alts = self.alts_service.get_alts(request.sender.char_id)
        blob = self.format_alt_list(alts)

        return ChatBlob(self.getresp("module/alts", "list", {"char": alts[0].name, "amount": len(alts)}), blob)

    def get_alt_status(self, status):
        if status == AltsService.MAIN:
            return " - [main]"
        else:
            return ""

    @command(command="alts", params=[Const("setmain")], access_level="all",
             description="Set a new main", extended_description="You must run this from the character you want to be your new main")
    def alts_setmain_cmd(self, request, _):
        msg, result = self.alts_service.set_as_main(request.sender.char_id)

        if result:
            return self.getresp("module/alts", "new_main", {"char":request.sender.name})
        elif msg == "not_an_alt":
            return self.getresp("module/alts", "not_an_alt")
        elif msg == "already_main":
            return self.getresp("module/alts", "already_main")
        else:
            raise Exception("Unknown msg: " + msg)

    @command(command="alts", params=[Const("add"), Character("character")], access_level="all",
             description="Add an alt")
    def alts_add_cmd(self, request, _, alt_char):
        if not alt_char.char_id:
            return self.getresp("global", "char_not_found", {"char":alt_char.name})
        elif alt_char.char_id == request.sender.char_id:
            return self.getresp("module/alts", "add_fail_self")

        msg, result = self.alts_service.add_alt(request.sender.char_id, alt_char.char_id)
        if result:
            self.bot.send_private_message(alt_char.char_id, self.getresp("module/alts", "add_success_target",
                                                                         {"char": request.sender.name}))
            return self.getresp("module/alts", "add_success_self", {"char": alt_char.name})
        elif msg == "another_main":
            return self.getresp("module/alts", "add_fail_already", {"char": alt_char.name})
        else:
            raise Exception("Unknown msg: " + msg)

    @command(command="alts", params=[Options(["rem", "remove"]), Character("character")], access_level="all",
             description="Remove an alt")
    def alts_remove_cmd(self, request, _, alt_char):
        if not alt_char.char_id:
            return self.getresp("global", "char_not_found", {"char":alt_char.name})

        msg, result = self.alts_service.remove_alt(request.sender.char_id, alt_char.char_id)
        if result:
            return self.getresp("module/alts", "rem_success", {"char": alt_char.name})
        elif msg == "not_alt":
            return self.getresp("module/alts", "rem_fail_not", {"char": alt_char.name})
        elif msg == "remove_main":
            return self.getresp("module/alts", "rem_fail_main")
        else:
            raise Exception("Unknown msg: " + msg)

    @command(command="alts", params=[Character("character")], access_level="member",
             description="Show alts of another character", sub_command="show")
    def alts_list_other_cmd(self, request, char):
        if not char.char_id:
            return self.getresp("global", "char_not_found", {"char":char.name})

        alts = self.alts_service.get_alts(char.char_id)
        blob = self.format_alt_list(alts)

        return ChatBlob(self.getresp("module/alts", "alts_list", {"char": alts[0].name, "amount": len(alts)}), blob)

    def format_alt_list(self, alts):
        blob = ""
        for alt in alts:
            blob += "<highlight>%s<end> (%d/<green>%d<end>) %s %s" % (alt.name, alt.level, alt.ai_level, alt.faction, alt.profession)
            if self.buddy_service.is_online(alt.char_id):
                blob += " [<green>Online<end>]"
            blob += "\n"
        return blob
Ejemplo n.º 21
0
class UtilController:
    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.db = registry.get_instance("db")
        self.util = registry.get_instance("util")
        self.command_service = registry.get_instance("command_service")
        self.buddy_service = registry.get_instance("buddy_service")
        self.access_service = registry.get_instance("access_service")
        self.event_service = registry.get_instance("event_service")
        self.public_channel_service = registry.get_instance(
            "public_channel_service")

    @command(command="checkaccess",
             params=[Character("character", is_optional=True)],
             access_level="all",
             description="Check access level for a character")
    def checkaccess_cmd(self, request, char):
        char = char or request.sender

        if not char.char_id:
            return "Could not find character <highlight>%s<end>." % char.name

        return "Access level for <highlight>%s<end> is <highlight>%s<end> (%s)." % \
               (char.name, char.access_level["label"], self.access_service.get_single_access_level(char.char_id)["label"])

    @command(command="macro",
             params=[Any("command1|command2|command3...")],
             access_level="all",
             description="Execute multiple commands at once")
    def macro_cmd(self, request, commands):
        commands = commands.split("|")
        for command_str in commands:
            self.command_service.process_command(command_str, request.channel,
                                                 request.sender.char_id,
                                                 request.reply)

    @command(command="echo",
             params=[Any("message")],
             access_level="all",
             description="Echo back a message")
    def echo_cmd(self, request, message):
        return html.escape(message)

    @command(command="showcommand",
             params=[Character("character"),
                     Any("message")],
             access_level="admin",
             description="Show command output to another character")
    def showcommand_cmd(self, request, char, command_str):
        if not char.char_id:
            return "Could not find <highlight>%s<end>." % char.name

        self.bot.send_private_message(
            char.char_id,
            "<highlight>%s<end> is showing you output for command <highlight>%s<end>:"
            % (request.sender.name, command_str))

        self.command_service.process_command(
            command_str, request.channel, request.sender.char_id,
            lambda msg: self.bot.send_private_message(char.char_id, msg))

        return "Command <highlight>%s<end> output has been sent to <highlight>%s<end>." % (
            command_str, char.name)

    @command(command="system",
             params=[],
             access_level="admin",
             description="Show system information")
    def system_cmd(self, request):
        blob = ""
        blob += "Version: <highlight>Tyrbot %s<end>\n" % self.bot.version
        blob += "Name: <highlight><myname><end>\n"
        blob += "\n"
        blob += "OS: <highlight>%s %s<end>\n" % (platform.system(),
                                                 platform.release())
        blob += "Python: <highlight>%d.%d.%d %s<end>\n" % (
            sys.version_info.major, sys.version_info.minor,
            sys.version_info.micro, sys.version_info.releaselevel)
        blob += "Database: <highlight>%s<end>\n" % self.db.type
        blob += "Memory Usage: <highlight>%s KB<end>\n" % self.util.format_number(
            psutil.Process(os.getpid()).memory_info().rss / 1024)
        blob += "\n"
        blob += "Superadmin: <highlight>%s<end>\n" % self.bot.superadmin
        blob += "Buddy List: <highlight>%d / %d<end>\n" % (len(
            self.buddy_service.buddy_list), self.buddy_service.buddy_list_size)
        blob += "Uptime: <highlight>%s<end>\n" % self.util.time_to_readable(
            int(time.time()) - self.bot.start_time, max_levels=None)
        blob += "Dimension: <highlight>%s<end>\n" % self.bot.dimension
        blob += "\n"
        blob += "Org Id: <highlight>%s<end>\n" % self.public_channel_service.org_id
        blob += "Org Name: <highlight>%s<end>\n" % self.public_channel_service.org_name

        blob += "\n<pagebreak><header2>Public Channels<end>\n"
        for channel_id, name in self.public_channel_service.get_all_public_channels(
        ).items():
            blob += "%s - <highlight>%d<end>\n" % (name, channel_id)

        blob += "\n<pagebreak><header2>Event Types<end>\n"
        for event_type in self.event_service.get_event_types():
            blob += "%s\n" % event_type

        blob += "\n<pagebreak><header2>Access Levels<end>\n"
        for access_level in self.access_service.get_access_levels():
            blob += "%s (%d)\n" % (access_level["label"],
                                   access_level["level"])

        return ChatBlob("System Info", blob)

    @command(
        command="htmldecode",
        params=[Any("command")],
        access_level="all",
        description=
        "Decode html entities from a command before passing to the bot for execution"
    )
    def htmldecode_cmd(self, request, command_str):
        self.command_service.process_command(html.unescape(command_str),
                                             request.channel,
                                             request.sender.char_id,
                                             request.reply)
Ejemplo n.º 22
0
class PrivateChannelController:
    RELAY_HUB_SOURCE = "private_channel"

    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.private_channel_service = registry.get_instance(
            "private_channel_service")
        self.character_service = registry.get_instance("character_service")
        self.job_scheduler = registry.get_instance("job_scheduler")
        self.access_service = registry.get_instance("access_service")
        self.relay_hub_service = registry.get_instance("relay_hub_service")
        self.ban_service = registry.get_instance("ban_service")
        self.log_controller = registry.get_instance("log_controller")
        self.online_controller = registry.get_instance("online_controller")
        self.relay_controller = registry.get_instance("relay_controller")
        self.text: Text = registry.get_instance("text")
        self.ts: TranslationService = registry.get_instance(
            "translation_service")
        self.getresp = self.ts.get_response
        self.setting_service: SettingService = registry.get_instance(
            "setting_service")

    def start(self):
        self.relay_hub_service.register_relay(
            self.RELAY_HUB_SOURCE, self.handle_incoming_relay_message)
        self.ts.register_translation("module/private_channel",
                                     self.load_private_channel_msg)

    def load_private_channel_msg(self):
        with open("modules/core/private_channel/private_channel.msg",
                  mode="r",
                  encoding="utf-8") as f:
            return hjson.load(f)

    def handle_incoming_relay_message(self, ctx):
        message = ctx.message

        self.bot.send_private_channel_message(message,
                                              fire_outgoing_event=False)

    @setting(
        name="prefix_org",
        value="true",
        description=
        "Should the prefix [Org Tag] be displayed in relayed messages",
    )
    def prefix_priv(self):
        return BooleanSettingType()

    @command(command="join",
             params=[],
             access_level="all",
             description="Join the private channel")
    def join_cmd(self, request):
        self.private_channel_service.invite(request.sender.char_id)

    @command(command="leave",
             params=[],
             access_level="all",
             description="Leave the private channel")
    def leave_cmd(self, request):
        self.private_channel_service.kick(request.sender.char_id)

    @command(command="invite",
             params=[Character("character")],
             access_level="all",
             description="Invite a character to the private channel")
    def invite_cmd(self, request, char):
        if char.char_id:
            if self.private_channel_service.in_private_channel(char.char_id):
                return self.getresp("module/private_channel", "invite_fail",
                                    {"target": char.name})
            else:
                self.bot.send_private_message(
                    char.char_id,
                    self.getresp("module/private_channel",
                                 "invite_success_target",
                                 {"inviter": request.sender.name}))
                self.private_channel_service.invite(char.char_id)
                return self.getresp("module/private_channel",
                                    "invite_success_self",
                                    {"target": char.name})
        else:
            return self.getresp("global", "char_not_found",
                                {"char": char.name})

    @command(command="kick",
             params=[Character("character")],
             access_level="admin",
             description="Kick a character from the private channel")
    def kick_cmd(self, request, char):
        if char.char_id:
            if not self.private_channel_service.in_private_channel(
                    char.char_id):
                return self.getresp("module/private_channel",
                                    "kick_fail_not_in_priv",
                                    {"target": char.name})
            else:
                # TODO use request.sender.access_level and char.access_level
                if self.access_service.has_sufficient_access_level(
                        request.sender.char_id, char.char_id):
                    self.bot.send_private_message(
                        char.char_id,
                        self.getresp("module/private_channel",
                                     "kick_success_target",
                                     {"kicker": request.sender.name}))
                    self.private_channel_service.kick(char.char_id)
                    return self.getresp("module/private_channel",
                                        "kick_success_self",
                                        {"target": char.name})
                else:
                    return self.getresp("module/private_channel", "kick_fail",
                                        {"target": char.name})
        else:
            return self.getresp("global", "char_not_found",
                                {"char": char.name})

    @command(command="kickall",
             params=[],
             access_level="admin",
             description="Kick all characters from the private channel")
    def kickall_cmd(self, request):
        self.bot.send_private_channel_message(
            self.getresp("module/private_channel", "kick_all",
                         {"char": request.sender.name}))
        self.job_scheduler.delayed_job(
            lambda t: self.private_channel_service.kickall(), 10)

    @event(
        event_type=BanService.BAN_ADDED_EVENT,
        description="Kick characters from the private channel who are banned",
        is_hidden=True)
    def ban_added_event(self, event_type, event_data):
        self.private_channel_service.kick(event_data.char_id)

    @event(
        event_type=PrivateChannelService.PRIVATE_CHANNEL_MESSAGE_EVENT,
        description="Relay messages from the private channel to the relay hub",
        is_hidden=True)
    def handle_private_channel_message_event(self, event_type, event_data):
        if event_data.char_id == self.bot.char_id or self.ban_service.get_ban(
                event_data.char_id):
            return

        char_name = self.character_service.resolve_char_to_name(
            event_data.char_id)
        sender = DictObject({"char_id": event_data.char_id, "name": char_name})
        org = (
            "[" + self.relay_controller.get_org_channel_prefix() +
            "]") if self.setting_service.get_value("prefix_org") == "1" else ""
        priv = "[Private]"
        char = self.text.make_charlink(char_name) + ": "
        message = self.getresp("module/private_channel", "relay_from_priv", {
            "org": org,
            "priv": priv,
            "char": char,
            "message": event_data.message
        })
        self.relay_hub_service.send_message(self.RELAY_HUB_SOURCE, sender,
                                            message)

    @event(event_type=PrivateChannelService.JOINED_PRIVATE_CHANNEL_EVENT,
           description="Notify when a character joins the private channel")
    def handle_private_channel_joined_event(self, event_type, event_data):
        msg = self.getresp(
            "module/private_channel", "join", {
                "char":
                self.online_controller.get_char_info_display(
                    event_data.char_id),
                "logon":
                self.log_controller.get_logon(event_data.char_id)
            })
        self.bot.send_private_channel_message(msg)

    @event(event_type=PrivateChannelService.LEFT_PRIVATE_CHANNEL_EVENT,
           description="Notify when a character leaves the private channel")
    def handle_private_channel_left_event(self, event_type, event_data):
        char_name = self.character_service.resolve_char_to_name(
            event_data.char_id)
        msg = self.getresp(
            "module/private_channel", "leave", {
                "char": char_name,
                "logoff": self.log_controller.get_logon(event_data.char_id)
            })
        self.bot.send_private_channel_message(msg)

    @event(
        event_type=Tyrbot.OUTGOING_PRIVATE_CHANNEL_MESSAGE_EVENT,
        description="Relay commands from the private channel to the relay hub")
    def outgoing_private_channel_message_event(self, event_type, event_data):
        org = (
            "[" + self.relay_controller.get_org_channel_prefix() +
            "]") if self.setting_service.get_value("prefix_org") == "1" else ""
        priv = "[Private]"
        if isinstance(event_data.message, ChatBlob):
            pages = self.text.paginate(
                ChatBlob(event_data.message.title, event_data.message.msg),
                self.setting_service.get(
                    "org_channel_max_page_length").get_value())
            if len(pages) < 4:
                for page in pages:
                    message = self.getresp("module/private_channel",
                                           "relay_from_priv", {
                                               "org": org,
                                               "priv": priv,
                                               "message": page,
                                               "char": ""
                                           })
                    #message = "[%s][Private] %s" % (self.relay_controller.get_org_channel_prefix(), page)
                    self.relay_hub_service.send_message(
                        self.RELAY_HUB_SOURCE,
                        DictObject({
                            "name": self.bot.char_name,
                            "char_id": self.bot.char_id
                        }), message)
            else:
                message = self.getresp(
                    "module/private_channel", "relay_from_priv", {
                        "org": org,
                        "priv": priv,
                        "message": event_data.message.title,
                        "char": ""
                    })
                self.relay_hub_service.send_message(
                    self.RELAY_HUB_SOURCE,
                    DictObject({
                        "name": self.bot.char_name,
                        "char_id": self.bot.char_id
                    }), message)
        else:
            message = self.getresp(
                "module/private_channel", "relay_from_priv", {
                    "org": org,
                    "priv": priv,
                    "message": event_data.message,
                    "char": ""
                })
            #message = "[%s][Private] %s" % (self.relay_controller.get_org_channel_prefix(), event_data.message)
            self.relay_hub_service.send_message(
                self.RELAY_HUB_SOURCE,
                DictObject({
                    "name": self.bot.char_name,
                    "char_id": self.bot.char_id
                }), message)
Ejemplo n.º 23
0
class PrivateChannelController:
    MESSAGE_SOURCE = "private_channel"
    MESSAGE_SOURCE_UPDATE = "private_channel_update"

    def __init__(self):
        self.logger = Logger(__name__)
        self.private_channel_conn = None

    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.private_channel_service = registry.get_instance(
            "private_channel_service")
        self.character_service = registry.get_instance("character_service")
        self.job_scheduler = registry.get_instance("job_scheduler")
        self.access_service = registry.get_instance("access_service")
        self.message_hub_service = registry.get_instance("message_hub_service")
        self.ban_service = registry.get_instance("ban_service")
        self.log_controller = registry.get_instance(
            "log_controller",
            is_optional=True)  # TODO core module depending on standard module
        self.online_controller = registry.get_instance(
            "online_controller",
            is_optional=True)  # TODO core module depending on standard module
        self.text: Text = registry.get_instance("text")
        self.setting_service: SettingService = registry.get_instance(
            "setting_service")

    def pre_start(self):
        self.message_hub_service.register_message_source(self.MESSAGE_SOURCE)
        self.message_hub_service.register_message_source(
            self.MESSAGE_SOURCE_UPDATE)

    def start(self):
        self.setting_service.register(
            self.module_name, "private_channel_prefix", "[Priv]",
            TextSettingType(["[Priv]", "[Guest]"]),
            "The name to show for messages coming from the private channel")

        self.setting_service.register(
            self.module_name,
            "private_channel_conn",
            "",
            TextSettingType(allow_empty=True),
            "The conn id or name to use for the private channel",
            extended_description=
            "If empty, the bot will use the primary conn. You MUST restart the bot after changing this value for the change to take effect."
        )

        self.message_hub_service.register_message_destination(
            self.MESSAGE_SOURCE, self.handle_incoming_relay_message, [
                "org_channel", "org_channel_update", "discord",
                "websocket_relay", "broadcast", "raffle", "shutdown_notice",
                "raid", "timers", "alliance"
            ], [self.MESSAGE_SOURCE, self.MESSAGE_SOURCE_UPDATE])

    def handle_incoming_relay_message(self, ctx):
        self.bot.send_private_channel_message(ctx.formatted_message,
                                              conn=self.get_conn(None))

    @command(command="join",
             params=[],
             access_level="member",
             description="Join the private channel")
    def join_cmd(self, request):
        self.private_channel_service.invite(request.sender.char_id,
                                            self.get_conn(request.conn))

    @command(command="leave",
             params=[],
             access_level="all",
             description="Leave the private channel")
    def leave_cmd(self, request):
        self.private_channel_service.kick(request.sender.char_id,
                                          self.get_conn(request.conn))

    @command(command="invite",
             params=[Character("character")],
             access_level="all",
             description="Invite a character to the private channel")
    def invite_cmd(self, request, char):
        if char.char_id:
            conn = self.get_conn(request.conn)
            if char.char_id in conn.private_channel:
                return f"<highlight>{char.name}</highlight> is already in the private channel."
            else:
                self.bot.send_private_message(
                    char.char_id,
                    f"You have been invited to the private channel by <highlight>{request.sender.name}</highlight>.",
                    conn=conn)
                self.private_channel_service.invite(char.char_id, conn)
                return f"You have invited <highlight>{char.name}</highlight> to the private channel."
        else:
            return StandardMessage.char_not_found(char.name)

    @command(command="kick",
             params=[Character("character")],
             access_level="moderator",
             description="Kick a character from the private channel")
    def kick_cmd(self, request, char):
        if char.char_id:
            conn = self.get_conn(request.conn)
            if char.char_id not in conn.private_channel:
                return f"<highlight>{char.name}</highlight> is not in the private channel."
            else:
                # TODO use request.sender.access_level and char.access_level
                if self.access_service.has_sufficient_access_level(
                        request.sender.char_id, char.char_id):
                    self.bot.send_private_message(
                        char.char_id,
                        f"You have been kicked from the private channel by <highlight>{request.sender.name}</highlight>.",
                        conn=conn)
                    self.private_channel_service.kick(char.char_id, conn)
                    return f"You have kicked <highlight>{char.name}</highlight> from the private channel."
                else:
                    return f"You do not have the required access level to kick <highlight>{char.name}</highlight>."
        else:
            return StandardMessage.char_not_found(char.name)

    @command(command="kickall",
             params=[],
             access_level="moderator",
             description="Kick all characters from the private channel")
    def kickall_cmd(self, request):
        conn = self.get_conn(request.conn)
        self.bot.send_private_channel_message(
            f"Everyone will be kicked from this channel in 10 seconds. [by <highlight>{request.sender.name}</highlight>]",
            conn=conn)
        self.job_scheduler.delayed_job(
            lambda t: self.private_channel_service.kickall(conn), 10)

    @event(event_type="connect",
           description=
           "Load the conn ids as choice for private_channel_conn setting",
           is_system=True)
    def load_conns_into_setting_choice(self, event_type, event_data):
        options = []
        for _id, conn in self.bot.get_conns(lambda x: x.is_main == True):
            options.append(conn.char_name)

        setting = self.setting_service.get("private_channel_conn")
        setting.options = options

    @event(
        event_type=BanService.BAN_ADDED_EVENT,
        description="Kick characters from the private channel who are banned",
        is_system=True)
    def ban_added_event(self, event_type, event_data):
        self.private_channel_service.kick_from_all(event_data.char_id)

    @event(
        event_type=PrivateChannelService.PRIVATE_CHANNEL_MESSAGE_EVENT,
        description="Relay messages from the private channel to the relay hub",
        is_system=True)
    def handle_private_channel_message_event(self, event_type, event_data):
        if self.bot.get_conn_by_char_id(
                event_data.char_id) or self.ban_service.get_ban(
                    event_data.char_id):
            return

        sender = DictObject({
            "char_id": event_data.char_id,
            "name": event_data.name
        })
        self.message_hub_service.send_message(
            self.MESSAGE_SOURCE, sender, self.get_private_channel_prefix(),
            event_data.message)

    @event(event_type=PrivateChannelService.JOINED_PRIVATE_CHANNEL_EVENT,
           description="Notify when a character joins the private channel")
    def handle_private_channel_joined_event(self, event_type, event_data):
        if self.online_controller:
            char_info = self.online_controller.get_char_info_display(
                event_data.char_id, event_data.conn)
        else:
            char_info = self.character_service.resolve_char_to_name(
                event_data.char_id)

        msg = f"{char_info} has joined the private channel."
        if self.log_controller:
            msg += " " + self.log_controller.get_logon(event_data.char_id)

        self.bot.send_private_channel_message(msg, conn=event_data.conn)
        self.message_hub_service.send_message(
            self.MESSAGE_SOURCE_UPDATE, None,
            self.get_private_channel_prefix(), msg)

    @event(event_type=PrivateChannelService.LEFT_PRIVATE_CHANNEL_EVENT,
           description="Notify when a character leaves the private channel")
    def handle_private_channel_left_event(self, event_type, event_data):
        msg = f"<highlight>{event_data.name}</highlight> has left the private channel."
        if self.log_controller:
            msg += " " + self.log_controller.get_logoff(event_data.char_id)

        self.bot.send_private_channel_message(msg, conn=event_data.conn)
        self.message_hub_service.send_message(
            self.MESSAGE_SOURCE_UPDATE, None,
            self.get_private_channel_prefix(), msg)

    @event(
        event_type=PrivateChannelService.PRIVATE_CHANNEL_COMMAND_EVENT,
        description="Relay commands from the private channel to the relay hub",
        is_system=True)
    def outgoing_private_channel_message_event(self, event_type, event_data):
        sender = None
        if event_data.name:
            sender = DictObject({
                "char_id": event_data.char_id,
                "name": event_data.name
            })

        if isinstance(event_data.message, ChatBlob):
            pages = self.text.paginate(
                ChatBlob(event_data.message.title, event_data.message.msg),
                event_data.conn,
                self.setting_service.get(
                    "org_channel_max_page_length").get_value())
            if len(pages) < 4:
                for page in pages:
                    self.message_hub_service.send_message(
                        self.MESSAGE_SOURCE, sender,
                        self.get_private_channel_prefix(), page)
            else:
                self.message_hub_service.send_message(
                    self.MESSAGE_SOURCE, sender,
                    self.get_private_channel_prefix(),
                    event_data.message.title)
        else:
            self.message_hub_service.send_message(
                self.MESSAGE_SOURCE, sender, self.get_private_channel_prefix(),
                event_data.message)

    def get_conn(self, conn):
        if self.private_channel_conn:
            return self.private_channel_conn

        conn_id = self.setting_service.get_value("private_channel_conn")
        if conn_id:
            for _id, conn in self.bot.get_conns(
                    lambda x: x.id == conn_id or x.char_name == conn_id):
                self.private_channel_conn = conn
                break

            if not self.private_channel_conn:
                self.logger.warning(
                    f"Could not find conn with id '{conn_id}', defaulting to primary conn"
                )
                self.private_channel_conn = self.bot.get_primary_conn()
        else:
            # use the primary conn if private_channel_conn is not set
            self.private_channel_conn = self.bot.get_primary_conn()

        return self.private_channel_conn

    def get_private_channel_prefix(self):
        return self.setting_service.get_value("private_channel_prefix")
Ejemplo n.º 24
0
class RaidController:
    MESSAGE_SOURCE = "raid"
    NO_RAID_RUNNING_RESPONSE = "No raid is running."

    def __init__(self):
        self.raid: Raid = None

    def inject(self, registry):
        self.bot: Tyrbot = registry.get_instance("bot")
        self.db: DB = registry.get_instance("db")
        self.text: Text = registry.get_instance("text")
        self.setting_service: SettingService = registry.get_instance("setting_service")
        self.alts_service: AltsService = registry.get_instance("alts_service")
        self.buddy_service = registry.get_instance("buddy_service")
        self.character_service: CharacterService = registry.get_instance("character_service")
        self.private_channel_service = registry.get_instance("private_channel_service")
        self.points_controller: PointsController = registry.get_instance("points_controller")
        self.util: Util = registry.get_instance("util")
        self.message_hub_service = registry.get_instance("message_hub_service")
        self.leader_controller = registry.get_instance("leader_controller")
        self.topic_controller = registry.get_instance("topic_controller")
        self.member_controller = registry.get_instance("member_controller")

    def pre_start(self):
        self.message_hub_service.register_message_source(self.MESSAGE_SOURCE)

        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.load_sql_file(self.module_dir + "/" + "raid_loot.sql")

    @command(command="raid", params=[], access_level="member",
             description="Show the current raid status")
    def raid_cmd(self, request):
        if not self.raid:
            return self.NO_RAID_RUNNING_RESPONSE

        t = int(time.time())

        blob = ""
        blob += "Name: <highlight>%s</highlight>\n" % self.raid.raid_name
        blob += "Started By: <highlight>%s</highlight>\n" % self.raid.started_by.name
        blob += "Started At: <highlight>%s</highlight> (%s ago)\n" % (self.util.format_datetime(self.raid.started_at), self.util.time_to_readable(t - self.raid.started_at))
        blob += "Status: %s" % ("<green>Open</green>" if self.raid.is_open else "<red>Closed</red>")
        if self.raid.is_open:
            blob += " (%s)" % self.text.make_tellcmd("Join", "raid join")
        blob += "\n\n"

        topic = self.topic_controller.get_topic()
        if topic:
            time_str = self.util.time_to_readable(int(time.time()) - topic["created_at"])
            blob += "<header2>Orders</header2>\n"
            blob += "%s\n- <highlight>%s</highlight> %s ago\n\n" % (topic["topic_message"], topic["created_by"]["name"], time_str)

        blob += "<header2>Raiders</header2>\n"
        for raider in self.raid.raiders:
            if raider.is_active:
                blob += self.text.format_char_info(raider.get_active_char()) + "\n"

        return ChatBlob("Raid Status", blob)

    @command(command="raid", params=[Const("start"), Any("raid_name")],
             description="Start new raid", access_level="moderator", sub_command="manage")
    def raid_start_cmd(self, request, _, raid_name: str):
        if self.raid:
            return f"The raid <highlight>{self.raid.raid_name}</highlight> is already running."

        # if a leader is already set, only start raid if sender can take leader from current leader
        msg = self.leader_controller.set_raid_leader(request.sender, request.sender, request.conn)
        request.reply(msg)
        leader = self.leader_controller.get_leader(request.conn)
        if leader and leader.char_id != request.sender.char_id:
            return None

        self.raid = Raid(raid_name, request.sender)

        sql = "INSERT INTO raid_log (raid_name, started_by, raid_start, raid_end) VALUES (?,?,?,?)"
        self.db.exec(sql, [self.raid.raid_name, self.raid.started_by.char_id, self.raid.started_at, 0])
        self.raid.raid_id = self.db.last_insert_id()

        leader_alts = self.alts_service.get_alts(request.sender.char_id)
        self.raid.raiders.append(Raider(leader_alts, request.sender.char_id))

        join_link = self.text.paginate_single(ChatBlob("Click here", self.get_raid_join_blob()), request.conn)

        msg = "\n<highlight>----------------------------------------</highlight>\n"
        msg += "<highlight>%s</highlight> has started the raid <highlight>%s</highlight>.\n" % (request.sender.name, raid_name)
        msg += "%s to join\n" % join_link
        msg += "<highlight>----------------------------------------</highlight>"

        self.send_message(msg, request.conn)

    @command(command="raid", params=[Const("cancel")], description="Cancel the raid without saving/logging",
             access_level="moderator", sub_command="manage")
    def raid_cancel_cmd(self, request, _):
        if self.raid is None:
            return self.NO_RAID_RUNNING_RESPONSE

        self.send_message("<highlight>%s</highlight> canceled the raid <highlight>%s</highlight>." % (request.sender.name, self.raid.raid_name), request.conn)
        self.raid = None
        self.topic_controller.clear_topic()

    @command(command="raid", params=[Const("join")], description="Join the ongoing raid", access_level="member")
    def raid_join_cmd(self, request, _):
        if not self.raid:
            return self.NO_RAID_RUNNING_RESPONSE

        main_id = self.alts_service.get_main(request.sender.char_id).char_id
        in_raid = self.is_in_raid(main_id)

        if in_raid is not None:
            if in_raid.active_id == request.sender.char_id:
                if in_raid.is_active:
                    return "You are already participating in the raid."
                else:
                    if not self.raid.is_open:
                        return "Raid is closed."
                    in_raid.is_active = True
                    in_raid.was_kicked = None
                    in_raid.was_kicked_reason = None
                    in_raid.left_raid = None

                    self.points_controller.add_log_entry(main_id, request.sender.char_id, f"Joined raid {self.raid.raid_name}")
                    self.send_message("%s returned to actively participating in the raid." % request.sender.name, request.conn)

            elif in_raid.is_active:
                former_active_name = self.character_service.resolve_char_to_name(in_raid.active_id)
                in_raid.active_id = request.sender.char_id
                self.points_controller.add_log_entry(main_id, request.sender.char_id,
                                                     f"Switched to alt {request.sender.name} ({request.sender.char_id} in raid {self.raid.raid_name}")
                self.send_message("<highlight>%s</highlight> joined the raid with a different alt, <highlight>%s</highlight>." % (former_active_name, request.sender.name),
                                  request.conn)

            elif not in_raid.is_active:
                if not self.raid.is_open:
                    return "Raid is closed."

                self.points_controller.add_log_entry(main_id, request.sender.char_id,
                                                     f"Switched to alt {request.sender.name} in raid {self.raid.raid_name}")
                self.points_controller.add_log_entry(main_id, request.sender.char_id, f"Joined raid {self.raid.raid_name}")

                former_active_name = self.character_service.resolve_char_to_name(in_raid.active_id)
                in_raid.active_id = request.sender.char_id
                in_raid.was_kicked = None
                in_raid.was_kicked_reason = None
                in_raid.left_raid = None
                self.send_message("%s returned to actively participate with a different alt, <highlight>%s</highlight>." % (former_active_name, request.sender.name),
                                  request.conn)

        elif self.raid.is_open:
            alts = self.alts_service.get_alts(request.sender.char_id)
            self.raid.raiders.append(Raider(alts, request.sender.char_id))
            self.points_controller.add_log_entry(main_id, request.sender.char_id, f"Joined raid {self.raid.raid_name}")
            self.send_message("<highlight>%s</highlight> joined the raid." % request.sender.name, request.conn)
            if request.sender.char_id not in self.bot.get_primary_conn().private_channel:
                self.private_channel_service.invite(request.sender.char_id, self.bot.get_primary_conn())
        else:
            return "Raid is closed."

    @command(command="raid", params=[Const("leave")], description="Leave the ongoing raid", access_level="member")
    def raid_leave_cmd(self, request, _):
        main_id = self.alts_service.get_main(request.sender.char_id).char_id
        in_raid = self.is_in_raid(main_id)
        if in_raid:
            if not in_raid.is_active:
                return "You are not active in the raid."

            in_raid.is_active = False
            in_raid.left_raid = int(time.time())
            self.points_controller.add_log_entry(main_id, request.sender.char_id, f"Left raid {self.raid.raid_name}")
            self.send_message("<highlight>%s</highlight> left the raid." % request.sender.name, request.conn)
        else:
            return "You are not in the raid."

    @command(command="raid", params=[Const("addpts"), Any("name")], description="Add points to all active participants",
             access_level="moderator", sub_command="manage")
    def points_add_cmd(self, request, _, name: str):
        if not self.raid:
            return self.NO_RAID_RUNNING_RESPONSE

        preset = self.db.query_single("SELECT name, points FROM points_presets WHERE name = ?", [name])
        if not preset:
            return ChatBlob("No such preset - see list of presets", self.points_controller.build_preset_list())

        self.raid.added_points = True

        for raider in self.raid.raiders:
            account = self.points_controller.get_account(raider.main_id, request.conn)

            if raider.is_active:
                if account.disabled == 0:
                    self.points_controller.alter_points(raider.main_id, request.sender.char_id, preset.name, preset.points)
                    raider.accumulated_points += preset.points
                else:
                    self.points_controller.add_log_entry(raider.main_id, request.sender.char_id,
                                                         "Participated in raid with a disabled account, missed points from %s." % preset.name)
            else:
                self.points_controller.add_log_entry(raider.main_id, request.sender.char_id,
                                                     "Was inactive during raid, %s, when points for %s were dished out." % (self.raid.raid_name, preset.name))

        self.send_message("<highlight>%d</highlight> points added to all active raiders for <highlight>%s</highlight>." % (preset.points, preset.name), request.conn)

    @command(command="raid", params=[Const("active")], description="Get a list of raiders to do active check",
             access_level="moderator", sub_command="manage")
    def raid_active_cmd(self, request, _):
        if not self.raid:
            return self.NO_RAID_RUNNING_RESPONSE

        blob = ""

        count = 0
        raider_names = []
        for raider in self.raid.raiders:
            if count == 10:
                active_check_names = "/assist "
                active_check_names += "\\n /assist ".join(raider_names)
                blob += "\n[<a href='chatcmd://%s'>Active check</a>]\n\n" % active_check_names
                count = 0
                raider_names.clear()

            raider_name = self.character_service.resolve_char_to_name(raider.active_id)
            akick_link = self.text.make_tellcmd("Active kick", "raid kick %s inactive" % raider_name)
            warn_link = self.text.make_chatcmd("Warn", "/tell %s You missed active check, please give notice." % raider_name)
            blob += "<highlight>%s</highlight> [%s] [%s]\n" % (raider_name, akick_link, warn_link)
            raider_names.append(raider_name)
            count += 1

        if len(raider_names) > 0:
            active_check_names = "/assist "
            active_check_names += "\\n /assist ".join(raider_names)

            blob += "\n[<a href='chatcmd://%s'>Active check</a>]\n\n" % active_check_names
            raider_names.clear()

        return ChatBlob("Active check", blob)

    @command(command="raid", params=[Const("add"), Character("char")],
             description="Add a character to the raid", access_level="moderator", sub_command="manage")
    def raid_add_cmd(self, request, _, char):
        if self.raid is None:
            return self.NO_RAID_RUNNING_RESPONSE

        alts = self.alts_service.get_alts(char.char_id)
        main_id = alts[0].char_id
        in_raid = self.is_in_raid(main_id)

        if in_raid is None:
            self.raid.raiders.append(Raider(alts, char.char_id))
            self.bot.send_private_message(char.char_id,
                                          f"You have been added to the raid <highlight>{self.raid.raid_name}</highlight>.",
                                          conn=request.conn)
            self.points_controller.add_log_entry(main_id, request.sender.char_id, f"Added to raid {self.raid.raid_name}")
            if char.char_id not in self.bot.get_primary_conn().private_channel:
                self.private_channel_service.invite(char.char_id)
            return "<highlight>%s</highlight> has been added to the raid." % char.name
        else:
            if not in_raid.is_active:
                in_raid.is_active = True
                in_raid.was_kicked = None
                in_raid.was_kicked_reason = None
                in_raid.left_raid = None
                self.points_controller.add_log_entry(main_id, request.sender.char_id, f"Added to raid {self.raid.raid_name}")
                self.bot.send_private_message(char.char_id,
                                              f"You have been set as active in the raid <highlight>{self.raid.raid_name}</highlight>.",
                                              conn=request.conn)
                return f"<highlight>{char.name}</highlight> has been set as active."
            else:
                return f"<highlight>{char.name}</highlight> is already in the raid."

    @command(command="raid", params=[Const("kick"), Character("char"), Any("reason")],
             description="Set raider as kicked with a reason", access_level="moderator", sub_command="manage")
    def raid_kick_cmd(self, request, _, char: SenderObj, reason: str):
        if self.raid is None:
            return self.NO_RAID_RUNNING_RESPONSE

        main_id = self.alts_service.get_main(char.char_id).char_id
        in_raid = self.is_in_raid(main_id)

        if in_raid is not None:
            if not in_raid.is_active:
                return "<highlight>%s</highlight> is already set as inactive." % char.name

            in_raid.is_active = False
            in_raid.was_kicked = int(time.time())
            in_raid.was_kicked_reason = reason
            self.points_controller.add_log_entry(main_id, request.sender.char_id, f"Kicked from raid {self.raid.raid_name} with reason: {reason}")
            self.bot.send_private_message(char.char_id,
                                          f"You have been kicked from raid <highlight>{self.raid.raid_name}</highlight> with reason <highlight>{reason}</highlight>.",
                                          conn=request.conn)
            return "<highlight>%s</highlight> has been kicked from the raid with reason <highlight>%s</highlight>." % (char.name, reason)
        else:
            return "<highlight>%s</highlight> is not participating." % char.name

    @command(command="raid", params=[Options(["open", "unlock"])], description="Open raid for new participants",
             access_level="moderator", sub_command="manage")
    def raid_open_cmd(self, request, action):
        if not self.raid:
            return self.NO_RAID_RUNNING_RESPONSE

        if self.raid.is_open:
            return "Raid is already open."
        else:
            self.raid.is_open = True
            self.send_message("Raid has been opened by %s." % request.sender.name, request.conn)

    @command(command="raid", params=[Options(["close", "lock"])], description="Close raid for new participants",
             access_level="moderator", sub_command="manage")
    def raid_close_cmd(self, request, action):
        if not self.raid:
            return self.NO_RAID_RUNNING_RESPONSE

        if self.raid.is_open:
            self.raid.is_open = False
            self.send_message("Raid has been closed by %s." % request.sender.name, request.conn)
        else:
            return "Raid is already closed."

    @command(command="raid", params=[Options(["end", "save"]), NamedFlagParameters(["force"])], description="End raid, and log results",
             access_level="moderator", sub_command="manage")
    def raid_save_cmd(self, request, _, flag_params):
        if not self.raid:
            return self.NO_RAID_RUNNING_RESPONSE

        if not self.raid.added_points and not flag_params.force:
            blob = "You have not added any points for this raid. Are you sure you want to end this raid now? "
            blob += self.text.make_tellcmd("Yes", "raid end --force")
            return ChatBlob("End Raid Confirmation", blob)

        sql = "UPDATE raid_log SET raid_end = ? WHERE raid_id = ?"
        self.db.exec(sql, [int(time.time()), self.raid.raid_id])

        for raider in self.raid.raiders:
            sql = "INSERT INTO raid_log_participants (raid_id, raider_id, accumulated_points, left_raid, was_kicked, was_kicked_reason) VALUES (?,?,?,?,?,?)"
            self.db.exec(sql, [self.raid.raid_id, raider.active_id, raider.accumulated_points, raider.left_raid, raider.was_kicked, raider.was_kicked_reason])

        self.raid = None
        self.topic_controller.clear_topic()

        self.send_message("Raid saved and ended.", request.conn)

    @command(command="raid", params=[Const("history"), Int("raid_id")],
             description="Show log entry for raid",
             access_level="moderator", sub_command="manage")
    def raid_history_detail_cmd(self, request, _, raid_id: int):
        sql = "SELECT r.*, p.*, p2.name AS raider_name FROM raid_log r " \
              "LEFT JOIN raid_log_participants p ON r.raid_id = p.raid_id " \
              "LEFT JOIN player p2 ON p.raider_id = p2.char_id " \
              "WHERE r.raid_id = ? ORDER BY p.accumulated_points DESC"
        log_entry = self.db.query(sql, [raid_id])

        if not log_entry:
            return "No such log entry."

        blob = "Raid name: <highlight>%s</highlight>\n" % log_entry[0].raid_name
        blob += "Started by: <highlight>%s</highlight>\n" % self.character_service.resolve_char_to_name(log_entry[0].started_by)
        blob += "Start time: <highlight>%s</highlight>\n" % self.util.format_datetime(log_entry[0].raid_start)
        blob += "End time: <highlight>%s</highlight>\n" % self.util.format_datetime(log_entry[0].raid_end)
        blob += "Run time: <highlight>%s</highlight>\n" % self.util.time_to_readable(log_entry[0].raid_end - log_entry[0].raid_start)

        pts_sum = self.db.query_single("SELECT COALESCE(SUM(p.accumulated_points), 0) AS sum FROM raid_log_participants p WHERE p.raid_id = ?", [raid_id]).sum
        blob += "Total points: <highlight>%d</highlight>\n\n" % pts_sum

        blob += "<header2>Participants</header2>\n"
        for raider in log_entry:
            main_info = self.alts_service.get_main(raider.raider_id)
            if main_info.char_id != raider.raider_id:
                alt_link_text = "Alt of %s" % main_info.name
            else:
                alt_link_text = "Alts"
            alt_link = self.text.make_tellcmd(alt_link_text, "alts %s" % raider.raider_name)
            account_link = self.text.make_tellcmd("Account", "account %s" % raider.raider_name)
            blob += "%s - %d points earned [%s] [%s]\n" % (raider.raider_name, raider.accumulated_points, account_link, alt_link)

            if raider.left_raid:
                blob += "Left raid: %s\n" % self.util.format_datetime(raider.left_raid)

            if raider.was_kicked:
                blob += "Was kicked: %s\n" % self.util.format_datetime(raider.was_kicked)

            if raider.was_kicked_reason:
                blob += "Kick reason: %s\n" % raider.was_kicked_reason

            blob += "\n"

        return ChatBlob("Raid: %s" % log_entry[0].raid_name, blob)

    @command(command="raid", params=[Const("history")], description="Show a list of recent raids",
             access_level="member")
    def raid_history_cmd(self, request, _):
        sql = "SELECT * FROM raid_log ORDER BY raid_end DESC LIMIT 30"
        raids = self.db.query(sql)

        blob = ""
        for raid in raids:
            participant_link = self.text.make_tellcmd("Detail", "raid history %d" % raid.raid_id)
            timestamp = self.util.format_datetime(raid.raid_start)
            leader_name = self.character_service.resolve_char_to_name(raid.started_by)
            blob += "[%d] [%s] <highlight>%s</highlight> started by <highlight>%s</highlight> [%s]\n" % (raid.raid_id, timestamp, raid.raid_name, leader_name, participant_link)

        return ChatBlob("Raid History (%d)" % len(raids), blob)

    @command(command="raid", params=[Const("announce"), Any("message", is_optional=True)], access_level="moderator", sub_command="manage",
             description="Announce the current raid to members")
    def raid_announce_cmd(self, request, _, message):
        if not self.raid:
            return self.NO_RAID_RUNNING_RESPONSE

        if not self.bot.mass_message_queue:
            return "Could not announce raid since bot does not have mass messaging capabilities."

        join_link = self.text.paginate_single(ChatBlob("Click here", self.get_raid_join_blob()), request.conn)

        msg = "<highlight>%s</highlight> has started the raid <highlight>%s</highlight>. " % (self.raid.started_by.name, self.raid.raid_name)
        msg += "%s to join." % join_link
        if message:
            msg += " " + message

        count = 0
        for member in self.member_controller.get_all_members():
            main = self.alts_service.get_main(member.char_id)
            if self.buddy_service.is_online(member.char_id) and not self.is_in_raid(main.char_id):
                count += 1
                self.bot.send_mass_message(member.char_id, msg, conn=request.conn)

        return f"Raid announcement is sending to <highlight>{count}</highlight> online members."

    def is_in_raid(self, main_id: int):
        if self.raid is None:
            return None

        for raider in self.raid.raiders:
            if raider.main_id == main_id:
                return raider

    def get_raid_join_blob(self):
        return "<header2>1. Join the raid</header2>\n" \
               "To join the current raid <highlight>%s</highlight>, send the following tell to <myname>\n" \
               "<tab><tab><a href='chatcmd:///tell <myname> <symbol>raid join'>/tell <myname> raid " \
               "join</a>\n\n<header2>2. Enable LFT</header2>\nWhen you have joined the raid, go lft " \
               "with \"<myname>\" as description\n<tab><tab><a href='chatcmd:///lft <myname>'>/lft <myname></a>\n\n" \
               "<header2>3. Announce</header2>\nYou could announce to the raid leader, that you have enabled " \
               "LFT\n<tab><tab><a href='chatcmd:///group <myname> I am on lft'>Announce</a> that you have enabled " \
               "lft\n\n<header2>4. Rally with yer mateys</header2>\nFinally, move towards the starting location of " \
               "the raid.\n<highlight>Ask for help</highlight> if you're in doubt of where to go." % self.raid.raid_name

    def send_message(self, msg, conn):
        # TODO remove once messagehub can handle ChatBlobs
        pages = self.bot.get_text_pages(msg, conn, self.setting_service.get("private_message_max_page_length").get_value())
        for page in pages:
            self.message_hub_service.send_message(self.MESSAGE_SOURCE, None, None, page)
Ejemplo n.º 25
0
class AdminController:
    def __init__(self):
        pass

    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.admin_service = registry.get_instance("admin_service")
        self.pork_service = registry.get_instance("pork_service")
        self.command_alias_service = registry.get_instance(
            "command_alias_service")
        self.buddy_service = registry.get_instance("buddy_service")
        self.ts: TranslationService = registry.get_instance(
            "translation_service")
        self.getresp = self.ts.get_response

    def start(self):
        self.command_alias_service.add_alias("adminlist", "admin")
        self.command_alias_service.add_alias("admins", "admin")
        self.ts.register_translation("module/admin", self.load_admin_msg)

    def load_admin_msg(self):
        with open("modules/core/admin/admin.msg", mode="r",
                  encoding="UTF-8") as f:
            return hjson.load(f)

    @command(command="admin",
             params=[],
             access_level="all",
             description="Show the admin list")
    def admin_list_cmd(self, request):
        admins = self.admin_service.get_all()

        blob = ""
        current_access_level = ""
        for row in admins:
            if row.access_level != current_access_level:
                blob += "\n<header2>%s</header2>\n" % row.access_level.capitalize(
                )
                current_access_level = row.access_level

            blob += row.name
            if self.buddy_service.is_online(row.char_id):
                blob += " [<green>Online</green>]"
            blob += "\n"

        return ChatBlob("Admin List (%d)" % len(admins), blob)

    @command(command="admin",
             params=[Const("add"), Character("character")],
             access_level="superadmin",
             description="Add an admin",
             sub_command="modify")
    def admin_add_cmd(self, request, _, char):
        if not char.char_id:
            return self.getresp("global", "char_not_found",
                                {"char": char.name})

        if self.admin_service.add(char.char_id, AdminService.ADMIN):
            return self.getresp("module/admin", "add_success", {
                "char": char.name,
                "rank": AdminService.ADMIN
            })
        else:
            return self.getresp("module/admin", "add_fail", {
                "char": char.name,
                "rank": AdminService.ADMIN
            })

    @command(command="admin",
             params=[Options(["remove", "rem"]),
                     Character("character")],
             access_level="superadmin",
             description="Remove an admin",
             sub_command="modify")
    def admin_remove_cmd(self, request, _, char):
        if not char.char_id:
            return self.getresp("global", "char_not_found",
                                {"char": char.name})

        if self.admin_service.remove(char.char_id):
            return self.getresp("module/admin", "rem_success", {
                "char": char.name,
                "rank": AdminService.ADMIN
            })
        else:
            return self.getresp("module/admin", "rem_fail", {
                "char": char.name,
                "rank": AdminService.ADMIN
            })

    @command(command="moderator",
             params=[Const("add"), Character("character")],
             access_level="admin",
             description="Add a moderator",
             sub_command="modify")
    def moderator_add_cmd(self, request, _, char):
        if not char.char_id:
            return self.getresp("global", "char_not_found",
                                {"char": char.name})

        if self.admin_service.add(char.char_id, AdminService.MODERATOR):
            return self.getresp("module/admin", "add_success", {
                "char": char.name,
                "rank": AdminService.MODERATOR
            })
        else:
            return self.getresp("module/admin", "add_fail", {
                "char": char.name,
                "rank": AdminService.MODERATOR
            })

    @command(command="moderator",
             params=[Options(["remove", "rem"]),
                     Character("character")],
             access_level="admin",
             description="Remove a moderator",
             sub_command="modify")
    def moderator_remove_cmd(self, request, _, char):
        if not char.char_id:
            return self.getresp("global", "char_not_found",
                                {"char": char.name})

        if self.admin_service.remove(char.char_id):
            return self.getresp("module/admin", "rem_success", {
                "char": char.name,
                "rank": AdminService.MODERATOR
            })
        else:
            return self.getresp("module/admin", "rem_fail", {
                "char": char.name,
                "rank": AdminService.MODERATOR
            })
Ejemplo n.º 26
0
class LeaderController:
    NOT_LEADER_MSG = "Error! You must be raid leader, or have higher access " \
                     "level than the raid leader to use this command."

    def __init__(self):
        self.leader = None
        self.last_activity = None
        self.echo = False

    def inject(self, registry):
        self.db: DB = registry.get_instance("db")
        self.text: Text = registry.get_instance("text")
        self.access_service: AccessService = registry.get_instance(
            "access_service")
        self.character_service: CharacterService = registry.get_instance(
            "character_service")
        self.bot: Tyrbot = registry.get_instance("bot")
        self.setting_service: SettingService = registry.get_instance(
            "setting_service")

    @setting(
        name="leader_echo_color",
        value="#00FF00",
        description="Color with which the leader's messages will be echoed with"
    )
    def leader_echo_color(self):
        return ColorSettingType()

    @setting(name="leader_auto_echo",
             value=True,
             description=
             "If turned on, when someone assume the leader role, leader echo "
             "will automatically be activated for said person")
    def leader_auto_echo(self):
        return BooleanSettingType()

    @command(command="leader",
             params=[],
             access_level="all",
             description="Show the current raid leader")
    def leader_show_command(self, _):
        if self.leader:
            return "The current raid leader is <highlight>%s<end>." % self.leader.name
        else:
            return "There is no current raid leader. Use <highlight><symbol>leader set<end> to become the raid leader."

    @command(
        command="leader",
        params=[Const("echo"), Options(["on", "off"])],
        access_level="all",
        description=
        "Echo whatever the current leader types in channel, in a distinctive color"
    )
    def leader_echo_command(self, request, _2, switch_to):
        if self.leader:
            if self.can_use_command(request.sender.char_id):
                self.echo = switch_to == "on"
                return "Leader echo for <highlight>%s<end> has been turned <highlight>%s<end>." % \
                       (self.leader.name, switch_to)
            else:
                return "Insufficient access level."
        elif self.leader is None and switch_to == "on":
            return "No current leader set, can't turn on leader echo."

    @command(command="leader",
             params=[Const("echo")],
             access_level="all",
             description="See the current status for leader echoing")
    def leader_echo_status_command(self, _1, _2):
        if self.leader:
            on_off = "on" if self.echo else "off"
            return "<highlight>%s<end> is set as leader, leader echo is <highlight>%s<end>" % \
                   (self.leader.name, on_off)
        return "No current leader set."

    @command(command="leader",
             params=[Const("clear")],
             access_level="all",
             description="Clear the current raid leader")
    def leader_clear_command(self, request, _):
        return self.set_raid_leader(request.sender, None)

    @command(command="leader",
             params=[Const("set")],
             access_level="all",
             description="Set (or unset) yourself as raid leader")
    def leader_set_self_command(self, request, _):
        return self.set_raid_leader(request.sender, request.sender)

    @command(command="leader",
             params=[Const("set", is_optional=True),
                     Character("character")],
             access_level="all",
             description="Set another character as raid leader")
    def leader_set_other_command(self, request, _, char):
        if not char.char_id:
            return "Could not find <highlight>%s<end>." % char.name

        return self.set_raid_leader(request.sender, char)

    @timerevent(
        budatime="1h",
        description=
        "Remove raid leader if raid leader hasn't been active for more than 1 hour"
    )
    def leader_auto_remove(self, _1, _2):
        if self.last_activity:
            if self.last_activity - int(time.time()) > 3600:
                self.leader = None
                self.last_activity = None
                self.echo = False

                self.bot.send_private_channel_message(
                    "Raid leader has been automatically "
                    "cleared because of inactivity.")
                self.bot.send_org_message(
                    "Raid leader has been automatically cleared because of inactivity."
                )

    @event(PrivateChannelService.LEFT_PRIVATE_CHANNEL_EVENT,
           "Remove raid leader if raid leader leaves private channel")
    def leader_remove_on_leave_private(self, _, event_data):
        if self.leader:
            if self.leader.char_id == event_data.char_id:
                self.leader = None
                self.last_activity = None
                self.echo = False
                self.bot.send_private_channel_message(
                    "%s left private channel, and has been cleared as raid leader."
                    % self.character_service.resolve_char_to_name(
                        event_data.char_id))

    @event(OrgMemberController.ORG_MEMBER_LOGOFF_EVENT,
           "Remove raid leader if raid leader logs off")
    def leader_remove_on_logoff(self, _, event_data):
        if self.leader:
            if self.leader.char_id == event_data.char_id:
                self.leader = None
                self.last_activity = None
                self.echo = False
                self.bot.send_org_message(
                    "%s has logged off, and has been cleared as raid leader." %
                    self.character_service.resolve_char_to_name(
                        event_data.char_id))

    @event(PrivateChannelService.PRIVATE_CHANNEL_MESSAGE_EVENT,
           "Echo leader messages from private channel",
           is_hidden=True)
    def leader_echo_private_event(self, _, event_data):
        if self.leader and self.echo:
            if self.leader.char_id == event_data.char_id:
                if self.setting_service.get(
                        "symbol").get_value() != event_data.message[0]:
                    self.leader_echo(event_data.char_id, event_data.message,
                                     "priv")

    @event(PublicChannelService.ORG_CHANNEL_MESSAGE_EVENT,
           "Echo leader messages from org channel",
           is_hidden=True)
    def leader_echo_org_event(self, _, event_data):
        if self.leader and self.echo:
            if self.leader.char_id == event_data.char_id:
                if self.setting_service.get(
                        "symbol").get_value() != event_data.message[0]:
                    self.leader_echo(event_data.char_id, event_data.message,
                                     "org")

    def leader_echo(self, char_id, message, channel):
        sender = self.character_service.resolve_char_to_name(char_id)
        color = self.setting_service.get("leader_echo_color").get_value()

        if channel == "org":
            self.bot.send_org_message("%s: <font color=%s>%s" %
                                      (sender, color, message))
        if channel == "priv":
            self.bot.send_private_channel_message("%s: <font color=%s>%s" %
                                                  (sender, color, message))

        self.activity_done()

    def activity_done(self):
        self.last_activity = int(time.time())

    def can_use_command(self, char_id):
        if not self.leader or self.access_service.has_sufficient_access_level(
                char_id, self.leader.char_id):
            self.activity_done()
            return True

        return False

    def set_raid_leader(self, sender, set_to):
        if set_to is None:
            if not self.leader:
                return "There is no current raid leader."
            elif self.leader.char_id == sender.char_id:
                self.leader = None
                self.echo = False
                return "You have been removed as raid leader."
            elif self.can_use_command(sender.char_id):
                old_leader = self.leader
                self.leader = None
                self.echo = False
                self.bot.send_private_message(
                    old_leader.char_id,
                    "You have been removed as raid leader by <highlight>%s<end>."
                    % sender.name)
                return "You have removed <highlight>%s<end> as raid leader." % old_leader.name
            else:
                return "You do not have a high enough access level to remove raid leader from <highlight>%s<end>." % \
                       self.leader.name
        elif sender.char_id == set_to.char_id:
            if not self.leader:
                self.leader = sender
                self.echo = self.setting_service.get(
                    "leader_auto_echo").get_value()
                reply = "You have been set as raid leader."
                if self.echo:
                    reply += " Leader echo is <green>enabled<end>."
                return reply
            elif self.leader.char_id == sender.char_id:
                self.leader = None
                self.echo = False
                return "You have been removed as raid leader."
            elif self.can_use_command(sender.char_id):
                old_leader = self.leader
                self.leader = sender
                self.echo = self.setting_service.get(
                    "leader_auto_echo").get_value()
                reply = "<highlight>%s<end> has taken raid leader from you." % sender.name
                if self.echo:
                    reply += " Leader echo is <green>enabled<end>."
                self.bot.send_private_message(old_leader.char_id, reply)
                reply = "You have taken raid leader from <highlight>%s<end>." % old_leader.name
                if self.echo:
                    reply += " Leader echo is <green>enabled<end>."
                return reply
            else:
                return "You do not have a high enough access level to take raid leader from <highlight>%s<end>." % \
                       self.leader.name
        else:
            if self.can_use_command(sender.char_id):
                self.leader = set_to
                self.echo = self.setting_service.get(
                    "leader_auto_echo").get_value()
                reply = "<highlight>%s<end> has set you as raid leader." % sender.name
                if self.echo:
                    reply += " Leader echo is <green>enabled<end>."
                self.bot.send_private_message(set_to.char_id, reply)
                reply = "<highlight>%s<end> has been set as raid leader by %s." % (
                    set_to.name, sender.name)
                if self.echo:
                    reply += " Leader echo is <green>enabled<end>."
                return reply
            else:
                return "You do not have a high enough access level to take raid leader from <highlight>%s<end>." % \
                       self.leader.name
Ejemplo n.º 27
0
class LastSeenController:
    def __init__(self):
        self.logger = Logger(__name__)

    def inject(self, registry):
        self.db = registry.get_instance("db")
        self.util = registry.get_instance("util")
        self.buddy_service = registry.get_instance("buddy_service")

    def start(self):
        self.db.exec("CREATE TABLE IF NOT EXISTS last_seen (char_id INT NOT NULL PRIMARY KEY, "
                     "dt INT NOT NULL DEFAULT 0)")

    @command(command="lastseen", params=[Character("character"), NamedFlagParameters(["show_all"])], access_level="org_member",
             description="Show the last time an org member was online (on any alt)")
    def lastseen_cmd(self, request, char, flag_params):
        sql = "SELECT p.*, a.group_id, a.status, l.dt FROM player p " \
              "LEFT JOIN alts a ON p.char_id = a.char_id " \
              "LEFT JOIN last_seen l ON p.char_id = l.char_id " \
              "WHERE p.char_id = ? OR a.group_id = (SELECT group_id FROM alts WHERE char_id = ?) " \
              "ORDER BY l.dt DESC, p.name ASC"

        data = self.db.query(sql, [char.char_id, char.char_id])
        blob = ""
        if len(data) == 0:
            return f"No lastseen information for <highlight>{char.name}</highlight> has been recorded."
        else:
            if flag_params.show_all:
                for row in data:
                    blob += f"<highlight>{row.name}</highlight>"
                    if row.dt:
                        blob += " last seen at " + self.util.format_datetime(row.dt)
                    else:
                        blob += " unknown"
                    blob += "\n\n"

                return ChatBlob("Last Seen Info for %s (%d)" % (char.name, len(data)), blob)
            else:
                online_alts = list(filter(lambda x: self.buddy_service.is_online(x.char_id), data))
                if online_alts:
                    online_alts_str = ", ".join(map(lambda x: f"<highlight>{x.name}</highlight>", online_alts))

                    return f"<highlight>{char.name}</highlight> is <green>online</green> with: {online_alts_str}."
                else:
                    alt_name = data[0].name
                    if data[0].dt:
                        last_seen = self.util.format_datetime(data[0].dt)
                        return f"<highlight>{char.name}</highlight> was last seen online with <highlight>{alt_name}</highlight> at <highlight>{last_seen}</highlight>."
                    else:
                        return f"No lastseen information for <highlight>{char.name}</highlight> has been recorded."

    @event(event_type=BuddyService.BUDDY_LOGON_EVENT, description="Record last seen info")
    def handle_buddy_logon_event(self, event_type, event_data):
        self.update_last_seen(event_data.char_id)

    def update_last_seen(self, char_id):
        t = int(time.time())
        if self.db.exec("UPDATE last_seen SET dt = ? WHERE char_id = ?", [t, char_id]) == 0:
            self.db.exec("INSERT IGNORE INTO last_seen (char_id, dt) VALUES (?, ?)", [char_id, t])

    def get_last_seen(self, char_id):
        return self.db.query_single("SELECT dt FROM last_seen WHERE char_id = ?", [char_id])
Ejemplo n.º 28
0
class PointsController:
    def __init__(self):
        pass

    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.db: DB = registry.get_instance("db")
        self.text: Text = registry.get_instance("text")
        self.character_service: CharacterService = registry.get_instance("character_service")
        self.util: Util = registry.get_instance("util")
        self.setting_service: SettingService = registry.get_instance("setting_service")
        self.alts_service: AltsService = registry.get_instance("alts_service")

    def start(self):
        self.db.exec("CREATE TABLE IF NOT EXISTS points (char_id BIGINT PRIMARY KEY, points INT DEFAULT 0, created_at INT NOT NULL, "
                     "disabled SMALLINT DEFAULT 0)")
        self.db.exec("CREATE TABLE IF NOT EXISTS points_log (log_id INT PRIMARY KEY, char_id BIGINT NOT NULL, audit INT NOT NULL, "
                     "leader_id BIGINT NOT NULL, reason VARCHAR(255), created_at INT NOT NULL)")
        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))")

        if self.db.query_single("SELECT COUNT(*) AS count FROM points_presets").count < 1:
            # Populate with pre-made presets if empty
            presets = ["s13", "s28", "s35", "s42", "zodiac", "zod",
                       "tnh", "beast", "12m", "tara", "pvp", "towers",
                       "wipe", "clanwipe", "clan", "omniwipe", "omni",
                       "bonus", "early"]
            sql = "INSERT INTO points_presets (name) VALUES (?)"
            for preset in presets:
                self.db.exec(sql, [preset])

    @command(command="account", params=[Const("create"), Character("char")], access_level="moderator",
             description="Create a new account for given character name", sub_command="modify")
    def bank_create_cmd(self, request, _, char: SenderObj):
        alts_info = self.alts_service.get_alts(char.char_id)

        for alt in alts_info:
            sql = "SELECT char_id, disabled FROM points WHERE char_id = ? LIMIT 1"
            row = self.db.query_single(sql, [alt.char_id])

            if row:
                was_disabled = False

                if row.disabled == 1:
                    if self.db.exec("UPDATE points SET disabled = 0 WHERE char_id = ?", [alt.char_id]):
                        was_disabled = True

                if alt.char_id == char.char_id:
                    if was_disabled:
                        self.add_log_entry(alt.char_id, request.sender.char_id, "Account was re-enabled by %s" % request.sender.name)
                        return "<highlight>%s</highlight>'s account has been re-enabled." % char.name
                    else:
                        return "<highlight>%s</highlight> already has an account." % char.name
                else:
                    if was_disabled:
                        self.add_log_entry(alt.char_id, request.sender.char_id, "Account was re-enabled by %s" % request.sender.name)
                        return "<highlight>%s</highlight>'s (%s) account has been re-enabled." % (char.name, alt.name)
                    else:
                        return "<highlight>%s</highlight> (%s) already has an account." % (char.name, alt.name)

        main_info = alts_info[0]
        changed_to_main = main_info.char_id == char.char_id

        self.create_account(main_info.char_id, request.sender)

        name_reference = "%s (%s)" % (char.name, main_info.name) if changed_to_main else char.name
        return "A new account has been created for <highlight>%s</highlight>." % name_reference

    @command(command="account", params=[Const("close"), Character("char")], access_level="moderator",
             description="Close the account for given character name", sub_command="modify")
    def close_account_cmd(self, request, _, char: SenderObj):
        main = self.alts_service.get_main(char.char_id)

        sql = "UPDATE points SET disabled = 1 WHERE char_id = ?"
        if self.db.exec(sql, [main.char_id]) > 0:
            reason = f"Account was closed by {request.sender.name}"
            self.add_log_entry(main.char_id, request.sender.char_id, reason)
            name_reference = "%s (%s)" % (char.name, main.name) if main.char_id != char.char_id else char.name
            return f"<highlight>{name_reference}</highlight> has had their account disabled. Logs have been preserved."
        else:
            return "<highlight>%s</highlight> does not have an open account." % char.name

    @command(command="account", params=[Const("history"), Int("log_id")], access_level="moderator",
             description="Look up specific account history record", sub_command="modify")
    def account_history_cmd(self, request, _, log_id: int):
        log_entry = self.db.query_single("SELECT log_id, char_id, audit, leader_id, reason, created_at FROM points_log WHERE log_id = ?", [log_id])

        if not log_entry:
            return "No account history record with given ID <highlight>%d</highlight>." % log_id

        char_name = self.character_service.resolve_char_to_name(log_entry.char_id)
        leader_name = self.character_service.resolve_char_to_name(log_entry.leader_id)

        blob = f"ID: <highlight>{log_entry.log_id}</highlight>\n"
        blob += f"Account: <highlight>{char_name}</highlight>\n"
        blob += f"Action by: <highlight>{leader_name}</highlight>\n"
        blob += "Type: <highlight>%s</highlight>\n" % ("Management" if log_entry.audit == 0 else "Altering of points")
        blob += f"Reason: <highlight>{log_entry.reason}</highlight>\n"
        blob += f"Audit: <highlight>{log_entry.audit}</highlight>\n"
        action_links = None
        if log_entry.audit == 0:
            if "closed" in log_entry.reason:
                action_links = self.text.make_tellcmd("Open the account", "account create %s" % char_name)
            elif "re-enabled" in log_entry.reason:
                action_links = self.text.make_tellcmd("Close the account", "account close %s" % char_name)
        else:
            reason = f"Points from event ({log_id}) have been retracted"
            if log_entry.audit < 0:
                action_links = self.text.make_tellcmd("Retract", f"account add {char_name} {-log_entry.audit} {reason}")
            else:
                action_links = self.text.make_tellcmd("Retract", f"account rem {char_name} {log_entry.audit} {reason}")

        blob += "Actions available: [%s]\n" % (action_links if action_links is not None else "No actions available")

        return ChatBlob(f"Account History Record ({log_id})", blob)

    @command(command="account", params=[Const("add"), Character("char"), Int("amount"), Any("reason")], access_level="moderator",
             description="Add points to an account", sub_command="modify")
    def account_add_cmd(self, request, _, char: SenderObj, amount: int, reason: str):
        main = self.alts_service.get_main(char.char_id)
        row = self.get_account(main.char_id, request.conn)

        if not row:
            return f"<highlight>{char.name}</highlight> does not have an account."

        if row.disabled == 1:
            return f"Account for <highlight>{char.name}</highlight> is disabled and cannot be altered."

        self.alter_points(main.char_id, request.sender.char_id, reason, amount)

        return f"<highlight>{char.name}</highlight> has had <highlight>{amount}</highlight> points added to their account."

    @command(command="account", params=[Options(["rem", "remove"]), Character("char"), Int("amount"), Any("reason")], access_level="moderator",
             description="Remove points from an account", sub_command="modify")
    def account_remove_cmd(self, request, _, char: SenderObj, amount: int, reason: str):
        main = self.alts_service.get_main(char.char_id)
        row = self.get_account(main.char_id, request.conn)

        if not row:
            return f"<highlight>{char.name}</highlight> does not have an account."

        if row.disabled == 1:
            return f"Account for <highlight>{char.name}</highlight> is disabled and cannot be altered."

        if amount > row.points:
            return f"<highlight>{char.name}</highlight> only has <highlight>{row.points}</highlight> points."

        self.alter_points(main.char_id, request.sender.char_id, reason, -amount)

        return f"<highlight>{char.name}</highlight> has had <highlight>{amount}</highlight> points removed from their account."

    @command(command="account", params=[NamedParameters(["page"])], access_level="all",
             description="Look up your account")
    def account_self_cmd(self, request, named_params):
        return self.get_account_display(request.sender, named_params.page)

    @command(command="account", params=[Character("char"), NamedParameters(["page"])], access_level="moderator",
             description="Look up account of another char", sub_command="modify")
    def account_other_cmd(self, request, char: SenderObj, named_params):
        return self.get_account_display(char, named_params.page)

    @command(command="raid", params=[Const("presets"), Const("add"), Any("name"), Int("points")], access_level="admin",
             description="Add new points preset", sub_command="manage_points")
    def presets_add_cmd(self, request, _1, _2, name: str, points: int):
        count = self.db.query_single("SELECT COUNT(*) AS count FROM points_presets WHERE name = ?", [name]).count

        if count > 0:
            return "A preset already exists with the name <highlight>%s</highlight>." % name

        sql = "INSERT INTO points_presets (name, points) VALUES (?,?)"
        self.db.exec(sql, [name, points])
        return "A preset with the name <highlight>%s</highlight> was added, worth <green>%d</green> points." % (name, points)

    @command(command="raid", params=[Const("presets"), Const("rem"), Int("preset_id")], access_level="admin",
             description="Delete preset", sub_command="manage_points")
    def presets_rem_cmd(self, request, _1, _2, preset_id: int):
        if self.db.exec("DELETE FROM points_presets WHERE preset_id = ?", [preset_id]) > 0:
            return "Successfully removed preset with ID <highlight>%d</highlight>." % preset_id
        else:
            return "No preset with given ID <highlight>%d</highlight>." % preset_id

    @command(command="raid", params=[Const("presets"), Const("alter"), Int("preset_id"), Int("new_points")], access_level="admin",
             description="Alter the points dished out by given preset", sub_command="manage_points")
    def presets_alter_cmd(self, request, _1, _2, preset_id: int, new_points: int):
        preset = self.db.query_single("SELECT * FROM points_presets WHERE preset_id = ?", [preset_id])

        if not preset:
            return f"Preset with ID <highlight>{preset_id}</highlight> does not exist."

        self.db.exec("UPDATE points_presets SET points = ? WHERE preset_id = ?", [new_points, preset_id])
        return "Successfully updated the preset, <highlight>%s</highlight>, to dish out " \
               "<green>%d</green> points instead of <red>%d</red>." % (preset.name, new_points, preset.points)

    @command(command="raid", params=[Options(["presets", "addpts"])], access_level="member",
             description="See list of points presets")
    def presets_cmd(self, request, _):
        return ChatBlob("Raid Points Presets", self.build_preset_list())

    def build_preset_list(self):
        presets = self.db.query("SELECT * FROM points_presets ORDER BY name ASC, points DESC")

        if presets:
            blob = ""

            for preset in presets:
                add_points_link = self.text.make_tellcmd("Add pts", "raid addpts %s" % preset.name)
                blob += "<highlight>%s</highlight> worth <green>%d</green> points %s [id: %d]\n\n" \
                        % (preset.name, preset.points, add_points_link, preset.preset_id)

            return blob

        return "No presets available. To add new presets use <highlight><symbol>presets add preset_name preset_points</highlight>."

    def add_log_entry(self, char_id: int, leader_id: int, reason: str, amount=0):
        sql = "INSERT INTO points_log (char_id, audit, leader_id, reason, created_at) VALUES (?,?,?,?,?)"
        return self.db.exec(sql, [char_id, amount, leader_id, reason, int(time.time())])

    def alter_points(self, char_id: int, leader_id: int, reason: str, amount: int):
        sql = "UPDATE points SET points = points + ? WHERE char_id = ?"
        self.db.exec(sql, [amount, char_id])

        self.add_log_entry(char_id, leader_id, reason, amount)

    def get_account(self, main_id, conn):
        sql = "SELECT p.char_id, p.points, p.disabled FROM points p WHERE p.char_id = ?"
        row = self.db.query_single(sql, [main_id])
        if not row:
            self.create_account(main_id, SenderObj(conn.get_char_id(),
                                                   conn.get_char_name(),
                                                   None))
            row = self.db.query_single(sql, [main_id])

        return row

    def create_account(self, main_id, sender):
        sql = "INSERT INTO points (char_id, points, created_at) VALUES (?,?,?)"
        self.db.exec(sql, [main_id, 0, int(time.time())])

        self.add_log_entry(main_id, sender.char_id, "Account opened by %s" % sender.name)

    def get_account_display(self, char: SenderObj, page):
        main = self.alts_service.get_main(char.char_id)
        if not main:
            return "Could not find character <highlight>%s</highlight>." % char.name

        page = int(page) if page else 1
        page_size = 20
        offset = (page - 1) * page_size

        points = self.db.query_single("SELECT points, disabled FROM points WHERE char_id = ?", [main.char_id])
        if not points:
            return "Could not find raid account for <highlight>%s</highlight>." % char.name

        alts_link = self.text.make_tellcmd("Alts", "alts %s" % main.name)
        blob = ""
        blob += "Account: %s [%s]\n" % (main.name, alts_link)
        blob += "Points: %d\n" % points.points
        blob += "Status: %s\n\n" % ("<green>Open</green>" if points.disabled == 0 else "<red>Disabled</red>")

        points_log = self.db.query("SELECT * FROM points_log WHERE char_id = ? ORDER BY created_at DESC LIMIT ?, ?",
                                   [main.char_id, offset, page_size])
        blob += "<header2>Account log</header2>\n"
        if points_log is None:
            blob += "No entries in log."
        else:
            for entry in points_log:
                if entry.audit > 0:
                    pts = "<green>+%d</green>" % entry.audit
                    blob += "<grey>[%s]</grey> %s points by <highlight>%s</highlight>; <orange>%s</orange>" \
                            % (self.util.format_datetime(entry.created_at), pts,
                               self.character_service.resolve_char_to_name(entry.leader_id), entry.reason)
                elif entry.audit < 0:
                    pts = "<red>-%d</red>" % (-1 * entry.audit)
                    blob += "<grey>[%s]</grey> %s points by <highlight>%s</highlight>; <orange>%s</orange>" \
                            % (self.util.format_datetime(entry.created_at), pts,
                               self.character_service.resolve_char_to_name(entry.leader_id),
                               entry.reason)
                else:
                    # If points is 0, then it's a general case log
                    blob += "<grey>[%s]</grey> <orange>%s</orange>" % (self.util.format_datetime(entry.created_at), entry.reason)

                log_entry_link = self.text.make_tellcmd(entry.log_id, f"account history {entry.log_id}")
                blob += " [%s]\n" % log_entry_link

        return ChatBlob("%s Account" % char.name, blob)
Ejemplo n.º 29
0
class UtilController:
    def inject(self, registry):
        self.bot = registry.get_instance("bot")
        self.db = registry.get_instance("db")
        self.util = registry.get_instance("util")
        self.command_service = registry.get_instance("command_service")
        self.buddy_service = registry.get_instance("buddy_service")
        self.access_service = registry.get_instance("access_service")
        self.event_service = registry.get_instance("event_service")
        self.public_channel_service = registry.get_instance(
            "public_channel_service")
        self.getresp = registry.get_instance(
            "translation_service").get_response

    @command(command="checkaccess",
             params=[Character("character", is_optional=True)],
             access_level="all",
             description="Check access level for a character")
    def checkaccess_cmd(self, request, char):
        char = char or request.sender

        if not char.char_id:
            return self.getresp("global", "char_not_found",
                                {"char": char.name})

        return self.getresp(
            "module/system", "check_access", {
                "char":
                char.name,
                "rank_main":
                char.access_level["label"],
                "rank_self":
                self.access_service.get_single_access_level(
                    char.char_id)["label"]
            })

    @command(command="macro",
             params=[Any("command1|command2|command3...")],
             access_level="all",
             description="Execute multiple commands at once")
    def macro_cmd(self, request, commands):
        commands = commands.split("|")
        for command_str in commands:
            self.command_service.process_command(
                self.command_service.trim_command_symbol(command_str),
                request.channel, request.sender.char_id, request.reply)

    @command(command="echo",
             params=[Any("message")],
             access_level="all",
             description="Echo back a message")
    def echo_cmd(self, request, message):
        return html.escape(message)

    @command(command="showcommand",
             params=[Character("character"),
                     Any("message")],
             access_level="admin",
             description="Show command output to another character")
    def showcommand_cmd(self, request, char, command_str):
        if not char.char_id:
            return self.getresp("global", "char_not_found",
                                {"char": char.name})

        self.bot.send_private_message(
            char.char_id,
            self.getresp("module/system", "show_output_target", {
                "sender": request.sender.name,
                "cmd": command_str
            }))

        self.command_service.process_command(
            self.command_service.trim_command_symbol(command_str),
            request.channel, request.sender.char_id,
            lambda msg: self.bot.send_private_message(char.char_id, msg))

        return self.getresp("module/system", "show_output_self", {
            "target": char.name,
            "cmd": command_str
        })

    @command(command="system",
             params=[],
             access_level="admin",
             description="Show system information")
    def system_cmd(self, request):
        pub_channels = ""
        event_types = ""
        access_levels = ""
        bots_connected = ""

        for _id, conn in self.bot.conns.items():
            bots_connected += f"{_id} - {conn.char_name} ({conn.char_id})\n"

        for channel_id, name in self.public_channel_service.get_all_public_channels(
        ).items():
            pub_channels += "%s - <highlight>%d</highlight>\n" % (name,
                                                                  channel_id)

        for event_type in self.event_service.get_event_types():
            event_types += "%s\n" % event_type

        for access_level in self.access_service.get_access_levels():
            access_levels += "%s (%d)\n" % (access_level["label"],
                                            access_level["level"])

        blob = self.getresp(
            "module/system", "status_blob", {
                "bot_ver":
                self.bot.version,
                "os_ver":
                platform.system() + " " + platform.release(),
                "python_ver":
                str(sys.version_info.major) + "." +
                str(sys.version_info.minor) + "." +
                str(sys.version_info.micro) + "." +
                sys.version_info.releaselevel,
                "db_type":
                self.db.type,
                "mem_usage":
                self.util.format_number(
                    psutil.Process(os.getpid()).memory_info().rss / 1024),
                "superadmin":
                self.bot.superadmin,
                "bl_used":
                self.buddy_service.get_buddy_list_size(),
                "bl_size":
                self.buddy_service.buddy_list_size,
                "uptime":
                self.util.time_to_readable(
                    int(time.time()) - self.bot.start_time, max_levels=None),
                "dim":
                self.bot.dimension,
                "org_id":
                self.public_channel_service.org_id,
                "org_name":
                self.public_channel_service.org_name,
                "bots_connected":
                bots_connected,
                "pub_channels":
                pub_channels,
                "event_types":
                event_types,
                "access_levels":
                access_levels
            })

        return ChatBlob(self.getresp("module/system", "status_title"), blob)

    @command(
        command="htmldecode",
        params=[Any("command")],
        access_level="all",
        description=
        "Decode html entities from a command before passing to the bot for execution"
    )
    def htmldecode_cmd(self, request, command_str):
        self.command_service.process_command(html.unescape(command_str),
                                             request.channel,
                                             request.sender.char_id,
                                             request.reply)
Ejemplo n.º 30
0
class LeaderController:
    NOT_LEADER_MSG = "Error! You must be leader, or have higher access level than the leader to use this command."

    def __init__(self):
        self.leader = None
        self.last_activity = None

    def inject(self, registry):
        self.db: DB = registry.get_instance("db")
        self.text: Text = registry.get_instance("text")
        self.access_service = registry.get_instance("access_service")
        self.character_service = registry.get_instance("character_service")
        self.bot: Tyrbot = registry.get_instance("bot")

    @command(command="leader",
             params=[],
             access_level="all",
             description="Show the current raidleader")
    def leader_show_command(self, request):
        if self.leader:
            return "The current raidleader is <highlight>%s<end>." % self.leader.name
        else:
            return "There is no current raidleader."

    @command(command="leader",
             params=[Const("set")],
             access_level="all",
             description="Set (or unset) yourself as raidleader")
    def leader_set_self_command(self, request, _):
        if not self.leader:
            self.leader = request.sender
            return "You have been set as raidleader."
        elif self.leader.char_id == request.sender.char_id:
            self.leader = None
            return "You have been removed as raidleader."
        elif self.access_service.has_sufficient_access_level(
                request.sender.char_id, self.leader.char_id):
            old_leader = self.leader
            self.leader = request.sender
            return "You have taken leader from <highlight>%s<end>." % old_leader.name
        else:
            return "You do not have a high enough access level to take raidleader from <highlight>%s<end>." % self.leader.name

    @command(command="leader",
             params=[Const("set", is_optional=True),
                     Character("character")],
             access_level="all",
             description="Set another character as raidleader")
    def leader_set_other_command(self, request, _, char):
        if not char.char_id:
            return "Could not find <highlight>%s<end>." % char.name

        if not self.leader or self.access_service.has_sufficient_access_level(
                request.sender.char_id, self.leader.char_id):
            self.leader = char
            return "<highlight>%s<end> has been set as raidleader." % char.name
        else:
            return "You do not have a high enough access level to take raidleader from <highlight>%s<end>." % self.leader.name

    @timerevent(
        budatime="1h",
        description=
        "Remove leader if leader hasn't been active for more than 1 hour")
    def leader_auto_remove(self, event_type, event_data):
        if self.last_activity:
            if self.last_activity - int(time.time()) > 3600:
                self.leader = None
                self.last_activity = None

                self.bot.send_private_channel_message(
                    "Leader has been automatically cleared because of inactivity."
                )
                self.bot.send_org_message(
                    "Leader has been automatically cleared because of inactivity."
                )

    @event(PrivateChannelService.LEFT_PRIVATE_CHANNEL_EVENT,
           "Remove leader if leader leaves private channel")
    def leader_remove_on_leave_private(self, event_type, event_data):
        if self.leader and self.leader.char_id == event_data.char_id:
            self.leader = None
            self.last_activity = None
            self.bot.send_private_channel_message(
                "%s left private channel, and has been cleared as leader." %
                self.character_service.resolve_char_to_name(
                    event_data.char_id))

    @event(OrgMemberController.ORG_MEMBER_LOGOFF_EVENT,
           "Remove leader if leader logs off")
    def leader_remove_on_logoff(self, event_type, event_data):
        if self.leader and self.leader.char_id == event_data.char_id:
            self.leader = None
            self.last_activity = None
            self.bot.send_org_message(
                "%s has logged off, and has been cleared as leader." %
                self.character_service.resolve_char_to_name(
                    event_data.char_id))

    def activity_done(self):
        self.last_activity = int(time.time())

    def can_use_command(self, char_id):
        if not self.leader or self.access_service.has_sufficient_access_level(
                char_id, self.leader.char_id):
            self.activity_done()
            return True

        return False