package crawler import ( "encoding/json" "errors" "fmt" "net/url" "regexp" "strconv" "strings" "time" "pcgamedb/cache" "pcgamedb/config" "pcgamedb/constant" "pcgamedb/model" "pcgamedb/utils" ) func GetSteamAppDetail(id int) (*model.SteamAppDetail, error) { baseURL, _ := url.Parse(constant.SteamAppDetailURL) params := url.Values{} params.Add("appids", strconv.Itoa(id)) // params.Add("l", "schinese") baseURL.RawQuery = params.Encode() resp, err := utils.Fetch(utils.FetchConfig{ Url: baseURL.String(), Headers: map[string]string{ "User-Agent": "", }, }) if err != nil { return nil, err } var detail map[string]*model.SteamAppDetail if err = json.Unmarshal(resp.Data, &detail); err != nil { return nil, err } if _, ok := detail[strconv.Itoa(id)]; !ok { return nil, fmt.Errorf("steam App not found: %d", id) } if detail[strconv.Itoa(id)] == nil { return nil, fmt.Errorf("steam App not found: %d", id) } return detail[strconv.Itoa(id)], nil } func GetSteamAppDetailCache(id int) (*model.SteamAppDetail, error) { if config.Config.RedisAvaliable { key := fmt.Sprintf("steam_game:%d", id) val, exist := cache.Get(key) if exist { var detail model.SteamAppDetail if err := json.Unmarshal([]byte(val), &detail); err != nil { return nil, err } return &detail, nil } else { data, err := GetSteamAppDetail(id) if err != nil { return nil, err } dataBytes, err := json.Marshal(data) if err != nil { return nil, err } _ = cache.Add(key, dataBytes) return data, nil } } else { return GetSteamAppDetail(id) } } func GenerateSteamGameInfo(id int) (*model.GameInfo, error) { item := &model.GameInfo{} detail, err := GetSteamAppDetailCache(id) if err != nil { return nil, err } item.SteamID = id item.Name = detail.Data.Name item.Description = detail.Data.ShortDescription item.Cover = fmt.Sprintf("https://shared.cloudflare.steamstatic.com/store_item_assets/steam/apps/%v/library_600x900_2x.jpg", id) item.Developers = detail.Data.Developers item.Publishers = detail.Data.Publishers item.InfoUpdatedAt = time.Now() var screenshots []string for _, screenshot := range detail.Data.Screenshots { screenshots = append(screenshots, screenshot.PathFull) } item.Screenshots = screenshots return item, nil } func GetSteamIDByIGDBID(IGDBID int) (int, error) { var err error resp, err := igdbFetch(constant.IGDBWebsitesURL, fmt.Sprintf(`where game = %v; fields *; limit 500;`, IGDBID)) if err != nil { return 0, err } var data []struct { Game int `json:"game"` Url string `json:"url"` } if err = json.Unmarshal(resp.Data, &data); err != nil { return 0, err } if len(data) == 0 { return 0, errors.New("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+)/?`) idStr := regex.FindStringSubmatch(v.Url) if len(idStr) < 2 { return 0, errors.New("failed parse") } steamID, err := strconv.Atoi(idStr[1]) if err != nil { return 0, err } return steamID, nil } } return 0, errors.New("not found") } func GetSteamIDByIGDBIDCache(IGDBID int) (int, error) { if config.Config.RedisAvaliable { key := fmt.Sprintf("steam_game:%d", IGDBID) val, exist := cache.Get(key) if exist { id, err := strconv.Atoi(val) if err != nil { return 0, err } return id, nil } else { id, err := GetSteamIDByIGDBID(IGDBID) if err != nil { return 0, err } dataBytes := strconv.Itoa(id) _ = cache.Add(key, dataBytes) return id, nil } } else { return GetSteamIDByIGDBID(IGDBID) } }