#!/bin/bash # # activity-scan.sh - Scan repos and output activity feed JSON # Usage: ./activity-scan.sh [REPOS_DIR] # # Output format matches activity-feed.json spec for maicivy CV # set -e REPOS_DIR="${1:-/home/debian}" # Repos to showcase on CV SHOWCASE_REPOS="maicivy vba-mcp-server vba-mcp-monorepo groveengine confluent seogeneratorserver civjdr videotoMP3Transcriptor freelance-dashboard freelance-notify timetrack-pro CTPL" # GitHub URLs mapping (repo_name -> github_url) declare -A GITHUB_URLS=( ["maicivy"]="https://github.com/AlexisTrouve/maicivy" ["confluent"]="https://github.com/AlexisTrouve/confluent" ["groveengine"]="https://github.com/AlexisTrouve/GroveEngine" ["vba-mcp-server"]="https://github.com/AlexisTrouve/vba-mcp-server" ["vba-mcp-monorepo"]="https://github.com/AlexisTrouve/vba-mcp-server" ["timetrack-pro"]="https://github.com/AlexisTrouve/timetrack-pro" ["freelance-dashboard"]="https://github.com/AlexisTrouve/freelance-dashboard" ["freelance-notify"]="https://github.com/AlexisTrouve/freelance-notify" ["RedditSaveSaver"]="https://github.com/AlexisTrouve/RedditSaveSaver" ["CTPL"]="https://github.com/AlexisTrouve/CTPL" ) # Category mapping declare -A CATEGORIES=( ["maicivy"]="WIP" ["vba-mcp-server"]="WIP" ["vba-mcp-monorepo"]="WIP" ["groveengine"]="WIP" ["confluent"]="WIP" ["seogeneratorserver"]="WIP" ["civjdr"]="CONSTANT" ["videotoMP3Transcriptor"]="DONE" ["freelance-dashboard"]="WIP" ["freelance-notify"]="WIP" ["timetrack-pro"]="WIP" ["CTPL"]="DONE" ) # Escape JSON string json_escape() { printf '%s' "$1" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read())[1:-1])' } # Get languages from file extensions get_languages() { local repo_dir="$1" cd "$repo_dir" 2>/dev/null || return git ls-files 2>/dev/null | sed 's/.*\.//' | sort | uniq -c | sort -rn | head -5 | while read count ext; do case "$ext" in go) echo "Go" ;; ts|tsx) echo "TypeScript" ;; js|jsx) echo "JavaScript" ;; py) echo "Python" ;; rs) echo "Rust" ;; cpp|cc|cxx|hpp) echo "C++" ;; c|h) echo "C" ;; rb) echo "Ruby" ;; java) echo "Java" ;; sh|bash) echo "Shell" ;; sql) echo "SQL" ;; *) ;; esac done | sort -u | head -4 | tr '\n' ',' | sed 's/,$//' } # Start JSON output echo '{' echo ' "last_updated": "'$(date -Iseconds)'",' echo ' "projects": [' first=true total_commits_30d=0 active_count=0 for repo_path in "$REPOS_DIR"/*/; do [ -d "$repo_path/.git" ] || continue name=$(basename "$repo_path") cd "$repo_path" 2>/dev/null || continue # Get commit counts commits_7d=$(git log --since="7 days ago" --oneline 2>/dev/null | wc -l | tr -d ' ') commits_30d=$(git log --since="30 days ago" --oneline 2>/dev/null | wc -l | tr -d ' ') total_commits_30d=$((total_commits_30d + commits_30d)) [ "$commits_30d" -gt 0 ] && active_count=$((active_count + 1)) # Check if showcase showcase="false" [[ " $SHOWCASE_REPOS " =~ " $name " ]] && showcase="true" # Get category category="${CATEGORIES[$name]:-WIP}" # Get URLs github_url="${GITHUB_URLS[$name]:-null}" [ "$github_url" != "null" ] && github_url="\"$github_url\"" gitea_remote=$(git remote get-url origin 2>/dev/null || echo "") if [[ "$gitea_remote" == *"git.etheryale.com"* ]]; then repo_url="\"https://git.etheryale.com/StillHammer/$name\"" else repo_url="null" fi # Get description from README or empty description="" if [ -f "README.md" ]; then description=$(head -20 README.md | grep -E "^[A-Za-z]" | head -1 | cut -c1-150) fi description=$(json_escape "$description") # Get languages languages=$(get_languages "$repo_path") # Get recent commits (last 3) recent_commits="" while IFS='|' read -r sha msg date author; do [ -z "$sha" ] && continue msg=$(json_escape "$msg") [ -n "$recent_commits" ] && recent_commits="$recent_commits," recent_commits="$recent_commits{\"sha\":\"$sha\",\"message\":\"$msg\",\"date\":\"$date\",\"author\":\"$author\"}" done < <(git log -3 --format="%h|%s|%aI|%an" 2>/dev/null) # Output JSON $first || echo ',' first=false cat <