diff --git a/core/igncore.py b/core/igncore.py
index aa257c1..029c624 100644
--- a/core/igncore.py
+++ b/core/igncore.py
@@ -42,7 +42,7 @@ class IgnCore:
self.last_timer_event = 0
self.start_time = int(time.time())
self.major_version = "IGNCore v2.7"
- self.minor_version = "0"
+ self.minor_version = "1"
self.incoming_queue = FifoQueue()
self.mass_message_queue = None
self.conns = DictObject()
diff --git a/modules/core/accounting/account_controller.py b/modules/core/accounting/account_controller.py
index 0359ecb..0cde41d 100644
--- a/modules/core/accounting/account_controller.py
+++ b/modules/core/accounting/account_controller.py
@@ -255,7 +255,8 @@ class AccountController:
perms.append(key)
response += f" Status: {'Open' if alts[0].disabled == 0 else 'Closed'}\n"
response += f" Created at: {self.util.format_datetime(alts[0].created)}\n"
- response += f" Last seen on {last_seen.name} {self.util.time_to_readable(time.time()-last_seen.last_seen)} ago\n"
+ if last_seen:
+ response += f" Last seen on {last_seen.name} {self.util.time_to_readable(time.time()-last_seen.last_seen)} ago\n"
response += f" Permissions: {', '.join(perms)}\n"
if alts[0].discord_joined == 1:
joined = ' (Joined server)'
diff --git a/modules/core/accounting/alts_controller.py b/modules/core/accounting/alts_controller.py
index bef89a4..f28adc9 100644
--- a/modules/core/accounting/alts_controller.py
+++ b/modules/core/accounting/alts_controller.py
@@ -60,30 +60,36 @@ class AltsController:
@command(command="alts", params=[Const("add"), Multiple(Character("character"))], access_level="member",
description="Add an alt")
def alts_add_cmd(self, request, _, alt_chars):
- responses = []
- for alt_char in alt_chars:
- if not alt_char.char_id:
- responses.append(self.getresp("global", "char_not_found", {"char": alt_char.name}))
- continue
- elif alt_char.char_id == request.sender.char_id:
- responses.append(self.getresp("module/alts", "add_fail_self"))
- continue
- manual = self.setting_service.get_value("alt_verification") == "1"
- if manual:
- responses.append(self.register_controller.register_alt(request, _, alt_char))
- continue
- msg, result = self.account_service.add_alt(request.sender.char_id, alt_char.char_id)
+ notfound = []
+ done = []
+ failed = []
+ gotalts = []
+ main = self.account_service.get_main(request.sender.char_id)
+ for alt in alt_chars:
+ if not alt.char_id:
+ notfound.append(alt)
+ continue
+ if main.char_id == alt.char_id:
+ failed.append(self.getresp("module/alts", "add_fail_self"))
+ continue
+ msg, result = self.account_service.add_alt(main.char_id, alt.char_id)
if result:
- self.bot.send_mass_message(alt_char.char_id, self.getresp("module/alts", "add_success_target",
- {"char": request.sender.name}))
- responses.append(self.getresp("module/alts", "add_success_self", {"char": alt_char.name}))
+ done.append(alt.name)
+ self.bot.send_mass_message(alt.char_id, self.getresp("module/alts", "add_success_target", {"char": main.name}))
elif msg == "another_main":
- responses.append(self.getresp("module/alts", "add_fail_already", {"char": alt_char.name}))
- else:
- raise Exception("Unknown msg: " + msg)
+ gotalts.append(alt.name)
- return "\n".join(responses)
+ reply = ""
+ if len(done) > 0:
+ reply += self.getresp("module/alts", "add_success_self",
+ {"char": ", ".join(done)})
+ if len(notfound) > 0:
+ reply += "\n" + self.getresp("global", "char_not_found", {"char": ", ".join(notfound)})
+ if len(gotalts) > 0:
+ reply += "\n" + self.getresp("module/alts", "add_fail_already", {"char": ", ".join(gotalts)})
+ reply += "\n".join(failed)
+ return reply
@command(command="alts", params=[Options(["rem", "remove"]), Character("character")], access_level="member",
description="Remove an alt")
diff --git a/modules/orgbot/broadcast/broadcast_controller.py b/modules/orgbot/broadcast/broadcast_controller.py
new file mode 100644
index 0000000..713970c
--- /dev/null
+++ b/modules/orgbot/broadcast/broadcast_controller.py
@@ -0,0 +1,86 @@
+import time
+
+from core.chat_blob import ChatBlob
+from core.command_param_types import Const, Character, Options, Any
+from core.db import DB
+from core.decorators import instance, command
+from core.translation_service import TranslationService
+
+
+@instance()
+class BroadcastController:
+ MESSAGE_SOURCE = "broadcast"
+
+ def inject(self, registry):
+ self.db: DB = registry.get_instance("db")
+ self.character_service = registry.get_instance("character_service")
+ self.command_service = registry.get_instance("command_service")
+ self.message_hub_service = registry.get_instance("message_hub_service")
+ self.ts: TranslationService = registry.get_instance("translation_service")
+ self.access_service = registry.get_instance("access_service")
+ self.getresp = self.ts.get_response
+
+ def pre_start(self):
+ self.message_hub_service.register_message_source(self.MESSAGE_SOURCE)
+
+ def start(self):
+ self.command_service.register_command_pre_processor(self.command_pre_process)
+ self.db.exec("CREATE TABLE IF NOT EXISTS broadcast (char_id INT NOT NULL PRIMARY KEY, alias VARCHAR(50), created_at INT NOT NULL)")
+
+ @command(command="broadcast", params=[], access_level="admin",
+ description="Show characters/bots on the broadcast list")
+ def broadcast_list_cmd(self, request):
+ data = self.db.query("SELECT p.name, alias FROM broadcast b JOIN player p ON b.char_id = p.char_id ORDER BY p.name ASC")
+
+ blob = ""
+ for row in data:
+ blob += row.name
+ if row.alias:
+ blob += " (" + row.alias + ")"
+ blob += "\n"
+
+ return ChatBlob("Broadcast List (%d)" % len(data), blob)
+
+ @command(command="broadcast", params=[Const("add"), Character("char"), Any("alias", is_optional=True)], access_level="admin",
+ description="Add a character/bot to the broadcast list")
+ def broadcast_add_cmd(self, request, _, char, alias):
+ if char.char_id is None:
+ return self.getresp("global", "char_not_found", {"char": char.name})
+
+ if char.char_id == request.sender.char_id or self.access_service.check_access(char.char_id, "moderator"):
+ return "This Character could not be added to the broadcast list."
+
+ row = self.db.query_single("SELECT 1 FROM broadcast WHERE char_id = ?", [char.char_id])
+
+ if row:
+ return f"Error! {char.name} already exists on the broadcast list."
+ else:
+ self.db.exec("INSERT INTO broadcast (char_id, alias, created_at) VALUES (?, ?, ?)", [char.char_id, alias, int(time.time())])
+ return f"{char.name} has been added to the broadcast list."
+
+ @command(command="broadcast", params=[Options(["rem", "remove"]), Character("char")], access_level="admin",
+ description="Remove a character/bot from the broadcast list")
+ def broadcast_remove_cmd(self, request, _, char):
+ if char.char_id is None:
+ return self.getresp("global", "char_not_found", {"char": char.name})
+
+ row = self.db.query_single("SELECT 1 FROM broadcast WHERE char_id = ?", [char.char_id])
+
+ if not row:
+ return f"Error! {char.name} does not exist on the broadcast list."
+ else:
+ self.db.exec("DELETE FROM broadcast WHERE char_id = ?", [char.char_id])
+ return f"{char.name} has been removed from the broadcast list."
+
+ def command_pre_process(self, context):
+ row = self.db.query_single("SELECT alias FROM broadcast WHERE char_id = ?", [context.char_id])
+ if row:
+ if row.alias:
+ name = row.alias
+ else:
+ name = self.character_service.resolve_char_to_name(context.char_id)
+ formatted_message = f"[{name}] {context.message}"
+ self.message_hub_service.send_message(self.MESSAGE_SOURCE, None, None, formatted_message)
+ return False
+ else:
+ return True
\ No newline at end of file
diff --git a/modules/orgbot/org/org_roster_controller.py b/modules/orgbot/org/org_roster_controller.py
index b225f2a..b610b27 100644
--- a/modules/orgbot/org/org_roster_controller.py
+++ b/modules/orgbot/org/org_roster_controller.py
@@ -2,7 +2,6 @@ import json
import time
import requests
-from mysql.connector.cursor import CursorBase
from core.buddy_service import BuddyService
from core.cache_service import CacheService
@@ -162,7 +161,6 @@ class OrgRosterController:
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, "
diff --git a/modules/standard/wants/wants_controller.py b/modules/standard/wants/wants_controller.py
index 6905d76..941b8d5 100644
--- a/modules/standard/wants/wants_controller.py
+++ b/modules/standard/wants/wants_controller.py
@@ -88,17 +88,17 @@ class WantsController:
main_name = alts[0].name
blob += f"{main_name}\n{want.want}\n\n"
- return ChatBlob("Search Results (%d)" % len(wants), blob)
+ return ChatBlob(f"Search Results ({len(wants)})", blob)
@command(command="wants", params=[Const("list")], access_level="member",
description="Shows all wants")
def wants_all_cmd(self, request, _):
+
sql = "SELECT w.*, p.name FROM wants w \
- LEFT JOIN alts a ON w.char_id = a.char_id \
- LEFT JOIN alts a2 ON (a2.group_id = a.group_id AND a2.status = 2) \
+ LEFT JOIN account a ON w.char_id = a.char_id \
+ LEFT JOIN account a2 ON (a2.main = a.main) \
LEFT JOIN player p ON p.char_id = COALESCE(a2.char_id, w.char_id) \
ORDER BY p.name"
-
data = self.db.query(sql)
blob = ""
@@ -110,4 +110,4 @@ class WantsController:
blob += want.want + "\n"
- return ChatBlob(f"Wants List ({len(data):d})", blob)
+ return ChatBlob(f"Wants List ({len(data)})", blob)