import textwrap import time from datetime import datetime, timezone from core import command_request from core.buddy_service import BuddyService from core.command_alias_service import CommandAliasService from core.command_param_types import Any, Int, Const from core.db import DB from core.decorators import instance, command, timerevent from core.logger import Logger from core.lookup.pork_service import PorkService from core.private_channel_service import PrivateChannelService from core.setting_service import SettingService from core.text import Text from core.igncore import IgnCore from core.util import Util from modules.core.accounting.services.account_service import AccountService from modules.core.ban.ban_service import BanService # noinspection SqlResolve class Raid: leader = {} raid_desc = "[No description set]" raid_time = "[unknown]" min_level = 200 leader_rank = {} last_spam = 0 last_action = 0 bot = "" def __init__(self, leader, rank): self.leader = leader self.leader_rank = rank self.last_action = time.time() # noinspection SqlResolve,DuplicatedCode,PyAttributeOutsideInit @instance() class RaidController: profs = {"Meta-Physicist": 16308, "Adventurer": 84203, "Engineer": 16252, "Soldier": 16237, "Keeper": 84197, "Shade": 39290, "Fixer": 16300, "Agent": 16186, "Trader": 117993, "Doctor": 44235, "Enforcer": 100998, "Bureaucrat": 16341, "Martial Artist": 16196, "Nano-Technician": 16283} legal_bots = ["allianceraid", "aapf", "theallianz", "igncom", "ignraid"] def __init__(self): # noinspection PyTypeChecker self.raid: Raid = None def inject(self, registry): self.logger = Logger(__name__) self.bot: IgnCore = registry.get_instance("bot") self.db: DB = registry.get_instance("db") self.text: Text = registry.get_instance("text") self.util: Util = registry.get_instance("util") self.pork: PorkService = registry.get_instance("pork_service") self.org_pork: PorkService = registry.get_instance("org_pork_service") self.command_alias_service: CommandAliasService = registry.get_instance("command_alias_service") self.buddy_service: BuddyService = registry.get_instance("buddy_service") self.setting_service: SettingService = registry.get_instance("setting_service") self.ban: BanService = registry.get_instance("ban_service") self.private_channel_service: PrivateChannelService = registry.get_instance("private_channel_service") self.account_service: AccountService = registry.get_instance("account_service") @command(command="raid", params=[Const("desc"), Any("<description>")], description="Change the title of the Raid", access_level="leader") def raid_set_name(self, request: command_request, _, desc): if not self.raid: return "There's no raid running." if request.sender.access_level["level"] <= self.raid.leader_rank: self.raid.raid_desc = desc self.raid.last_action = time.time() return f"Successfully changed the raid description to {desc}" return f"Error! You cant do that. Your accesslevel must be equal or higher than " \ f"{self.raid.leader.name}'s rank." @command(command="raid", params=[Const("bot"), Any("<botname>")], description="Change the master Raidbot", access_level="leader") def raid_set_bot(self, request: command_request, _, bot): if not self.raid: return "There's no raid running." if request.sender.access_level["level"] <= self.raid.leader_rank: if bot in self.legal_bots: self.raid.bot = bot self.raid.last_action = time.time() return f"Successfully changed the raidbot to {bot}" else: return f"The bot {bot} is not whitelisted, you cannot use it as a raidbot. " return f"Error! You cant do that. Your accesslevel must be equal or higher than " \ f"{self.raid.leader.name}'s rank." @command(command="raid", params=[Const("level"), Int("<min_level>")], description="Change the minimal level of the Raid", access_level="leader") def raid_set_level(self, request: command_request, _, level): if not self.raid: return "There's no raid running." if request.sender.access_level["level"] <= self.raid.leader_rank: self.raid.min_level = level self.raid.last_action = time.time() return f"Successfully changed the minimum raid level to {level}" return f"Error! You cant do that. Your accesslevel must be equal or higher than " \ f"{self.raid.leader.name}'s rank." @command(command="raid", params=[Const("time"), Any("<stepping_time>")], description="Change the stepping time of the Raid", access_level="leader") def raid_set_time(self, request: command_request, _, step): if not self.raid: return "There's no raid running." if request.sender.access_level["level"] <= self.raid.leader_rank: self.raid.raid_time = step self.raid.last_action = time.time() return f"Successfully changed the stepping time to {step}" return f"Error! You cant do that. Your accesslevel must be equal or higher than " \ f"{self.raid.leader.name}'s rank." @command(command="raid", params=[Const("start")], description="Start a raid", access_level="leader") def raid_start(self, request: command_request, _): if self.raid: return "There's already a raid running." self.raid = Raid(request.sender, request.sender.access_level["level"]) # after I saw myself sending raid invites with the wrong bot reference by accident atleast once, # the default is being set to allianceraid again. self.raid.bot = "allianceraid" # self.bot.get_char_name() self.raid.last_action = time.time() spam = f""" ________________ You started a raid... but I need some more details about it, please fill in this form: {self.raid_settings(request, "")} ________________ """ return spam @command(command="raid", params=[Const("stop")], description="Stop the raid", access_level="leader") def raid_stop(self, _, _1): if not self.raid: return "There's no raid running." self.raid = None return "You stopped the raid." # noinspection LongLine @command(command="raid", params=[Const("invite")], description="Send the Spam to the defined Audience", access_level="leader") def send_tha_spam(self, request, _): if not self.raid: return "There's no raid running." def blob(label, msg): return f"{textwrap.dedent(label)}" last = time.time() if self.raid.last_spam + 5 * 60 > last: return f"There was an invite in the last 5 minutes; please wait " \ f"{self.util.time_to_readable(self.raid.last_spam + 5 * 60 - last)} " \ f"before sending another one." click_here = blob("click here", f"""
How to join the Raid
Step 1: - Please join {self.raid.bot}: [{self.text.make_chatcmd("Join", f"/tell {self.raid.bot} join")}] Step 2: - Please go LFT, to show your interest: [{self.text.make_chatcmd("Go LFT", f"/lft ยป {self.raid.bot}")}] Step 3: Wait at the raid starting location. Stepping is scheduled for {self.raid.raid_time} Currently it is {(datetime.now(timezone.utc).strftime("%H:%M"))} GMT-0 """) spam = f""" ________________ {request.sender.name} has invited you to join a {self.raid.raid_desc} Raid Type /tell {self.raid.bot} join to participate or {click_here} ________________ """ subtile = f"""[{request.sender.name}]: Raid Starting: {self.raid.raid_desc} -- use /tell {self.raid.bot} join to participate or {click_here} """ # noinspection SqlAggregates players = self.db.query("SELECT p.*, a.subtile_spam, a.raid_invite, a.raid_spam, a.main, a.disabled, a.member from online o " "left join player p on o.char_id = p.char_id " "left join account a on a.char_id=(select main from account where char_id=o.char_id) " "where p.level >= ? AND ((a.raid_invite=1 or a.raid_spam = 1) " "and a.disabled = 0 " "and a.member != -1 " "AND a.char_id NOT IN (SELECT char_id FROM org_bots) " "AND o.char_id NOT IN (SELECT char_id FROM org_bots)) " "AND o.bot=? group by o.char_id " "ORDER BY p.profession, p.name, p.level, p.org_rank_id;", [self.raid.min_level, self.bot.get_char_id()]) self.bot.send_mass_message(request.sender.char_id, f"Attempting to send {len(players)} invites...") info = "Sent invites to:" prof = "" count = len(players) for i in players: if not self.account_service.simple_checks(i): count -= 1 continue if prof != i.profession: info += "\n\n" info += "\n" + f"{i.profession}\n" info += "" prof = i.profession if i.raid_spam == 1: self.bot.send_mass_message(i.char_id, spam if i.subtile_spam == 0 else subtile) # if i.raid_invite == 1: # if self.raid.bot == self.bot.get_char_name(): # if not self.private_channel_service.in_private_channel(i.char_id): # self.private_channel_service.invite(i.char_id) info += f"\n - {i.name: <13} ({i.level: >3}/{i.ai_level: >2}) - {i.org_name}" self.raid.last_action = time.time() self.raid.last_spam = time.time() self.bot.send_mass_message(request.sender.char_id, f"Successfully sent {count} invite{'s' if count != 1 else ''}! [{self.text.format_page('More', info)}]") @command(command="raid", params=[Const("settings")], description="Change the title of the Raid", access_level="leader") def raid_settings(self, request: command_request, _): if not self.raid: return "There's no raid running." if request.sender.access_level["level"] <= self.raid.leader_rank: level_rest = " -" for i in [0, 200, 205, 210, 215, 220]: level_rest += f" [{self.text.make_chatcmd(i, '/tell raid level ' + str(i))}]" bots = " -" for i in ["allianceraid", "aapf", "theallianz"]: bots += f" [{self.text.make_chatcmd(i, '/tell raid bot ' + str(i))}]" description = " -" for i in ["S42", "Pandemonium", "APF's"]: description += f" [{self.text.make_chatcmd(i, '/tell raid desc ' + str(i))}]" step = " -" count = 0 for i in ["19:00 GMT-0", "19:30 GMT-0", "20:00 GMT-0", "20:30 GMT-0", "21:00 GMT-0", "21:30 GMT-0"]: if count == 2: count = 0 step += "
-" step += f" [{self.text.make_chatcmd(i, '/tell raid time ' + str(i))}]" count += 1 # noinspection LongLine settings = self.text.format_page("Raid Settings", textwrap.dedent( f"""
Raid Settings
Set the minimum level [{self.raid.min_level}]: {level_rest} Change the Description [{self.raid.raid_desc}]: {description} Change the Raidbot [{self.raid.bot}]: {bots} Change the raid stepping time [{self.raid.raid_time}]: -> Current Time: {(datetime.now(timezone.utc).strftime("%H:%M"))} GMT-0 {step} Send the invites! [{self.text.make_chatcmd("send the spam!", "/tell raid invite")}] End the raid [{self.text.make_chatcmd("stop it", "/tell raid stop")}] """)) return settings return f"Error! You cant do that. Your accesslevel must be equal or higher than " \ f"{self.raid.leader.name}'s rank." @timerevent(budatime="15m", description="Stop raid if inactive") def clear_raid(self, _, _1): if self.raid: if self.raid.last_action + 60 * 60 < time.time(): self.bot.send_mass_message(self.raid.leader.char_id, f"There was no interaction for more then 60 minutes for your Raid " f"{self.raid.raid_desc}; I'll stop it for you.") self.raid = None