Show non-eliminated loser's manager tag in Scored Matches notifications
All checks were successful
🚀 Deploy / 🧪 Test (pull_request) Successful in 3m7s
🚀 Deploy / ʦ🔍 Typecheck & Lint (pull_request) Successful in 1m24s
🚀 Deploy / 🐳 Build (pull_request) Has been skipped
🚀 Deploy / 🚀 Deploy (pull_request) Has been skipped
🚀 Deploy / 🧪 Test (push) Successful in 3m5s
🚀 Deploy / ʦ🔍 Typecheck & Lint (push) Successful in 1m22s
🚀 Deploy / 🐳 Build (push) Successful in 1m12s
🚀 Deploy / 🚀 Deploy (push) Successful in 12s
All checks were successful
🚀 Deploy / 🧪 Test (pull_request) Successful in 3m7s
🚀 Deploy / ʦ🔍 Typecheck & Lint (pull_request) Successful in 1m24s
🚀 Deploy / 🐳 Build (pull_request) Has been skipped
🚀 Deploy / 🚀 Deploy (pull_request) Has been skipped
🚀 Deploy / 🧪 Test (push) Successful in 3m5s
🚀 Deploy / ʦ🔍 Typecheck & Lint (push) Successful in 1m22s
🚀 Deploy / 🐳 Build (push) Successful in 1m12s
🚀 Deploy / 🚀 Deploy (push) Successful in 12s
In playoff "Scored Matches" Discord notifications, the winner's manager tag was shown unconditionally but the loser's was gated behind isLoserNotifiable, which is only true when the loser scored or was eliminated. A World Cup semifinal loser (drops to the 3rd-place playoff) or an AFL Qualifying-Final loser (drops to a Semi Final) is neither, so their tag was dropped: • Argentina (philosohraptors) def. England Decouple the loser's display name from the ping gate, mirroring the winner: loserUsername is now shown whenever the loser's team is drafted, while the @-ping (loserDiscordUserId) stays gated by showLoser. A still-alive loser is named for context but not pinged: • Argentina (philosohraptors) def. England (elementsoul) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
7e578c714c
commit
932f36ca07
2 changed files with 41 additions and 3 deletions
|
|
@ -1940,8 +1940,10 @@ export async function recalculateAffectedLeagues(
|
||||||
// in the World Cup) does not qualify on its own — their owner hasn't earned anything yet.
|
// in the World Cup) does not qualify on its own — their owner hasn't earned anything yet.
|
||||||
// When a match qualifies because the loser is owned, the winner's manager tag is still
|
// When a match qualifies because the loser is owned, the winner's manager tag is still
|
||||||
// shown for context (who beat them), but the winner is not Discord-pinged.
|
// shown for context (who beat them), but the winner is not Discord-pinged.
|
||||||
// Losers who advance to another match (loserAdvances=true, e.g. NBA 7v8 → PIR2) have
|
// Both managers' tags are always shown for context when their teams are drafted; the
|
||||||
// showLoser=false and are correctly suppressed.
|
// showLoser flag (isLoserNotifiable) only gates whether the loser is @-pinged — a loser
|
||||||
|
// who advanced rather than being eliminated (loserAdvances=true, e.g. NBA 7v8 → PIR2, or
|
||||||
|
// a World Cup semifinal loser) is named but not pinged.
|
||||||
let scoredMatches: ScoredMatch[] | undefined;
|
let scoredMatches: ScoredMatch[] | undefined;
|
||||||
if (allCompletedMatches.length > 0) {
|
if (allCompletedMatches.length > 0) {
|
||||||
const relevant = allCompletedMatches.filter(
|
const relevant = allCompletedMatches.filter(
|
||||||
|
|
@ -1974,7 +1976,12 @@ export async function recalculateAffectedLeagues(
|
||||||
winnerName: x.m.winnerName ?? "",
|
winnerName: x.m.winnerName ?? "",
|
||||||
loserName: x.m.loserName ?? "",
|
loserName: x.m.loserName ?? "",
|
||||||
winnerUsername: x.winnerOwnerId ? usernameByUserId.get(x.winnerOwnerId) : undefined,
|
winnerUsername: x.winnerOwnerId ? usernameByUserId.get(x.winnerOwnerId) : undefined,
|
||||||
loserUsername: x.showLoser && x.loserOwnerId ? usernameByUserId.get(x.loserOwnerId) : undefined,
|
// Show the loser's manager tag whenever their team is drafted, mirroring the
|
||||||
|
// winner above — even when the loser advances rather than being eliminated
|
||||||
|
// (World Cup semifinal → 3rd-place playoff, AFL Qualifying Final → Semi Final).
|
||||||
|
// The @-ping stays gated by showLoser (loserDiscordUserId below): a still-alive
|
||||||
|
// loser who neither scored nor was eliminated is named for context but not pinged.
|
||||||
|
loserUsername: x.loserOwnerId ? usernameByUserId.get(x.loserOwnerId) : undefined,
|
||||||
winnerDiscordUserId: x.winnerScoreChanged && x.winnerOwnerId ? discordIdByUserId.get(x.winnerOwnerId) : undefined,
|
winnerDiscordUserId: x.winnerScoreChanged && x.winnerOwnerId ? discordIdByUserId.get(x.winnerOwnerId) : undefined,
|
||||||
loserDiscordUserId: x.showLoser && x.loserOwnerId ? discordIdByUserId.get(x.loserOwnerId) : undefined,
|
loserDiscordUserId: x.showLoser && x.loserOwnerId ? discordIdByUserId.get(x.loserOwnerId) : undefined,
|
||||||
}))
|
}))
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,37 @@ describe("sendStandingsUpdateNotification", () => {
|
||||||
expect(desc).toContain("• **Sporting (christhrowsrocks)** def. Bodø/Glimt (apatel)");
|
expect(desc).toContain("• **Sporting (christhrowsrocks)** def. Bodø/Glimt (apatel)");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("names a non-eliminated loser for context without @-pinging them", async () => {
|
||||||
|
// Argentina beats England in the World Cup semifinal. Argentina scored, so it's
|
||||||
|
// pinged; England advances to the 3rd-place playoff (not eliminated, no points
|
||||||
|
// change), so its manager is shown by plain username but NOT @-pinged.
|
||||||
|
await sendStandingsUpdateNotification({
|
||||||
|
webhookUrl: WEBHOOK_URL,
|
||||||
|
seasonName: "Diablo League 2026",
|
||||||
|
standings: [{ teamId: "a", teamName: "Alpha", totalPoints: 160, rank: 7 }],
|
||||||
|
previousStandings: new Map([["a", 130]]),
|
||||||
|
scoredMatches: [
|
||||||
|
{
|
||||||
|
winnerName: "Argentina",
|
||||||
|
loserName: "England",
|
||||||
|
winnerUsername: "philosohraptors",
|
||||||
|
winnerDiscordUserId: "111",
|
||||||
|
loserUsername: "elementsoul",
|
||||||
|
// no loserDiscordUserId — still alive, no ping
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const payload = getPayload();
|
||||||
|
const desc = payload.embeds[0].description as string;
|
||||||
|
// Winner scored → rendered as an @-mention; loser is named by plain username.
|
||||||
|
expect(desc).toContain("• **Argentina (<@111>)** def. England (elementsoul)");
|
||||||
|
// England's manager is named but not mentioned/pinged.
|
||||||
|
expect(desc).not.toContain("England (<@");
|
||||||
|
expect(payload.content ?? "").toContain("<@111>");
|
||||||
|
expect(payload.content ?? "").not.toContain("elementsoul");
|
||||||
|
});
|
||||||
|
|
||||||
it("shows winner's manager for context when the match fires due to an owned loser", async () => {
|
it("shows winner's manager for context when the match fires due to an owned loser", async () => {
|
||||||
// Brazil beats Japan (R32, non-scoring). Japan's manager is the reason for the
|
// Brazil beats Japan (R32, non-scoring). Japan's manager is the reason for the
|
||||||
// notification; Brazil's manager is shown for context even though they didn't score.
|
// notification; Brazil's manager is shown for context even though they didn't score.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue