feat(Core/Commands): add .account info (#27160)
This commit is contained in:
parent
5fa7cb00fa
commit
fe5b07e057
9 changed files with 218 additions and 1 deletions
|
|
@ -0,0 +1,7 @@
|
|||
DELETE FROM `rbac_permissions` WHERE `id` = 945;
|
||||
INSERT INTO `rbac_permissions` (`id`, `name`) VALUES
|
||||
(945, 'Command: account info');
|
||||
|
||||
DELETE FROM `rbac_linked_permissions` WHERE `linkedId` = 945;
|
||||
INSERT INTO `rbac_linked_permissions` (`id`, `linkedId`) VALUES
|
||||
(197, 945);
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
DELETE FROM `command` WHERE `name` = 'account info';
|
||||
INSERT INTO `command` (`name`, `security`, `help`) VALUES
|
||||
('account info', 2, 'Syntax: .account info [$account]\nDisplays account level information for $account, given either as an account name or an account id. Defaults to the account of the selected player, or your own account when nothing is selected.');
|
||||
|
||||
DELETE FROM `acore_string` WHERE `entry` IN (35471, 35472, 35473, 35474, 35475, 35476, 35477, 35478, 35479);
|
||||
INSERT INTO `acore_string` (`entry`, `content_default`, `locale_koKR`, `locale_frFR`, `locale_deDE`, `locale_zhCN`, `locale_zhTW`, `locale_esES`, `locale_esMX`, `locale_ruRU`) VALUES
|
||||
(35471, '| Created: {}', '| 생성일: {}', '| Créé le: {}', '| Erstellt: {}', '| 创建时间: {}', '| 建立時間: {}', '| Creada: {}', '| Creada: {}', '| Создан: {}'),
|
||||
(35472, '| Expansion: {}', '| 확장팩: {}', '| Extension: {}', '| Erweiterung: {}', '| 资料片: {}', '| 資料片: {}', '| Expansión: {}', '| Expansión: {}', '| Дополнение: {}'),
|
||||
(35473, '| Locked to country: {}', '| 국가 잠금: {}', '| Verrouillé au pays: {}', '| Gesperrt auf Land: {}', '| 锁定国家: {}', '| 鎖定國家: {}', '| Bloqueada al país: {}', '| Bloqueada al país: {}', '| Привязан к стране: {}'),
|
||||
(35474, '|-- Banned: (Reason: {}, Time: {}, By: {})', '|-- 차단됨: (사유: {}, 기간: {}, 처리자: {})', '|-- Banni: (Raison: {}, Temps: {}, Par: {})', '|-- Gesperrt: (Grund: {}, Zeit: {}, Von: {})', '|-- 封禁: (原因: {}, 时间: {}, 操作者: {})', '|-- 封禁: (原因: {}, 時間: {}, 操作者: {})', '|-- Baneado: (Razón: {}, Tiempo: {}, Por: {})', '|-- Baneado: (Razón: {}, Tiempo: {}, Por: {})', '|-- Заблокирован: (Причина: {}, Время: {}, Кем: {})'),
|
||||
(35475, '| Characters on this realm: {}', '| 이 서버의 캐릭터: {}', '| Personnages sur ce royaume: {}', '| Charaktere auf diesem Realm: {}', '| 该服务器上的角色: {}', '| 該伺服器上的角色: {}', '| Personajes en este reino: {}', '| Personajes en este reino: {}', '| Персонажи в этом мире: {}'),
|
||||
(35476, '|-- {}{} (GUID: {}) - Level {} {} {}', '|-- {}{} (GUID: {}) - 레벨 {} {} {}', '|-- {}{} (GUID: {}) - Niveau {} {} {}', '|-- {}{} (GUID: {}) - Level {} {} {}', '|-- {}{} (GUID: {}) - 等级 {} {} {}', '|-- {}{} (GUID: {}) - 等級 {} {} {}', '|-- {}{} (GUID: {}) - Nivel {} {} {}', '|-- {}{} (GUID: {}) - Nivel {} {} {}', '|-- {}{} (GUID: {}) - Уровень {} {} {}'),
|
||||
(35477, '| No characters on this realm.', '| 이 서버에 캐릭터가 없습니다.', '| Aucun personnage sur ce royaume.', '| Keine Charaktere auf diesem Realm.', '| 该服务器上没有角色。', '| 該伺服器上沒有角色。', '| Sin personajes en este reino.', '| Sin personajes en este reino.', '| Нет персонажей в этом мире.'),
|
||||
(35478, '| Current IP: {}', '| 현재 IP: {}', '| IP actuelle: {}', '| Aktuelle IP: {}', '| 当前 IP: {}', '| 目前 IP: {}', '| IP actual: {}', '| IP actual: {}', '| Текущий IP: {}'),
|
||||
(35479, ' (offline)', ' (오프라인)', ' (hors ligne)', ' (offline)', ' (离线)', ' (離線)', ' (sin conexión)', ' (sin conexión)', ' (не в сети)');
|
||||
|
|
@ -409,6 +409,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
|||
PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME_LIMIT, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate, level FROM characters WHERE deleteDate IS NOT NULL AND deleteInfos_Name LIKE CONCAT('%%', ?, '%%') ORDER BY deleteDate DESC LIMIT 51", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_DEL_INFO, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate, level FROM characters WHERE deleteDate IS NOT NULL ORDER BY deleteDate DESC LIMIT 51", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID, "SELECT guid FROM characters WHERE account = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_INFO_CHARS, "SELECT guid, name, level, race, class, online FROM characters WHERE account = ? AND deleteDate IS NULL ORDER BY level DESC, name ASC", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_PINFO, "SELECT totaltime, level, money, account, race, class, map, zone, gender, health, playerFlags FROM characters WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM character_banned WHERE guid = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PINFO_MAILS, "SELECT SUM(CASE WHEN (checked & 1) THEN 1 ELSE 0 END) AS 'readmail', COUNT(*) AS 'totalmail' FROM mail WHERE `receiver` = ?", CONNECTION_SYNCH);
|
||||
|
|
|
|||
|
|
@ -337,6 +337,7 @@ enum CharacterDatabaseStatements : uint32
|
|||
CHAR_SEL_CHAR_DEL_INFO,
|
||||
|
||||
CHAR_SEL_CHARS_BY_ACCOUNT_ID,
|
||||
CHAR_SEL_ACCOUNT_INFO_CHARS,
|
||||
CHAR_SEL_CHAR_PINFO,
|
||||
CHAR_SEL_PINFO_XP,
|
||||
CHAR_SEL_PINFO_MAILS,
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
|
|||
PrepareStatement(LOGIN_UPD_SET_ACCOUNT_FLAG, "UPDATE account SET Flags = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.gmlevel, a.email, a.reg_mail, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby, a.failed_logins, a.locked, a.OS FROM account a LEFT JOIN account_access aa ON (a.id = aa.id AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM account_banned WHERE id = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_DETAILED, "SELECT a.username, aa.gmlevel, a.email, a.reg_mail, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby, a.failed_logins, a.locked, a.OS, a.expansion, a.Flags, DATE_FORMAT(a.joindate, '%Y-%m-%d %T'), a.totaltime, a.lock_country FROM account a LEFT JOIN account_access aa ON (a.id = aa.id AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ? ORDER BY aa.RealmID DESC LIMIT 1", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_GM_ACCOUNTS, "SELECT a.username, aa.gmlevel FROM account a, account_access aa WHERE a.id=aa.id AND aa.gmlevel >= ? AND (aa.realmid = -1 OR aa.realmid = ?)", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_INFO, "SELECT a.username, a.last_ip, aa.gmlevel, a.expansion FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.id = ? ORDER BY a.last_ip", CONNECTION_SYNCH); // Only used in ".account onlinelist" command
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS_GMLEVEL_TEST, "SELECT 1 FROM account_access WHERE id = ? AND gmlevel > ?", CONNECTION_SYNCH);
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ enum LoginDatabaseStatements : uint32
|
|||
LOGIN_UPD_SET_ACCOUNT_FLAG,
|
||||
LOGIN_SEL_PINFO,
|
||||
LOGIN_SEL_PINFO_BANS,
|
||||
LOGIN_SEL_ACCOUNT_INFO_DETAILED,
|
||||
LOGIN_SEL_GM_ACCOUNTS,
|
||||
LOGIN_SEL_ACCOUNT_INFO,
|
||||
LOGIN_SEL_ACCOUNT_ACCESS_GMLEVEL_TEST,
|
||||
|
|
|
|||
|
|
@ -706,6 +706,7 @@ enum RBACPermissions
|
|||
RBAC_PERM_COMMAND_ACCOUNT_FLAG_LIST = 942,
|
||||
RBAC_PERM_COMMAND_ACCOUNT_FLAG_ADD = 943,
|
||||
RBAC_PERM_COMMAND_ACCOUNT_FLAG_REMOVE = 944,
|
||||
RBAC_PERM_COMMAND_ACCOUNT_INFO = 945,
|
||||
// custom permissions 1000+
|
||||
RBAC_PERM_MAX
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1545,6 +1545,17 @@ enum AcoreStrings
|
|||
LANG_ACCOUNT_FLAG_INVALID = 35467,
|
||||
LANG_ACCOUNT_FLAG_RESERVED = 35468,
|
||||
LANG_ACCOUNT_FLAG_ADDED = 35469,
|
||||
LANG_ACCOUNT_FLAG_REMOVED = 35470
|
||||
LANG_ACCOUNT_FLAG_REMOVED = 35470,
|
||||
|
||||
// Account info command
|
||||
LANG_ACCOUNT_INFO_JOINDATE = 35471,
|
||||
LANG_ACCOUNT_INFO_EXPANSION = 35472,
|
||||
LANG_ACCOUNT_INFO_LOCK_COUNTRY = 35473,
|
||||
LANG_ACCOUNT_INFO_BANNED = 35474,
|
||||
LANG_ACCOUNT_INFO_CHARS = 35475,
|
||||
LANG_ACCOUNT_INFO_CHAR_ENTRY = 35476,
|
||||
LANG_ACCOUNT_INFO_NO_CHARS = 35477,
|
||||
LANG_ACCOUNT_INFO_CURRENT_IP = 35478,
|
||||
LANG_ACCOUNT_INFO_CHAR_OFFLINE = 35479
|
||||
};
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
#include "CommandScript.h"
|
||||
#include "Common.h"
|
||||
#include "CryptoGenerics.h"
|
||||
#include "DBCStores.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "GameTime.h"
|
||||
#include "IPLocation.h"
|
||||
#include "Language.h"
|
||||
#include "Player.h"
|
||||
|
|
@ -89,6 +92,7 @@ public:
|
|||
{ "create", HandleAccountCreateCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_CREATE, Console::Yes },
|
||||
{ "delete", HandleAccountDeleteCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_DELETE, Console::Yes },
|
||||
{ "flag", accountFlagCommandTable },
|
||||
{ "info", HandleAccountInfoCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_INFO, Console::Yes },
|
||||
{ "onlinelist", HandleAccountOnlineListCommand, rbac::RBAC_PERM_COMMAND_ACCOUNT_ONLINE_LIST, Console::Yes },
|
||||
{ "lock", accountLockCommandTable },
|
||||
{ "set", accountSetCommandTable },
|
||||
|
|
@ -681,6 +685,181 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
// Show account-wide info, optionally for another account (by name or id)
|
||||
static bool HandleAccountInfoCommand(ChatHandler* handler, Optional<AccountIdentifier> account)
|
||||
{
|
||||
uint32 accountId;
|
||||
std::string accountName;
|
||||
|
||||
if (account)
|
||||
{
|
||||
accountId = account->GetID();
|
||||
accountName = account->GetName();
|
||||
}
|
||||
else if (Player* target = handler->getSelectedPlayerOrSelf())
|
||||
{
|
||||
accountId = target->GetSession()->GetAccountId();
|
||||
AccountMgr::GetName(accountId, accountName);
|
||||
}
|
||||
else
|
||||
{
|
||||
handler->SendErrorMessage(LANG_CMD_SYNTAX);
|
||||
return false;
|
||||
}
|
||||
|
||||
// The strong check rejects equal security, so inspecting your own account has to be exempted
|
||||
if (handler->GetSession() && handler->GetSession()->GetAccountId() != accountId &&
|
||||
handler->HasLowerSecurityAccount(nullptr, accountId, true))
|
||||
return false;
|
||||
|
||||
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_DETAILED);
|
||||
stmt->SetData(0, int32(realm.Id.Realm));
|
||||
stmt->SetData(1, accountId);
|
||||
|
||||
PreparedQueryResult result = LoginDatabase.Query(stmt);
|
||||
if (!result)
|
||||
{
|
||||
handler->SendErrorMessage(LANG_ACCOUNT_NOT_EXIST, accountName);
|
||||
return false;
|
||||
}
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
accountName = fields[0].Get<std::string>();
|
||||
uint32 security = fields[1].Get<uint8>();
|
||||
std::string eMail = fields[2].Get<std::string>();
|
||||
std::string regMail = fields[3].Get<std::string>();
|
||||
std::string lastIp = fields[4].Get<std::string>();
|
||||
std::string lastLogin = fields[5].Get<std::string>();
|
||||
int64 muteTime = fields[6].Get<uint64>();
|
||||
std::string muteReason = fields[7].Get<std::string>();
|
||||
std::string muteBy = fields[8].Get<std::string>();
|
||||
uint32 failedLogins = fields[9].Get<uint32>();
|
||||
uint8 locked = fields[10].Get<uint8>();
|
||||
std::string OS = fields[11].Get<std::string>();
|
||||
uint32 expansion = fields[12].Get<uint8>();
|
||||
uint32 accountFlags = fields[13].Get<uint32>();
|
||||
std::string joinDate = fields[14].Get<std::string>();
|
||||
uint32 totalTime = fields[15].Get<uint32>();
|
||||
std::string lockCountry = fields[16].Get<std::string>();
|
||||
|
||||
// Empty unless the account is online, in which case it holds the address of the live connection
|
||||
std::string currentIp;
|
||||
uint32 latency = 0;
|
||||
|
||||
if (WorldSession* targetSession = sWorldSessionMgr->FindSession(accountId))
|
||||
{
|
||||
latency = targetSession->GetLatency();
|
||||
muteTime = targetSession->m_muteTime;
|
||||
accountFlags = targetSession->GetAccountFlags();
|
||||
currentIp = targetSession->GetRemoteAddress();
|
||||
}
|
||||
|
||||
if (!handler->GetSession() || handler->GetSession()->GetSecurity() >= AccountTypes(security))
|
||||
{
|
||||
if (IpLocationRecord const* location = sIPLocation->GetLocationRecord(lastIp))
|
||||
lastIp.append(" (").append(location->CountryName).append(")");
|
||||
|
||||
if (!currentIp.empty())
|
||||
if (IpLocationRecord const* location = sIPLocation->GetLocationRecord(currentIp))
|
||||
currentIp.append(" (").append(location->CountryName).append(")");
|
||||
}
|
||||
else
|
||||
{
|
||||
eMail = handler->GetAcoreString(LANG_UNAUTHORIZED);
|
||||
regMail = handler->GetAcoreString(LANG_UNAUTHORIZED);
|
||||
lastIp = handler->GetAcoreString(LANG_UNAUTHORIZED);
|
||||
lastLogin = handler->GetAcoreString(LANG_UNAUTHORIZED);
|
||||
|
||||
if (!currentIp.empty())
|
||||
currentIp = handler->GetAcoreString(LANG_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
int64 banTime = -1;
|
||||
std::string banReason = handler->GetAcoreString(LANG_NO_REASON);
|
||||
std::string bannedBy = handler->GetAcoreString(LANG_UNKNOWN);
|
||||
|
||||
LoginDatabasePreparedStatement* banStmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO_BANS);
|
||||
banStmt->SetData(0, accountId);
|
||||
|
||||
if (PreparedQueryResult banResult = LoginDatabase.Query(banStmt))
|
||||
{
|
||||
Field* banFields = banResult->Fetch();
|
||||
banTime = int64(banFields[1].Get<uint64>() ? 0 : banFields[0].Get<uint32>());
|
||||
bannedBy = banFields[2].Get<std::string>();
|
||||
banReason = banFields[3].Get<std::string>();
|
||||
}
|
||||
|
||||
handler->PSendSysMessage(LANG_PINFO_ACC_ACCOUNT, accountName, accountId, security);
|
||||
|
||||
if (accountFlags)
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_FLAGS_PINFO);
|
||||
for (uint8 i = 0; i < MAX_ACCOUNT_FLAG; ++i)
|
||||
if (accountFlags & (uint32(1) << i))
|
||||
handler->PSendSysMessage(LANG_SUBCMDS_LIST_ENTRY, accountFlagNames[i].full);
|
||||
}
|
||||
|
||||
if (banTime >= 0)
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_INFO_BANNED, banReason,
|
||||
banTime > 0 ? secsToTimeString(banTime - GameTime::GetGameTime().count(), true) : handler->GetAcoreString(LANG_PERMANENTLY), bannedBy);
|
||||
|
||||
// mutetime is only cleared once the muted player logs back in, so an expired mute can still be stored
|
||||
if (muteTime > GameTime::GetGameTime().count())
|
||||
handler->PSendSysMessage(LANG_PINFO_MUTED, muteReason, secsToTimeString(muteTime - GameTime::GetGameTime().count(), true), muteBy);
|
||||
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_INFO_JOINDATE, joinDate);
|
||||
handler->PSendSysMessage(LANG_PINFO_ACC_LASTLOGIN, lastLogin, failedLogins);
|
||||
handler->PSendSysMessage(LANG_PINFO_ACC_OS, OS, latency);
|
||||
handler->PSendSysMessage(LANG_PINFO_ACC_REGMAILS, regMail, eMail);
|
||||
handler->PSendSysMessage(LANG_PINFO_ACC_IP, lastIp, locked ? handler->GetAcoreString(LANG_YES) : handler->GetAcoreString(LANG_NO));
|
||||
|
||||
if (!currentIp.empty())
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_INFO_CURRENT_IP, currentIp);
|
||||
|
||||
// "00" is the default value meaning no country lock is set
|
||||
if (lockCountry != "00")
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_INFO_LOCK_COUNTRY, lockCountry);
|
||||
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_INFO_EXPANSION, expansion);
|
||||
handler->PSendSysMessage(LANG_PINFO_CHR_PLAYEDTIME, secsToTimeString(totalTime, true));
|
||||
|
||||
CharacterDatabasePreparedStatement* charStmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_INFO_CHARS);
|
||||
charStmt->SetData(0, accountId);
|
||||
|
||||
PreparedQueryResult charResult = CharacterDatabase.Query(charStmt);
|
||||
if (!charResult)
|
||||
{
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_INFO_NO_CHARS);
|
||||
return true;
|
||||
}
|
||||
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_INFO_CHARS, uint32(charResult->GetRowCount()));
|
||||
|
||||
LocaleConstant locale = handler->GetSessionDbcLocale();
|
||||
|
||||
do
|
||||
{
|
||||
Field* charFields = charResult->Fetch();
|
||||
ObjectGuid::LowType guid = charFields[0].Get<uint32>();
|
||||
std::string name = charFields[1].Get<std::string>();
|
||||
uint8 level = charFields[2].Get<uint8>();
|
||||
uint8 raceId = charFields[3].Get<uint8>();
|
||||
uint8 classId = charFields[4].Get<uint8>();
|
||||
bool online = charFields[5].Get<bool>();
|
||||
|
||||
ChrRacesEntry const* race = sChrRacesStore.LookupEntry(raceId);
|
||||
ChrClassesEntry const* cls = sChrClassesStore.LookupEntry(classId);
|
||||
|
||||
// Own marker rather than LANG_OFFLINE, whose leading space is missing in some locales
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_INFO_CHAR_ENTRY, handler->playerLink(name),
|
||||
online ? "" : handler->GetAcoreString(LANG_ACCOUNT_INFO_CHAR_OFFLINE), guid, uint32(level),
|
||||
race ? race->name[locale] : handler->GetAcoreString(LANG_UNKNOWN),
|
||||
cls ? cls->name[locale] : handler->GetAcoreString(LANG_UNKNOWN));
|
||||
} while (charResult->NextRow());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Set/Unset the expansion level for an account
|
||||
static bool HandleAccountSetAddonCommand(ChatHandler* handler, char const* args)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue