From 29c1faf49e28be696a98909135d37f32a172616e Mon Sep 17 00:00:00 2001 From: Haewon Kam Date: Sat, 4 Apr 2026 21:25:26 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20correct=20OtherChannels=20URLs=20?= =?UTF-8?q?=E2=80=94=20Google=20Maps,=20Naver=20Blog,=20Naver=20Place?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Google Maps: was using gm.website (clinic's own site) → now always generates maps.google.com/search URL Naver Blog: was linking to first search result post (random personal blog) → now links to Naver blog search results page Naver Place: np.link was the clinic's own website, not Naver Place → now generates map.naver.com search URL. Also fixed collect-channel-data to search with "성형외과" suffix and match by category (성형/피부) to avoid same-name dental clinics. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/lib/transformReport.ts | 10 +++-- .../functions/collect-channel-data/index.ts | 39 +++++++++++++------ 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/lib/transformReport.ts b/src/lib/transformReport.ts index 3f5b8bf..83bad93 100644 --- a/src/lib/transformReport.ts +++ b/src/lib/transformReport.ts @@ -994,7 +994,8 @@ export function mergeEnrichment( name: '구글 지도', status: 'active' as const, details: `평점: ${gm.rating ?? '-'} / 리뷰: ${gm.reviewCount ?? '-'}`, - url: gm.website || (gm.name ? `https://www.google.com/maps/search/${encodeURIComponent(String(gm.name))}` : ''), + // Always use Google Maps search URL — gm.website is the clinic's own site, not Maps + url: gm.name ? `https://www.google.com/maps/search/${encodeURIComponent(String(gm.name))}` : '', }; if (gmChannelIdx >= 0) { merged.otherChannels[gmChannelIdx] = gmChannel; @@ -1089,7 +1090,8 @@ export function mergeEnrichment( name: '네이버 블로그', status: 'active' as const, details: `검색 결과: ${nb.totalResults?.toLocaleString() ?? '-'}건 / 최근 포스트 ${nb.posts?.length ?? 0}개`, - url: nb.posts?.[0]?.link || (nb.searchQuery ? `https://search.naver.com/search.naver?query=${encodeURIComponent(String(nb.searchQuery))}` : ''), + // Always link to Naver blog search — individual post links may be unrelated personal blogs + url: nb.searchQuery ? `https://search.naver.com/search.naver?where=blog&query=${encodeURIComponent(String(nb.searchQuery))}` : '', }; if (nbChannelIdx >= 0) { merged.otherChannels[nbChannelIdx] = nbChannel; @@ -1106,7 +1108,9 @@ export function mergeEnrichment( name: '네이버 플레이스', status: 'active' as const, details: np.category || '', - url: np.link || '', + // np.link is the clinic's own website, NOT Naver Place page + // Use Naver Place search URL instead + url: np.name ? `https://map.naver.com/v5/search/${encodeURIComponent(String(np.name))}` : '', }; if (npChannelIdx >= 0) { merged.otherChannels[npChannelIdx] = npChannel; diff --git a/supabase/functions/collect-channel-data/index.ts b/supabase/functions/collect-channel-data/index.ts index 1221432..33caf1b 100644 --- a/supabase/functions/collect-channel-data/index.ts +++ b/supabase/functions/collect-channel-data/index.ts @@ -247,17 +247,34 @@ Deno.serve(async (req) => { })()); tasks.push((async () => { - const query = encodeURIComponent(clinicName); - const res = await fetch(`https://openapi.naver.com/v1/search/local.json?query=${query}&display=5&sort=comment`, { headers: naverHeaders }); - if (!res.ok) return; - const data = await res.json(); - const place = (data.items || [])[0]; - if (place) { - channelData.naverPlace = { - name: (place.title || "").replace(/<[^>]*>/g, ""), - category: place.category, address: place.roadAddress || place.address, - telephone: place.telephone, link: place.link, mapx: place.mapx, mapy: place.mapy, - }; + // Try multiple queries to find the correct place (avoid same-name different clinics) + const queries = [ + `${clinicName} 성형외과`, + `${clinicName} 성형`, + clinicName, + ]; + for (const q of queries) { + const query = encodeURIComponent(q); + const res = await fetch(`https://openapi.naver.com/v1/search/local.json?query=${query}&display=5&sort=comment`, { headers: naverHeaders }); + if (!res.ok) continue; + const data = await res.json(); + // Find the best match: prefer category containing 성형 or 피부 + const items = (data.items || []) as Record[]; + const match = items.find(i => + (i.category || '').includes('성형') || (i.category || '').includes('피부') + ) || items.find(i => { + const name = (i.title || '').replace(/<[^>]*>/g, '').toLowerCase(); + return name.includes(clinicName.replace(/성형외과|병원|의원/g, '').trim().toLowerCase()); + }) || null; + + if (match) { + channelData.naverPlace = { + name: (match.title || "").replace(/<[^>]*>/g, ""), + category: match.category, address: match.roadAddress || match.address, + telephone: match.telephone, link: match.link, mapx: match.mapx, mapy: match.mapy, + }; + break; + } } })()); }