Fetch and parse Harry and Finn with a stored Compass session per child and store every item against the right children.id. - cmd/school/session.go + internal/store/session.go: read and write the per-child harness session state in the SQLite `session` table. `show` prints metadata only; the state is never printed. - scripts/compass-fetch-patchright.mjs: reuse the stored session, refresh it after login, resolve the child's userId from the parent page by name, and keep the shared calendar out of the per-child run (it would leak the eldest's timetable into the younger child). - scripts/scan-compass.sh + make scan: scan one child or both; restore the session, fetch, persist the session, then parse. A failing child is recorded in `scans` with ok = 0 and the script exits non-zero (FR-12). - cmd/school/scan.go: `school scan record` writes a fetch failure to the scans table. cmd/school/items.go: `school items purge` removes rows that a shared page stored against the wrong child. - internal/store/store_test.go: prove items and sessions are separated by child. docs/phase-4-both-children-notes.md; README + image tag 0.3.0-phase4. Live evidence: Harry 70 tasks / 1 message / 35 events (6 overdue); Finn 42 tasks / 1 message / 0 events (2 overdue). Finn's subjects are Year 7, Harry's are Year 11. Both sessions stored. Co-Authored-By: Paperclip <noreply@paperclip.ing>
91 lines
2.4 KiB
Go
91 lines
2.4 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
|
|
"gitea.lab.audasmedia.com.au/sam/compass_teams_nhs/internal/config"
|
|
"gitea.lab.audasmedia.com.au/sam/compass_teams_nhs/internal/store"
|
|
)
|
|
|
|
// scanCommand is the `school scan` entry point. It only records the outcome of a
|
|
// scan; the scan itself runs the patchright fetcher on the host and then
|
|
// `school parse` (AGENTS.md §11 Phase 4).
|
|
//
|
|
// `school scan record` exists so a fetch failure is written to the append-only
|
|
// `scans` table with ok = 0 (FR-12/FR-13): the dashboard can then show an
|
|
// explicit failure instead of an empty day.
|
|
func scanCommand(args []string) {
|
|
if len(args) == 0 || args[0] != "record" {
|
|
fmt.Fprintln(os.Stderr, "usage: school scan record --child NAME [--ok] [--pages N] [--items N] --message TEXT")
|
|
os.Exit(2)
|
|
}
|
|
fs := flag.NewFlagSet("scan record", flag.ContinueOnError)
|
|
var (
|
|
child string
|
|
pages int
|
|
items int
|
|
message string
|
|
ok bool
|
|
)
|
|
fs.StringVar(&child, "child", "", "child name (Harry or Finn)")
|
|
fs.BoolVar(&ok, "ok", false, "true when the scan succeeded")
|
|
fs.IntVar(&pages, "pages", 0, "pages fetched")
|
|
fs.IntVar(&items, "items", 0, "items found")
|
|
fs.StringVar(&message, "message", "", "failure message (required when --ok=false)")
|
|
_ = fs.Parse(args[1:])
|
|
|
|
if child == "" {
|
|
fmt.Fprintln(os.Stderr, "school scan record: --child is required")
|
|
os.Exit(2)
|
|
}
|
|
if !ok && message == "" {
|
|
fmt.Fprintln(os.Stderr, "school scan record: --message is required for a failed scan")
|
|
os.Exit(2)
|
|
}
|
|
if err := runScanRecord(child, pages, items, ok, message); err != nil {
|
|
fmt.Fprintln(os.Stderr, "school scan:", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func runScanRecord(child string, pages, items int, ok bool, message string) error {
|
|
ctx := context.Background()
|
|
|
|
cfg, err := config.LoadDB()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
st, err := store.Open(cfg.DBPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer st.Close()
|
|
if err := st.Migrate(ctx); err != nil {
|
|
return err
|
|
}
|
|
if err := st.SeedChildren(ctx, seedChildren...); err != nil {
|
|
return err
|
|
}
|
|
|
|
c, err := st.ChildByName(ctx, child)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if c == nil {
|
|
return fmt.Errorf("unknown child %q", child)
|
|
}
|
|
id, err := st.RecordScan(ctx, &c.ID, pages, items, ok, message)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
status := "ok"
|
|
if !ok {
|
|
status = "failed"
|
|
}
|
|
fmt.Printf("scan=%d child=%s status=%s pages=%d items=%d\n", id, c.Name, status, pages, items)
|
|
return nil
|
|
}
|