A community based topic aggregation platform built on atproto
1package communities 2 3import ( 4 "time" 5) 6 7// Community represents a Coves community indexed from the firehose 8// Communities are federated, instance-scoped forums built on atProto 9type Community struct { 10 ID int `json:"id" db:"id"` 11 DID string `json:"did" db:"did"` // Permanent community identifier (did:plc:xxx) 12 Handle string `json:"handle" db:"handle"` // Scoped handle (!gaming@coves.social) 13 Name string `json:"name" db:"name"` // Short name (local part of handle) 14 DisplayName string `json:"displayName" db:"display_name"` // Display name for UI 15 Description string `json:"description" db:"description"` // Community description 16 DescriptionFacets []byte `json:"descriptionFacets,omitempty" db:"description_facets"` // Rich text annotations (JSONB) 17 18 // Media 19 AvatarCID string `json:"avatarCid,omitempty" db:"avatar_cid"` // CID of avatar image 20 BannerCID string `json:"bannerCid,omitempty" db:"banner_cid"` // CID of banner image 21 22 // Ownership 23 OwnerDID string `json:"ownerDid" db:"owner_did"` // V2: same as DID (community owns itself) 24 CreatedByDID string `json:"createdByDid" db:"created_by_did"` // User who created the community 25 HostedByDID string `json:"hostedByDid" db:"hosted_by_did"` // Instance hosting this community 26 27 // V2: PDS Account Credentials (NEVER expose in public API responses!) 28 PDSEmail string `json:"-" db:"pds_email"` // System email for PDS account 29 PDSPasswordHash string `json:"-" db:"pds_password_hash"` // bcrypt hash for re-authentication 30 PDSAccessToken string `json:"-" db:"pds_access_token"` // JWT for API calls (expires) 31 PDSRefreshToken string `json:"-" db:"pds_refresh_token"` // For refreshing sessions 32 PDSURL string `json:"-" db:"pds_url"` // PDS hosting this community's repo 33 34 // Visibility & Federation 35 Visibility string `json:"visibility" db:"visibility"` // public, unlisted, private 36 AllowExternalDiscovery bool `json:"allowExternalDiscovery" db:"allow_external_discovery"` // Can other instances index? 37 38 // Moderation 39 ModerationType string `json:"moderationType,omitempty" db:"moderation_type"` // moderator, sortition 40 ContentWarnings []string `json:"contentWarnings,omitempty" db:"content_warnings"` // NSFW, violence, spoilers 41 42 // Statistics (cached counts) 43 MemberCount int `json:"memberCount" db:"member_count"` 44 SubscriberCount int `json:"subscriberCount" db:"subscriber_count"` 45 PostCount int `json:"postCount" db:"post_count"` 46 47 // Federation metadata (future: Lemmy interop) 48 FederatedFrom string `json:"federatedFrom,omitempty" db:"federated_from"` // lemmy, coves 49 FederatedID string `json:"federatedId,omitempty" db:"federated_id"` // Original ID on source platform 50 51 // Timestamps 52 CreatedAt time.Time `json:"createdAt" db:"created_at"` 53 UpdatedAt time.Time `json:"updatedAt" db:"updated_at"` 54 55 // AT-Proto metadata 56 RecordURI string `json:"recordUri,omitempty" db:"record_uri"` // AT-URI of community profile record 57 RecordCID string `json:"recordCid,omitempty" db:"record_cid"` // CID of community profile record 58} 59 60// Subscription represents a lightweight feed follow (user subscribes to see posts) 61type Subscription struct { 62 ID int `json:"id" db:"id"` 63 UserDID string `json:"userDid" db:"user_did"` 64 CommunityDID string `json:"communityDid" db:"community_did"` 65 SubscribedAt time.Time `json:"subscribedAt" db:"subscribed_at"` 66 67 // AT-Proto metadata (subscription is a record in user's repo) 68 RecordURI string `json:"recordUri,omitempty" db:"record_uri"` 69 RecordCID string `json:"recordCid,omitempty" db:"record_cid"` 70} 71 72// Membership represents active participation with reputation tracking 73type Membership struct { 74 ID int `json:"id" db:"id"` 75 UserDID string `json:"userDid" db:"user_did"` 76 CommunityDID string `json:"communityDid" db:"community_did"` 77 ReputationScore int `json:"reputationScore" db:"reputation_score"` // Gained through participation 78 ContributionCount int `json:"contributionCount" db:"contribution_count"` // Posts + comments + actions 79 JoinedAt time.Time `json:"joinedAt" db:"joined_at"` 80 LastActiveAt time.Time `json:"lastActiveAt" db:"last_active_at"` 81 82 // Moderation status 83 IsBanned bool `json:"isBanned" db:"is_banned"` 84 IsModerator bool `json:"isModerator" db:"is_moderator"` 85} 86 87// ModerationAction represents a moderation action taken against a community 88type ModerationAction struct { 89 ID int `json:"id" db:"id"` 90 CommunityDID string `json:"communityDid" db:"community_did"` 91 Action string `json:"action" db:"action"` // delist, quarantine, remove 92 Reason string `json:"reason,omitempty" db:"reason"` 93 InstanceDID string `json:"instanceDid" db:"instance_did"` // Which instance took this action 94 Broadcast bool `json:"broadcast" db:"broadcast"` // Share signal with network? 95 CreatedAt time.Time `json:"createdAt" db:"created_at"` 96 ExpiresAt *time.Time `json:"expiresAt,omitempty" db:"expires_at"` // Optional: temporary moderation 97} 98 99// CreateCommunityRequest represents input for creating a new community 100type CreateCommunityRequest struct { 101 Name string `json:"name"` 102 DisplayName string `json:"displayName,omitempty"` 103 Description string `json:"description"` 104 AvatarBlob []byte `json:"avatarBlob,omitempty"` // Raw image data 105 BannerBlob []byte `json:"bannerBlob,omitempty"` // Raw image data 106 Rules []string `json:"rules,omitempty"` 107 Categories []string `json:"categories,omitempty"` 108 Language string `json:"language,omitempty"` 109 Visibility string `json:"visibility"` // public, unlisted, private 110 AllowExternalDiscovery bool `json:"allowExternalDiscovery"` 111 CreatedByDID string `json:"createdByDid"` // User creating the community 112 HostedByDID string `json:"hostedByDid"` // Instance hosting the community 113} 114 115// UpdateCommunityRequest represents input for updating community metadata 116type UpdateCommunityRequest struct { 117 CommunityDID string `json:"communityDid"` 118 UpdatedByDID string `json:"updatedByDid"` // User making the update (for authorization) 119 DisplayName *string `json:"displayName,omitempty"` 120 Description *string `json:"description,omitempty"` 121 AvatarBlob []byte `json:"avatarBlob,omitempty"` 122 BannerBlob []byte `json:"bannerBlob,omitempty"` 123 Visibility *string `json:"visibility,omitempty"` 124 AllowExternalDiscovery *bool `json:"allowExternalDiscovery,omitempty"` 125 ModerationType *string `json:"moderationType,omitempty"` 126 ContentWarnings []string `json:"contentWarnings,omitempty"` 127} 128 129// ListCommunitiesRequest represents query parameters for listing communities 130type ListCommunitiesRequest struct { 131 Limit int `json:"limit"` 132 Offset int `json:"offset"` 133 Visibility string `json:"visibility,omitempty"` // Filter by visibility 134 HostedBy string `json:"hostedBy,omitempty"` // Filter by hosting instance 135 SortBy string `json:"sortBy,omitempty"` // created_at, member_count, post_count 136 SortOrder string `json:"sortOrder,omitempty"` // asc, desc 137} 138 139// SearchCommunitiesRequest represents query parameters for searching communities 140type SearchCommunitiesRequest struct { 141 Query string `json:"query"` // Search term 142 Limit int `json:"limit"` 143 Offset int `json:"offset"` 144 Visibility string `json:"visibility,omitempty"` // Filter by visibility 145}