diff --git a/internal/atproto/lexicon/social/coves/actor/blockUser.json b/internal/atproto/lexicon/social/coves/actor/blockUser.json new file mode 100644 index 0000000..653d0a7 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/actor/blockUser.json @@ -0,0 +1,59 @@ +{ + "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" + } + } + } + }, + "errors": [ + { + "name": "SubjectNotFound", + "description": "Subject user not found" + }, + { + "name": "AlreadyBlocked", + "description": "User is already blocked" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/actor/getProfile.json b/internal/atproto/lexicon/social/coves/actor/getProfile.json new file mode 100644 index 0000000..16465e6 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/actor/getProfile.json @@ -0,0 +1,102 @@ +{ + "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" + } + } + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/actor/getSaved.json b/internal/atproto/lexicon/social/coves/actor/getSaved.json index a8be76b..3217a7a 100644 --- a/internal/atproto/lexicon/social/coves/actor/getSaved.json +++ b/internal/atproto/lexicon/social/coves/actor/getSaved.json @@ -3,7 +3,7 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/actor/membership.json b/internal/atproto/lexicon/social/coves/actor/membership.json index d9bbbdd..2ec5497 100644 --- a/internal/atproto/lexicon/social/coves/actor/membership.json +++ b/internal/atproto/lexicon/social/coves/actor/membership.json @@ -8,7 +8,7 @@ "key": "tid", "record": { "type": "object", - "required": ["community", "reputation", "createdAt", "createdAt"], + "required": ["community", "reputation", "createdAt"], "properties": { "community": { "type": "string", diff --git a/internal/atproto/lexicon/social/coves/actor/preferences.json b/internal/atproto/lexicon/social/coves/actor/preferences.json new file mode 100644 index 0000000..72305c4 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/actor/preferences.json @@ -0,0 +1,197 @@ +{ + "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 + } + } + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/actor/saveItem.json b/internal/atproto/lexicon/social/coves/actor/saveItem.json new file mode 100644 index 0000000..90dcab1 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/actor/saveItem.json @@ -0,0 +1,63 @@ +{ + "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" + } + } + } + }, + "errors": [ + { + "name": "SubjectNotFound", + "description": "The post or comment to save was not found" + }, + { + "name": "AlreadySaved", + "description": "Item is already saved" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/actor/unblockUser.json b/internal/atproto/lexicon/social/coves/actor/unblockUser.json new file mode 100644 index 0000000..6abbc33 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/actor/unblockUser.json @@ -0,0 +1,37 @@ +{ + "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" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/actor/unsaveItem.json b/internal/atproto/lexicon/social/coves/actor/unsaveItem.json new file mode 100644 index 0000000..42bc86d --- /dev/null +++ b/internal/atproto/lexicon/social/coves/actor/unsaveItem.json @@ -0,0 +1,37 @@ +{ + "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" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/actor/updateProfile.json b/internal/atproto/lexicon/social/coves/actor/updateProfile.json new file mode 100644 index 0000000..ecf2629 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/actor/updateProfile.json @@ -0,0 +1,75 @@ +{ + "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" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/community/create.json b/internal/atproto/lexicon/social/coves/community/create.json new file mode 100644 index 0000000..b6c0cc9 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/community/create.json @@ -0,0 +1,106 @@ +{ + "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" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/community/get.json b/internal/atproto/lexicon/social/coves/community/get.json new file mode 100644 index 0000000..ca79606 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/community/get.json @@ -0,0 +1,114 @@ +{ + "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" + } + } + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/community/getMembers.json b/internal/atproto/lexicon/social/coves/community/getMembers.json new file mode 100644 index 0000000..cfffa0c --- /dev/null +++ b/internal/atproto/lexicon/social/coves/community/getMembers.json @@ -0,0 +1,96 @@ +{ + "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" + } + } + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/community/getSubscribers.json b/internal/atproto/lexicon/social/coves/community/getSubscribers.json new file mode 100644 index 0000000..62b7fd8 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/community/getSubscribers.json @@ -0,0 +1,82 @@ +{ + "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" + } + } + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/community/list.json b/internal/atproto/lexicon/social/coves/community/list.json new file mode 100644 index 0000000..c05c0c0 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/community/list.json @@ -0,0 +1,96 @@ +{ + "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" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/community/moderator.json b/internal/atproto/lexicon/social/coves/community/moderator.json new file mode 100644 index 0000000..263e024 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/community/moderator.json @@ -0,0 +1,68 @@ +{ + "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" + } + } + } + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/community/search.json b/internal/atproto/lexicon/social/coves/community/search.json new file mode 100644 index 0000000..0e4d64c --- /dev/null +++ b/internal/atproto/lexicon/social/coves/community/search.json @@ -0,0 +1,57 @@ +{ + "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": 25 + }, + "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" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/community/subscribe.json b/internal/atproto/lexicon/social/coves/community/subscribe.json new file mode 100644 index 0000000..d0c5adb --- /dev/null +++ b/internal/atproto/lexicon/social/coves/community/subscribe.json @@ -0,0 +1,57 @@ +{ + "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" + } + } + } + }, + "errors": [ + { + "name": "CommunityNotFound", + "description": "Community not found" + }, + { + "name": "AlreadySubscribed", + "description": "Already subscribed to this community" + }, + { + "name": "Blocked", + "description": "Cannot subscribe - you are blocked from this community" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/community/unsubscribe.json b/internal/atproto/lexicon/social/coves/community/unsubscribe.json new file mode 100644 index 0000000..e829b13 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/community/unsubscribe.json @@ -0,0 +1,37 @@ +{ + "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" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/community/update.json b/internal/atproto/lexicon/social/coves/community/update.json new file mode 100644 index 0000000..ef9d0f6 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/community/update.json @@ -0,0 +1,105 @@ +{ + "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" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/interaction/createComment.json b/internal/atproto/lexicon/social/coves/interaction/createComment.json new file mode 100644 index 0000000..032c45a --- /dev/null +++ b/internal/atproto/lexicon/social/coves/interaction/createComment.json @@ -0,0 +1,79 @@ +{ + "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" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/interaction/createVote.json b/internal/atproto/lexicon/social/coves/interaction/createVote.json new file mode 100644 index 0000000..883e8ae --- /dev/null +++ b/internal/atproto/lexicon/social/coves/interaction/createVote.json @@ -0,0 +1,67 @@ +{ + "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" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/interaction/deleteComment.json b/internal/atproto/lexicon/social/coves/interaction/deleteComment.json new file mode 100644 index 0000000..34fefd7 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/interaction/deleteComment.json @@ -0,0 +1,41 @@ +{ + "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" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/interaction/deleteVote.json b/internal/atproto/lexicon/social/coves/interaction/deleteVote.json new file mode 100644 index 0000000..1d34220 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/interaction/deleteVote.json @@ -0,0 +1,37 @@ +{ + "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" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/post/create.json b/internal/atproto/lexicon/social/coves/post/create.json new file mode 100644 index 0000000..c0bbe1f --- /dev/null +++ b/internal/atproto/lexicon/social/coves/post/create.json @@ -0,0 +1,175 @@ +{ + "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"], + "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": 100000, + "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" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/post/delete.json b/internal/atproto/lexicon/social/coves/post/delete.json new file mode 100644 index 0000000..8afd6db --- /dev/null +++ b/internal/atproto/lexicon/social/coves/post/delete.json @@ -0,0 +1,41 @@ +{ + "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" + } + ] + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/post/get.json b/internal/atproto/lexicon/social/coves/post/get.json new file mode 100644 index 0000000..8b8bf1c --- /dev/null +++ b/internal/atproto/lexicon/social/coves/post/get.json @@ -0,0 +1,268 @@ +{ + "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" + } + } + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/post/getFeed.json b/internal/atproto/lexicon/social/coves/post/getFeed.json new file mode 100644 index 0000000..58b6333 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/post/getFeed.json @@ -0,0 +1,128 @@ +{ + "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": 25 + }, + "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" + } + } + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/post/search.json b/internal/atproto/lexicon/social/coves/post/search.json new file mode 100644 index 0000000..6d8e683 --- /dev/null +++ b/internal/atproto/lexicon/social/coves/post/search.json @@ -0,0 +1,80 @@ +{ + "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": 25 + }, + "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" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/internal/atproto/lexicon/social/coves/post/update.json b/internal/atproto/lexicon/social/coves/post/update.json new file mode 100644 index 0000000..245db8e --- /dev/null +++ b/internal/atproto/lexicon/social/coves/post/update.json @@ -0,0 +1,99 @@ +{ + "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)" + } + ] + } + } +} \ No newline at end of file -- 2.51.2 From b1b5e6444cbc74fd10361166e5c2a310a24aa379 Mon Sep 17 00:00:00 2001 From: Bretton Date: Thu, 3 Jul 2025 17:10:02 -0700 Subject: [PATCH 2/2] Ensuring DID community references, simplifying error handling --- .../atproto/lexicon/social/coves/actor/blockUser.json | 8 ++++---- .../atproto/lexicon/social/coves/actor/membership.json | 4 ++-- internal/atproto/lexicon/social/coves/actor/saveItem.json | 8 ++++---- .../atproto/lexicon/social/coves/actor/subscription.json | 4 ++-- .../atproto/lexicon/social/coves/community/search.json | 2 +- .../atproto/lexicon/social/coves/community/subscribe.json | 8 ++++---- internal/atproto/lexicon/social/coves/moderation/ban.json | 4 ++-- .../atproto/lexicon/social/coves/moderation/banUser.json | 4 ++-- .../lexicon/social/coves/moderation/getBanStatus.json | 4 ++-- .../atproto/lexicon/social/coves/moderation/listBans.json | 4 ++-- .../lexicon/social/coves/moderation/ruleProposal.json | 4 ++-- .../lexicon/social/coves/moderation/unbanUser.json | 4 ++-- internal/atproto/lexicon/social/coves/post/article.json | 4 ++-- internal/atproto/lexicon/social/coves/post/create.json | 4 ++-- internal/atproto/lexicon/social/coves/post/getFeed.json | 2 +- internal/atproto/lexicon/social/coves/post/image.json | 4 ++-- internal/atproto/lexicon/social/coves/post/microblog.json | 4 ++-- internal/atproto/lexicon/social/coves/post/search.json | 2 +- internal/atproto/lexicon/social/coves/post/text.json | 4 ++-- internal/atproto/lexicon/social/coves/post/video.json | 4 ++-- 20 files changed, 43 insertions(+), 43 deletions(-) diff --git a/internal/atproto/lexicon/social/coves/actor/blockUser.json b/internal/atproto/lexicon/social/coves/actor/blockUser.json index 653d0a7..1a58bc7 100644 --- a/internal/atproto/lexicon/social/coves/actor/blockUser.json +++ b/internal/atproto/lexicon/social/coves/actor/blockUser.json @@ -40,6 +40,10 @@ "type": "string", "format": "cid", "description": "CID of the created block record" + }, + "existing": { + "type": "boolean", + "description": "True if user was already blocked" } } } @@ -48,10 +52,6 @@ { "name": "SubjectNotFound", "description": "Subject user not found" - }, - { - "name": "AlreadyBlocked", - "description": "User is already blocked" } ] } diff --git a/internal/atproto/lexicon/social/coves/actor/membership.json b/internal/atproto/lexicon/social/coves/actor/membership.json index 2ec5497..f3d33b7 100644 --- a/internal/atproto/lexicon/social/coves/actor/membership.json +++ b/internal/atproto/lexicon/social/coves/actor/membership.json @@ -12,8 +12,8 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/actor/saveItem.json b/internal/atproto/lexicon/social/coves/actor/saveItem.json index 90dcab1..6d1f629 100644 --- a/internal/atproto/lexicon/social/coves/actor/saveItem.json +++ b/internal/atproto/lexicon/social/coves/actor/saveItem.json @@ -44,6 +44,10 @@ "type": "string", "format": "cid", "description": "CID of the created saved record" + }, + "existing": { + "type": "boolean", + "description": "True if item was already saved" } } } @@ -52,10 +56,6 @@ { "name": "SubjectNotFound", "description": "The post or comment to save was not found" - }, - { - "name": "AlreadySaved", - "description": "Item is already saved" } ] } diff --git a/internal/atproto/lexicon/social/coves/actor/subscription.json b/internal/atproto/lexicon/social/coves/actor/subscription.json index 81b4537..37419b9 100644 --- a/internal/atproto/lexicon/social/coves/actor/subscription.json +++ b/internal/atproto/lexicon/social/coves/actor/subscription.json @@ -12,8 +12,8 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/community/search.json b/internal/atproto/lexicon/social/coves/community/search.json index 0e4d64c..98b203a 100644 --- a/internal/atproto/lexicon/social/coves/community/search.json +++ b/internal/atproto/lexicon/social/coves/community/search.json @@ -17,7 +17,7 @@ "type": "integer", "minimum": 1, "maximum": 100, - "default": 25 + "default": 50 }, "cursor": { "type": "string" diff --git a/internal/atproto/lexicon/social/coves/community/subscribe.json b/internal/atproto/lexicon/social/coves/community/subscribe.json index d0c5adb..4f56246 100644 --- a/internal/atproto/lexicon/social/coves/community/subscribe.json +++ b/internal/atproto/lexicon/social/coves/community/subscribe.json @@ -34,6 +34,10 @@ "type": "string", "format": "cid", "description": "CID of the created subscription record" + }, + "existing": { + "type": "boolean", + "description": "True if item was already subscribed" } } } @@ -43,10 +47,6 @@ "name": "CommunityNotFound", "description": "Community not found" }, - { - "name": "AlreadySubscribed", - "description": "Already subscribed to this community" - }, { "name": "Blocked", "description": "Cannot subscribe - you are blocked from this community" diff --git a/internal/atproto/lexicon/social/coves/moderation/ban.json b/internal/atproto/lexicon/social/coves/moderation/ban.json index 0515889..2a893d8 100644 --- a/internal/atproto/lexicon/social/coves/moderation/ban.json +++ b/internal/atproto/lexicon/social/coves/moderation/ban.json @@ -12,8 +12,8 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/moderation/banUser.json b/internal/atproto/lexicon/social/coves/moderation/banUser.json index cd35b46..4d307bb 100644 --- a/internal/atproto/lexicon/social/coves/moderation/banUser.json +++ b/internal/atproto/lexicon/social/coves/moderation/banUser.json @@ -13,8 +13,8 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/moderation/getBanStatus.json b/internal/atproto/lexicon/social/coves/moderation/getBanStatus.json index a01cd3e..7818cff 100644 --- a/internal/atproto/lexicon/social/coves/moderation/getBanStatus.json +++ b/internal/atproto/lexicon/social/coves/moderation/getBanStatus.json @@ -11,8 +11,8 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/moderation/listBans.json b/internal/atproto/lexicon/social/coves/moderation/listBans.json index 14510bc..0c2aeb9 100644 --- a/internal/atproto/lexicon/social/coves/moderation/listBans.json +++ b/internal/atproto/lexicon/social/coves/moderation/listBans.json @@ -11,8 +11,8 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/moderation/ruleProposal.json b/internal/atproto/lexicon/social/coves/moderation/ruleProposal.json index 3448e14..768a989 100644 --- a/internal/atproto/lexicon/social/coves/moderation/ruleProposal.json +++ b/internal/atproto/lexicon/social/coves/moderation/ruleProposal.json @@ -12,8 +12,8 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/moderation/unbanUser.json b/internal/atproto/lexicon/social/coves/moderation/unbanUser.json index 724e3d7..bf63d21 100644 --- a/internal/atproto/lexicon/social/coves/moderation/unbanUser.json +++ b/internal/atproto/lexicon/social/coves/moderation/unbanUser.json @@ -13,8 +13,8 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/post/article.json b/internal/atproto/lexicon/social/coves/post/article.json index 7c7b63c..1e2a494 100644 --- a/internal/atproto/lexicon/social/coves/post/article.json +++ b/internal/atproto/lexicon/social/coves/post/article.json @@ -12,8 +12,8 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/post/create.json b/internal/atproto/lexicon/social/coves/post/create.json index c0bbe1f..743aa2e 100644 --- a/internal/atproto/lexicon/social/coves/post/create.json +++ b/internal/atproto/lexicon/social/coves/post/create.json @@ -9,7 +9,7 @@ "encoding": "application/json", "schema": { "type": "object", - "required": ["community", "type"], + "required": ["community", "type", "title"], "properties": { "community": { "type": "string", @@ -30,7 +30,7 @@ "text": { "type": "string", "maxGraphemes": 10000, - "maxLength": 100000, + "maxLength": 40000, "description": "Post body text" }, "textMarkup": { diff --git a/internal/atproto/lexicon/social/coves/post/getFeed.json b/internal/atproto/lexicon/social/coves/post/getFeed.json index 58b6333..c63a4fe 100644 --- a/internal/atproto/lexicon/social/coves/post/getFeed.json +++ b/internal/atproto/lexicon/social/coves/post/getFeed.json @@ -29,7 +29,7 @@ "type": "integer", "minimum": 1, "maximum": 100, - "default": 25 + "default": 15 }, "cursor": { "type": "string" diff --git a/internal/atproto/lexicon/social/coves/post/image.json b/internal/atproto/lexicon/social/coves/post/image.json index c1339d5..f1a5f2f 100644 --- a/internal/atproto/lexicon/social/coves/post/image.json +++ b/internal/atproto/lexicon/social/coves/post/image.json @@ -12,8 +12,8 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/post/microblog.json b/internal/atproto/lexicon/social/coves/post/microblog.json index 2b908a5..2704049 100644 --- a/internal/atproto/lexicon/social/coves/post/microblog.json +++ b/internal/atproto/lexicon/social/coves/post/microblog.json @@ -12,8 +12,8 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/post/search.json b/internal/atproto/lexicon/social/coves/post/search.json index 6d8e683..1a83b75 100644 --- a/internal/atproto/lexicon/social/coves/post/search.json +++ b/internal/atproto/lexicon/social/coves/post/search.json @@ -49,7 +49,7 @@ "type": "integer", "minimum": 1, "maximum": 100, - "default": 25 + "default": 50 }, "cursor": { "type": "string" diff --git a/internal/atproto/lexicon/social/coves/post/text.json b/internal/atproto/lexicon/social/coves/post/text.json index 3a98bf8..0928f51 100644 --- a/internal/atproto/lexicon/social/coves/post/text.json +++ b/internal/atproto/lexicon/social/coves/post/text.json @@ -12,8 +12,8 @@ "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", diff --git a/internal/atproto/lexicon/social/coves/post/video.json b/internal/atproto/lexicon/social/coves/post/video.json index 331e793..c9aa247 100644 --- a/internal/atproto/lexicon/social/coves/post/video.json +++ b/internal/atproto/lexicon/social/coves/post/video.json @@ -12,8 +12,8 @@ "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",