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.tyrbot import Tyrbot
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: Tyrbot = registry.get_instance("bot")
self.db: DB = registry.get_instance("db")
self.text: Text = registry.get_instance("text")
self.util: Util = registry.get_instance("util")
self.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"""
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"""
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