### Create Development Environment File Source: https://github.com/majorfi/immich-stack/blob/main/docs/development.md Copies the example environment file to a new file named .env. This file is used to store environment-specific configurations for the development setup. ```shell cp .env.example .env ``` -------------------------------- ### Install Go Project Dependencies Source: https://github.com/majorfi/immich-stack/blob/main/docs/development.md Downloads and installs all the necessary Go module dependencies for the Immich Stack project. This command should be run after cloning the repository. ```go go mod download ``` -------------------------------- ### Run immich-stack locally (Shell) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/quick-start.md These commands show how to execute the immich-stack binary locally. It covers running the application directly or when it's installed in the system's PATH. ```sh # Using the binary ./immich-stack # Or if installed in PATH immich-stack ``` -------------------------------- ### Complete Immich Stack Example Configuration Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/configuration.md A comprehensive example demonstrating the setup of various Immich Stack configurations, including API details, run mode, stack management, asset inclusion, logging, and custom criteria. ```shell # Required API_KEY=your_immich_api_key API_URL=http://immich-server:2283/api # Run mode RUN_MODE=cron CRON_INTERVAL=3600 # Stack management PARENT_FILENAME_PROMOTE=edit,raw PARENT_EXT_PROMOTE=.jpg,.dng DRY_RUN=false RESET_STACKS=false REPLACE_STACKS=true # Asset inclusion WITH_ARCHIVED=false WITH_DELETED=false # Logging LOG_LEVEL=info LOG_FORMAT=text LOG_FILE=/app/logs/immich-stack.log # Custom criteria CRITERIA='[{"key":"originalFileName","split":{"delimiters":["~","."],"index":0}},{"key":"localDateTime","delta":{"milliseconds":1000}}]' ``` -------------------------------- ### Build Immich Stack Binary (Go) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/installation.md Compiles the Immich Stack project from source using Go. Requires Go version 1.21 or later to be installed. The output is a binary named 'immich-stack'. ```go go build -o immich-stack ./cmd/... ``` -------------------------------- ### Table-Driven Test Structure Example (Go) Source: https://github.com/majorfi/immich-stack/blob/main/docs/contributing/testing.md An example demonstrating the table-driven test structure commonly used in the Immich Stack project for Go. This pattern facilitates testing multiple scenarios efficiently. ```go func TestStackBy(t *testing.T) { tests := []struct { name string input []Asset expected []Stack }{ { name: "basic stacking", input: []Asset{ // test data }, expected: []Stack{ // expected results }, }, // more test cases } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := StackBy(tt.input) // assertions }) } } ``` -------------------------------- ### Configure immich-stack with flags and environment variables (Shell) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/quick-start.md This snippet provides examples of how to configure immich-stack using command-line flags and environment variables. It shows how to enable dry run, promote parent filenames, and include archived or deleted items. ```sh # Example with flags ./immich-stack --dry-run --parent-filename-promote=edit --parent-ext-promote=.jpg,.dng --with-archived --with-deleted # Or using environment variables export DRY_RUN=true export PARENT_FILENAME_PROMOTE=edit export PARENT_EXT_PROMOTE=.jpg,.dng export WITH_ARCHIVED=true export WITH_DELETED=true ./immich-stack ``` -------------------------------- ### Install Color Library for Go Source: https://github.com/majorfi/immich-stack/blob/main/vendor/github.com/fatih/color/README.md This snippet shows how to install the 'fatih/color' library using the Go build tools. It's a prerequisite for using the library's functionalities. ```go go get github.com/fatih/color ``` -------------------------------- ### Run immich-stack using Docker (Bash) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/quick-start.md This snippet shows how to run the immich-stack container using Docker. It utilizes an environment file for configuration and maps a local logs directory to the container. It provides commands for both Docker Hub and GitHub Container Registry images. ```bash docker run -d --name immich-stack --env-file .env -v ./logs:/app/logs majorfi/immich-stack:latest ``` ```bash docker run -d --name immich-stack --env-file .env -v ./logs:/app/logs ghcr.io/majorfi/immich-stack:latest ``` -------------------------------- ### Cron Mode Run Cycle Log Example Source: https://github.com/majorfi/immich-stack/blob/main/docs/features/cron-mode.md Provides an example log output for a single cron cycle, showing the start time, user processing details, completion time, and the duration of the sleep period until the next run. ```text [12:00:00] INFO Starting cron cycle [12:00:00] INFO Running for user: John Doe (john@example.com) [12:00:05] INFO Processing 5,234 assets ... [12:02:15] INFO Cron cycle completed in 2m 15s [12:02:15] INFO Sleeping for 3600 seconds until next run ``` -------------------------------- ### Create .env file for Basic Usage (Bash) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/quick-start.md This snippet demonstrates how to create a `.env` file to configure the immich-stack for basic usage. It sets essential environment variables like API keys and URLs, and specifies the run mode and cron interval. ```bash cat > .env << EOL API_KEY=your_immich_api_key API_URL=http://immich-server:2283/api RUN_MODE=cron CRON_INTERVAL=60 # Optional: Enable file logging for persistent logs # LOG_FILE=/app/logs/immich-stack.log EOL ``` -------------------------------- ### Create .env file for Local Running (Shell) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/quick-start.md This snippet illustrates the creation of a `.env` file for running immich-stack locally. It specifies the Immich API key and the URL for the local Immich server. ```sh API_KEY=your_immich_api_key API_URL=http://your_immich_server:3001/api ``` -------------------------------- ### Clone Immich Stack Repository (Shell) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/installation.md Clones the Immich Stack Git repository and navigates into the project directory. This is a common first step for both source and Docker installations. ```shell git clone https://github.com/majorfi/immich-stack.git cd immich-stack ``` -------------------------------- ### Example Immich Stack .env Configuration for Multi-User Source: https://github.com/majorfi/immich-stack/blob/main/docs/features/multi-user.md An example of an .env file configuration for Immich Stack when supporting multiple users. It includes the API_KEY with comma-separated keys and the API_URL. ```dotenv # .env file API_KEY=abc123,def456,ghi789 API_URL=http://immich-server:2283/api ``` -------------------------------- ### Multi-User Cron Mode Log Example Source: https://github.com/majorfi/immich-stack/blob/main/docs/features/cron-mode.md Example log output demonstrating sequential processing of multiple users in cron mode. Each user's processing start and completion are logged distinctly, followed by the sleep interval for the next cycle. ```text [12:00:00] INFO Running for user: Alice (alice@example.com) [12:01:30] INFO User Alice completed [12:01:30] INFO Running for user: Bob (bob@example.com) [12:03:00] INFO User Bob completed [12:03:00] INFO Running for user: Carol (carol@example.com) [12:04:15] INFO User Carol completed [12:04:15] INFO Sleeping for 3600 seconds until next run ``` -------------------------------- ### Install GoDotEnv as a Library Source: https://github.com/majorfi/immich-stack/blob/main/vendor/github.com/joho/godotenv/README.md Installs the GoDotEnv library for use within your Go projects. This is the standard method for integrating GoDotEnv's functionality into your application. ```shell go get github.com/joho/godotenv ``` -------------------------------- ### Execute immich-stack commands (Shell) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/quick-start.md This snippet demonstrates the execution of various immich-stack commands, including the default stacking operation, identifying duplicates, and fixing trash consistency. It shows how to use the `--dry-run` flag for previewing changes before execution. ```sh # Run the main stacking operation immich-stack # Or explicitly: immich-stack stack # Identify duplicate assets in your library immich-stack duplicates # Move related assets to trash when their companions are trashed immich-stack fix-trash --dry-run # Preview first immich-stack fix-trash # Execute ``` -------------------------------- ### Example Grouping Operations Usage Source: https://github.com/majorfi/immich-stack/blob/main/docs/api-reference/grouping.md Provides example Go code demonstrating how to use the grouping operations, including defining criteria for grouping assets, fetching a specific group, updating a group's name, and deleting a group. Includes basic error checking for each operation. ```go // Group assets with criteria criteria := []Criterion{ { Key: "originalFileName", Split: &SplitConfig{ Delimiters: []string{"~", "."}, Index: 0, }, }, { Key: "localDateTime", Delta: &DeltaConfig{ Milliseconds: 1000, }, }, } groups, err := GroupAssets(ctx, client, assets, criteria) if err != nil { log.Printf("Error grouping assets: %v", err) return } // Get single group group, err := GetGroup(ctx, client, "group-id") if err != nil { log.Printf("Error getting group: %v", err) return } // Update group group.Name = "New Name" err = UpdateGroup(ctx, client, group) if err != nil { log.Printf("Error updating group: %v", err) return } // Delete group err = DeleteGroup(ctx, client, "group-id") if err != nil { log.Printf("Error deleting group: %v", err) return } ``` -------------------------------- ### Install go-colorable Package Source: https://github.com/majorfi/immich-stack/blob/main/vendor/github.com/mattn/go-colorable/README.md This command installs the go-colorable package, which is necessary for enabling colored output in terminal applications on Windows. It fetches the package from its remote repository and makes it available for use in Go projects. ```bash go get github.com/mattn/go-colorable ``` -------------------------------- ### Basic Logrus Logging Example (Go) Source: https://github.com/majorfi/immich-stack/blob/main/vendor/github.com/sirupsen/logrus/README.md Demonstrates the simplest way to use the package-level exported logger in Logrus. This example shows how to import the library and log a message with a field. ```go package main import ( log "github.com/sirupsen/logrus" ) func main() { log.WithFields(log.Fields{ "animal": "walrus", }).Info("A walrus appears") } ``` -------------------------------- ### Handle Burst Photos with Sequence Keyword (Shell) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/quick-start.md This section demonstrates how to configure immich-stack to handle burst photos using the `sequence` keyword. It covers basic ordering, prioritizing cover photos, and handling specific numeric formats or prefixes. ```sh # Order any burst photos by their numeric sequence export PARENT_FILENAME_PROMOTE=sequence # For Sony burst photos with COVER priority export PARENT_FILENAME_PROMOTE=COVER,sequence # For Canon burst photos with specific 4-digit format export PARENT_FILENAME_PROMOTE=sequence:4 # For files with specific prefix export PARENT_FILENAME_PROMOTE=sequence:IMG_ ./immich-stack ``` -------------------------------- ### Move Binary to PATH (Shell) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/installation.md Moves the compiled 'immich-stack' binary to a directory included in the system's PATH, allowing it to be executed from any location. Requires superuser privileges. ```shell sudo mv immich-stack /usr/local/bin/ ``` -------------------------------- ### Install GoDotEnv Command-Line Tool (Go < 1.17) Source: https://github.com/majorfi/immich-stack/blob/main/vendor/github.com/joho/godotenv/README.md Installs the GoDotEnv command-line interface (CLI) for Go versions prior to 1.17. Use this command if you are working with an older Go toolchain. ```shell go get github.com/joho/godotenv/cmd/godotenv ``` -------------------------------- ### Shorthand Flags and Options Source: https://github.com/majorfi/immich-stack/blob/main/vendor/github.com/spf13/pflag/README.md Explains the use of shorthand flags, limitations and examples, including how they interact with boolean and non-boolean flags and their default values. ```text // boolean or flags where the 'no option default value' is set -f -f=true -abc but -b true is INVALID // non-boolean and flags without a 'no option default value' -n 1234 -n=1234 -n1234 // mixed -abcs "hello" -absd="hello" -abcs1234 ``` -------------------------------- ### Install GoDotEnv Command-Line Tool (Go >= 1.17) Source: https://github.com/majorfi/immich-stack/blob/main/vendor/github.com/joho/godotenv/README.md Installs the GoDotEnv command-line interface (CLI) for Go versions 1.17 and later. This allows you to use GoDotEnv to load environment variables for commands directly from your terminal. ```shell go install github.com/joho/godotenv/cmd/godotenv@latest ``` -------------------------------- ### Split Configuration Example for String Extraction (JSON) Source: https://github.com/majorfi/immich-stack/blob/main/docs/features/custom-criteria.md Demonstrates how to extract parts of string values using specified delimiters and an index. This is useful for parsing filenames or paths. ```JSON { "key": "originalFileName", "split": { "delimiters": ["~", "."], "index": 0 } } ``` ```JSON { "key": "originalPath", "split": { "delimiters": ["/"], "index": 2 } } ``` -------------------------------- ### Build Go Binary Source: https://github.com/majorfi/immich-stack/blob/main/docs/development.md Compiles the Immich Stack project into an executable binary. Supports building for the current platform and cross-compiling for a specified platform like Linux. ```go # Build binary go build -o immich-stack # Build for specific platform GOOS=linux GOARCH=amd64 go build -o immich-stack ``` -------------------------------- ### Run Go Tests Source: https://github.com/majorfi/immich-stack/blob/main/docs/development.md Executes unit tests for the Immich Stack project. Supports running all tests, specific package tests, and tests with coverage reporting. ```go # Run all tests go test ./... # Run specific test go test ./internal/stack # Run with coverage go test -cover ./... ``` -------------------------------- ### Initialize Immich Client (Go) Source: https://github.com/majorfi/immich-stack/blob/main/docs/development/command-architecture.md This Go code example demonstrates how to initialize the Immich client within a command. It shows the parameters typically passed, including API URL, key, command-specific options (like resetStacks, replaceStacks, withPartners), and global options (dryRun, withArchived, withDeleted), along with the logger instance. This ensures the client is configured correctly for each command's execution. ```go client := immich.NewClient( apiURL, key, resetStacks, // Command-specific replaceStacks, // Command-specific dryRun, // Global option withArchived, // Global option withDeleted, // Global option withPartners, // Command-specific logger ) ``` -------------------------------- ### Dual Logging Setup in Go Source: https://github.com/majorfi/immich-stack/blob/main/docs/architecture.md Implements dual logging, outputting logs to both standard output and a specified log file when the LOG_FILE environment variable is set. It includes error handling for file opening and a fallback mechanism to ensure logs are always captured. ```go if logFile != "" { file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err == nil { logger.SetOutput(io.MultiWriter(os.Stdout, file)) } else { // Fallback to stdout only logger.Warn("Could not open log file, using stdout only") } } ``` -------------------------------- ### Manage Immich Stack Docker Service (Docker Compose) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/installation.md Commands to manage the Immich Stack service using Docker Compose. Includes starting, stopping, viewing logs, and restarting the service, especially after configuration changes like switching to cron mode. ```docker-compose # Start service in detached mode docker compose up -d # Stop service docker compose down # View logs in real-time docker compose logs -f # Restart service (e.g., after changing .env for cron mode) docker compose down docker compose up -d ``` -------------------------------- ### Thread-Safe HTTP Client Initialization in Go Source: https://github.com/majorfi/immich-stack/blob/main/docs/architecture.md Demonstrates the correct way to initialize and use HTTP clients for different API keys to ensure thread safety. It contrasts a safe approach of creating a new client instance per goroutine with an unsafe method that shares a single client across goroutines, leading to potential race conditions. ```go // Safe: New client per user for _, key := range apiKeys { client := immich.NewClient(...) // Fresh instance // Use client for this user only } // Unsafe: Sharing client across goroutines client := immich.NewClient(...) for _, key := range apiKeys { go func() { // DON'T DO THIS - not thread-safe client.SetAPIKey(key) }() } ``` -------------------------------- ### Handle Burst Photos with Numeric Sequences (Legacy) (Shell) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/quick-start.md This snippet shows the legacy method of handling burst photos by explicitly listing numeric sequences in the `PARENT_FILENAME_PROMOTE` environment variable. It provides examples for Sony and Canon burst photo naming conventions. ```sh # For Sony burst photos (DSCPDC_0000_BURST..., DSCPDC_0001_BURST..., etc.) export PARENT_FILENAME_PROMOTE=0000,0001,0002,0003 # For Canon burst photos (IMG_0001, IMG_0002, etc.) export PARENT_FILENAME_PROMOTE=IMG_0001,IMG_0002,IMG_0003 # The system automatically detects sequences and orders photos correctly # Even files beyond your list (e.g., 0999) will be sorted properly ./immich-stack ``` -------------------------------- ### Go Project Test Structure Example Source: https://github.com/majorfi/immich-stack/blob/main/docs/architecture.md Illustrates a typical project directory structure for Go projects, showcasing the separation of implementation files (e.g., `stacker.go`) from their corresponding unit (`_test.go`) and integration (`_integration_test.go`) tests. It also shows how API client tests can be organized. ```tree pkg/ ├─ stacker/ │ ├─ stacker.go # Implementation │ ├─ stacker_test.go # Unit tests │ └─ stacker_integration_test.go # Integration tests │ └─ immich/ ├─ client.go # API client └─ client_test.go # Mock API tests ``` -------------------------------- ### Initialize Immich API Client in Go Source: https://context7.com/majorfi/immich-stack/llms.txt Demonstrates how to create and configure an Immich API client in Go. It includes setting up the API URL, API key, and various options like retry logic and timeouts. The client is configured with default retry settings and connection pooling. ```go package main import ( "github.com/majorfi/immich-stack/pkg/immich" "github.com/sirupsen/logrus" ) func main() { logger := logrus.New() logger.SetLevel(logrus.InfoLevel) // Create client with configuration client := immich.NewClient( "http://immich-server:2283/api", // API URL "your-api-key-here", // API key false, // resetStacks true, // replaceStacks false, // dryRun false, // withArchived false, // withDeleted false, // removeSingleAssetStacks logger, ) if client == nil { logger.Fatal("Failed to create client - check API URL and key") } // Client is configured with: // - 600 second timeout // - 3 max retries with exponential backoff // - Connection pooling (100 max idle connections) logger.Info("✅ Client created successfully") } ``` -------------------------------- ### Complete Stack Workflow Example (Go) Source: https://github.com/majorfi/immich-stack/blob/main/docs/api-reference/stack-operations.md This Go code snippet outlines a comprehensive workflow for managing stacks within Immich. It covers fetching existing stacks and assets, grouping assets into new stacks based on defined criteria, deleting old stacks that require replacement, and finally creating or updating stacks with the grouped assets. It includes error handling at each step. ```go // 1. Fetch existing stacks stacks, err := client.FetchAllStacks() if err != nil { log.Fatalf("Error: %v", err) } // 2. Fetch all assets assets, err := client.FetchAssets(1000, stacks) if err != nil { log.Fatalf("Error: %v", err) } // 3. Group assets into new stacks groups := stacker.StackBy(assets, criteria, ...) // 4. Delete old conflicting stacks for _, group := range groups { if needsReplacement(group) { err := client.DeleteStack(oldStackID, utils.REASON_REPLACE) if err != nil { log.Errorf("Delete failed: %v", err) } } } // 5. Create/update stacks for _, group := range groups { assetIDs := extractIDs(group) err := client.ModifyStack(assetIDs) if err != nil { log.Errorf("Modify failed: %v", err) } } ``` -------------------------------- ### Cron Mode Timing Behavior Example Source: https://github.com/majorfi/immich-stack/blob/main/docs/features/cron-mode.md Demonstrates the timing behavior of cron mode where the interval timer starts after each run completes. If a run exceeds the `CRON_INTERVAL`, the next run starts immediately, and a warning is logged if processing time is more than 50% of the interval. ```text CRON_INTERVAL=3600 (1 hour) Run 1: [12:00:00 - 12:02:15] → Wait 3600s → Run 2: [13:02:15 - 13:04:30] → Wait 3600s → ... If a run takes longer than the interval: Run 1: 12:00:00 - 13:30:00 (90 minutes) ⚠️ Warning: Processing took 5400s, which exceeds interval of 3600s Run 2: 13:30:00 - 15:00:00 (90 minutes) ⚠️ Warning: Processing took 5400s, which exceeds interval of 3600s ``` -------------------------------- ### Handle Multiple Users Sequentially (Go) Source: https://github.com/majorfi/immich-stack/blob/main/docs/api-reference/stack-operations.md This Go code illustrates how to manage operations for multiple users by iterating through a list of API keys. For each key, it creates a new client instance, fetches the current user, and then proceeds with user-specific operations. Error handling is included to log failures for individual keys and continue processing others. ```go // Process multiple users sequentially apiKeys := strings.Split(os.Getenv("API_KEYS"), ",") for _, key := range apiKeys { client := immich.NewClient(apiURL, key, ...) user, err := client.GetCurrentUser() if err != nil { logger.Errorf("Failed for key %s: %v", key, err) continue } logger.Infof("Processing user: %s", user.Name) // ... perform operations } ``` -------------------------------- ### Configure Cron Interval Source: https://github.com/majorfi/immich-stack/blob/main/docs/troubleshooting.md Sets the interval in seconds for the cron job to run. For example, 3600 seconds equals one hour. This is crucial for proper scheduling in cron mode. ```shell CRON_INTERVAL=3600 ``` -------------------------------- ### Configure Immich Stack Docker Environment (.env) Source: https://github.com/majorfi/immich-stack/blob/main/docs/getting-started/installation.md Creates and populates a .env file for Docker Compose configuration. This file holds essential Immich credentials and operational settings like API keys, URLs, and run modes. ```env # Required API_KEY=your_immich_api_key API_URL=http://your_immich_server:3001/api # Optional - Default values shown DRY_RUN=false RESET_STACKS=false REPLACE_STACKS=false PARENT_FILENAME_PROMOTE=edit PARENT_EXT_PROMOTE=.jpg,.dng WITH_ARCHIVED=false WITH_DELETED=false # Run mode settings RUN_MODE=once # Options: once, cron CRON_INTERVAL=86400 # in seconds, only used if RUN_MODE=cron ``` -------------------------------- ### Structured Logging with Logrus in Go Source: https://github.com/majorfi/immich-stack/blob/main/docs/architecture.md Demonstrates how to use the logrus library for structured logging in Go. It shows how to attach fields like assetID, filename, and stackID to log messages for better context and easier querying. This approach enhances log analysis by providing key-value pairs. ```go logger.WithFields(logrus.Fields{ "assetID": asset.ID, "filename": asset.OriginalFileName, "stackID": stack.ID, }).Info("Stack created") ``` -------------------------------- ### Docker: Deploy and Manage Immich Stacking Tool Source: https://context7.com/majorfi/immich-stack/llms.txt This section details how to run the Immich stacking tool using Docker containers. It covers creating an environment file for configuration, running the tool in detached mode for cron scheduling, viewing logs, and executing one-time commands for duplicate detection or trash fixing. It also shows how to perform a dry run and reset all stacks. ```bash # Create environment file cat > .env << 'EOF' # Required settings API_KEY=your_immich_api_key_here API_URL=http://immich-server:2283/api # Execution mode RUN_MODE=cron CRON_INTERVAL=3600 # Run every hour # Logging configuration LOG_LEVEL=info LOG_FORMAT=text LOG_FILE=/app/logs/immich-stack.log # Stacking behavior REPLACE_STACKS=true REMOVE_SINGLE_ASSET_STACKS=false WITH_ARCHIVED=false # Parent selection priorities PARENT_FILENAME_PROMOTE=cover,edit,crop,hdr,biggestNumber PARENT_EXT_PROMOTE=.jpg,.png,.jpeg,.dng # Custom criteria (optional) CRITERIA='[{"key":"originalFileName","split":{"delimiters":["~","."],"index":0}},{"key":"localDateTime","delta":{"milliseconds":1000}}]' EOF # Run main stacking command docker run -d \ --name immich-stack \ --env-file .env \ -v ./logs:/app/logs \ --restart on-failure \ majorfi/immich-stack:latest # View logs docker logs -f immich-stack # Run duplicate detection (one-time) docker run --rm \ --env-file .env \ majorfi/immich-stack:latest \ duplicates # Run trash fix (one-time) docker run --rm \ --env-file .env \ majorfi/immich-stack:latest \ fix-trash # Dry run to preview changes docker run --rm \ -e API_KEY=your_key \ -e API_URL=http://immich:2283/api \ -e DRY_RUN=true \ majorfi/immich-stack:latest # Reset all stacks (destructive - requires confirmation) docker run --rm \ -e API_KEY=your_key \ -e API_URL=http://immich:2283/api \ -e RESET_STACKS=true \ -e CONFIRM_RESET_STACK=true \ majorfi/immich-stack:latest ``` -------------------------------- ### HTTP Client Configuration in Go Source: https://github.com/majorfi/immich-stack/blob/main/docs/architecture.md Shows how to configure a custom `http.Client` in Go with specific timeouts and transport settings. This includes setting a global request timeout and optimizing connection pooling parameters like MaxIdleConns, MaxIdleConnsPerHost, and IdleConnTimeout for better performance. ```go client := &http.Client{ Timeout: 600 * time.Second, // 10 minutes Transport: &http.Transport{ MaxIdleConns: 100, MaxIdleConnsPerHost: 100, IdleConnTimeout: 90 * time.Second, }, } ``` -------------------------------- ### Promote Unedited JPGs Over Edited Ones - Shell Source: https://github.com/majorfi/immich-stack/blob/main/docs/api-reference/environment-variables.md This example demonstrates how to configure the `PARENT_FILENAME_PROMOTE` environment variable in a shell script to prioritize unedited JPG files over their edited counterparts. It utilizes negative matching by starting the list with a comma, indicating files that do not contain the subsequent substring. ```shell # Promote unedited JPGs over edited ones PARENT_FILENAME_PROMOTE=,_edited # Result: IMG_1234.jpg > IMG_1234_edited.jpg ``` -------------------------------- ### Shared Logger Initialization (Go) Source: https://github.com/majorfi/immich-stack/blob/main/docs/development/command-architecture.md This Go code illustrates the usage of the shared `loadEnv()` function to initialize the application's logger. The `loadEnv()` function is responsible for setting up the logger based on environment variables like `LOG_LEVEL` and `LOG_FORMAT`, ensuring consistent logging across all commands. Examples of different log levels (Info, Debug, Error) are shown. ```go logger := loadEnv() // Initializes logger with LOG_LEVEL and LOG_FORMAT logger.Info("Starting command...") logger.Debug("Detailed information...") logger.Error("Error occurred: %v", err) ``` -------------------------------- ### Install Cobra Library (Go) Source: https://github.com/majorfi/immich-stack/blob/main/vendor/github.com/spf13/cobra/README.md Installs the latest version of the Cobra library using the Go package manager. ```bash go get -u github.com/spf13/cobra@latest ``` -------------------------------- ### Create Immich API Client (Go) Source: https://github.com/majorfi/immich-stack/blob/main/docs/api-reference/stack-operations.md Illustrates how to instantiate a new Immich API client. It requires the API URL, an API key, and several boolean flags to configure the client's behavior, along with a logger instance. The function returns a configured client object. ```go client := immich.NewClient( apiURL, // Base URL of Immich API apiKey, // API key for authentication resetStacks, // Delete all existing stacks replaceStacks, // Replace stacks for new groups dryRun, // Simulate without making changes withArchived, // Include archived assets withDeleted, // Include deleted assets removeSingleAssetStacks, // Remove single-asset stacks logger, // Logger instance ) ``` -------------------------------- ### Install Cobra CLI Generator (Go) Source: https://github.com/majorfi/immich-stack/blob/main/vendor/github.com/spf13/cobra/README.md Installs the cobra-cli command-line tool, used for scaffolding new Cobra-based applications. ```bash go install github.com/spf13/cobra-cli@latest ``` -------------------------------- ### Example of Deep Nesting in Expression Mode (JSON) Source: https://github.com/majorfi/immich-stack/blob/main/docs/features/stacking-logic.md Illustrates a complex JSON expression with multiple nested operators (AND, OR) and criteria. This example demonstrates a nesting level of 3, highlighting the potential for performance impact with deeper structures. ```json { "mode": "advanced", "expression": { "operator": "AND", "children": [ { "operator": "OR", "children": [ { "operator": "AND", "children": [ { "criteria": { "key": "originalFileName", "regex": { "key": "PXL_", "index": 0 } } }, { "criteria": { "key": "localDateTime", "delta": { "milliseconds": 1000 } } } ] } ] } ] } } ``` -------------------------------- ### Sequential Multi-User API Key Processing in Go Source: https://github.com/majorfi/immich-stack/blob/main/docs/architecture.md Demonstrates sequential processing of multiple API keys, each representing a different user. It splits API keys from an environment variable, creates a client for each, and processes their data one by one. Errors for one user are logged, and the loop continues to the next. ```go apiKeys := strings.Split(os.Getenv("API_KEY"), ",") for _, key := range apiKeys { client := immich.NewClient(apiURL, key, ...) user, err := client.GetCurrentUser() if err != nil { logger.Errorf("Failed for key: %v", err) continue // Skip this user, continue with others } logger.Infof("Processing user: %s", user.Name) // Process stacks for this user if err := processStacks(client); err != nil { logger.Errorf("Error for user %s: %v", user.Name, err) continue } } ``` -------------------------------- ### Install go-isatty Library (Go) Source: https://github.com/majorfi/immich-stack/blob/main/vendor/github.com/mattn/go-isatty/README.md This command installs the `go-isatty` library, a Go package used for checking if a file descriptor is a terminal. It uses the standard Go tooling to fetch and manage the dependency. ```bash $ go get github.com/mattn/go-isatty ``` -------------------------------- ### Regex-Based Grouping with Promotion in Go Source: https://context7.com/majorfi/immich-stack/llms.txt This Go function showcases advanced regex-based grouping for organizing photos into stacks. It defines a flexible criteria using regular expressions with capture groups to identify base filenames and variants. The 'promote_keys' parameter allows for prioritizing specific file variants (e.g., motion photos, edits) as stack parents, ensuring the most relevant version is chosen. ```go package main import ( "github.com/majorfi/immich-stack/pkg/stacker" "github.com/majorfi/immich-stack/pkg/utils" "github.com/sirupsen/logrus" ) func advancedRegexStacking() { logger := logrus.New() // Example assets: // PXL_20240115_143022001.jpg // PXL_20240115_143022001_MP.jpg (motion photo) // PXL_20240115_143022001_edit.jpg // Regex-based criteria with capture groups criteria := `[ { "key": "originalFileName", "regex": { "key": "(PXL_\\d{8}_\\d{9})(_\\w+)?\\.(jpg|JPG|dng|DNG)", "index": 1, "promote_index": 2, "promote_keys": ["_MP", "_Portrait", "_Night", "_edit", "_crop", ""] } } ]` // This regex: // - Captures base filename in group 1: "PXL_20240115_143022001" // - Captures variant suffix in group 2: "_MP", "_edit", etc. // - Groups by group 1 (all variants together) // - Promotes based on group 2 priority (_MP > _Portrait > _Night > ...) var assets []utils.TAsset // ... populate assets from Immich ... stacks, err := stacker.StackBy( assets, criteria, "", // no filename promotion needed with regex ".jpg", // extension promotion as fallback logger, ) if err != nil { logger.Fatalf("Stacking failed: %v", err) } // Result: PXL_20240115_143022001_MP.jpg becomes parent // because "_MP" is highest priority in promote_keys for _, stack := range stacks { logger.Infof("Stack parent: %s (children: %d)", stack[0].OriginalFileName, len(stack)-1) } } ``` -------------------------------- ### Error Logging Example (Plain Text) Source: https://github.com/majorfi/immich-stack/blob/main/docs/features/cron-mode.md This example demonstrates the format of error and informational messages logged by the Immich Stack cron mode. It shows how recoverable errors are logged along with retry information. ```text [12:00:00] ERROR Failed to fetch assets: connection timeout [12:00:00] INFO Will retry in next cycle (3600s) [13:00:00] INFO Retrying stacking operation ``` -------------------------------- ### Fetch Assets with Stack Info in Go Source: https://context7.com/majorfi/immich-stack/llms.txt Illustrates how to retrieve all image assets from an Immich server, including pagination and stack metadata. It first fetches all stacks to enrich asset data and then retrieves assets, logging information about assets that belong to a stack. ```go package main import ( "github.com/majorfi/immich-stack/pkg/immich" "github.com/sirupsen/logrus" ) func fetchAllAssets() { logger := logrus.New() client := immich.NewClient( "http://immich-server:2283/api", "your-api-key", false, true, false, false, false, false, logger, ) // First fetch all stacks to enrich asset data stacksMap, err := client.FetchAllStacks() if err != nil { logger.Fatalf("Failed to fetch stacks: %v", err) } logger.Infof("📚 Found %d stacks", len(stacksMap)) // Fetch all assets with pagination (1000 per page) // Assets are automatically enriched with stack information assets, err := client.FetchAssets(1000, stacksMap) if err != nil { logger.Fatalf("Failed to fetch assets: %v", err) } // Process assets logger.Infof("🌄 Retrieved %d total assets", len(assets)) for _, asset := range assets { if asset.Stack != nil { logger.Debugf("Asset %s is in stack %s (primary: %s)", asset.OriginalFileName, asset.Stack.ID, asset.Stack.PrimaryAssetID, ) } } } ``` -------------------------------- ### JSON Log Format Example Source: https://github.com/majorfi/immich-stack/blob/main/docs/architecture.md An example of a machine-parseable JSON log format. This structured format is ideal for automated log aggregation, analysis, and monitoring systems, providing key-value pairs for each log entry, including a timestamp. ```json { "level": "info", "msg": "Stack created", "assetID": "abc-123", "filename": "IMG_1234.jpg", "time": "2025-11-12T10:30:00Z" } ``` -------------------------------- ### Text Log Format Example Source: https://github.com/majorfi/immich-stack/blob/main/docs/architecture.md An example of a human-readable text-based log format. This format is easy to read for developers during debugging but might be less convenient for automated parsing and analysis compared to structured formats like JSON. ```text level=info msg="Stack created" assetID=abc-123 filename=IMG_1234.jpg ``` -------------------------------- ### Command-line Flag Syntax Source: https://github.com/majorfi/immich-stack/blob/main/vendor/github.com/spf13/pflag/README.md Illustrates the syntax for defining and using command-line flags with pflag. Covers boolean flags, flags with default values, and shorthand notations. ```text --flag // boolean flags, or flags with no option default values --flag x // only on flags without a default value --flag=x ``` -------------------------------- ### Shell Script: Processing Recent Photos with Criteria Source: https://github.com/majorfi/immich-stack/blob/main/docs/how-to/optimize-performance.md An example of how to specify complex criteria using a JSON string assigned to the `CRITERIA` environment variable in a shell script. This specific example targets recent photos based on `localDateTime` and `originalFileName`. ```sh # Process only recent photos CRITERIA='[{"key":"localDateTime","delta":{"milliseconds":1000}},{"key":"originalFileName","regex":{"key":"^2025","index":0}}]' ``` -------------------------------- ### Configure Sequence Parent Promotion Source: https://github.com/majorfi/immich-stack/blob/main/docs/how-to/debug-parent-selection.md Demonstrates the correct way to configure parent selection for sequenced files (like burst photos). Using the 'sequence' keyword is preferred over manual numbering. ```shell # Correct: Use the 'sequence' keyword for ordered files PARENT_FILENAME_PROMOTE=sequence # Example for 4-digit sequence numbers or specific prefix # PARENT_FILENAME_PROMOTE=sequence:4 # PARENT_FILENAME_PROMOTE=sequence:IMG_ ``` -------------------------------- ### Multi-User Cron Setup for Immich Stack (YAML) Source: https://github.com/majorfi/immich-stack/blob/main/docs/features/cron-mode.md A Docker Compose configuration tailored for multi-user cron operation in Immich Stack. This setup allows for multiple API keys to be specified, enabling the service to manage assets for different users. ```yaml version: "3" services: immich-stack: image: majorfi/immich-stack:latest init: true environment: - API_KEY=user1_key,user2_key,user3_key - API_URL=http://immich:2283/api - RUN_MODE=cron - CRON_INTERVAL=3600 - REPLACE_STACKS=true - LOG_LEVEL=info - PARENT_FILENAME_PROMOTE=edit,raw restart: unless-stopped ``` -------------------------------- ### Error Handling Examples (Go) Source: https://github.com/majorfi/immich-stack/blob/main/docs/api-reference/stack-operations.md Demonstrates common error types encountered during API requests and responses, including request creation, body marshaling, API call failures, response body reading, and decoding errors. These examples are crucial for robust error management. ```go // Request errors fmt.Errorf("error creating request: %w", err) fmt.Errorf("error marshaling request body: %w", err) // Response errors fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body)) fmt.Errorf("error reading response body: %w", err) fmt.Errorf("error decoding response: %w", err) ```