Get an ever updating ics link for all the events you RSVP to on the Atmosphere
whenslunch.app
3.3 kB
115 lines
1package models
2
3import (
4 "bytes"
5 "context"
6 "fmt"
7 "time"
8
9 community "tangled.org/pds.dad/whens-lunch/api/community"
10
11 "github.com/bluesky-social/indigo/atproto/syntax"
12
13 "gorm.io/gorm"
14 "gorm.io/gorm/clause"
15)
16
17type JetStreamCursor struct {
18 Url string `gorm:"primaryKey"`
19 Cursor int64 `gorm:"not null"`
20}
21
22type CalendarEvent struct {
23 URI string `gorm:"primaryKey;column:uri"`
24 RepoDID string `gorm:"not null;column:repo_did"`
25 StartsAt time.Time `gorm:"column:starts_at;index:idx_starts_at"`
26 EndsAt time.Time `gorm:"column:ends_at"`
27 RecordCreatedAt time.Time `gorm:"column:record_created_at"`
28 CreatedAt time.Time `gorm:"column:created_at"`
29 UpdatedAt time.Time `gorm:"column:updated_at"`
30 Record []byte `gorm:"not null;column:record"`
31}
32
33func AddOrUpdateEvent(ctx context.Context, DB *gorm.DB, event *community.CalendarEvent, aturi syntax.ATURI) error {
34 repoDID := aturi.Authority().String()
35 buf := bytes.Buffer{}
36 err := event.MarshalCBOR(&buf)
37 if err != nil {
38 return fmt.Errorf("failed to marshal event: %w", err)
39 }
40 createdAt, err := time.Parse(time.RFC3339, event.CreatedAt)
41 if err != nil {
42 return fmt.Errorf("invalid createdAt: %w", err)
43 }
44
45 dbEvent := &CalendarEvent{
46 URI: aturi.String(),
47 RepoDID: repoDID,
48 Record: buf.Bytes(),
49 RecordCreatedAt: createdAt,
50 }
51
52 if event.StartsAt != nil {
53 startsAt, err := time.Parse(time.RFC3339, *event.StartsAt)
54 if err != nil {
55 return fmt.Errorf("invalid startsAt: %w", err)
56 }
57 dbEvent.StartsAt = startsAt
58 }
59 if event.EndsAt != nil {
60 endsAt, err := time.Parse(time.RFC3339, *event.EndsAt)
61 if err != nil {
62 return fmt.Errorf("invalid endsAt: %w", err)
63 }
64 dbEvent.EndsAt = endsAt
65 }
66
67 err = DB.WithContext(ctx).Save(dbEvent).Error
68 if err != nil {
69 return fmt.Errorf("failed to add/update event: %w", err)
70 }
71 return nil
72
73}
74
75type RsvpEvent struct {
76 URI string `gorm:"primaryKey;column:uri"`
77 RepoDID string `gorm:"not null;column:repo_did;index;uniqueIndex:idx_rsvp_repo_event"`
78 EventURI string `gorm:"not null;column:event_uri;index;uniqueIndex:idx_rsvp_repo_event"`
79 Status string `gorm:"not null;column:status"`
80 CreatedAt time.Time `gorm:"column:created_at"`
81 UpdatedAt time.Time `gorm:"column:updated_at"`
82 Record []byte `gorm:"not null;column:record"`
83 Event CalendarEvent `gorm:"foreignKey:EventURI;references:URI"`
84}
85
86func AddOrUpdateRsvp(ctx context.Context, DB *gorm.DB, rsvp *community.CalendarRsvp, aturi syntax.ATURI) error {
87 repoDID := aturi.Authority().String()
88 buf := bytes.Buffer{}
89 err := rsvp.MarshalCBOR(&buf)
90 if err != nil {
91 return fmt.Errorf("failed to marshal rsvp: %w", err)
92 }
93
94 if rsvp.Subject == nil {
95 return fmt.Errorf("rsvp subject is nil")
96 }
97
98 dbRsvp := &RsvpEvent{
99 URI: aturi.String(),
100 RepoDID: repoDID,
101 EventURI: rsvp.Subject.Uri,
102 Status: rsvp.Status,
103 Record: buf.Bytes(),
104 }
105
106 err = DB.WithContext(ctx).Clauses(clause.OnConflict{
107 Columns: []clause.Column{{Name: "repo_did"}, {Name: "event_uri"}},
108 UpdateAll: true,
109 }).Create(dbRsvp).Error
110 if err != nil {
111 return fmt.Errorf("failed to add/update rsvp: %w", err)
112 }
113 return nil
114
115}