feat: add frontend + backend + database to retrieve and compute news from Yahoo

This commit is contained in:
2026-04-18 23:53:57 +02:00
parent f9b6d35c49
commit 93668273ff
84 changed files with 15431 additions and 0 deletions

View File

@ -0,0 +1,75 @@
package scraper
import (
"context"
"time"
"github.com/tradarr/backend/internal/models"
)
type Article struct {
Title string
Content string
URL string
PublishedAt *time.Time
Symbols []string
}
type Scraper interface {
Name() string
Scrape(ctx context.Context, symbols []string) ([]Article, error)
}
// detectSymbols extrait les symboles mentionnés dans un texte
func DetectSymbols(text string, watchlist []string) []string {
found := map[string]bool{}
for _, s := range watchlist {
// Recherche du symbole en majuscules dans le texte
if containsWord(text, s) {
found[s] = true
}
}
result := make([]string, 0, len(found))
for s := range found {
result = append(result, s)
}
return result
}
func containsWord(text, word string) bool {
upper := []byte(text)
w := []byte(word)
for i := 0; i <= len(upper)-len(w); i++ {
match := true
for j := range w {
c := upper[i+j]
if c >= 'a' && c <= 'z' {
c -= 32
}
if c != w[j] {
match = false
break
}
}
if match {
// Vérifier que c'est un mot entier
before := i == 0 || !isAlphaNum(upper[i-1])
after := i+len(w) >= len(upper) || !isAlphaNum(upper[i+len(w)])
if before && after {
return true
}
}
}
return false
}
func isAlphaNum(b byte) bool {
return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9')
}
// ScraperResult est le résultat d'un job de scraping
type ScraperResult struct {
Source *models.Source
Articles []Article
Err error
}