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"`
@ -64,15 +72,16 @@ func (v *FinalizeCreateVersionResponse) GetSuccess() bool { return v.Success }
// GetModMod includes the requested fields of the GraphQL type Mod. // GetModMod includes the requested fields of the GraphQL type Mod.
type GetModMod struct { type GetModMod struct {
Id string `json:"id"` Id string `json:"id"`
Mod_reference string `json:"mod_reference"` Mod_reference string `json:"mod_reference"`
Name string `json:"name"` Name string `json:"name"`
Views int `json:"views"` Views int `json:"views"`
Downloads int `json:"downloads"` Downloads int `json:"downloads"`
Authors []GetModModAuthorsUserMod `json:"authors"` Authors []GetModModAuthorsUserMod `json:"authors"`
Full_description string `json:"full_description"` Compatibility GetModModCompatibilityCompatibilityInfo `json:"compatibility"`
Source_url string `json:"source_url"` Full_description string `json:"full_description"`
Created_at time.Time `json:"-"` Source_url string `json:"source_url"`
Created_at time.Time `json:"-"`
} }
// GetId returns GetModMod.Id, and is useful for accessing the field via an interface. // GetId returns GetModMod.Id, and is useful for accessing the field via an interface.
@ -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,40 +25,46 @@ 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
modError chan string modDataCache ficsit.GetModMod
error *components.ErrorComponent modError chan string
help help.Model error *components.ErrorComponent
keys modInfoKeyMap help help.Model
viewport viewport.Model keys modInfoKeyMap
spinner spinner.Model viewport viewport.Model
ready bool spinner spinner.Model
ready bool
compatViewMode bool
} }
type modInfoKeyMap struct { type modInfoKeyMap struct {
Up key.Binding Up key.Binding
UpHalf key.Binding UpHalf key.Binding
UpPage key.Binding UpPage key.Binding
Down key.Binding Down key.Binding
DownHalf key.Binding DownHalf key.Binding
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},
} }
} }
@ -72,14 +80,15 @@ func NewModInfo(root components.RootModel, parent tea.Model, mod utils.Mod) tea.
ready: false, ready: false,
help: help.New(), help: help.New(),
keys: modInfoKeyMap{ keys: modInfoKeyMap{
Up: key.NewBinding(key.WithKeys("up", "k"), key.WithHelp("↑/k", "move up")), Up: key.NewBinding(key.WithKeys("up", "k"), key.WithHelp("↑/k", "move up")),
UpHalf: key.NewBinding(key.WithKeys("u"), key.WithHelp("u", "up half page")), UpHalf: key.NewBinding(key.WithKeys("u"), key.WithHelp("u", "up half page")),
UpPage: key.NewBinding(key.WithKeys("pgup", "b"), key.WithHelp("pgup/b", "page up")), UpPage: key.NewBinding(key.WithKeys("pgup", "b"), key.WithHelp("pgup/b", "page up")),
Down: key.NewBinding(key.WithKeys("down", "j"), key.WithHelp("↓/j", "move down")), Down: key.NewBinding(key.WithKeys("down", "j"), key.WithHelp("↓/j", "move down")),
DownHalf: key.NewBinding(key.WithKeys("d"), key.WithHelp("d", "down half page")), DownHalf: key.NewBinding(key.WithKeys("d"), key.WithHelp("d", "down half page")),
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:
var cmd tea.Cmd break
m.viewport, cmd = m.viewport.Update(msg)
return m, cmd
} }
var cmd tea.Cmd
m.viewport, cmd = m.viewport.Update(msg)
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:
bottomPadding := 2 m.modDataCache = mod
if m.help.ShowAll { m.viewport = m.newViewport()
bottomPadding = 4 m.viewport.SetContent(m.renderModInfo())
} break
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}
title := lipgloss.NewStyle().Padding(0, 2).Render(utils.TitleStyle.Render(mod.Name)) + "\n"
sidebar := ""
sidebar += utils.LabelStyle.Render("Views: ") + strconv.Itoa(mod.Views) + "\n"
sidebar += utils.LabelStyle.Render("Downloads: ") + strconv.Itoa(mod.Downloads) + "\n"
sidebar += "\n"
sidebar += utils.LabelStyle.Render("Authors:") + "\n"
for _, author := range mod.Authors {
sidebar += "\n"
sidebar += utils.LabelStyle.Render(author.User.Username) + " - " + author.Role
}
converter := md.NewConverter("", true, nil)
converter.AddRules(md.Rule{
Filter: []string{"#text"},
Replacement: func(content string, selec *goquery.Selection, options *md.Options) *string {
text := selec.Text()
return &text
},
})
markdownDescription, err := converter.ConvertString(mod.Full_description)
if err != nil {
slog.Error("failed to convert html to markdown", slog.Any("err", err))
markdownDescription = mod.Full_description
}
description, err := glamour.Render(markdownDescription, "dark")
if err != nil {
slog.Error("failed to render markdown", slog.Any("err", err))
description = mod.Full_description
}
bottomPart := lipgloss.JoinHorizontal(lipgloss.Top, sidebar, strings.TrimSpace(description))
m.viewport.SetContent(lipgloss.JoinVertical(lipgloss.Left, title, bottomPart))
var cmd tea.Cmd
m.viewport, cmd = m.viewport.Update(msg)
return m, cmd
case err := <-m.modError: case err := <-m.modError:
errorComponent, cmd := components.NewErrorComponent(err, time.Second*5) errorComponent, _ := components.NewErrorComponent(err, time.Second*5)
m.error = errorComponent m.error = errorComponent
return m, cmd break
default: default:
return m, utils.Ticker() // skip
break
} }
return m, utils.Ticker()
} }
return m, nil return m, nil
} }
func (m modInfo) newViewport() viewport.Model {
bottomPadding := 2
if m.help.ShowAll {
bottomPadding = 4
}
top, right, bottom, left := lipgloss.NewStyle().Margin(m.root.Height(), 3, bottomPadding).GetMargin()
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, 3).Render("("+string(mod.Mod_reference)+")") + "\n"
sidebar := ""
sidebar += utils.LabelStyle.Render("Views: ") + strconv.Itoa(mod.Views) + "\n"
sidebar += utils.LabelStyle.Render("Downloads: ") + strconv.Itoa(mod.Downloads) + "\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"
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 {
sidebar += "\n"
sidebar += utils.LabelStyle.Render(author.User.Username) + " - " + author.Role
}
description := ""
if m.compatViewMode {
a := ""
a += "Compatibility information is maintained by the community." + "\n"
a += "If you encounter issues with a mod, please report it on the Discord." + "\n"
a += "Learn more about what compatibility states mean on ficsit.app" + "\n\n"
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 {
slog.Error("failed to convert html to markdown", slog.Any("err", err))
markdownDescription = text
}
description, err := glamour.Render(markdownDescription, "dark")
if err != nil {
slog.Error("failed to render markdown", slog.Any("err", err))
description = text
}
return description
}
func (m modInfo) renderCompatInfo(state ficsit.CompatibilityState) string {
stateText := string(state)
switch state {
case ficsit.CompatibilityStateWorks:
return utils.CompatWorksStyle.Render(stateText)
case ficsit.CompatibilityStateDamaged:
return utils.CompatDamagedStyle.Render(stateText)
case ficsit.CompatibilityStateBroken:
return utils.CompatBrokenStyle.Render(stateText)
default:
return utils.CompatUntestedStyle.Render("Unknown")
}
}
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)
}
} }