Use with caution and adopt to your needs. Its still work in progress!


#!/bin/bash

# Variables for the script
phpinterpreter="php -d memory_limit=1G"
pathtoconsole="../code/bin/console"
lockfile="/tmp/cronjob.lock"

# Email sending settings
emails_per_batch=14  # Number of emails per batch and rate limit (14 emails/sec)

# Limits for other Mautic commands
segments_update_limit=900
campaigns_rebuild_limit=300
broadcasts_send_limit=800
import_limit=500

# Loop control
max_loops=60
current_loop=0
milliseconds_per_second=1000

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Locking mechanism
if [ -f "$lockfile" ]; then
    # Colored output in the console
    echo "${RED}Script is already running.${NC}"
    
    # No color codes in the log file
    echo "Script is already running." >> "$log_file"
    exit 1
fi
touch "$lockfile"
trap 'rm -f "$lockfile"; exit' INT TERM EXIT

# Log file for the current run
log_file="$log_dir/$(date +'%Y%m%d_%H%M%S').log"

# Function to execute Mautic commands
execute_command() {
    local command="$1"
    
    # Colored output in the console (stdout)
    echo "${BLUE}Executing: $command${NC}"
    
    # Output without colors in the log file
    echo "Executing: $command" >> "$log_file"
    
    # Execute command and capture both stdout and stderr
    output=$($phpinterpreter $pathtoconsole $command 2>&1)
    
    # Colored output in the console (stdout and stderr)
    if [ $? -eq 0 ]; then
        echo "${GREEN}$output${NC}"
    else
        echo "${RED}$output${NC}" >&2
    fi
    
    # Output without colors in the log file
    echo "$output" >> "$log_file"
    
    return $?  # Return command exit status
}

# Calculate dynamic sleep time in microseconds
calculate_sleep_time() {
    local duration=$1  # Duration in milliseconds
    local target_duration=$((milliseconds_per_second))  # Target duration in milliseconds for 14 emails per second
    local sleep_time=$(( (target_duration - duration) * 1000 ))  # Convert to microseconds
    echo "$sleep_time"
}

# Execute other commands before the email sending loop
execute_command "mautic:segments:update --batch-limit=$segments_update_limit"
execute_command "mautic:campaigns:rebuild --batch-limit=$campaigns_rebuild_limit"
execute_command "mautic:campaigns:trigger"
execute_command "mautic:broadcasts:send --batch=$broadcasts_send_limit"

# Loop for sending emails
while [ $current_loop -lt $max_loops ]
do
    # Increment the loop counter
    current_loop=$((current_loop+1))

    # Capture start time in milliseconds
    start_time=$(date +%s%3N)
    
    # Execute the command to send emails
    output=$(execute_command "messenger:consume email --limit=$emails_per_batch --time-limit=1")
    
    # Capture end time in milliseconds
    end_time=$(date +%s%3N)
    
    # Calculate the duration of the command in milliseconds
    duration=$((end_time - start_time))

    # Calculate the sleep time to maintain the rate limit
    sleep_time=$(calculate_sleep_time $duration)

    # Ensure the command was successful
    if [ $? -ne 0 ]; then
        echo "${RED}Error during email sending. Exiting loop.${NC}" >&2
        echo "Error during email sending. Exiting loop." >> "$log_file"
        break
    fi
    
    # If the number of sent emails is less than the batch limit, exit the loop
    sent_emails=$(echo "$output" | grep -oP '\b\d+(?= emails sent)' || echo 0)
    if [ "$sent_emails" -lt "$emails_per_batch" ]; then
        echo "${RED}Less than $emails_per_batch emails sent. Exiting loop.${NC}"
        echo "Less than $emails_per_batch emails sent. Exiting loop." >> "$log_file"
        break
    fi

    # Pause for the calculated sleep time
    if [ "$sleep_time" -gt 0 ]; then
        usleep "$sleep_time"
    fi
done

# Execute additional Mautic commands
execute_command "mautic:unusedip:delete"
execute_command "mautic:import --limit=$import_limit"
execute_command "mautic:webhooks:process"
execute_command "mautic:reports:scheduler"

# Remove the lock file at the end
rm -f "$lockfile"