import time from core.command_alias_service import CommandAliasService from core.command_param_types import Const, Character, Options from core.db import DB from core.decorators import instance, command, timerevent, event from core.lookup.character_service import CharacterService from core.private_channel_service import PrivateChannelService from core.setting_service import SettingService from core.setting_types import ColorSettingType, BooleanSettingType from core.text import Text from core.igncore import IgnCore from modules.core.accounting.services.access_service import AccessService @instance() 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: IgnCore = registry.get_instance("bot") self.setting_service: SettingService = registry.get_instance("setting_service") self.command_alias_service: CommandAliasService = registry.get_instance("command_alias_service") def pre_start(self): self.command_alias_service.add_alias("repeat", "leader echo") self.setting_service.register(self.module_name, "leader_echo_color", "#00FF00", ColorSettingType(), "Color with which the leader's messages will be echoed with") self.setting_service.register(self.module_name, "leader_auto_echo", True, BooleanSettingType(), "If turned on, when someone assume the leader role, " "leader echo will automatically be activated for said person") @command(command="leader", params=[], access_level="member", description="Show the current raid leader") def leader_show_command(self, _): if self.leader: return "The current raid leader is {leader}.".format(leader=self.leader.name) else: return "There is no current raid leader. Use leader set to become the raid leader." @command(command="leader", params=[Const("echo"), Options(["on", "off"])], access_level="leader", description="Echo whatever the current leader types in channel, in a distinctive color", sub_command="mgn") 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 f"Raidleader echo for {self.leader.name} has been turned " \ f"{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="leader", description="See the current status for leader echoing", sub_command="mgn") def leader_echo_status_command(self, _1, _2): if self.leader: on_off = "on" if self.echo else "off" return f"{self.leader.name} is set as leader, leader echo is {on_off}" else: return "No current leader set, echo is off." @command(command="leader", params=[Const("clear")], access_level="leader", description="Clear the current raid leader", sub_command="mgn") def leader_clear_command(self, request, _): return self.set_raid_leader(request.sender, None) @command(command="leader", params=[Const("set")], access_level="leader", sub_command="mgn", 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="leader", sub_command="mgn1", description="Set another character as raid leader") def leader_set_other_command(self, request, _, char): if not char.char_id: return "Could not find {player}.".format(player=char) return self.set_raid_leader(request.sender, char) @timerevent(budatime="15m", description="Remove raid leader if raid leader hasn't been active for more than 1 hour") def purge_leader_on_inactivity(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 cleared automatically " "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( f"{self.character_service.resolve_char_to_name(event_data.char_id)} " f"left private channel, and has been cleared as raid leader.") @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) def leader_echo(self, char_id, message): sender = self.character_service.resolve_char_to_name(char_id) color = self.setting_service.get("leader_echo_color").get_value() self.bot.send_private_channel_message(f"{sender}: {message}", fire_outgoing_event=False) 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, f"You have been removed as raid leader " f"by {sender.name}.") return f"You have removed {old_leader.name} as raid leader." else: return f"You do not have a high enough access level to remove raid leader " \ f"from {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 enabled." 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 = f"{sender.name} has taken raid leader from you." if self.echo: reply += " Leader echo is enabled." self.bot.send_private_message(old_leader.char_id, reply) reply = f"You have taken raid leader from {old_leader.name}." if self.echo: reply += " Leader echo is enabled." return reply else: return f"You do not have a high enough access level to " \ f"take raid leader from {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 = f"{sender.name} has set you as raid leader." if self.echo: reply += " Leader echo is enabled." self.bot.send_private_message(set_to.char_id, reply) reply = f"{set_to.name} has been set as raid leader by {sender.name}." if self.echo: reply += " Leader echo is enabled." return reply else: return f"You do not have a high enough access level to " \ f"take raid leader from {self.leader.name}."