diff --git a/cmd/shared.go b/cmd/shared.go index e5e88cfe..59919b66 100644 --- a/cmd/shared.go +++ b/cmd/shared.go @@ -10,7 +10,6 @@ import ( "os" "runtime" "strings" - "time" "github.com/simulot/immich-go/helpers/configuration" "github.com/simulot/immich-go/helpers/fileevent" @@ -46,14 +45,14 @@ type SharedFlags struct { } func (app *SharedFlags) InitSharedFlags() { - app.ConfigurationFile = configuration.DefaultFile() + app.ConfigurationFile = configuration.DefaultConfigFile() + app.LogFile = configuration.DefaultLogFile() app.NoLogColors = runtime.GOOS == "windows" app.APITrace = false app.Debug = false app.SkipSSL = false app.LogLevel = "INFO" app.NoUI = false - app.LogFile = "./immich-go " + time.Now().Format("2006-01-02 15-04-05") + ".log" } // SetFlag add common flags to a flagset @@ -89,31 +88,28 @@ func (app *SharedFlags) Start(ctx context.Context) error { if app.LogFile != "" { if app.LogWriterCloser == nil { + err := configuration.MakeDirForFile(app.LogFile) + if err != nil { + return err + } f, err := os.OpenFile(app.LogFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o664) if err != nil { - joinedErr = errors.Join(joinedErr, err) - } else { - err = app.Level.UnmarshalText([]byte(strings.ToUpper(app.LogLevel))) - if err != nil { - joinedErr = errors.Join(joinedErr, err) - } else { - app.Log = slog.New(humane.NewHandler(f, &humane.Options{Level: app.Level})) - app.Jnl.SetLogger(app.Log) - } + return err + } + err = app.Level.UnmarshalText([]byte(strings.ToUpper(app.LogLevel))) + if err != nil { + return err } + app.Log = slog.New(humane.NewHandler(f, &humane.Options{Level: app.Level})) + app.Jnl.SetLogger(app.Log) app.LogWriterCloser = f } } - // at this point, exits if there is an error - if joinedErr != nil { - return joinedErr - } - // If the client isn't yet initialized if app.Immich == nil { if app.Server == "" && app.API == "" && app.Key == "" { - conf, err := configuration.Read(app.ConfigurationFile) + conf, err := configuration.ConfigRead(app.ConfigurationFile) confExist := err == nil if confExist && app.Server == "" && app.Key == "" && app.API == "" { app.Server = conf.ServerURL @@ -130,6 +126,9 @@ func (app *SharedFlags) Start(ctx context.Context) error { } if app.Key == "" { joinedErr = errors.Join(joinedErr, errors.New("missing -key")) + } + + if joinedErr != nil { return joinedErr } @@ -139,12 +138,15 @@ func (app *SharedFlags) Start(ctx context.Context) error { APIKey: app.Key, APIURL: app.API, } - err := conf.Write(app.ConfigurationFile) + err := configuration.MakeDirForFile(app.ConfigurationFile) if err != nil { - err = fmt.Errorf("can't write into the configuration file: %w", err) - joinedErr = errors.Join(joinedErr, err) - return joinedErr + return err + } + err = conf.Write(app.ConfigurationFile) + if err != nil { + return fmt.Errorf("can't write into the configuration file: %w", err) } + app.Log.Info("Connection to the server " + app.Server) app.Immich, err = immich.NewImmichClient(app.Server, app.Key, app.SkipSSL) if err != nil { @@ -164,13 +166,13 @@ func (app *SharedFlags) Start(ctx context.Context) error { if err != nil { return err } - fmt.Println("Server status: OK") + app.Log.Info("Server status: OK") user, err := app.Immich.ValidateConnection(ctx) if err != nil { return err } - fmt.Printf("Connected, user: %s\n", user.Email) + app.Log.Info(fmt.Sprintf("Connected, user: %s", user.Email)) } return nil } diff --git a/docs/releases.md b/docs/releases.md index 0bacf0c4..d8910a66 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1,5 +1,19 @@ # Release notes +## Release next + +### fix [#215](https://github.com/simulot/immich-go/issues/215) Use XDG_CONFIG_HOME for storing config +The configuration file that contains the server and the key is now stored by default in following folder: +- Linux `$HOME/.config/immich-go/immich-go.json` +- Windows `%AppData%\immich-go\immich-go.json` +- Apple `$HOME/Library/Application Support/immich-go/immich-go.json` + +### Store the log files into sensible dir for user's system +The default log file is: +- Linux `$HOME/.cache/immich-go/immich-go_YYYY-MM-DD_HH-MI-SS.log` +- Windows `%LocalAppData%\immich-go\immich-go_YYYY-MM-DD_HH-MI-SS.log` +- Apple `$HOME/Library/Caches/immich-go/immich-go_YYYY-MM-DD_HH-MI-SS.log` + ### Feat: [[#249](https://github.com/simulot/immich-go/issues/249)] Fix Display the path of log file name The log file's name is displayed at exection end. @@ -7,7 +21,7 @@ The log file's name is displayed at exection end. ## Release 0.14.1 -### [#246](https://github.com/simulot/immich-go/issues/246) Google Takeout 403 Forbidden on non admin user +### fix [#246](https://github.com/simulot/immich-go/issues/246) Google Takeout 403 Forbidden on non admin user Uses the endpoint /api/asset/statistics to get the number of user's assets. ## Release 0.14.0 "A better UI" diff --git a/helpers/configuration/config.go b/helpers/configuration/config.go index 584fb84f..b59e884d 100644 --- a/helpers/configuration/config.go +++ b/helpers/configuration/config.go @@ -4,6 +4,7 @@ import ( "encoding/json" "os" "path/filepath" + "time" ) type Configuration struct { @@ -12,18 +13,20 @@ type Configuration struct { APIKey string } -// DefaultFile return the default configuration file name -// Return a local file nama when the default UserHomeDir can't be determined, -func DefaultFile() string { - d, err := os.UserHomeDir() +// DefaultConfigFile return the default configuration file name +// Return a local file when the default UserHomeDir can't be determined, +func DefaultConfigFile() string { + config, err := os.UserConfigDir() if err != nil { - return "immich-go.json" + // $XDG_CONFIG_HOME nor $HOME is set + // return current + return "./immich-go.json" } - return filepath.Join(d, ".immich-go", "immich-go.json") + return filepath.Join(config, "immich-go", "immich-go.json") } -// Read the configuration in file name -func Read(name string) (Configuration, error) { +// ConfigRead the configuration in file name +func ConfigRead(name string) (Configuration, error) { f, err := os.Open(name) if err != nil { return Configuration{}, err @@ -56,3 +59,20 @@ func (c Configuration) Write(name string) error { enc.SetIndent("", " ") return enc.Encode(c) } + +// DefaultLogDir give the default log file +// Return the current dir when $HOME not $XDG_CACHE_HOME are not set +func DefaultLogFile() string { + f := time.Now().Format("immich-go_2006-01-02_15-04-05.log") + d, err := os.UserCacheDir() + if err != nil { + return f + } + return filepath.Join(d, "immich-go", f) +} + +// MakeDirForFile create all dirs to write the given file +func MakeDirForFile(f string) error { + dir := filepath.Dir(f) + return os.MkdirAll(dir, 0o700) +} diff --git a/readme.md b/readme.md index ff6eeda1..60e4acf5 100644 --- a/readme.md +++ b/readme.md @@ -57,19 +57,19 @@ immich-go -server URL -key KEY -general_options COMMAND -command_options... {fil -| **Parameter** | **Description** | **Default value** | -| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | -| `-use-configuration=path/to/config/file` | Specifies the configuration file to use.
Server URL and the API key are stored into the immich-go configuration file. They can be omitted for the next runs. | `$HOME/.immich-go/immich-go.json` | -| `-server=URL` | URL of the Immich service, example http://:2283 or https://your-domain | | -| `-api=URL` | URL of the Immich api endpoint (http://container_ip:3301) | | -| `-device-uuid=VALUE` | Force the device identification | `$HOSTNAME` | -| `-skip-verify-ssl` | Skip SSL verification for use with self-signed certificates | `false` | -| `-key=KEY` | A key generated by the user. Uploaded photos will belong to the key's owner. | | -| `-no-colors-log` | Remove color codes from logs. | `TRUE` on Windows, `FALSE` otherwise | -| `-log-level=LEVEL` | Adjust the log verbosity as follows:
- `ERROR`: Display only errors
- `WARNING`: Same as previous one plus non blocking error
- `INFO`: Information messages | `INFO` | -| `-log-file=/path/to/log/file` | Write all messages to a file | `immich-go YYYY-MM-DD HH-MI-SS.log` | -| `-time-zone=time_zone_name` | Set the time zone for dates without time zone information | the system's time zone | -| `-no-ui` | Disable the user interface | 'false' | +| **Parameter** | **Description** | **Default value** | +| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | +| `-use-configuration=path/to/config/file` | Specifies the configuration file to use.
Server URL and the API key are stored into the immich-go configuration file. They can be omitted for the next runs. | Linux `$HOME/.config/immich-go/immich-go.json`
Windows `%AppData%\immich-go\immich-go.json`
Apple `$HOME/Library/Application Support/immich-go/immich-go.json` | +| `-server=URL` | URL of the Immich service, example http://:2283 or https://your-domain | | +| `-api=URL` | URL of the Immich api endpoint (http://container_ip:3301) | | +| `-device-uuid=VALUE` | Force the device identification | `$HOSTNAME` | +| `-skip-verify-ssl` | Skip SSL verification for use with self-signed certificates | `false` | +| `-key=KEY` | A key generated by the user. Uploaded photos will belong to the key's owner. | | +| `-no-colors-log` | Remove color codes from logs. | `TRUE` on Windows, `FALSE` otherwise | +| `-log-level=LEVEL` | Adjust the log verbosity as follows:
- `ERROR`: Display only errors
- `WARNING`: Same as previous one plus non blocking error
- `INFO`: Information messages | `INFO` | +| `-log-file=/path/to/log/file` | Write all messages to a file | Linux `$HOME/.cache/immich-go/immich-go_YYYY-MM-DD_HH-MI-SS.log`
Windows `%LocalAppData%\immich-go\immich-go_YYYY-MM-DD_HH-MI-SS.log`
Apple `$HOME/Library/Caches/immich-go/immich-go_YYYY-MM-DD_HH-MI-SS.log`| +| `-time-zone=time_zone_name` | Set the time zone for dates without time zone information | the system's time zone | +| `-no-ui` | Disable the user interface | 'false' | ## Command `upload` @@ -82,7 +82,7 @@ Use this command for uploading photos and videos from a local directory, a zippe | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | | `-album="ALBUM NAME"` | Import assets into the Immich album `ALBUM NAME`. | | | `-dry-run` | Preview all actions as they would be done. | `FALSE` | -| `-create-album-folder` | Generate immich albums after folder names. | `FALSE` | +| `-create-album-folder` | Generate immich albums after folder names. | `FALSE` | | `-force-sidecar ` | Force sending a .xmp sidecar file beside images. With Google photos date and GPS coordinates are taken from metadata.json files to creates an XMP file and. | `FALSE` | | `-create-stacks` | Stack jpg/raw or bursts. | `TRUE` | | `-stack-jpg-raw` | Control the stacking of jpg/raw photos. | `TRUE` |