chore: auto-commit (1 archivos)
- tools/ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Clasificador de notas sueltas de un vault Obsidian por titulo, via ask_llm (claude-direct).
|
||||
|
||||
Uso:
|
||||
classify_notes.py [Vault] [--apply]
|
||||
Vault por defecto: NotasDeObsidian.
|
||||
Sin --apply: genera el plan (classify_plan_<vault>.json) y muestra distribucion, sin mover.
|
||||
Con --apply: mueve cada nota suelta a su carpeta (in-situ; Obsidian resuelve links por nombre).
|
||||
|
||||
Taxonomia: estudio, tech, hacking, personal, finanzas, proyectos, otros.
|
||||
"""
|
||||
import sys, os, json, re, shutil
|
||||
from collections import Counter
|
||||
|
||||
sys.path.insert(0, "/home/enmanuel/fn_registry/python/functions")
|
||||
from core.ask_llm import ask_llm
|
||||
from obsidian import list_obsidian_notes
|
||||
|
||||
OBS = "/home/enmanuel/Obsidian"
|
||||
CATS = ["estudio", "tech", "hacking", "personal", "finanzas", "proyectos", "otros"]
|
||||
BATCH = 50
|
||||
|
||||
|
||||
def root_notes(vault):
|
||||
vp = f"{OBS}/{vault}"
|
||||
out = []
|
||||
for n in list_obsidian_notes(vp):
|
||||
rel = os.path.relpath(n, vp)
|
||||
if "/" in rel or "/.git/" in n or "/dist/" in n:
|
||||
continue
|
||||
out.append(os.path.basename(n)[:-3])
|
||||
return sorted(set(out))
|
||||
|
||||
|
||||
def classify_batch(titles):
|
||||
listado = "\n".join(f"{i}. {t}" for i, t in enumerate(titles))
|
||||
prompt = (
|
||||
"Clasifica cada nota de Obsidian (vault personal de un dev espanol) en UNA categoria.\n"
|
||||
f"Categorias validas: {', '.join(CATS)}.\n"
|
||||
"Guia: estudio=apuntes de cursos/teoria (data science, matematicas, bases de datos, frameworks). "
|
||||
"tech=dev practico (comandos, docker, linux, git, apis, servidores, herramientas). "
|
||||
"hacking=seguridad ofensiva real (bug bounty, exploits, recon, osint tecnico, web hacking). "
|
||||
"personal=vida personal (citas, salud, tramites, viajes, familia). "
|
||||
"finanzas=banca personal, cripto, trading. proyectos=proyectos propios de software/negocio. "
|
||||
"otros=no encaja.\n"
|
||||
"Devuelve SOLO un objeto JSON {indice: categoria}, indices 0-based, sin texto extra.\n\n"
|
||||
+ listado
|
||||
)
|
||||
raw = ask_llm(prompt, model="claude-haiku-4-5-20251001", echo=False)
|
||||
m = re.search(r'\{.*\}', raw, re.S)
|
||||
if not m:
|
||||
return {}
|
||||
try:
|
||||
return json.loads(m.group(0))
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
|
||||
def main():
|
||||
args = [a for a in sys.argv[1:] if not a.startswith("--")]
|
||||
vault = args[0] if args else "NotasDeObsidian"
|
||||
apply = "--apply" in sys.argv
|
||||
vp = f"{OBS}/{vault}"
|
||||
plan_path = f"/home/enmanuel/fn_registry/projects/obsidian/tools/classify_plan_{vault}.json"
|
||||
|
||||
titles = root_notes(vault)
|
||||
print(f"{vault}: {len(titles)} notas sueltas en raiz")
|
||||
plan = {}
|
||||
for b in range(0, len(titles), BATCH):
|
||||
chunk = titles[b:b + BATCH]
|
||||
res = classify_batch(chunk)
|
||||
for i, t in enumerate(chunk):
|
||||
cat = str(res.get(str(i), res.get(i, "otros"))).strip().lower()
|
||||
plan[t] = cat if cat in CATS else "otros"
|
||||
json.dump(plan, open(plan_path, "w", encoding="utf-8"), ensure_ascii=False, indent=2)
|
||||
|
||||
c = Counter(plan.values())
|
||||
print("distribucion:", {k: c[k] for k in CATS if c[k]})
|
||||
for cat in CATS:
|
||||
ej = [t for t, cc in plan.items() if cc == cat][:4]
|
||||
if ej:
|
||||
print(f" [{cat}] " + " | ".join(ej))
|
||||
|
||||
if apply:
|
||||
moved = 0
|
||||
for t, cat in plan.items():
|
||||
src = f"{vp}/{t}.md"
|
||||
if not os.path.exists(src):
|
||||
continue
|
||||
dd = f"{vp}/{cat}"; os.makedirs(dd, exist_ok=True)
|
||||
dst = f"{dd}/{t}.md"
|
||||
if os.path.exists(dst):
|
||||
continue
|
||||
shutil.move(src, dst); moved += 1
|
||||
print(f"\nmovidas: {moved}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,185 @@
|
||||
{
|
||||
"01 - Bug Bounty Basics": "hacking",
|
||||
"01 - Tendencias y Estacionalidad": "finanzas",
|
||||
"02 - Open Redirect": "hacking",
|
||||
"03 - HTTP Parameter Pollution": "hacking",
|
||||
"2025-05-10": "otros",
|
||||
"2025-06-11": "otros",
|
||||
"78": "otros",
|
||||
"Almacenar Contraseñas de Github": "tech",
|
||||
"Apuntes rapidos automatizacion prefect": "estudio",
|
||||
"Argumentos para chromium en docker desktop": "tech",
|
||||
"Arreglar codigo usando diffs": "tech",
|
||||
"Asesinato sql": "hacking",
|
||||
"Bases de datos publicas para verificar los identificadores": "tech",
|
||||
"Bibliotecas de simulaciones para python": "estudio",
|
||||
"CURSO - Time Series": "estudio",
|
||||
"Camara raspberry Arducam IMX135": "tech",
|
||||
"Cambiar menu contextual": "tech",
|
||||
"Comando para conectarte desde ssh": "tech",
|
||||
"Comandos de micro": "tech",
|
||||
"Comenzar proyecto con Julia": "estudio",
|
||||
"Como hacerlo segun chatgpt": "otros",
|
||||
"Como instalar Node.js en windows": "tech",
|
||||
"Como se consigue el texto despues de procesarlo": "tech",
|
||||
"Como se ve el texto con latex desde chatgpt": "tech",
|
||||
"Como usar confy UI": "tech",
|
||||
"Compilacion usando tarjeta grafica de llama.cpp": "tech",
|
||||
"Conectarse a server kumatora": "tech",
|
||||
"Conseguir codigo latex usando una IA": "tech",
|
||||
"Conseguuir codigo latex usando una IA": "tech",
|
||||
"Continuar sesion codex": "tech",
|
||||
"Coolify": "tech",
|
||||
"Cosas que arreglar en contenedor docker": "tech",
|
||||
"Crear imagenes con IA": "tech",
|
||||
"Curso DDLR TV Hacking": "estudio",
|
||||
"Curso avanzado de Simulacion": "estudio",
|
||||
"Curso basico para hacer en un momento": "estudio",
|
||||
"Curso sobre simulaciones con python": "estudio",
|
||||
"Custom LLMs": "tech",
|
||||
"Dar de alta demanda de madrid": "personal",
|
||||
"Data Science para invertir en bolsa": "finanzas",
|
||||
"DataStack": "tech",
|
||||
"Database de grafos": "estudio",
|
||||
"Descargar cualquier version de chromium para scraping": "tech",
|
||||
"Documentacion tixl": "tech",
|
||||
"Drawing 2024-08-28 21.45.22.excalidraw": "otros",
|
||||
"Drawing 2024-10-12 16.52.25.excalidraw": "otros",
|
||||
"Drawing 2024-10-19 23.03.02.excalidraw": "otros",
|
||||
"Drawing 2025-06-11 22.05.14.excalidraw": "otros",
|
||||
"Drawing 2025-09-07 01.56.43.excalidraw": "otros",
|
||||
"Drawing 2026-01-01 04.44.45.excalidraw": "otros",
|
||||
"Drawing 2026-01-01 04.44.45.excalidraw.restored": "otros",
|
||||
"Drawing 2026-04-09 00.31.22.excalidraw": "otros",
|
||||
"Editor de texto": "tech",
|
||||
"Ejemplos de datascience en bolsa": "estudio",
|
||||
"Ejempos de tipos de simulaciones": "estudio",
|
||||
"Embeddings y Búsqueda Semántica": "estudio",
|
||||
"Enlaces para descargar apks de Android": "tech",
|
||||
"Estudios": "estudio",
|
||||
"Exchangers criptomonedas": "finanzas",
|
||||
"Extraer assets de cities skylines": "proyectos",
|
||||
"FITZ-Studio": "proyectos",
|
||||
"Fallos de generacion de notebook completo": "tech",
|
||||
"FavMusiic": "personal",
|
||||
"Formulas de series": "estudio",
|
||||
"Foro peliculas shinchan": "personal",
|
||||
"Foros": "personal",
|
||||
"Foros con databases": "tech",
|
||||
"FrontendStack": "proyectos",
|
||||
"Fuentes Generacion Imagenes": "tech",
|
||||
"Funciones de matrix synapsis element": "tech",
|
||||
"Generacion Alternativa Obsidian con bbdd y Embeddings": "tech",
|
||||
"Google Dorking to found vulns": "hacking",
|
||||
"Grupos comerciales": "finanzas",
|
||||
"Guardar y mover formulas matematicas": "estudio",
|
||||
"HAcer bots de telegram": "proyectos",
|
||||
"Herramientas open source": "tech",
|
||||
"Herramientas para Neo4j": "tech",
|
||||
"Identificadores de Libros Academicos": "estudio",
|
||||
"Iniciar Dagster": "tech",
|
||||
"Instalar Julia": "tech",
|
||||
"Instalar Office 2025": "tech",
|
||||
"Ip Homer gui": "tech",
|
||||
"Java open source": "tech",
|
||||
"LLM a tener en cuenta": "estudio",
|
||||
"LeaksCSV": "hacking",
|
||||
"Libro All of statistics diagrama": "estudio",
|
||||
"Libro Real world Bug hunting": "hacking",
|
||||
"Matematicas": "estudio",
|
||||
"Mcp Inspector": "tech",
|
||||
"Media Aritmetica": "estudio",
|
||||
"Mejoras fuzzygraph": "proyectos",
|
||||
"Metodos de acceso a datos usando LLMs": "estudio",
|
||||
"Metricas de correlacion": "estudio",
|
||||
"Metricas para kmeans": "estudio",
|
||||
"Milkdown editor de markdown": "tech",
|
||||
"Minecraft mods": "personal",
|
||||
"Modelos de machineLearning": "estudio",
|
||||
"MonteMiniCam": "proyectos",
|
||||
"MyToolbox": "proyectos",
|
||||
"NVM": "tech",
|
||||
"Notas desde android": "personal",
|
||||
"Notas para procesamiento de audio": "tech",
|
||||
"Ocr sencillo para windows": "tech",
|
||||
"Orden implementacion": "proyectos",
|
||||
"Osint Rapido": "hacking",
|
||||
"Paginas ciencia de datos": "estudio",
|
||||
"Paginas embeddings": "estudio",
|
||||
"Paginas para investigar": "hacking",
|
||||
"Pandas para knime": "estudio",
|
||||
"Plasmic para el diseño frontend": "tech",
|
||||
"Preparacion de carpeta para aplicaciones con react": "tech",
|
||||
"Presencia en Red": "personal",
|
||||
"Prioridades": "personal",
|
||||
"Probabilidad": "estudio",
|
||||
"Prompt Marimo para llm": "tech",
|
||||
"Prompt para marimo": "tech",
|
||||
"Prompt para trabajar con Mantine": "tech",
|
||||
"Prompt para tutoriales de librerias": "tech",
|
||||
"Prompts para modelos": "tech",
|
||||
"Proveedores de contexto": "tech",
|
||||
"Proyecto Miguel Facturas": "proyectos",
|
||||
"Prueba de comentarios": "tech",
|
||||
"Prueba formula en latex": "tech",
|
||||
"Prueba texto markdown": "tech",
|
||||
"PruebaDibujoAndroid": "personal",
|
||||
"Pruebas de extraccion": "tech",
|
||||
"Quants": "estudio",
|
||||
"Qué es una simulación": "estudio",
|
||||
"Redes de criptomonedas": "finanzas",
|
||||
"Reino de Nicoya - Wikipedia, la enciclopedia libre": "personal",
|
||||
"Sensores de windows con WMI": "tech",
|
||||
"Servidor minecraft docker": "tech",
|
||||
"Servidor ssh para Windows": "tech",
|
||||
"Simulaciones - 01": "estudio",
|
||||
"Sitios desde donde descargar datasets": "estudio",
|
||||
"SocialCasino Programacion": "proyectos",
|
||||
"Sprites para simulacion": "tech",
|
||||
"TAREAS DATABROKER": "personal",
|
||||
"Tareas Gente": "personal",
|
||||
"Tareas Mias": "personal",
|
||||
"Texto control de espacios y saltos de linea": "tech",
|
||||
"Tutorial Instalación de Docker": "tech",
|
||||
"Tutorial Servidores Coolify": "tech",
|
||||
"Tutorial Sympy": "estudio",
|
||||
"Tutorial de React": "estudio",
|
||||
"Unidad de Control (Control Unit - CU)": "estudio",
|
||||
"Untitled": "otros",
|
||||
"Untitled 1": "otros",
|
||||
"Untitled 10": "otros",
|
||||
"Untitled 11": "otros",
|
||||
"Untitled 12": "otros",
|
||||
"Untitled 13": "otros",
|
||||
"Untitled 2": "otros",
|
||||
"Untitled 3": "otros",
|
||||
"Untitled 4": "otros",
|
||||
"Untitled 5": "otros",
|
||||
"Untitled 6": "otros",
|
||||
"Untitled 7": "otros",
|
||||
"Untitled 8": "otros",
|
||||
"Untitled 9": "otros",
|
||||
"Ver environment de conda por defecto en la terminal de visual studio": "tech",
|
||||
"Ver severance online": "personal",
|
||||
"Verano Joven 2024": "personal",
|
||||
"Vscode-navegador": "tech",
|
||||
"cURL": "tech",
|
||||
"comandos para conectarse a ssh": "tech",
|
||||
"comandos raspberry pi": "tech",
|
||||
"como arreglar mi cuerpo by-ashlly": "personal",
|
||||
"como crear un metodo de estudio en mi tablet": "personal",
|
||||
"como crear un metodo de estudio en mi tablet.sync-conflict-20240912-102912-XYN43SQ": "personal",
|
||||
"como crear un metodo de estudio en mi tablet.sync-conflict-20240912-102933-XYN43SQ": "personal",
|
||||
"correos temporales nuevo": "personal",
|
||||
"darkweblinks": "hacking",
|
||||
"dataherrero": "tech",
|
||||
"diseño ui": "tech",
|
||||
"endpoints": "tech",
|
||||
"ffdjklafjl": "otros",
|
||||
"formulas random": "otros",
|
||||
"instalar ollama en wsl": "tech",
|
||||
"livekit": "tech",
|
||||
"popelisss": "otros",
|
||||
"prompt rob0ts": "tech",
|
||||
"redes neuronales python": "estudio"
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Organiza AurgiObsidian in-situ por reglas (los titulos tienen prefijos consistentes).
|
||||
|
||||
Mover notas dentro del mismo vault es seguro: Obsidian resuelve wikilinks/embeds por nombre,
|
||||
no por ruta. Idempotente. Con --apply mueve; sin flag solo muestra el plan.
|
||||
"""
|
||||
import sys, os, re, shutil, glob
|
||||
from collections import Counter
|
||||
|
||||
V = "/home/enmanuel/Obsidian/AurgiObsidian"
|
||||
FECHA = re.compile(r'^\d{4}-\d{2}-\d{2}')
|
||||
|
||||
|
||||
def cat(t):
|
||||
tl = t.lower()
|
||||
if FECHA.match(t):
|
||||
return "bitacora"
|
||||
if "excalidraw" in tl or t.startswith("Drawing") or t.startswith("2334Drawing"):
|
||||
return "diagramas"
|
||||
if t.startswith(("Carga DDS", "Carga Stg", "STG.", "ETL", "INITIAL_", "Carga Movimientos")) \
|
||||
or t.startswith(("Llenar", "llenar_", "insert_", "update ")):
|
||||
return "etl"
|
||||
if t.startswith("Navision."):
|
||||
return "navision"
|
||||
if "reunion" in tl:
|
||||
return "reuniones"
|
||||
if t.startswith("GENAI") or "mioti" in tl or "prompt engineering" in tl or "curso palantir" in tl:
|
||||
return "cursos"
|
||||
if any(k in tl for k in ["bigquery", "big query", "looker", "metabase", "kpi", "dashboard",
|
||||
"cuadro de mando", "cubo", "informe", "reporte", "visualiz", "tabla de hecho",
|
||||
"modelos de datos", "segmentacion", "clustering"]):
|
||||
return "bi"
|
||||
if any(k in tl for k in ["sql", "query", "querys", "tabla", "tablas", "conexion", "conexiones",
|
||||
"transformacion", "transformaciones", "origen", "origenes", "tpv", "vista",
|
||||
"datos", "bbdd", "base de datos"]):
|
||||
return "datos"
|
||||
return "otros"
|
||||
|
||||
|
||||
def main():
|
||||
apply = "--apply" in sys.argv
|
||||
notes = [p for p in glob.glob(f"{V}/**/*.md", recursive=True)
|
||||
if "/.obsidian/" not in p and "/.git/" not in p]
|
||||
plan = []
|
||||
for p in notes:
|
||||
rel = os.path.relpath(p, V)
|
||||
if "/" in rel: # ya en subcarpeta — no remover (excepto Compartir en Drive lo dejamos)
|
||||
continue
|
||||
plan.append((p, cat(os.path.basename(p)[:-3])))
|
||||
dist = Counter(c for _, c in plan)
|
||||
print(f"AurgiObsidian: {len(plan)} notas sueltas en raiz")
|
||||
for c, n in dist.most_common():
|
||||
print(f" {c}: {n}")
|
||||
if not apply:
|
||||
print("\n(dry-run; usa --apply para mover)")
|
||||
return
|
||||
moved = 0
|
||||
for p, c in plan:
|
||||
dd = f"{V}/{c}"; os.makedirs(dd, exist_ok=True)
|
||||
dst = f"{dd}/{os.path.basename(p)}"
|
||||
if os.path.exists(dst):
|
||||
continue
|
||||
shutil.move(p, dst); moved += 1
|
||||
print(f"\nmovidas: {moved}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user