feat: compatibility info display in View Mod screen. log to ficsit-cli.log by default (#33)

* fix: log by default (ficsit-cli.log in CWD)

* chore: update readme with info on code generation

* chore: regenerate docs for default log file location

* feat: compatibility info state and note display. wip: keybind to switch view modes not working

* fix: move render code out to a function, but it still isn't quite working yet

* feat: display mod reference below mod name

* Fix compat toggle with

* Show scroll up/down on quick help

* chore: fix merge conflict

* chore: run go install mvdan.cc/gofumpt@latest; gofumpt -l -w .

* chore: run gci.exe write --skip-generated -s standard -s default -s 'prefix(github.com/satisfactorymodding/ficsit-cli)' -s blank -s dot .

* chore: update readme linting info and run golangci-lint --version

* fix: log file is defaulted to empty again

* fix(#33): update render to return just string

* fix(#33): renderModInfo returns only string

* fix(#33): reollback func namechange

* refactor(#33): remove redundant viewport refresh

* refactor(#33): update is not required after setting content

* refactor(#33): remove unrequired log

* docs(#33): update documentation to latest generated

* docs(#33): update cache reference to not contain username

* docs(#33): fix local dir references too

* refactor(#33): replace vague variable with more helpful

* Add directions about using dev schema when generate command fails

* Fix issues from earlier merge conflict

---------

Co-authored-by: Jack Stupple <jack.stupple@protonmail.com>
This commit is contained in:
Rob B 2023-12-27 18:32:56 -08:00 committed by GitHub
parent 0b2bc27119
commit e313efdfec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 534 additions and 253 deletions

View file

@ -90,6 +90,18 @@ Run `ficsit help` to see a list of available commands.
* [Go 1.21](https://go.dev/doc/install) * [Go 1.21](https://go.dev/doc/install)
* IDE of Choice. Goland or VSCode suggested. * IDE of Choice. Goland or VSCode suggested.
### Code Generation
If you update any of the GraphQL queries, run this to update generated code:
```bash
(echo "y") | npx graphqurl https://api.ficsit.app/v2/query --introspect -H 'content-type: application/json' > schema.graphql
go generate -tags tools -x ./...
```
If this command fails due to a mismatched schema,
you may need to use the url `https://api.ficsit.dev/v2/query` instead.
## Building ## Building
```bash ```bash
@ -97,3 +109,23 @@ go build
``` ```
Will produce `ficsit-cli.exe` in the repo root directory. Will produce `ficsit-cli.exe` in the repo root directory.
### Linting
Install `golangci-lint` via the directions [here](https://golangci-lint.run/usage/install/#local-installation),
but make sure to install the version specified in `.github/workflows/push.yaml` instead of whatever it suggests.
Then, to run it, use:
```bash
golangci-lint run --fix
```
### Updating generated docs
The files within `./docs` are generated using cobra, use the following to update
them.
```bash
go run tools.go
```

View file

@ -40,7 +40,7 @@ func (l localDisk) Read(path string) ([]byte, error) {
} }
func (l localDisk) Write(path string, data []byte) error { func (l localDisk) Write(path string, data []byte) error {
return os.WriteFile(path, data, 0777) //nolint return os.WriteFile(path, data, 0o777) //nolint
} }
func (l localDisk) Remove(path string) error { func (l localDisk) Remove(path string) error {
@ -48,7 +48,7 @@ func (l localDisk) Remove(path string) error {
} }
func (l localDisk) MkDir(path string) error { func (l localDisk) MkDir(path string) error {
return os.MkdirAll(path, 0777) //nolint return os.MkdirAll(path, 0o777) //nolint
} }
func (l localDisk) ReadDir(path string) ([]Entry, error) { func (l localDisk) ReadDir(path string) ([]Entry, error) {
@ -68,5 +68,5 @@ func (l localDisk) ReadDir(path string) ([]Entry, error) {
} }
func (l localDisk) Open(path string, flag int) (io.WriteCloser, error) { func (l localDisk) Open(path string, flag int) (io.WriteCloser, error) {
return os.OpenFile(path, flag, 0777) //nolint return os.OpenFile(path, flag, 0o777) //nolint
} }

View file

@ -7,7 +7,14 @@
// words - list of words to be always considered correct // words - list of words to be always considered correct
"words": [ "words": [
"ficsit", "ficsit",
"gofumpt",
"Goland", "Goland",
"golangci",
"goquery",
"graphqurl",
"mvdan",
"pgdn",
"pgup",
"wordwrap" "wordwrap"
], ],
// flagWords - list of words to be always considered incorrect // flagWords - list of words to be always considered incorrect

View file

@ -7,13 +7,13 @@ cli mod manager for satisfactory
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
-h, --help help for ficsit -h, --help help for ficsit
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit apply [installation] ... [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit cli [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -13,12 +13,12 @@ Manage installations
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit installation add <path> [profile] [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit installation ls [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit installation remove <path> [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit installation set-profile <path> <profile> [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -13,12 +13,12 @@ Manage profiles
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit profile delete <name> [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit profile ls [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit profile mods <profile> [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit profile new <name> [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit profile rename <old> <name> [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -22,12 +22,12 @@ ficsit search [query] [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -13,12 +13,12 @@ Manage mods on SMR
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -19,12 +19,12 @@ ficsit smr upload [flags] <mod-id> <file> <changelog...>
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -17,12 +17,12 @@ ficsit version [flags]
``` ```
--api-base string URL for API (default "https://api.ficsit.app") --api-base string URL for API (default "https://api.ficsit.app")
--api-key string API key to use when sending requests --api-key string API key to use when sending requests
--cache-dir string The cache directory (default "/home/vilsol/.cache/ficsit") --cache-dir string The cache directory (default "/home/{{Username}}/.cache/ficsit")
--concurrent-downloads int Maximum number of concurrent downloads (default 5) --concurrent-downloads int Maximum number of concurrent downloads (default 5)
--dry-run Dry-run. Do not save any changes --dry-run Dry-run. Do not save any changes
--graphql-api string Path for GraphQL API (default "/v2/query") --graphql-api string Path for GraphQL API (default "/v2/query")
--installations-file string The installations file (default "installations.json") --installations-file string The installations file (default "installations.json")
--local-dir string The local directory (default "/home/vilsol/.local/share/ficsit") --local-dir string The local directory (default "/home/{{Username}}/.local/share/ficsit")
--log string The log level to output (default "info") --log string The log level to output (default "info")
--log-file string File to output logs to --log-file string File to output logs to
--offline Whether to only use local data --offline Whether to only use local data

View file

@ -11,6 +11,16 @@ query GetMod ($modId: String!) {
username username
} }
} }
compatibility {
EA {
note
state
}
EXP {
note
state
}
}
full_description full_description
source_url source_url
created_at created_at

View file

@ -46,6 +46,14 @@ type CheckVersionUploadStateStateCreateVersionResponseVersion struct {
// GetId returns CheckVersionUploadStateStateCreateVersionResponseVersion.Id, and is useful for accessing the field via an interface. // GetId returns CheckVersionUploadStateStateCreateVersionResponseVersion.Id, and is useful for accessing the field via an interface.
func (v *CheckVersionUploadStateStateCreateVersionResponseVersion) GetId() string { return v.Id } func (v *CheckVersionUploadStateStateCreateVersionResponseVersion) GetId() string { return v.Id }
type CompatibilityState string
const (
CompatibilityStateWorks CompatibilityState = "Works"
CompatibilityStateDamaged CompatibilityState = "Damaged"
CompatibilityStateBroken CompatibilityState = "Broken"
)
// CreateVersionResponse is returned by CreateVersion on success. // CreateVersionResponse is returned by CreateVersion on success.
type CreateVersionResponse struct { type CreateVersionResponse struct {
VersionID string `json:"versionID"` VersionID string `json:"versionID"`
@ -70,6 +78,7 @@ type GetModMod struct {
Views int `json:"views"` Views int `json:"views"`
Downloads int `json:"downloads"` Downloads int `json:"downloads"`
Authors []GetModModAuthorsUserMod `json:"authors"` Authors []GetModModAuthorsUserMod `json:"authors"`
Compatibility GetModModCompatibilityCompatibilityInfo `json:"compatibility"`
Full_description string `json:"full_description"` Full_description string `json:"full_description"`
Source_url string `json:"source_url"` Source_url string `json:"source_url"`
Created_at time.Time `json:"-"` Created_at time.Time `json:"-"`
@ -93,6 +102,11 @@ func (v *GetModMod) GetDownloads() int { return v.Downloads }
// GetAuthors returns GetModMod.Authors, and is useful for accessing the field via an interface. // GetAuthors returns GetModMod.Authors, and is useful for accessing the field via an interface.
func (v *GetModMod) GetAuthors() []GetModModAuthorsUserMod { return v.Authors } func (v *GetModMod) GetAuthors() []GetModModAuthorsUserMod { return v.Authors }
// GetCompatibility returns GetModMod.Compatibility, and is useful for accessing the field via an interface.
func (v *GetModMod) GetCompatibility() GetModModCompatibilityCompatibilityInfo {
return v.Compatibility
}
// GetFull_description returns GetModMod.Full_description, and is useful for accessing the field via an interface. // GetFull_description returns GetModMod.Full_description, and is useful for accessing the field via an interface.
func (v *GetModMod) GetFull_description() string { return v.Full_description } func (v *GetModMod) GetFull_description() string { return v.Full_description }
@ -128,7 +142,7 @@ func (v *GetModMod) UnmarshalJSON(b []byte) error {
src, dst) src, dst)
if err != nil { if err != nil {
return fmt.Errorf( return fmt.Errorf(
"Unable to unmarshal GetModMod.Created_at: %w", err) "unable to unmarshal GetModMod.Created_at: %w", err)
} }
} }
} }
@ -148,6 +162,8 @@ type __premarshalGetModMod struct {
Authors []GetModModAuthorsUserMod `json:"authors"` Authors []GetModModAuthorsUserMod `json:"authors"`
Compatibility GetModModCompatibilityCompatibilityInfo `json:"compatibility"`
Full_description string `json:"full_description"` Full_description string `json:"full_description"`
Source_url string `json:"source_url"` Source_url string `json:"source_url"`
@ -172,6 +188,7 @@ func (v *GetModMod) __premarshalJSON() (*__premarshalGetModMod, error) {
retval.Views = v.Views retval.Views = v.Views
retval.Downloads = v.Downloads retval.Downloads = v.Downloads
retval.Authors = v.Authors retval.Authors = v.Authors
retval.Compatibility = v.Compatibility
retval.Full_description = v.Full_description retval.Full_description = v.Full_description
retval.Source_url = v.Source_url retval.Source_url = v.Source_url
{ {
@ -183,7 +200,7 @@ func (v *GetModMod) __premarshalJSON() (*__premarshalGetModMod, error) {
&src) &src)
if err != nil { if err != nil {
return nil, fmt.Errorf( return nil, fmt.Errorf(
"Unable to marshal GetModMod.Created_at: %w", err) "unable to marshal GetModMod.Created_at: %w", err)
} }
} }
return &retval, nil return &retval, nil
@ -209,6 +226,50 @@ type GetModModAuthorsUserModUser struct {
// GetUsername returns GetModModAuthorsUserModUser.Username, and is useful for accessing the field via an interface. // GetUsername returns GetModModAuthorsUserModUser.Username, and is useful for accessing the field via an interface.
func (v *GetModModAuthorsUserModUser) GetUsername() string { return v.Username } func (v *GetModModAuthorsUserModUser) GetUsername() string { return v.Username }
// GetModModCompatibilityCompatibilityInfo includes the requested fields of the GraphQL type CompatibilityInfo.
type GetModModCompatibilityCompatibilityInfo struct {
EA GetModModCompatibilityCompatibilityInfoEACompatibility `json:"EA"`
EXP GetModModCompatibilityCompatibilityInfoEXPCompatibility `json:"EXP"`
}
// GetEA returns GetModModCompatibilityCompatibilityInfo.EA, and is useful for accessing the field via an interface.
func (v *GetModModCompatibilityCompatibilityInfo) GetEA() GetModModCompatibilityCompatibilityInfoEACompatibility {
return v.EA
}
// GetEXP returns GetModModCompatibilityCompatibilityInfo.EXP, and is useful for accessing the field via an interface.
func (v *GetModModCompatibilityCompatibilityInfo) GetEXP() GetModModCompatibilityCompatibilityInfoEXPCompatibility {
return v.EXP
}
// GetModModCompatibilityCompatibilityInfoEACompatibility includes the requested fields of the GraphQL type Compatibility.
type GetModModCompatibilityCompatibilityInfoEACompatibility struct {
Note string `json:"note"`
State CompatibilityState `json:"state"`
}
// GetNote returns GetModModCompatibilityCompatibilityInfoEACompatibility.Note, and is useful for accessing the field via an interface.
func (v *GetModModCompatibilityCompatibilityInfoEACompatibility) GetNote() string { return v.Note }
// GetState returns GetModModCompatibilityCompatibilityInfoEACompatibility.State, and is useful for accessing the field via an interface.
func (v *GetModModCompatibilityCompatibilityInfoEACompatibility) GetState() CompatibilityState {
return v.State
}
// GetModModCompatibilityCompatibilityInfoEXPCompatibility includes the requested fields of the GraphQL type Compatibility.
type GetModModCompatibilityCompatibilityInfoEXPCompatibility struct {
Note string `json:"note"`
State CompatibilityState `json:"state"`
}
// GetNote returns GetModModCompatibilityCompatibilityInfoEXPCompatibility.Note, and is useful for accessing the field via an interface.
func (v *GetModModCompatibilityCompatibilityInfoEXPCompatibility) GetNote() string { return v.Note }
// GetState returns GetModModCompatibilityCompatibilityInfoEXPCompatibility.State, and is useful for accessing the field via an interface.
func (v *GetModModCompatibilityCompatibilityInfoEXPCompatibility) GetState() CompatibilityState {
return v.State
}
// GetModNameMod includes the requested fields of the GraphQL type Mod. // GetModNameMod includes the requested fields of the GraphQL type Mod.
type GetModNameMod struct { type GetModNameMod struct {
Id string `json:"id"` Id string `json:"id"`
@ -245,51 +306,51 @@ type ModFields string
const ( const (
ModFieldsCreatedAt ModFields = "created_at" ModFieldsCreatedAt ModFields = "created_at"
ModFieldsUpdatedAt ModFields = "updated_at"
ModFieldsName ModFields = "name"
ModFieldsViews ModFields = "views"
ModFieldsDownloads ModFields = "downloads" ModFieldsDownloads ModFields = "downloads"
ModFieldsHotness ModFields = "hotness" ModFieldsHotness ModFields = "hotness"
ModFieldsLastVersionDate ModFields = "last_version_date"
ModFieldsName ModFields = "name"
ModFieldsPopularity ModFields = "popularity" ModFieldsPopularity ModFields = "popularity"
ModFieldsLastVersionDate ModFields = "last_version_date"
ModFieldsSearch ModFields = "search" ModFieldsSearch ModFields = "search"
ModFieldsUpdatedAt ModFields = "updated_at"
ModFieldsViews ModFields = "views"
) )
type ModFilter struct { type ModFilter struct {
Hidden bool `json:"hidden,omitempty"`
Ids []string `json:"ids,omitempty"`
Limit int `json:"limit,omitempty"` Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"` Offset int `json:"offset,omitempty"`
Order Order `json:"order,omitempty"`
Order_by ModFields `json:"order_by,omitempty"` Order_by ModFields `json:"order_by,omitempty"`
References []string `json:"references,omitempty"` Order Order `json:"order,omitempty"`
Search string `json:"search,omitempty"` Search string `json:"search,omitempty"`
Ids []string `json:"ids,omitempty"`
References []string `json:"references,omitempty"`
Hidden bool `json:"hidden,omitempty"`
TagIDs []string `json:"tagIDs,omitempty"` TagIDs []string `json:"tagIDs,omitempty"`
} }
// GetHidden returns ModFilter.Hidden, and is useful for accessing the field via an interface.
func (v *ModFilter) GetHidden() bool { return v.Hidden }
// GetIds returns ModFilter.Ids, and is useful for accessing the field via an interface.
func (v *ModFilter) GetIds() []string { return v.Ids }
// GetLimit returns ModFilter.Limit, and is useful for accessing the field via an interface. // GetLimit returns ModFilter.Limit, and is useful for accessing the field via an interface.
func (v *ModFilter) GetLimit() int { return v.Limit } func (v *ModFilter) GetLimit() int { return v.Limit }
// GetOffset returns ModFilter.Offset, and is useful for accessing the field via an interface. // GetOffset returns ModFilter.Offset, and is useful for accessing the field via an interface.
func (v *ModFilter) GetOffset() int { return v.Offset } func (v *ModFilter) GetOffset() int { return v.Offset }
// GetOrder_by returns ModFilter.Order_by, and is useful for accessing the field via an interface.
func (v *ModFilter) GetOrder_by() ModFields { return v.Order_by }
// GetOrder returns ModFilter.Order, and is useful for accessing the field via an interface. // GetOrder returns ModFilter.Order, and is useful for accessing the field via an interface.
func (v *ModFilter) GetOrder() Order { return v.Order } func (v *ModFilter) GetOrder() Order { return v.Order }
// GetOrder_by returns ModFilter.Order_by, and is useful for accessing the field via an interface. // GetSearch returns ModFilter.Search, and is useful for accessing the field via an interface.
func (v *ModFilter) GetOrder_by() ModFields { return v.Order_by } func (v *ModFilter) GetSearch() string { return v.Search }
// GetIds returns ModFilter.Ids, and is useful for accessing the field via an interface.
func (v *ModFilter) GetIds() []string { return v.Ids }
// GetReferences returns ModFilter.References, and is useful for accessing the field via an interface. // GetReferences returns ModFilter.References, and is useful for accessing the field via an interface.
func (v *ModFilter) GetReferences() []string { return v.References } func (v *ModFilter) GetReferences() []string { return v.References }
// GetSearch returns ModFilter.Search, and is useful for accessing the field via an interface. // GetHidden returns ModFilter.Hidden, and is useful for accessing the field via an interface.
func (v *ModFilter) GetSearch() string { return v.Search } func (v *ModFilter) GetHidden() bool { return v.Hidden }
// GetTagIDs returns ModFilter.TagIDs, and is useful for accessing the field via an interface. // GetTagIDs returns ModFilter.TagIDs, and is useful for accessing the field via an interface.
func (v *ModFilter) GetTagIDs() []string { return v.TagIDs } func (v *ModFilter) GetTagIDs() []string { return v.TagIDs }
@ -503,7 +564,7 @@ func (v *ModsModsGetModsModsMod) UnmarshalJSON(b []byte) error {
src, dst) src, dst)
if err != nil { if err != nil {
return fmt.Errorf( return fmt.Errorf(
"Unable to unmarshal ModsModsGetModsModsMod.Last_version_date: %w", err) "unable to unmarshal ModsModsGetModsModsMod.Last_version_date: %w", err)
} }
} }
} }
@ -516,7 +577,7 @@ func (v *ModsModsGetModsModsMod) UnmarshalJSON(b []byte) error {
src, dst) src, dst)
if err != nil { if err != nil {
return fmt.Errorf( return fmt.Errorf(
"Unable to unmarshal ModsModsGetModsModsMod.Created_at: %w", err) "unable to unmarshal ModsModsGetModsModsMod.Created_at: %w", err)
} }
} }
} }
@ -566,7 +627,7 @@ func (v *ModsModsGetModsModsMod) __premarshalJSON() (*__premarshalModsModsGetMod
&src) &src)
if err != nil { if err != nil {
return nil, fmt.Errorf( return nil, fmt.Errorf(
"Unable to marshal ModsModsGetModsModsMod.Last_version_date: %w", err) "unable to marshal ModsModsGetModsModsMod.Last_version_date: %w", err)
} }
} }
{ {
@ -578,7 +639,7 @@ func (v *ModsModsGetModsModsMod) __premarshalJSON() (*__premarshalModsModsGetMod
&src) &src)
if err != nil { if err != nil {
return nil, fmt.Errorf( return nil, fmt.Errorf(
"Unable to marshal ModsModsGetModsModsMod.Created_at: %w", err) "unable to marshal ModsModsGetModsModsMod.Created_at: %w", err)
} }
} }
retval.Views = v.Views retval.Views = v.Views
@ -683,46 +744,46 @@ func (v *SMLVersionsSmlVersionsGetSMLVersionsSml_versionsSMLVersionTargetsSMLVer
type TargetName string type TargetName string
const ( const (
TargetNameLinuxserver TargetName = "LinuxServer"
TargetNameWindows TargetName = "Windows" TargetNameWindows TargetName = "Windows"
TargetNameWindowsserver TargetName = "WindowsServer" TargetNameWindowsserver TargetName = "WindowsServer"
TargetNameLinuxserver TargetName = "LinuxServer"
) )
type VersionFields string type VersionFields string
const ( const (
VersionFieldsCreatedAt VersionFields = "created_at" VersionFieldsCreatedAt VersionFields = "created_at"
VersionFieldsDownloads VersionFields = "downloads"
VersionFieldsUpdatedAt VersionFields = "updated_at" VersionFieldsUpdatedAt VersionFields = "updated_at"
VersionFieldsDownloads VersionFields = "downloads"
) )
type VersionFilter struct { type VersionFilter struct {
Ids []string `json:"ids,omitempty"`
Limit int `json:"limit,omitempty"` Limit int `json:"limit,omitempty"`
Offset int `json:"offset,omitempty"` Offset int `json:"offset,omitempty"`
Order Order `json:"order,omitempty"`
Order_by VersionFields `json:"order_by,omitempty"` Order_by VersionFields `json:"order_by,omitempty"`
Order Order `json:"order,omitempty"`
Search string `json:"search,omitempty"` Search string `json:"search,omitempty"`
Ids []string `json:"ids,omitempty"`
} }
// GetIds returns VersionFilter.Ids, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetIds() []string { return v.Ids }
// GetLimit returns VersionFilter.Limit, and is useful for accessing the field via an interface. // GetLimit returns VersionFilter.Limit, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetLimit() int { return v.Limit } func (v *VersionFilter) GetLimit() int { return v.Limit }
// GetOffset returns VersionFilter.Offset, and is useful for accessing the field via an interface. // GetOffset returns VersionFilter.Offset, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetOffset() int { return v.Offset } func (v *VersionFilter) GetOffset() int { return v.Offset }
// GetOrder returns VersionFilter.Order, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetOrder() Order { return v.Order }
// GetOrder_by returns VersionFilter.Order_by, and is useful for accessing the field via an interface. // GetOrder_by returns VersionFilter.Order_by, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetOrder_by() VersionFields { return v.Order_by } func (v *VersionFilter) GetOrder_by() VersionFields { return v.Order_by }
// GetOrder returns VersionFilter.Order, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetOrder() Order { return v.Order }
// GetSearch returns VersionFilter.Search, and is useful for accessing the field via an interface. // GetSearch returns VersionFilter.Search, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetSearch() string { return v.Search } func (v *VersionFilter) GetSearch() string { return v.Search }
// GetIds returns VersionFilter.Ids, and is useful for accessing the field via an interface.
func (v *VersionFilter) GetIds() []string { return v.Ids }
// VersionMod includes the requested fields of the GraphQL type Mod. // VersionMod includes the requested fields of the GraphQL type Mod.
type VersionMod struct { type VersionMod struct {
Id string `json:"id"` Id string `json:"id"`
@ -863,15 +924,8 @@ func (v *__VersionInput) GetModId() string { return v.ModId }
// GetVersion returns __VersionInput.Version, and is useful for accessing the field via an interface. // GetVersion returns __VersionInput.Version, and is useful for accessing the field via an interface.
func (v *__VersionInput) GetVersion() string { return v.Version } func (v *__VersionInput) GetVersion() string { return v.Version }
func CheckVersionUploadState( // The query or mutation executed by CheckVersionUploadState.
ctx context.Context, const CheckVersionUploadState_Operation = `
client graphql.Client,
modId string,
versionId string,
) (*CheckVersionUploadStateResponse, error) {
req := &graphql.Request{
OpName: "CheckVersionUploadState",
Query: `
query CheckVersionUploadState ($modId: ModID!, $versionId: VersionID!) { query CheckVersionUploadState ($modId: ModID!, $versionId: VersionID!) {
state: checkVersionUploadState(modId: $modId, versionId: $versionId) { state: checkVersionUploadState(modId: $modId, versionId: $versionId) {
auto_approved auto_approved
@ -880,7 +934,17 @@ query CheckVersionUploadState ($modId: ModID!, $versionId: VersionID!) {
} }
} }
} }
`, `
func CheckVersionUploadState(
ctx context.Context,
client graphql.Client,
modId string,
versionId string,
) (*CheckVersionUploadStateResponse, error) {
req := &graphql.Request{
OpName: "CheckVersionUploadState",
Query: CheckVersionUploadState_Operation,
Variables: &__CheckVersionUploadStateInput{ Variables: &__CheckVersionUploadStateInput{
ModId: modId, ModId: modId,
VersionId: versionId, VersionId: versionId,
@ -900,6 +964,13 @@ query CheckVersionUploadState ($modId: ModID!, $versionId: VersionID!) {
return &data, err return &data, err
} }
// The query or mutation executed by CreateVersion.
const CreateVersion_Operation = `
mutation CreateVersion ($modId: ModID!) {
versionID: createVersion(modId: $modId)
}
`
func CreateVersion( func CreateVersion(
ctx context.Context, ctx context.Context,
client graphql.Client, client graphql.Client,
@ -907,11 +978,7 @@ func CreateVersion(
) (*CreateVersionResponse, error) { ) (*CreateVersionResponse, error) {
req := &graphql.Request{ req := &graphql.Request{
OpName: "CreateVersion", OpName: "CreateVersion",
Query: ` Query: CreateVersion_Operation,
mutation CreateVersion ($modId: ModID!) {
versionID: createVersion(modId: $modId)
}
`,
Variables: &__CreateVersionInput{ Variables: &__CreateVersionInput{
ModId: modId, ModId: modId,
}, },
@ -930,6 +997,13 @@ mutation CreateVersion ($modId: ModID!) {
return &data, err return &data, err
} }
// The query or mutation executed by FinalizeCreateVersion.
const FinalizeCreateVersion_Operation = `
mutation FinalizeCreateVersion ($modId: ModID!, $versionId: VersionID!, $version: NewVersion!) {
success: finalizeCreateVersion(modId: $modId, versionId: $versionId, version: $version)
}
`
func FinalizeCreateVersion( func FinalizeCreateVersion(
ctx context.Context, ctx context.Context,
client graphql.Client, client graphql.Client,
@ -939,11 +1013,7 @@ func FinalizeCreateVersion(
) (*FinalizeCreateVersionResponse, error) { ) (*FinalizeCreateVersionResponse, error) {
req := &graphql.Request{ req := &graphql.Request{
OpName: "FinalizeCreateVersion", OpName: "FinalizeCreateVersion",
Query: ` Query: FinalizeCreateVersion_Operation,
mutation FinalizeCreateVersion ($modId: ModID!, $versionId: VersionID!, $version: NewVersion!) {
success: finalizeCreateVersion(modId: $modId, versionId: $versionId, version: $version)
}
`,
Variables: &__FinalizeCreateVersionInput{ Variables: &__FinalizeCreateVersionInput{
ModId: modId, ModId: modId,
VersionId: versionId, VersionId: versionId,
@ -964,14 +1034,8 @@ mutation FinalizeCreateVersion ($modId: ModID!, $versionId: VersionID!, $version
return &data, err return &data, err
} }
func GetMod( // The query or mutation executed by GetMod.
ctx context.Context, const GetMod_Operation = `
client graphql.Client,
modId string,
) (*GetModResponse, error) {
req := &graphql.Request{
OpName: "GetMod",
Query: `
query GetMod ($modId: String!) { query GetMod ($modId: String!) {
mod: getModByIdOrReference(modIdOrReference: $modId) { mod: getModByIdOrReference(modIdOrReference: $modId) {
id id
@ -985,12 +1049,31 @@ query GetMod ($modId: String!) {
username username
} }
} }
compatibility {
EA {
note
state
}
EXP {
note
state
}
}
full_description full_description
source_url source_url
created_at created_at
} }
} }
`, `
func GetMod(
ctx context.Context,
client graphql.Client,
modId string,
) (*GetModResponse, error) {
req := &graphql.Request{
OpName: "GetMod",
Query: GetMod_Operation,
Variables: &__GetModInput{ Variables: &__GetModInput{
ModId: modId, ModId: modId,
}, },
@ -1009,14 +1092,8 @@ query GetMod ($modId: String!) {
return &data, err return &data, err
} }
func GetModName( // The query or mutation executed by GetModName.
ctx context.Context, const GetModName_Operation = `
client graphql.Client,
modId string,
) (*GetModNameResponse, error) {
req := &graphql.Request{
OpName: "GetModName",
Query: `
query GetModName ($modId: String!) { query GetModName ($modId: String!) {
mod: getModByIdOrReference(modIdOrReference: $modId) { mod: getModByIdOrReference(modIdOrReference: $modId) {
id id
@ -1024,7 +1101,16 @@ query GetModName ($modId: String!) {
name name
} }
} }
`, `
func GetModName(
ctx context.Context,
client graphql.Client,
modId string,
) (*GetModNameResponse, error) {
req := &graphql.Request{
OpName: "GetModName",
Query: GetModName_Operation,
Variables: &__GetModNameInput{ Variables: &__GetModNameInput{
ModId: modId, ModId: modId,
}, },
@ -1043,15 +1129,8 @@ query GetModName ($modId: String!) {
return &data, err return &data, err
} }
func ModVersions( // The query or mutation executed by ModVersions.
ctx context.Context, const ModVersions_Operation = `
client graphql.Client,
modId string,
filter VersionFilter,
) (*ModVersionsResponse, error) {
req := &graphql.Request{
OpName: "ModVersions",
Query: `
query ModVersions ($modId: String!, $filter: VersionFilter) { query ModVersions ($modId: String!, $filter: VersionFilter) {
mod: getModByIdOrReference(modIdOrReference: $modId) { mod: getModByIdOrReference(modIdOrReference: $modId) {
id id
@ -1061,7 +1140,17 @@ query ModVersions ($modId: String!, $filter: VersionFilter) {
} }
} }
} }
`, `
func ModVersions(
ctx context.Context,
client graphql.Client,
modId string,
filter VersionFilter,
) (*ModVersionsResponse, error) {
req := &graphql.Request{
OpName: "ModVersions",
Query: ModVersions_Operation,
Variables: &__ModVersionsInput{ Variables: &__ModVersionsInput{
ModId: modId, ModId: modId,
Filter: filter, Filter: filter,
@ -1081,14 +1170,8 @@ query ModVersions ($modId: String!, $filter: VersionFilter) {
return &data, err return &data, err
} }
func ModVersionsWithDependencies( // The query or mutation executed by ModVersionsWithDependencies.
ctx context.Context, const ModVersionsWithDependencies_Operation = `
client graphql.Client,
modId string,
) (*ModVersionsWithDependenciesResponse, error) {
req := &graphql.Request{
OpName: "ModVersionsWithDependencies",
Query: `
query ModVersionsWithDependencies ($modId: String!) { query ModVersionsWithDependencies ($modId: String!) {
mod: getModByIdOrReference(modIdOrReference: $modId) { mod: getModByIdOrReference(modIdOrReference: $modId) {
id id
@ -1110,7 +1193,16 @@ query ModVersionsWithDependencies ($modId: String!) {
} }
} }
} }
`, `
func ModVersionsWithDependencies(
ctx context.Context,
client graphql.Client,
modId string,
) (*ModVersionsWithDependenciesResponse, error) {
req := &graphql.Request{
OpName: "ModVersionsWithDependencies",
Query: ModVersionsWithDependencies_Operation,
Variables: &__ModVersionsWithDependenciesInput{ Variables: &__ModVersionsWithDependenciesInput{
ModId: modId, ModId: modId,
}, },
@ -1129,14 +1221,8 @@ query ModVersionsWithDependencies ($modId: String!) {
return &data, err return &data, err
} }
func Mods( // The query or mutation executed by Mods.
ctx context.Context, const Mods_Operation = `
client graphql.Client,
filter ModFilter,
) (*ModsResponse, error) {
req := &graphql.Request{
OpName: "Mods",
Query: `
query Mods ($filter: ModFilter) { query Mods ($filter: ModFilter) {
mods: getMods(filter: $filter) { mods: getMods(filter: $filter) {
count count
@ -1153,7 +1239,16 @@ query Mods ($filter: ModFilter) {
} }
} }
} }
`, `
func Mods(
ctx context.Context,
client graphql.Client,
filter ModFilter,
) (*ModsResponse, error) {
req := &graphql.Request{
OpName: "Mods",
Query: Mods_Operation,
Variables: &__ModsInput{ Variables: &__ModsInput{
Filter: filter, Filter: filter,
}, },
@ -1172,13 +1267,8 @@ query Mods ($filter: ModFilter) {
return &data, err return &data, err
} }
func SMLVersions( // The query or mutation executed by SMLVersions.
ctx context.Context, const SMLVersions_Operation = `
client graphql.Client,
) (*SMLVersionsResponse, error) {
req := &graphql.Request{
OpName: "SMLVersions",
Query: `
query SMLVersions { query SMLVersions {
smlVersions: getSMLVersions(filter: {limit:100}) { smlVersions: getSMLVersions(filter: {limit:100}) {
count count
@ -1193,7 +1283,15 @@ query SMLVersions {
} }
} }
} }
`, `
func SMLVersions(
ctx context.Context,
client graphql.Client,
) (*SMLVersionsResponse, error) {
req := &graphql.Request{
OpName: "SMLVersions",
Query: SMLVersions_Operation,
} }
var err error var err error
@ -1209,15 +1307,8 @@ query SMLVersions {
return &data, err return &data, err
} }
func Version( // The query or mutation executed by Version.
ctx context.Context, const Version_Operation = `
client graphql.Client,
modId string,
version string,
) (*VersionResponse, error) {
req := &graphql.Request{
OpName: "Version",
Query: `
query Version ($modId: String!, $version: String!) { query Version ($modId: String!, $version: String!) {
mod: getModByIdOrReference(modIdOrReference: $modId) { mod: getModByIdOrReference(modIdOrReference: $modId) {
id id
@ -1229,7 +1320,17 @@ query Version ($modId: String!, $version: String!) {
} }
} }
} }
`, `
func Version(
ctx context.Context,
client graphql.Client,
modId string,
version string,
) (*VersionResponse, error) {
req := &graphql.Request{
OpName: "Version",
Query: Version_Operation,
Variables: &__VersionInput{ Variables: &__VersionInput{
ModId: modId, ModId: modId,
Version: version, Version: version,

View file

@ -1,5 +1,7 @@
package mods package mods
// cspell:disable
import ( import (
"context" "context"
"log/slog" "log/slog"
@ -23,12 +25,15 @@ import (
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
// cspell:enable
var _ tea.Model = (*modVersionMenu)(nil) var _ tea.Model = (*modVersionMenu)(nil)
type modInfo struct { type modInfo struct {
root components.RootModel root components.RootModel
parent tea.Model parent tea.Model
modData chan ficsit.GetModMod modData chan ficsit.GetModMod
modDataCache ficsit.GetModMod
modError chan string modError chan string
error *components.ErrorComponent error *components.ErrorComponent
help help.Model help help.Model
@ -36,6 +41,7 @@ type modInfo struct {
viewport viewport.Model viewport viewport.Model
spinner spinner.Model spinner spinner.Model
ready bool ready bool
compatViewMode bool
} }
type modInfoKeyMap struct { type modInfoKeyMap struct {
@ -47,16 +53,18 @@ type modInfoKeyMap struct {
DownPage key.Binding DownPage key.Binding
Help key.Binding Help key.Binding
Back key.Binding Back key.Binding
CompatInfo key.Binding
} }
func (k modInfoKeyMap) ShortHelp() []key.Binding { func (k modInfoKeyMap) ShortHelp() []key.Binding {
return []key.Binding{k.Help, k.Back} return []key.Binding{k.Help, k.Back, k.Up, k.Down, k.CompatInfo}
} }
func (k modInfoKeyMap) FullHelp() [][]key.Binding { func (k modInfoKeyMap) FullHelp() [][]key.Binding {
return [][]key.Binding{ return [][]key.Binding{
{k.Up, k.UpHalf, k.UpPage}, {k.Up, k.UpHalf, k.UpPage},
{k.Down, k.DownHalf, k.DownPage}, {k.Down, k.DownHalf, k.DownPage},
{k.CompatInfo},
{k.Help, k.Back}, {k.Help, k.Back},
} }
} }
@ -80,6 +88,7 @@ func NewModInfo(root components.RootModel, parent tea.Model, mod utils.Mod) tea.
DownPage: key.NewBinding(key.WithKeys("pgdn", "f"), key.WithHelp("pgdn/f", "page down")), DownPage: key.NewBinding(key.WithKeys("pgdn", "f"), key.WithHelp("pgdn/f", "page down")),
Help: key.NewBinding(key.WithKeys("?"), key.WithHelp("?", "toggle help")), Help: key.NewBinding(key.WithKeys("?"), key.WithHelp("?", "toggle help")),
Back: key.NewBinding(key.WithKeys("q"), key.WithHelp("q", "back")), Back: key.NewBinding(key.WithKeys("q"), key.WithHelp("q", "back")),
CompatInfo: key.NewBinding(key.WithKeys("i"), key.WithHelp("i", "toggle compatibility info view")),
}, },
} }
@ -144,13 +153,19 @@ func (m modInfo) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, tea.Quit return m, tea.Quit
case "?": case "?":
m.help.ShowAll = !m.help.ShowAll m.help.ShowAll = !m.help.ShowAll
newModel, cmd := m.CalculateSizes(m.root.Size()) return m.CalculateSizes(m.root.Size())
return newModel, cmd case "i":
m.compatViewMode = !m.compatViewMode
m.viewport = m.newViewport()
m.viewport.SetContent(m.renderModInfo())
return m.CalculateSizes(m.root.Size())
default: default:
break
}
var cmd tea.Cmd var cmd tea.Cmd
m.viewport, cmd = m.viewport.Update(msg) m.viewport, cmd = m.viewport.Update(msg)
return m, cmd return m, cmd
}
case tea.WindowSizeMsg: case tea.WindowSizeMsg:
return m.CalculateSizes(msg) return m.CalculateSizes(msg)
case spinner.TickMsg: case spinner.TickMsg:
@ -160,67 +175,121 @@ func (m modInfo) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case utils.TickMsg: case utils.TickMsg:
select { select {
case mod := <-m.modData: case mod := <-m.modData:
m.modDataCache = mod
m.viewport = m.newViewport()
m.viewport.SetContent(m.renderModInfo())
break
case err := <-m.modError:
errorComponent, _ := components.NewErrorComponent(err, time.Second*5)
m.error = errorComponent
break
default:
// skip
break
}
return m, utils.Ticker()
}
return m, nil
}
func (m modInfo) newViewport() viewport.Model {
bottomPadding := 2 bottomPadding := 2
if m.help.ShowAll { if m.help.ShowAll {
bottomPadding = 4 bottomPadding = 4
} }
top, right, bottom, left := lipgloss.NewStyle().Margin(m.root.Height(), 3, bottomPadding).GetMargin() top, right, bottom, left := lipgloss.NewStyle().Margin(m.root.Height(), 3, bottomPadding).GetMargin()
m.viewport = viewport.Model{Width: m.root.Size().Width - left - right, Height: m.root.Size().Height - top - bottom} return viewport.Model{Width: m.root.Size().Width - left - right, Height: m.root.Size().Height - top - bottom}
}
func (m modInfo) renderModInfo() string {
mod := m.modDataCache
title := lipgloss.NewStyle().Padding(0, 2).Render(utils.TitleStyle.Render(mod.Name)) + "\n" title := lipgloss.NewStyle().Padding(0, 2).Render(utils.TitleStyle.Render(mod.Name)) + "\n"
title += lipgloss.NewStyle().Padding(0, 3).Render("("+string(mod.Mod_reference)+")") + "\n"
sidebar := "" sidebar := ""
sidebar += utils.LabelStyle.Render("Views: ") + strconv.Itoa(mod.Views) + "\n" sidebar += utils.LabelStyle.Render("Views: ") + strconv.Itoa(mod.Views) + "\n"
sidebar += utils.LabelStyle.Render("Downloads: ") + strconv.Itoa(mod.Downloads) + "\n" sidebar += utils.LabelStyle.Render("Downloads: ") + strconv.Itoa(mod.Downloads) + "\n"
sidebar += "\n" sidebar += "\n"
sidebar += utils.LabelStyle.Render("EA Compat: ") + m.renderCompatInfo(mod.Compatibility.EA.State) + "\n"
sidebar += utils.LabelStyle.Render("EXP Compat: ") + m.renderCompatInfo(mod.Compatibility.EXP.State) + "\n"
sidebar += "\n"
sidebar += utils.LabelStyle.Render("Authors:") + "\n" sidebar += utils.LabelStyle.Render("Authors:") + "\n"
converter := md.NewConverter("", true, nil)
converter.AddRules(md.Rule{
Filter: []string{"#text"},
Replacement: func(content string, selection *goquery.Selection, options *md.Options) *string {
text := selection.Text()
return &text
},
})
for _, author := range mod.Authors { for _, author := range mod.Authors {
sidebar += "\n" sidebar += "\n"
sidebar += utils.LabelStyle.Render(author.User.Username) + " - " + author.Role sidebar += utils.LabelStyle.Render(author.User.Username) + " - " + author.Role
} }
converter := md.NewConverter("", true, nil) description := ""
converter.AddRules(md.Rule{ if m.compatViewMode {
Filter: []string{"#text"}, a := ""
Replacement: func(content string, selec *goquery.Selection, options *md.Options) *string { a += "Compatibility information is maintained by the community." + "\n"
text := selec.Text() a += "If you encounter issues with a mod, please report it on the Discord." + "\n"
return &text a += "Learn more about what compatibility states mean on ficsit.app" + "\n\n"
},
})
markdownDescription, err := converter.ConvertString(mod.Full_description) description = m.renderDescriptionText(a, converter)
description += " " + utils.TitleStyle.Render("Early Access Branch Compatibility Note") + "\n"
description += m.renderDescriptionText(mod.Compatibility.EA.Note, converter)
description += "\n\n"
description += " " + utils.TitleStyle.Render("Experimental Branch Compatibility Note") + "\n"
description += m.renderDescriptionText(mod.Compatibility.EXP.Note, converter)
} else {
description += m.renderDescriptionText(mod.Full_description, converter)
}
bottomPart := lipgloss.JoinHorizontal(lipgloss.Top, sidebar, strings.TrimSpace(description))
return lipgloss.JoinVertical(lipgloss.Left, title, bottomPart)
}
func (m modInfo) renderDescriptionText(text string, converter *md.Converter) string {
text = strings.TrimSpace(text)
if text == "" {
text = "(No notes provided)"
}
markdownDescription, err := converter.ConvertString(text)
if err != nil { if err != nil {
slog.Error("failed to convert html to markdown", slog.Any("err", err)) slog.Error("failed to convert html to markdown", slog.Any("err", err))
markdownDescription = mod.Full_description markdownDescription = text
} }
description, err := glamour.Render(markdownDescription, "dark") description, err := glamour.Render(markdownDescription, "dark")
if err != nil { if err != nil {
slog.Error("failed to render markdown", slog.Any("err", err)) slog.Error("failed to render markdown", slog.Any("err", err))
description = mod.Full_description description = text
} }
bottomPart := lipgloss.JoinHorizontal(lipgloss.Top, sidebar, strings.TrimSpace(description)) return description
}
m.viewport.SetContent(lipgloss.JoinVertical(lipgloss.Left, title, bottomPart)) func (m modInfo) renderCompatInfo(state ficsit.CompatibilityState) string {
stateText := string(state)
var cmd tea.Cmd switch state {
m.viewport, cmd = m.viewport.Update(msg) case ficsit.CompatibilityStateWorks:
return m, cmd return utils.CompatWorksStyle.Render(stateText)
case err := <-m.modError: case ficsit.CompatibilityStateDamaged:
errorComponent, cmd := components.NewErrorComponent(err, time.Second*5) return utils.CompatDamagedStyle.Render(stateText)
m.error = errorComponent case ficsit.CompatibilityStateBroken:
return m, cmd return utils.CompatBrokenStyle.Render(stateText)
default: default:
return m, utils.Ticker() return utils.CompatUntestedStyle.Render("Unknown")
} }
} }
return m, nil
}
func (m modInfo) View() string { func (m modInfo) View() string {
if m.error != nil { if m.error != nil {
helpBar := lipgloss.NewStyle().Padding(1, 2).Render(m.help.View(m.keys)) helpBar := lipgloss.NewStyle().Padding(1, 2).Render(m.help.View(m.keys))

View file

@ -12,6 +12,13 @@ var (
NonListTitleStyle = TitleStyle.Copy().MarginLeft(2).Background(lipgloss.Color("#b34100")) NonListTitleStyle = TitleStyle.Copy().MarginLeft(2).Background(lipgloss.Color("#b34100"))
) )
var (
CompatWorksStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#00b12d"))
CompatDamagedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#e69000"))
CompatBrokenStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#e60000"))
CompatUntestedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#838383"))
)
var ( var (
LogoForegroundStyles = []lipgloss.Style{ LogoForegroundStyles = []lipgloss.Style{
lipgloss.NewStyle().Foreground(lipgloss.Color("#ff5f00")).Background(lipgloss.Color("#ff5f00")), lipgloss.NewStyle().Foreground(lipgloss.Color("#ff5f00")).Background(lipgloss.Color("#ff5f00")),

View file

@ -5,25 +5,80 @@ package main
import ( import (
"os" "os"
"os/user"
"path/filepath"
"runtime"
"strings"
_ "github.com/Khan/genqlient/generate"
"github.com/spf13/cobra/doc" "github.com/spf13/cobra/doc"
"github.com/satisfactorymodding/ficsit-cli/cmd" "github.com/satisfactorymodding/ficsit-cli/cmd"
_ "github.com/Khan/genqlient/generate"
) )
//go:generate go run github.com/Khan/genqlient //go:generate go run github.com/Khan/genqlient
//go:generate go run -tags tools tools.go //go:generate go run -tags tools tools.go
func main() { func main() {
var err error
_ = os.RemoveAll("./docs/") _ = os.RemoveAll("./docs/")
if err := os.Mkdir("./docs/", 0777); err != nil { if err = os.Mkdir("./docs/", 0o777); err != nil {
panic(err) panic(err)
} }
err := doc.GenMarkdownTree(cmd.RootCmd, "./docs/") err = doc.GenMarkdownTree(cmd.RootCmd, "./docs/")
if err != nil { if err != nil {
panic(err) panic(err)
} }
// replace user dir information with generic username
baseCacheDir, err := os.UserCacheDir()
if err != nil {
panic(err)
}
var baseLocalDir string
switch runtime.GOOS {
case "windows":
baseLocalDir = os.Getenv("APPDATA")
case "linux":
baseLocalDir = filepath.Join(os.Getenv("HOME"), ".local", "share")
default:
panic("unsupported platform: " + runtime.GOOS)
}
docFiles, err := os.ReadDir("./docs/")
if err != nil {
panic(err)
}
user, err := user.Current()
if err != nil {
panic(err)
}
for _, f := range docFiles {
fPath := "./docs/" + f.Name()
oldContents, err := os.ReadFile(fPath)
if err != nil {
panic(err)
}
newContents := strings.ReplaceAll(
string(oldContents),
baseCacheDir,
strings.ReplaceAll(baseCacheDir, user.Username, "{{Username}}"),
)
newContents = strings.ReplaceAll(
newContents,
baseLocalDir,
strings.ReplaceAll(baseLocalDir, user.Username, "{{Username}}"),
)
os.WriteFile(fPath, []byte(newContents), 0o777)
}
} }