main pico / cmd / scripts / dates / dates.go
Antonio Mika  ·  2026-10-10
  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	picoDb := postgres.NewDB(os.Getenv("DATABASE_URL"), logger)
 63
 64	logger.Info("fetching all posts")
 65	posts, err := findPosts(picoDb.Db)
 66	if err != nil {
 67		panic(err)
 68	}
 69	logger.Info("found posts", "len", len(posts))
 70
 71	ctx := context.Background()
 72	tx, err := picoDb.Db.BeginTx(ctx, nil)
 73	if err != nil {
 74		panic(err)
 75	}
 76
 77	defer func() {
 78		err = tx.Rollback()
 79		panic(err)
 80	}()
 81
 82	datesFixed := []string{}
 83	logger.Info("updating dates")
 84	for _, post := range posts {
 85		if post.Space == "prose" {
 86			parsed, err := shared.ParseText(post.Text)
 87			if err != nil {
 88				logger.Error(err.Error())
 89				continue
 90			}
 91
 92			if parsed.PublishAt != nil && !parsed.PublishAt.IsZero() {
 93				err = updateDates(tx, post.ID, parsed.PublishAt)
 94				if err != nil {
 95					logger.Error(err.Error())
 96					continue
 97				}
 98
 99				if !parsed.PublishAt.Equal(*post.PublishAt) {
100					datesFixed = append(datesFixed, post.ID)
101				}
102			}
103		} else if post.Space == "lists" {
104			parsed := shared.ListParseText(post.Text)
105			if err != nil {
106				logger.Error(err.Error())
107				continue
108			}
109
110			if parsed.PublishAt != nil && !parsed.PublishAt.IsZero() {
111				err = updateDates(tx, post.ID, parsed.PublishAt)
112				if err != nil {
113					logger.Error(err.Error())
114					continue
115				}
116				if !parsed.PublishAt.Equal(*post.PublishAt) {
117					datesFixed = append(datesFixed, post.ID)
118				}
119			}
120		}
121	}
122
123	err = tx.Commit()
124	if err != nil {
125		panic(err)
126	}
127	logger.Info("dates fixed!", "len", len(datesFixed))
128}