fix(scan): Use native JPEG stream for scan-book and img2pdf for 100% robust multi-page assembly
This commit is contained in:
@@ -1,18 +1,161 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
cd repos/dnes.git
|
# dnes: Daily plan tracker and journal of done things with anti-recursion protection
|
||||||
git init
|
set -euo pipefail
|
||||||
|
|
||||||
cat << 'EOF' > ./02_observator/mpd_drift_gate.patch
|
PLAN_DIR="$HOME/src/dnes"
|
||||||
diff --git a/main.go b/main.go
|
PLAN_FILE="$PLAN_DIR/plan.md"
|
||||||
index a2f3b4c..c5d6e7f 100644
|
JOURNAL_FILE="$PLAN_DIR/journal.md"
|
||||||
--- a/main.go
|
LOCK_FILE="/tmp/dnes-sync.lock"
|
||||||
+++ b/main.go
|
LOG_DIR="$HOME/.local/state/dnes"
|
||||||
@@ -12,3 +12,3 @@ const (
|
mkdir -p "$LOG_DIR"
|
||||||
- DriftGate = 500 * time.Millisecond
|
|
||||||
+ DriftGate = 300 * time.Millisecond
|
|
||||||
MpdPort = "6600"
|
|
||||||
)
|
|
||||||
EOF
|
|
||||||
|
|
||||||
git add .
|
# Prevent recursive self-invocation
|
||||||
git commit -m "init: kompletní struktura /dnes, vyčištěná administrativa a mpd patch"
|
if [ "${DNES_IN_SUBPROCESS:-0}" = "1" ]; then
|
||||||
|
echo "Warning: Nested dnes execution detected. Aborting recursion." >&2
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
export DNES_IN_SUBPROCESS=1
|
||||||
|
|
||||||
|
cmd_done() {
|
||||||
|
local text="${*:-}"
|
||||||
|
if [ -z "$text" ]; then
|
||||||
|
echo "Usage: dnes done <description of completed task>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local today
|
||||||
|
today=$(date +%Y-%m-%d)
|
||||||
|
local time_now
|
||||||
|
time_now=$(date +%H:%M)
|
||||||
|
|
||||||
|
# Ensure journal file exists with header
|
||||||
|
if [ ! -f "$JOURNAL_FILE" ]; then
|
||||||
|
echo "# Journal / Hotovo" > "$JOURNAL_FILE"
|
||||||
|
echo "" >> "$JOURNAL_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if today's section exists; if not, create it
|
||||||
|
if ! grep -q "^## $today" "$JOURNAL_FILE" 2>/dev/null; then
|
||||||
|
echo "" >> "$JOURNAL_FILE"
|
||||||
|
echo "## $today" >> "$JOURNAL_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Append entry under today
|
||||||
|
echo "- [$time_now] $text" >> "$JOURNAL_FILE"
|
||||||
|
echo "Logged to journal: [$time_now] $text"
|
||||||
|
|
||||||
|
# Trigger Syncthing rescan so peers receive the entry immediately
|
||||||
|
local api_key
|
||||||
|
api_key=$(grep -oPm1 "(?<=<apikey>)[^<]+" "$HOME/.config/syncthing/config.xml" 2>/dev/null || true)
|
||||||
|
if [ -n "$api_key" ]; then
|
||||||
|
curl -s -f -X POST -H "X-API-Key: $api_key" "http://127.0.0.1:8384/rest/db/scan?folder=dnes" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_cron() {
|
||||||
|
exec 200>"$LOCK_FILE"
|
||||||
|
if ! flock -n 200; then
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - Sync/cron already running. Skipping."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - Starting 23:45 nightly archive..."
|
||||||
|
cd "$PLAN_DIR"
|
||||||
|
|
||||||
|
# Git checkpoint
|
||||||
|
git add plan.md journal.md .gitignore .stignore 2>/dev/null || true
|
||||||
|
if ! git diff-index --quiet HEAD -- 2>/dev/null; then
|
||||||
|
local today
|
||||||
|
today=$(date +%Y-%m-%d)
|
||||||
|
git commit -m "archive ($today): nightly 23:45 snapshot"
|
||||||
|
git push origin main || echo "Warning: git push failed (remote offline or ahead)"
|
||||||
|
echo "Nightly Git checkpoint completed."
|
||||||
|
else
|
||||||
|
echo "No changes to commit."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Trigger Syncthing folder scan to ensure all peers have identical state
|
||||||
|
local api_key
|
||||||
|
api_key=$(grep -oPm1 "(?<=<apikey>)[^<]+" "$HOME/.config/syncthing/config.xml" 2>/dev/null || true)
|
||||||
|
if [ -n "$api_key" ]; then
|
||||||
|
curl -s -f -X POST -H "X-API-Key: $api_key" "http://127.0.0.1:8384/rest/db/scan?folder=dnes" >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - Nightly archive finished successfully."
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_view() {
|
||||||
|
if [ -f "$PLAN_FILE" ]; then
|
||||||
|
cat "$PLAN_FILE"
|
||||||
|
fi
|
||||||
|
if [ -f "$JOURNAL_FILE" ]; then
|
||||||
|
local today
|
||||||
|
today=$(date +%Y-%m-%d)
|
||||||
|
if grep -q "^## $today" "$JOURNAL_FILE" 2>/dev/null; then
|
||||||
|
echo ""
|
||||||
|
echo "---"
|
||||||
|
echo "### Dnes hotovo ($today):"
|
||||||
|
awk "/^## $today/{flag=1; next} /^## /{flag=0} flag" "$JOURNAL_FILE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
done|d|log)
|
||||||
|
shift
|
||||||
|
cmd_done "$@"
|
||||||
|
;;
|
||||||
|
journal|j)
|
||||||
|
cat "$JOURNAL_FILE" 2>/dev/null || echo "No journal.md found"
|
||||||
|
;;
|
||||||
|
plan|p)
|
||||||
|
cat "$PLAN_FILE" 2>/dev/null || echo "No plan.md found"
|
||||||
|
;;
|
||||||
|
edit|e)
|
||||||
|
${EDITOR:-vim} "$PLAN_FILE"
|
||||||
|
;;
|
||||||
|
edit-journal|ej)
|
||||||
|
${EDITOR:-vim} "$JOURNAL_FILE"
|
||||||
|
;;
|
||||||
|
status|sync)
|
||||||
|
if command -v sync-scope >/dev/null 2>&1; then
|
||||||
|
sync-scope status
|
||||||
|
elif [ -x "$HOME/bin/sync-scope" ]; then
|
||||||
|
"$HOME/bin/sync-scope" status
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
cron)
|
||||||
|
cmd_cron
|
||||||
|
;;
|
||||||
|
git|commit)
|
||||||
|
shift || true
|
||||||
|
MSG="${*:-dnes update $(date +%s)}"
|
||||||
|
cd "$PLAN_DIR"
|
||||||
|
git add plan.md journal.md .gitignore .stignore 2>/dev/null || true
|
||||||
|
if ! git diff-index --quiet HEAD -- 2>/dev/null; then
|
||||||
|
git commit -m "$MSG"
|
||||||
|
git push origin main
|
||||||
|
echo "Git checkpoint pushed."
|
||||||
|
else
|
||||||
|
echo "Working tree clean. Nothing to commit."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
help|-h|--help)
|
||||||
|
echo "dnes - Daily plan tracker & journal of done things"
|
||||||
|
echo ""
|
||||||
|
echo "Usage: dnes [command]"
|
||||||
|
echo ""
|
||||||
|
echo "Commands:"
|
||||||
|
echo " (no args) Show plan & today's completed journal items"
|
||||||
|
echo " done <text> Log completed task to journal.md with timestamp"
|
||||||
|
echo " journal, j Display complete journal.md"
|
||||||
|
echo " plan, p Display plan.md"
|
||||||
|
echo " edit, e Edit plan.md in \$EDITOR"
|
||||||
|
echo " edit-journal, ej Edit journal.md in \$EDITOR"
|
||||||
|
echo " status Show multi-device sync status"
|
||||||
|
echo " git [msg] Save manual Git commit checkpoint & push"
|
||||||
|
echo " cron Run nightly 23:45 archive routine"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
cmd_view
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|||||||
+59
-7
@@ -1,11 +1,12 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
moonphase.py - Calculate Lunar Phase
|
moonphase.py - Calculate Lunar Phase
|
||||||
Author: Sean B. Palmer, inamidst.com
|
Author: Sean B. Palmer, inamidst.com
|
||||||
|
Enhanced for Samizdat & Observatoř Cybernetics
|
||||||
Cf. http://en.wikipedia.org/wiki/Lunar_phase#Lunar_phase_calculation
|
Cf. http://en.wikipedia.org/wiki/Lunar_phase#Lunar_phase_calculation
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import math, decimal, datetime
|
import math, decimal, datetime, sys
|
||||||
dec = decimal.Decimal
|
dec = decimal.Decimal
|
||||||
|
|
||||||
def position(now=None):
|
def position(now=None):
|
||||||
@@ -32,12 +33,63 @@ def phase(pos):
|
|||||||
7: "Waning Crescent"
|
7: "Waning Crescent"
|
||||||
}[int(index) & 7]
|
}[int(index) & 7]
|
||||||
|
|
||||||
def main():
|
def phase_cz(pos):
|
||||||
pos = position()
|
index = (pos * dec(8)) + dec("0.5")
|
||||||
phasename = phase(pos)
|
index = math.floor(index)
|
||||||
|
return {
|
||||||
|
0: "Nov (New Moon)",
|
||||||
|
1: "Dorůstající srpek (Waxing Crescent)",
|
||||||
|
2: "První čtvrť (First Quarter)",
|
||||||
|
3: "Dorůstající Měsíc (Waxing Gibbous)",
|
||||||
|
4: "Úplněk (Full Moon)",
|
||||||
|
5: "Ubývající Měsíc (Waning Gibbous)",
|
||||||
|
6: "Poslední čtvrť (Last Quarter)",
|
||||||
|
7: "Ubývající srpek (Waning Crescent)"
|
||||||
|
}[int(index) & 7]
|
||||||
|
|
||||||
roundedpos = round(float(pos), 3)
|
def illumination(pos):
|
||||||
print "%s (%s)" % (phasename, roundedpos)
|
# Approximate illumination percentage
|
||||||
|
# pos is 0 at New Moon, 0.5 at Full Moon, 1.0 at New Moon
|
||||||
|
p = float(pos)
|
||||||
|
return round((1 - math.cos(p * 2 * math.pi)) / 2 * 100, 1)
|
||||||
|
|
||||||
|
def moon_ascii(pos):
|
||||||
|
index = int((pos * dec(8)) + dec("0.5")) & 7
|
||||||
|
icons = ["🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"]
|
||||||
|
return icons[index]
|
||||||
|
|
||||||
|
def get_moon_metrics(now=None):
|
||||||
|
if now is None:
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
pos = position(now)
|
||||||
|
p_name = phase(pos)
|
||||||
|
p_name_cz = phase_cz(pos)
|
||||||
|
illum = illumination(pos)
|
||||||
|
icon = moon_ascii(pos)
|
||||||
|
lunation_num = int(math.floor(float((now - datetime.datetime(2001, 1, 1)).days) / 29.53058867)) + 300 # relative count
|
||||||
|
roundedpos = round(float(pos), 4)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"datetime": now.isoformat(),
|
||||||
|
"position": roundedpos,
|
||||||
|
"phase_en": p_name,
|
||||||
|
"phase_cz": p_name_cz,
|
||||||
|
"illumination_pct": illum,
|
||||||
|
"icon": icon,
|
||||||
|
"lunation_est": lunation_num,
|
||||||
|
"summary": f"{icon} {p_name_cz} | Phase: {roundedpos} | Illumination: {illum}%"
|
||||||
|
}
|
||||||
|
|
||||||
|
def main():
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
m = get_moon_metrics(now)
|
||||||
|
if len(sys.argv) > 1 and sys.argv[1] == "--json":
|
||||||
|
import json
|
||||||
|
print(json.dumps(m, indent=2))
|
||||||
|
elif len(sys.argv) > 1 and sys.argv[1] == "--raw":
|
||||||
|
print(m["position"])
|
||||||
|
else:
|
||||||
|
print(m["summary"])
|
||||||
|
|
||||||
if __name__=="__main__":
|
if __name__=="__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -49,35 +49,30 @@ while true; do
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
PAGE_FILE="$OUT_DIR/page_$(printf '%04d' $PAGE).pdf"
|
PAGE_FILE="$OUT_DIR/page_$(printf '%04d' $PAGE).jpg"
|
||||||
printf " [+] Skenuji stranu %03d (300 DPI True Gray)... " "$PAGE"
|
printf " [+] Skenuji stranu %03d (300 DPI True Gray)... " "$PAGE"
|
||||||
|
|
||||||
# Execute scan on bazina via USB
|
# Execute scan on bazina via USB (native JPEG output for zero-loss lossless packaging)
|
||||||
ssh bazina "scanimage -d 'brother4:bus1;dev8' --resolution 300 --mode 'True Gray' -x 210 -y 297 --format=pdf" > "$PAGE_FILE" 2>/dev/null || {
|
ssh bazina "scanimage -d 'brother4:bus1;dev8' --resolution 300 --mode 'True Gray' -x 210 -y 297 --format=jpeg" > "$PAGE_FILE" 2>/dev/null || {
|
||||||
# Fallback to network airscan if USB re-enumerated
|
# Fallback to network airscan if USB re-enumerated
|
||||||
scanimage -d "airscan:w0:Brother DCP-J4120DW" --resolution 300 --mode "Gray" -x 210 -y 297 --format=pdf > "$PAGE_FILE" 2>/dev/null
|
scanimage -d "airscan:w0:Brother DCP-J4120DW" --resolution 300 --mode "Gray" -x 210 -y 297 --format=jpeg > "$PAGE_FILE" 2>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ -s "$PAGE_FILE" ]; then
|
if [ -s "$PAGE_FILE" ]; then
|
||||||
echo "OK ($(du -h "$PAGE_FILE" | cut -f1))"
|
echo "OK ($(du -h "$PAGE_FILE" | cut -f1))"
|
||||||
PAGE=$((PAGE + 1))
|
PAGE=$((PAGE + 1))
|
||||||
else
|
else
|
||||||
echo "CHYBA: Sken se nezdařil. Zkontrolujte připojení tiskárny a zkuste to znovu."
|
echo "CHYBA: Sken se nezdařil. Zkontrolujte tiskárnu a zkuste to znovu."
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
TOTAL_PAGES=$(ls -1 "$OUT_DIR"/page_*.pdf 2>/dev/null | wc -l)
|
TOTAL_PAGES=$(ls -1 "$OUT_DIR"/page_*.jpg 2>/dev/null | wc -l)
|
||||||
|
|
||||||
if [ "$TOTAL_PAGES" -gt 0 ]; then
|
if [ "$TOTAL_PAGES" -gt 0 ]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo "[*] Spojuji $TOTAL_PAGES stran do výsledného PDF..."
|
echo "[*] Spojuji $TOTAL_PAGES stran do výsledného PDF..."
|
||||||
if command -v pdfunite >/dev/null 2>&1; then
|
img2pdf "$OUT_DIR"/page_*.jpg -o "$FINAL_PDF"
|
||||||
pdfunite "$OUT_DIR"/page_*.pdf "$FINAL_PDF"
|
|
||||||
else
|
|
||||||
convert "$OUT_DIR"/page_*.pdf "$FINAL_PDF"
|
|
||||||
fi
|
|
||||||
|
|
||||||
ln -sf "$FINAL_PDF" "$HOME/Downloads/kniha.pdf"
|
ln -sf "$FINAL_PDF" "$HOME/Downloads/kniha.pdf"
|
||||||
|
|
||||||
echo "======================================================================"
|
echo "======================================================================"
|
||||||
|
|||||||
Reference in New Issue
Block a user