Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ again when you get more games or want to update the category overlays.
* *(optional)* Append `--skipCategory <category>` to skip processing of games assigned to a specific Steam category
* *(optional)* Append `--steamgriddbonly` to search for artwork only in SteamGridDB
* *(optional)* Append `--namefilter "<text>"` to process only games with names that contain provided *text*
* *(optional)* Append `--searchcustomgames` if you have non-steam games that have a page in the steam store
* *(tip)* Run with `--help` to see all available options again.
6. Read the report and open Steam in grid view to check the results.

Expand Down
41 changes: 41 additions & 0 deletions custom-games.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"fmt"
"io"
"net/url"
"regexp"
)

const steamSearchUrl = `https://store.steampowered.com/search/?category1=998%2C994%2C21%2C10%2C997&term=` // category is set to exclude bundles
const regexPattern = `https:\/\/store\.steampowered\.com\/app\/(\d*)\/`

// updateIdForCustomGames searches Steam Store using the game name and updates the game's ID.
// For non-steam games that have page in steam store, we can update their ID and download art from steam server as normal
func updateIdForCustomGames(game *Game) error {
// Search for the game on Steam
formattedUrl := steamSearchUrl + url.QueryEscape(game.Name)
response, err := tryDownload(formattedUrl)
if err != nil || response == nil {
return fmt.Errorf("downloading html: %w", err)
}
// Read the response body
defer response.Body.Close()
htmlBytes, err2 := io.ReadAll(response.Body)
if err2 != nil {
return fmt.Errorf("reading response body: %w", err2)
}
html := string(htmlBytes)
// Get the first match using regex
re, err := regexp.Compile(regexPattern)
if err != nil {
return fmt.Errorf("invalid regex pattern: %w", err)
}
matches := re.FindStringSubmatch(html)
if len(matches) < 2 {
return fmt.Errorf("no match or no capture group found")
}
game.ID = matches[1]
fmt.Println("Found a custom game on Steam:", game.Name, ", Id:", game.ID)
return nil
}
10 changes: 6 additions & 4 deletions games.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type Game struct {
Custom bool
// LegacyID used in BigPicture
LegacyID uint64
// For steam games it's the same as ID, but for non-steam games it's the shortcut ID (in case ID get overwritten by updateIdForCustomGames)
OriginalID string
}

// Pattern of game declarations in the public profile. It's actually JSON
Expand All @@ -53,7 +55,7 @@ func addGamesFromProfile(user User, games map[string]*Game) (err error) {
gameID := groups[1]
gameName := groups[2]
tags := []string{""}
games[gameID] = &Game{gameID, gameName, tags, "", nil, nil, "", false, 0}
games[gameID] = &Game{gameID, gameName, tags, "", nil, nil, "", false, 0, gameID}
}

return
Expand Down Expand Up @@ -91,7 +93,7 @@ func addUnknownGames(user User, games map[string]*Game, skipCategory string) {
// If for some reason it wasn't included in the profile, create a new
// entry for it now. Unfortunately we don't have a name.
gameName := ""
games[gameID] = &Game{gameID, gameName, []string{tag}, "", nil, nil, "", false, 0}
games[gameID] = &Game{gameID, gameName, []string{tag}, "", nil, nil, "", false, 0, gameID}
}

if len(skipCategory) > 0 && strings.Contains(strings.ToLower(tag), strings.ToLower(skipCategory)) {
Expand Down Expand Up @@ -130,7 +132,7 @@ func addNonSteamGames(user User, games map[string]*Game, skipCategory string) {
uniqueName := bytes.Join([][]byte{target, gameName}, []byte(""))
LegacyID := uint64(crc32.ChecksumIEEE(uniqueName)) | 0x80000000

game := Game{gameID, string(gameName), []string{}, "", nil, nil, "", true, LegacyID}
game := Game{gameID, string(gameName), []string{}, "", nil, nil, "", true, LegacyID, gameID}
games[gameID] = &game

tagsText := gameGroups[4]
Expand All @@ -153,7 +155,7 @@ func GetGames(user User, nonSteamOnly bool, appIDs string, skipCategory string)

if appIDs != "" {
for _, appID := range strings.Split(appIDs, ",") {
games[appID] = &Game{appID, "", []string{}, "", nil, nil, "", false, 0}
games[appID] = &Game{appID, "", []string{}, "", nil, nil, "", false, 0, appID}
}
return games
}
Expand Down
10 changes: 9 additions & 1 deletion steamgrid.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func startApplication() {
skipCategory := flag.String("skipcategory", "", "Name of the category with games to skip during processing")
steamgriddbonly := flag.Bool("steamgriddbonly", false, "Search for artwork only in SteamGridDB")
nameFilter := flag.String("namefilter", "", "Process only games with name that contains this value")
searchCustomGames := flag.Bool("searchcustomgames", false, "Try to find non-steam games on Steam Store using their game name")
flag.Parse()
if flag.NArg() == 1 {
steamDir = &flag.Args()[0]
Expand Down Expand Up @@ -177,6 +178,13 @@ func startApplication() {
for _, game := range games {
i++

if game.Custom && *searchCustomGames && game.Name != "" {
err := updateIdForCustomGames(game)
if err != nil {
fmt.Println("Error updating id for custom games: " + err.Error())
}
}

var name string
if game.Name == "" {
game.Name = getGameName(game.ID)
Expand Down Expand Up @@ -271,7 +279,7 @@ func startApplication() {
errorAndExit(err)
}

imagePath := filepath.Join(gridDir, game.ID+artStyleExtensions[0]+game.ImageExt)
imagePath := filepath.Join(gridDir, game.OriginalID+artStyleExtensions[0]+game.ImageExt)
err = ioutil.WriteFile(imagePath, game.OverlayImageBytes, 0666)

// Copy with legacy naming for Big Picture mode
Expand Down