gamebanana: add function for retrieving Gamebanana mod information

This commit is contained in:
Nico 2025-08-29 02:51:59 +10:00
parent e46278757b
commit baccafb8ce
Signed by: nico
SSH key fingerprint: SHA256:XuacYOrGqRxC3jVFjfLROn1CSvLz85Dec6N7O9Gwu/0
2 changed files with 165 additions and 0 deletions

139
gamebanana/mods.go Normal file
View file

@ -0,0 +1,139 @@
package gamebanana
import (
"encoding/json"
"io"
"net/http"
"net/url"
"github.com/charmbracelet/log"
)
// all fields for the "mod" type got at GET api.gamebanana.com/Core/Item/Data/AllowedFields?itemtype=Mod
// struct is gotten from requesting all fields and then converting them with https://transform.tools/json-to-go
type GameBananaMod struct {
AppsUsed string `json:"apps_used"`
Authors string `json:"authors"`
CategoryName string `json:"Category().name"`
Catid int `json:"catid"`
Contestid int `json:"contestid"`
Creator string `json:"creator"`
CreditsAAuthors [][]string `json:"Credits().aAuthors()"`
CreditsAAuthorsAndGroups struct {
KeyAuthor [][]string `json:"Key Author"`
ModelSources [][]string `json:"Model Sources"`
SpecialThanks [][]string `json:"Special Thanks"`
} `json:"Credits().aAuthorsAndGroups()"`
CreditsSsvAuthorNames string `json:"Credits().ssvAuthorNames()"`
Date int `json:"date"`
Description string `json:"description"`
Downloads int `json:"downloads"`
FeedbackInstructions string `json:"feedback_instructions"`
FilesAFiles struct {
Num884808 struct {
IDRow string `json:"_idRow"`
SFile string `json:"_sFile"`
NFilesize int `json:"_nFilesize"`
TsDateAdded int `json:"_tsDateAdded"`
NDownloadCount int `json:"_nDownloadCount"`
SDownloadURL string `json:"_sDownloadUrl"`
SMd5Checksum string `json:"_sMd5Checksum"`
SAnalysisState string `json:"_sAnalysisState"`
SAnalysisResult string `json:"_sAnalysisResult"`
SAnalysisResultVerbose string `json:"_sAnalysisResultVerbose"`
SAvState string `json:"_sAvState"`
SAvResult string `json:"_sAvResult"`
BIsArchived bool `json:"_bIsArchived"`
BHasContents bool `json:"_bHasContents"`
} `json:"884808"`
} `json:"Files().aFiles()"`
GameName string `json:"Game().name"`
InstallInstructions string `json:"install_instructions"`
IsObsolete string `json:"is_obsolete"`
LastpostDate int `json:"lastpost_date"`
LastpostUserid int `json:"lastpost_userid"`
Likes int `json:"likes"`
Mdate int `json:"mdate"`
Modnote string `json:"modnote"`
Name string `json:"name"`
NsfwBIsNsfw bool `json:"Nsfw().bIsNsfw()"`
ObsolNotice string `json:"obsol_notice"`
OwnerName string `json:"Owner().name"`
Postcount int `json:"postcount"`
PostsLastPostIDPosterRow int `json:"Posts().LastPost().idPosterRow()"`
PostsLastPostSText string `json:"Posts().LastPost().sText()"`
PostsLastPostTsDateAdded int `json:"Posts().LastPost().tsDateAdded()"`
PostsPostcountNPostCount int `json:"Posts().Postcount().nPostCount()"`
PreviewSStructuredDataFullsizeURL string `json:"Preview().sStructuredDataFullsizeUrl()"`
PreviewSSubFeedImageURL string `json:"Preview().sSubFeedImageUrl()"`
RootCategoryID int `json:"RootCategory().id"`
RootCategoryName string `json:"RootCategory().name"`
Screenshots string `json:"screenshots"`
Studioid int `json:"studioid"`
Text string `json:"text"`
TrashBIsTrashed bool `json:"Trash().bIsTrashed()"`
Udate int `json:"udate"`
UpdatesAGetLatestUpdates []interface{} `json:"Updates().aGetLatestUpdates()"`
UpdatesALatestUpdates []interface{} `json:"Updates().aLatestUpdates()"`
UpdatesBSubmissionHasUpdates bool `json:"Updates().bSubmissionHasUpdates()"`
UpdatesNUpdatesCount int `json:"Updates().nUpdatesCount()"`
URLSDownloadURL string `json:"Url().sDownloadUrl()"`
URLSEditURL string `json:"Url().sEditUrl()"`
URLSEmbeddablesURL string `json:"Url().sEmbeddablesUrl()"`
URLSHistoryURL string `json:"Url().sHistoryUrl()"`
URLSProfileURL string `json:"Url().sProfileUrl()"`
URLSTrashURL string `json:"Url().sTrashUrl()"`
URLSUntrashURL string `json:"Url().sUntrashUrl()"`
URLSUpdatesURL string `json:"Url().sUpdatesUrl()"`
URLSWithholdURL string `json:"Url().sWithholdUrl()"`
Userid int `json:"userid"`
Views int `json:"views"`
WithholdBIsWithheld bool `json:"Withhold().bIsWithheld()"`
}
func GetGameBananaMod(id string) (GameBananaMod, error) {
// build URL params
base, err := url.Parse("https://api.gamebanana.com/Core/Item/Data")
if err != nil {
log.Error("failed to parse URL", "err", err)
return GameBananaMod{}, err
}
params := url.Values{}
params.Add("itemtype", "Mod")
params.Add("itemid", id)
params.Add("format", "json_min")
params.Add("return_keys", "1")
params.Add("fields", "apps_used,authors,Category().name,catid,contestid,creator,Credits().aAuthors(),Credits().aAuthorsAndGroups(),Credits().ssvAuthorNames(),date,description,downloads,feedback_instructions,Files().aFiles(),Game().name,install_instructions,is_obsolete,lastpost_date,lastpost_userid,likes,mdate,modnote,name,Nsfw().bIsNsfw(),obsol_notice,Owner().name,postcount,Posts().LastPost().idPosterRow(),Posts().LastPost().sText(),Posts().LastPost().tsDateAdded(),Posts().Postcount().nPostCount(),Preview().sStructuredDataFullsizeUrl(),Preview().sSubFeedImageUrl(),RootCategory().id,RootCategory().name,screenshots,studioid,text,Trash().bIsTrashed(),udate,Updates().aGetLatestUpdates(),Updates().aLatestUpdates(),Updates().bSubmissionHasUpdates(),Updates().nUpdatesCount(),Url().sDownloadUrl(),Url().sEditUrl(),Url().sEmbeddablesUrl(),Url().sHistoryUrl(),Url().sProfileUrl(),Url().sTrashUrl(),Url().sUntrashUrl(),Url().sUpdatesUrl(),Url().sWithholdUrl(),userid,views,Withhold().bIsWithheld()")
base.RawQuery = params.Encode()
// send request
log.Info("got request url for Mod information", "id", id, "url", base.String())
resp, err := http.Get(base.String())
if err != nil || resp.StatusCode != 200 {
log.Error("failed to request URL", "url", base.String(), "err", err, "httpstatus", resp.StatusCode)
return GameBananaMod{}, err
}
defer resp.Body.Close()
// decode response
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Error("failed to decode body into bytes")
return GameBananaMod{}, err
}
var dataStruct GameBananaMod
err = json.Unmarshal(body, &dataStruct)
if err != nil {
log.Error("failed to decode request body", "err", err)
log.Debug(string(body))
return GameBananaMod{}, err
}
return dataStruct, nil
}