Commit Graph

19 Commits

Author SHA1 Message Date
5ba5710db2 feat: daemon con bot de Telegram, killswitch y servicio systemd
Pasa de un cron ciego a un servicio en segundo plano. El killswitch lo exige:
para poder cancelar un fichaje pendiente desde el movil tiene que haber un
proceso escuchando durante la espera.

- daemon: bucle propio que duerme exactamente hasta el siguiente evento, con
  precision de decimas. No usa JobQueue de PTB porque APScheduler 3.6 importa
  pkg_resources, que ya no existe en Python 3.13; ademas asi no se añade una
  dependencia. Recupera fichajes perdidos si el equipo estuvo apagado.
- bot: /hoy /saldo /plan /fichar /desfichar /off /on /pausa /reanudar /log.
  Los comandos se registran con setMyCommands para que salgan en el menu del
  chat. Solo atiende al chat_id configurado.
- killswitch: aviso 12 min antes con teclado inline (cancelar / +15 min /
  fichar ya).
- Google Calendar queda solo para ausencias personales; festivos y vacaciones
  salen del calendario de Timenet.
- deploy/autoficher.service: unidad de usuario endurecida (ProtectSystem
  strict, escritura solo en el propio directorio), Restart=always.
- requirements: python-telegram-bot >= 22. La 20.5 tiene un bug de __slots__
  en Updater que rompe el polling en Python 3.13.
- .gitignore: data/, *.db, .env, __pycache__ en cualquier nivel.

tools/test_daemon.py cubre con reloj simulado y sin red: plan, aviso previo,
fichaje a su hora, killswitch, retraso de 15 min, pausa, recuperacion tras
apagon, fallo de red y dia no laborable. 19 comprobaciones.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-24 18:51:46 +02:00
9294474066 feat: nucleo nuevo: cliente API, calendario laboral, planificador y jitter
Timenet recorta el tiempo a la ventana teorica del horario:

    trabajado = min(salida, fin_teorico) - max(entrada, inicio_teorico)

Verificado sobre 6 meses (104 dias laborables, 376 fichajes). La API guarda dos
horas por fichaje: HR (la que fichas) y H (la que cuenta). De 376 fichajes, 136
llevaban ajuste: todos salidas, todos recortados hacia atras. Ninguna entrada
ajustada jamas. Resultado: una entrada tardia se debita al minuto y una salida
tardia no acredita nada, asi que el jitter aleatorio positivo que habia perdia
unos 3,2 min/dia (-776 min acumulados, casi 13 horas).

Y acabar el mes en positivo es imposible: 0 dias con saldo positivo en 108, y
timeExtraHours=false en todos los tipos de jornada. El objetivo es 0 clavado.

- timenet_api: cliente limpio. Documenta que Tn-D y dStr son obligatorias (sin
  ellas el servidor responde 403 hasta en endpoints publicos).
- schedule: calendario laboral desde cp/calendar. Festivos, vacaciones y tramos
  horarios los da Timenet, no hace falta adivinarlos.
- planner + jitter: entradas siempre ANTES de la hora, salidas siempre DESPUES,
  con costumbre que deriva lenta y cola larga hacia el lado seguro. Invariantes
  que fallan en duro si una entrada se planifica tarde.
- jitter_geo: las coordenadas del historico son identicas al sexto decimal en
  los 376 fichajes; ahora se desplazan dentro de un disco.
- store: SQLite con plan diario, overrides, auditoria y estado del drift.
- settings: config sin el acoplamiento a argparse del config_parser original.

tools/dryrun.py simula el año entero: saldo +0 en 226 dias laborables, con
~3,5 min/dia de presencia extra.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-24 18:51:33 +02:00
51976fbe22 fix: corregir bugs que costaban minutos y tapaban errores
- google_calendar: RefreshError se referenciaba como
  google.oauth2.credentials.exceptions.RefreshError, ruta que no existe. Al
  fallar un refresh de token saltaba un AttributeError que ocultaba el error
  real y rompia el re-auth. Ahora se importa de google.auth.exceptions.

- google_calendar: getEvent() comprobaba si habia un evento activo en ese
  instante. El daemon planifica de madrugada, asi que una ausencia de 09:00 a
  18:00 no se detectaba y se fichaba igual. Ahora acepta un dia y comprueba
  solapamiento. Sin argumento mantiene el comportamiento anterior.

- google_calendar: datetime.utcnow() esta deprecado en Python 3.12+.

- timenet_manager: "args.basedtime and not args.type" ignoraba -t 0 (Entrada)
  al combinarlo con -bt, porque not 0 es True. Ahora es "args.type is None".

- timenet_manager: updateVersion() asignaba el objeto Response al header Tn-V
  en vez de su texto.

- timenet_manager: geo.accuracy se parseaba y se podia sobrescribir por CLI
  pero nunca se enviaba en el payload de cp/checks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-24 18:50:59 +02:00
Omar Sánchez Pizarro
ce179ebff9 Agregar logging estructurado, try-catches y envío de errores por Telegram
- Agregado logging estructurado en todos los módulos
- Implementados try-catches en todos los métodos críticos
- Errores ahora se envían automáticamente por Telegram
- Mejorado manejo de excepciones en requests HTTP
- Agregado try-catch global en main.py para errores no manejados
- Logging detallado en timenet_manager, telegram_bot, google_calendar y config_parser
2026-01-13 01:39:16 +01:00
Omar Sánchez Pizarro
c052439de3 now working again
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
2025-12-02 09:49:01 +01:00
Omar Sánchez Pizarro
5929be384a fix: add sleep commented
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
2025-12-01 20:16:12 +01:00
Omar Sánchez Pizarro
b612fcb4ac feat: now check last check
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
2025-12-01 20:03:46 +01:00
Omar Sánchez Pizarro
5fdfbf1927 fix: headers
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
2025-12-01 17:37:26 +01:00
Omar Sánchez Pizarro
1612510301 feat: upgrade to new api version
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
2025-12-01 17:25:36 +01:00
8123de824e fixes y calendario de google holidays desactivado
Signed-off-by: Omar Sánchez Pizarro <admin@pribyte.cloud>
2025-09-04 14:13:57 +02:00
Omar Sánchez Pizarro
e9ec438183 cosas bonitas con el fiching
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
2023-11-09 18:48:07 +01:00
Omar Sánchez Pizarro
1f3f57e3eb send report after errors
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
2023-10-27 15:19:36 +02:00
Omar Sánchez Pizarro
6159ec68ae fix time check of timenet api when need sleep after web request.
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
2023-10-27 15:16:50 +02:00
e63027cf24 delete __pycache__ 2023-10-27 15:13:44 +02:00
90a2bf4578 sleep not working 2023-10-27 15:12:40 +02:00
Omar Sánchez Pizarro
6020ce5acb send message async 2023-10-09 14:55:54 +02:00
Omar Sánchez Pizarro
4f1aea3139 sleep 2023-10-09 14:23:49 +02:00
Omar Sánchez Pizarro
d09c66b125 particionado 2023-10-09 14:13:36 +02:00
Omar Sánchez Pizarro
927c281631 separación de codigo para facil edición
Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
2023-08-02 10:06:48 +02:00