diff --git a/dnes b/dnes index 9f5d7e0..ed4d4ed 100755 --- a/dnes +++ b/dnes @@ -1,18 +1,161 @@ -#!/bin/bash -cd repos/dnes.git -git init +#!/usr/bin/env bash +# dnes: Daily plan tracker and journal of done things with anti-recursion protection +set -euo pipefail -cat << 'EOF' > ./02_observator/mpd_drift_gate.patch -diff --git a/main.go b/main.go -index a2f3b4c..c5d6e7f 100644 ---- a/main.go -+++ b/main.go -@@ -12,3 +12,3 @@ const ( -- DriftGate = 500 * time.Millisecond -+ DriftGate = 300 * time.Millisecond - MpdPort = "6600" - ) -EOF +PLAN_DIR="$HOME/src/dnes" +PLAN_FILE="$PLAN_DIR/plan.md" +JOURNAL_FILE="$PLAN_DIR/journal.md" +LOCK_FILE="/tmp/dnes-sync.lock" +LOG_DIR="$HOME/.local/state/dnes" +mkdir -p "$LOG_DIR" -git add . -git commit -m "init: kompletní struktura /dnes, vyčištěná administrativa a mpd patch" +# Prevent recursive self-invocation +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 " >&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 "(?<=)[^<]+" "$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 "(?<=)[^<]+" "$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 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 diff --git a/moonphase.py b/moonphase.py index fe9cb88..41e7d66 100755 --- a/moonphase.py +++ b/moonphase.py @@ -1,11 +1,12 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """ moonphase.py - Calculate Lunar Phase Author: Sean B. Palmer, inamidst.com +Enhanced for Samizdat & Observatoř Cybernetics Cf. http://en.wikipedia.org/wiki/Lunar_phase#Lunar_phase_calculation """ -import math, decimal, datetime +import math, decimal, datetime, sys dec = decimal.Decimal def position(now=None): @@ -32,12 +33,63 @@ def phase(pos): 7: "Waning Crescent" }[int(index) & 7] -def main(): - pos = position() - phasename = phase(pos) +def phase_cz(pos): + index = (pos * dec(8)) + dec("0.5") + 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) - print "%s (%s)" % (phasename, roundedpos) +def illumination(pos): + # 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__": main() diff --git a/postgen b/postgen deleted file mode 120000 index f671a29..0000000 --- a/postgen +++ /dev/null @@ -1 +0,0 @@ -/home/kof/src/postgen/postgen \ No newline at end of file diff --git a/postgen b/postgen new file mode 100755 index 0000000..3ac8208 Binary files /dev/null and b/postgen differ diff --git a/scan-book b/scan-book index a808dec..a0f9977 100755 --- a/scan-book +++ b/scan-book @@ -49,35 +49,30 @@ while true; do 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" - # Execute scan on bazina via USB - ssh bazina "scanimage -d 'brother4:bus1;dev8' --resolution 300 --mode 'True Gray' -x 210 -y 297 --format=pdf" > "$PAGE_FILE" 2>/dev/null || { + # 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=jpeg" > "$PAGE_FILE" 2>/dev/null || { # 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 echo "OK ($(du -h "$PAGE_FILE" | cut -f1))" PAGE=$((PAGE + 1)) 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 echo "" 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 echo "" echo "[*] Spojuji $TOTAL_PAGES stran do výsledného PDF..." - if command -v pdfunite >/dev/null 2>&1; then - pdfunite "$OUT_DIR"/page_*.pdf "$FINAL_PDF" - else - convert "$OUT_DIR"/page_*.pdf "$FINAL_PDF" - fi - + img2pdf "$OUT_DIR"/page_*.jpg -o "$FINAL_PDF" ln -sf "$FINAL_PDF" "$HOME/Downloads/kniha.pdf" echo "======================================================================"