package main import ( "context" "database/sql" "fmt" "iter" "os" "strings" "sync" _ "embed" _ "github.com/mattn/go-sqlite3" "go.yarn.social/lextwt" "go.yarn.social/types" ) func run(c console) error { a := c.Args() app := &appState{ args: a, feeds: sync.Map{}, queue: FibHeap(func(a, b *Feed) bool { return a.LastScanOn.Time.Before(b.LastScanOn.Time) }), } // Setup DB err := func(ctx context.Context) error { db, err := app.DB() if err != nil { return err } defer db.Close() for _, stmt := range strings.Split(initSQL, ";") { _, err = db.ExecContext(ctx, stmt) if err != nil { return err } } return nil }(c.Context) if err != nil { return err } // Seed File err = func() error { f, err := os.Open(a.baseFeed) if err != nil { return err } defer f.Close() twtfile, err := lextwt.ParseFile(f, &types.Twter{ Nick: a.Nick, URI: a.URI, }) if err != nil { return fmt.Errorf("%w: %w", ErrParseFailed, err) } db, err := app.DB() if err != nil { return err } defer db.Close() return storeFeed(db, twtfile) }() if err != nil { return err } go refreshLoop(c, app) go httpServer(c, app) <-c.Done() return c.Err() } type appState struct { args args feeds sync.Map queue *fibHeap[Feed] } func (app *appState) DB() (*sql.DB, error) { return sql.Open(app.args.dbtype, app.args.dbfile) } func (app *appState) Feed(feedID string) *Feed { return nil } func (app *appState) Feeds() iter.Seq2[string, *Feed] { return func(yield func(string, *Feed) bool) { app.feeds.Range(func(k, v any) bool { key, _ := k.(string) value, ok := v.(*Feed) if !ok { return false } if !yield(key, value) { return false } return true }) } }