Monorepo for Tangled tangled.org
2

Configure Feed

Select the types of activity you want to include in your feed.

1package db 2 3import ( 4 "database/sql" 5 "fmt" 6 "time" 7) 8 9// Newsletter preference status values. Both states hide the signup widget; 10// they're distinguished so we can later reconcile with Resend or re-prompt 11// dismissed-but-not-subscribed users if we ever want to. 12const ( 13 NewsletterStatusSubscribed = "subscribed" 14 NewsletterStatusDismissed = "dismissed" 15) 16 17type NewsletterPref struct { 18 ID int64 19 UserDid string 20 Status string 21 Email string 22 UpdatedAt time.Time 23} 24 25// GetNewsletterPref returns the newsletter preference row for a user, or nil 26// when no row exists (the caller should treat nil as "show the widget"). 27func GetNewsletterPref(e Execer, did string) (*NewsletterPref, error) { 28 var ( 29 pref NewsletterPref 30 email sql.NullString 31 updatedAt string 32 ) 33 34 err := e.QueryRow( 35 `select id, user_did, status, email, updated_at 36 from newsletter_preferences 37 where user_did = ?`, 38 did, 39 ).Scan(&pref.ID, &pref.UserDid, &pref.Status, &email, &updatedAt) 40 if err == sql.ErrNoRows { 41 return nil, nil 42 } 43 if err != nil { 44 return nil, err 45 } 46 47 if email.Valid { 48 pref.Email = email.String 49 } 50 if t, perr := time.Parse(time.RFC3339, updatedAt); perr == nil { 51 pref.UpdatedAt = t 52 } 53 54 return &pref, nil 55} 56 57// UpsertNewsletterPref writes or replaces a user's newsletter preference and 58// refreshes updated_at. Passing an empty email is fine — the column is 59// nullable and is only meaningful for subscribed rows. 60func UpsertNewsletterPref(e Execer, did, status, email string) error { 61 if status != NewsletterStatusSubscribed && status != NewsletterStatusDismissed { 62 return fmt.Errorf("invalid newsletter status %q", status) 63 } 64 65 var emailArg any 66 if email != "" { 67 emailArg = email 68 } else { 69 emailArg = nil 70 } 71 72 _, err := e.Exec( 73 `insert into newsletter_preferences (user_did, status, email, updated_at) 74 values (?, ?, ?, strftime('%Y-%m-%dT%H:%M:%SZ', 'now')) 75 on conflict(user_did) do update set 76 status = excluded.status, 77 email = coalesce(excluded.email, newsletter_preferences.email), 78 updated_at = excluded.updated_at`, 79 did, 80 status, 81 emailArg, 82 ) 83 if err != nil { 84 return fmt.Errorf("upsert newsletter pref: %w", err) 85 } 86 return nil 87}