@@ -17,7 +17,7 @@ type DebugLogger func(message string)
1717// Fetcher defines the interface for fetching data from Reddit.
1818// Uses Reddit's public JSON API for goal link retrieval.
1919type Fetcher interface {
20- Search (query string , limit int , matchTime time.Time ) ([]SearchResult , error )
20+ Search (query string , limit int , matchTime time.Time , sort string ) ([]SearchResult , error )
2121}
2222
2323// PublicJSONFetcher uses Reddit's public JSON endpoints (no auth required).
@@ -67,21 +67,28 @@ func NewPublicJSONFetcher() *PublicJSONFetcher {
6767
6868// Search performs a search on r/soccer for Media posts matching the query.
6969// matchTime is used to filter results to posts created around the match date.
70- func (f * PublicJSONFetcher ) Search (query string , limit int , matchTime time.Time ) ([]SearchResult , error ) {
70+ // sort controls the result ordering (e.g., "relevance", "top", "new", "hot").
71+ func (f * PublicJSONFetcher ) Search (query string , limit int , matchTime time.Time , sort string ) ([]SearchResult , error ) {
7172 f .rateLimiter .wait ()
7273
7374 // Build timestamp range for filtering (match day only ±12 hours)
7475 // Goal videos are posted very soon after goals happen - limit to match day
7576 startTime := matchTime .Add (- 12 * time .Hour ).Unix ()
7677 endTime := matchTime .Add (12 * time .Hour ).Unix ()
7778
79+ // Default to relevance if sort is empty
80+ if sort == "" {
81+ sort = "relevance"
82+ }
83+
7884 // Build search URL for r/soccer with Media flair filter and timestamp
7985 // Reddit CloudSearch supports timestamp:START..END syntax
8086 searchURL := fmt .Sprintf (
81- "https://www.reddit.com/r/soccer/search.json?q=%s+flair:Media+timestamp:%d..%d&restrict_sr=on&sort=relevance &limit=%d" ,
87+ "https://www.reddit.com/r/soccer/search.json?q=%s+flair:Media+timestamp:%d..%d&restrict_sr=on&sort=%s &limit=%d" ,
8288 url .QueryEscape (query ),
8389 startTime ,
8490 endTime ,
91+ url .QueryEscape (sort ),
8592 limit ,
8693 )
8794
@@ -316,7 +323,7 @@ func (c *Client) searchForGoalOnce(goal GoalInfo) (*GoalLink, error) {
316323 query1 := fmt .Sprintf ("%s %s %d'" , goal .HomeTeam , goal .AwayTeam , goal .Minute )
317324 c .debugLog (fmt .Sprintf ("Reddit search query: '%s' for goal %d:%d (%s vs %s)" ,
318325 query1 , goal .MatchID , goal .Minute , goal .HomeTeam , goal .AwayTeam ))
319- results1 , err := c .fetcher .Search (query1 , 15 , goal .MatchTime )
326+ results1 , err := c .fetcher .Search (query1 , 15 , goal .MatchTime , "relevance" )
320327 if err != nil {
321328 c .debugLog (fmt .Sprintf ("Reddit search failed for query '%s': %v" , query1 , err ))
322329 } else {
@@ -361,7 +368,7 @@ func (c *Client) searchForGoalOnce(goal GoalInfo) (*GoalLink, error) {
361368 }
362369 query2 := fmt .Sprintf ("%s %d'" , scoringTeam , goal .Minute )
363370 c .debugLog (fmt .Sprintf ("Reddit search query (strategy 2): '%s' for goal %d:%d" , query2 , goal .MatchID , goal .Minute ))
364- results2 , err := c .fetcher .Search (query2 , 15 , goal .MatchTime )
371+ results2 , err := c .fetcher .Search (query2 , 15 , goal .MatchTime , "relevance" )
365372 if err != nil {
366373 c .debugLog (fmt .Sprintf ("Reddit search failed for strategy 2 query '%s': %v" , query2 , err ))
367374 } else {
@@ -379,12 +386,75 @@ func (c *Client) searchForGoalOnce(goal GoalInfo) (*GoalLink, error) {
379386 }
380387 }
381388
382- // Find the best matching result
389+ // Check if strategies 1+2 found a match before trying strategy 3
383390 match := findBestMatch (uniqueResults , goal )
391+ if match != nil {
392+ c .debugLog (fmt .Sprintf ("Strategy 1+2 match found for goal %d:%d, skipping strategy 3" , goal .MatchID , goal .Minute ))
393+ c .debugLog (fmt .Sprintf ("Found goal link for %d:%d: %s (post: %s)" , goal .MatchID , goal .Minute , match .URL , match .PostURL ))
394+ return & GoalLink {
395+ MatchID : goal .MatchID ,
396+ Minute : goal .Minute ,
397+ URL : match .URL ,
398+ Title : match .Title ,
399+ PostURL : match .PostURL ,
400+ FetchedAt : time .Now (),
401+ }, nil
402+ }
403+
404+ // Strategy 3: Try with short/alternative team names + sort by top (upvotes)
405+ // Only runs if strategies 1+2 did not find a match
406+ homeShort := strings .TrimSpace (goal .HomeTeamShort )
407+ awayShort := strings .TrimSpace (goal .AwayTeamShort )
408+
409+ // Skip if short names are empty or identical to full names (avoids redundant API call)
410+ homeShortDifferent := homeShort != "" && ! strings .EqualFold (homeShort , goal .HomeTeam )
411+ awayShortDifferent := awayShort != "" && ! strings .EqualFold (awayShort , goal .AwayTeam )
412+
413+ if ! homeShortDifferent && ! awayShortDifferent {
414+ c .debugLog (fmt .Sprintf ("Skipping strategy 3 for goal %d:%d: short names empty or identical to full names" , goal .MatchID , goal .Minute ))
415+ return nil , nil // No match found across all strategies
416+ }
417+
418+ // Build query using short names where they differ, falling back to full names
419+ homeQuery := goal .HomeTeam
420+ if homeShortDifferent {
421+ homeQuery = homeShort
422+ }
423+ awayQuery := goal .AwayTeam
424+ if awayShortDifferent {
425+ awayQuery = awayShort
426+ }
427+
428+ query3 := fmt .Sprintf ("%s %s %d'" , homeQuery , awayQuery , goal .Minute )
429+ c .debugLog (fmt .Sprintf ("Reddit search query (strategy 3): '%s' for goal %d:%d" , query3 , goal .MatchID , goal .Minute ))
430+ results3 , err := c .fetcher .Search (query3 , 15 , goal .MatchTime , "top" )
431+ if err != nil {
432+ c .debugLog (fmt .Sprintf ("Reddit search failed for strategy 3 query '%s': %v" , query3 , err ))
433+ } else {
434+ c .debugLog (fmt .Sprintf ("Reddit search returned %d results for strategy 3 query '%s'" , len (results3 ), query3 ))
435+ // Debug: log the first few result titles
436+ for i , result := range results3 {
437+ if i < 3 { // Log first 3 results
438+ c .debugLog (fmt .Sprintf ("Strategy 3 result %d: '%s' (score: %d)" , i + 1 , result .Title , result .Score ))
439+ }
440+ }
441+ // Combine with all prior results for best match selection
442+ for _ , result := range results3 {
443+ if ! seen [result .URL ] {
444+ seen [result .URL ] = true
445+ uniqueResults = append (uniqueResults , result )
446+ }
447+ }
448+ }
449+
450+ // Find the best matching result across all strategies
451+ match = findBestMatch (uniqueResults , goal )
452+ c .debugLog (fmt .Sprintf ("findBestMatch result (strategy 3) for goal %d:%d: %v" , goal .MatchID , goal .Minute , match != nil ))
384453 if match == nil {
385454 return nil , nil // No match found, but not an error
386455 }
387456
457+ c .debugLog (fmt .Sprintf ("Found goal link (strategy 3) for %d:%d: %s (post: %s)" , goal .MatchID , goal .Minute , match .URL , match .PostURL ))
388458 return & GoalLink {
389459 MatchID : goal .MatchID ,
390460 Minute : goal .Minute ,
0 commit comments