feat: add flexible region matching to servers API
- Add shared buildFlexibleRegionConditions() in utils.ts - Add COUNTRY_NAME_TO_REGIONS mapping for country/city expansion - Update servers.ts to use flexible region matching (korea, tokyo, japan, etc.) - Update recommend.ts to use shared function (remove duplicate code) - Fix servers GROUP BY to show all regions (it.id, r.id) - Update CLAUDE.md with single-line curl examples Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,7 +28,8 @@ import {
|
||||
isValidTechSpec,
|
||||
isValidAIRecommendation,
|
||||
sanitizeForAIPrompt,
|
||||
DEFAULT_REGION_FILTER_SQL
|
||||
DEFAULT_REGION_FILTER_SQL,
|
||||
buildFlexibleRegionConditions
|
||||
} from '../utils';
|
||||
|
||||
export async function handleRecommend(
|
||||
@@ -384,52 +385,11 @@ async function queryCandidateServers(
|
||||
}
|
||||
}
|
||||
|
||||
// Country name to code mapping for common names
|
||||
// Note: Use specific city names to avoid LIKE pattern collisions (e.g., 'de' matches 'Delhi')
|
||||
const countryNameToCode: Record<string, string[]> = {
|
||||
'korea': ['seoul', 'koreacentral', 'kr', 'ap-northeast-2'],
|
||||
'south korea': ['seoul', 'koreacentral', 'kr', 'ap-northeast-2'],
|
||||
'japan': ['tokyo', 'osaka', 'ap-northeast-1', 'ap-northeast-3'],
|
||||
'singapore': ['singapore', 'ap-southeast-1'],
|
||||
'indonesia': ['jakarta', 'ap-southeast-3'],
|
||||
'india': ['mumbai', 'delhi', 'bangalore', 'hyderabad', 'ap-south-1'],
|
||||
'australia': ['sydney', 'melbourne', 'ap-southeast-2'],
|
||||
'germany': ['frankfurt', 'nuremberg', 'falkenstein', 'eu-central-1'],
|
||||
'usa': ['us-east', 'us-west', 'virginia', 'oregon', 'ohio'],
|
||||
'united states': ['us-east', 'us-west', 'virginia', 'oregon', 'ohio'],
|
||||
'uk': ['london', 'manchester', 'eu-west-2'],
|
||||
'united kingdom': ['london', 'manchester', 'eu-west-2'],
|
||||
'netherlands': ['amsterdam', 'eu-west-1'],
|
||||
'france': ['paris', 'eu-west-3'],
|
||||
'hong kong': ['hong kong', 'ap-east-1'],
|
||||
'taiwan': ['taipei', 'ap-northeast-1'],
|
||||
'brazil': ['sao paulo', 'sa-east-1'],
|
||||
'canada': ['montreal', 'toronto', 'ca-central-1'],
|
||||
};
|
||||
|
||||
// Flexible region matching: region_code, region_name, or country_code
|
||||
if (req.region_preference && req.region_preference.length > 0) {
|
||||
// User specified region → filter to that region only
|
||||
const regionConditions: string[] = [];
|
||||
for (const region of req.region_preference) {
|
||||
const lowerRegion = region.toLowerCase();
|
||||
|
||||
// Expand country names to their codes/cities
|
||||
const expandedRegions = countryNameToCode[lowerRegion] || [lowerRegion];
|
||||
const allRegions = [lowerRegion, ...expandedRegions];
|
||||
|
||||
for (const r of allRegions) {
|
||||
const escapedRegion = escapeLikePattern(r);
|
||||
regionConditions.push(`(
|
||||
LOWER(r.region_code) = ? OR
|
||||
LOWER(r.region_code) LIKE ? ESCAPE '\\' OR
|
||||
LOWER(r.region_name) LIKE ? ESCAPE '\\' OR
|
||||
LOWER(r.country_code) = ?
|
||||
)`);
|
||||
params.push(r, `%${escapedRegion}%`, `%${escapedRegion}%`, r);
|
||||
}
|
||||
}
|
||||
query += ` AND (${regionConditions.join(' OR ')})`;
|
||||
const { conditions, params: regionParams } = buildFlexibleRegionConditions(req.region_preference);
|
||||
query += ` AND (${conditions.join(' OR ')})`;
|
||||
params.push(...regionParams);
|
||||
} else {
|
||||
// No region specified → default to Seoul/Tokyo/Osaka/Singapore
|
||||
query += ` AND ${DEFAULT_REGION_FILTER_SQL}`;
|
||||
|
||||
Reference in New Issue
Block a user