Compare commits
8 commits
mythica-de
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 92fda8086e | |||
|
|
28b9fd1aee | ||
| 24c7c403ba | |||
|
|
0e7cf0f988 | ||
| 424d65233b | |||
|
|
6d7398d055 | ||
|
|
cc7ca06182 | ||
| ffdeacc0c4 |
8 changed files with 108 additions and 4 deletions
|
|
@ -9,6 +9,8 @@
|
|||
},
|
||||
"loadDbcs": true,
|
||||
"hideGameMasters": true,
|
||||
"hideBotAccounts": true,
|
||||
"botAccountPatterns": "RNDBOT%",
|
||||
"transmogModule": false,
|
||||
"useZamCdn": false,
|
||||
"realms": [
|
||||
|
|
|
|||
|
|
@ -40,7 +40,19 @@ services:
|
|||
|
||||
# --- behaviour -----------------------------------------------------
|
||||
ACORE_ARMORY_LOAD_DBCS: ${ARMORY_LOAD_DBCS:-1}
|
||||
ACORE_ARMORY_HIDE_GAME_MASTERS: ${ARMORY_HIDE_GMS:-1}
|
||||
# Off by default here: GM accounts on this realm belong to real
|
||||
# players who should appear in the armory like anyone else. Set to
|
||||
# 1 to hide them from search and 404 their character pages.
|
||||
ACORE_ARMORY_HIDE_GAME_MASTERS: ${ARMORY_HIDE_GMS:-0}
|
||||
|
||||
# Playerbots are ordinary accounts, not game masters, so the GM
|
||||
# filter does not touch them. Without this the armory lists ~1350
|
||||
# bots against ~29 real characters.
|
||||
# Comma-separated LIKE patterns. RNDBOT% covers the Playerbots
|
||||
# accounts; ahouse is the auction-house bot, which owns 9 mule
|
||||
# characters. Add further service accounts here as they appear.
|
||||
ACORE_ARMORY_HIDE_BOT_ACCOUNTS: ${ARMORY_HIDE_BOTS:-1}
|
||||
ACORE_ARMORY_BOT_ACCOUNT_PATTERNS: ${ARMORY_BOT_PATTERNS:-RNDBOT%,ahouse}
|
||||
ACORE_ARMORY_TRANSMOG_MODULE: ${ARMORY_TRANSMOG:-0}
|
||||
|
||||
# 0 = serve 3D model assets from the local data directory.
|
||||
|
|
|
|||
|
|
@ -129,5 +129,12 @@ FLUSH PRIVILEGES;
|
|||
page rather than shipping both.
|
||||
- **The Dockerfile builds from `node:16`**, which is end-of-life. It builds and
|
||||
runs fine; bumping it is a separate change from getting this deployed.
|
||||
- **`hideGameMasters` defaults to on** here, so GM characters are hidden from
|
||||
search and return 404.
|
||||
- **`hideGameMasters` is off** in this stack, unlike upstream. GM accounts on
|
||||
this realm belong to real players — `Spinnaker` among them — so hiding them
|
||||
would hide people who should be listed. Set `ARMORY_HIDE_GMS=1` to restore
|
||||
upstream behaviour.
|
||||
- **Service accounts are hidden** via `hideBotAccounts` / `botAccountPatterns`,
|
||||
a comma-separated list of LIKE patterns defaulting to `RNDBOT%,ahouse` — the
|
||||
Playerbots accounts and the auction-house bot, which owns 9 mule characters.
|
||||
None of them are game masters, so the GM filter never touched them. Add more
|
||||
with `ARMORY_BOT_PATTERNS`, or set `ARMORY_HIDE_BOTS=0` to show them all.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ export class Config {
|
|||
public iframeMode: IIframeModeConfig;
|
||||
public loadDbcs: boolean;
|
||||
public hideGameMasters: boolean;
|
||||
public hideBotAccounts: boolean;
|
||||
public botAccountPatterns: string;
|
||||
public transmogModule: boolean;
|
||||
public useZamCdn: boolean;
|
||||
public realms: IRealmConfig[];
|
||||
|
|
|
|||
|
|
@ -60,4 +60,37 @@ export class Utils {
|
|||
background: obj.background.toString().padStart(padLength, "0"),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote a configuration-supplied string for inline use in SQL.
|
||||
*
|
||||
* The bot-account filter has to be spliced into join clauses that the query
|
||||
* builder emits as raw SQL, so it cannot be passed as a bound parameter the
|
||||
* way a normal value would be. The value comes from the operator's own
|
||||
* config rather than from a request, but quoting it keeps a stray apostrophe
|
||||
* from producing a broken or surprising query.
|
||||
*/
|
||||
public static quoteSqlString(value: string): string {
|
||||
return `'${String(value).replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the LIKE test that identifies non-player accounts.
|
||||
*
|
||||
* `patterns` is a comma-separated list, so a realm can name several service
|
||||
* accounts at once — Playerbots plus an auction-house bot, say. Returns an
|
||||
* empty string when nothing is configured, which callers treat as "do not
|
||||
* filter" rather than emitting an always-false clause.
|
||||
*/
|
||||
public static botAccountFilter(column: string, patterns: string): string {
|
||||
const list = String(patterns ?? "")
|
||||
.split(",")
|
||||
.map((p) => p.trim())
|
||||
.filter((p) => p.length > 0);
|
||||
|
||||
if (list.length === 0) {
|
||||
return "";
|
||||
}
|
||||
return `(${list.map((p) => `${column} LIKE ${Utils.quoteSqlString(p)}`).join(" OR ")})`;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -342,16 +342,32 @@ export class CharacterController {
|
|||
|
||||
private async getCharacterData(realm: IRealmConfig, character: string | number): Promise<ICharacterData> {
|
||||
const where = typeof character === "string" ? "LOWER(`characters`.`name`) = LOWER(?)" : "`characters`.`guid` = ?";
|
||||
|
||||
// Bot accounts are hidden the same way game masters are: left join the
|
||||
// rows we do not want, then require the join to have missed. Keeping the
|
||||
// pattern inline rather than bound avoids disturbing the positional
|
||||
// values below.
|
||||
const botFilter = this.armory.config.hideBotAccounts
|
||||
? Utils.botAccountFilter("`bot_account`.`username`", this.armory.config.botAccountPatterns)
|
||||
: "";
|
||||
const botJoin =
|
||||
botFilter === ""
|
||||
? ""
|
||||
: `LEFT JOIN \`${realm.authDatabase}\`.\`account\` AS \`bot_account\` ON \`bot_account\`.\`id\` = \`characters\`.\`account\` AND ${botFilter}`;
|
||||
const botWhere = botFilter === "" ? "" : "AND `bot_account`.`id` IS NULL";
|
||||
|
||||
const [rows] = await this.armory.getCharactersDb(realm.name).query({
|
||||
sql: `
|
||||
SELECT \`characters\`.\`guid\`, \`characters\`.\`name\`, \`race\`, \`class\`, \`gender\`, \`level\`, \`skin\`, \`face\`, \`hairStyle\`, \`hairColor\`, \`facialStyle\`, \`playerFlags\`, \`online\`, \`guild\`.\`name\` AS \`guild\`
|
||||
SELECT \`characters\`.\`guid\`, \`characters\`.\`name\`, \`characters\`.\`race\`, \`characters\`.\`class\`, \`characters\`.\`gender\`, \`characters\`.\`level\`, \`characters\`.\`skin\`, \`characters\`.\`face\`, \`characters\`.\`hairStyle\`, \`characters\`.\`hairColor\`, \`characters\`.\`facialStyle\`, \`characters\`.\`playerFlags\`, \`characters\`.\`online\`, \`guild\`.\`name\` AS \`guild\`
|
||||
FROM \`characters\`
|
||||
LEFT JOIN \`guild_member\` ON \`guild_member\`.\`guid\` = \`characters\`.\`guid\`
|
||||
LEFT JOIN \`guild\` ON \`guild\`.\`guildid\` = \`guild_member\`.\`guildid\`
|
||||
LEFT JOIN \`${realm.authDatabase}\`.\`account_access\` ON \`account_access\`.\`id\` = \`characters\`.\`account\` AND \`account_access\`.\`RealmID\` IN (-1, ${realm.realmId}) AND \`account_access\`.\`gmlevel\` > 0
|
||||
${botJoin}
|
||||
WHERE
|
||||
${where}
|
||||
AND (\`account_access\`.\`id\` IS NULL OR ? = 0)
|
||||
${botWhere}
|
||||
`,
|
||||
values: [character, this.armory.config.hideGameMasters ? 1 : 0],
|
||||
timeout: this.armory.config.dbQueryTimeout,
|
||||
|
|
|
|||
|
|
@ -93,6 +93,22 @@ export class GuildController {
|
|||
ssp = ssp.where("`account_access`.`id` IS NULL");
|
||||
}
|
||||
|
||||
const botFilter = this.armory.config.hideBotAccounts
|
||||
? Utils.botAccountFilter(`\`${realm.authDatabase}\`.\`account\`.\`username\``, this.armory.config.botAccountPatterns)
|
||||
: "";
|
||||
if (botFilter !== "") {
|
||||
ssp.joins.push({
|
||||
table1: "characters",
|
||||
column1: "account",
|
||||
table2: "account",
|
||||
column2: "id",
|
||||
database2: realm.authDatabase,
|
||||
kind: "LEFT",
|
||||
where: `AND ${botFilter}`,
|
||||
});
|
||||
ssp = ssp.where(`\`${realm.authDatabase}\`.\`account\`.\`id\` IS NULL`);
|
||||
}
|
||||
|
||||
const result = await ssp.where("`guildid` = ?", guildId).where("`deleteInfos_Account` IS NULL").run(this.armory.config.dbQueryTimeout);
|
||||
|
||||
const ranks = await this.getGuildRanks(realm, guildId);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,22 @@ export class IndexController {
|
|||
ssp = ssp.where("`account_access`.`id` IS NULL");
|
||||
}
|
||||
|
||||
const botFilter = this.armory.config.hideBotAccounts
|
||||
? Utils.botAccountFilter(`\`${realm.authDatabase}\`.\`account\`.\`username\``, this.armory.config.botAccountPatterns)
|
||||
: "";
|
||||
if (botFilter !== "") {
|
||||
ssp.joins.push({
|
||||
table1: "characters",
|
||||
column1: "account",
|
||||
table2: "account",
|
||||
column2: "id",
|
||||
database2: realm.authDatabase,
|
||||
kind: "LEFT",
|
||||
where: `AND ${botFilter}`,
|
||||
});
|
||||
ssp = ssp.where(`\`${realm.authDatabase}\`.\`account\`.\`id\` IS NULL`);
|
||||
}
|
||||
|
||||
const result = await ssp.where("`deleteInfos_Account` IS NULL").run(this.armory.config.dbQueryTimeout);
|
||||
|
||||
res.json({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue