63 рядки
2.5 KiB
Markdown
63 рядки
2.5 KiB
Markdown
# pllist
|
|
|
|
Access-based Telegram bot for creating and managing lists of planned purchases.
|
|
|
|
A user owns lists. A list contains items. Items can be added, marked done, and
|
|
reserved by the person responsible for buying them. Items carry an urgency
|
|
level. An owner can share a list with other users as a reader or an editor.
|
|
Bot access itself is allowlisted: the owner runs `/allow` and `/kick`.
|
|
The codebase stays small but extensible.
|
|
|
|
- Architecture: `docs/architecture.md`
|
|
- Infrastructure: `docs/infra.md`
|
|
- MVP plan: `docs/roadmap-mvp.md`
|
|
- Other notes: `docs/temp-*.md`
|
|
|
|
## Stack
|
|
|
|
- Go 1.27
|
|
- `github.com/mymmrac/telego` for the Telegram Bot API, long polling
|
|
- GORM with PostgreSQL
|
|
- `github.com/joho/godotenv` for local environment loading
|
|
- Docker Compose for local development
|
|
- Gitea for version control and CI, Dokploy for deployment
|
|
|
|
## Commands
|
|
|
|
```sh
|
|
cp .env.example .env # fill values
|
|
make build # build bin/bot
|
|
make run # run bin/bot
|
|
go test ./... # unit tests
|
|
go vet ./... # static checks
|
|
gofmt -l . # formatting check
|
|
```
|
|
|
|
## Engineering rules
|
|
|
|
1. Use constructor injection. Build concrete types in `cmd/bot/main.go` and
|
|
pass dependencies down. No package-level globals and no `init()` side
|
|
effects.
|
|
2. Define small interfaces where they are consumed, not next to the
|
|
implementation.
|
|
3. Keep business rules in `internal/domain` and `internal/service`. Handlers
|
|
parse input and render output only.
|
|
4. Route every list operation through one authorization function. Do not
|
|
reimplement access checks in handlers or repositories.
|
|
5. Implement item changes as domain methods (`Reserve`, `Release`, `Complete`,
|
|
`Reopen`, `SetUrgency`). Do not assign state fields from handlers.
|
|
6. Apply DRY to behavior: one callback-data codec, one keyboard builder per
|
|
view, one error-to-message mapper.
|
|
7. Use sentinel domain errors (`ErrNotFound`, `ErrForbidden`, `ErrConflict`,
|
|
`ErrInvalidInput`) and map them in the Telegram layer. Never leak database
|
|
errors to users.
|
|
8. Revalidate authorization on every callback. Callback data is untrusted and
|
|
limited to 64 bytes.
|
|
9. Reserve items with a conditional database update, not read-then-write.
|
|
10. Emit future side effects through `events.Publisher`. Services never call
|
|
Telegram directly.
|
|
11. Keep Telegram types out of `domain` and `service`.
|
|
12. Test every access-matrix row and every item transition.
|
|
13. Never commit secrets. `.env` is ignored; keep `.env.example` current.
|
|
14. Update the docs when a design decision changes.
|