Added games
This commit is contained in:
parent
0920771bbf
commit
769fc87f0a
@ -2,12 +2,12 @@
|
||||
TRAKT_CLIENT_ID=your_trakt_client_id
|
||||
TRAKT_CLIENT_SECRET=your_trakt_client_secret
|
||||
TRAKT_REDIRECT_URI=your_trakt_redirect_uri
|
||||
IMDB_API_KEY=your_imdb_api_key
|
||||
IGDB_API_KEY=your_igdb_api_key
|
||||
FANART_API_KEY=your_fanart_api_key
|
||||
GOOGLE_BOOKS_API_KEY=your_gbooks_api_key
|
||||
GOOGLE_CUSTOM_SEARCH_ENGINE_API_KEY=your_cse_api_key
|
||||
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
|
||||
|
||||
# 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 {
|
||||
Title string `yaml:"title"`
|
||||
Platform string `yaml:"platform"`
|
||||
ID int `yaml:"igdb_id"`
|
||||
Link string `yaml:"link"`
|
||||
Slug string `yaml:"slug"`
|
||||
Subtitle string `yaml:"subtitle"`
|
||||
Year int `yaml:"year"`
|
||||
Year string `yaml:"year"`
|
||||
Rate float64 `yaml:"rate"`
|
||||
Progress string `yaml:"progress"`
|
||||
Image string `yaml:"image"`
|
||||
|
23
main.go
23
main.go
@ -4,6 +4,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"hugo-medialog/internal/books"
|
||||
"hugo-medialog/internal/games"
|
||||
"hugo-medialog/internal/movies"
|
||||
"hugo-medialog/internal/series"
|
||||
"hugo-medialog/utils"
|
||||
@ -13,7 +14,7 @@ func main() {
|
||||
// Load .env file
|
||||
utils.LoadConfig()
|
||||
|
||||
// Parameter
|
||||
// --media parameter
|
||||
media := flag.String("media", "", "Specify the media type to process: movies, series, books, games, or music")
|
||||
flag.Parse()
|
||||
|
||||
@ -27,8 +28,8 @@ func main() {
|
||||
processSeries()
|
||||
case "books":
|
||||
processBooks()
|
||||
// case "games":
|
||||
// processGames()
|
||||
case "games":
|
||||
processGames()
|
||||
// case "music":
|
||||
// processMusic()
|
||||
default:
|
||||
@ -41,10 +42,10 @@ func processAll() {
|
||||
processMovies()
|
||||
processSeries()
|
||||
processBooks()
|
||||
processGames()
|
||||
}
|
||||
|
||||
func processMovies() {
|
||||
// Movies
|
||||
moviesList, err := movies.LoadMovies()
|
||||
if err != nil {
|
||||
fmt.Printf("Error reading movies file: %v\n", err)
|
||||
@ -57,7 +58,6 @@ func processMovies() {
|
||||
}
|
||||
|
||||
func processSeries() {
|
||||
// Series
|
||||
seriesList, err := series.LoadSeries()
|
||||
if err != nil {
|
||||
fmt.Printf("Error reading series file: %v\n", err)
|
||||
@ -70,7 +70,6 @@ func processSeries() {
|
||||
}
|
||||
|
||||
func processBooks() {
|
||||
// Books
|
||||
booksList, err := books.LoadBooks()
|
||||
if err != nil {
|
||||
fmt.Printf("Error reading books file: %v\n", err)
|
||||
@ -81,3 +80,15 @@ func processBooks() {
|
||||
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%"
|
||||
rate: 9.8
|
||||
date: 2024-10-08
|
||||
|
||||
- title: "Diablo 4"
|
||||
progress: "100%"
|
||||
rate: 9.8
|
||||
date: 2024-10-08
|
||||
|
@ -6,8 +6,8 @@ year: {{ .Year }}
|
||||
rate: {{ .Rate }}
|
||||
progress: {{ .Progress }}
|
||||
image: {{ .Image }}
|
||||
poster-image: {{ .PosterImage }}
|
||||
background-image: {{ .BackgroundImage }}
|
||||
poster-image: {{ .Poster }}
|
||||
background-image: {{ .Background }}
|
||||
date: {{ .Date }}
|
||||
draft: false
|
||||
tags: {{ .Tags }}
|
||||
|
Loading…
Reference in New Issue
Block a user