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}