mirror of
https://github.com/Dvorinka/facr-scraper.git
synced 2026-06-05 04:52:56 +00:00
push
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
export LOGOAPI_BASE_URL="http://localhost:8080" # or your real logoapi base URL
|
export LOGOAPI_BASE_URL="https://logoapi.sportcreative.eu" # or your real logoapi base URL
|
||||||
export SMTP_HOST="smtp.purelymail.com"
|
export SMTP_HOST="smtp.purelymail.com"
|
||||||
export SMTP_PORT="465"
|
export SMTP_PORT="465"
|
||||||
export SMTP_USER="info@tdvorak.dev"
|
export SMTP_USER="info@tdvorak.dev"
|
||||||
|
|||||||
@@ -431,18 +431,14 @@ func simplifyClubQuery(name string) string {
|
|||||||
func getLogoFromLogoAPI(teamName string, teamID string) string {
|
func getLogoFromLogoAPI(teamName string, teamID string) string {
|
||||||
base := strings.TrimSpace(os.Getenv("LOGOAPI_BASE_URL"))
|
base := strings.TrimSpace(os.Getenv("LOGOAPI_BASE_URL"))
|
||||||
if base == "" {
|
if base == "" {
|
||||||
return ""
|
base = "https://logoapi.sportcreative.eu"
|
||||||
}
|
}
|
||||||
base = strings.TrimRight(base, "/")
|
base = strings.TrimRight(base, "/")
|
||||||
name := strings.TrimSpace(teamName)
|
name := strings.TrimSpace(teamName)
|
||||||
id := strings.TrimSpace(teamID)
|
if name == "" {
|
||||||
if name == "" && id == "" {
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
cacheKey := "logoapi|" + strings.ToLower(name)
|
cacheKey := "logoapi|" + strings.ToLower(name)
|
||||||
if id != "" {
|
|
||||||
cacheKey += "|" + strings.ToLower(id)
|
|
||||||
}
|
|
||||||
if v, ok := logoCache[cacheKey]; ok {
|
if v, ok := logoCache[cacheKey]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
@@ -464,31 +460,47 @@ func getLogoFromLogoAPI(teamName string, teamID string) string {
|
|||||||
}
|
}
|
||||||
var payload []logoAPISearchResult
|
var payload []logoAPISearchResult
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {
|
if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {
|
||||||
|
// Non-JSON or invalid response – treat as no result
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
return payload, true
|
return payload, true
|
||||||
}
|
}
|
||||||
var candidates []logoAPISearchResult
|
// Search strictly by full club name; if it yields nothing usable, let caller fall back to FACR.
|
||||||
if id != "" {
|
payload, ok := doSearch(name)
|
||||||
if payload, ok := doSearch(id); ok && len(payload) > 0 {
|
if !ok || len(payload) == 0 {
|
||||||
candidates = payload
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(candidates) == 0 && name != "" {
|
|
||||||
q := simplifyClubQuery(name)
|
|
||||||
if q == "" {
|
|
||||||
q = name
|
|
||||||
}
|
|
||||||
if payload, ok := doSearch(q); ok && len(payload) > 0 {
|
|
||||||
candidates = payload
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(candidates) == 0 {
|
|
||||||
logoCache[cacheKey] = ""
|
logoCache[cacheKey] = ""
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
// Normalize names for comparison (case-insensitive, strip common legal/sport suffixes).
|
||||||
|
normalize := func(s string) string {
|
||||||
|
s = strings.ToLower(strings.TrimSpace(s))
|
||||||
|
if s == "" {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
parts := strings.Fields(s)
|
||||||
|
stop := map[string]struct{}{
|
||||||
|
"fotbal": {}, "futsal": {},
|
||||||
|
"z.s.": {}, "z.s": {}, "zs": {},
|
||||||
|
"o.s.": {}, "o.s": {}, "os": {},
|
||||||
|
"a.s.": {}, "a.s": {}, "as": {},
|
||||||
|
"s.r.o.": {}, "s.r.o": {}, "sro": {},
|
||||||
|
}
|
||||||
|
end := len(parts)
|
||||||
|
for end > 0 {
|
||||||
|
if _, banned := stop[parts[end-1]]; banned {
|
||||||
|
end--
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if end != len(parts) {
|
||||||
|
parts = parts[:end]
|
||||||
|
}
|
||||||
|
return strings.Join(parts, " ")
|
||||||
|
}
|
||||||
|
want := normalize(name)
|
||||||
var withLogo []logoAPISearchResult
|
var withLogo []logoAPISearchResult
|
||||||
for _, r := range candidates {
|
for _, r := range payload {
|
||||||
if r.HasLocalLogo {
|
if r.HasLocalLogo {
|
||||||
withLogo = append(withLogo, r)
|
withLogo = append(withLogo, r)
|
||||||
}
|
}
|
||||||
@@ -497,28 +509,16 @@ func getLogoFromLogoAPI(teamName string, teamID string) string {
|
|||||||
logoCache[cacheKey] = ""
|
logoCache[cacheKey] = ""
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
var best string
|
// Only accept a logo when the normalized club name matches; avoid arbitrary first-result picks.
|
||||||
if id != "" {
|
|
||||||
for _, r := range withLogo {
|
for _, r := range withLogo {
|
||||||
if strings.EqualFold(strings.TrimSpace(r.ID), id) {
|
if normalize(r.Name) == want {
|
||||||
best = r.LogoURL
|
logoCache[cacheKey] = r.LogoURL
|
||||||
break
|
return r.LogoURL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// No strong match – treat as "no logo" so upstream can fall back to FACR and send notification.
|
||||||
if best == "" && name != "" {
|
logoCache[cacheKey] = ""
|
||||||
for _, r := range withLogo {
|
return ""
|
||||||
if strings.EqualFold(strings.TrimSpace(r.Name), name) {
|
|
||||||
best = r.LogoURL
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if best == "" {
|
|
||||||
best = withLogo[0].LogoURL
|
|
||||||
}
|
|
||||||
logoCache[cacheKey] = best
|
|
||||||
return best
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLogoBySearch(name string) string {
|
func getLogoBySearch(name string) string {
|
||||||
@@ -836,6 +836,11 @@ func getClubSearch(w http.ResponseWriter, r *http.Request) {
|
|||||||
href = "https://www.fotbal.cz" + href
|
href = "https://www.fotbal.cz" + href
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prefer logoapi / local logo when available
|
||||||
|
if l := strings.TrimSpace(getLogo(name, clubID)); l != "" {
|
||||||
|
logoURL = l
|
||||||
|
}
|
||||||
|
|
||||||
results = append(results, SearchResult{
|
results = append(results, SearchResult{
|
||||||
Name: name,
|
Name: name,
|
||||||
ClubID: clubID,
|
ClubID: clubID,
|
||||||
@@ -1017,6 +1022,9 @@ func getClubTables(w http.ResponseWriter, r *http.Request) {
|
|||||||
clubName := strings.TrimSpace(doc.Find("h1.H4 span").First().Text())
|
clubName := strings.TrimSpace(doc.Find("h1.H4 span").First().Text())
|
||||||
clubURL := strings.TrimSpace(doc.Find("h1.H4 a").First().AttrOr("href", ""))
|
clubURL := strings.TrimSpace(doc.Find("h1.H4 a").First().AttrOr("href", ""))
|
||||||
logoURL := strings.TrimSpace(doc.Find("img.Logo").First().AttrOr("src", ""))
|
logoURL := strings.TrimSpace(doc.Find("img.Logo").First().AttrOr("src", ""))
|
||||||
|
if l := strings.TrimSpace(getLogo(clubName, clubID)); l != "" {
|
||||||
|
logoURL = l
|
||||||
|
}
|
||||||
category := strings.TrimSpace(doc.Find("section").First().Find("h3 span").First().Text())
|
category := strings.TrimSpace(doc.Find("section").First().Find("h3 span").First().Text())
|
||||||
address := strings.TrimSpace(doc.Find("section").First().Find("ul li").First().Text())
|
address := strings.TrimSpace(doc.Find("section").First().Find("ul li").First().Text())
|
||||||
|
|
||||||
@@ -1078,7 +1086,10 @@ func getClubInfo(w http.ResponseWriter, r *http.Request) {
|
|||||||
clubName := strings.TrimSpace(doc.Find("h1.H4 span").First().Text())
|
clubName := strings.TrimSpace(doc.Find("h1.H4 span").First().Text())
|
||||||
// Basic club metadata
|
// Basic club metadata
|
||||||
clubURL := fmt.Sprintf("%s/%s", baseURL, clubID)
|
clubURL := fmt.Sprintf("%s/%s", baseURL, clubID)
|
||||||
logoURL := fmt.Sprintf("https://is1.fotbal.cz/media/kluby/%s/%s_crop.jpg", clubID, clubID)
|
logoURL := getLogo(clubName, clubID)
|
||||||
|
if logoURL == "" {
|
||||||
|
logoURL = fmt.Sprintf("https://is1.fotbal.cz/media/kluby/%s/%s_crop.jpg", clubID, clubID)
|
||||||
|
}
|
||||||
category := "Fotbal"
|
category := "Fotbal"
|
||||||
if strings.EqualFold(clubType, "futsal") {
|
if strings.EqualFold(clubType, "futsal") {
|
||||||
category = "Futsal"
|
category = "Futsal"
|
||||||
|
|||||||
Reference in New Issue
Block a user