Added the option to !opt-in/opt-out [onlinebot only]
Fixed command & event threading Events are now threaded by event_type (i.e. all buddy_logon events get ran in the same one) Added default preferences Fixed recipe loading for multiple installs (i.e. on different machines)
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
from core.command_service import CommandService
|
||||
from core.decorators import instance, command
|
||||
from modules.core.accounting.preference_controller import PreferenceController
|
||||
from modules.core.accounting.services.account_service import AccountService
|
||||
|
||||
|
||||
@instance(name="account_service", override=True)
|
||||
class AccountServiceOnlineBot(AccountService):
|
||||
registered = []
|
||||
|
||||
def inject(self, registry):
|
||||
super().inject(registry)
|
||||
self.preference_controller: PreferenceController = registry.get_instance("preference_controller")
|
||||
|
||||
def pre_start(self):
|
||||
super().pre_start()
|
||||
self.db.exec("CREATE TABLE IF NOT EXISTS registered (char_id int primary key)")
|
||||
self.registered = [x.char_id for x in self.db.query("SELECT * from registered")]
|
||||
self.access_service.register_access_level("unregistered", 95, self.check_unregistered)
|
||||
|
||||
@command(command="opt-in", params=[],
|
||||
description="Register yourself in the bot",
|
||||
access_level="unregistered")
|
||||
def cmd_opt_in(self, request):
|
||||
player = self.pork.get_character_info(request.sender.name)
|
||||
if player.org_id in self.get_orgs():
|
||||
if self.is_registered((main := self.get_main(request.sender.char_id)).char_id):
|
||||
return "You're already registered."
|
||||
self.db.exec("INSERT IGNORE INTO registered VALUES (?)", [main.char_id])
|
||||
pref_autoinvite = int(self.setting_service.get_value("pref_autoinvite"))
|
||||
pref_raidinvite = int(self.setting_service.get_value("pref_raidinvite"))
|
||||
pref_raidspam = int(self.setting_service.get_value("pref_raidspam"))
|
||||
pref_newsspam = int(self.setting_service.get_value("pref_newsspam"))
|
||||
self.registered.append(main.char_id)
|
||||
|
||||
self.preference_controller.set_pref(main.char_id, "news", pref_newsspam)
|
||||
self.preference_controller.set_pref(main.char_id, "raidspam", pref_raidspam)
|
||||
self.preference_controller.set_pref(main.char_id, "autoinvite", pref_autoinvite)
|
||||
|
||||
# This one is of no use in Onlinebots,
|
||||
# as the command taking advantage of it
|
||||
# is only implemented in the raidbot modules.
|
||||
# raidspam is used instead.
|
||||
self.preference_controller.set_pref(main.char_id, "raidinvite", pref_raidinvite)
|
||||
|
||||
return "You've been registered successfully, and your preferences have been set to the defaults."
|
||||
|
||||
@command(command="opt-out", params=[],
|
||||
description="Unregister yourself from the bot",
|
||||
access_level="member")
|
||||
def cmd_opt_out(self, request):
|
||||
main = self.get_main(request.sender.char_id)
|
||||
if self.is_registered(main.char_id):
|
||||
self.db.exec("DELETE FROM registered where char_id = ?", [main.char_id])
|
||||
self.registered.remove(main.char_id)
|
||||
self.db.exec("UPDATE account SET disabled=1 where char_id=?", [main.char_id])
|
||||
return "You've been unregistered successfully. For re-registering, " \
|
||||
"you may need to contact an Administrator, " \
|
||||
"as you may only register once as a spam protection. " \
|
||||
"Further tells will get ignored."
|
||||
else:
|
||||
return "You're not registered, and thus cannot unregister yourself."
|
||||
|
||||
def is_registered(self, char_id):
|
||||
return char_id in self.registered
|
||||
|
||||
def simple_checks(self, account):
|
||||
main = account.get("main", -1)
|
||||
if main and main in self.registered:
|
||||
return super().simple_checks(account)
|
||||
return False
|
||||
|
||||
def check_unregistered(self, char_id) -> bool:
|
||||
account = self.get_account(char_id) or {}
|
||||
return super().simple_checks(account)
|
||||
|
||||
def check_member(self, char_id) -> bool:
|
||||
account = self.get_account(char_id) or {}
|
||||
if self.simple_checks(account):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@instance(name="command_service", override=True)
|
||||
class AccountServiceOnlineBot(CommandService):
|
||||
def access_denied_response(self, message, sender, cmd_config, reply):
|
||||
self.relay_hub_service.send_message("access_denied_logger", sender, f"[DENIED] {sender.name}: {message}",
|
||||
f"[DENIED] {sender.name}: {message}")
|
||||
|
||||
if sender.access_level["label"] != "all":
|
||||
if sender.access_level['label'] == "unregistered":
|
||||
self.bot.send_mass_message(sender.char_id,
|
||||
"You are not registered yet. To gain access to my commands, you'll need to use <highlight><symbol>opt-in</highlight>")
|
||||
return
|
||||
self.bot.send_mass_message(sender.char_id, self.getresp("global", "access_denied"))
|
||||
@@ -76,23 +76,23 @@ class OrgController:
|
||||
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)
|
||||
sender.reply(f"Adding the organisation <highlight>{orgs.org_name}<end> to the roster...")
|
||||
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
|
||||
return f"The organisation <highlight>{orgs.org_name}<end> is in the roster already."
|
||||
elif len(orgs) == 0:
|
||||
return "No org with the name <highlight>%s<end> was found on PoRK." % search
|
||||
return f"No org with the name <highlight>{search}<end> was found on PoRK."
|
||||
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)
|
||||
blob += f'[{self.text.make_chatcmd("Add", f"/tell <myname> orgs add {org.org_id}")}]' \
|
||||
f'[{self.text.make_chatcmd("More", f"/tell <myname> org info {org.org_id}")}]' \
|
||||
f' <highlight>{org.org_name}<end> (<highlight>{org.org_id}<end>) ' \
|
||||
f'<{org.faction.lower()}>{org.faction}<end> [<highlight>{org.member_count}<end> members]' \
|
||||
f'<br><pagebreak>'
|
||||
return ChatBlob("Pick an Org", blob)
|
||||
|
||||
@command(command="orgs", params=[Const("rem"), Any("Organisation")], access_level="admin",
|
||||
@@ -109,19 +109,19 @@ class OrgController:
|
||||
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
|
||||
return f"Removed the organisation <highlight>{orgs.org_name}<end> from the roster."
|
||||
else:
|
||||
return "The organisation <highlight>%s<end> is not on the roster list." % orgs.org_name
|
||||
return f"The organisation <highlight>{orgs.org_name}<end> is not on the roster list."
|
||||
elif len(orgs) == 0:
|
||||
return "The organisation <highlight>%s<end> is not on the roster list." % search
|
||||
return f"The organisation <highlight>{search}<end> is not on the roster list."
|
||||
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)
|
||||
blob += f'[{self.text.make_chatcmd("Remove", f"/tell <myname> orgs remove {org.org_id}")}]' \
|
||||
f'[{self.text.make_chatcmd("More", f"/tell <myname> org info {org.org_id}")}]' \
|
||||
f' <highlight>{org.org_name}<end> (<highlight>{org.org_id}<end>) ' \
|
||||
f'<{org.faction.lower()}>{org.faction}<end> [<highlight>{org.member_count}<end> members]' \
|
||||
f'<br><pagebreak>'
|
||||
return ChatBlob("Pick an Org", blob)
|
||||
|
||||
@command(command="orgs", params=[Const("list", is_optional=True)], access_level="member",
|
||||
@@ -169,7 +169,7 @@ class OrgController:
|
||||
continue
|
||||
data.append((int(match[0]), match[1], int(match[2]), match[4], start))
|
||||
count += 1
|
||||
self.logger.info("Batch %s done!" % letter)
|
||||
self.logger.info(f"Batch {letter} done!")
|
||||
|
||||
with self.db.pool.get_connection() as conn:
|
||||
with conn.cursor() as cur:
|
||||
@@ -183,7 +183,7 @@ class OrgController:
|
||||
"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.logger.info(f"Successfully fetched {count} orgs in {time.time() - start:.2f} seconds.")
|
||||
self.threads.pop('orgdiscover', None)
|
||||
|
||||
if "orgdiscover" not in self.threads.keys():
|
||||
@@ -229,7 +229,7 @@ class OrgController:
|
||||
"level": char_info["LEVELX"],
|
||||
"ai_level": char_info["ALIENLEVEL"],
|
||||
"ranks": 0}))
|
||||
self.logger.info("Organisation %s has been updated." % org.org_name)
|
||||
self.logger.info(f"Organisation {org.org_name} has been updated.")
|
||||
self.account_service.create_users(accounts)
|
||||
if len(data) > 1:
|
||||
with self.db.lock:
|
||||
@@ -286,8 +286,9 @@ class OrgController:
|
||||
"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))
|
||||
self.logger.info(
|
||||
f"Successfully fetched {len(data)} players from {len(ours)} orgs "
|
||||
f"in {time.time() - start:.2f} seconds. - ")
|
||||
del self.threads['roster']
|
||||
|
||||
if "roster" not in self.threads.keys():
|
||||
@@ -330,11 +331,11 @@ class OrgController:
|
||||
"pvp_rating, pvp_title, source, last_updated) VALUES "
|
||||
"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", data)
|
||||
self.account_service.create_users(accounts)
|
||||
self.logger.info("Organisation %s added!" % org_name)
|
||||
self.logger.info(f"Organisation {org_name} added!")
|
||||
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))
|
||||
self.logger.info(f"Successfully fetched {count} players in {time.time() - start} seconds.")
|
||||
del self.threads[org_id]
|
||||
|
||||
def remove_single(self, org_id, org_name):
|
||||
@@ -344,7 +345,7 @@ class OrgController:
|
||||
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)
|
||||
self.logger.info(f"Organisation {org_name} removed!")
|
||||
del self.threads[org_id]
|
||||
|
||||
def log(self, blob, duration):
|
||||
|
||||
@@ -15,6 +15,7 @@ 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
|
||||
|
||||
|
||||
@@ -62,6 +63,7 @@ class RaidController:
|
||||
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")
|
||||
@@ -119,7 +121,9 @@ class RaidController:
|
||||
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()
|
||||
# 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"""
|
||||
________________
|
||||
@@ -146,7 +150,7 @@ class RaidController:
|
||||
return "There's no raid running."
|
||||
|
||||
def blob(label, msg):
|
||||
return "<a href=\"text://%s\">%s</a>" % (textwrap.dedent(msg), textwrap.dedent(label))
|
||||
return f"<a href=\"text://{textwrap.dedent(msg)}\">{textwrap.dedent(label)}</a>"
|
||||
|
||||
last = time.time()
|
||||
if self.raid.last_spam + 5 * 60 > last:
|
||||
@@ -178,7 +182,7 @@ class RaidController:
|
||||
"""
|
||||
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 "
|
||||
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) "
|
||||
@@ -189,18 +193,20 @@ class RaidController:
|
||||
"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...")
|
||||
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<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 += "\n" + f"<img src=rdb://{self.profs.get(i.profession)}><tab><green>{i.profession}<end>\n"
|
||||
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:
|
||||
@@ -211,7 +217,7 @@ class RaidController:
|
||||
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)}]")
|
||||
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")
|
||||
|
||||
Reference in New Issue
Block a user