commit de9963c92f4be07a94f9103b78ac364ffac205cc
parent c23929aadf2d74a805c4656a232f25afb81af68f
Author: Sivaldo <gxixtx@xsxixvxaxlxdxoxdxaxvxix.xcxoxm>
Date: Fri, 31 Jul 2026 14:22:11 -0300
refactor: remove suporte ao password-store e script de desenho
Diffstat:
2 files changed, 0 insertions(+), 304 deletions(-)
diff --git a/.config/X11/profile b/.config/X11/profile
@@ -7,7 +7,6 @@ export TERMINAL="st"
export BROWSER="firefox"
export READER="zathura"
export PATH="$HOME/.local/bin:$PATH"
-export PASSWORD_STORE_GPG_OPTS="--trust-model always"
# ---------------------------
# Variáveis de base (XDG)
@@ -25,7 +24,6 @@ export XDG_VIDEOS_DIR="$HOME/videos"
# ---------------------------
# Pastas de programas
# ---------------------------
-export PASSWORD_STORE_DIR="$XDG_DATA_HOME/password-store"
export GNUPGHOME="$XDG_DATA_HOME/gnupg"
export GOPATH="$XDG_DATA_HOME/go"
export HISTFILE="$XDG_CACHE_HOME/ash_history"
diff --git a/.local/bin/draw b/.local/bin/draw
@@ -1,302 +0,0 @@
-#!/usr/bin/env python3
-"""
-Servidor local minimalista para Excalidraw.
-Assets JS ficam em ~/.cache/excalidraw para sobreviver a reboots.
-Bibliotecas em ~/.local/share/excalidraw são mescladas automaticamente
-num único all-libraries.excalidrawlib servido pelo servidor.
-"""
-
-import json
-import mimetypes
-import os
-import signal
-import sys
-import urllib.request
-from concurrent.futures import ThreadPoolExecutor, as_completed
-from datetime import datetime, timezone
-from http.server import HTTPServer, BaseHTTPRequestHandler
-from pathlib import Path
-from socketserver import ThreadingMixIn
-
-# ── Configurações ────────────────────────────────────────────────────────────
-PORT = 8080
-CACHE_DIR = Path.home() / ".cache" / "excalidraw"
-LIBS_DIR = Path.home() / ".local" / "share" / "excalidraw"
-MERGED_LIB = CACHE_DIR / "all-libraries.excalidrawlib"
-
-ASSETS = {
- "react.js": "https://unpkg.com/react@18.2.0/umd/react.production.min.js",
- "react-dom.js": "https://unpkg.com/react-dom@18.2.0/umd/react-dom.production.min.js",
- "excalidraw.js": "https://unpkg.com/@excalidraw/excalidraw@0.17.6/dist/excalidraw.production.min.js",
-}
-
-EXCALIDRAW_ASSET_PATH = "https://unpkg.com/@excalidraw/excalidraw@0.17.6/dist/"
-# ─────────────────────────────────────────────────────────────────────────────
-
-
-def fetch_asset(filename: str, url: str, retries: int = 4) -> None:
- dest = CACHE_DIR / filename
- if dest.exists() and dest.stat().st_size > 1024:
- return
-
- req = urllib.request.Request(
- url,
- headers={"User-Agent": "Mozilla/5.0 (compatible; ExcalidrawLocal/1.0)", "Accept": "*/*"},
- )
-
- last_exc: Exception = RuntimeError("sem tentativas")
- for attempt in range(1, retries + 1):
- try:
- with urllib.request.urlopen(req, timeout=20) as response:
- data = response.read()
- if len(data) < 1024:
- raise RuntimeError(f"payload suspeito ({len(data)} bytes)")
- dest.write_bytes(data)
- return
- except Exception as exc:
- last_exc = exc
- wait = 2 ** attempt # 2, 4, 8, 16 s
- print(f" ↺ {filename} tentativa {attempt}/{retries} falhou ({exc}); aguardando {wait}s…")
- import time; time.sleep(wait)
-
- raise last_exc
-
-
-def bootstrap_assets() -> None:
- CACHE_DIR.mkdir(parents=True, exist_ok=True)
- os.chdir(CACHE_DIR)
-
- with ThreadPoolExecutor(max_workers=3) as pool:
- futures = {pool.submit(fetch_asset, name, url): name for name, url in ASSETS.items()}
- for future in as_completed(futures):
- name = futures[future]
- try:
- future.result()
- print(f" ✓ {name}")
- except Exception as exc:
- print(f" ✗ {name}: {exc}")
- sys.exit(1)
-
-
-def merge_libraries() -> None:
- """
- Varre ~/.local/share/excalidraw, mescla todos os .excalidrawlib
- num único arquivo em ~/.cache/excalidraw/all-libraries.excalidrawlib.
- IDs duplicados são ignorados para o caso de re-execução.
- """
- if not LIBS_DIR.is_dir():
- print(" – Diretório de bibliotecas não encontrado, pulando merge.")
- return
-
- files = sorted(LIBS_DIR.glob("*.excalidrawlib"))
- if not files:
- print(" – Nenhuma biblioteca encontrada em ~/.local/share/excalidraw.")
- return
-
- all_items: list = []
- seen_ids: set = set()
-
- for f in files:
- try:
- data = json.loads(f.read_text(encoding="utf-8"))
- except Exception as e:
- print(f" ✗ {f.name}: {e}")
- continue
-
- version = data.get("version", 1)
-
- # v2: libraryItems é uma lista plana de elementos individuais (cada um é 1 item).
- # v1: library é uma lista de grupos, onde cada grupo é uma lista de elementos
- # que formam juntos um único item da biblioteca.
- if version >= 2:
- raw_items = data.get("libraryItems", [])
- else:
- # Converte cada grupo de elementos v1 num libraryItem v2.
- raw_items = []
- import uuid as _uuid
- for group in data.get("library", []):
- raw_items.append({
- "id": str(_uuid.uuid4()),
- "status": "published",
- "elements": group,
- "created": 0,
- })
-
- added = 0
- for item in raw_items:
- uid = item.get("id")
- if uid in seen_ids:
- continue
- seen_ids.add(uid)
- all_items.append(item)
- added += 1
-
- print(f" ✓ {f.name:45s} {added:3d} itens (v{version})")
-
- merged = {
- "type": "excalidrawlib",
- "version": 2,
- "source": f"merged:{datetime.now(timezone.utc).isoformat()}",
- "libraryItems": all_items,
- }
- MERGED_LIB.write_text(json.dumps(merged, ensure_ascii=False), encoding="utf-8")
- print(f" → {len(all_items)} itens mesclados → {MERGED_LIB}")
-
-
-class SPAHandler(BaseHTTPRequestHandler):
- _html_payload: bytes = b""
-
- def _send_headers(self, status: int = 200) -> None:
- self.send_response(status)
- self.send_header("X-Content-Type-Options", "nosniff")
-
- def _serve_file(self, filepath: Path) -> None:
- try:
- data = filepath.read_bytes()
- except (OSError, IOError):
- self.send_error(404)
- return
-
- self._send_headers(200)
- mime, _ = mimetypes.guess_type(filepath.name)
- self.send_header("Content-Type", mime or "application/octet-stream")
-
- if filepath.suffix == ".js":
- self.send_header("Cache-Control", "public, max-age=31536000, immutable")
- elif filepath.suffix == ".excalidrawlib":
- # Lib mesclada pode ser regenerada; não cachear no browser.
- self.send_header("Cache-Control", "no-store")
-
- self.send_header("Content-Length", str(len(data)))
- self.end_headers()
- self.wfile.write(data)
-
- def _serve_spa(self) -> None:
- self._send_headers(200)
- self.send_header("Content-Type", "text/html; charset=utf-8")
- self.send_header("Cache-Control", "no-store")
- self.end_headers()
- self.wfile.write(self._html_payload)
-
- def do_GET(self) -> None:
- requested = self.path.lstrip("/") or "index.html"
- filepath = CACHE_DIR / requested
- if filepath.is_file():
- self._serve_file(filepath)
- else:
- self._serve_spa()
-
- def log_message(self, format, *args) -> None:
- pass
-
-
-class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
- daemon_threads = True
- allow_reuse_address = True
-
-
-def generate_index_html() -> bytes:
- if MERGED_LIB.exists():
- bootstrap_js = """
- function startApp(libraryItems) {
- var initialData = libraryItems ? { libraryItems: libraryItems } : null;
-
- var App = function() {
- return React.createElement(
- "div",
- { style: { height: "100vh", width: "100vw" } },
- React.createElement(window.ExcalidrawLib.Excalidraw, {
- initialData: initialData,
- })
- );
- };
-
- ReactDOM.createRoot(document.getElementById("root")).render(React.createElement(App));
- }
-
- fetch("/all-libraries.excalidrawlib")
- .then(function(r) { return r.json(); })
- .then(function(data) { startApp(data.libraryItems || []); })
- .catch(function(e) {
- console.warn("Biblioteca não carregada:", e);
- startApp(null);
- });
-"""
- else:
- bootstrap_js = """
- var App = function() {
- return React.createElement(
- "div",
- { style: { height: "100vh", width: "100vw" } },
- React.createElement(window.ExcalidrawLib.Excalidraw)
- );
- };
- ReactDOM.createRoot(document.getElementById("root")).render(React.createElement(App));
-"""
-
- html = f"""<!DOCTYPE html>
-<html lang="pt-BR">
-<head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Excalidraw Local</title>
- <script src="/react.js"></script>
- <script src="/react-dom.js"></script>
- <script src="/excalidraw.js"></script>
- <style>
- body, html {{ margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: #ffffff; }}
- #root {{ width: 100vw; height: 100vh; }}
- </style>
-</head>
-<body>
- <div id="root"></div>
- <script>
- window.EXCALIDRAW_ASSET_PATH = "{EXCALIDRAW_ASSET_PATH}";
-
- window.addEventListener("DOMContentLoaded", function() {{
- if (!window.React || !window.ReactDOM || !window.ExcalidrawLib) {{
- document.getElementById("root").innerHTML =
- '<div style="padding:2rem;color:#d32f2f;font-family:sans-serif;">' +
- '<strong>Falha de carga:</strong> bibliotecas não disponíveis.</div>';
- return;
- }}
-
- {bootstrap_js}
- }});
- </script>
-</body>
-</html>
-"""
- return html.encode("utf-8")
-
-
-def shutdown_handler(signum, frame) -> None:
- print("\nEncerrando servidor...")
- sys.exit(0)
-
-
-def main() -> None:
- signal.signal(signal.SIGINT, shutdown_handler)
- signal.signal(signal.SIGTERM, shutdown_handler)
-
- print(f"Cache: {CACHE_DIR}")
- print("\nBaixando assets JS...")
- bootstrap_assets()
-
- print("\nMesclando bibliotecas...")
- merge_libraries()
-
- SPAHandler._html_payload = generate_index_html()
-
- server = ThreadedHTTPServer(("", PORT), SPAHandler)
- print(f"\nServidor ativo em http://localhost:{PORT}")
- print("Pressione Ctrl+C para encerrar.\n")
-
- try:
- server.serve_forever()
- finally:
- server.server_close()
-
-
-if __name__ == "__main__":
- main()