A community based topic aggregation platform built on atproto

Merge pull request #4 from BrettM86/feature/lexicon-procedure-query-implementation

Implement query and procedure lexicon definitions

+59
internal/atproto/lexicon/social/coves/actor/blockUser.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.actor.blockUser",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Block another user",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["subject"],
+
"properties": {
+
"subject": {
+
"type": "string",
+
"format": "did",
+
"description": "DID of the user to block"
+
},
+
"reason": {
+
"type": "string",
+
"maxGraphemes": 300,
+
"maxLength": 3000,
+
"description": "Optional reason for blocking"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri", "cid"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the created block record"
+
},
+
"cid": {
+
"type": "string",
+
"format": "cid",
+
"description": "CID of the created block record"
+
},
+
"existing": {
+
"type": "boolean",
+
"description": "True if user was already blocked"
+
}
+
}
+
}
+
},
+
"errors": [
+
{
+
"name": "SubjectNotFound",
+
"description": "Subject user not found"
+
}
+
]
+
}
+
}
+
}
+102
internal/atproto/lexicon/social/coves/actor/getProfile.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.actor.getProfile",
+
"defs": {
+
"main": {
+
"type": "query",
+
"description": "Get a user's profile with aggregated statistics",
+
"parameters": {
+
"type": "params",
+
"required": ["actor"],
+
"properties": {
+
"actor": {
+
"type": "string",
+
"format": "at-identifier",
+
"description": "DID or handle of the user"
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["did", "profile"],
+
"properties": {
+
"did": {
+
"type": "string",
+
"format": "did"
+
},
+
"profile": {
+
"type": "ref",
+
"ref": "social.coves.actor.profile"
+
},
+
"stats": {
+
"type": "ref",
+
"ref": "#profileStats"
+
},
+
"viewer": {
+
"type": "ref",
+
"ref": "#viewerState",
+
"description": "Viewer's relationship to this profile"
+
}
+
}
+
}
+
}
+
},
+
"profileStats": {
+
"type": "object",
+
"description": "Aggregated statistics for a user profile",
+
"required": ["postCount", "commentCount", "communityCount", "savedCount", "reputation"],
+
"properties": {
+
"postCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Total number of posts created"
+
},
+
"commentCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Total number of comments made"
+
},
+
"communityCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Number of communities subscribed to"
+
},
+
"savedCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Number of saved items"
+
},
+
"reputation": {
+
"type": "integer",
+
"description": "Global reputation score"
+
},
+
"membershipCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Number of communities with membership status"
+
}
+
}
+
},
+
"viewerState": {
+
"type": "object",
+
"description": "The viewing user's relationship to this profile",
+
"properties": {
+
"blocked": {
+
"type": "boolean",
+
"description": "Whether the viewer has blocked this user"
+
},
+
"blockedBy": {
+
"type": "boolean",
+
"description": "Whether the viewer is blocked by this user"
+
},
+
"blockUri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the block record if viewer blocked this user"
+
}
+
}
+
}
+
}
+
}
+1 -1
internal/atproto/lexicon/social/coves/actor/getSaved.json
···
"id": "social.coves.actor.getSaved",
"defs": {
"main": {
-
"type": "procedure",
+
"type": "query",
"description": "Get all saved posts and comments for the authenticated user",
"input": {
"encoding": "application/json",
+3 -3
internal/atproto/lexicon/social/coves/actor/membership.json
···
"key": "tid",
"record": {
"type": "object",
-
"required": ["community", "reputation", "createdAt", "createdAt"],
+
"required": ["community", "reputation", "createdAt"],
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community (DID-based)"
+
"format": "at-identifier",
+
"description": "DID or handle of the community"
},
"reputation": {
"type": "integer",
+197
internal/atproto/lexicon/social/coves/actor/preferences.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.actor.preferences",
+
"defs": {
+
"main": {
+
"type": "record",
+
"description": "User preferences and settings",
+
"key": "literal:self",
+
"record": {
+
"type": "object",
+
"properties": {
+
"feedPreferences": {
+
"type": "ref",
+
"ref": "#feedPreferences"
+
},
+
"contentFiltering": {
+
"type": "ref",
+
"ref": "#contentFiltering"
+
},
+
"notificationSettings": {
+
"type": "ref",
+
"ref": "#notificationSettings"
+
},
+
"privacySettings": {
+
"type": "ref",
+
"ref": "#privacySettings"
+
},
+
"displayPreferences": {
+
"type": "ref",
+
"ref": "#displayPreferences"
+
}
+
}
+
}
+
},
+
"feedPreferences": {
+
"type": "object",
+
"description": "Feed and content preferences",
+
"properties": {
+
"defaultFeed": {
+
"type": "string",
+
"enum": ["home", "popular", "new"],
+
"default": "home"
+
},
+
"defaultSort": {
+
"type": "string",
+
"enum": ["hot", "new", "top", "controversial"],
+
"default": "hot"
+
},
+
"showNSFW": {
+
"type": "boolean",
+
"default": false
+
},
+
"blurNSFW": {
+
"type": "boolean",
+
"default": true,
+
"description": "Blur NSFW content until clicked"
+
},
+
"autoplayVideos": {
+
"type": "boolean",
+
"default": false
+
},
+
"infiniteScroll": {
+
"type": "boolean",
+
"default": true
+
}
+
}
+
},
+
"contentFiltering": {
+
"type": "object",
+
"description": "Content filtering preferences",
+
"properties": {
+
"blockedTags": {
+
"type": "array",
+
"items": {
+
"type": "string"
+
},
+
"description": "Tags to filter out from feeds"
+
},
+
"blockedCommunities": {
+
"type": "array",
+
"items": {
+
"type": "string",
+
"format": "did"
+
},
+
"description": "Communities to filter out from /all feeds"
+
},
+
"mutedWords": {
+
"type": "array",
+
"items": {
+
"type": "string"
+
},
+
"description": "Words to filter out from content"
+
},
+
"languageFilter": {
+
"type": "array",
+
"items": {
+
"type": "string",
+
"format": "language"
+
},
+
"description": "Only show content in these languages"
+
}
+
}
+
},
+
"notificationSettings": {
+
"type": "object",
+
"description": "Notification preferences",
+
"properties": {
+
"postReplies": {
+
"type": "boolean",
+
"default": true
+
},
+
"commentReplies": {
+
"type": "boolean",
+
"default": true
+
},
+
"mentions": {
+
"type": "boolean",
+
"default": true
+
},
+
"upvotes": {
+
"type": "boolean",
+
"default": false
+
},
+
"newFollowers": {
+
"type": "boolean",
+
"default": true
+
},
+
"communityInvites": {
+
"type": "boolean",
+
"default": true
+
},
+
"moderatorNotifications": {
+
"type": "boolean",
+
"default": true,
+
"description": "Notifications for moderator actions in your communities"
+
}
+
}
+
},
+
"privacySettings": {
+
"type": "object",
+
"description": "Privacy preferences",
+
"properties": {
+
"profileVisibility": {
+
"type": "string",
+
"enum": ["public", "authenticated", "followers"],
+
"default": "public"
+
},
+
"showSubscriptions": {
+
"type": "boolean",
+
"default": true
+
},
+
"showSavedPosts": {
+
"type": "boolean",
+
"default": false
+
},
+
"showVoteHistory": {
+
"type": "boolean",
+
"default": false
+
},
+
"allowDMs": {
+
"type": "string",
+
"enum": ["everyone", "followers", "none"],
+
"default": "everyone"
+
}
+
}
+
},
+
"displayPreferences": {
+
"type": "object",
+
"description": "Display and UI preferences",
+
"properties": {
+
"theme": {
+
"type": "string",
+
"enum": ["light", "dark", "auto"],
+
"default": "auto"
+
},
+
"compactView": {
+
"type": "boolean",
+
"default": false
+
},
+
"showAvatars": {
+
"type": "boolean",
+
"default": true
+
},
+
"showThumbnails": {
+
"type": "boolean",
+
"default": true
+
},
+
"postsPerPage": {
+
"type": "integer",
+
"minimum": 10,
+
"maximum": 100,
+
"default": 25
+
}
+
}
+
}
+
}
+
}
+63
internal/atproto/lexicon/social/coves/actor/saveItem.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.actor.saveItem",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Save a post or comment",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["subject", "type"],
+
"properties": {
+
"subject": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the post or comment to save"
+
},
+
"type": {
+
"type": "string",
+
"enum": ["post", "comment"],
+
"description": "Type of content being saved"
+
},
+
"note": {
+
"type": "string",
+
"maxLength": 300,
+
"description": "Optional note about why this was saved"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri", "cid"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the created saved record"
+
},
+
"cid": {
+
"type": "string",
+
"format": "cid",
+
"description": "CID of the created saved record"
+
},
+
"existing": {
+
"type": "boolean",
+
"description": "True if item was already saved"
+
}
+
}
+
}
+
},
+
"errors": [
+
{
+
"name": "SubjectNotFound",
+
"description": "The post or comment to save was not found"
+
}
+
]
+
}
+
}
+
}
+2 -2
internal/atproto/lexicon/social/coves/actor/subscription.json
···
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community (DID-based)"
+
"format": "at-identifier",
+
"description": "DID or handle of the community"
},
"createdAt": {
"type": "string",
+37
internal/atproto/lexicon/social/coves/actor/unblockUser.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.actor.unblockUser",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Unblock a previously blocked user",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["subject"],
+
"properties": {
+
"subject": {
+
"type": "string",
+
"format": "did",
+
"description": "DID of the user to unblock"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"properties": {}
+
}
+
},
+
"errors": [
+
{
+
"name": "NotBlocked",
+
"description": "User is not currently blocked"
+
}
+
]
+
}
+
}
+
}
+37
internal/atproto/lexicon/social/coves/actor/unsaveItem.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.actor.unsaveItem",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Unsave a previously saved post or comment",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["subject"],
+
"properties": {
+
"subject": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the post or comment to unsave"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"properties": {}
+
}
+
},
+
"errors": [
+
{
+
"name": "NotSaved",
+
"description": "Item is not currently saved"
+
}
+
]
+
}
+
}
+
}
+75
internal/atproto/lexicon/social/coves/actor/updateProfile.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.actor.updateProfile",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Update the authenticated user's profile",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"properties": {
+
"displayName": {
+
"type": "string",
+
"maxGraphemes": 64,
+
"maxLength": 640,
+
"description": "Optional display name"
+
},
+
"bio": {
+
"type": "string",
+
"maxGraphemes": 256,
+
"maxLength": 2560,
+
"description": "User bio with rich text support"
+
},
+
"bioMarkup": {
+
"type": "array",
+
"description": "Rich text annotations for bio",
+
"items": {
+
"type": "union",
+
"refs": [
+
"social.coves.richtext.markup",
+
"social.coves.richtext.mention",
+
"social.coves.richtext.link"
+
]
+
}
+
},
+
"avatar": {
+
"type": "blob",
+
"accept": ["image/png", "image/jpeg", "image/webp"],
+
"maxSize": 1000000
+
},
+
"banner": {
+
"type": "blob",
+
"accept": ["image/png", "image/jpeg", "image/webp"],
+
"maxSize": 2000000
+
},
+
"location": {
+
"type": "ref",
+
"ref": "social.coves.actor.profile#geoLocation"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri", "cid"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the updated profile record"
+
},
+
"cid": {
+
"type": "string",
+
"format": "cid",
+
"description": "CID of the updated profile record"
+
}
+
}
+
}
+
}
+
}
+
}
+
}
+106
internal/atproto/lexicon/social/coves/community/create.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.community.create",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Create a new community",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["name", "description"],
+
"properties": {
+
"name": {
+
"type": "string",
+
"maxGraphemes": 64,
+
"maxLength": 640,
+
"description": "Community display name"
+
},
+
"description": {
+
"type": "string",
+
"maxGraphemes": 300,
+
"maxLength": 3000,
+
"description": "Community description"
+
},
+
"avatar": {
+
"type": "blob",
+
"accept": ["image/png", "image/jpeg", "image/webp"],
+
"maxSize": 1000000
+
},
+
"banner": {
+
"type": "blob",
+
"accept": ["image/png", "image/jpeg", "image/webp"],
+
"maxSize": 2000000
+
},
+
"rules": {
+
"type": "array",
+
"maxLength": 10,
+
"items": {
+
"type": "string",
+
"maxGraphemes": 200,
+
"maxLength": 2000
+
},
+
"description": "Community rules"
+
},
+
"categories": {
+
"type": "array",
+
"maxLength": 3,
+
"items": {
+
"type": "string",
+
"maxLength": 50
+
},
+
"description": "Community categories for discovery"
+
},
+
"language": {
+
"type": "string",
+
"format": "language",
+
"description": "Primary language of the community"
+
},
+
"membershipThreshold": {
+
"type": "integer",
+
"minimum": 0,
+
"maximum": 10000,
+
"default": 100,
+
"description": "Reputation threshold required for membership"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri", "cid", "did"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the created community profile"
+
},
+
"cid": {
+
"type": "string",
+
"format": "cid",
+
"description": "CID of the created community profile"
+
},
+
"did": {
+
"type": "string",
+
"format": "did",
+
"description": "DID of the created community"
+
}
+
}
+
}
+
},
+
"errors": [
+
{
+
"name": "NameTaken",
+
"description": "Community name is already taken"
+
},
+
{
+
"name": "TooManyCommunities",
+
"description": "User has reached the maximum number of communities they can create"
+
}
+
]
+
}
+
}
+
}
+114
internal/atproto/lexicon/social/coves/community/get.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.community.get",
+
"defs": {
+
"main": {
+
"type": "query",
+
"description": "Get detailed information about a community",
+
"parameters": {
+
"type": "params",
+
"required": ["community"],
+
"properties": {
+
"community": {
+
"type": "string",
+
"format": "at-identifier",
+
"description": "DID or handle of the community"
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["did", "profile"],
+
"properties": {
+
"did": {
+
"type": "string",
+
"format": "did"
+
},
+
"profile": {
+
"type": "ref",
+
"ref": "social.coves.community.profile"
+
},
+
"stats": {
+
"type": "ref",
+
"ref": "#communityStats"
+
},
+
"viewer": {
+
"type": "ref",
+
"ref": "#viewerState",
+
"description": "Viewer's relationship to this community"
+
}
+
}
+
}
+
}
+
},
+
"communityStats": {
+
"type": "object",
+
"required": ["subscriberCount", "memberCount", "postCount", "activePostersCount"],
+
"properties": {
+
"subscriberCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Number of users subscribed to this community"
+
},
+
"memberCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Number of users with membership status"
+
},
+
"postCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Total number of posts in this community"
+
},
+
"activePostersCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Number of unique posters in the last 30 days"
+
},
+
"moderatorCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Number of active moderators"
+
}
+
}
+
},
+
"viewerState": {
+
"type": "object",
+
"description": "The viewing user's relationship to this community",
+
"properties": {
+
"subscribed": {
+
"type": "boolean",
+
"description": "Whether the viewer is subscribed"
+
},
+
"subscriptionUri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the subscription record if subscribed"
+
},
+
"member": {
+
"type": "boolean",
+
"description": "Whether the viewer has membership status"
+
},
+
"membershipUri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the membership record if member"
+
},
+
"reputation": {
+
"type": "integer",
+
"description": "Viewer's reputation in this community"
+
},
+
"moderator": {
+
"type": "boolean",
+
"description": "Whether the viewer is a moderator"
+
},
+
"banned": {
+
"type": "boolean",
+
"description": "Whether the viewer is banned from this community"
+
}
+
}
+
}
+
}
+
}
+96
internal/atproto/lexicon/social/coves/community/getMembers.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.community.getMembers",
+
"defs": {
+
"main": {
+
"type": "query",
+
"description": "Get list of users with membership status in a community",
+
"parameters": {
+
"type": "params",
+
"required": ["community"],
+
"properties": {
+
"community": {
+
"type": "string",
+
"format": "at-identifier",
+
"description": "DID or handle of the community"
+
},
+
"limit": {
+
"type": "integer",
+
"minimum": 1,
+
"maximum": 100,
+
"default": 50
+
},
+
"cursor": {
+
"type": "string"
+
},
+
"sort": {
+
"type": "string",
+
"enum": ["reputation", "recent", "alphabetical"],
+
"default": "reputation"
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["members"],
+
"properties": {
+
"members": {
+
"type": "array",
+
"items": {
+
"type": "ref",
+
"ref": "#memberView"
+
}
+
},
+
"cursor": {
+
"type": "string"
+
}
+
}
+
}
+
}
+
},
+
"memberView": {
+
"type": "object",
+
"required": ["did", "memberSince", "reputation"],
+
"properties": {
+
"did": {
+
"type": "string",
+
"format": "did"
+
},
+
"handle": {
+
"type": "string",
+
"format": "handle"
+
},
+
"displayName": {
+
"type": "string"
+
},
+
"avatar": {
+
"type": "string",
+
"format": "uri"
+
},
+
"memberSince": {
+
"type": "string",
+
"format": "datetime"
+
},
+
"reputation": {
+
"type": "integer",
+
"minimum": 0
+
},
+
"isModerator": {
+
"type": "boolean"
+
},
+
"postCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Number of posts in this community"
+
},
+
"commentCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Number of comments in this community"
+
}
+
}
+
}
+
}
+
}
+82
internal/atproto/lexicon/social/coves/community/getSubscribers.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.community.getSubscribers",
+
"defs": {
+
"main": {
+
"type": "query",
+
"description": "Get list of users subscribed to a community",
+
"parameters": {
+
"type": "params",
+
"required": ["community"],
+
"properties": {
+
"community": {
+
"type": "string",
+
"format": "at-identifier",
+
"description": "DID or handle of the community"
+
},
+
"limit": {
+
"type": "integer",
+
"minimum": 1,
+
"maximum": 100,
+
"default": 50
+
},
+
"cursor": {
+
"type": "string"
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["subscribers"],
+
"properties": {
+
"subscribers": {
+
"type": "array",
+
"items": {
+
"type": "ref",
+
"ref": "#subscriberView"
+
}
+
},
+
"cursor": {
+
"type": "string"
+
}
+
}
+
}
+
}
+
},
+
"subscriberView": {
+
"type": "object",
+
"required": ["did", "subscribedAt"],
+
"properties": {
+
"did": {
+
"type": "string",
+
"format": "did"
+
},
+
"handle": {
+
"type": "string",
+
"format": "handle"
+
},
+
"displayName": {
+
"type": "string"
+
},
+
"avatar": {
+
"type": "string",
+
"format": "uri"
+
},
+
"subscribedAt": {
+
"type": "string",
+
"format": "datetime"
+
},
+
"isMember": {
+
"type": "boolean",
+
"description": "Whether this subscriber has membership status"
+
},
+
"reputation": {
+
"type": "integer",
+
"description": "User's reputation in this community"
+
}
+
}
+
}
+
}
+
}
+96
internal/atproto/lexicon/social/coves/community/list.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.community.list",
+
"defs": {
+
"main": {
+
"type": "query",
+
"description": "List communities with various sorting options",
+
"parameters": {
+
"type": "params",
+
"properties": {
+
"limit": {
+
"type": "integer",
+
"minimum": 1,
+
"maximum": 100,
+
"default": 50
+
},
+
"cursor": {
+
"type": "string",
+
"description": "Pagination cursor"
+
},
+
"sort": {
+
"type": "string",
+
"enum": ["popular", "active", "new", "alphabetical"],
+
"default": "popular",
+
"description": "Sorting method"
+
},
+
"category": {
+
"type": "string",
+
"description": "Filter by category"
+
},
+
"language": {
+
"type": "string",
+
"format": "language",
+
"description": "Filter by language"
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["communities"],
+
"properties": {
+
"communities": {
+
"type": "array",
+
"items": {
+
"type": "ref",
+
"ref": "#communityView"
+
}
+
},
+
"cursor": {
+
"type": "string"
+
}
+
}
+
}
+
}
+
},
+
"communityView": {
+
"type": "object",
+
"required": ["did", "profile", "subscriberCount", "postCount"],
+
"properties": {
+
"did": {
+
"type": "string",
+
"format": "did"
+
},
+
"profile": {
+
"type": "ref",
+
"ref": "social.coves.community.profile"
+
},
+
"subscriberCount": {
+
"type": "integer",
+
"minimum": 0
+
},
+
"memberCount": {
+
"type": "integer",
+
"minimum": 0
+
},
+
"postCount": {
+
"type": "integer",
+
"minimum": 0
+
},
+
"viewer": {
+
"type": "object",
+
"properties": {
+
"subscribed": {
+
"type": "boolean"
+
},
+
"member": {
+
"type": "boolean"
+
}
+
}
+
}
+
}
+
}
+
}
+
}
+68
internal/atproto/lexicon/social/coves/community/moderator.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.community.moderator",
+
"defs": {
+
"main": {
+
"type": "record",
+
"description": "A moderator assignment for a community",
+
"key": "tid",
+
"record": {
+
"type": "object",
+
"required": ["user", "community", "role", "createdAt", "createdBy"],
+
"properties": {
+
"user": {
+
"type": "string",
+
"format": "did",
+
"description": "DID of the user being assigned as moderator"
+
},
+
"community": {
+
"type": "string",
+
"format": "did",
+
"description": "DID of the community"
+
},
+
"role": {
+
"type": "string",
+
"enum": ["moderator", "admin"],
+
"description": "Level of moderation privileges"
+
},
+
"permissions": {
+
"type": "array",
+
"description": "Specific permissions granted",
+
"items": {
+
"type": "string",
+
"enum": [
+
"remove_posts",
+
"remove_comments",
+
"ban_users",
+
"manage_rules",
+
"manage_wiki",
+
"manage_moderators",
+
"manage_settings"
+
]
+
}
+
},
+
"createdAt": {
+
"type": "string",
+
"format": "datetime",
+
"description": "When the moderator was assigned"
+
},
+
"createdBy": {
+
"type": "string",
+
"format": "did",
+
"description": "DID of the user who assigned this moderator"
+
},
+
"expiresAt": {
+
"type": "string",
+
"format": "datetime",
+
"description": "When the moderator assignment expires (optional)"
+
},
+
"note": {
+
"type": "string",
+
"maxLength": 300,
+
"description": "Note about why this person was made a moderator"
+
}
+
}
+
}
+
}
+
}
+
}
+57
internal/atproto/lexicon/social/coves/community/search.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.community.search",
+
"defs": {
+
"main": {
+
"type": "query",
+
"description": "Search for communities by name or description",
+
"parameters": {
+
"type": "params",
+
"required": ["q"],
+
"properties": {
+
"q": {
+
"type": "string",
+
"description": "Search query"
+
},
+
"limit": {
+
"type": "integer",
+
"minimum": 1,
+
"maximum": 100,
+
"default": 50
+
},
+
"cursor": {
+
"type": "string"
+
},
+
"category": {
+
"type": "string",
+
"description": "Filter by category"
+
},
+
"language": {
+
"type": "string",
+
"format": "language",
+
"description": "Filter by language"
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["communities"],
+
"properties": {
+
"communities": {
+
"type": "array",
+
"items": {
+
"type": "ref",
+
"ref": "social.coves.community.list#communityView"
+
}
+
},
+
"cursor": {
+
"type": "string"
+
}
+
}
+
}
+
}
+
}
+
}
+
}
+57
internal/atproto/lexicon/social/coves/community/subscribe.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.community.subscribe",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Subscribe to a community to see its posts in your feed",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["community"],
+
"properties": {
+
"community": {
+
"type": "string",
+
"format": "at-identifier",
+
"description": "DID or handle of the community to subscribe to"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri", "cid"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the created subscription record"
+
},
+
"cid": {
+
"type": "string",
+
"format": "cid",
+
"description": "CID of the created subscription record"
+
},
+
"existing": {
+
"type": "boolean",
+
"description": "True if item was already subscribed"
+
}
+
}
+
}
+
},
+
"errors": [
+
{
+
"name": "CommunityNotFound",
+
"description": "Community not found"
+
},
+
{
+
"name": "Blocked",
+
"description": "Cannot subscribe - you are blocked from this community"
+
}
+
]
+
}
+
}
+
}
+37
internal/atproto/lexicon/social/coves/community/unsubscribe.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.community.unsubscribe",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Unsubscribe from a community",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["community"],
+
"properties": {
+
"community": {
+
"type": "string",
+
"format": "at-identifier",
+
"description": "DID or handle of the community to unsubscribe from"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"properties": {}
+
}
+
},
+
"errors": [
+
{
+
"name": "NotSubscribed",
+
"description": "Not currently subscribed to this community"
+
}
+
]
+
}
+
}
+
}
+105
internal/atproto/lexicon/social/coves/community/update.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.community.update",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Update community profile",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["community"],
+
"properties": {
+
"community": {
+
"type": "string",
+
"format": "did",
+
"description": "DID of the community to update"
+
},
+
"name": {
+
"type": "string",
+
"maxGraphemes": 64,
+
"maxLength": 640,
+
"description": "Community display name"
+
},
+
"description": {
+
"type": "string",
+
"maxGraphemes": 300,
+
"maxLength": 3000,
+
"description": "Community description"
+
},
+
"avatar": {
+
"type": "blob",
+
"accept": ["image/png", "image/jpeg", "image/webp"],
+
"maxSize": 1000000
+
},
+
"banner": {
+
"type": "blob",
+
"accept": ["image/png", "image/jpeg", "image/webp"],
+
"maxSize": 2000000
+
},
+
"rules": {
+
"type": "array",
+
"maxLength": 10,
+
"items": {
+
"type": "string",
+
"maxGraphemes": 200,
+
"maxLength": 2000
+
},
+
"description": "Community rules"
+
},
+
"categories": {
+
"type": "array",
+
"maxLength": 3,
+
"items": {
+
"type": "string",
+
"maxLength": 50
+
},
+
"description": "Community categories for discovery"
+
},
+
"language": {
+
"type": "string",
+
"format": "language",
+
"description": "Primary language of the community"
+
},
+
"membershipThreshold": {
+
"type": "integer",
+
"minimum": 0,
+
"maximum": 10000,
+
"description": "Reputation threshold required for membership"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri", "cid"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the updated community profile"
+
},
+
"cid": {
+
"type": "string",
+
"format": "cid",
+
"description": "CID of the updated community profile"
+
}
+
}
+
}
+
},
+
"errors": [
+
{
+
"name": "NotFound",
+
"description": "Community not found"
+
},
+
{
+
"name": "NotAuthorized",
+
"description": "User is not authorized to update this community"
+
}
+
]
+
}
+
}
+
}
+79
internal/atproto/lexicon/social/coves/interaction/createComment.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.interaction.createComment",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Create a comment on a post or another comment",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["parent", "text"],
+
"properties": {
+
"parent": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the post or comment being replied to"
+
},
+
"text": {
+
"type": "string",
+
"maxGraphemes": 3000,
+
"maxLength": 30000,
+
"description": "Comment text"
+
},
+
"textMarkup": {
+
"type": "array",
+
"description": "Rich text annotations",
+
"items": {
+
"type": "union",
+
"refs": [
+
"social.coves.richtext.markup",
+
"social.coves.richtext.mention",
+
"social.coves.richtext.link"
+
]
+
}
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri", "cid"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the created comment"
+
},
+
"cid": {
+
"type": "string",
+
"format": "cid",
+
"description": "CID of the created comment"
+
}
+
}
+
}
+
},
+
"errors": [
+
{
+
"name": "ParentNotFound",
+
"description": "Parent post or comment not found"
+
},
+
{
+
"name": "NotAuthorized",
+
"description": "User is not authorized to comment"
+
},
+
{
+
"name": "ThreadLocked",
+
"description": "Comment thread is locked"
+
},
+
{
+
"name": "Banned",
+
"description": "User is banned from this community"
+
}
+
]
+
}
+
}
+
}
+67
internal/atproto/lexicon/social/coves/interaction/createVote.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.interaction.createVote",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Vote on a post or comment",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["subject", "direction"],
+
"properties": {
+
"subject": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the post or comment to vote on"
+
},
+
"direction": {
+
"type": "string",
+
"enum": ["up", "down"],
+
"description": "Vote direction"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri", "cid"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the created vote record"
+
},
+
"cid": {
+
"type": "string",
+
"format": "cid",
+
"description": "CID of the created vote record"
+
},
+
"existing": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of existing vote if updating"
+
}
+
}
+
}
+
},
+
"errors": [
+
{
+
"name": "SubjectNotFound",
+
"description": "Post or comment not found"
+
},
+
{
+
"name": "NotAuthorized",
+
"description": "User is not authorized to vote"
+
},
+
{
+
"name": "Banned",
+
"description": "User is banned from this community"
+
}
+
]
+
}
+
}
+
}
+41
internal/atproto/lexicon/social/coves/interaction/deleteComment.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.interaction.deleteComment",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Delete a comment",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the comment to delete"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"properties": {}
+
}
+
},
+
"errors": [
+
{
+
"name": "CommentNotFound",
+
"description": "Comment not found"
+
},
+
{
+
"name": "NotAuthorized",
+
"description": "User is not authorized to delete this comment"
+
}
+
]
+
}
+
}
+
}
+37
internal/atproto/lexicon/social/coves/interaction/deleteVote.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.interaction.deleteVote",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Remove a vote from a post or comment",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["subject"],
+
"properties": {
+
"subject": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the post or comment to remove vote from"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"properties": {}
+
}
+
},
+
"errors": [
+
{
+
"name": "VoteNotFound",
+
"description": "No vote found on this subject"
+
}
+
]
+
}
+
}
+
}
+2 -2
internal/atproto/lexicon/social/coves/moderation/ban.json
···
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community"
+
"format": "at-identifier",
+
"description": "DID or handle of the community"
},
"subject": {
"type": "string",
+2 -2
internal/atproto/lexicon/social/coves/moderation/banUser.json
···
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community"
+
"format": "at-identifier",
+
"description": "DID or handle of the community"
},
"subject": {
"type": "string",
+2 -2
internal/atproto/lexicon/social/coves/moderation/getBanStatus.json
···
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community"
+
"format": "at-identifier",
+
"description": "DID or handle of the community"
},
"subject": {
"type": "string",
+2 -2
internal/atproto/lexicon/social/coves/moderation/listBans.json
···
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community"
+
"format": "at-identifier",
+
"description": "DID or handle of the community"
},
"status": {
"type": "string",
+2 -2
internal/atproto/lexicon/social/coves/moderation/ruleProposal.json
···
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community"
+
"format": "at-identifier",
+
"description": "DID or handle of the community"
},
"proposalType": {
"type": "string",
+2 -2
internal/atproto/lexicon/social/coves/moderation/unbanUser.json
···
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community"
+
"format": "at-identifier",
+
"description": "DID or handle of the community"
},
"subject": {
"type": "string",
+2 -2
internal/atproto/lexicon/social/coves/post/article.json
···
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community this was posted to"
+
"format": "at-identifier",
+
"description": "DID or handle of the community this was posted to"
},
"title": {
"type": "string",
+175
internal/atproto/lexicon/social/coves/post/create.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.post.create",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Create a new post in a community",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["community", "type", "title"],
+
"properties": {
+
"community": {
+
"type": "string",
+
"format": "at-identifier",
+
"description": "DID or handle of the community to post in"
+
},
+
"type": {
+
"type": "string",
+
"enum": ["text", "image", "video", "article", "microblog"],
+
"description": "Type of post to create"
+
},
+
"title": {
+
"type": "string",
+
"maxGraphemes": 300,
+
"maxLength": 3000,
+
"description": "Post title (required for text, article, image, video posts)"
+
},
+
"text": {
+
"type": "string",
+
"maxGraphemes": 10000,
+
"maxLength": 40000,
+
"description": "Post body text"
+
},
+
"textMarkup": {
+
"type": "array",
+
"description": "Rich text annotations for body",
+
"items": {
+
"type": "union",
+
"refs": [
+
"social.coves.richtext.markup",
+
"social.coves.richtext.mention",
+
"social.coves.richtext.link"
+
]
+
}
+
},
+
"images": {
+
"type": "array",
+
"maxLength": 10,
+
"description": "Images for image posts",
+
"items": {
+
"type": "object",
+
"required": ["image"],
+
"properties": {
+
"image": {
+
"type": "blob",
+
"accept": ["image/png", "image/jpeg", "image/webp"],
+
"maxSize": 5000000
+
},
+
"alt": {
+
"type": "string",
+
"maxLength": 1000,
+
"description": "Alt text for accessibility"
+
}
+
}
+
}
+
},
+
"video": {
+
"type": "object",
+
"description": "Video for video posts",
+
"required": ["video"],
+
"properties": {
+
"video": {
+
"type": "blob",
+
"accept": ["video/mp4", "video/webm"],
+
"maxSize": 100000000
+
},
+
"thumbnail": {
+
"type": "blob",
+
"accept": ["image/png", "image/jpeg", "image/webp"],
+
"maxSize": 1000000
+
},
+
"alt": {
+
"type": "string",
+
"maxLength": 1000
+
}
+
}
+
},
+
"external": {
+
"type": "object",
+
"description": "External link embed",
+
"required": ["uri"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "uri"
+
},
+
"title": {
+
"type": "string",
+
"maxLength": 300
+
},
+
"description": {
+
"type": "string",
+
"maxLength": 1000
+
},
+
"thumb": {
+
"type": "blob",
+
"accept": ["image/png", "image/jpeg", "image/webp"],
+
"maxSize": 1000000
+
}
+
}
+
},
+
"tags": {
+
"type": "array",
+
"maxLength": 10,
+
"items": {
+
"type": "string",
+
"maxLength": 50
+
},
+
"description": "Tags for categorization"
+
},
+
"nsfw": {
+
"type": "boolean",
+
"default": false,
+
"description": "Whether the post contains NSFW content"
+
},
+
"language": {
+
"type": "string",
+
"format": "language",
+
"description": "Language of the post"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri", "cid"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the created post"
+
},
+
"cid": {
+
"type": "string",
+
"format": "cid",
+
"description": "CID of the created post"
+
}
+
}
+
}
+
},
+
"errors": [
+
{
+
"name": "CommunityNotFound",
+
"description": "Community not found"
+
},
+
{
+
"name": "NotAuthorized",
+
"description": "User is not authorized to post in this community"
+
},
+
{
+
"name": "Banned",
+
"description": "User is banned from this community"
+
},
+
{
+
"name": "InvalidContent",
+
"description": "Post content violates community rules"
+
}
+
]
+
}
+
}
+
}
+41
internal/atproto/lexicon/social/coves/post/delete.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.post.delete",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Delete a post",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the post to delete"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"properties": {}
+
}
+
},
+
"errors": [
+
{
+
"name": "PostNotFound",
+
"description": "Post not found"
+
},
+
{
+
"name": "NotAuthorized",
+
"description": "User is not authorized to delete this post"
+
}
+
]
+
}
+
}
+
}
+268
internal/atproto/lexicon/social/coves/post/get.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.post.get",
+
"defs": {
+
"main": {
+
"type": "query",
+
"description": "Get a single post with all its details",
+
"parameters": {
+
"type": "params",
+
"required": ["uri"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the post"
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["post"],
+
"properties": {
+
"post": {
+
"type": "ref",
+
"ref": "#postView"
+
}
+
}
+
}
+
}
+
},
+
"postView": {
+
"type": "object",
+
"required": ["uri", "cid", "author", "record", "community", "type", "createdAt"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri"
+
},
+
"cid": {
+
"type": "string",
+
"format": "cid"
+
},
+
"author": {
+
"type": "ref",
+
"ref": "#authorView"
+
},
+
"record": {
+
"type": "unknown",
+
"description": "The actual post record (text, image, video, etc.)"
+
},
+
"community": {
+
"type": "ref",
+
"ref": "#communityRef"
+
},
+
"type": {
+
"type": "string",
+
"enum": ["text", "image", "video", "article", "microblog"]
+
},
+
"title": {
+
"type": "string"
+
},
+
"text": {
+
"type": "string"
+
},
+
"textMarkup": {
+
"type": "array",
+
"items": {
+
"type": "union",
+
"refs": [
+
"social.coves.richtext.markup",
+
"social.coves.richtext.mention",
+
"social.coves.richtext.link"
+
]
+
}
+
},
+
"images": {
+
"type": "array",
+
"items": {
+
"type": "ref",
+
"ref": "#imageView"
+
}
+
},
+
"video": {
+
"type": "ref",
+
"ref": "#videoView"
+
},
+
"external": {
+
"type": "ref",
+
"ref": "#externalView"
+
},
+
"tags": {
+
"type": "array",
+
"items": {
+
"type": "string"
+
}
+
},
+
"nsfw": {
+
"type": "boolean"
+
},
+
"language": {
+
"type": "string",
+
"format": "language"
+
},
+
"createdAt": {
+
"type": "string",
+
"format": "datetime"
+
},
+
"editedAt": {
+
"type": "string",
+
"format": "datetime"
+
},
+
"stats": {
+
"type": "ref",
+
"ref": "#postStats"
+
},
+
"viewer": {
+
"type": "ref",
+
"ref": "#viewerState"
+
}
+
}
+
},
+
"authorView": {
+
"type": "object",
+
"required": ["did", "handle"],
+
"properties": {
+
"did": {
+
"type": "string",
+
"format": "did"
+
},
+
"handle": {
+
"type": "string",
+
"format": "handle"
+
},
+
"displayName": {
+
"type": "string"
+
},
+
"avatar": {
+
"type": "string",
+
"format": "uri"
+
},
+
"reputation": {
+
"type": "integer",
+
"description": "Author's reputation in the community"
+
}
+
}
+
},
+
"communityRef": {
+
"type": "object",
+
"required": ["did", "name"],
+
"properties": {
+
"did": {
+
"type": "string",
+
"format": "did"
+
},
+
"name": {
+
"type": "string"
+
},
+
"avatar": {
+
"type": "string",
+
"format": "uri"
+
}
+
}
+
},
+
"imageView": {
+
"type": "object",
+
"required": ["fullsize"],
+
"properties": {
+
"fullsize": {
+
"type": "string",
+
"format": "uri"
+
},
+
"thumb": {
+
"type": "string",
+
"format": "uri"
+
},
+
"alt": {
+
"type": "string"
+
}
+
}
+
},
+
"videoView": {
+
"type": "object",
+
"required": ["url"],
+
"properties": {
+
"url": {
+
"type": "string",
+
"format": "uri"
+
},
+
"thumbnail": {
+
"type": "string",
+
"format": "uri"
+
},
+
"alt": {
+
"type": "string"
+
}
+
}
+
},
+
"externalView": {
+
"type": "object",
+
"required": ["uri"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "uri"
+
},
+
"title": {
+
"type": "string"
+
},
+
"description": {
+
"type": "string"
+
},
+
"thumb": {
+
"type": "string",
+
"format": "uri"
+
}
+
}
+
},
+
"postStats": {
+
"type": "object",
+
"required": ["upvotes", "downvotes", "score", "commentCount"],
+
"properties": {
+
"upvotes": {
+
"type": "integer",
+
"minimum": 0
+
},
+
"downvotes": {
+
"type": "integer",
+
"minimum": 0
+
},
+
"score": {
+
"type": "integer",
+
"description": "Calculated score (upvotes - downvotes)"
+
},
+
"commentCount": {
+
"type": "integer",
+
"minimum": 0
+
},
+
"shareCount": {
+
"type": "integer",
+
"minimum": 0
+
}
+
}
+
},
+
"viewerState": {
+
"type": "object",
+
"properties": {
+
"vote": {
+
"type": "string",
+
"enum": ["up", "down"],
+
"description": "Viewer's vote on this post"
+
},
+
"voteUri": {
+
"type": "string",
+
"format": "at-uri"
+
},
+
"saved": {
+
"type": "boolean"
+
},
+
"savedUri": {
+
"type": "string",
+
"format": "at-uri"
+
}
+
}
+
}
+
}
+
}
+128
internal/atproto/lexicon/social/coves/post/getFeed.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.post.getFeed",
+
"defs": {
+
"main": {
+
"type": "query",
+
"description": "Get a feed of posts",
+
"parameters": {
+
"type": "params",
+
"properties": {
+
"feed": {
+
"type": "string",
+
"enum": ["home", "popular", "new", "controversial"],
+
"default": "home",
+
"description": "Type of feed to retrieve"
+
},
+
"community": {
+
"type": "string",
+
"format": "at-identifier",
+
"description": "Filter by specific community (DID or handle)"
+
},
+
"timeframe": {
+
"type": "string",
+
"enum": ["hour", "day", "week", "month", "year", "all"],
+
"default": "day",
+
"description": "Timeframe for popular/controversial feeds"
+
},
+
"limit": {
+
"type": "integer",
+
"minimum": 1,
+
"maximum": 100,
+
"default": 15
+
},
+
"cursor": {
+
"type": "string"
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["posts"],
+
"properties": {
+
"posts": {
+
"type": "array",
+
"items": {
+
"type": "ref",
+
"ref": "#feedPost"
+
}
+
},
+
"cursor": {
+
"type": "string"
+
}
+
}
+
}
+
}
+
},
+
"feedPost": {
+
"type": "object",
+
"required": ["uri", "author", "community", "type", "createdAt"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri"
+
},
+
"author": {
+
"type": "ref",
+
"ref": "social.coves.post.get#authorView"
+
},
+
"community": {
+
"type": "ref",
+
"ref": "social.coves.post.get#communityRef"
+
},
+
"type": {
+
"type": "string",
+
"enum": ["text", "image", "video", "article", "microblog"]
+
},
+
"title": {
+
"type": "string"
+
},
+
"text": {
+
"type": "string",
+
"maxLength": 500,
+
"description": "Truncated preview of the post text"
+
},
+
"images": {
+
"type": "array",
+
"maxLength": 4,
+
"description": "Preview of images (max 4)",
+
"items": {
+
"type": "ref",
+
"ref": "social.coves.post.get#imageView"
+
}
+
},
+
"video": {
+
"type": "ref",
+
"ref": "social.coves.post.get#videoView"
+
},
+
"external": {
+
"type": "ref",
+
"ref": "social.coves.post.get#externalView"
+
},
+
"tags": {
+
"type": "array",
+
"items": {
+
"type": "string"
+
}
+
},
+
"nsfw": {
+
"type": "boolean"
+
},
+
"createdAt": {
+
"type": "string",
+
"format": "datetime"
+
},
+
"stats": {
+
"type": "ref",
+
"ref": "social.coves.post.get#postStats"
+
},
+
"viewer": {
+
"type": "ref",
+
"ref": "social.coves.post.get#viewerState"
+
}
+
}
+
}
+
}
+
}
+2 -2
internal/atproto/lexicon/social/coves/post/image.json
···
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community this was posted to"
+
"format": "at-identifier",
+
"description": "DID or handle of the community this was posted to"
},
"title": {
"type": "string",
+2 -2
internal/atproto/lexicon/social/coves/post/microblog.json
···
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community this was posted to"
+
"format": "at-identifier",
+
"description": "DID or handle of the community this was posted to"
},
"content": {
"type": "string",
+80
internal/atproto/lexicon/social/coves/post/search.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.post.search",
+
"defs": {
+
"main": {
+
"type": "query",
+
"description": "Search for posts",
+
"parameters": {
+
"type": "params",
+
"required": ["q"],
+
"properties": {
+
"q": {
+
"type": "string",
+
"description": "Search query"
+
},
+
"community": {
+
"type": "string",
+
"format": "at-identifier",
+
"description": "Filter by specific community"
+
},
+
"author": {
+
"type": "string",
+
"format": "at-identifier",
+
"description": "Filter by author"
+
},
+
"type": {
+
"type": "string",
+
"enum": ["text", "image", "video", "article", "microblog"],
+
"description": "Filter by post type"
+
},
+
"tags": {
+
"type": "array",
+
"items": {
+
"type": "string"
+
},
+
"description": "Filter by tags"
+
},
+
"sort": {
+
"type": "string",
+
"enum": ["relevance", "new", "top"],
+
"default": "relevance"
+
},
+
"timeframe": {
+
"type": "string",
+
"enum": ["hour", "day", "week", "month", "year", "all"],
+
"default": "all"
+
},
+
"limit": {
+
"type": "integer",
+
"minimum": 1,
+
"maximum": 100,
+
"default": 50
+
},
+
"cursor": {
+
"type": "string"
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["posts"],
+
"properties": {
+
"posts": {
+
"type": "array",
+
"items": {
+
"type": "ref",
+
"ref": "social.coves.post.getFeed#feedPost"
+
}
+
},
+
"cursor": {
+
"type": "string"
+
}
+
}
+
}
+
}
+
}
+
}
+
}
+2 -2
internal/atproto/lexicon/social/coves/post/text.json
···
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community this was posted to"
+
"format": "at-identifier",
+
"description": "DID or handle of the community this was posted to"
},
"title": {
"type": "string",
+99
internal/atproto/lexicon/social/coves/post/update.json
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.post.update",
+
"defs": {
+
"main": {
+
"type": "procedure",
+
"description": "Update an existing post",
+
"input": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the post to update"
+
},
+
"title": {
+
"type": "string",
+
"maxGraphemes": 300,
+
"maxLength": 3000,
+
"description": "Updated title"
+
},
+
"text": {
+
"type": "string",
+
"maxGraphemes": 10000,
+
"maxLength": 100000,
+
"description": "Updated body text"
+
},
+
"textMarkup": {
+
"type": "array",
+
"description": "Updated rich text annotations",
+
"items": {
+
"type": "union",
+
"refs": [
+
"social.coves.richtext.markup",
+
"social.coves.richtext.mention",
+
"social.coves.richtext.link"
+
]
+
}
+
},
+
"tags": {
+
"type": "array",
+
"maxLength": 10,
+
"items": {
+
"type": "string",
+
"maxLength": 50
+
},
+
"description": "Updated tags"
+
},
+
"nsfw": {
+
"type": "boolean",
+
"description": "Updated NSFW status"
+
},
+
"editNote": {
+
"type": "string",
+
"maxLength": 300,
+
"description": "Optional note explaining the edit"
+
}
+
}
+
}
+
},
+
"output": {
+
"encoding": "application/json",
+
"schema": {
+
"type": "object",
+
"required": ["uri", "cid"],
+
"properties": {
+
"uri": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "AT-URI of the updated post"
+
},
+
"cid": {
+
"type": "string",
+
"format": "cid",
+
"description": "New CID of the updated post"
+
}
+
}
+
}
+
},
+
"errors": [
+
{
+
"name": "PostNotFound",
+
"description": "Post not found"
+
},
+
{
+
"name": "NotAuthorized",
+
"description": "User is not authorized to edit this post"
+
},
+
{
+
"name": "EditWindowExpired",
+
"description": "Edit window has expired (posts can only be edited within 24 hours)"
+
}
+
]
+
}
+
}
+
}
+2 -2
internal/atproto/lexicon/social/coves/post/video.json
···
"properties": {
"community": {
"type": "string",
-
"format": "at-uri",
-
"description": "AT-URI of the community this was posted to"
+
"format": "at-identifier",
+
"description": "DID or handle of the community this was posted to"
},
"title": {
"type": "string",