Add three new automations: FreshRSS digest, birthday tracker, home stack monitor
- FreshRSS Smart Digest: Daily AI-ranked RSS summary at 7 AM - Birthday Tracker: Smart reminders for family birthdays with gift suggestions - Home Stack Monitor: Health checks every 15 min with self-healing attempts All cron jobs configured and ready to run. Telegram bot token saved to .env
This commit is contained in:
322
automations/birthday-tracker/birthday-tracker.sh
Executable file
322
automations/birthday-tracker/birthday-tracker.sh
Executable file
@@ -0,0 +1,322 @@
|
||||
#!/bin/bash
|
||||
# Birthday & Gift Tracker
|
||||
# Tracks family birthdays, sends reminders, suggests gifts
|
||||
# Checks daily at 9:00 AM
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
DATA_FILE="$SCRIPT_DIR/birthdays.json"
|
||||
LOG_FILE="$SCRIPT_DIR/reminder-log.json"
|
||||
source "$SCRIPT_DIR/../../.env" 2>/dev/null || true
|
||||
|
||||
TELEGRAM_CHAT="${TELEGRAM_CHAT:-1793951355}"
|
||||
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
|
||||
}
|
||||
|
||||
# Initialize data file if not exists
|
||||
init_data() {
|
||||
if [[ ! -f "$DATA_FILE" ]]; then
|
||||
log "Creating birthday database..."
|
||||
cat > "$DATA_FILE" << 'EOF'
|
||||
{
|
||||
"people": [
|
||||
{
|
||||
"name": "Grace Martin",
|
||||
"relationship": "Mum",
|
||||
"birthday": "06-02",
|
||||
"birth_year": 1951,
|
||||
"notes": "Cancer treatment ongoing - be extra thoughtful. Loves gardening, cooking, family time.",
|
||||
"gift_ideas": ["Flowers", "Gardening supplies", "Photo album", "Day spa voucher", "Home-cooked meal"],
|
||||
"past_gifts": []
|
||||
},
|
||||
{
|
||||
"name": "Harvey Martin",
|
||||
"relationship": "Dad",
|
||||
"birthday": "12-08",
|
||||
"birth_year": 1949,
|
||||
"notes": "Full-time carer for Grace. Needs respite/support. Loves tech gadgets, wine, coffee.",
|
||||
"gift_ideas": ["Ember mug", "Wine subscription", "Coffee beans", "Tech gadget", "Day out voucher"],
|
||||
"past_gifts": []
|
||||
},
|
||||
{
|
||||
"name": "Elizabeth Martin",
|
||||
"relationship": "Sister",
|
||||
"birthday": "09-11",
|
||||
"birth_year": 1990,
|
||||
"notes": "Vegan - avoid food gifts unless specifically vegan. Creative, environmentally conscious.",
|
||||
"gift_ideas": ["Vegan cookbook", "Eco-friendly products", "Plants", "Art supplies", "Experience gift"],
|
||||
"past_gifts": []
|
||||
},
|
||||
{
|
||||
"name": "Alexander",
|
||||
"relationship": "Godson/Cousin",
|
||||
"birthday": "07-XX",
|
||||
"birth_year": 2016,
|
||||
"notes": "8 years old (born July 2016). Loves games, books, LEGO, sports.",
|
||||
"gift_ideas": ["LEGO set", "Books", "Board games", "Sports equipment", "Science kit"],
|
||||
"past_gifts": []
|
||||
},
|
||||
{
|
||||
"name": "Mia Martin",
|
||||
"relationship": "Doggo 🐕",
|
||||
"birthday": "XX-XX",
|
||||
"notes": "14 years old, beloved geriatric girl. Treats, toys, comfy beds.",
|
||||
"gift_ideas": ["Premium dog treats", "Comfy bed", "New toy", "Grooming session"],
|
||||
"past_gifts": []
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"reminder_weeks_before": 2,
|
||||
"reminder_days_before": 7,
|
||||
"reminder_day_of": true
|
||||
}
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [[ ! -f "$LOG_FILE" ]]; then
|
||||
echo '{"sent_reminders": []}' > "$LOG_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get today's date in MM-DD format
|
||||
today_mmdd() {
|
||||
date +%m-%d
|
||||
}
|
||||
|
||||
# Get today's date in YYYY-MM-DD format
|
||||
today_yyyymmdd() {
|
||||
date +%Y-%m-%d
|
||||
}
|
||||
|
||||
# Calculate days until birthday
|
||||
days_until_birthday() {
|
||||
local bday_mmdd="$1"
|
||||
local today=$(today_yyyymmdd)
|
||||
local current_year=$(date +%Y)
|
||||
|
||||
# Handle missing day (XX)
|
||||
if [[ "$bday_mmdd" == *"XX"* ]]; then
|
||||
echo "unknown"
|
||||
return
|
||||
fi
|
||||
|
||||
local bday_this_year="$current_year-$bday_mmdd"
|
||||
local bday_ts=$(date -d "$bday_this_year" +%s 2>/dev/null || echo "0")
|
||||
local today_ts=$(date -d "$today" +%s)
|
||||
|
||||
# If birthday passed this year, calculate for next year
|
||||
if ((bday_ts < today_ts)); then
|
||||
((current_year++))
|
||||
bday_this_year="$current_year-$bday_mmdd"
|
||||
bday_ts=$(date -d "$bday_this_year" +%s)
|
||||
fi
|
||||
|
||||
local diff=$(( (bday_ts - today_ts) / 86400 ))
|
||||
echo "$diff"
|
||||
}
|
||||
|
||||
# Check if reminder already sent today
|
||||
reminder_sent() {
|
||||
local person="$1"
|
||||
local type="$2"
|
||||
local today=$(today_yyyymmdd)
|
||||
|
||||
grep -q "\"$today-$person-$type\"" "$LOG_FILE" 2>/dev/null
|
||||
}
|
||||
|
||||
# Log that reminder was sent
|
||||
log_reminder() {
|
||||
local person="$1"
|
||||
local type="$2"
|
||||
local today=$(today_yyyymmdd)
|
||||
|
||||
# Add to log
|
||||
local temp_file=$(mktemp)
|
||||
jq --arg key "$today-$person-$type" '.sent_reminders += [$key]' "$LOG_FILE" > "$temp_file"
|
||||
mv "$temp_file" "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Clean old reminders from log (keep last 90 days)
|
||||
cleanup_log() {
|
||||
local cutoff=$(date -d "90 days ago" +%Y-%m-%d)
|
||||
local temp_file=$(mktemp)
|
||||
|
||||
jq --arg cutoff "$cutoff" '.sent_reminders |= map(select(. > $cutoff or length < 10))' "$LOG_FILE" > "$temp_file" 2>/dev/null || true
|
||||
mv "$temp_file" "$LOG_FILE" 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Send Telegram message
|
||||
send_telegram() {
|
||||
local message="$1"
|
||||
|
||||
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"chat_id\": \"$TELEGRAM_CHAT\",
|
||||
\"text\": \"$message\",
|
||||
\"parse_mode\": \"Markdown\"
|
||||
}" > /dev/null || {
|
||||
log "ERROR: Failed to send Telegram message"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
# Generate gift suggestions text
|
||||
gift_suggestions() {
|
||||
local ideas=$(echo "$1" | jq -r '.gift_ideas | join(", ")')
|
||||
local notes=$(echo "$1" | jq -r '.notes')
|
||||
local past=$(echo "$1" | jq -r '.past_gifts | if length > 0 then "Past gifts: " + join(", ") else "" end')
|
||||
|
||||
local text="💡 *Gift Ideas:* $ideas"
|
||||
if [[ -n "$past" && "$past" != "Past gifts: " ]]; then
|
||||
text+="\n🎁 $past"
|
||||
fi
|
||||
text+="\n📝 *Notes:* $notes"
|
||||
|
||||
echo "$text"
|
||||
}
|
||||
|
||||
# Check birthdays and send reminders
|
||||
check_birthdays() {
|
||||
log "Checking birthdays..."
|
||||
|
||||
local people=$(jq -c '.people[]' "$DATA_FILE")
|
||||
local settings=$(jq '.settings' "$DATA_FILE")
|
||||
local weeks_before=$(echo "$settings" | jq -r '.reminder_weeks_before')
|
||||
local days_before=$(echo "$settings" | jq -r '.reminder_days_before')
|
||||
|
||||
local reminders_sent=0
|
||||
|
||||
while IFS= read -r person; do
|
||||
local name=$(echo "$person" | jq -r '.name')
|
||||
local relationship=$(echo "$person" | jq -r '.relationship')
|
||||
local birthday=$(echo "$person" | jq -r '.birthday')
|
||||
local birth_year=$(echo "$person" | jq -r '.birth_year // empty')
|
||||
|
||||
# Skip if no specific date
|
||||
if [[ "$birthday" == *"XX"* ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
local days_until=$(days_until_birthday "$birthday")
|
||||
|
||||
# Calculate age if birth year known
|
||||
local age_text=""
|
||||
if [[ -n "$birth_year" && "$birth_year" != "null" ]]; then
|
||||
local current_year=$(date +%Y)
|
||||
local age=$((current_year - birth_year))
|
||||
if ((days_until < 365)); then
|
||||
age_text=" (turning $age)"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check reminders
|
||||
local should_remind=false
|
||||
local reminder_type=""
|
||||
local message=""
|
||||
|
||||
if ((days_until == 0)); then
|
||||
reminder_type="today"
|
||||
if ! reminder_sent "$name" "$reminder_type"; then
|
||||
message="🎂 *Birthday Today!*\n\n*$name* — your $relationship$age_text\n\nDon't forget to call/message them! 💝"
|
||||
local gifts=$(gift_suggestions "$person")
|
||||
message+="\n\n$gifts"
|
||||
should_remind=true
|
||||
fi
|
||||
elif ((days_until == days_before)); then
|
||||
reminder_type="week"
|
||||
if ! reminder_sent "$name" "$reminder_type"; then
|
||||
message="📅 *Birthday Reminder*\n\n*$name* — your $relationship$age_text\nBirthday in *$days_until days* ($birthday)\n\nTime to plan something! 🎁"
|
||||
local gifts=$(gift_suggestions "$person")
|
||||
message+="\n\n$gifts"
|
||||
should_remind=true
|
||||
fi
|
||||
elif ((days_until == weeks_before * 7)); then
|
||||
reminder_type="twoweeks"
|
||||
if ! reminder_sent "$name" "$reminder_type"; then
|
||||
message="📅 *Upcoming Birthday*\n\n*$name* — your $relationship$age_text\nBirthday in *$days_until days* ($birthday)\n\nStart thinking about gifts! 🎁"
|
||||
local gifts=$(gift_suggestions "$person")
|
||||
message+="\n\n$gifts"
|
||||
should_remind=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$should_remind" == true ]]; then
|
||||
log "Sending $reminder_type reminder for $name"
|
||||
send_telegram "$message"
|
||||
log_reminder "$name" "$reminder_type"
|
||||
((reminders_sent++))
|
||||
fi
|
||||
|
||||
done <<< "$people"
|
||||
|
||||
log "Sent $reminders_sent reminders"
|
||||
}
|
||||
|
||||
# Add/update a person (can be called manually)
|
||||
add_person() {
|
||||
local name="$1"
|
||||
local relationship="$2"
|
||||
local birthday="$3" # MM-DD format
|
||||
local notes="$4"
|
||||
|
||||
local temp_file=$(mktemp)
|
||||
jq --arg name "$name" \
|
||||
--arg rel "$relationship" \
|
||||
--arg bday "$birthday" \
|
||||
--arg notes "$notes" \
|
||||
'.people += [{"name": $name, "relationship": $rel, "birthday": $bday, "notes": $notes, "gift_ideas": [], "past_gifts": []}]' \
|
||||
"$DATA_FILE" > "$temp_file"
|
||||
mv "$temp_file" "$DATA_FILE"
|
||||
|
||||
log "Added $name to birthday tracker"
|
||||
}
|
||||
|
||||
# Log a past gift
|
||||
log_gift() {
|
||||
local name="$1"
|
||||
local gift="$2"
|
||||
local year="${3:-$(date +%Y)}"
|
||||
|
||||
local temp_file=$(mktemp)
|
||||
jq --arg name "$name" \
|
||||
--arg gift "$gift ($year)" \
|
||||
'(.people[] | select(.name == $name)).past_gifts += [$gift]' \
|
||||
"$DATA_FILE" > "$temp_file"
|
||||
mv "$temp_file" "$DATA_FILE"
|
||||
|
||||
log "Logged gift for $name: $gift"
|
||||
}
|
||||
|
||||
# Main
|
||||
main() {
|
||||
case "${1:-check}" in
|
||||
check)
|
||||
init_data
|
||||
check_birthdays
|
||||
cleanup_log
|
||||
;;
|
||||
add)
|
||||
add_person "$2" "$3" "$4" "$5"
|
||||
;;
|
||||
gift)
|
||||
log_gift "$2" "$3" "$4"
|
||||
;;
|
||||
list)
|
||||
jq '.people[] | {name, relationship, birthday, notes}' "$DATA_FILE"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [check|add|gift|list]"
|
||||
echo " check - Run daily birthday check"
|
||||
echo " add 'Name' 'Relationship' 'MM-DD' 'Notes' - Add new person"
|
||||
echo " gift 'Name' 'Gift description' [year] - Log a gift given"
|
||||
echo " list - Show all tracked birthdays"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user