feat: add bg front matter
This commit is contained in:
@@ -0,0 +1,134 @@
|
|||||||
|
// Command seed-bg-intro seeds the Bhagavad-gītā front-matter (Dedication,
|
||||||
|
// Foreword, Preface, Introduction, The Disciplic Succession) into the
|
||||||
|
// `prose_chapters` MongoDB collection as intro-segments (book="bg", volume=0).
|
||||||
|
//
|
||||||
|
// The segment JSON is produced by extractor/scripts/bg_intro_extract.py.
|
||||||
|
//
|
||||||
|
// Usage (from the spsays-bff directory, so .env is picked up):
|
||||||
|
//
|
||||||
|
// go run ./cmd/seed-bg-intro
|
||||||
|
// go run ./cmd/seed-bg-intro --dir ../extractor/jsons/books/bg/intro
|
||||||
|
//
|
||||||
|
// It is idempotent: existing bg intro-segments are removed before insert.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
"github.com/prabhupadasays/spsays-bff/internal/config"
|
||||||
|
"github.com/prabhupadasays/spsays-bff/internal/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
type introSegment struct {
|
||||||
|
Slug string `json:"slug"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Book string `json:"book"`
|
||||||
|
Volume int `json:"volume"`
|
||||||
|
Order int `json:"order"`
|
||||||
|
Paragraphs []string `json:"paragraphs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
dir := flag.String("dir", "../extractor/jsons/books/bg/intro",
|
||||||
|
"directory containing bg intro-segment JSON files")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
cfg, err := config.Load()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "failed to load config: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger, _ := zap.NewDevelopment()
|
||||||
|
defer logger.Sync()
|
||||||
|
sugar := logger.Sugar()
|
||||||
|
|
||||||
|
mongoDB, err := repository.NewMongoDB(cfg.MongoURI, cfg.MongoDB, logger)
|
||||||
|
if err != nil {
|
||||||
|
sugar.Fatalf("failed to connect to MongoDB: %v", err)
|
||||||
|
}
|
||||||
|
defer mongoDB.Close()
|
||||||
|
|
||||||
|
entries, err := os.ReadDir(*dir)
|
||||||
|
if err != nil {
|
||||||
|
sugar.Fatalf("failed to read dir %s: %v", *dir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var segments []introSegment
|
||||||
|
var files []string
|
||||||
|
for _, e := range entries {
|
||||||
|
if e.IsDir() || filepath.Ext(e.Name()) != ".json" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
files = append(files, e.Name())
|
||||||
|
}
|
||||||
|
sort.Strings(files)
|
||||||
|
|
||||||
|
for _, name := range files {
|
||||||
|
raw, err := os.ReadFile(filepath.Join(*dir, name))
|
||||||
|
if err != nil {
|
||||||
|
sugar.Fatalf("read %s: %v", name, err)
|
||||||
|
}
|
||||||
|
var seg introSegment
|
||||||
|
if err := json.Unmarshal(raw, &seg); err != nil {
|
||||||
|
sugar.Fatalf("parse %s: %v", name, err)
|
||||||
|
}
|
||||||
|
if seg.Book != "bg" || seg.Type != "intro-segment" {
|
||||||
|
sugar.Warnf("skipping %s (book=%q type=%q)", name, seg.Book, seg.Type)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
segments = append(segments, seg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(segments) == 0 {
|
||||||
|
sugar.Fatal("no bg intro-segments found to seed")
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
col := mongoDB.Collection("prose_chapters")
|
||||||
|
|
||||||
|
// Idempotent: clear any previously seeded bg intro-segments.
|
||||||
|
del, err := col.DeleteMany(ctx, map[string]any{
|
||||||
|
"book": "bg",
|
||||||
|
"type": "intro-segment",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
sugar.Fatalf("delete existing bg intro-segments: %v", err)
|
||||||
|
}
|
||||||
|
sugar.Infof("removed %d existing bg intro-segment(s)", del.DeletedCount)
|
||||||
|
|
||||||
|
docs := make([]any, 0, len(segments))
|
||||||
|
for _, seg := range segments {
|
||||||
|
// chapter is intentionally null for intro-segments (matches the
|
||||||
|
// ProseChapterDoc shape used by KB/NoD front matter).
|
||||||
|
docs = append(docs, map[string]any{
|
||||||
|
"book": "bg",
|
||||||
|
"volume": 0,
|
||||||
|
"chapter": nil,
|
||||||
|
"title": seg.Title,
|
||||||
|
"type": "intro-segment",
|
||||||
|
"slug": seg.Slug,
|
||||||
|
"order": seg.Order,
|
||||||
|
"paragraphs": seg.Paragraphs,
|
||||||
|
})
|
||||||
|
sugar.Infof(" %s (order %d, %d paragraphs)", seg.Slug, seg.Order, len(seg.Paragraphs))
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := col.InsertMany(ctx, docs)
|
||||||
|
if err != nil {
|
||||||
|
sugar.Fatalf("insert bg intro-segments: %v", err)
|
||||||
|
}
|
||||||
|
sugar.Infof("inserted %d bg intro-segment(s)", len(res.InsertedIDs))
|
||||||
|
}
|
||||||
@@ -432,8 +432,8 @@ func (s *Server) setupRouter() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// --- Verse books without divisions ---
|
// --- Verse books without divisions ---
|
||||||
// BG, SB1962: pure verse books
|
// SB1962: pure verse book
|
||||||
for _, code := range []string{"bg", "sb1962"} {
|
for _, code := range []string{"sb1962"} {
|
||||||
code := code // capture for closure
|
code := code // capture for closure
|
||||||
r.Route("/"+code, func(r chi.Router) {
|
r.Route("/"+code, func(r chi.Router) {
|
||||||
r.Use(injectBookCode(code))
|
r.Use(injectBookCode(code))
|
||||||
@@ -445,8 +445,9 @@ func (s *Server) setupRouter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- Verse + prose intro books (no division) ---
|
// --- Verse + prose intro books (no division) ---
|
||||||
// BS, MM, NBS: have both verses and prose intro segments
|
// BG, BS, MM, NBS: verses plus prose front-matter segments
|
||||||
for _, code := range []string{"bs", "mm", "nbs"} {
|
// (the static /chapters routes take precedence over /{chapter}).
|
||||||
|
for _, code := range []string{"bg", "bs", "mm", "nbs"} {
|
||||||
code := code
|
code := code
|
||||||
r.Route("/"+code, func(r chi.Router) {
|
r.Route("/"+code, func(r chi.Router) {
|
||||||
r.Use(injectBookCode(code))
|
r.Use(injectBookCode(code))
|
||||||
|
|||||||
Reference in New Issue
Block a user