commit 48fb09cfb9b0f45c370b50600b2f0fa3f4ee6ec5 Author: specCon18 Date: Sat Jun 21 05:56:19 2025 -0400 Initial commit need to add nix code to setup service and timer example service and timer are provided diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c1e761c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +latest_version.txt diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..e83cbc6 --- /dev/null +++ b/flake.lock @@ -0,0 +1,26 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1750400657, + "owner": "nixos", + "repo": "nixpkgs", + "rev": "b2485d56967598da068b5a6946dadda8bfcbcd37", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..57fd6e4 --- /dev/null +++ b/flake.nix @@ -0,0 +1,60 @@ +{ + description = "A simple Go package"; + + # Nixpkgs / NixOS version to use. + inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; + + outputs = + { self, nixpkgs }: + let + # System types to support. + supportedSystems = [ + "x86_64-linux" + ]; + + # Helper function to generate an attrset '{ x86_64-linux = f "x86_64-linux"; ... }'. + forAllSystems = nixpkgs.lib.genAttrs supportedSystems; + + # Nixpkgs instantiated for supported system types. + nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; }); + + in + { + + # Provide some binary packages for selected system types by mapping over each system architecture. + packages = forAllSystems ( + system: + let + # Set pkgs = the correct version for a given architecture. + pkgs = nixpkgsFor.${system}; + in + { + #TODO: NEED TO GO OVER THIS SYNTAX AGAIN. + go-hello = pkgs.callPackage ./package.nix { }; + } + ); + + # Add dependencies that are only needed for development, this also allows for nix develop command to launch a devshell + devShells = forAllSystems ( + system: + let + pkgs = nixpkgsFor.${system}; + in + { + default = pkgs.mkShell { + buildInputs = with pkgs; [ + go + gopls + gotools + go-tools + ]; + }; + } + ); + + # The default package for 'nix build'. This makes sense if the + # flake provides only one package or there is a clear "main" + # package. + defaultPackage = forAllSystems (system: self.packages.${system}.go-hello); + }; +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d8d0273 --- /dev/null +++ b/go.mod @@ -0,0 +1,2 @@ +module reforgerds-updater +go 1.16 diff --git a/main.go b/main.go new file mode 100644 index 0000000..919f5dd --- /dev/null +++ b/main.go @@ -0,0 +1,106 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "os/exec" + "strings" +) + +type Update struct { + Version string `json:"version"` + Build string `json:"build"` + Published string `json:"published"` +} + +const ( + updateURL = "http://127.0.0.1:3000/updates" + stateFilePath = "latest_version.txt" +) +func main() { + resp, err := http.Get(updateURL) + if err != nil { + fmt.Printf("Failed to fetch updates: %v\n", err) + return + } + defer resp.Body.Close() + + body, _ := io.ReadAll(resp.Body) + + var updates []Update + err = json.Unmarshal(body, &updates) + if err != nil { + fmt.Printf("Failed to parse response: %v\n", err) + return + } + + if len(updates) == 0 { + fmt.Println("No updates found.") + return + } + + latest := updates[0].Version + + prevVersion := "" + if data, err := os.ReadFile(stateFilePath); err == nil { + prevVersion = strings.TrimSpace(string(data)) + } + + if prevVersion == "" { + fmt.Println("No previous version found. Storing latest:", latest) + _ = os.WriteFile(stateFilePath, []byte(latest), 0644) + return + } + + if versionCompare(latest, prevVersion) > 0 { + fmt.Printf("New version found! %s > %s\n", latest, prevVersion) + + // Run steamcmd with reforger_update script + fmt.Println("Running update command...") + cmd := exec.Command("./steamcmd.sh", "+runscript", "reforger_update") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Run() + if err != nil { + fmt.Printf("Update command failed: %v\n", err) + return + } + + // Store the new latest version + _ = os.WriteFile(stateFilePath, []byte(latest), 0644) + } else { + fmt.Printf("No new version. Latest seen: %s\n", prevVersion) + } +} + +func versionCompare(a, b string) int { + segA := strings.Split(a, ".") + segB := strings.Split(b, ".") + + max := len(segA) + if len(segB) > max { + max = len(segB) + } + + for i := 0; i < max; i++ { + var ai, bi int + if i < len(segA) { + fmt.Sscanf(segA[i], "%d", &ai) + } + if i < len(segB) { + fmt.Sscanf(segB[i], "%d", &bi) + } + + if ai > bi { + return 1 + } + if ai < bi { + return -1 + } + } + return 0 +} + diff --git a/package.nix b/package.nix new file mode 100644 index 0000000..a792b35 --- /dev/null +++ b/package.nix @@ -0,0 +1,30 @@ +{ buildGoModule, gitMinimal }: +# This is the wrapping around mkderivation that abstracts away the standard boilerplate logic for building go packages. +buildGoModule { + # The final built binary name. + pname = "go-hello"; + # The binary version | NEEDS TO BE IN STEP WITH GO MOD. + version = "v1.0.0"; + # In 'nix develop', we don't need a copy of the source tree + # in the Nix store. + src = builtins.path { + name = "source"; + path = ./.; + }; + + # required deps for build time nativeBuildInputs are runtime deps + buildInputs = [ + # Just an example input + gitMinimal + ]; + # This hash locks the dependencies of this package. It is + # necessary because of how Go requires network access to resolve + # VCS. See https://www.tweag.io/blog/2021-03-04-gomod2nix/ for + # details. Normally one can build with a fake hash and rely on native Go + # mechanisms to tell you what the hash should be or determine what + # it should be "out-of-band" with other tooling (eg. gomod2nix). + # To begin with it is recommended to set this, but one must + # remember to bump this hash when your dependencies change. + # vendorHash = pkgs.lib.fakeHash; + vendorHash = null; +} diff --git a/reforger-updater.service b/reforger-updater.service new file mode 100644 index 0000000..7071499 --- /dev/null +++ b/reforger-updater.service @@ -0,0 +1,6 @@ +[Unit] +Description=Check and run reforger update if needed + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/reforger-updater diff --git a/reforger-updater.timer b/reforger-updater.timer new file mode 100644 index 0000000..22cf3b7 --- /dev/null +++ b/reforger-updater.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Run reforger-updater every 4 hours + +[Timer] +OnBootSec=5min +OnUnitActiveSec=4h +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/reforger_update b/reforger_update new file mode 100644 index 0000000..dcf0563 --- /dev/null +++ b/reforger_update @@ -0,0 +1,8 @@ +// update_arma_reforger_ds +// +@ShutdownOnFailedCommand 1 +@NoPromptForPassword 1 +force_install_dir ../reforger +login anonymous +app_update 1874900 validate +quit