- workspace: capmetro-monitor, github-notifications, model-selector - workspace-security: vt-monitor, monitor-unauthorized - workspace-home: cron-manager, monitor-unauthorized - extensions: vt-sentinel (VT-Sentinel plugin) Includes sync.sh for pull/push, README, AGENTS.md, .gitignore.
105 lines
2.8 KiB
Bash
Executable File
105 lines
2.8 KiB
Bash
Executable File
#!/bin/bash
|
|
# GitHub Notifications Checker
|
|
# Filters PRs and releases, tracks state, returns JSON summary
|
|
|
|
set -e
|
|
|
|
STATE_FILE="${STATE_FILE:-memory/github-check-state.json}"
|
|
WORKSPACE="${WORKSPACE:-/home/node/.openclaw/workspace}"
|
|
cd "$WORKSPACE"
|
|
|
|
# Initialize state file if missing
|
|
if [ ! -f "$STATE_FILE" ]; then
|
|
mkdir -p "$(dirname "$STATE_FILE")"
|
|
echo '{"lastCheck":"1970-01-01T00:00:00Z","seenPRs":[],"seenReleases":[]}' > "$STATE_FILE"
|
|
fi
|
|
|
|
# Load last check time
|
|
LAST_CHECK=$(jq -r '.lastCheck' "$STATE_FILE")
|
|
NOW=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
# Fetch notifications (PRs only)
|
|
PR_DATA=$(gh api 'notifications?all=true&per_page=100' 2>&1)
|
|
|
|
if [ $? -ne 0 ]; then
|
|
echo '{"error":"GitHub API failed","details":"'"${PR_DATA//\"/\\\"}"'"}' | jq .
|
|
exit 1
|
|
fi
|
|
|
|
# Filter PRs where user is mentioned or author
|
|
FILTERED_PRS=$(echo "$PR_DATA" | jq -r '[
|
|
.[] |
|
|
select(.subject.type == "PullRequest") |
|
|
select(.reason == "mention" or .reason == "author" or .reason == "review_requested") |
|
|
{
|
|
repo: .repository.full_name,
|
|
title: .subject.title,
|
|
url: .subject.url,
|
|
updated: .updated_at,
|
|
reason: .reason,
|
|
id: (.repository.full_name + "#" + .subject.title)
|
|
}
|
|
]')
|
|
|
|
# Filter releases
|
|
RELEASE_DATA=$(echo "$PR_DATA" | jq -r '[
|
|
.[] |
|
|
select(.subject.type == "Release") |
|
|
{
|
|
repo: .repository.full_name,
|
|
title: .subject.title,
|
|
updated: .updated_at,
|
|
id: (.repository.full_name + "@" + .subject.title)
|
|
}
|
|
]')
|
|
|
|
# Filter major releases (v*.0.0) + ALL Mirrowel/LLM-API-Key-Proxy releases
|
|
FILTERED_RELEASES=$(echo "$RELEASE_DATA" | jq -r '[
|
|
.[] |
|
|
select(
|
|
(.repo == "Mirrowel/LLM-API-Key-Proxy") or
|
|
(.title | test("^v[0-9]+\\.0\\.0"))
|
|
) |
|
|
select(.title | test("(rc|pre|beta|alpha|nightly)") | not)
|
|
]')
|
|
|
|
# Load seen items
|
|
SEEN_PRS=$(jq -r '.seenPRs // []' "$STATE_FILE")
|
|
SEEN_RELEASES=$(jq -r '.seenReleases // []' "$STATE_FILE")
|
|
|
|
# Find new items
|
|
NEW_PRS=$(echo "$FILTERED_PRS" | jq --argjson seen "$SEEN_PRS" '[
|
|
.[] | select(.id as $id | $seen | index($id) | not)
|
|
]')
|
|
|
|
NEW_RELEASES=$(echo "$FILTERED_RELEASES" | jq --argjson seen "$SEEN_RELEASES" '[
|
|
.[] | select(.id as $id | $seen | index($id) | not)
|
|
]')
|
|
|
|
# Count new items
|
|
NEW_PR_COUNT=$(echo "$NEW_PRS" | jq 'length')
|
|
NEW_RELEASE_COUNT=$(echo "$NEW_RELEASES" | jq 'length')
|
|
|
|
# Update state
|
|
ALL_PR_IDS=$(echo "$FILTERED_PRS" | jq -r '[.[].id]')
|
|
ALL_RELEASE_IDS=$(echo "$FILTERED_RELEASES" | jq -r '[.[].id]')
|
|
|
|
jq -n \
|
|
--arg now "$NOW" \
|
|
--argjson prIds "$ALL_PR_IDS" \
|
|
--argjson relIds "$ALL_RELEASE_IDS" \
|
|
'{lastCheck:$now, seenPRs:$prIds, seenReleases:$relIds}' \
|
|
> "$STATE_FILE"
|
|
|
|
# Output result
|
|
if [ "$NEW_PR_COUNT" -eq 0 ] && [ "$NEW_RELEASE_COUNT" -eq 0 ]; then
|
|
echo '{"hasNew":false}'
|
|
exit 0
|
|
fi
|
|
|
|
# Return new items
|
|
jq -n \
|
|
--argjson prs "$NEW_PRS" \
|
|
--argjson releases "$NEW_RELEASES" \
|
|
'{hasNew:true, newPRs:$prs, newReleases:$releases}'
|