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>
35 lines
857 B
Desktop File
35 lines
857 B
Desktop File
[Unit]
|
|
Description=Autoficher - fichaje automatico en Timenet
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
# si entra en bucle de fallos, deja de reintentar en vez de martillear la API
|
|
StartLimitIntervalSec=600
|
|
StartLimitBurst=6
|
|
|
|
[Service]
|
|
Type=simple
|
|
WorkingDirectory=%h/autoficher
|
|
ExecStart=%h/autoficher/venv/bin/python3 %h/autoficher/autoficherd.py
|
|
EnvironmentFile=%h/autoficher/.env
|
|
Environment=PYTHONUNBUFFERED=1
|
|
|
|
Restart=always
|
|
RestartSec=30
|
|
# margen para cerrar sesion de Telegram y avisar antes de morir
|
|
TimeoutStopSec=30
|
|
KillSignal=SIGTERM
|
|
|
|
# endurecimiento: solo puede escribir en su propio directorio
|
|
NoNewPrivileges=yes
|
|
PrivateTmp=yes
|
|
ProtectSystem=strict
|
|
ReadWritePaths=%h/autoficher
|
|
ProtectKernelTunables=yes
|
|
ProtectControlGroups=yes
|
|
RestrictSUIDSGID=yes
|
|
RestrictRealtime=yes
|
|
LockPersonality=yes
|
|
|
|
[Install]
|
|
WantedBy=default.target
|