132 lines
3.8 KiB
Go
132 lines
3.8 KiB
Go
package crawler
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/url"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"game-crawler/cache"
|
|
"game-crawler/constant"
|
|
"game-crawler/model"
|
|
"game-crawler/utils"
|
|
)
|
|
|
|
// GetSteamAppDetail fetches the details of a Steam app by its ID.
|
|
func GetSteamAppDetail(id int) (*model.SteamAppDetail, error) {
|
|
key := fmt.Sprintf("steam_game:%d", id)
|
|
if val, exist := cache.Get(key); exist {
|
|
var detail model.SteamAppDetail
|
|
if err := json.Unmarshal([]byte(val), &detail); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal cached Steam app detail for ID %d: %w", id, err)
|
|
}
|
|
return &detail, nil
|
|
}
|
|
|
|
baseURL, _ := url.Parse(constant.SteamAppDetailURL)
|
|
params := url.Values{}
|
|
params.Add("appids", strconv.Itoa(id))
|
|
baseURL.RawQuery = params.Encode()
|
|
|
|
resp, err := utils.Request().SetHeaders(map[string]string{
|
|
"User-Agent": "",
|
|
}).Get(baseURL.String())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to fetch Steam app detail for ID %d: %w", id, err)
|
|
}
|
|
|
|
var detail map[string]*model.SteamAppDetail
|
|
if err := json.Unmarshal(resp.Body(), &detail); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal Steam app detail for ID %d: %w", id, err)
|
|
}
|
|
|
|
if appDetail, ok := detail[strconv.Itoa(id)]; !ok || appDetail == nil {
|
|
return nil, fmt.Errorf("steam app not found: %d", id)
|
|
} else {
|
|
// Cache the result
|
|
jsonBytes, err := json.Marshal(appDetail)
|
|
if err == nil {
|
|
_ = cache.Set(key, string(jsonBytes))
|
|
}
|
|
return appDetail, nil
|
|
}
|
|
}
|
|
|
|
// GenerateSteamGameInfo generates detailed game information based on a Steam App ID.
|
|
func GenerateSteamGameInfo(id int) (*model.GameInfo, error) {
|
|
detail, err := GetSteamAppDetail(id)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to fetch Steam app detail for ID %d: %w", id, err)
|
|
}
|
|
|
|
item := &model.GameInfo{
|
|
SteamID: id,
|
|
Name: detail.Data.Name,
|
|
Description: detail.Data.ShortDescription,
|
|
Cover: fmt.Sprintf("https://shared.cloudflare.steamstatic.com/store_item_assets/steam/apps/%v/library_600x900_2x.jpg", id),
|
|
Developers: detail.Data.Developers,
|
|
Publishers: detail.Data.Publishers,
|
|
Screenshots: make([]string, 0, len(detail.Data.Screenshots)),
|
|
}
|
|
|
|
for _, screenshot := range detail.Data.Screenshots {
|
|
item.Screenshots = append(item.Screenshots, screenshot.PathFull)
|
|
}
|
|
|
|
return item, nil
|
|
}
|
|
|
|
// GetSteamIDByIGDBID retrieves the Steam App ID associated with a given IGDB ID.
|
|
func GetSteamIDByIGDBID(IGDBID int) (int, error) {
|
|
key := fmt.Sprintf("steam_game:%d", IGDBID)
|
|
if val, exist := cache.Get(key); exist {
|
|
id, err := strconv.Atoi(val)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("failed to parse cached Steam ID for IGDB ID %d: %w", IGDBID, err)
|
|
}
|
|
return id, nil
|
|
}
|
|
|
|
query := fmt.Sprintf(`where game = %v; fields *; limit 500;`, IGDBID)
|
|
resp, err := igdbRequest(constant.IGDBWebsitesURL, query)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("failed to fetch IGDB websites for IGDB ID %d: %w", IGDBID, err)
|
|
}
|
|
|
|
var data []struct {
|
|
Game int `json:"game"`
|
|
Url string `json:"url"`
|
|
}
|
|
if err := json.Unmarshal(resp.Body(), &data); err != nil {
|
|
return 0, fmt.Errorf("failed to unmarshal IGDB websites response for IGDB ID %d: %w", IGDBID, err)
|
|
}
|
|
|
|
if len(data) == 0 {
|
|
return 0, errors.New("steam ID not found")
|
|
}
|
|
|
|
for _, v := range data {
|
|
if strings.HasPrefix(v.Url, "https://store.steampowered.com/app/") {
|
|
regex := regexp.MustCompile(`https://store.steampowered.com/app/(\d+)/?`)
|
|
idMatch := regex.FindStringSubmatch(v.Url)
|
|
if len(idMatch) < 2 {
|
|
return 0, errors.New("failed to parse Steam ID from URL")
|
|
}
|
|
|
|
steamID, err := strconv.Atoi(idMatch[1])
|
|
if err != nil {
|
|
return 0, fmt.Errorf("failed to convert Steam ID from URL %s: %w", v.Url, err)
|
|
}
|
|
|
|
// Cache the result
|
|
_ = cache.Set(key, strconv.Itoa(steamID))
|
|
return steamID, nil
|
|
}
|
|
}
|
|
|
|
return 0, fmt.Errorf("no valid Steam ID found for IGDB ID %d", IGDBID)
|
|
}
|