Skip to content

Commit c67f033

Browse files
committed
Reapply "Add api names and display name area"
This reverts commit 9b457cc.
1 parent 9b457cc commit c67f033

File tree

7 files changed

+146
-5
lines changed

7 files changed

+146
-5
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* @type {import('node-pg-migrate').ColumnDefinitions | undefined}
3+
*/
4+
export const shorthands = undefined;
5+
6+
/**
7+
* @param pgm {import('node-pg-migrate').MigrationBuilder}
8+
* @param run {() => void | undefined}
9+
* @returns {Promise<void> | void}
10+
*/
11+
export const up = (pgm) => {
12+
pgm.addColumn('users', { display_name: { type: 'varchar(255)', notNull: false }})
13+
};
14+
15+
/**
16+
* @param pgm {import('node-pg-migrate').MigrationBuilder}
17+
* @param run {() => void | undefined}
18+
* @returns {Promise<void> | void}
19+
*/
20+
export const down = (pgm) => {
21+
pgm.dropColumn('users', 'display_name');
22+
};

src/api/routers/commands/stats.router.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ statsRouter.openapi(
4646
z.object({
4747
rank: z.number(),
4848
id: z.string(),
49+
name: z.string().nullable(),
4950
mmr: z.number(),
5051
wins: z.number(),
5152
losses: z.number(),
@@ -245,7 +246,7 @@ statsRouter.openapi(
245246
streak: z.number(),
246247
totalgames: z.number(),
247248
decay: z.number(),
248-
ign: z.any().nullable(),
249+
name: z.string().nullable(),
249250
peak_mmr: z.number(),
250251
peak_streak: z.number(),
251252
rank: z.number(),

src/command-handlers/stats/getLeaderboard.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { getQueueLeaderboard } from '../../utils/queryDB'
33
export type LeaderboardEntry = {
44
rank: number
55
id: string
6+
name: string | null
67
mmr: number
78
wins: number
89
losses: number

src/command-handlers/stats/getPlayerStats.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export type PlayerStatsData = {
88
streak: number
99
totalgames: number
1010
decay: number
11-
ign: null
11+
name: string | null
1212
peak_mmr: number
1313
peak_streak: number
1414
rank: number
@@ -35,8 +35,10 @@ export async function getPlayerStats(
3535
qu.peak_elo,
3636
qu.win_streak,
3737
qu.peak_win_streak,
38-
qu.is_decay
38+
qu.is_decay,
39+
u.display_name
3940
FROM queue_users qu
41+
LEFT JOIN users u ON u.user_id = qu.user_id
4042
WHERE qu.user_id = $1 AND qu.queue_id = $2
4143
`,
4244
[userId, queueId],
@@ -79,7 +81,7 @@ export async function getPlayerStats(
7981
streak: player.win_streak,
8082
totalgames,
8183
decay: player.is_decay ? 1 : 0,
82-
ign: null,
84+
name: player.display_name || null,
8385
peak_mmr: player.peak_elo,
8486
peak_streak: player.peak_win_streak,
8587
rank,

src/events/interactionCreate.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import {
5252
setUserDefaultDeckBans,
5353
setUserPriorityQueue,
5454
setWinningTeam,
55+
updateUserDisplayName,
5556
userInMatch,
5657
} from '../utils/queryDB'
5758
import {
@@ -71,6 +72,16 @@ export default {
7172
name: Events.InteractionCreate,
7273
async execute(interaction: Interaction) {
7374
if (!interaction) return console.log('*No interaction found*')
75+
76+
// Update display name for all interactions except autocomplete
77+
if (!interaction.isAutocomplete() && interaction.member instanceof GuildMember) {
78+
try {
79+
await updateUserDisplayName(interaction.user.id, interaction.member.displayName)
80+
} catch (err) {
81+
console.error('Error updating display name:', err)
82+
}
83+
}
84+
7485
// Slash commands
7586
if (interaction.isChatInputCommand()) {
7687
const command = interaction.client.commands.get(interaction.commandName)
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import '../register-paths'
2+
import { pool } from '../db'
3+
import { client, getGuild } from '../client'
4+
import * as dotenv from 'dotenv'
5+
6+
dotenv.config()
7+
8+
/**
9+
* Backfill script to populate display_name for all existing users
10+
* This script fetches all users from the database and updates their display_name
11+
* by fetching their current display name from Discord
12+
*/
13+
async function backfillDisplayNames() {
14+
try {
15+
console.log('Starting display name backfill...')
16+
17+
// Get all users from the database
18+
const result = await pool.query(
19+
'SELECT user_id FROM users WHERE display_name IS NULL',
20+
)
21+
const users = result.rows
22+
23+
console.log(`Found ${users.length} users without display names`)
24+
25+
if (users.length === 0) {
26+
console.log('No users to backfill!')
27+
return
28+
}
29+
30+
// Login to Discord
31+
await client.login(process.env.TOKEN)
32+
console.log('Discord client logged in')
33+
34+
let successCount = 0
35+
let errorCount = 0
36+
37+
// Process each user
38+
for (const user of users) {
39+
try {
40+
// Fetch the user from Discord
41+
const discordUser = await client.users.fetch(user.user_id)
42+
43+
// Get the display name from guilds (try to get server nickname if possible)
44+
let displayName = discordUser.username
45+
46+
const guild = await getGuild()
47+
48+
// Try to get the member from guilds to get server nickname
49+
try {
50+
const member = await guild.members.fetch(user.user_id)
51+
if (member) {
52+
displayName = member.displayName
53+
break
54+
}
55+
} catch (err) {}
56+
57+
// Update the database
58+
await pool.query(
59+
'UPDATE users SET display_name = $1 WHERE user_id = $2',
60+
[displayName, user.user_id],
61+
)
62+
63+
successCount++
64+
console.log(`✓ Updated ${user.user_id}: ${displayName}`)
65+
} catch (err) {
66+
errorCount++
67+
console.error(`✗ Error updating ${user.user_id}:`, err)
68+
}
69+
}
70+
71+
console.log('\nBackfill complete!')
72+
console.log(`Successfully updated: ${successCount}`)
73+
console.log(`Errors: ${errorCount}`)
74+
75+
// Close connections
76+
await client.destroy()
77+
await pool.end()
78+
process.exit(0)
79+
} catch (err) {
80+
console.error('Fatal error during backfill:', err)
81+
await client.destroy()
82+
await pool.end()
83+
process.exit(1)
84+
}
85+
}
86+
87+
// Run the backfill
88+
backfillDisplayNames()

src/utils/queryDB.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2060,6 +2060,7 @@ export async function getQueueLeaderboard(
20602060
Array<{
20612061
rank: number
20622062
id: string
2063+
name: string | null
20632064
mmr: number
20642065
wins: number
20652066
losses: number
@@ -2072,17 +2073,19 @@ export async function getQueueLeaderboard(
20722073
`
20732074
SELECT
20742075
qu.user_id,
2076+
u.display_name,
20752077
qu.elo,
20762078
qu.peak_elo,
20772079
qu.win_streak,
20782080
qu.peak_win_streak,
20792081
COUNT(CASE WHEN m.winning_team = mu.team THEN 1 END)::integer as wins,
20802082
COUNT(CASE WHEN m.winning_team IS NOT NULL AND m.winning_team != mu.team THEN 1 END)::integer as losses
20812083
FROM queue_users qu
2084+
LEFT JOIN users u ON u.user_id = qu.user_id
20822085
LEFT JOIN match_users mu ON mu.user_id = qu.user_id
20832086
LEFT JOIN matches m ON m.id = mu.match_id AND m.queue_id = $1
20842087
WHERE qu.queue_id = $1
2085-
GROUP BY qu.user_id, qu.elo, qu.peak_elo, qu.win_streak, qu.peak_win_streak
2088+
GROUP BY qu.user_id, u.display_name, qu.elo, qu.peak_elo, qu.win_streak, qu.peak_win_streak
20862089
ORDER BY qu.elo DESC
20872090
LIMIT $2`,
20882091
[queueId, limit],
@@ -2091,6 +2094,7 @@ export async function getQueueLeaderboard(
20912094
return res.rows.map((row, index) => ({
20922095
rank: index + 1,
20932096
id: row.user_id,
2097+
name: row.display_name || null,
20942098
mmr: row.elo,
20952099
wins: row.wins || 0,
20962100
losses: row.losses || 0,
@@ -2099,3 +2103,15 @@ export async function getQueueLeaderboard(
20992103
peak_streak: row.peak_win_streak || 0,
21002104
}))
21012105
}
2106+
2107+
// Update user's display name in the database
2108+
export async function updateUserDisplayName(
2109+
userId: string,
2110+
displayName: string,
2111+
): Promise<void> {
2112+
// Ensure user exists in users table
2113+
await pool.query(
2114+
'INSERT INTO users (user_id, display_name) VALUES ($1, $2) ON CONFLICT (user_id) DO UPDATE SET display_name = $2',
2115+
[userId, displayName],
2116+
)
2117+
}

0 commit comments

Comments
 (0)