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}