Added games
This commit is contained in:
parent
0920771bbf
commit
769fc87f0a
@ -2,12 +2,12 @@
|
|||||||
TRAKT_CLIENT_ID=your_trakt_client_id
|
TRAKT_CLIENT_ID=your_trakt_client_id
|
||||||
TRAKT_CLIENT_SECRET=your_trakt_client_secret
|
TRAKT_CLIENT_SECRET=your_trakt_client_secret
|
||||||
TRAKT_REDIRECT_URI=your_trakt_redirect_uri
|
TRAKT_REDIRECT_URI=your_trakt_redirect_uri
|
||||||
IMDB_API_KEY=your_imdb_api_key
|
FANART_API_KEY=your_fanart_api_key
|
||||||
IGDB_API_KEY=your_igdb_api_key
|
|
||||||
GOOGLE_BOOKS_API_KEY=your_gbooks_api_key
|
GOOGLE_BOOKS_API_KEY=your_gbooks_api_key
|
||||||
GOOGLE_CUSTOM_SEARCH_ENGINE_API_KEY=your_cse_api_key
|
GOOGLE_CUSTOM_SEARCH_ENGINE_API_KEY=your_cse_api_key
|
||||||
GOOGLE_CX=your_google_cx
|
GOOGLE_CX=your_google_cx
|
||||||
FANART_API_KEY=your_fanart_api_key
|
TWITCH_CLIENT_ID=your_twitch_client_id
|
||||||
|
TWITCH_SECRET_ID=your_twitch_secret_id
|
||||||
SPOTIFY_API_KEY=your_spotify_api_key
|
SPOTIFY_API_KEY=your_spotify_api_key
|
||||||
|
|
||||||
# PATH to Obisdian files where the information is
|
# PATH to Obisdian files where the information is
|
||||||
|
235
internal/games/api_igdb.go
Normal file
235
internal/games/api_igdb.go
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
package games
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"hugo-medialog/utils"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TokenResponse struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
ExpiresIn int `json:"expires_in"`
|
||||||
|
TokenType string `json:"token_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAccessToken() (string, error) {
|
||||||
|
clientID := os.Getenv("TWITCH_CLIENT_ID")
|
||||||
|
clientSecret := os.Getenv("TWITCH_SECRET_ID")
|
||||||
|
|
||||||
|
authURL := "https://id.twitch.tv/oauth2/token"
|
||||||
|
|
||||||
|
data := url.Values{}
|
||||||
|
data.Set("client_id", clientID)
|
||||||
|
data.Set("client_secret", clientSecret)
|
||||||
|
data.Set("grant_type", "client_credentials")
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", authURL, strings.NewReader(data.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
client := &http.Client{Timeout: 10 * time.Second}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return "", fmt.Errorf("error: non-200 response code: %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
var tokenResp TokenResponse
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokenResp.AccessToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SearchGameByTitle(title string, game *Game) error {
|
||||||
|
|
||||||
|
clientID := os.Getenv("TWITCH_CLIENT_ID")
|
||||||
|
accessToken, err := getAccessToken()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error getting access token: %v\n", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "https://api.igdb.com/v4/games"
|
||||||
|
|
||||||
|
query := fmt.Sprintf("search \"%s\";\nfields id,name,slug,cover,artworks,first_release_date,genres,platforms,screenshots,slug,url;\n", title)
|
||||||
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(query)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Client-ID", clientID)
|
||||||
|
req.Header.Set("Authorization", "Bearer "+accessToken)
|
||||||
|
req.Header.Set("Content-Type", "text/plain")
|
||||||
|
|
||||||
|
client := &http.Client{Timeout: 10 * time.Second}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var games []map[string]interface{}
|
||||||
|
if err := json.Unmarshal(body, &games); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(games) == 0 {
|
||||||
|
return fmt.Errorf("No games found")
|
||||||
|
}
|
||||||
|
|
||||||
|
first_game := games[0]
|
||||||
|
|
||||||
|
// Timestamp
|
||||||
|
if timestamp, ok := first_game["first_release_date"].(float64); ok {
|
||||||
|
game.Year = time.Unix(int64(timestamp), 0).Format("2006")
|
||||||
|
game.Subtitle = game.Year
|
||||||
|
}
|
||||||
|
// Cover
|
||||||
|
coverID := first_game["cover"].(float64)
|
||||||
|
coverURL, err := makeRequest("covers", coverID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Err: %s", err)
|
||||||
|
}
|
||||||
|
game.Image = coverURL
|
||||||
|
|
||||||
|
// Artwork
|
||||||
|
if artworks, ok := first_game["artworks"].([]interface{}); ok && len(artworks) > 0 {
|
||||||
|
artworkURL, err := makeRequest("artworks", artworks[0].(float64))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Err: %s", err)
|
||||||
|
}
|
||||||
|
game.Poster = artworkURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Screenshots
|
||||||
|
if screenshots, ok := first_game["screenshots"].([]interface{}); ok && len(screenshots) > 0 {
|
||||||
|
artworkURL, err := makeRequest("screenshots", screenshots[0].(float64))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Err: %s", err)
|
||||||
|
}
|
||||||
|
game.Background = artworkURL
|
||||||
|
}
|
||||||
|
|
||||||
|
game.ID = int(first_game["id"].(float64))
|
||||||
|
game.Link = first_game["url"].(string)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getImageURL(imageID int, size string) string {
|
||||||
|
return fmt.Sprintf("https://images.igdb.com/igdb/image/upload/t_%s/%d.jpg", size, imageID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to make requests to IGDB
|
||||||
|
func makeRequest(endpoint string, id float64) (string, error) {
|
||||||
|
|
||||||
|
clientID := os.Getenv("TWITCH_CLIENT_ID")
|
||||||
|
accessToken, err := getAccessToken()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error getting access token: %v\n", err)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the request body
|
||||||
|
idStr := fmt.Sprint(id)
|
||||||
|
body := fmt.Sprintf("fields id, image_id; where id = (%s);", idStr)
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", "https://api.igdb.com/v4/"+endpoint, strings.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add headers
|
||||||
|
req.Header.Add("Client-ID", clientID)
|
||||||
|
req.Header.Add("Authorization", "Bearer "+accessToken)
|
||||||
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
// Send the request
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// Read the response
|
||||||
|
responseData, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the response
|
||||||
|
var coverResponse []map[string]interface{}
|
||||||
|
err = json.Unmarshal(responseData, &coverResponse)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the image_id and construct the URL
|
||||||
|
if len(coverResponse) > 0 {
|
||||||
|
imageID := coverResponse[0]["image_id"].(string)
|
||||||
|
coverURL := fmt.Sprintf("https://images.igdb.com/igdb/image/upload/t_original/%s.jpg", imageID)
|
||||||
|
return coverURL, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("no image found for ID %d", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DownloadImage(url, slug, suffix string) error {
|
||||||
|
imageDir := filepath.Join(os.Getenv("MARKDOWN_OUTPUT_GAMES_DIR"), os.Getenv("IMAGES_OUTPUT_DIR"))
|
||||||
|
if err := utils.CreateDirIfNotExists(imageDir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
filename := fmt.Sprintf("%s%s.jpg", slug, suffix)
|
||||||
|
filePath := filepath.Join(imageDir, filename)
|
||||||
|
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error downloading image: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("non-200 response while downloading image: %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.Create(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error creating image file: %w", err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error reading image data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = file.Write(body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error writing image data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf(" - Image saved successfully at: %s\n", filePath)
|
||||||
|
return nil
|
||||||
|
}
|
@ -1 +1,103 @@
|
|||||||
|
package games
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"hugo-medialog/utils"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadGames() ([]Game, error) {
|
||||||
|
gamesFile := os.Getenv("OBSIDIAN_GAMES_FILE")
|
||||||
|
fileData, err := os.ReadFile(gamesFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var games []Game
|
||||||
|
err = yaml.Unmarshal(fileData, &games)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return games, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ProcessGames(games []Game) error {
|
||||||
|
utils.Sep()
|
||||||
|
for _, game := range games {
|
||||||
|
fmt.Printf("Title: %s\n", game.Title)
|
||||||
|
|
||||||
|
// If we dont have ID, search movie by Title and get the ID
|
||||||
|
if game.ID == 0 {
|
||||||
|
err := SearchGameByTitle(game.Title, &game)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error searching game by title %s: %s\n", game.Title, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
game.Slug = utils.Sluggify(game.Title)
|
||||||
|
|
||||||
|
// Download Images
|
||||||
|
if game.Image != "" {
|
||||||
|
suffix := ""
|
||||||
|
err := DownloadImage(game.Image, game.Slug, suffix)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error downloading %s: %s\n", game.Image, err)
|
||||||
|
}
|
||||||
|
game.Image = fmt.Sprintf("%s.jpg", game.Slug)
|
||||||
|
}
|
||||||
|
if game.Poster != "" {
|
||||||
|
suffix := "-poster"
|
||||||
|
err := DownloadImage(game.Poster, game.Slug, suffix)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error downloading %s: %s\n", game.Image, err)
|
||||||
|
}
|
||||||
|
game.Poster = fmt.Sprintf("%s%s.jpg", game.Slug, suffix)
|
||||||
|
}
|
||||||
|
if game.Background != "" {
|
||||||
|
suffix := "-background"
|
||||||
|
err := DownloadImage(game.Background, game.Slug, suffix)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error downloading %s: %s\n", game.Background, err)
|
||||||
|
}
|
||||||
|
game.Background = fmt.Sprintf("%s%s.jpg", game.Slug, suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := generateGameMarkdown(game)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.Sep()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateGameMarkdown(game Game) error {
|
||||||
|
templatePath := filepath.Join(os.Getenv("TEMPLATES_DIR"), "game.md.tpl")
|
||||||
|
outputDir := os.Getenv("MARKDOWN_OUTPUT_GAMES_DIR")
|
||||||
|
if err := utils.CreateDirIfNotExists(outputDir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
outputPath := filepath.Join(outputDir, fmt.Sprintf("%s.md", game.Slug))
|
||||||
|
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"Title": game.Title,
|
||||||
|
"Platform": game.Platform,
|
||||||
|
"Link": game.Link,
|
||||||
|
"Subtitle": game.Year,
|
||||||
|
"Year": game.Year,
|
||||||
|
"Rate": game.Rate,
|
||||||
|
"Progress": game.Progress,
|
||||||
|
"Image": game.Image,
|
||||||
|
"Poster": game.Poster,
|
||||||
|
"Background": game.Background,
|
||||||
|
"Date": game.Date,
|
||||||
|
"Tags": "playing",
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils.GenerateMarkdown(templatePath, outputPath, data)
|
||||||
|
}
|
||||||
|
@ -2,9 +2,12 @@ package games
|
|||||||
|
|
||||||
type Game struct {
|
type Game struct {
|
||||||
Title string `yaml:"title"`
|
Title string `yaml:"title"`
|
||||||
|
Platform string `yaml:"platform"`
|
||||||
|
ID int `yaml:"igdb_id"`
|
||||||
Link string `yaml:"link"`
|
Link string `yaml:"link"`
|
||||||
|
Slug string `yaml:"slug"`
|
||||||
Subtitle string `yaml:"subtitle"`
|
Subtitle string `yaml:"subtitle"`
|
||||||
Year int `yaml:"year"`
|
Year string `yaml:"year"`
|
||||||
Rate float64 `yaml:"rate"`
|
Rate float64 `yaml:"rate"`
|
||||||
Progress string `yaml:"progress"`
|
Progress string `yaml:"progress"`
|
||||||
Image string `yaml:"image"`
|
Image string `yaml:"image"`
|
||||||
|
23
main.go
23
main.go
@ -4,6 +4,7 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hugo-medialog/internal/books"
|
"hugo-medialog/internal/books"
|
||||||
|
"hugo-medialog/internal/games"
|
||||||
"hugo-medialog/internal/movies"
|
"hugo-medialog/internal/movies"
|
||||||
"hugo-medialog/internal/series"
|
"hugo-medialog/internal/series"
|
||||||
"hugo-medialog/utils"
|
"hugo-medialog/utils"
|
||||||
@ -13,7 +14,7 @@ func main() {
|
|||||||
// Load .env file
|
// Load .env file
|
||||||
utils.LoadConfig()
|
utils.LoadConfig()
|
||||||
|
|
||||||
// Parameter
|
// --media parameter
|
||||||
media := flag.String("media", "", "Specify the media type to process: movies, series, books, games, or music")
|
media := flag.String("media", "", "Specify the media type to process: movies, series, books, games, or music")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@ -27,8 +28,8 @@ func main() {
|
|||||||
processSeries()
|
processSeries()
|
||||||
case "books":
|
case "books":
|
||||||
processBooks()
|
processBooks()
|
||||||
// case "games":
|
case "games":
|
||||||
// processGames()
|
processGames()
|
||||||
// case "music":
|
// case "music":
|
||||||
// processMusic()
|
// processMusic()
|
||||||
default:
|
default:
|
||||||
@ -41,10 +42,10 @@ func processAll() {
|
|||||||
processMovies()
|
processMovies()
|
||||||
processSeries()
|
processSeries()
|
||||||
processBooks()
|
processBooks()
|
||||||
|
processGames()
|
||||||
}
|
}
|
||||||
|
|
||||||
func processMovies() {
|
func processMovies() {
|
||||||
// Movies
|
|
||||||
moviesList, err := movies.LoadMovies()
|
moviesList, err := movies.LoadMovies()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error reading movies file: %v\n", err)
|
fmt.Printf("Error reading movies file: %v\n", err)
|
||||||
@ -57,7 +58,6 @@ func processMovies() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func processSeries() {
|
func processSeries() {
|
||||||
// Series
|
|
||||||
seriesList, err := series.LoadSeries()
|
seriesList, err := series.LoadSeries()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error reading series file: %v\n", err)
|
fmt.Printf("Error reading series file: %v\n", err)
|
||||||
@ -70,7 +70,6 @@ func processSeries() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func processBooks() {
|
func processBooks() {
|
||||||
// Books
|
|
||||||
booksList, err := books.LoadBooks()
|
booksList, err := books.LoadBooks()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error reading books file: %v\n", err)
|
fmt.Printf("Error reading books file: %v\n", err)
|
||||||
@ -81,3 +80,15 @@ func processBooks() {
|
|||||||
fmt.Printf("Error processing books: %v\n", err)
|
fmt.Printf("Error processing books: %v\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func processGames() {
|
||||||
|
gamesList, err := games.LoadGames()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error reading games file: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = games.ProcessGames(gamesList)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error processing games: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,3 +2,8 @@
|
|||||||
progress: "40%"
|
progress: "40%"
|
||||||
rate: 9.8
|
rate: 9.8
|
||||||
date: 2024-10-08
|
date: 2024-10-08
|
||||||
|
|
||||||
|
- title: "Diablo 4"
|
||||||
|
progress: "100%"
|
||||||
|
rate: 9.8
|
||||||
|
date: 2024-10-08
|
||||||
|
@ -6,8 +6,8 @@ year: {{ .Year }}
|
|||||||
rate: {{ .Rate }}
|
rate: {{ .Rate }}
|
||||||
progress: {{ .Progress }}
|
progress: {{ .Progress }}
|
||||||
image: {{ .Image }}
|
image: {{ .Image }}
|
||||||
poster-image: {{ .PosterImage }}
|
poster-image: {{ .Poster }}
|
||||||
background-image: {{ .BackgroundImage }}
|
background-image: {{ .Background }}
|
||||||
date: {{ .Date }}
|
date: {{ .Date }}
|
||||||
draft: false
|
draft: false
|
||||||
tags: {{ .Tags }}
|
tags: {{ .Tags }}
|
||||||
|
Loading…
Reference in New Issue
Block a user