commit d84835525689a42f72b7ef56518fc5f737365ef7 Author: specCon18 Date: Thu Jun 19 21:04:39 2025 -0400 Initial Commit added caching diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e01ed50 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +STEAM_API/ diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f728c3b --- /dev/null +++ b/go.mod @@ -0,0 +1,16 @@ +module armareforger_update_checker + +go 1.23.8 + +require github.com/mmcdole/gofeed v1.3.0 + +require ( + github.com/PuerkitoBio/goquery v1.8.0 // indirect + github.com/andybalholm/cascadia v1.3.1 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/mmcdole/goxpp v1.1.1-0.20240225020742-a0c311522b23 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + golang.org/x/net v0.4.0 // indirect + golang.org/x/text v0.5.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..1ccfcda --- /dev/null +++ b/go.sum @@ -0,0 +1,37 @@ +github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U= +github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI= +github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= +github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/mmcdole/gofeed v1.3.0 h1:5yn+HeqlcvjMeAI4gu6T+crm7d0anY85+M+v6fIFNG4= +github.com/mmcdole/gofeed v1.3.0/go.mod h1:9TGv2LcJhdXePDzxiuMnukhV2/zb6VtnZt1mS+SjkLE= +github.com/mmcdole/goxpp v1.1.1-0.20240225020742-a0c311522b23 h1:Zr92CAlFhy2gL+V1F+EyIuzbQNbSgP4xhTODZtrXUtk= +github.com/mmcdole/goxpp v1.1.1-0.20240225020742-a0c311522b23/go.mod h1:v+25+lT2ViuQ7mVxcncQ8ch1URund48oH+jhjiwEgS8= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go new file mode 100644 index 0000000..ca141b3 --- /dev/null +++ b/main.go @@ -0,0 +1,104 @@ +package main + +import ( + "encoding/json" + "log" + "net/http" + "regexp" + "sync" + "time" + + "github.com/mmcdole/gofeed" +) + +type Update struct { + Version string `json:"version"` + Build string `json:"build"` + Published string `json:"published"` // ISO date string YYYY-MM-DD +} + +var ( + cacheMu sync.Mutex + cachedUpdates []Update + cacheExpiry time.Time + cacheDuration = 5 * time.Minute // adjust as needed +) + +func fetchUpdates(feedURL string) ([]Update, error) { + parser := gofeed.NewParser() + feed, err := parser.ParseURL(feedURL) + if err != nil { + return nil, err + } + + versionRe := regexp.MustCompile(`(?i)(?:^|\s)(\d+\.\d+(?:\.\d+)?(?:\.\d+)?)(?:\s+)?Update|Update\s+(\d+\.\d+(?:\.\d+)?(?:\.\d+)?)`) + buildRe := regexp.MustCompile(`SteamDB Build (\d+)`) + + var updates []Update + for _, item := range feed.Items { + buildMatch := buildRe.FindStringSubmatch(item.Description) + versionMatch := versionRe.FindStringSubmatch(item.Description) + + if len(buildMatch) > 1 && len(versionMatch) > 1 { + version := versionMatch[1] + if version == "" && len(versionMatch) > 2 { + version = versionMatch[2] + } + + build := buildMatch[1] + + pubTime, err := time.Parse(time.RFC1123Z, item.Published) + if err != nil { + log.Printf("Error parsing date for item %s: %v", item.Title, err) + continue + } + + updates = append(updates, Update{ + Version: version, + Build: build, + Published: pubTime.Format("2006-01-02"), + }) + } + } + return updates, nil +} + +func getCachedUpdates(feedURL string) ([]Update, error) { + cacheMu.Lock() + defer cacheMu.Unlock() + + if time.Now().Before(cacheExpiry) && cachedUpdates != nil { + return cachedUpdates, nil + } + + updates, err := fetchUpdates(feedURL) + if err != nil { + return nil, err + } + + cachedUpdates = updates + cacheExpiry = time.Now().Add(cacheDuration) + return updates, nil +} + +func updatesHandler(w http.ResponseWriter, r *http.Request) { + const feedURL = "https://steamdb.info/api/PatchnotesRSS/?appid=1874880" + + updates, err := getCachedUpdates(feedURL) + if err != nil { + http.Error(w, "Failed to fetch updates: "+err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(updates); err != nil { + http.Error(w, "Failed to encode JSON: "+err.Error(), http.StatusInternalServerError) + } +} + +func main() { + http.HandleFunc("/updates", updatesHandler) + log.Println("Listening on http://localhost:8080/updates") + log.Fatal(http.ListenAndServe(":8080", nil)) +} +