From 6385ce4f459b073696115949d064f0b28d62b80a Mon Sep 17 00:00:00 2001 From: arcnmx Date: Thu, 16 Oct 2025 03:33:41 -0700 Subject: [PATCH] feat: sources generation --- .github/workflows/taimihud-datasources.yml | 169 ++++++++++++ README.md | 10 + ci/config.nix | 102 +++++++ config.nix | 2 + default.nix | 11 + flake.lock | 78 ++++++ flake.nix | 197 +++++++++++++ modules/datasource.nix | 75 +++++ modules/direct/datasource.nix | 29 ++ modules/direct/remotesource.nix | 50 ++++ modules/direct/version.nix | 15 + modules/github/datasource.nix | 43 +++ modules/github/remotesource.nix | 117 ++++++++ modules/github/version.nix | 25 ++ modules/manual/datasource.nix | 25 ++ modules/manual/remotesource.nix | 50 ++++ modules/manual/version.nix | 15 + modules/sources/datasources.nix | 34 +++ modules/sources/output/settings.nix | 64 +++++ modules/specialargs.nix | 60 ++++ modules/version.nix | 57 ++++ pathing/config.nix | 5 + pathing/taco/config.nix | 5 + pathing/taco/derivation.nix | 32 +++ pathing/taco/sources.nix | 307 +++++++++++++++++++++ timers/config.nix | 26 ++ 26 files changed, 1603 insertions(+) create mode 100644 .github/workflows/taimihud-datasources.yml create mode 100644 ci/config.nix create mode 100644 config.nix create mode 100644 default.nix create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 modules/datasource.nix create mode 100644 modules/direct/datasource.nix create mode 100644 modules/direct/remotesource.nix create mode 100644 modules/direct/version.nix create mode 100644 modules/github/datasource.nix create mode 100644 modules/github/remotesource.nix create mode 100644 modules/github/version.nix create mode 100644 modules/manual/datasource.nix create mode 100644 modules/manual/remotesource.nix create mode 100644 modules/manual/version.nix create mode 100644 modules/sources/datasources.nix create mode 100644 modules/sources/output/settings.nix create mode 100644 modules/specialargs.nix create mode 100644 modules/version.nix create mode 100644 pathing/config.nix create mode 100644 pathing/taco/config.nix create mode 100644 pathing/taco/derivation.nix create mode 100644 pathing/taco/sources.nix create mode 100644 timers/config.nix diff --git a/.github/workflows/taimihud-datasources.yml b/.github/workflows/taimihud-datasources.yml new file mode 100644 index 0000000..d233b34 --- /dev/null +++ b/.github/workflows/taimihud-datasources.yml @@ -0,0 +1,169 @@ +env: + CI_ALLOW_ROOT: '1' + CI_CONFIG: ./ci/config.nix + CI_PLATFORM: gh-actions +jobs: + ci-check: + name: taimihud-datasources check + runs-on: ubuntu-latest + steps: + - id: checkout + name: git clone + uses: actions/checkout@v4 + with: + submodules: true + - id: nix-install + name: nix install + uses: arcnmx/ci/actions/nix/install@v0.7 + - id: ci-action-build + name: nix build ci.gh-actions.configFile + uses: arcnmx/ci/actions/nix/build@v0.7 + with: + attrs: ci.gh-actions.configFile + out-link: .ci/workflow.yml + - id: ci-action-compare + name: gh-actions compare + uses: arcnmx/ci/actions/nix/run@v0.7 + with: + args: -u .github/workflows/taimihud-datasources.yml .ci/workflow.yml + attrs: nixpkgs.diffutils + command: diff + main: + name: taimihud-datasources-main + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - id: checkout + name: git clone + uses: actions/checkout@v4 + with: + submodules: true + - id: nix-install + name: nix install + uses: arcnmx/ci/actions/nix/install@v0.7 + - id: ci-setup + name: nix setup + uses: arcnmx/ci/actions/nix/run@v0.7 + with: + attrs: ci.job.main.run.bootstrap + quiet: false + - id: ci-dirty + name: nix test dirty + uses: arcnmx/ci/actions/nix/run@v0.7 + with: + attrs: ci.job.main.run.test + command: ci-build-dirty + quiet: false + stdout: ${{ runner.temp }}/ci.build.dirty + - id: ci-test + name: nix test build + uses: arcnmx/ci/actions/nix/run@v0.7 + with: + attrs: ci.job.main.run.test + command: ci-build-realise + ignore-exit-code: true + quiet: false + stdin: ${{ runner.temp }}/ci.build.dirty + - env: + CI_EXIT_CODE: ${{ steps.ci-test.outputs.exit-code }} + id: ci-summary + name: nix test results + uses: arcnmx/ci/actions/nix/run@v0.7 + with: + attrs: ci.job.main.run.test + command: ci-build-summarise + quiet: false + stdin: ${{ runner.temp }}/ci.build.dirty + stdout: ${{ runner.temp }}/ci.build.cache + - env: + CACHIX_SIGNING_KEY: ${{ secrets.CACHIX_SIGNING_KEY }} + id: ci-cache + if: always() + name: nix test cache + uses: arcnmx/ci/actions/nix/run@v0.7 + with: + attrs: ci.job.main.run.test + command: ci-build-cache + quiet: false + stdin: ${{ runner.temp }}/ci.build.cache + - id: artifact-build + name: artifact build + uses: arcnmx/ci/actions/nix/build@v0.7 + with: + attrs: config.jobs.main.artifactPackage + file: + out-link: .ci/artifacts + - id: artifact-upload + name: artifact upload + uses: actions/upload-artifact@v4 + with: + name: TaimiHUD-DataSources + path: .ci/artifacts/share/taimihud/sources.toml + - id: release-upload + if: startsWith(github.ref, 'refs/tags/') + name: release + uses: softprops/action-gh-release@v1 + with: + files: .ci/artifacts/share/taimihud/sources.toml + updates: + name: taimihud-datasources-updates + runs-on: ubuntu-latest + steps: + - id: checkout + name: git clone + uses: actions/checkout@v4 + with: + submodules: true + - id: nix-install + name: nix install + uses: arcnmx/ci/actions/nix/install@v0.7 + - id: ci-setup + name: nix setup + uses: arcnmx/ci/actions/nix/run@v0.7 + with: + attrs: ci.job.updates.run.bootstrap + quiet: false + - id: ci-dirty + name: nix test dirty + uses: arcnmx/ci/actions/nix/run@v0.7 + with: + attrs: ci.job.updates.run.test + command: ci-build-dirty + quiet: false + stdout: ${{ runner.temp }}/ci.build.dirty + - id: ci-test + name: nix test build + uses: arcnmx/ci/actions/nix/run@v0.7 + with: + attrs: ci.job.updates.run.test + command: ci-build-realise + ignore-exit-code: true + quiet: false + stdin: ${{ runner.temp }}/ci.build.dirty + - env: + CI_EXIT_CODE: ${{ steps.ci-test.outputs.exit-code }} + id: ci-summary + name: nix test results + uses: arcnmx/ci/actions/nix/run@v0.7 + with: + attrs: ci.job.updates.run.test + command: ci-build-summarise + quiet: false + stdin: ${{ runner.temp }}/ci.build.dirty + stdout: ${{ runner.temp }}/ci.build.cache + - env: + CACHIX_SIGNING_KEY: ${{ secrets.CACHIX_SIGNING_KEY }} + id: ci-cache + if: always() + name: nix test cache + uses: arcnmx/ci/actions/nix/run@v0.7 + with: + attrs: ci.job.updates.run.test + command: ci-build-cache + quiet: false + stdin: ${{ runner.temp }}/ci.build.cache +name: taimihud-datasources +'on': +- push +- pull_request diff --git a/README.md b/README.md index 89b62b2..b8aefe4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ # TaimiHUD data sources This is a repository to be used for requests to list data sources for TaimiHUD. + +## Updating + +(this isn't necessary in order to generate sources.toml to be consumed by TaimiHUD so can be ignored for now) + +This should be automated by CI, but some of the manual process will be described here. + +```bash +nix build -L .#allUpdateChecks +``` diff --git a/ci/config.nix b/ci/config.nix new file mode 100644 index 0000000..eb26b97 --- /dev/null +++ b/ci/config.nix @@ -0,0 +1,102 @@ +{ config, pkgs, lib, ... }: with pkgs; with lib; let + datasources = import ../.; + legacyPackages = datasources.legacyPackages.${pkgs.system}; + packages = datasources.packages.${pkgs.system}; + artifactRoot = ".ci/artifacts"; + artifacts = "${artifactRoot}/${sourcesTomlPath}"; + release = "${artifactRoot}/${sourcesTomlPath}"; + sourcesTomlPath = "share/taimihud/sources.toml"; + sourcesToml = linkFarm "taimihud-sources.toml" [ + { name = sourcesTomlPath; path = packages.sourcesToml; } + ]; +in +{ + config = { + name = "taimihud-datasources"; + ci.version = "v0.7"; + ci.gh-actions = { + enable = true; + export = true; + }; + cache.cachix.taimihud = { + enable = true; + publicKey = "taimihud.cachix.org-1:2LByDgq5eUVU2FoeIlMd5NMgUeCDXuuVarS+XbNsIkY="; + signingKey = "nya"; + }; + #channels.nixpkgs.version = "25.05"; + jobs = { + main = { + tasks = { + build.inputs = [ sourcesToml ]; + }; + artifactPackages = { + sources = sourcesToml; + }; + }; + updates = { + tasks = { + build.inputs = legacyPackages.updateChecks; + }; + }; + }; + + # XXX: symlinks are not followed, see https://github.com/softprops/action-gh-release/issues/182 + artifactPackage = mkIf (config.artifactPackages != {}) (runCommand "taimihud-datasource-artifacts" { } ('' + mkdir -p $out/share + '' + concatStringsSep "\n" (mapAttrsToList (key: taimi: '' + cp -Lr --no-preserve=mode -t $out ${taimi}/share + '') config.artifactPackages))); + + gh-actions = { + jobs = mkIf (config.id != "ci" && config.artifactPackage != null) { + ${config.id} = { + permissions = { + contents = "write"; + }; + step = { + artifact-build = { + order = 1100; + name = "artifact build"; + uses = { + # XXX: a very hacky way of getting the runner + inherit (config.gh-actions.jobs.${config.id}.step.ci-setup.uses) owner repo version; + path = "actions/nix/build"; + }; + "with" = { + file = ""; + attrs = "config.jobs.${config.jobId}.artifactPackage"; + out-link = artifactRoot; + }; + }; + artifact-upload = { + order = 1110; + name = "artifact upload"; + uses.path = "actions/upload-artifact@v4"; + "with" = { + name = "TaimiHUD-DataSources"; + path = artifacts; + }; + }; + release-upload = { + order = 1111; + name = "release"; + "if" = "startsWith(github.ref, 'refs/tags/')"; + uses.path = "softprops/action-gh-release@v1"; + "with".files = release; + }; + }; + }; + }; + }; + }; + options = { + artifactPackage = mkOption { + type = types.nullOr types.package; + default = null; + }; + artifactPackages = mkOption { + type = with types; attrsOf package; + default = {}; + }; + }; +} diff --git a/config.nix b/config.nix new file mode 100644 index 0000000..87a13d7 --- /dev/null +++ b/config.nix @@ -0,0 +1,2 @@ +_: { +} diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..df2322b --- /dev/null +++ b/default.nix @@ -0,0 +1,11 @@ +let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + flakeCompat = fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + }; + taimiHUD = import flakeCompat { + src = ./.; + }; +in +taimiHUD.defaultNix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..adb8218 --- /dev/null +++ b/flake.lock @@ -0,0 +1,78 @@ +{ + "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1733328505, + "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1742237028, + "narHash": "sha256-xlpHmgBxUnvHo8FNnju0sgnEyasb4gC607b+keqjmX8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9bc8a90931262245919a26f995c1f24c6c70d3fe", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..05acb4e --- /dev/null +++ b/flake.nix @@ -0,0 +1,197 @@ +{ + description = "TaimiHUD remote data"; + inputs = { + flake-compat = { + url = "github:edolstra/flake-compat"; + flake = false; + }; + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils = { + url = "github:numtide/flake-utils"; + }; + }; + + outputs = { self, flake-utils, nixpkgs, ... }@inputs: let + nixlib = nixpkgs.lib; + mkSystem = system: let + legacyPackages = self.legacyPackages.${system}; + packages = self.packages.${system}; + inherit (legacyPackages) pkgs callPackage; + in { + packages = { + /* TODO + packs = callPackage ./pathing/taco/derivation.nix { + datasources = self; + };*/ + sourcesToml = callPackage self.lib.datasources.config.output.get.file {}; + + default = packages.sourcesToml; + }; + + legacyPackages = { + pkgs = nixpkgs.legacyPackages.${system} or (import nixpkgs { + inherit system; + }); + callPackage = pkgs.newScope { + datasources = self; + inherit (packages) packs sources; + }; + github-release-check = callPackage self.lib.github-release-check {}; + updateChecks = let + inherit (nixlib) mapAttrsToList attrValues concatLists filter makeOverridable removePrefix; + inherit (self.lib.datasources.config) datasources; + filterGithubSources = filter (ds: ds.remote.github.enable or false); + getGithubSources = dss: filterGithubSources (attrValues dss); + githubSources = concatLists (mapAttrsToList (_: getGithubSources) datasources); + mkGithubUpdate = ds: makeOverridable legacyPackages.github-release-check { + pname = ds.name; + ref = removePrefix "refs/tags/" ds.versions.${toString ds.latest.version}.fetcher.args.ref or "unknown"; + inherit (ds.remote.github) owner repo; + }; + in map mkGithubUpdate githubSources; + allUpdateChecks = let + mkUpdateLink = up: { + inherit (up) name; + path = up; + }; + allUpdateChecks = { + updateChecks + , linkFarm + }: linkFarm "taimihud-update-checks" (map mkUpdateLink updateChecks); + in callPackage allUpdateChecks { + inherit (legacyPackages) updateChecks; + }; + }; + }; + systems = flake-utils.lib.eachDefaultSystem mkSystem; + in { + inherit (systems) legacyPackages packages; + datasourceModules = { + datasource = { + datasource = ./modules/datasource.nix; + datasource'manual = ./modules/manual/datasource.nix; + datasource'direct = ./modules/direct/datasource.nix; + datasource'github = ./modules/github/datasource.nix; + default = let + inherit (self.datasourceModules) datasource; + in _: { + imports = [ + datasource.datasource + datasource.datasource'manual + datasource.datasource'direct + datasource.datasource'github + ]; + }; + }; + datasource'version = { + version = ./modules/version.nix; + default = let + inherit (self.datasourceModules) datasource'version; + in _: { + imports = [ + datasource'version.version + ]; + }; + }; + datasource'remote = { + datasource'manual'remote = ./modules/manual/remotesource.nix; + datasource'direct'remote = ./modules/direct/remotesource.nix; + datasource'github'remote = ./modules/github/remotesource.nix; + }; + sources = { + datasources = ./modules/sources/datasources.nix; + output-settings = ./modules/sources/output/settings.nix; + default = let + inherit (self.datasourceModules) sources; + in _: { + imports = [ + sources.datasources + sources.output-settings + ]; + }; + }; + generic = { + specialargs = ./modules/specialargs.nix; + }; + config = { + config = ./config.nix; + pathing = ./pathing/config.nix; + timers = ./timers/config.nix; + default = let + inherit (self.datasourceModules) config; + in _: { + imports = [ + config.config + config.pathing + config.timers + ]; + }; + }; + }; + lib = { + datasources = nixlib.evalModules { + modules = [ + self.datasourceModules.sources.default + self.datasourceModules.config.default + ]; + specialArgs = { + inherit (self) datasourceModules; + inherit inputs; + }; + }; + github-release-check = { + runCommand + , curl, jq + }: { + pname + , ref + , owner + , repo + , impure ? toString builtins.currentTime or self.sourceInfo.lastModified + , outputHashAlgo ? "sha256" + }: runCommand "${pname}-check-${ref}" { + inherit pname outputHashAlgo impure ref owner repo; + outputHash = builtins.hashString outputHashAlgo "${pname}!${ref}!${impure}\n"; + outputHashMode = "flat"; + preferLocalBuild = true; + allowSubstitutes = false; + impureEnvVars = nixlib.fetchers.proxyImpureEnvVars ++ [ "NIX_CURL_FLAGS" ]; + nativeBuildInputs = [ curl jq ]; + #queryRelease = "sort_by(.tag_name) | [.[]|select(.prerelease==false and .draft==false)] | .[-1].tag_name"; + queryTag = "sort_by(.name) | .[-1].name"; + queryReleaseLatest = ".tag_name"; + meta.displayName = "${pname} ${ref} outdated"; + } '' + #RELEASE_URL="https://api.github.com/repos/$owner/$repo/releases" + RELEASE_URL="https://api.github.com/repos/$owner/$repo/releases/latest" + TAGS_URL="https://api.github.com/repos/$owner/$repo/tags" + if REPO_RELEASES=$(curl \ + --insecure \ + -fSsL \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + $NIX_CURL_FLAGS \ + "$RELEASE_URL" + ); then + REPO_LATEST=$(jq -r "$queryReleaseLatest" - <<< "$REPO_RELEASES") + elif REPO_TAGS=$(curl \ + --insecure \ + -fSsL \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + $NIX_CURL_FLAGS \ + "$TAGS_URL" + ); then + REPO_LATEST=$(jq -r "$queryTag" - <<< "$REPO_TAGS") + else + echo failed to query latest release >&2 + return 1 + fi + if [[ $REPO_LATEST = $ref ]]; then + echo "$pname-$ref up-to-date" >&2 + else + echo "$pname-$ref out of date, found version $REPO_LATEST" >&2 + fi + printf '%s!%s!%s\n' "$pname" "$REPO_LATEST" "$impure" > $out + ''; + }; + }; +} diff --git a/modules/datasource.nix b/modules/datasource.nix new file mode 100644 index 0000000..ec657d6 --- /dev/null +++ b/modules/datasource.nix @@ -0,0 +1,75 @@ +{ datasourceModules, name, lib, config, ... }: let + inherit (lib.attrsets) attrNames; + inherit (lib.lists) sort head; + inherit (lib.modules) mkIf mkOptionDefault; + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.strings) versionAtLeast; + inherit (lib) types; +in { + options = { + name = mkOption { + type = types.str; + default = name; + }; + url = mkOption { + type = types.nullOr types.str; + default = null; + }; + description = mkOption { + type = types.nullOr types.str; + default = null; + }; + fileName = mkOption { + type = types.nullOr types.str; + default = null; + }; + remote = { + }; + versions = mkOption { + type = types.attrsOf (config.special.submoduleType datasourceModules.datasource'version.default); + default = {}; + }; + latest = { + version = mkOption { + type = types.nullOr types.str; + }; + url = mkOption { + type = types.nullOr types.str; + }; + }; + output = { + enable = mkEnableOption "sources.toml output" // { + default = true; + }; + sortPrio = mkOption { + type = types.int; + default = 100; + }; + settings = mkOption { + type = types.attrsOf types.unspecified; + }; + }; + }; + config = { + latest = { + version = let + # TODO: map to/from versionName since it can be customized to mismatch the attr... + versions = sort versionAtLeast (attrNames config.versions); + in mkOptionDefault ( + if config.versions == {} then null else head versions + ); + url = let + hasUrl = config.latest.version != null && url != null; + version = config.versions.${config.latest.version}; + url = version.get.urlFor {} {}; + in mkOptionDefault (if hasUrl then url else null); + }; + output.settings = { + name = mkOptionDefault config.name; + description = mkIf (config.description != null) (mkOptionDefault config.description); + }; + special.args = { + datasourceConfig = mkOptionDefault config; + }; + }; +} diff --git a/modules/direct/datasource.nix b/modules/direct/datasource.nix new file mode 100644 index 0000000..351005b --- /dev/null +++ b/modules/direct/datasource.nix @@ -0,0 +1,29 @@ +{ config, lib, ... }: let + mkAlmostOptionDefault = lib.mkOverride 1400; + inherit (lib.attrsets) mapAttrs; + inherit (lib.options) mkOption; + inherit (lib.modules) mkIf; + inherit (lib) types; + cfg = config.remote.direct; +in { + options = { + remote.direct = mkOption { + type = types.nullOr (config.special.submoduleType [ + ./remotesource.nix + ]); + default = null; + }; + versions = mkOption { + type = types.attrsOf (types.submodule [ + ./version.nix + ]); + }; + }; + config = mkIf cfg.enable or false { + output.settings = mapAttrs (_: mkAlmostOptionDefault) { + type = "Direct"; + inherit (cfg) url; + }; + url = mkAlmostOptionDefault cfg.url; + }; +} diff --git a/modules/direct/remotesource.nix b/modules/direct/remotesource.nix new file mode 100644 index 0000000..4c4a3f2 --- /dev/null +++ b/modules/direct/remotesource.nix @@ -0,0 +1,50 @@ +{ config, lib, ... }: let + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.strings) nameFromURL; + inherit (lib.trivial) defaultTo mapNullable; + inherit (lib) types; + getFileExt = getFileSuffix "."; + getFileSuffix = sep: filename: let + inherit (lib.lists) last length; + inherit (lib.strings) splitString; + components = splitString sep filename; + in if length components <= 1 then "" else "${sep}${last components}"; +in { + options = { + enable = mkEnableOption "URL remote source" // { + default = true; + }; + url = mkOption { + type = types.str; + }; + get = mkOption { + type = types.lazyAttrsOf (types.unspecified); + }; + }; + config = { + get = { + fetcherFor = { + fetchurl + }: { + extraArgs ? {} + , hash + , versionName ? null + , fileName ? null + , ... + }: let + inherit (config) url; + in { + inherit url hash versionName fileName extraArgs; + __toString = self: let + fileName = defaultTo (builtins.baseNameOf self.url) self.fileName or null; + in fetchurl ({ + ${mapNullable (_: "name") self.versionName} = "${nameFromURL fileName "."}-${self.versionName}${getFileExt fileName}"; + inherit (self) url hash; + } // self.extraArgs); + }; + srcFetcherFor = {}: args: let + fetcher = config.get.fetcherFor args; + in fetcher.__toString fetcher; + }; + }; +} diff --git a/modules/direct/version.nix b/modules/direct/version.nix new file mode 100644 index 0000000..85711ba --- /dev/null +++ b/modules/direct/version.nix @@ -0,0 +1,15 @@ +{ datasourceConfig, lib, ... }: let + inherit (lib.attrsets) mapAttrs; + inherit (lib.modules) mkDefault mkIf; + inherit (lib.trivial) defaultTo; + cfg = defaultTo { + enable = false; + } datasourceConfig.remote.direct or null; + get = mapAttrs (_: mkDefault) { + inherit (cfg.get) fetcherFor srcFetcherFor; + }; +in { + config = { + get = mkIf cfg.enable get; + }; +} diff --git a/modules/github/datasource.nix b/modules/github/datasource.nix new file mode 100644 index 0000000..1bc65b8 --- /dev/null +++ b/modules/github/datasource.nix @@ -0,0 +1,43 @@ +{ config, lib, ... }: let + mkAlmostOptionDefault = lib.mkOverride 1400; + inherit (lib.attrsets) mapAttrs; + inherit (lib.modules) mkIf; + inherit (lib.options) mkOption; + inherit (lib.strings) replaceStrings; + inherit (lib) types; + cfg = config.remote.github; +in { + options = { + remote.github = mkOption { + type = types.nullOr (config.special.submoduleType [ + ./remotesource.nix + ]); + default = null; + }; + versions = mkOption { + type = types.attrsOf (types.submodule [ + ./version.nix + ]); + }; + }; + config = mkIf cfg.enable or false { + latest.url = let + urlFor = cfg.get.fetcherFor { + fetchurl = lib.id; + fetchFromGitHub = lib.id; + } { + ref = "latest"; + versionName = "latest"; + inherit (config) fileName; + }; + hasGithubUrl = cfg.releases.enable or false; + url = replaceStrings [ "/releases/download/latest/" ] [ "/releases/latest/download/" ] urlFor.url; + in mkIf hasGithubUrl (mkAlmostOptionDefault url); + output.settings = mapAttrs (_: mkAlmostOptionDefault) { + type = "GitHub"; + inherit (cfg) owner; + repository = cfg.repo; + }; + url = mkAlmostOptionDefault "https://github.com/${cfg.owner}/${cfg.repo}"; + }; +} diff --git a/modules/github/remotesource.nix b/modules/github/remotesource.nix new file mode 100644 index 0000000..3cb3fab --- /dev/null +++ b/modules/github/remotesource.nix @@ -0,0 +1,117 @@ +{ config, lib, ... }: let + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.strings) nameFromURL removePrefix; + inherit (lib) types; + getFileExt = getFileSuffix "."; + getFileSuffix = sep: filename: let + inherit (lib.lists) last length; + inherit (lib.strings) splitString; + components = splitString sep filename; + in if length components <= 1 then "" else "${sep}${last components}"; +in { + options = { + enable = mkEnableOption "github remote source" // { + default = true; + }; + owner = mkOption { + type = types.str; + }; + repo = mkOption { + type = types.str; + }; + releases = { + enable = mkEnableOption "github release downloads"; + }; + archive = { + enable = mkEnableOption "archive download"; + format = mkOption { + type = types.enum [ "tar.gz" "zip" ]; + default = "tar.gz"; + }; + }; + sourceFile = { + path = mkOption { + type = types.nullOr types.str; + default = null; + }; + }; + get = mkOption { + type = types.lazyAttrsOf (types.unspecified); + }; + }; + config = { + get = { + fetcherFor = { + fetchurl + , fetchFromGitHub + , datasource'github'releaseFetcherFor ? config.get.releaseFetcherFor { inherit fetchurl; } + , datasource'github'archiveFetcherFor ? config.get.archiveFetcherFor { inherit fetchurl; } + , datasource'github'fileFetcherFor ? config.get.fileFetcherFor { inherit fetchurl; } + , datasource'github'srcFetcherFor ? config.get.srcFetcherFor { inherit fetchFromGitHub; } + }: { + versionName ? null + , fileName ? null + , ref ? if versionName != null then "refs/tags/${versionName}" else throw "ref or versionName required" + , hash ? lib.fakeHash + , ... + }@args: let + args' = { + inherit hash ref; + } // args; + in + if config.releases.enable then datasource'github'releaseFetcherFor args' + else if config.archive.enable then datasource'github'archiveFetcherFor args' + else if config.sourceFile.path != null then datasource'github'fileFetcherFor args' + else datasource'github'srcFetcherFor args'; + releaseFetcherFor = { + fetchurl + }: { + extraArgs ? {} + , hash + , ref + , fileName + , versionName ? removePrefix "refs/tags/" ref + }: let + url = "https://github.com/${config.owner}/${config.repo}/releases/download/${versionName}/${fileName}"; + in { + inherit url hash ref versionName extraArgs fileName; + __toString = self: fetchurl ({ + name = "${nameFromURL self.url "."}-${self.versionName}${getFileExt self.url}"; + inherit (self) url hash; + } // self.extraArgs); + }; + fileFetcherFor = { + fetchurl + }: _: throw "TODO: github.get.fileFetcherFor"; + archiveFetcherFor = { + fetchurl + }: { + extraArgs ? {} + , hash + , ref + , ... + }: let + url = "https://github.com/${config.owner}/${config.repo}/archive/${ref}.${config.archive.format}"; + in { + inherit url hash ref extraArgs; + __toString = self: fetchurl ({ + inherit (self) url hash; + } // self.extraArgs); + }; + srcFetcherFor = { + fetchFromGitHub + }: { + extraArgs ? {} + , hash + , ref + , ... + }: let + fetchArgs = ({ + inherit (config) owner repo; + inherit hash; + rev = ref; + } // extraArgs); + in fetchFromGitHub fetchArgs; + }; + }; +} diff --git a/modules/github/version.nix b/modules/github/version.nix new file mode 100644 index 0000000..a28aeda --- /dev/null +++ b/modules/github/version.nix @@ -0,0 +1,25 @@ +{ datasourceConfig, config, lib, ... }: let + mkAlmostOptionDefault = lib.mkOverride 1400; + inherit (lib.attrsets) mapAttrs; + inherit (lib.modules) mkDefault mkOptionDefault mkIf; + inherit (lib.strings) hasPrefix removePrefix; + inherit (lib.trivial) defaultTo; + cfg = defaultTo { + enable = false; + } datasourceConfig.remote.github or null; + get = mapAttrs (_: mkDefault) { + inherit (cfg.get) fetcherFor srcFetcherFor; + }; +in { + config = { + fetcher.args = let + hasRef = cfg.releases.enable || cfg.archive.enable; + in mkIf cfg.enable { + versionName = mkIf (hasRef && hasPrefix "v" config.versionName) (mkAlmostOptionDefault ( + removePrefix "v" config.versionName + )); + ref = mkIf hasRef (mkOptionDefault "refs/tags/${config.versionName}"); + }; + get = mkIf cfg.enable get; + }; +} diff --git a/modules/manual/datasource.nix b/modules/manual/datasource.nix new file mode 100644 index 0000000..8f5488e --- /dev/null +++ b/modules/manual/datasource.nix @@ -0,0 +1,25 @@ +{ config, lib, ... }: let + mkAlmostOptionDefault = lib.mkOverride 1400; + inherit (lib.options) mkOption; + inherit (lib.modules) mkIf; + inherit (lib) types; + cfg = config.remote.manual; +in { + options = { + remote.manual = mkOption { + type = types.nullOr (config.special.submoduleType [ + ./remotesource.nix + ]); + default = null; + }; + versions = mkOption { + type = types.attrsOf (types.submodule [ + ./version.nix + ]); + }; + }; + config = mkIf cfg.enable or false { + output.enable = mkAlmostOptionDefault false; + url = mkAlmostOptionDefault cfg.url; + }; +} diff --git a/modules/manual/remotesource.nix b/modules/manual/remotesource.nix new file mode 100644 index 0000000..ffd1bcb --- /dev/null +++ b/modules/manual/remotesource.nix @@ -0,0 +1,50 @@ +{ config, datasourceConfig, lib, ... }: let + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.trivial) defaultTo; + inherit (lib) types; +in { + options = { + enable = mkEnableOption "manual remote source" // { + default = true; + }; + url = mkOption { + type = types.str; + }; + get = mkOption { + type = types.lazyAttrsOf (types.unspecified); + }; + }; + config = { + get = { + fetcherFor = { + requireFile + }: { + extraArgs ? {} + , hash + , versionName ? null + , fileName ? null + , ... + }@args: let + inherit (config) url; + fileName' = defaultTo datasourceConfig.fileName args.fileName or null; + fileName = defaultTo (builtins.baseNameOf config.url) fileName'; + in { + inherit url hash versionName fileName extraArgs; + __toString = self: let + message = '' + ${self.fileName} must be downloaded manually. + Please visit ${self.url} to download manually, and add to the store: + nix-store --add-fixed sha256 ${self.fileName} + ''; + in requireFile ({ + name = self.fileName; + inherit (self) url hash; + inherit message; + } // self.extraArgs); + }; + srcFetcherFor = {}: args: let + fetcher = config.get.fetcherFor args; + in fetcher.__toString fetcher; + }; + }; +} diff --git a/modules/manual/version.nix b/modules/manual/version.nix new file mode 100644 index 0000000..0abbd6b --- /dev/null +++ b/modules/manual/version.nix @@ -0,0 +1,15 @@ +{ datasourceConfig, lib, ... }: let + inherit (lib.attrsets) mapAttrs; + inherit (lib.modules) mkDefault mkIf; + inherit (lib.trivial) defaultTo; + cfg = defaultTo { + enable = false; + } datasourceConfig.remote.manual or null; + get = mapAttrs (_: mkDefault) { + inherit (cfg.get) fetcherFor srcFetcherFor; + }; +in { + config = { + get = mkIf cfg.enable get; + }; +} diff --git a/modules/sources/datasources.nix b/modules/sources/datasources.nix new file mode 100644 index 0000000..4790e01 --- /dev/null +++ b/modules/sources/datasources.nix @@ -0,0 +1,34 @@ +{ datasourceModules, config, lib, ... }: let + inherit (lib.modules) mkOptionDefault; + inherit (lib.options) mkOption; + inherit (lib) types; +in { + imports = [ + datasourceModules.generic.specialargs + ]; + options = { + datasources = { + markers = mkOption { + type = types.attrsOf (config.special.submoduleType [ + datasourceModules.datasource.default + ]); + default = {}; + }; + pathing = mkOption { + type = types.attrsOf (config.special.submoduleType [ + datasourceModules.datasource.default + ]); + default = {}; + }; + timers = mkOption { + type = types.attrsOf (config.special.submoduleType [ + datasourceModules.datasource.default + ]); + default = {}; + }; + }; + }; + config.special.args = { + sourcesConfig = mkOptionDefault config; + }; +} diff --git a/modules/sources/output/settings.nix b/modules/sources/output/settings.nix new file mode 100644 index 0000000..8b5890f --- /dev/null +++ b/modules/sources/output/settings.nix @@ -0,0 +1,64 @@ +{ inputs, config, lib, ... }: let + inherit (lib.attrsets) mapAttrs attrValues; + inherit (lib.lists) sort; + inherit (lib.modules) mkIf; + inherit (lib.options) mkOption; + inherit (lib) types; + cfg = config.output; + formats = import (inputs.nixpkgs + "/pkgs/pkgs-lib/formats.nix") { + inherit lib; + pkgs = { + }; + }; + format = formats.toml {}; + outputModule = { ... }: { + freeformType = format.type; + options = { + type = mkOption { + type = types.enum [ "GitHub" "Direct" ]; + }; + #description = mkOption {}; + }; + }; + mkDatasourceOutputs = datasources: let + datasources'ordered = sort (a: b: a.output.sortPrio < b.output.sortPrio) (attrValues datasources); + in map mkDatasourceOutput datasources'ordered; + mkDatasourceOutput = ds: mkIf ds.output.enable ds.output.settings; + settings = { + Markers = cfg.settings.markers; + Pathing = cfg.settings.pathing; + Timers = cfg.settings.timers; + } // removeAttrs cfg.settings [ "markers" "pathing" "timers" ]; +in { + options.output = { + settings = { + markers = mkOption { + type = types.listOf (types.submodule [ + outputModule + ]); + default = {}; + }; + pathing = mkOption { + type = types.listOf (types.submodule [ + outputModule + ]); + default = {}; + }; + timers = mkOption { + type = types.listOf (types.submodule [ + outputModule + ]); + default = {}; + }; + }; + get.file = mkOption { + type = types.unspecified; + }; + }; + config.output = { + settings = mapAttrs (_: mkDatasourceOutputs) { + inherit (config.datasources) markers pathing timers; + }; + get.file = { formats }: (formats.toml {}).generate "sources.toml" settings; + }; +} diff --git a/modules/specialargs.nix b/modules/specialargs.nix new file mode 100644 index 0000000..f934c59 --- /dev/null +++ b/modules/specialargs.nix @@ -0,0 +1,60 @@ +{ config, lib, specialArgs, ... }: let + inherit (lib.attrsets) optionalAttrs; + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.modules) mkOptionDefault; + inherit (lib.trivial) isFunction; + inherit (lib.lists) toList optionals; + inherit (lib) types; + cfg = config.special; + submoduleType = args: let + shorthand = (! builtins.isAttrs args) || isFunction args; + modules' = if shorthand + then toList args + else toList args.modules or []; + modules = modules' ++ optionals cfg."inherit".enable cfg."inherit".include; + specialArgs' = config.special.specialArgs // optionalAttrs (!shorthand) args.specialArgs or {}; + args' = optionalAttrs (!shorthand) args // { + inherit modules; + specialArgs = specialArgs'; + shorthandOnlyDefinesConfig = shorthand || args.shorthandOnlyDefinesConfig or true; + }; + in types.submoduleWith args'; +in { + options = { + special = { + "inherit" = { + enable = mkEnableOption "inherit specialArgs" // { + default = true; + }; + includeArgs = mkOption { + type = types.deferredModule; + default = { ... }: { + #config.__module.args.specialArgs = cfg.specialArgs; + #config.special.args = mapAttrs (_: mkOptionDefault cfg.specialArgs) + }; + }; + include = mkOption { + type = types.listOf types.deferredModule; + default = [ ./specialargs.nix cfg."inherit".includeArgs ]; + }; + }; + args = mkOption { + type = types.lazyAttrsOf types.unspecified; + default = {}; + }; + specialArgs = mkOption { + type = types.lazyAttrsOf types.unspecified; + readOnly = true; + }; + submoduleType = mkOption { + type = types.unspecified; + default = submoduleType; + }; + }; + }; + config = { + special = { + specialArgs = mkOptionDefault (specialArgs // cfg.args); + }; + }; +} diff --git a/modules/version.nix b/modules/version.nix new file mode 100644 index 0000000..f6683c7 --- /dev/null +++ b/modules/version.nix @@ -0,0 +1,57 @@ +{ config, datasourceConfig, name, lib, ... }: let + inherit (lib.attrsets) filterAttrs mapAttrs; + inherit (lib.customisation) callPackageWith; + inherit (lib.modules) mkOptionDefault; + inherit (lib.options) mkOption; + inherit (lib.trivial) defaultTo functionArgs id; + inherit (lib) types; +in { + options = { + versionName = mkOption { + type = types.str; + default = name; + }; + hash = mkOption { + type = types.nullOr types.str; + default = null; + }; + fileName = mkOption { + type = types.nullOr types.str; + default = null; + }; + fetcher = { + args = mkOption { + type = types.attrsOf (types.unspecified); + default = {}; + }; + }; + get = mkOption { + type = types.lazyAttrsOf (types.unspecified); + default = {}; + }; + }; + config = { + fetcher.args = mapAttrs (_: mkOptionDefault) { + inherit (config) versionName; + fileName = defaultTo datasourceConfig.fileName config.fileName; + hash = defaultTo lib.fakeHash config.hash; + }; + get = { + urlFetcherFor = args: let + fetcherFor = config.get.fetcherFor or null; + hasFetcher = fetcherFor != null; + mkFakeArg = _: _: id; + scope = mapAttrs mkFakeArg (filterAttrs (_: default: !default) (functionArgs fetcherFor)) // { + fetchurl = builtins.fetchurl; + } // args; + callPackage = callPackageWith scope; + fetcher = callPackage fetcherFor {}; + fetcherArgs' = functionArgs fetcher; + fetcherArgs = filterAttrs (name: _: fetcherArgs' ? ${name}) config.fetcher.args; + in args: if hasFetcher then fetcher (fetcherArgs // args) else throw "remote fetcher missing for ${config.versionName}"; + urlFor = {}: args: let + url = config.get.urlFetcherFor {} args; + in url.url; + }; + }; +} diff --git a/pathing/config.nix b/pathing/config.nix new file mode 100644 index 0000000..fe6a5b2 --- /dev/null +++ b/pathing/config.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./taco/config.nix + ]; +} diff --git a/pathing/taco/config.nix b/pathing/taco/config.nix new file mode 100644 index 0000000..ae44743 --- /dev/null +++ b/pathing/taco/config.nix @@ -0,0 +1,5 @@ +_: { + imports = [ + ./sources.nix + ]; +} diff --git a/pathing/taco/derivation.nix b/pathing/taco/derivation.nix new file mode 100644 index 0000000..9f02011 --- /dev/null +++ b/pathing/taco/derivation.nix @@ -0,0 +1,32 @@ +# TODO +{ lib, unzip, fetchurl, mkDerivationNoCC }: let + inherit (lib.attrsets) attrValues mapAttrsToList; + inherit (lib.strings) concatStringsSep escapeShellArg; + sources = import ./taco.nix; + mkInstall = name: src: '' + install -d ${escapeShellArg src.name} $out/share/gw2taco/${escapeShellArg name} + ''; +in mkDerivationNoCC { + name = "gw2-taco-packs"; + srcs = attrValues sources; + + #nativeBuildInputs = [ unzip ]; + + buildPhase = '' + runHook preBuild; + true + runHook postBuild; + ''; + + installPhase = '' + runHook preInstall; + + ${concatStringsSep "\n" (mapAttrsToList mkInstall sources)} + + runHook postInstall; + ''; + + passthru = { + inherit sources; + }; +} diff --git a/pathing/taco/sources.nix b/pathing/taco/sources.nix new file mode 100644 index 0000000..14336ad --- /dev/null +++ b/pathing/taco/sources.nix @@ -0,0 +1,307 @@ +{ + config.datasources.pathing = { + tehs-trails = { + name = "Teh's Trails - Map Completion"; + fileName = "TehsTrails.taco"; + description = "A collection of xTeh.7146's marker packs."; + remote.github = { + owner = "xrandox"; + repo = "TehsTrails"; + releases.enable = true; + }; + versions."v5.2.0".hash = "sha256-uY+lolPEnR7QbcexpU9wzpy5CfVXFeQaxzLsZBp+tSo="; + output.sortPrio = 10; + }; + tehs-trails-hp = { + name = "Teh's Trails - Hero Points"; + description = "A collection of xTeh.7146's marker packs. This pack contains trails for speed-completing Hero Points either solo or in small groups."; + fileName = "TehsTrails-HeroPoints.taco"; + remote.github = { + owner = "xrandox"; + repo = "TehsTrails-HeroPoints"; + releases.enable = true; + }; + versions."v1.0".hash = "sha256-hbdUuFNlr+5FFQG4wqQhm1/JMJ/CQP34mE9VR0Ztafg="; + output.sortPrio = 10; + }; + turtlepoint = { + name = "TurtlePoint"; + fileName = "TurtlePoint.taco"; + remote.github = { + owner = "AsherGlick"; + repo = "TurtlePoint"; + releases.enable = true; + }; + versions = { + "1.0".hash = "sha256-HmjH8BMbFtkidxpfwYA9rO6mA7hnv31qbMQXK9RywWY="; + "2.0".hash = null; + }; + }; + moar = { + name = "MOAR Marker Pack [BETA]"; + url = "https://www.moarloot.com/markers"; + fileName = "moar.taco"; + remote.direct.url = "https://moar-loot.web.app/releases/moar.taco"; + versions."2022-09-27".hash = "sha256-cf2DpX6NxCBilKZpdWOK+UkU2k+ASknE4TcycgpZAsw="; + }; + race-beetle-tracks = { + name = "RACE-Beetle-Racing-Tracks"; + fileName = "RACE_BeetleTracks.taco"; + remote.github = { + owner = "Garfried"; + repo = "RACE-Beetle-Racing-Tracks"; + releases.enable = true; + }; + versions."v1.0".hash = "sha256-WIDIkAOc8cccUVgSLlT3He5hdJOawLN6O3Co2Pj4gis="; + }; + czokalapik = { + name = "Czokalapik's Guides for GW2Taco"; + fileName = "Czokalapik-s-Guides-for-GW2Taco.taco"; + remote.github = { + owner = "czokalapik"; + repo = "Czokalapik-s-Guides-for-GW2Taco"; + releases.enable = true; + }; + versions."v1.0.0".hash = "sha256-tTaHk97mbxgf2HWcxP+4hbk+VzvQDP4BI62HOJFKqLI="; + }; + emysmarkers = { + #name = "Emythiel's GW2 Markers"; + name = "Emythiel's HoT HP Marker Pack"; + fileName = "emysmarkers.zip"; + remote.github = { + owner = "Emythiel"; + repo = "gw2-blish-markers"; + releases.enable = true; + }; + versions."v1.0.6".hash = "sha256-tO2ONztLeFIbThkXyr1z1vKwhKioSJdVFaDp3gIB+VY="; + }; + floochs-friendly = { + name = "Flooch's Friendly Collection Routes"; + fileName = "ffcr.taco"; + remote.github = { + owner = "placeholderwastakentwice"; + repo = "flooch-friendly-collection-routes"; + releases.enable = true; + }; + versions."V3".hash = "sha256-/KINq3fur93I4g8TBu0SUDvJiiBrXGdgVwrYT/xjye0="; + }; + heart-zones = { + name = "Heart Zones"; + fileName = "HeartZones.taco"; + remote.github = { + owner = "dlamkins"; + repo = "heart-zones"; + releases.enable = true; + }; + versions."3.0.0".hash = "sha256-nFo0l8iRQp38yA1WKb+Ryl4nd2kC3AeNdcaqCvqYHko="; + }; + heros-markers = { + name = "Hero's Pack"; + fileName = "Hero.Blish.Pack.zip"; + remote.github = { + owner = "QuitarHero"; + repo = "Heros-Marker-Pack"; + releases.enable = true; + }; + versions = { + "v2.7.6".hash = "sha256-AxkRx+YxMpb8/IFrGBQrYiFZHkRvokD3OimY1CzBx3c="; + "v2.7.10.2".hash = null; + }; + # TODO? some POIs may need mapid assigned, only mentioned in xml comments... + }; + heroine-darks-guides = { + name = "HeroineDark's Super Adventure Box Guide"; + fileName = "HeroineDark_SAB_Guides.taco"; + remote.github = { + owner = "HeroineDark"; + repo = "HeroineDarks-Super-Adventure-Box-Guide"; + sourceFile.path = "HeroineDark SAB Guides.taco"; # the zip is committed directly to repo + releases.enable = true; # but there's also a release so... + }; + versions."v3.1.12.69".hash = "sha256-QalAd/Ct94DgeWaJHlHYqwB7GOjz+JFiCNpIDGXiKws="; + }; + japyx-trails = { + name = "JapyxTrails"; + fileName = "JapyxTrails.taco"; + remote.github = { + owner = "OlivierCharton"; + repo = "JapyxTrails"; + releases.enable = true; + }; + versions."1.5".hash = "sha256-AGtYxIepDVau3j8PLWnF2vzVvGBIwHZz8fqtyUoQIsg="; + }; + lady-elyssa = { + name = "Lady Elyssa's Guides"; + fileName = "LadyElyssa.taco"; + remote.github = { + owner = "LadyElyssa"; + repo = "LadyElyssaTacoTrails"; + releases.enable = true; + }; + versions = { + "v20.5.1".hash = "sha256-kNqfXQxYECwdrFOcY6xZbPKhuMn/22Xnmf2P3nrMuIY="; + "v21.6".hash = null; + }; + }; + masmer-fractal-skips = { + name = "Mesmer Fractal Skips"; + fileName = "MesmerFractalSkips.taco"; + remote.github = { + owner = "Kaedalus"; + repo = "Mesmer-Fractal-Skips"; + releases.enable = true; + }; + versions."v1.0.2".hash = "sha256-s4sye9rL8C28kRAJXClaahMPVU009s/1UDogjDQlQeA="; + }; + metal-marker-myriad = { + name = "Metal Marker Myriad"; + fileName = "Metal-Marker-Myriad.taco"; + remote.github = { + owner = "Metallis"; + repo = "Metal-Marker-Myriad"; + releases.enable = true; + }; + versions = { + "v10.2.1".hash = "sha256-UtaHxBT5M7J8D4BxV/REfJhfKfv3A7j9ctd6vMWLGfE="; + "v11.0".hash = null; + }; + # TODO: fix inconsistent casing: + }; + nekres-hoard-lost-forgotten = { + name = "Nekres' Hoard of Lost 'n Forgotten Markers"; + fileName = "Nekres.Markers.taco"; + remote.github = { + owner = "agaertner"; + repo = "bhud-markers"; + releases.enable = true; + }; + versions."v0.1.4".hash = "sha256-DWusttMHOYWycJ9glsz0QrbbNBoUCiwG1/bR44gwImE="; + }; + nexploration = { + name = "Nexploration"; + fileName = "Nexploration.taco"; + remote.github = { + owner = "Nexrym"; + repo = "Nexploration"; + releases.enable = true; + }; + versions."v0.9.0".hash = "sha256-SVh4fKJRsYBFTH/xKdwP94mkCiiG3vYQbF9R2UA6xq4="; + }; + only-fish = { + name = "Only Fish"; + fileName = "Only-Fish.taco"; + remote.github = { + owner = "Metallis"; + repo = "Only-Fish-Marker-Pack"; + releases.enable = true; + }; + versions."v1.13".hash = "sha256-Vhb+B3h46Yd+ZR/Hx1fT2sSBlaq3vNtKp/18hePiTk8="; + }; + pewpews = { + name = "Pewpew's Power Paths"; + fileName = "Pewpews_Power_Paths.taco"; + remote.github = { + owner = "Girbilcannon"; + repo = "Pewpews-Power-Paths"; + releases.enable = true; + }; + versions = { + "v1.2.0".hash = "sha256-LczoEqIdHLZ+O+pp5XSX6VGdv9PicyFP2v8RSugkdSk="; + "v2.0.1".hash = null; + }; + }; + reactif-en = { + name = "ReActif (EN)"; + fileName = "GW2 TacO ReActif EN External.taco"; + url = "https://web.archive.org/web/20241204004932/https://www.heinze.fr/taco/?lang=en"; + remote.manual.url = "https://reactif.games/taco/download.php?f=3"; + # TODO? unknown attrs: resetoffset, hascountdown + versions = { + /* corrupt :< + "20220928" = { + url = "https://web.archive.org/web/20220928161858/https://reactif.games/taco/download.php?f=3"; + hash = ""; + };*/ + "2024-12-22".hash = "sha256-KL+NaJ10cuTCwqzkxvzF0OwpLPEAxGv7nbh2VlCBt4g="; + }; + output.sortPrio = 10; + }; + reactif-fr = { + name = "ReActif (FR)"; + fileName = "GW2 TacO ReActif FR Externe.taco"; + url = "https://web.archive.org/web/20250216050634/https://www.heinze.fr/taco/"; + remote.manual.url = "https://www.heinze.fr/taco/download.php?f=6"; + versions = { + /* corrupt :< + "20231204" = { + url = "https://web.archive.org/web/20231204223135/https://reactif.games/taco/download.php?f=6"; + hash = "sha256-eqO8/NfSDAhMeGV/3BpKahxlhQsCOWRtREXzeI8uMPg="; + };*/ + "2020-11-30".hash = "sha256-7/DYvBiEGNW36pGMm08PsI2uQo/bPKVVRD3FHdyfbak="; + }; + }; + rediche-wvw = { + name = "Reciche's WvW Siege Pack"; + fileName = "RedicheWvwPack.taco"; + remote.github = { + owner = "rediche"; + repo = "rediche-wvw-pack"; + releases.enable = true; + }; + versions."v1.0.8".hash = "sha256-pSkGGxorwzUd7rTSCaiQyH7JD5vU+t16jMOpyCZto0g="; + # TODO: Attribute 'type' is redefined: `type="rsp.ebg.off.catapults" type="rsp.ebg.off.catapults"` + }; + tekkits-aio = { + name = "Tekkit's All-In-One"; + fileName = "tw_ALL_IN_ONE.taco"; + remote.direct = { + #url = "https://www.tekkitsworkshop.net/download?download=1:tw-all-in-one"; + url = "https://www.tekkitsworkshop.net/downloads/tw_ALL_IN_ONE.taco"; + }; + versions."2025-08-27" = { + #version = "7e11b1dbef7f616cba3957b766a16578"? + hash = "sha256-bHpKeBBIr8F4BNO2sAaaCloQ5I5N7CFNZ0o059Iba2M="; + }; + output.sortPrio = 10; + }; + tryhard = { + name = "The Tryhard Marker Pack"; + fileName = "Deroirs Tryhard Marker Pack.zip"; + remote.manual.url = "https://drive.google.com/file/d/15Eqex_HIO3B0Aga4qWL8kLc1vlVEIJ8e/view"; + versions."2018-11-19".hash = "sha256-XFD4zU4ZM6IcxWPPOx1C3u0o8T5n9aQZC2bTtWxV604"; + }; + tyria-drft = { + name = "Tyria DRFT"; + fileName = "DRFT_Main.taco"; + remote.github = { + owner = "n1nj44r91"; + repo = "Tyria-Drift-DRFT-GW2-TacO-Racetracks"; + releases.enable = true; + }; + versions."v3.1".hash = "sha256-6fyn4smjQ9GukH4oKLu58QRVh1nCOQW8JIuCyww+lK8="; + }; + twisted-castle = { + name = "Twisted Castle"; + fileName = "TwistedCastle.taco"; + remote.github = { + owner = "SZG5"; + repo = "gw2-twisted-castle"; + releases.enable = true; + }; + versions."0.4".hash = "sha256-TPboDqTPtX2Rq77Yi6SR6NoTbHYEso0kd5MZOU4ljCs="; + }; + zippy-ziplines = { + name = "Zippy Ziplines"; + fileName = "Zippy.taco"; + remote.github = { + owner = "Girbilcannon"; + repo = "zippy"; + releases.enable = true; + }; + versions = { + "Zippy1_8_0".hash = "sha256-Q2t3oCBE6/rRPx158//Ye5t62/i4XwuqEyVnBkktQsM="; + "Zippy2_0_0".hash = null; + }; + }; + }; +} diff --git a/timers/config.nix b/timers/config.nix new file mode 100644 index 0000000..32be57a --- /dev/null +++ b/timers/config.nix @@ -0,0 +1,26 @@ +{ + config.datasources.timers = { + hero-timers = { + name = "Hero's Timers"; + fileName = "Hero.Timer.Pack.zip"; + description = "These are timers by QuitarHero created for Charr's Timer Module."; + remote.github = { + owner = "QuitarHero"; + repo = "Hero-Timers"; + releases.enable = true; + }; + versions."v1.8.4".hash = null; + }; + sabetha-timers = { + name = "Sabetha Timers"; + fileName = "Sabetha-Timers"; + description = "This edits the QuitarHero/Hero-Timers Sabetha timers to add the Commander's Markers details back into them, while retaining cardinal directions provided."; + remote.github = { + owner = "kittywitch"; + repo = "Sabetha-Timers"; + archive.enable = true; + }; + versions."0.0.1".hash = null; + }; + }; +}