Add Joplin, old Mac, and Fedora WiFi runbooks; simplify JA3 Whisky scripts and hotspot recovery.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ahauimix
2026-06-19 22:26:33 +03:00
parent 1938b7c743
commit 4bc9629a09
381 changed files with 3442 additions and 773 deletions

View File

@@ -0,0 +1,149 @@
#!/bin/sh
# Стабильный URL для Joplin на телефоне при Android-хотспоте: http://<подсеть>.100:8080
# Alias *.100 на en0 (DHCP primary не трогаем). LaunchAgent поднимает alias после reconnect.
#
# ./joplin-hotspot-alias.sh status
# ./joplin-hotspot-alias.sh ensure
#
# Passwordless: ./joplin-hotspot-alias-install-sudo.sh
set -e
CONFIG="${JOPLIN_WEBDAV_CONFIG:-$HOME/.config/joplin-webdav/env}"
WIFI_DEV="${WIFI_DEVICE:-en0}"
PORT="${JOPLIN_WEBDAV_PORT:-8080}"
LOG="$HOME/Library/Logs/joplin-webdav/alias.log"
ipv4_subnet() {
printf '%s\n' "$1" | awk -F. '{print $1"."$2"."$3}'
}
ipv4_last_octet() {
printf '%s\n' "$1" | awk -F. '{print $4}'
}
default_gateway() {
route -n get default 2>/dev/null | awk '/gateway:/{print $2; exit}'
}
load_config() {
if [ -f "$CONFIG" ]; then
# shellcheck disable=SC1090
. "$CONFIG"
fi
PORT="${JOPLIN_WEBDAV_PORT:-$PORT}"
}
joplin_phone_ip() {
load_config
gw="$(default_gateway 2>/dev/null || true)"
[ -n "$gw" ] || return 1
subnet="$(ipv4_subnet "$gw")"
if [ -n "${JOPLIN_STATIC_IP:-}" ]; then
last="$(ipv4_last_octet "$JOPLIN_STATIC_IP")"
else
last=100
fi
printf '%s\n' "${subnet}.${last}"
}
phone_url() {
ip="$(joplin_phone_ip 2>/dev/null || true)"
[ -n "$ip" ] || return 1
printf 'http://%s:%s\n' "$ip" "$PORT"
}
has_ip_on_dev() {
ip="$1"
dev="$2"
ifconfig "$dev" 2>/dev/null | grep -q "inet ${ip} "
}
log_msg() {
mkdir -p "$(dirname "$LOG")"
printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >>"$LOG"
}
run_priv() {
if [ "$(id -u)" -eq 0 ]; then
"$@"
else
sudo "$@"
fi
}
write_phone_url_env() {
url="$(phone_url 2>/dev/null || true)"
[ -n "$url" ] && [ -f "$CONFIG" ] || return 0
if grep -q '^JOPLIN_PHONE_URL=' "$CONFIG" 2>/dev/null; then
sed -i '' "s|^JOPLIN_PHONE_URL=.*|JOPLIN_PHONE_URL=$url|" "$CONFIG" 2>/dev/null \
|| sed -i "s|^JOPLIN_PHONE_URL=.*|JOPLIN_PHONE_URL=$url|" "$CONFIG"
else
printf 'JOPLIN_PHONE_URL=%s\n' "$url" >>"$CONFIG"
fi
}
cmd_status() {
load_config
target="$(joplin_phone_ip 2>/dev/null || true)"
primary="$(ipconfig getifaddr "$WIFI_DEV" 2>/dev/null || true)"
gw="$(default_gateway 2>/dev/null || true)"
url="$(phone_url 2>/dev/null || true)"
echo "mode: Android-хотспот (alias *.100)"
echo "device: $WIFI_DEV"
echo "primary: ${primary:-(none)}"
echo "gateway: ${gw:-(none)}"
echo "joplin IP: ${target:-(no gateway)}"
if [ -n "$target" ] && has_ip_on_dev "$target" "$WIFI_DEV"; then
echo "alias: OK"
elif [ -n "$target" ] && [ "$primary" = "$target" ]; then
echo "alias: OK (primary)"
elif [ -n "$target" ]; then
echo "alias: MISSING — телефон не достучится"
echo " fix: $0 ensure"
fi
if [ -n "$url" ]; then
echo ""
echo "URL на телефоне (работает с Android-хотспота):"
echo " $url"
echo ""
echo "⚠ http://*.local:8080 с телефона НЕ работает (Android не резолвит mDNS клиентов хотспота)"
fi
}
cmd_ensure() {
target="$(joplin_phone_ip 2>/dev/null || true)"
if [ -z "$target" ]; then
log_msg "skip: no gateway"
exit 0
fi
primary="$(ipconfig getifaddr "$WIFI_DEV" 2>/dev/null || true)"
if [ -z "$primary" ]; then
log_msg "skip: no primary IP"
exit 0
fi
if [ "$primary" = "$target" ] || has_ip_on_dev "$target" "$WIFI_DEV"; then
write_phone_url_env
exit 0
fi
log_msg "add alias $target on $WIFI_DEV (primary $primary)"
run_priv ifconfig "$WIFI_DEV" inet "$target" netmask 255.255.255.0 alias
write_phone_url_env
echo "alias OK: $target"
echo "URL на телефоне: $(phone_url)"
}
usage() {
echo "Usage: $(basename "$0") status|ensure" >&2
exit 1
}
case "${1:-ensure}" in
status) cmd_status ;;
ensure) cmd_ensure ;;
-h|--help) usage ;;
*) usage ;;
esac