-
Notifications
You must be signed in to change notification settings - Fork 1
Add membership ID support to player search #116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,7 @@ import { playerSearchQueryTimer } from "@/integrations/prometheus/metrics" | |||||||||||
| import { withHistogramTimer } from "@/integrations/prometheus/util" | ||||||||||||
| import { PlayerInfo } from "@/schema/components/PlayerInfo" | ||||||||||||
| import { DestinyMembershipType } from "@/schema/enums/DestinyMembershipType" | ||||||||||||
| import { getPlayer } from "@/services/player" | ||||||||||||
|
|
||||||||||||
| /** | ||||||||||||
| * Case insensitive search | ||||||||||||
|
|
@@ -18,14 +19,17 @@ export async function searchForPlayer( | |||||||||||
| searchTerm: string | ||||||||||||
| results: PlayerInfo[] | ||||||||||||
| }> { | ||||||||||||
| const searchTerm = query.trim().toLowerCase() | ||||||||||||
| const trimmedQuery = query.trim() | ||||||||||||
| const searchTerm = trimmedQuery.toLowerCase() | ||||||||||||
| const isMembershipIdQuery = /^\d+$/.test(trimmedQuery) | ||||||||||||
|
|
||||||||||||
| const results = await withHistogramTimer( | ||||||||||||
| playerSearchQueryTimer, | ||||||||||||
| { prefixLength: searchTerm.split("#")[0]?.length ?? 0 }, | ||||||||||||
| () => | ||||||||||||
| pgReader.queryRows<PlayerInfo>( | ||||||||||||
| `SELECT | ||||||||||||
| const [nameResults, membershipIdResult] = await Promise.all([ | ||||||||||||
| withHistogramTimer( | ||||||||||||
| playerSearchQueryTimer, | ||||||||||||
| { prefixLength: searchTerm.split("#")[0]?.length ?? 0 }, | ||||||||||||
| () => | ||||||||||||
| pgReader.queryRows<PlayerInfo>( | ||||||||||||
| `SELECT | ||||||||||||
| membership_id AS "membershipId", | ||||||||||||
| membership_type AS "membershipType", | ||||||||||||
| icon_path AS "iconPath", | ||||||||||||
|
|
@@ -41,13 +45,23 @@ export async function searchForPlayer( | |||||||||||
| AND last_seen > TIMESTAMP 'epoch' | ||||||||||||
| ORDER BY _search_score DESC | ||||||||||||
| LIMIT $2;`, | ||||||||||||
| { | ||||||||||||
| params: opts.membershipType | ||||||||||||
| ? [searchTerm + "%", opts.count, opts.membershipType] | ||||||||||||
| : [searchTerm + "%", opts.count] | ||||||||||||
| } | ||||||||||||
| ) | ||||||||||||
| ) | ||||||||||||
| { | ||||||||||||
| params: opts.membershipType | ||||||||||||
| ? [searchTerm + "%", opts.count, opts.membershipType] | ||||||||||||
| : [searchTerm + "%", opts.count] | ||||||||||||
| } | ||||||||||||
| ) | ||||||||||||
| ), | ||||||||||||
| isMembershipIdQuery ? getPlayer(trimmedQuery).catch(() => null) : Promise.resolve(null) | ||||||||||||
| ]) | ||||||||||||
|
|
||||||||||||
| let results = nameResults | ||||||||||||
| if (membershipIdResult) { | ||||||||||||
| const membershipIdBigInt = BigInt(trimmedQuery) | ||||||||||||
| if (!results.some(r => r.membershipId === membershipIdBigInt)) { | ||||||||||||
|
||||||||||||
| if (!results.some(r => r.membershipId === membershipIdBigInt)) { | |
| const membershipTypeMatches = | |
| !opts.membershipType || membershipIdResult.membershipType === opts.membershipType | |
| if (membershipTypeMatches && !results.some(r => r.membershipId === membershipIdBigInt)) { |
Copilot
AI
Feb 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a membership ID result is prepended to the name-based results, the total results array can exceed the requested opts.count limit. For example, if opts.count is 10 and the name search returns 10 results, prepending the membership ID result would yield 11 results total.
Consider either slicing the results array to maintain the count limit, or documenting that membership ID matches can cause the result count to be count+1.
| if (results.length > opts.count) { | |
| results = results.slice(0, opts.count) | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test for membership ID queries should include a test case that validates the membershipType filter is respected. Currently, there's no test verifying that when a membershipType filter is provided with a membership ID query, only players from that platform are returned (or the result is filtered out if the platform doesn't match).
Consider adding a test similar to "full bungie name wrong platform" that queries by membership ID with a mismatched membershipType to ensure proper filtering.