package scraper import ( "fmt" "net/http" "strconv" "strings" "time" "streamflow-backend/internal/models" "github.com/PuerkitoBio/goquery" ) const PhimMoiChillBaseURL = "https://phimmoichill.my" type PhimMoiChillScraper struct { client *http.Client } func NewPhimMoiChillScraper() *PhimMoiChillScraper { return &PhimMoiChillScraper{ client: &http.Client{ Timeout: 30 * time.Second, }, } } func (s *PhimMoiChillScraper) GetMoviesByCategory(category string, page int) ([]models.RophimMovie, error) { // Map categories to URL paths // Home -> list/phim-moi-cap-nhat (or just use list/phim-le for now as default) // category "phim-le", "phim-bo" -> list/phim-le // others -> genre/category var path string switch category { case "home", "": path = "list/phim-moi" // Better for home than phim-le case "phim-le", "phim-bo", "hoat-hinh", "tv-shows": path = fmt.Sprintf("list/%s", category) default: path = fmt.Sprintf("genre/phim-%s", category) } targetURL := fmt.Sprintf("%s/%s", PhimMoiChillBaseURL, path) if page > 1 { targetURL = fmt.Sprintf("%s?page=%d", targetURL, page) } return s.scrapeList(targetURL) } func (s *PhimMoiChillScraper) Search(query string, page int) ([]models.RophimMovie, error) { encodedQuery := strings.ReplaceAll(query, " ", "+") targetURL := fmt.Sprintf("%s/tim-kiem/%s/", PhimMoiChillBaseURL, encodedQuery) // If page > 1, might need suffix. Let's append ?page= just in case if page > 1 { targetURL = fmt.Sprintf("%s/tim-kiem/%s/page/%d", PhimMoiChillBaseURL, encodedQuery, page) } return s.scrapeList(targetURL) } func (s *PhimMoiChillScraper) scrapeList(targetURL string) ([]models.RophimMovie, error) { req, err := http.NewRequest("GET", targetURL, nil) if err != nil { return nil, err } req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36") req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7") req.Header.Set("Accept-Language", "vi-VN,vi;q=0.9,en-US;q=0.8,en;q=0.7") req.Header.Set("Referer", PhimMoiChillBaseURL) req.Header.Set("Connection", "keep-alive") res, err := s.client.Do(req) if err != nil { return nil, err } defer res.Body.Close() if res.StatusCode != 200 { return nil, fmt.Errorf("status code error: %d %s", res.StatusCode, res.Status) } doc, err := goquery.NewDocumentFromReader(res.Body) if err != nil { return nil, err } var movies []models.RophimMovie // Selectors based on inspection (list-film item is common) // Assuming structure similar to: