package bm import ( "context" "errors" "sync" "git.golem15.com/golem15/summercms/modules/diary" "git.golem15.com/jakub/sm-bm-plugin/classes" "git.golem15.com/jakub/sm-bm-plugin/jobs" "gocloud.dev/blob" "gorm.io/gorm" ) // pdfToolWarning is logged at most once per process when pdftotext is // missing. var pdfToolWarning sync.Once // extractMaterialText runs one jz.bm.extract_material_text job: the text of // the material's PDFs that have none yet is extracted and stored, then the // material's search document is synced. A missing database or bucket is an // error, so River retries; a missing pdftotext is logged once and the // document is still synced. func (p *Plugin) extractMaterialText(ctx context.Context, args jobs.ExtractMaterialTextArgs) error { if p.app == nil { return errors.New("jz.bm: app is not booted") } db, ok := p.app.Lookup[*gorm.DB]() if !ok || db == nil { return errors.New("jz.bm: database is not configured") } bucket, ok := p.app.Lookup[*blob.Bucket]() if !ok || bucket == nil { return errors.New("jz.bm: the uploads bucket is not configured") } _, err := classes.EnsureFileTexts(ctx, db, bucket, classes.DefaultPDFText(), args.MaterialID) switch { case errors.Is(err, classes.ErrPDFToolMissing): pdfToolWarning.Do(func() { diary.For("jz.bm").Warn("pdftotext not found; attached PDFs add no search text until poppler-utils is installed") }) case err != nil: return err } p.materialIndex.Sync(ctx, db, args.MaterialID) return nil }