Initial Release of IGNCore version 2.5
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
import re
|
||||
|
||||
from core.aochat import server_packets, client_packets
|
||||
from core.conn import Conn
|
||||
from core.decorators import instance
|
||||
from core.logger import Logger
|
||||
from core.lookup.character_service import CharacterService
|
||||
from core.setting_service import SettingService
|
||||
from core.setting_types import BooleanSettingType
|
||||
from core.text import Text
|
||||
from core.tyrbot import Tyrbot
|
||||
|
||||
|
||||
@instance("Darknet")
|
||||
class DarkController:
|
||||
relay_channel_id = None
|
||||
relay_name = None
|
||||
MESSAGE_SOURCE = "darknet"
|
||||
message_regex = re.compile(r"^(<font color='#\S+'>){2}\[([a-zA-Z]{2,})]</font> "
|
||||
r"<font color='#\S+'>(.+)</font> \[(.+)] \[(.+)]$", re.DOTALL)
|
||||
name_regex = re.compile(r"<a.*?href='user://(.+?)'>\1</a>", re.DOTALL)
|
||||
|
||||
def __init__(self):
|
||||
self.logger = Logger(__name__)
|
||||
|
||||
def inject(self, registry):
|
||||
self.bot: Tyrbot = registry.get_instance("bot")
|
||||
self.text: Text = registry.get_instance("text")
|
||||
self.setting_service: SettingService = registry.get_instance("setting_service")
|
||||
self.character_service: CharacterService = registry.get_instance("character_service")
|
||||
self.message_hub_service = registry.get_instance("message_hub_service")
|
||||
|
||||
def pre_start(self):
|
||||
self.bot.register_packet_handler(server_packets.PrivateChannelInvited.id, self.handle_private_channel_invite)
|
||||
self.bot.register_packet_handler(server_packets.PrivateChannelMessage.id, self.handle_private_channel_message)
|
||||
self.message_hub_service.register_message_source(self.MESSAGE_SOURCE)
|
||||
|
||||
def start(self):
|
||||
self.setting_service.register_new(self.module_name, "dark_relay", "true", BooleanSettingType(),
|
||||
"Is the Module Enabled?")
|
||||
self.setting_service.register_new(self.module_name, "dark_wts", "true", BooleanSettingType(),
|
||||
"Is the WTS channel visible?")
|
||||
self.setting_service.register_new(self.module_name, "dark_wtb", "true", BooleanSettingType(),
|
||||
"Is the WTB channel visible?")
|
||||
self.setting_service.register_new(self.module_name, "dark_lr", "true", BooleanSettingType(),
|
||||
"Is the Lootrights channel visible?")
|
||||
self.setting_service.register_new(self.module_name, "dark_gen", "true", BooleanSettingType(),
|
||||
"Is the General channel visible?")
|
||||
self.setting_service.register_new(self.module_name, "dark_pvp", "true", BooleanSettingType(),
|
||||
"Is the PvP channel visible?")
|
||||
self.setting_service.register_new(self.module_name, "dark_pvm", "true", BooleanSettingType(),
|
||||
"Is the PVM channel visible?")
|
||||
self.setting_service.register_new(self.module_name, "dark_event", "true", BooleanSettingType(),
|
||||
"Is the Event channel visible?")
|
||||
|
||||
def handle_private_channel_invite(self, conn: Conn, packet: server_packets.PrivateChannelInvited):
|
||||
if conn != "main":
|
||||
pass
|
||||
if self.setting_service.get_value("dark_relay") == "0":
|
||||
return
|
||||
if "Darknet" == self.character_service.get_char_name(packet.private_channel_id):
|
||||
channel_name = self.character_service.get_char_name(packet.private_channel_id)
|
||||
self.bot.send_packet(client_packets.PrivateChannelJoin(packet.private_channel_id))
|
||||
self.logger.info("Joined private channel {channel}".format(channel=channel_name))
|
||||
self.relay_channel_id = packet.private_channel_id
|
||||
self.relay_name = channel_name
|
||||
|
||||
def handle_private_channel_message(self, conn, packet: server_packets.PrivateChannelMessage):
|
||||
if conn != "main":
|
||||
pass
|
||||
if self.setting_service.get_value("dark_relay") == "0":
|
||||
return
|
||||
if packet.private_channel_id == self.relay_channel_id:
|
||||
if self.bot.get_char_id() == packet.char_id:
|
||||
return
|
||||
if packet.char_id != self.relay_channel_id:
|
||||
return
|
||||
message = packet.message.strip()
|
||||
self.process_incoming_relay_message(message)
|
||||
|
||||
def process_incoming_relay_message(self, message):
|
||||
if re.search(self.message_regex, message):
|
||||
cont = re.findall(self.message_regex, message)
|
||||
cont = cont[0]
|
||||
ch = cont[1].lower()
|
||||
msg = cont[2]
|
||||
tell = cont[3]
|
||||
if ch == "wts":
|
||||
if self.setting_service.get_value("dark_wts") == "0":
|
||||
return
|
||||
channel = "<red>WTS</red>"
|
||||
elif ch == "wtb":
|
||||
if self.setting_service.get_value("dark_wtb") == "0":
|
||||
return
|
||||
channel = "<green>WTB</green>"
|
||||
elif ch == "lootrights":
|
||||
if self.setting_service.get_value("dark_lr") == "0":
|
||||
return
|
||||
channel = "<violet>LR</violet>"
|
||||
elif ch == "general":
|
||||
if self.setting_service.get_value("dark_gen") == "0":
|
||||
return
|
||||
channel = "<notice>Gen</notice>"
|
||||
elif ch == "pvm":
|
||||
if self.setting_service.get_value("dark_pvm") == "0":
|
||||
return
|
||||
channel = "<cyan>PvM</cyan>"
|
||||
elif ch == "event":
|
||||
if self.setting_service.get_value("dark_event") == "0":
|
||||
return
|
||||
channel = "<highlight>Event</highlight>"
|
||||
elif ch == "pvp":
|
||||
if self.setting_service.get_value("dark_pvp") == "0":
|
||||
return
|
||||
channel = "<grey>PvP</grey>"
|
||||
elif ch == "auction":
|
||||
channel = "<yellow>AUCTION</yellow>"
|
||||
else:
|
||||
return
|
||||
message = ("[%s] %s [%s]" % (self.text.strip_html_tags(channel), msg, tell))
|
||||
self.message_hub_service.send_message(self.MESSAGE_SOURCE, None, message, message)
|
||||
@@ -0,0 +1,110 @@
|
||||
from core.aochat import server_packets, client_packets
|
||||
from core.conn import Conn
|
||||
from core.decorators import instance
|
||||
from core.logger import Logger
|
||||
from core.lookup.character_service import CharacterService
|
||||
from core.setting_service import SettingService
|
||||
from core.setting_types import TextSettingType, BooleanSettingType, ColorSettingType
|
||||
from core.text import Text
|
||||
from core.tyrbot import Tyrbot
|
||||
|
||||
|
||||
@instance("AllianceRelayController")
|
||||
class AllianceRelayController:
|
||||
relay_channel_id = None
|
||||
MESSAGE_SOURCE = "alliance"
|
||||
|
||||
def __init__(self):
|
||||
self.logger = Logger(__name__)
|
||||
|
||||
# noinspection DuplicatedCode
|
||||
def inject(self, registry):
|
||||
self.bot: Tyrbot = registry.get_instance("bot")
|
||||
self.setting_service: SettingService = registry.get_instance("setting_service")
|
||||
self.character_service: CharacterService = registry.get_instance("character_service")
|
||||
self.message_hub_service = registry.get_instance("message_hub_service")
|
||||
self.public_channel_service = registry.get_instance("public_channel_service")
|
||||
self.text: Text = registry.get_instance("text")
|
||||
|
||||
def pre_start(self):
|
||||
self.message_hub_service.register_message_source(self.MESSAGE_SOURCE)
|
||||
|
||||
def start(self):
|
||||
self.setting_service.register_new(self.module_name, "arelaybot", "",
|
||||
TextSettingType(allow_empty=True), "Bot for alliance relay")
|
||||
|
||||
self.setting_service.register_new(self.module_name, "arelay_enabled", False,
|
||||
BooleanSettingType(), "Enable the alliance relay")
|
||||
|
||||
self.setting_service.register_new(self.module_name, "arelay_color", "#C3C3C3",
|
||||
ColorSettingType(),
|
||||
"Color of messages from relay")
|
||||
|
||||
self.message_hub_service.register_message_destination(self.MESSAGE_SOURCE, self.handle_relay_hub_message, [],
|
||||
[self.MESSAGE_SOURCE])
|
||||
|
||||
self.bot.register_packet_handler(server_packets.PrivateChannelInvited.id, self.handle_private_channel_invite,
|
||||
100)
|
||||
self.bot.register_packet_handler(server_packets.PrivateChannelMessage.id, self.handle_private_channel_message)
|
||||
|
||||
# noinspection DuplicatedCode
|
||||
def handle_private_channel_invite(self, conn: Conn, packet: server_packets.PrivateChannelInvited):
|
||||
if conn.id != "main":
|
||||
return
|
||||
|
||||
if not self.setting_service.get("arelay_enabled").get_value():
|
||||
return
|
||||
|
||||
channel_name = self.character_service.get_char_name(packet.private_channel_id)
|
||||
if self.setting_service.get_value("arelaybot").lower() == channel_name.lower():
|
||||
self.bot.send_packet(client_packets.PrivateChannelJoin(packet.private_channel_id))
|
||||
self.logger.info("Joined private channel {channel}".format(channel=channel_name))
|
||||
self.relay_channel_id = packet.private_channel_id
|
||||
|
||||
# noinspection DuplicatedCode
|
||||
def handle_private_channel_message(self, conn: Conn, packet: server_packets.PrivateChannelMessage):
|
||||
if conn.id != "main":
|
||||
return
|
||||
|
||||
if not self.setting_service.get("arelay_enabled").get_value():
|
||||
return
|
||||
|
||||
# ignore packets from the bot's own private channel and from the bot itself
|
||||
if packet.private_channel_id == self.bot.get_char_id() or packet.char_id == self.bot.get_char_id():
|
||||
return
|
||||
|
||||
message = packet.message.lstrip()
|
||||
if message[:6] != "!agcr ":
|
||||
return
|
||||
|
||||
message = message[6:]
|
||||
formatted_message = self.setting_service.get("arelay_color").format_text(message)
|
||||
|
||||
sender = None
|
||||
self.message_hub_service.send_message(self.MESSAGE_SOURCE, sender, message, formatted_message)
|
||||
|
||||
def handle_relay_hub_message(self, ctx):
|
||||
if not self.setting_service.get("arelay_enabled").get_value():
|
||||
return
|
||||
|
||||
plain_msg = ctx.message or ctx.formatted_message
|
||||
invite = self.text.make_chatcmd("click here", "/tell <myname> discord invite",
|
||||
style="style='text-decoration:none'")
|
||||
|
||||
blob = self.text.format_page('Info',
|
||||
f"<header>::: Information :::</header><br><br>"
|
||||
f"This message has been sent to you by:<br><br>"
|
||||
f"<header2>Igncom</header2><br>"
|
||||
f"<notice>{ctx.sender[1].name + '#' + ctx.sender[1].discriminator}</notice><br>"
|
||||
f"<highlight>{ctx.sender[0]}</highlight> on Alliance Discord.<br><br>"
|
||||
f"To reply, either respond in the relay or "
|
||||
f"contact them directly at the provided handles.<br><br>"
|
||||
f"<header2>Have you joined The Alliance Discord yet? "
|
||||
f"If not <highlight>{invite}</highlight> to receive an invite.</header2>")
|
||||
self.send_message_to_alliance(plain_msg + f" <yellow>[{blob}]</yellow>")
|
||||
|
||||
def send_message_to_alliance(self, msg):
|
||||
if self.relay_channel_id:
|
||||
packet = client_packets.PrivateChannelMessage(self.relay_channel_id,
|
||||
"!agcr " + self.text.format_message(msg, False), "\0")
|
||||
self.bot.conns["main"].send_packet(packet)
|
||||
@@ -0,0 +1,125 @@
|
||||
import random
|
||||
import re
|
||||
|
||||
from core.conn import Conn
|
||||
from core.db import DB
|
||||
from core.decorators import instance
|
||||
from core.logger import Logger
|
||||
from core.lookup.character_service import CharacterService
|
||||
from core.setting_service import SettingService
|
||||
from core.text import Text
|
||||
from core.tyrbot import Tyrbot
|
||||
|
||||
|
||||
@instance("DingController")
|
||||
class DingController:
|
||||
axp = re.compile(
|
||||
r"ICC planet-wide announcement: (.+) has been awarded the highest honorary rank for "
|
||||
r"outstanding dedication to the defence of Rubi-Ka.")
|
||||
xp = re.compile(
|
||||
r"You feel the core of your being shift, as the source makes room for a divine presence. "
|
||||
r"'(.+)' has reached enlightenment.")
|
||||
|
||||
text_options_xp = ["Congratz! You have reached the end of the line! NO MORE FUN FOR YOU! :P",
|
||||
|
||||
"Holy shit, you finally made it! What an accomplishment... Congratulations "
|
||||
"<font color=#FF1493>{name}</font>, for reaching a level reserved for the greatest!",
|
||||
|
||||
"Damn <font color=#FF1493>{name}</font>.... I'm going to miss you a great deal, "
|
||||
"because after this, we no longer can be together <font color=#FF1493>{name}</font>."
|
||||
" We must part so you can continue getting your research and AI levels done! Farewell!",
|
||||
|
||||
"Hey <font color=#FF1493>{name}</font>, how was the inferno grind? "
|
||||
"I'm glad to see you made it through, and congratulations for "
|
||||
"finally getting the level you well deserved!",
|
||||
|
||||
"Our congratulations, to our newest <font color=#FF1493>level 220</font> member, "
|
||||
"<font color=#FF1493>{name}</font>, for his dedication. "
|
||||
"We present him with his new honorary rank, Chuck Norris!",
|
||||
|
||||
"Holy crap, you actually did it! Dear <font color=#FF1493>{name}</font>, "
|
||||
"I salute you for your determination and sheer awesomeness. Congratulations, "
|
||||
"to our newest <font color=#FF1493>level 220</font> member!"]
|
||||
|
||||
text_options_axp = ["Congratz! You have reached the end of the line! NO MORE FUN FOR YOU! :P",
|
||||
|
||||
"Holy shit, you finally made it! What an accomplishment... "
|
||||
"Congratulations <font color=#FF1493>{name}</font>, "
|
||||
"for reaching <green>Alien Level 30</green>!",
|
||||
|
||||
"Damn... I'm going to miss you a great deal, because after this, we no longer can be together, "
|
||||
"<font color=#FF1493>{name}</font>. We must part so you can continue getting your research!"
|
||||
" Farewell!",
|
||||
|
||||
"Hey <font color=#FF1493>{name}</font>, how was the <green>alien</green> grind?"
|
||||
" I'm glad to see you made it through, "
|
||||
"and congratulations for finally getting the level you well deserved!",
|
||||
|
||||
"Our congratulations, to our newest <green>Alien Level 30</green> member, "
|
||||
"<font color=#FF1493>{name}</font>, for his dedication. "
|
||||
"We present him with his new honorary rank, <yellow>Vindicator</yellow>!",
|
||||
|
||||
"Holy crap, you actually did it! Dear <font color=#FF1493>{name}</font>, "
|
||||
"I salute you for your determination and sheer awesomeness. Congratulations, "
|
||||
"to our newest <green>Alien Level 30</green> member!"]
|
||||
|
||||
def __init__(self):
|
||||
self.logger = Logger(__name__)
|
||||
|
||||
def inject(self, registry):
|
||||
self.bot: Tyrbot = registry.get_instance("bot")
|
||||
self.text: Text = registry.get_instance("text")
|
||||
self.setting_service: SettingService = registry.get_instance("setting_service")
|
||||
self.character_service: CharacterService = registry.get_instance("character_service")
|
||||
self.message_hub_service = registry.get_instance("message_hub_service")
|
||||
self.db: DB = registry.get_instance("db")
|
||||
|
||||
def pre_start(self):
|
||||
self.bot.register_packet_handler(36, self.handle_ding)
|
||||
self.bot.register_packet_handler(35, self.handle_ding)
|
||||
|
||||
def handle_ding(self, conn: Conn, packet):
|
||||
if conn.char_id != self.bot.get_char_id():
|
||||
return
|
||||
# AXP 30
|
||||
if packet.id == 36:
|
||||
info = re.findall(self.axp, packet.message)
|
||||
if info:
|
||||
user = self.get_user(info[0])
|
||||
if user:
|
||||
self.bot.send_mass_message(user.char_id,
|
||||
f"<green>Game Over</green>! "
|
||||
f"{random.choice(self.text_options_axp).format(**user)} "
|
||||
f"<yellow>[{self.generate_output('AI 220')}]</yellow>",
|
||||
log_message=True)
|
||||
|
||||
# XP 220
|
||||
if packet.id == 35:
|
||||
info = re.findall(self.xp, packet.message)
|
||||
if info:
|
||||
user = self.get_user(info[0])
|
||||
if user:
|
||||
self.bot.send_mass_message(user.char_id,
|
||||
f"<font color=#FF1493>Game Over</font>! "
|
||||
f"{random.choice(self.text_options_xp).format(**user)} "
|
||||
f"<yellow>[{self.generate_output('Level 220')}]</yellow>",
|
||||
log_message=True)
|
||||
|
||||
def generate_output(self, level):
|
||||
invite = self.text.make_chatcmd("click here", "/tell <myname> discord invite",
|
||||
style="style='text-decoration:none'")
|
||||
sys = self.text.make_chatcmd("SYSTEM", "/tell <myname> admins",
|
||||
style="style='text-decoration:none'")
|
||||
blob = self.text.format_page('Info',
|
||||
f"<header>::: Information :::</header><br><br>"
|
||||
f"This automated message has been sent to you by:<br><br>"
|
||||
f"<header2>Igncom</header2> <yellow>[<green>{sys}</green>]</yellow><br>"
|
||||
f"<header2>Reason for this Message: "
|
||||
f"<highlight>You dinged {level}</highlight></header2><br><br>"
|
||||
f"<header2>Have you joined The Alliance Discord yet? "
|
||||
f"If not <highlight>{invite}</highlight> to receive an invite. "
|
||||
f"(/tell <myname> discord invite from your Main)</header2>")
|
||||
return blob
|
||||
|
||||
def get_user(self, name):
|
||||
return self.db.query_single("SELECT * FROM player where name=? and org_id in (SELECT * from orgs)", [name])
|
||||
@@ -0,0 +1,68 @@
|
||||
from threading import Thread
|
||||
|
||||
from core import command_request, sender_obj
|
||||
from core.aochat.BaseModule import BaseModule
|
||||
from core.buddy_service import BuddyService
|
||||
from core.chat_blob import ChatBlob
|
||||
from core.command_alias_service import CommandAliasService
|
||||
from core.command_param_types import Const, Character
|
||||
from core.db import DB
|
||||
from core.decorators import instance, command
|
||||
from core.logger import Logger
|
||||
from core.lookup.pork_service import PorkService
|
||||
from core.text import Text
|
||||
from core.tyrbot import Tyrbot
|
||||
from core.util import Util
|
||||
|
||||
|
||||
# noinspection DuplicatedCode
|
||||
@instance()
|
||||
class BotController(BaseModule):
|
||||
bots = []
|
||||
threads = {}
|
||||
|
||||
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")
|
||||
|
||||
def pre_start(self):
|
||||
self.db.exec("CREATE TABLE IF NOT EXISTS org_bots(char_id int primary key not null, org_id int not null)")
|
||||
|
||||
def start(self):
|
||||
pass
|
||||
|
||||
@command(command="bots", params=[Const("add"), Character("botname")], access_level="admin",
|
||||
description="Add an bot to the bot list")
|
||||
def bots_add_any(self, sender, _, bot):
|
||||
Thread(target=self.bots_add, args=(bot, sender)).start()
|
||||
|
||||
def bots_add(self, bot: sender_obj, request: command_request):
|
||||
player = self.pork.request_char_info(bot.name, 5)
|
||||
if self.db.exec("INSERT IGNORE INTO org_bots(char_id, org_id) VALUES(?, ?)", [bot.char_id, player.org_id]) == 0:
|
||||
request.reply("The bot <highlight>%s<end> is already marked as an chatbot." % bot.name)
|
||||
else:
|
||||
request.reply("Successfully marked <highlight>%s<end> as an chatbot." % bot.name)
|
||||
|
||||
@command(command="bots",
|
||||
params=[],
|
||||
access_level="moderator",
|
||||
description="show all orgbots",
|
||||
sub_command="show")
|
||||
def bots_show_all(self, _):
|
||||
def format_row(query):
|
||||
bud = self.buddy_service.is_online(query["char_id"])
|
||||
buddy = "<green>O<end>" if bud == 1 else "<red>O<end>" if bud == 0 else "<grey>U<end>"
|
||||
return "- [{status}] <highlight>{name}<end> (<notice>{org_name}<end>)\n".format(**query, status=buddy)
|
||||
|
||||
data = self.db.query("SELECT * FROM org_bots o LEFT JOIN player p on o.char_id = p.char_id order by p.org_name")
|
||||
blob = ""
|
||||
for row in data:
|
||||
blob += format_row(row)
|
||||
return ChatBlob("Our Orgbots", blob)
|
||||
@@ -0,0 +1,35 @@
|
||||
from core.command_param_types import Const, Int, Any
|
||||
from core.decorators import instance, command
|
||||
from modules.standard.online.online_controller import OnlineController
|
||||
|
||||
|
||||
@instance(name="online_controller", override=True)
|
||||
class OrgOnlineController(OnlineController):
|
||||
|
||||
@command(command="online", params=[Const('all', is_optional=True),
|
||||
Int("min_level", is_optional=True),
|
||||
Any("profession", is_optional=True)],
|
||||
description="shows online players",
|
||||
access_level="member")
|
||||
def online_all_cmd(self, request, const_all, min_level, profession):
|
||||
query = ""
|
||||
params = [self.bot.name, self.bot.get_char_id()]
|
||||
priv = self.priv.in_private_channel(request.sender.char_id)
|
||||
if priv:
|
||||
if const_all:
|
||||
query += "and channel_id IN (1, 2, 3) "
|
||||
else:
|
||||
query += "and channel_id IN (1, 2) "
|
||||
else:
|
||||
query += "and channel_id = 3 "
|
||||
if min_level:
|
||||
query += "and p.level >= ? "
|
||||
params.append(min_level)
|
||||
if profession:
|
||||
query += "and p.profession = ? "
|
||||
params.append(self.util.get_profession(profession))
|
||||
if priv and not const_all:
|
||||
blob = self.online_display.format_by_channel_prof(query, params)
|
||||
else:
|
||||
blob = self.online_display.format_by_org(query, params)
|
||||
self.bot.send_mass_message(request.sender.char_id, self.online_display.format_blob(blob))
|
||||
@@ -0,0 +1,38 @@
|
||||
from core.buddy_service import BuddyService
|
||||
from core.command_alias_service import CommandAliasService
|
||||
from core.db import DB
|
||||
from core.decorators import instance
|
||||
from core.logger import Logger
|
||||
from core.lookup.pork_service import PorkService
|
||||
from core.text import Text
|
||||
from core.tyrbot import Tyrbot
|
||||
from core.util import Util
|
||||
from modules.core.accounting.services.access_service import AccessService
|
||||
|
||||
|
||||
# noinspection DuplicatedCode
|
||||
@instance()
|
||||
class OrgAliasController:
|
||||
org_prefix = {4736: "AP", 9632: "AP", 9622: "AC", 9831: "AC", 581633: "BST", 9707: "CoH", 9990: "CoH", 4637: "HAV",
|
||||
10197: "IMP", 6093: "LCG", 4789: "MJ", 4687: "NA", 4800: "PR", 4993: "REGS", 813067: "SOTL",
|
||||
4851: "SP", 9611: "SP", 4614: "TA", 4831: "TGNF", 6183: "TRE", 9822: "TS", 4611: "UHS",
|
||||
5571: "UOTR", 520210: "WO", 1349649: "VR", 4826: "42", 1349647: "VR", 6332: "DRA", 848: "DRA",
|
||||
4675: "VA", 1558530: "EoS"}
|
||||
|
||||
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.access_service: AccessService = registry.get_instance("access_service")
|
||||
|
||||
def start(self):
|
||||
self.db.exec("CREATE TABLE IF NOT EXISTS org_alias(org_id int primary key not null, org_alias VARCHAR(255))")
|
||||
|
||||
def get_alias(self, org_id):
|
||||
return self.org_prefix.get(org_id, "-UKN-")
|
||||
@@ -0,0 +1,369 @@
|
||||
import json
|
||||
import re
|
||||
import time
|
||||
from threading import Thread
|
||||
|
||||
import requests
|
||||
from mysql.connector.cursor import CursorBase
|
||||
|
||||
from core.buddy_service import BuddyService
|
||||
from core.cache_service import CacheService
|
||||
from core.chat_blob import ChatBlob
|
||||
from core.command_alias_service import CommandAliasService
|
||||
from core.command_param_types import Const, Any
|
||||
from core.command_request import CommandRequest
|
||||
from core.db import DB
|
||||
from core.decorators import instance, command, timerevent, event
|
||||
from core.dict_object import DictObject
|
||||
from core.logger import Logger
|
||||
from core.lookup.org_pork_service import OrgPorkService
|
||||
from core.lookup.pork_service import PorkService
|
||||
from core.message_hub_service import MessageHubService
|
||||
from core.text import Text
|
||||
from core.tyrbot import Tyrbot
|
||||
from core.util import Util
|
||||
from modules.core.accounting.services.access_service import AccessService
|
||||
# noinspection PyAttributeOutsideInit,SpellCheckingInspection,DuplicatedCode
|
||||
from modules.core.accounting.services.account_service import AccountService
|
||||
from modules.onlinebot.online.org_alias_controller import OrgAliasController
|
||||
|
||||
|
||||
# noinspection DuplicatedCode
|
||||
@instance()
|
||||
class OrgController:
|
||||
threads = {}
|
||||
letters = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
|
||||
"v", "w", "x", "y", "z", "others", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
|
||||
pork_uri = "https://people.anarchy-online.com/people/lookup/orgs.html?l=%s"
|
||||
single_org_uri = "https://people.anarchy-online.com/org/stats/d/5/name/%d/basicstats.xml?data_type=json"
|
||||
|
||||
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: OrgPorkService = 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.access_service: AccessService = registry.get_instance("access_service")
|
||||
self.relay_hub_service: MessageHubService = registry.get_instance("message_hub_service")
|
||||
self.alias_controller: OrgAliasController = registry.get_instance("org_alias_controller")
|
||||
self.account_service: AccountService = registry.get_instance("account_service")
|
||||
self.cache: CacheService = registry.get_instance("cache_service")
|
||||
|
||||
def start(self):
|
||||
self.db.exec("CREATE TABLE IF NOT EXISTS orgs(org_id int primary key not null)")
|
||||
|
||||
self.command_alias_service.add_alias("org", "orgs")
|
||||
|
||||
@event("connect", "Adds all members to buddylist")
|
||||
def connect(self, _, _1):
|
||||
query = self.db.query("SELECT char_id, member from account where member IN (SELECT org_id from orgs)")
|
||||
if query:
|
||||
for player in query:
|
||||
self.buddy_service.add_buddy(player.char_id, "member")
|
||||
|
||||
@command(command="orgs", params=[Const("add"), Any("Organisation")], access_level="admin",
|
||||
description="Add an org to the online list")
|
||||
def orgs_add_any(self, sender, _, org):
|
||||
return self.orgs_add(org, sender)
|
||||
|
||||
def orgs_add(self, search, sender):
|
||||
orgs = self.find_org(search)
|
||||
if len(orgs) == 1:
|
||||
orgs = orgs[0]
|
||||
if self.db.exec("REPLACE INTO orgs(org_id) VALUES(?)",
|
||||
[orgs.org_id]) == 1:
|
||||
sender.reply("Adding the organisation <highlight>%s<end> to the roster..." % orgs.org_name)
|
||||
org_adder = Thread(name=orgs.org_id, target=self.fetch_single,
|
||||
args=(orgs.org_id, orgs.org_name, sender))
|
||||
self.threads[orgs.org_id] = org_adder
|
||||
org_adder.start()
|
||||
else:
|
||||
return "The organisation <highlight>%s<end> is in the roster already." % orgs.org_name
|
||||
elif len(orgs) == 0:
|
||||
return "No org with the name <highlight>%s<end> was found on PoRK." % search
|
||||
else:
|
||||
blob = "Your search had multiple results; please pick an org:<br>"
|
||||
for org in orgs:
|
||||
blob += "[%s][%s] <highlight>%s<end> (<highlight>%s<end>) <%s>%s<end> [<highlight>%s<end> " \
|
||||
"members]<br><pagebreak>" \
|
||||
% (self.text.make_chatcmd("Add", "/tell <myname> orgs add %s" % org.org_id),
|
||||
self.text.make_chatcmd("More", "/tell <myname> org info %s" % org.org_id),
|
||||
org.org_name, org.org_id, org.faction.lower(), org.faction, org.member_count)
|
||||
return ChatBlob("Pick an Org", blob)
|
||||
|
||||
@command(command="orgs", params=[Const("rem"), Any("Organisation")], access_level="admin",
|
||||
description="Remove an org from the online list")
|
||||
def orgs_rem_any(self, _, _1, org):
|
||||
return self.orgs_rem(org)
|
||||
|
||||
def orgs_rem(self, search):
|
||||
orgs = self.find_org(search)
|
||||
|
||||
if len(orgs) == 1:
|
||||
orgs = orgs[0]
|
||||
if self.db.exec("DELETE FROM orgs where org_id = ?", [orgs.org_id]) == 1:
|
||||
org_remover = Thread(name=orgs.org_id, target=self.remove_single, args=(orgs.org_id, orgs.org_name))
|
||||
self.threads[orgs.org_id] = org_remover
|
||||
org_remover.start()
|
||||
return "Removed the organisation <highlight>%s<end> from the roster." % orgs.org_name
|
||||
else:
|
||||
return "The organisation <highlight>%s<end> is not on the roster list." % orgs.org_name
|
||||
elif len(orgs) == 0:
|
||||
return "The organisation <highlight>%s<end> is not on the roster list." % search
|
||||
else:
|
||||
blob = "Your search had multiple results; please pick an org:<br>"
|
||||
for org in orgs:
|
||||
blob += "[%s][%s] <highlight>%s<end> (<highlight>%s<end>) <%s>%s<end> [<highlight>%s<end> " \
|
||||
"members]<br><pagebreak>" \
|
||||
% (self.text.make_chatcmd("Remove", "/tell <myname> orgs remove %s" % org.org_id),
|
||||
self.text.make_chatcmd("More", "/tell <myname> org info %s" % org.org_id),
|
||||
org.org_name, org.org_id, org.faction.lower(), org.faction, org.member_count)
|
||||
return ChatBlob("Pick an Org", blob)
|
||||
|
||||
@command(command="orgs", params=[Const("list", is_optional=True)], access_level="member",
|
||||
description="View all orgs on the online list", sub_command="list")
|
||||
def orgs_list(self, sender: CommandRequest, _):
|
||||
head = "<header>Organisations in our Alliance<end>"
|
||||
blob = ""
|
||||
for org in self.db.query("SELECT * from orgs o "
|
||||
"left join all_orgs a on o.org_id = a.org_id order by a.org_name"):
|
||||
org = DictObject(org)
|
||||
blob += "- %s%s<highlight>%s<end> (%d) with <highlight>%d<end> members\n" % (
|
||||
"[<highlight>" + self.text.make_chatcmd("Info", "/tell <myname> orgs info %d" % org.org_id,
|
||||
style="style='text-decoration:none'") + "</highlight>] ",
|
||||
"[<red>" + self.text.make_chatcmd("Remove", "/tell <myname> orgs rem %d" % org.org_id,
|
||||
style="style='text-decoration:none'") + "</red>] " if
|
||||
sender.sender.access_level["level"] <= 10 else "",
|
||||
org.org_name, org.org_id,
|
||||
self.db.query_single("SELECT member_count from all_orgs where org_id=?", [org.org_id]).member_count)
|
||||
|
||||
return ChatBlob(head, blob)
|
||||
|
||||
@timerevent(budatime="48h", description="pull list of all orgs from PoRK")
|
||||
def discover_orgs(self, _, _1):
|
||||
def discover():
|
||||
start = time.time()
|
||||
self.logger.info("Fetching global orgdata..")
|
||||
count = 0
|
||||
data = []
|
||||
|
||||
for letter in self.letters:
|
||||
result = requests.get(self.pork_uri % letter)
|
||||
# noinspection RegExpRepeatedSpace
|
||||
matches = re.findall("""<tr>
|
||||
<td align="left">
|
||||
<a href="//people.anarchy-online.com/org/stats/d/5/name/(\d+)">
|
||||
(.+)</a></td>
|
||||
<td align="right">(\d+)</td>
|
||||
<td align="right">(\d+)</td>
|
||||
<td align="left">(\w+)</td>
|
||||
<td align="left">(\w+)</td>
|
||||
<td align="left" class="dim">RK5</td>
|
||||
</tr>""", result.text)
|
||||
for match in matches:
|
||||
if int(match[2]) < 6:
|
||||
continue
|
||||
data.append((int(match[0]), match[1], int(match[2]), match[4], start))
|
||||
count += 1
|
||||
self.logger.info("Batch %s done!" % letter)
|
||||
|
||||
with self.db.pool.get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur: CursorBase
|
||||
cur.executemany(
|
||||
"INSERT INTO all_orgs(org_id, org_name, member_count, faction, last_seen) "
|
||||
"VALUES(?, ?, ?, ?, ?) "
|
||||
"ON DUPLICATE KEY UPDATE "
|
||||
"org_name=VALUE(org_name), "
|
||||
"member_count=VALUE(member_count), "
|
||||
"last_seen=VALUE(last_seen)",
|
||||
data)
|
||||
self.db.exec("DELETE FROM all_orgs where last_seen < ?", [time.time() - 2 * 24 * 60 * 60])
|
||||
self.logger.info("Successfully fetched %d orgs in %d seconds." % (count, time.time() - start))
|
||||
self.threads.pop('orgdiscover', None)
|
||||
|
||||
if "orgdiscover" not in self.threads.keys():
|
||||
thread = Thread(name="orgdiscover", target=discover, daemon=True)
|
||||
self.threads["orgdiscover"] = thread
|
||||
thread.start()
|
||||
|
||||
@timerevent(budatime="24h", description="Pull data for our own orgs")
|
||||
def fetch_orgs(self, _, _1):
|
||||
def discover():
|
||||
start = time.time()
|
||||
self.logger.info("Fetching orgdata..")
|
||||
output = []
|
||||
data = []
|
||||
accounts = []
|
||||
ours = self.db.query("SELECT o.org_id, a.org_name from orgs o "
|
||||
"left join all_orgs a on o.org_id = a.org_id order by lower(a.org_name)")
|
||||
for org in ours:
|
||||
result = requests.get(self.single_org_uri % org.org_id).json()
|
||||
if result:
|
||||
self.cache.store('org_roster', f"{org.org_id}.5.json", json.dumps(result))
|
||||
else:
|
||||
result = json.loads(self.cache.retrieve('org_roster', f"{org.org_id}.5.json").data)
|
||||
|
||||
for char_info in result[1]:
|
||||
data.append((char_info["CHAR_INSTANCE"], char_info["NAME"], char_info["FIRSTNAME"],
|
||||
char_info["LASTNAME"], char_info["LEVELX"], char_info["BREED"],
|
||||
char_info["SEX"], result[0]["SIDE_NAME"], char_info["PROF"],
|
||||
char_info["PROF_TITLE"], char_info["DEFENDER_RANK_TITLE"], char_info["ALIENLEVEL"],
|
||||
result[0]["ORG_INSTANCE"], result[0]["NAME"], char_info["RANK_TITLE"],
|
||||
char_info["RANK"], char_info["CHAR_DIMENSION"], char_info["HEADID"],
|
||||
0, char_info["PVPTITLE"], "roster", int(time.time())))
|
||||
accounts.append((char_info["CHAR_INSTANCE"],
|
||||
char_info["CHAR_INSTANCE"],
|
||||
result[0]["ORG_INSTANCE"],
|
||||
start, start))
|
||||
if not self.buddy_service.get_buddy(char_info["CHAR_INSTANCE"]):
|
||||
self.buddy_service.add_buddy(char_info["CHAR_INSTANCE"], "member")
|
||||
output.append(DictObject({"action": "JOIN",
|
||||
"name": char_info['NAME'],
|
||||
"org_name": result[0]["NAME"],
|
||||
"org_id": result[0]["ORG_INSTANCE"],
|
||||
"level": char_info["LEVELX"],
|
||||
"ai_level": char_info["ALIENLEVEL"],
|
||||
"ranks": 0}))
|
||||
self.logger.info("Organisation %s has been updated." % org.org_name)
|
||||
self.account_service.create_users(accounts)
|
||||
if len(data) > 1:
|
||||
with self.db.lock:
|
||||
with self.db.pool.get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur: CursorBase
|
||||
cur.executemany("INSERT INTO player(char_id, name, first_name, last_name, "
|
||||
"level, breed, gender, faction, profession, profession_title, "
|
||||
"ai_rank, ai_level, org_id, org_name, org_rank_name, "
|
||||
"org_rank_id, dimension, head_id, pvp_rating, pvp_title, "
|
||||
"source, last_updated) VALUES "
|
||||
"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
|
||||
"ON DUPLICATE KEY UPDATE first_name=VALUE(first_name), "
|
||||
"last_name=VALUE(last_name), level=VALUE(level), "
|
||||
"breed=VALUE(breed), gender=VALUE(gender), "
|
||||
"faction=VALUE(faction), profession=VALUE(profession), "
|
||||
"profession_title=VALUE(profession_title),ai_rank=VALUE(ai_rank), "
|
||||
"ai_level=VALUE(ai_level), org_name=VALUE(org_name), "
|
||||
"org_id=VALUE(org_id), org_rank_name=VALUE(org_rank_name), "
|
||||
"org_rank_id=VALUE(org_rank_id), source=VALUE(source), "
|
||||
"last_updated=VALUE(last_updated)", data)
|
||||
conn.commit()
|
||||
self.db.exec("UPDATE account set member = -1 "
|
||||
"where char_id NOT IN "
|
||||
"(select char_id from player where org_id in (select org_id from orgs)) and member > 0")
|
||||
self.db.exec("DELETE FROM ranks where main not in (select main from account where member > -1)")
|
||||
players = self.db.query("SELECT a.char_id, p.* FROM account a "
|
||||
"left join player p on a.char_id=p.char_id "
|
||||
"where (a.last_updated < ? and member >1) or "
|
||||
"(p.org_id NOT IN (select org_id from orgs) and a.member>1) ",
|
||||
[time.time() - 24 * 60 * 60])
|
||||
accounts = []
|
||||
for player in players:
|
||||
bonus = None
|
||||
player = DictObject(player)
|
||||
count = 0
|
||||
if self.buddy_service.remove_buddy(player.char_id, "member"):
|
||||
count = self.db.exec("DELETE FROM ranks where main=?", [player.char_id])
|
||||
accounts.append((player.char_id, 1))
|
||||
bonus = "LEAVE"
|
||||
new_data = self.pork.request_char_info(player.name, player.dimension)
|
||||
if new_data and new_data.char_id == player.char_id:
|
||||
self.pork.save_character_info(new_data)
|
||||
else:
|
||||
bonus = "DEL"
|
||||
accounts.append((player.char_id, 1))
|
||||
if bonus:
|
||||
output.append(DictObject({"action": bonus,
|
||||
"name": player.name,
|
||||
"org_name": player.org_name,
|
||||
"org_id": player.org_id,
|
||||
"level": player.level,
|
||||
"ai_level": player.ai_level,
|
||||
"ranks": count}))
|
||||
self.account_service.remove_members(accounts)
|
||||
self.log(output, time.time() - start)
|
||||
self.logger.info("Successfully fetched %d players from %d orgs in %d seconds. - " % (
|
||||
len(data), len(ours), time.time() - start))
|
||||
del self.threads['roster']
|
||||
|
||||
if "roster" not in self.threads.keys():
|
||||
thread = Thread(name="roster", target=discover, daemon=True)
|
||||
self.threads["roster"] = thread
|
||||
thread.start()
|
||||
|
||||
def find_org(self, search, table="all_orgs"):
|
||||
if search.isdigit():
|
||||
return self.db.query("SELECT * FROM " + table + " where org_id = ?", [search])
|
||||
elif isinstance(search, str):
|
||||
return self.db.query("SELECT * FROM " + table + " where org_name LIKE ?", ["%" + search + "%"])
|
||||
|
||||
def fetch_single(self, org_id, org_name, sender: object):
|
||||
start = time.time()
|
||||
data = []
|
||||
accounts = []
|
||||
self.logger.info("Fetching orgdata..")
|
||||
count = 0
|
||||
result = requests.get(self.single_org_uri % org_id).json()
|
||||
for char_info in result[1]:
|
||||
data.append((char_info["CHAR_INSTANCE"], char_info["NAME"], char_info["FIRSTNAME"],
|
||||
char_info["LASTNAME"],
|
||||
char_info["LEVELX"], char_info["BREED"],
|
||||
char_info["SEX"], result[0]["SIDE_NAME"], char_info["PROF"],
|
||||
char_info["PROF_TITLE"], char_info["DEFENDER_RANK_TITLE"], char_info["ALIENLEVEL"],
|
||||
result[0]["ORG_INSTANCE"], result[0]["NAME"], char_info["RANK_TITLE"],
|
||||
char_info["RANK"], char_info["CHAR_DIMENSION"], char_info["HEADID"],
|
||||
0, char_info["PVPTITLE"], "roster", int(time.time())))
|
||||
|
||||
accounts.append((char_info["CHAR_INSTANCE"], char_info["CHAR_INSTANCE"], result[0]["ORG_INSTANCE"],
|
||||
start, start))
|
||||
self.buddy_service.add_buddy(char_info['CHAR_INSTANCE'], "member")
|
||||
count += 1
|
||||
with self.db.pool.get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.executemany("REPLACE INTO player(char_id, name, first_name, last_name, level, breed, "
|
||||
"gender, faction, profession, profession_title, ai_rank, ai_level, "
|
||||
"org_id, org_name, org_rank_name, org_rank_id, dimension, head_id, "
|
||||
"pvp_rating, pvp_title, source, last_updated) VALUES "
|
||||
"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", data)
|
||||
self.account_service.create_users(accounts)
|
||||
self.logger.info("Organisation %s added!" % org_name)
|
||||
sender.reply(f"<highlight>{org_name}</highlight> has been added to the roster. "
|
||||
f"Runtime: {time.time() - start:.2f} seconds.")
|
||||
|
||||
self.logger.info("Successfully fetched %d players in %d seconds." % (count, time.time() - start))
|
||||
del self.threads[org_id]
|
||||
|
||||
def remove_single(self, org_id, org_name):
|
||||
members = self.db.query("SELECT * from player where org_id=?", [org_id])
|
||||
for member in members:
|
||||
self.buddy_service.remove_buddy(member.char_id, "member")
|
||||
self.db.exec("UPDATE account set member=-1 where char_id in"
|
||||
" (SELECT char_id from player where org_id=?)", [org_id])
|
||||
self.db.exec("DELETE FROM online where char_id in (SELECT char_id from player where org_id=?)", [org_id])
|
||||
self.logger.info("Organisation %s removed!" % org_name)
|
||||
del self.threads[org_id]
|
||||
|
||||
def log(self, blob, duration):
|
||||
out = []
|
||||
s = []
|
||||
current = ""
|
||||
|
||||
for entry in blob:
|
||||
s.append(f"[{self.alias_controller.get_alias(entry.org_id)}] [{entry.action}] {entry.name} "
|
||||
f"({entry.level}/{entry.ai_level}) {'[R-P]' if entry.ranks > 0 else ''}\n")
|
||||
s = sorted(s)
|
||||
if len(s) > 0:
|
||||
s.append(f"\nRuntime: {duration:.2f} seconds.")
|
||||
for entry in s:
|
||||
if len(current) > 1500:
|
||||
out.append(current)
|
||||
current = ""
|
||||
current += entry
|
||||
if len(current) > 10:
|
||||
out.append(current)
|
||||
if len(out) > 0:
|
||||
self.relay_hub_service.send_message("member_logger", None, out, out)
|
||||
@@ -0,0 +1,278 @@
|
||||
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.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")
|
||||
|
||||
@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 <highlight>{desc}</highlight>"
|
||||
return f"Error! You cant do that. Your accesslevel must be equal or higher than " \
|
||||
f"<highlight>{self.raid.leader.name}</highlight>'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 <highlight>{bot}</highlight>"
|
||||
else:
|
||||
return f"The bot <highlight>{bot}</highlight> 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"<highlight>{self.raid.leader.name}</highlight>'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 <highlight>{level}</highlight>"
|
||||
return f"Error! You cant do that. Your accesslevel must be equal or higher than " \
|
||||
f"<highlight>{self.raid.leader.name}</highlight>'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 <highlight>{step}</highlight>"
|
||||
return f"Error! You cant do that. Your accesslevel must be equal or higher than " \
|
||||
f"<highlight>{self.raid.leader.name}</highlight>'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"])
|
||||
self.raid.bot = self.bot.get_char_name()
|
||||
self.raid.last_action = time.time()
|
||||
spam = f"""
|
||||
________________
|
||||
<yellow>
|
||||
You started a raid... but I need some more details about it,
|
||||
please fill in this form: {self.raid_settings(request, "")}
|
||||
</yellow>
|
||||
________________
|
||||
"""
|
||||
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 "<a href=\"text://%s\">%s</a>" % (textwrap.dedent(msg), 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"<highlight>{self.util.time_to_readable(self.raid.last_spam + 5 * 60 - last)}</highlight> " \
|
||||
f"before sending another one."
|
||||
click_here = blob("click here",
|
||||
f"""
|
||||
<header>How to join the Raid</header>
|
||||
|
||||
<notice>Step 1:</notice>
|
||||
- Please join {self.raid.bot}: [{self.text.make_chatcmd("Join", f"/tell {self.raid.bot} join")}]
|
||||
|
||||
<notice>Step 2:</notice>
|
||||
- Please go LFT, to show your interest: [{self.text.make_chatcmd("Go LFT", f"/lft » <green>{self.raid.bot}</green>")}]
|
||||
|
||||
<notice>Step 3:</notice>
|
||||
Wait at the raid starting location.
|
||||
Stepping is scheduled for <highlight>{self.raid.raid_time}</highlight>
|
||||
Currently it is <highlight>{(datetime.now(timezone.utc).strftime("%H:%M"))} GMT-0</highlight>
|
||||
""")
|
||||
spam = f"""
|
||||
________________
|
||||
|
||||
<yellow><green>{request.sender.name}</green> has invited you to join a <notice>{self.raid.raid_desc}</notice> Raid
|
||||
Type <notice>/tell {self.raid.bot} join</notice> to participate
|
||||
or {click_here}</yellow>
|
||||
________________
|
||||
"""
|
||||
subtile = f"""<yellow>[<green>{request.sender.name}</green>]: Raid Starting: <notice>{self.raid.raid_desc}</notice> -- use <notice>/tell {self.raid.bot} join</notice> to participate or {click_here}</yellow></yellow> """
|
||||
# noinspection SqlAggregates
|
||||
players = self.db.query("SELECT p.*, a.subtile_spam, a.raid_invite, a.raid_spam 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"Sending invites to {len(players)} Players...")
|
||||
info = "Sent invites to:"
|
||||
prof = ""
|
||||
for i in players:
|
||||
if prof != i.profession:
|
||||
info += "\n\n<img src=tdb://id:GFX_GUI_FRIENDLIST_SPLITTER>"
|
||||
info += "\n" + "<img src=rdb://" + str(
|
||||
self.profs.get(i.profession)) + "><tab><green>%s<end>\n" % i.profession
|
||||
info += "<img src=tdb://id:GFX_GUI_FRIENDLIST_SPLITTER>"
|
||||
prof = i.profession
|
||||
if self.ban.get_ban(i.char_id):
|
||||
continue
|
||||
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}/<green>{i.ai_level: >2}</green>) - {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 {len(players)} invites! [{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 <myname> raid level ' + str(i))}]"
|
||||
|
||||
bots = " -"
|
||||
for i in ["allianceraid", "aapf", "theallianz"]:
|
||||
bots += f" [{self.text.make_chatcmd(i, '/tell <myname> raid bot ' + str(i))}]"
|
||||
|
||||
description = " -"
|
||||
for i in ["S42", "Pandemonium", "APF's"]:
|
||||
description += f" [{self.text.make_chatcmd(i, '/tell <myname> 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 += "<br> -"
|
||||
step += f" [{self.text.make_chatcmd(i, '/tell <myname> raid time ' + str(i))}]"
|
||||
count += 1
|
||||
# noinspection LongLine
|
||||
settings = self.text.format_page("Raid Settings",
|
||||
textwrap.dedent(
|
||||
f"""
|
||||
<header>Raid Settings</header>
|
||||
|
||||
<notice>Set the minimum level [<yellow>{self.raid.min_level}</yellow>]:</notice>
|
||||
{level_rest}
|
||||
|
||||
<notice>Change the Description [<yellow>{self.raid.raid_desc}</yellow>]:</notice>
|
||||
{description}
|
||||
|
||||
<notice>Change the Raidbot [<yellow>{self.raid.bot}</yellow>]:</notice>
|
||||
{bots}
|
||||
|
||||
<notice>Change the raid stepping time [<yellow>{self.raid.raid_time}</yellow>]:</notice>
|
||||
-> Current Time: {(datetime.now(timezone.utc).strftime("%H:%M"))} GMT-0
|
||||
{step}
|
||||
|
||||
<notice>Send the invites!</notice>
|
||||
[{self.text.make_chatcmd("send the spam!", "/tell <myname> raid invite")}]
|
||||
|
||||
<notice>End the raid</notice>
|
||||
[{self.text.make_chatcmd("stop it", "/tell <myname> raid stop")}]
|
||||
"""))
|
||||
return settings
|
||||
return f"Error! You cant do that. Your accesslevel must be equal or higher than " \
|
||||
f"<highlight>{self.raid.leader.name}</highlight>'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"<highlight>{self.raid.raid_desc}</highlight>; I'll stop it for you.")
|
||||
self.raid = None
|
||||
@@ -0,0 +1,99 @@
|
||||
import os
|
||||
import platform
|
||||
import threading
|
||||
import time
|
||||
from threading import Thread
|
||||
|
||||
import psutil
|
||||
|
||||
from core.buddy_service import BuddyService
|
||||
from core.chat_blob import ChatBlob
|
||||
from core.command_alias_service import CommandAliasService
|
||||
from core.command_param_types import Const
|
||||
from core.db import DB
|
||||
from core.decorators import instance, command
|
||||
from core.lookup.pork_service import PorkService
|
||||
from core.message_hub_service import MessageHubService
|
||||
from core.text import Text
|
||||
from core.tyrbot import Tyrbot
|
||||
from core.util import Util
|
||||
from modules.core.accounting.services.access_service import AccessService
|
||||
|
||||
|
||||
# noinspection DuplicatedCode
|
||||
@instance()
|
||||
class StatController:
|
||||
threads = {}
|
||||
letters = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
|
||||
"v", "w", "x", "y", "z", "others", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
|
||||
pork_uri = "https://people.anarchy-online.com/people/lookup/orgs.html?l=%s"
|
||||
single_org_uri = "https://people.anarchy-online.com/org/stats/d/5/name/%d/basicstats.xml?data_type=json"
|
||||
|
||||
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.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.access_service: AccessService = registry.get_instance("access_service")
|
||||
self.relay_hub_service: MessageHubService = registry.get_instance("message_hub_service")
|
||||
|
||||
# noinspection LongLine
|
||||
@command(command="debug", params=[Const("verbose", is_optional=True)], access_level="admin",
|
||||
description="Display debugging statistics about igncom")
|
||||
def debug_output(self, _, verbose):
|
||||
def adjust_size(size):
|
||||
factor = 1024
|
||||
for i in [" B", " KB", " MB", " GB", " TB"]:
|
||||
if size > factor:
|
||||
size /= factor
|
||||
else:
|
||||
return f"{size:.3f}{i}"
|
||||
|
||||
threads = ""
|
||||
for thread in threading.enumerate():
|
||||
thread: Thread
|
||||
threads += f" - {thread.name} [Deamon: {'YES' if thread.daemon else 'NO'}] [Alive: {'YES' if thread.is_alive() else 'NO'}]\n"
|
||||
uname = platform.uname()
|
||||
virtual_mem = psutil.virtual_memory()
|
||||
blob = f" <header>::: Summary :::</header>\n" \
|
||||
f" - Tracked orgs: {self.db.query_single('SELECT count(*) as count from orgs').count}\n" \
|
||||
f"<tab>- Tracked characters: {self.db.query_single('SELECT count(*) as count from account a where member>1').count}\n" \
|
||||
f"<tab>- Registered alts: {self.db.query_single('SELECT count(*) as count from account where char_id != main').count}\n" \
|
||||
f"<tab>- Registered mains: {self.db.query_single('SELECT count(*) as count from (SELECT main from account where char_id != main group by main) a').count}\n" \
|
||||
f"<tab>- Banned players: {self.db.query_single('SELECT count(*) as count from account where disabled=1').count}\n" \
|
||||
f"<tab>- Online players: {self.db.query_single('SELECT count(*) as count from online where char_id not in (SELECT char_id from org_bots)').count}\n" \
|
||||
f"<tab>- Online bots: {self.db.query_single('SELECT count(*) as count from online where char_id in (SELECT char_id from org_bots)').count}\n" \
|
||||
f"<tab><tab>- Registered bots: {self.db.query_single('SELECT count(*) as count from org_bots').count}\n" \
|
||||
f" - Active discord accounts: {self.db.query_single('SELECT count(*) as count from account where discord_joined=1').count}\n" \
|
||||
f""" - Inactive discord accounts: {self.db.query_single("SELECT count(*) as count from account where discord_joined=0 and discord_id != 0 and member>1").count}\n""" \
|
||||
f" - Commands issued: {self.db.query_single('SELECT count(*) as count from command_usage').count} [since last reset]\n" \
|
||||
f"<tab>- Most used command: {self.db.query_single('SELECT COUNT(*) AS count, command from command_usage GROUP BY command ORDER BY count desc;').command} [since last reset]\n" \
|
||||
f" - Cached players: {self.db.query_single('SELECT count(*) as count from player').count}\n" \
|
||||
f" - Cached orgs: {self.db.query_single('SELECT count(*) as count from all_orgs').count}\n" \
|
||||
f"\n" \
|
||||
f" <header>::: Bot :::</header>\n" \
|
||||
f" - Memory usage: {adjust_size(psutil.Process(os.getpid()).memory_info().rss)}\n" \
|
||||
f" - Thread count: {len(threading.enumerate())}\n" \
|
||||
f" - Slaves: {len(self.bot.conns)}\n" \
|
||||
f" - Runtime: {self.util.time_to_readable(int(time.time()) - self.bot.start_time, max_levels=None)}\n" \
|
||||
f"\n" \
|
||||
f" <header>::: System :::</header>\n" \
|
||||
f" - System: {uname.system}\n" \
|
||||
f" - Release: {uname.release}\n" \
|
||||
f" - Version: {uname.version}\n" \
|
||||
f" - Processor: {uname.processor} ({psutil.cpu_count(logical=False)}C / {psutil.cpu_count()}T)\n" \
|
||||
f" - CPU Usage: {psutil.cpu_percent()}%\n" \
|
||||
f" - Memory (Total): {adjust_size(virtual_mem.total)}\n" \
|
||||
f" - Memory (Avail): {adjust_size(virtual_mem.available)}\n" \
|
||||
f" - Memory (Used): {adjust_size(virtual_mem.used)}\n" \
|
||||
f" - Database: {self.db.get_type()} using {self.db.pool_size} connections\n" \
|
||||
f"\n"
|
||||
if verbose:
|
||||
blob += f" <header>::: Threads :::</header>\n" \
|
||||
f"{threads}\n" \
|
||||
f"\n"
|
||||
return ChatBlob(f"{self.bot.get_char_name()}'s debugging stats", blob)
|
||||
Reference in New Issue
Block a user