Get an ever updating ics link for all the events you RSVP to on the Atmosphere whenslunch.app
0

Configure Feed

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

whens-lunch / models / models.go
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}