A community based topic aggregation platform built on atproto
1package posts
2
3import (
4 "time"
5)
6
7// SelfLabels represents self-applied content labels per com.atproto.label.defs#selfLabels
8// This is the structured format used in atProto for content warnings
9type SelfLabels struct {
10 Values []SelfLabel `json:"values"`
11}
12
13// SelfLabel represents a single label value per com.atproto.label.defs#selfLabel
14// Neg is optional and negates the label when true
15type SelfLabel struct {
16 Neg *bool `json:"neg,omitempty"`
17 Val string `json:"val"`
18}
19
20// Post represents a post in the AppView database
21// Posts are indexed from the firehose after being written to community repositories
22type Post struct {
23 CreatedAt time.Time `json:"createdAt" db:"created_at"`
24 IndexedAt time.Time `json:"indexedAt" db:"indexed_at"`
25 EditedAt *time.Time `json:"editedAt,omitempty" db:"edited_at"`
26 Embed *string `json:"embed,omitempty" db:"embed"`
27 DeletedAt *time.Time `json:"deletedAt,omitempty" db:"deleted_at"`
28 ContentLabels *string `json:"labels,omitempty" db:"content_labels"`
29 Title *string `json:"title,omitempty" db:"title"`
30 Content *string `json:"content,omitempty" db:"content"`
31 ContentFacets *string `json:"contentFacets,omitempty" db:"content_facets"`
32 CID string `json:"cid" db:"cid"`
33 CommunityDID string `json:"communityDid" db:"community_did"`
34 RKey string `json:"rkey" db:"rkey"`
35 URI string `json:"uri" db:"uri"`
36 AuthorDID string `json:"authorDid" db:"author_did"`
37 ID int64 `json:"id" db:"id"`
38 UpvoteCount int `json:"upvoteCount" db:"upvote_count"`
39 DownvoteCount int `json:"downvoteCount" db:"downvote_count"`
40 Score int `json:"score" db:"score"`
41 CommentCount int `json:"commentCount" db:"comment_count"`
42}
43
44// CreatePostRequest represents input for creating a new post
45// Matches social.coves.community.post.create lexicon input schema
46type CreatePostRequest struct {
47 OriginalAuthor interface{} `json:"originalAuthor,omitempty"`
48 FederatedFrom interface{} `json:"federatedFrom,omitempty"`
49 Location interface{} `json:"location,omitempty"`
50 Title *string `json:"title,omitempty"`
51 Content *string `json:"content,omitempty"`
52 Embed map[string]interface{} `json:"embed,omitempty"`
53 ThumbnailURL *string `json:"thumbnailUrl,omitempty"`
54 Labels *SelfLabels `json:"labels,omitempty"`
55 Community string `json:"community"`
56 AuthorDID string `json:"authorDid"`
57 Facets []interface{} `json:"facets,omitempty"`
58}
59
60// CreatePostResponse represents the response from creating a post
61// Matches social.coves.community.post.create lexicon output schema
62type CreatePostResponse struct {
63 URI string `json:"uri"` // AT-URI of created post
64 CID string `json:"cid"` // CID of created post
65}
66
67// PostRecord represents the actual atProto record structure written to PDS
68// This is the data structure that gets stored in the community's repository
69type PostRecord struct {
70 OriginalAuthor interface{} `json:"originalAuthor,omitempty"`
71 FederatedFrom interface{} `json:"federatedFrom,omitempty"`
72 Location interface{} `json:"location,omitempty"`
73 Title *string `json:"title,omitempty"`
74 Content *string `json:"content,omitempty"`
75 Embed map[string]interface{} `json:"embed,omitempty"`
76 Labels *SelfLabels `json:"labels,omitempty"`
77 Type string `json:"$type"`
78 Community string `json:"community"`
79 Author string `json:"author"`
80 CreatedAt string `json:"createdAt"`
81 Facets []interface{} `json:"facets,omitempty"`
82}
83
84// PostView represents the full view of a post with all metadata
85// Matches social.coves.community.post.get#postView lexicon
86// Used in feeds and get endpoints
87type PostView struct {
88 IndexedAt time.Time `json:"indexedAt"`
89 CreatedAt time.Time `json:"createdAt"`
90 Record interface{} `json:"record,omitempty"`
91 Embed interface{} `json:"embed,omitempty"`
92 Language *string `json:"language,omitempty"`
93 EditedAt *time.Time `json:"editedAt,omitempty"`
94 Title *string `json:"title,omitempty"`
95 Text *string `json:"text,omitempty"`
96 Viewer *ViewerState `json:"viewer,omitempty"`
97 Author *AuthorView `json:"author"`
98 Stats *PostStats `json:"stats,omitempty"`
99 Community *CommunityRef `json:"community"`
100 RKey string `json:"rkey"`
101 CID string `json:"cid"`
102 URI string `json:"uri"`
103 TextFacets []interface{} `json:"textFacets,omitempty"`
104 UpvoteCount int `json:"-"`
105 DownvoteCount int `json:"-"`
106 Score int `json:"-"`
107 CommentCount int `json:"-"`
108}
109
110// AuthorView represents author information in post views
111type AuthorView struct {
112 DisplayName *string `json:"displayName,omitempty"`
113 Avatar *string `json:"avatar,omitempty"`
114 Reputation *int `json:"reputation,omitempty"`
115 DID string `json:"did"`
116 Handle string `json:"handle"`
117}
118
119// CommunityRef represents minimal community info in post views
120type CommunityRef struct {
121 Avatar *string `json:"avatar,omitempty"`
122 DID string `json:"did"`
123 Handle string `json:"handle"`
124 Name string `json:"name"`
125 PDSURL string `json:"-"` // Not exposed to API, used for blob URL transformation
126}
127
128// PostStats represents aggregated statistics
129type PostStats struct {
130 TagCounts map[string]int `json:"tagCounts,omitempty"`
131 Upvotes int `json:"upvotes"`
132 Downvotes int `json:"downvotes"`
133 Score int `json:"score"`
134 CommentCount int `json:"commentCount"`
135 ShareCount int `json:"shareCount,omitempty"`
136}
137
138// ViewerState represents the viewer's relationship with the post
139type ViewerState struct {
140 Vote *string `json:"vote,omitempty"`
141 VoteURI *string `json:"voteUri,omitempty"`
142 SavedURI *string `json:"savedUri,omitempty"`
143 Tags []string `json:"tags,omitempty"`
144 Saved bool `json:"saved"`
145}