app
Adom Chip Fetcher
Public Made by Adomby adom
Your whole parts library — manufacturer-grade chip CAD (symbol, footprint, 3D) one tap from your EDA tool.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
#!/bin/bash
# Watch the chip-fetcher pup window for CAPTCHA solve, click Submit, then poll
# the user's Downloads folder for the resulting ul_*.zip and pull+import it.
#
# Usage: cf-autowatch.sh <MPN>
#
# Race-safety: only one watcher can run at a time (PID lock at /tmp/cf-autowatch.lock).
# Tab-safety: confirms the pup tab URL still references this MPN before clicking Submit.
set -u
MPN="${1:?usage: cf-autowatch.sh <MPN>}"
LOCK=/tmp/cf-autowatch.lock
TIMEOUT=300
# Acquire lock — refuse if another watcher is still running on a live PID
if [ -e "$LOCK" ]; then
OLD_PID=$(cat "$LOCK" 2>/dev/null || echo "")
if [ -n "$OLD_PID" ] && kill -0 "$OLD_PID" 2>/dev/null; then
echo "ERROR: another watcher (pid $OLD_PID) is running. Stop it first."
exit 2
fi
rm -f "$LOCK"
fi
echo $$ > "$LOCK"
trap 'rm -f "$LOCK"' EXIT
# Loose base part for URL matching (e.g. MCF8316A1RRYR → MCF8316A)
MPN_BASE=$(echo "$MPN" | sed -E 's/(R|T)$//; s/[A-Z]+[0-9]*$//')
[ -z "$MPN_BASE" ] && MPN_BASE="$MPN"
START=$(date +%s)
echo "[$(date +%H:%M:%S)] watching CAPTCHA for ${MPN} (base: ${MPN_BASE})..."
# Step 1: poll CAPTCHA until solved AND the tab still shows our MPN
while [ $(($(date +%s) - START)) -lt $TIMEOUT ]; do
STATE=$(adom-desktop browser_eval "{\"sessionId\":\"chip-fetcher\",\"expr\":\"JSON.stringify({token: document.getElementById('g-recaptcha-response')?.value || '', url: location.href})\"}" 2>/dev/null \
| python3 -c "import sys,json;d=json.load(sys.stdin);print(d.get('result','{}'))" 2>/dev/null)
TOKEN_LEN=$(echo "$STATE" | python3 -c "import sys,json;print(len(json.loads(sys.stdin.read()).get('token','')))" 2>/dev/null)
URL=$(echo "$STATE" | python3 -c "import sys,json;print(json.loads(sys.stdin.read()).get('url',''))" 2>/dev/null)
if [ "${TOKEN_LEN:-0}" -gt 50 ]; then
# Tab-safety: URL must still reference our MPN base (case-insensitive)
if echo "$URL" | grep -qiE "$MPN_BASE|$MPN"; then
echo "[$(date +%H:%M:%S)] CAPTCHA solved (token len $TOKEN_LEN), URL matches → click Submit"
adom-desktop browser_eval '{"sessionId":"chip-fetcher","expr":"(()=>{const l=document.getElementById(\"SubmitLink\"); if(!l) return \"no link\"; l.classList.remove(\"disabled\"); l.click(); return \"clicked\"})()"}' >/dev/null
break
else
echo "[$(date +%H:%M:%S)] CAPTCHA solved but tab is at '$URL' — not our MPN ($MPN_BASE), aborting"
exit 3
fi
fi
sleep 2
done
# Step 2: watch Downloads for new download matching our MPN base.
# Match both UL (ul_*.zip) and Component Search Engine (LIB_*.zip) filename prefixes.
# desktop_watch_files only supports one glob at a time, so we poll the union via
# desktop_list_files (with mtime filter) on a short cadence.
echo "[$(date +%H:%M:%S)] watching Downloads for {ul_,LIB_}*.zip matching ${MPN_BASE}..."
SINCE=$(($(date +%s) - 30))
PULL_START=$(date +%s)
while [ $(($(date +%s) - PULL_START)) -lt 60 ]; do
for GLOB in "ul_*${MPN_BASE}*.zip" "LIB_*${MPN_BASE}*.zip"; do
LIST=$(adom-desktop desktop_list_files "{\"path\":\"%USERPROFILE%\\\\Downloads\",\"glob\":\"$GLOB\",\"modifiedSince\":$SINCE}" 2>/dev/null)
REMOTE=$(echo "$LIST" | python3 -c "
import sys, json
try:
d = json.load(sys.stdin)
f = (d.get('data', {}).get('files') or d.get('files') or [])
if f: print(f[0].get('path',''))
except: pass
")
if [ -n "$REMOTE" ]; then
echo "[$(date +%H:%M:%S)] desktop has $REMOTE"
/home/adom/project/chip-fetcher/target/release/chip-fetcher pull "$REMOTE" --mpn "$MPN" 2>&1 | head -10
exit 0
fi
done
sleep 2
done
echo "TIMEOUT waiting for download"
exit 1