package handlers import ( "errors" "io/fs" "path/filepath" "time" "github.com/dustin/go-humanize" "sneak.berlin/go/webhooker/internal/database" "sneak.berlin/go/webhooker/internal/delivery" ) // TargetRowView is one row of the target list on a webhook's page. type TargetRowView struct { delivery.TargetView // Archive is a database target's archive file, and nil for a target // of any other type. Archive *ArchiveFileView } // ArchiveFileView is what a database target's row shows about its // archive file. type ArchiveFileView struct { Name string // Note stands in for the size and the last write when there are // none to show, and is empty when there are. Note string // Size is the size on disk. Written is how long ago the file was // last written, and WrittenUTC the full time the page shows on // hover. Size string Written string WrittenUTC string } // targetRows projects a webhook's targets for the target list on its // page. func (h *Handlers) targetRows( webhook *database.Webhook, targets []database.Target, ) []TargetRowView { views := delivery.NewTargetViews(targets) rows := make([]TargetRowView, len(views)) // NewTargetViews returns one view per target, in order. for i := range views { rows[i].TargetView = views[i] if targets[i].Type == database.TargetTypeDatabase { rows[i].Archive = h.archiveFileView(webhook, &targets[i]) } } return rows } // archiveFileView describes a database target's archive file from the // file's metadata alone; the archive is never opened. The file is found // by the name the archive writer uses, so it follows a rename of the // webhook or the target. func (h *Handlers) archiveFileView( webhook *database.Webhook, target *database.Target, ) *ArchiveFileView { path := delivery.ArchivePath(h.dbMgr, webhook, target) view := &ArchiveFileView{Name: filepath.Base(path)} file, err := delivery.StatArchive(path) switch { case errors.Is(err, fs.ErrNotExist): view.Note = "not created yet" case err != nil: h.log.Error( "failed to read archive file metadata", "target_id", target.ID, "error", err, ) view.Note = "could not be read" default: view.Size = humanize.Bytes(uint64(file.Size)) //nolint:gosec // never negative view.Written = humanize.Time(file.Written) view.WrittenUTC = file.Written.UTC().Format(time.DateTime) + " UTC" } return view }