repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

pico / cmd / scripts / dates
Eric Bower  ·  2025-12-17

dates.go

  1package main
  2
  3import (
  4	"context"
  5	"database/sql"
  6	"log/slog"
  7	"os"
  8	"time"
  9
 10	"github.com/jmoiron/sqlx"
 11	"github.com/picosh/pico/pkg/db"
 12	"github.com/picosh/pico/pkg/db/postgres"
 13	"github.com/picosh/pico/pkg/shared"
 14)
 15
 16func findPosts(dbpool *sqlx.DB) ([]*db.Post, error) {
 17	var posts []*db.Post
 18	rs, err := dbpool.Query(`SELECT
 19		id, user_id, filename, title, text, description,
 20		created_at, publish_at, updated_at, hidden, cur_space
 21		FROM posts
 22		WHERE cur_space = 'prose' OR cur_space = 'lists'
 23	`)
 24	if err != nil {
 25		return posts, err
 26	}
 27	for rs.Next() {
 28		post := &db.Post{}
 29		err := rs.Scan(
 30			&post.ID,
 31			&post.UserID,
 32			&post.Filename,
 33			&post.Title,
 34			&post.Text,
 35			&post.Description,
 36			&post.CreatedAt,
 37			&post.PublishAt,
 38			&post.UpdatedAt,
 39			&post.Hidden,
 40			&post.Space,
 41		)
 42		if err != nil {
 43			return posts, err
 44		}
 45
 46		posts = append(posts, post)
 47	}
 48	if rs.Err() != nil {
 49		return posts, rs.Err()
 50	}
 51	return posts, nil
 52}
 53
 54func updateDates(tx *sql.Tx, postID string, date *time.Time) error {
 55	_, err := tx.Exec("UPDATE posts SET publish_at = $1 WHERE id = $2", date, postID)
 56	return err
 57}
 58
 59func main() {
 60	logger := slog.Default()
 61
 62	picoCfg := shared.NewConfigSite()
 63	picoCfg.Logger = logger
 64	picoCfg.DbURL = os.Getenv("DATABASE_URL")
 65	picoDb := postgres.NewDB(picoCfg.DbURL, picoCfg.Logger)
 66
 67	logger.Info("fetching all posts")
 68	posts, err := findPosts(picoDb.Db)
 69	if err != nil {
 70		panic(err)
 71	}
 72	logger.Info("found posts", "len", len(posts))
 73
 74	ctx := context.Background()
 75	tx, err := picoDb.Db.BeginTx(ctx, nil)
 76	if err != nil {
 77		panic(err)
 78	}
 79
 80	defer func() {
 81		err = tx.Rollback()
 82		panic(err)
 83	}()
 84
 85	datesFixed := []string{}
 86	logger.Info("updating dates")
 87	for _, post := range posts {
 88		if post.Space == "prose" {
 89			parsed, err := shared.ParseText(post.Text)
 90			if err != nil {
 91				logger.Error(err.Error())
 92				continue
 93			}
 94
 95			if parsed.PublishAt != nil && !parsed.PublishAt.IsZero() {
 96				err = updateDates(tx, post.ID, parsed.PublishAt)
 97				if err != nil {
 98					logger.Error(err.Error())
 99					continue
100				}
101
102				if !parsed.PublishAt.Equal(*post.PublishAt) {
103					datesFixed = append(datesFixed, post.ID)
104				}
105			}
106		} else if post.Space == "lists" {
107			parsed := shared.ListParseText(post.Text)
108			if err != nil {
109				logger.Error(err.Error())
110				continue
111			}
112
113			if parsed.PublishAt != nil && !parsed.PublishAt.IsZero() {
114				err = updateDates(tx, post.ID, parsed.PublishAt)
115				if err != nil {
116					logger.Error(err.Error())
117					continue
118				}
119				if !parsed.PublishAt.Equal(*post.PublishAt) {
120					datesFixed = append(datesFixed, post.ID)
121				}
122			}
123		}
124	}
125
126	err = tx.Commit()
127	if err != nil {
128		panic(err)
129	}
130	logger.Info("dates fixed!", "len", len(datesFixed))
131}