2
0
Fork 0
FLIK/big-sort.go

187 lines
4.7 KiB
Go

package main
import (
"bufio"
"encoding/csv"
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
"strings"
"time"
)
type Movie struct {
Adult bool
Backdrop_path string
Genre_ids []int
Id int
Original_language string
Original_title string
Overview string
Popularity float64
Poster_path string
Release_date string
Title string
Video bool
Vote_average float64
Vote_count int
}
type Response struct {
Page int
Results []Movie
Total_pages int
Total_results int
}
func main() {
fmt.Println("Enter the input CSV file name:")
inputFileName := getInput()
fmt.Println("Enter the TMDB API Key:")
apiKey := getInput()
// Open output CSV file
outputFileName := "movies.csv"
outputFile, err := os.Create(outputFileName)
if err != nil {
fmt.Printf("Error creating output file: %v\n", err)
return
}
defer outputFile.Close()
writer := csv.NewWriter(outputFile)
writer.UseCRLF = true
writer.Comma = ','
defer writer.Flush()
processFile(inputFileName, apiKey, writer)
// Check failed.csv
checkFailedCsv(apiKey, writer)
}
func getInput() string {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
return scanner.Text()
}
func processFile(inputFileName, apiKey string, writer *csv.Writer) {
// Open the file
file, err := os.Open(inputFileName)
if err != nil {
fmt.Printf("Error opening file: %v\n", err)
return
}
defer file.Close()
// Open failed.csv
failedFileName := "failed.csv"
failedFile, err := os.Create(failedFileName)
if err != nil {
fmt.Printf("Error creating failed.csv: %v\n", err)
return
}
defer failedFile.Close()
failedWriter := csv.NewWriter(failedFile)
failedWriter.UseCRLF = true
failedWriter.Comma = ','
defer failedWriter.Flush()
scanner := bufio.NewScanner(file)
requests := time.Tick(time.Millisecond * 20) // Limit requests to 50 per second
for scanner.Scan() {
<-requests // Wait until we are allowed to perform a request
movie := scanner.Text()
movie = strings.Trim(movie, "\"") // Remove surrounding quotes
title, year, err := parseMovieTitleYear(movie)
if err != nil {
fmt.Printf("Failed to parse movie: %s, Error: %v\n", movie, err)
_ = failedWriter.Write([]string{title, year})
failedWriter.Flush() // Immediately write the failed record to the file
continue
}
fmt.Printf("Searching for movie: %s\n", movie)
popularity, err := getMovieData(title, year, apiKey)
if err != nil {
fmt.Printf("Failed to get data for movie: %s, Error: %v\n", movie, err)
_ = failedWriter.Write([]string{title, year})
failedWriter.Flush() // Immediately write the failed record to the file
continue
}
record := []string{title, year, fmt.Sprintf("%f", popularity)}
_ = writer.Write(record)
fmt.Printf("Movie: %s, Popularity: %f\n", movie, popularity)
}
}
func parseMovieTitleYear(movie string) (string, string, error) {
parts := strings.SplitN(movie, ",", 2)
if len(parts) < 2 {
return "", "", fmt.Errorf("invalid movie format: %s", movie)
}
title := parts[0]
year := parts[1]
return title, year, nil
}
func getMovieData(title, year, apiKey string) (float64, error) {
// url encode the title
encodedTitle := url.QueryEscape(title)
url := fmt.Sprintf("https://api.themoviedb.org/3/search/movie?include_adult=false&language=en-US&year=%s&page=1&query=%s", year, encodedTitle)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer "+apiKey)
req.Header.Add("accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil || res == nil {
return 0, fmt.Errorf("failed to make request: %v", err)
}
if res.StatusCode != 200 {
return 0, fmt.Errorf("received non-200 response: %d", res.StatusCode)
}
defer res.Body.Close()
var response Response
if err := json.NewDecoder(res.Body).Decode(&response); err != nil {
return 0, fmt.Errorf("failed to decode response: %v", err)
}
if len(response.Results) == 0 {
return 0, fmt.Errorf("no results found")
}
return response.Results[0].Popularity, nil
}
func checkFailedCsv(apiKey string, writer *csv.Writer) {
for {
fmt.Println("Do you want to check failed.csv and retry fetching data for failed movies? (Y/n)")
retry := getInput()
if strings.EqualFold(retry, "n") {
break
}
if retry == "" || strings.EqualFold(retry, "y") {
fmt.Println("Processing failed.csv...")
// Recreate failed.csv for the next run
failedFileName := "failed.csv"
failedFile, err := os.Create(failedFileName)
if err != nil {
fmt.Printf("Error creating failed.csv: %v\n", err)
return
}
failedFile.Close()
// Process the old failed.csv
processFile(failedFileName, apiKey, writer)
}
}
}