feat: initial gosleep-timer implementation

Go TUI sleep timer with modular architecture.
- Config: YAML-based, profile inheritance, auto WM detection
- Engine: timer, executor, stage pipeline (pre→timer→post)
- Modules: workspace (niri/hyprland/kde), media, lock, kill,
  notify, sound, brightness, mute, custom, script
- TUI: bubbletea app with profiles, module toggles, progress bar
- CLI: run, list-profiles, export, import, history, stats
- History: JSONL log with statistics
- QR: config export as ASCII QR
This commit is contained in:
2026-07-03 01:43:22 +02:00
commit 8501fd074c
34 changed files with 3401 additions and 0 deletions
+266
View File
@@ -0,0 +1,266 @@
# gosleep-timer — Go TUI Timer
## Цель
Переписать `timer.py` на Go с модульной архитектурой, поддержкой нескольких WM/DE (niri, Hyprland, KDE), пользовательскими командами, профилями, историей, CLI-режимом и QR-экспортом.
---
## Структура проекта
```
gosleep-timer/
├── main.go # CLI entrypoint
├── go.mod / go.sum
├── .gitignore
├── TODO.md
├── cicd.yaml # CI/CD pipeline
├── .golangci.yml # linter config
├── config/
│ ├── config.go # загрузка YAML
│ ├── defaults.go # дефолтные значения
│ └── types.go # структуры Config, Module, Profile, Stage
├── engine/
│ ├── timer.go # ядро отсчёта
│ ├── executor.go # запуск команд, таймауты, kill
│ └── stages.go # фазы: pre → timer → post
├── modules/
│ ├── module.go # интерфейс Module
│ ├── registry.go # глобальный реестр модулей
│ ├── workspace/
│ │ └── workspace.go # переключение workspace (niri/hyprland/kde)
│ ├── media/
│ │ └── media.go # playerctl / MPRIS
│ ├── lock/
│ │ └── lock.go # блокировка экрана
│ ├── kill/
│ │ └── kill.go # pkill процессов
│ ├── notify/
│ │ └── notify.go # notify-send / dunst
│ ├── sound/
│ │ └── sound.go # звуковой сигнал
│ ├── brightness/
│ │ └── brightness.go # управление яркостью (brightnessctl/light)
│ ├── mute/
│ │ └── mute.go # mute/unmute (pactl/wpctl)
│ ├── custom/
│ │ └── custom.go # пользовательские команды pre/post
│ └── script/
│ └── script.go # запуск произвольного скрипта
├── profiles/
│ ├── profile.go # структура Profile
│ └── manager.go # CRUD профилей
├── history/
│ ├── history.go # JSONL лог запусков
│ └── stats.go # статистика
├── tui/
│ ├── app.go # bubbletea App
│ ├── widgets.go # кастомные виджеты
│ ├── styles.go # темы
│ ├── keybinds.go # горячие клавиши
│ └── qr.go # QR код
```
---
## Очередность (от важного к мелкому)
### [x] 1. TODO.md
Этот файл.
### [ ] 2. Фундамент
- Инициализация Go модуля
- `.gitignore`
- Структура папок
- Первый коммит
### [ ] 3. Конфиг
- `config/types.go` — типы данных
- `config/defaults.go` — дефолты
- `config/config.go` — парсинг YAML
- Автоопределение WM (niri/hyprland/kde/none)
### [ ] 4. Ядро
- `engine/timer.go` — обратный отсчёт, тики
- `engine/executor.go` — exec.Command, таймауты, принудительное завершение
- `engine/stages.go` — фазы с callback-ами
### [ ] 5. Модули
- `modules/module.go` — интерфейс
- `modules/registry.go` — реестр
- workspace, media, lock, kill, notify, sound, brightness, mute, custom, script
### [ ] 6. Профили
- `profiles/profile.go`
- `profiles/manager.go`
- Загрузка/сохранение профилей, список, apply
### [ ] 7. История
- `history/history.go` — запись в JSONL
- `history/stats.go` — агрегация
### [ ] 8. TUI
- `tui/app.go`, `widgets.go`, `styles.go`, `keybinds.go`, `qr.go`
### [ ] 9. CLI
- `main.go` — cobra/флаги
- Режимы: `tui` (по умолчанию), `run`, `list-profiles`, `export`, `import`
### [ ] 10. Линтеры + CI/CD
- `.golangci.yml` (golint, staticcheck, gosec, revive, errcheck)
- `cicd.yaml` на основе `cicd.example.yaml`
- Go-специфичные линтеры
---
## Модули (детально)
### workspace
- Поле `Backend` (niri | hyprland | kde | auto)
- Поле `Workspace` (int)
- Автоопределение: `loginctl`, `$XDG_CURRENT_DESKTOP`, `hyprctl`, `niri msg`
- Команды:
- niri: `niri msg action focus-workspace {n}`
- hyprland: `hyprctl dispatch workspace {n}`
- kde: `qdbus org.kde.KWin /KWin setCurrentDesktop {n}`
### media
- Поле `Action` (stop | pause | play-pause | next | previous | none)
- fallback: `playerctl`
### lock
- Поле `Command` (кастомная строка)
- fallback: `loginctl lock-session`
### kill
- Поле `Processes` ([]string)
- `pkill {name}` для каждого
### notify
- Поле `Sound` (путь к файлу или none)
- `notify-send` + опционально звук
### sound
- Поле `File` (путь к wav/oga)
- `paplay`, `aplay`, `ffplay`
### brightness
- Поле `Value` (int 0-100)
- `brightnessctl set {n}%` или `light -S {n}`
### mute
- Поле `Mute` (bool)
- `pactl set-sink-mute @DEFAULT_SINK@ 1` / `0`
- `wpctl set-mute @DEFAULT_AUDIO_SINK@ 1` / `0`
### custom
- Поля `PreCommands`, `PostCommands` ([]string)
### script
- Поле `Path` (путь к скрипту)
- Аргументы из контекста таймера
---
## CLI флаги (`main.go`)
```
gosleep-timer # TUI режим
gosleep-timer run 25m # CLI режим
gosleep-timer run --profile work 25m
gosleep-timer list-profiles
gosleep-timer export > config.yaml
gosleep-timer import < config.yaml
gosleep-timer qr # показать QR с конфигом
```
---
## TUI (bubbletea)
### Экраны
1. **Main** — ввод времени, чекбоксы модулей, выбор профиля, Start/Stop
2. **Running** — прогресс-бар, оставшееся время, текущий этап
3. **History** — последние запуски
4. **Stats** — статистика
### Горячие клавиши
- `s` — Start
- `S` — Stop
- `q` / `Esc` — Quit
- `h` — History
- `Tab` — фокус следующий элемент
- `Enter` — toggle/action
---
## Формат конфига (`~/.config/gosleep-timer/config.yaml`)
```yaml
profiles:
default:
modules:
workspace:
enabled: true
backend: auto
workspace: 12
media:
enabled: true
action: stop
lock:
enabled: true
command: ""
kill:
enabled: false
processes: []
notify:
enabled: true
sound: ""
sound:
enabled: true
file: /usr/share/sounds/freedesktop/stereo/complete.oga
brightness:
enabled: false
value: 0
mute:
enabled: false
custom:
enabled: false
pre: []
post: []
script:
enabled: false
path: ""
work:
extends: default
modules:
workspace:
workspace: 5
gaming:
modules:
kill:
enabled: true
processes: [firefox, slack]
mute:
enabled: true
```
---
## История (`~/.local/share/gosleep-timer/history.jsonl`)
```jsonl
{"ts":"2026-07-03T01:30:00Z","profile":"default","duration":"25m","status":"completed"}
{"ts":"2026-07-03T02:00:00Z","profile":"work","duration":"1h","status":"killed"}
```
---
## CI/CD Pipeline
На основе `cicd.example.yaml`:
- `lint-go` — golangci-lint (все линтеры)
- `lint-yaml` — yamllint
- `lint-dockerfile` — hadolint (если появится)
- `build` — go build
- `test` — go test ./...
- `publish` — docker образ (опционально)