A community based topic aggregation platform built on atproto

Merge pull request #7 from BrettM86/feature/lexicon-post-reorg

feat: Unify post lexicon architecture and improve tag handling

+24 -1
internal/atproto/lexicon/social/coves/embed/external.json
···
"defs": {
"main": {
"type": "object",
-
"description": "External link embed with preview metadata",
"required": ["uri"],
"properties": {
"uri": {
···
"domain": {
"type": "string",
"description": "Domain of the linked content"
}
}
}
···
"defs": {
"main": {
"type": "object",
+
"description": "External link embed with preview metadata and provider support",
"required": ["uri"],
"properties": {
"uri": {
···
"domain": {
"type": "string",
"description": "Domain of the linked content"
+
},
+
"embedType": {
+
"type": "string",
+
"enum": ["article", "image", "video-stream"],
+
"description": "Type hint for special handling of known providers"
+
},
+
"provider": {
+
"type": "string",
+
"description": "Service provider name (e.g., imgur, streamable)"
+
},
+
"images": {
+
"type": "array",
+
"maxLength": 8,
+
"description": "Preview images for image gallery providers",
+
"items": {
+
"type": "ref",
+
"ref": "social.coves.embed.images#image"
+
}
+
},
+
"totalCount": {
+
"type": "integer",
+
"minimum": 0,
+
"description": "Total number of items if more than displayed (for galleries)"
}
}
}
-43
internal/atproto/lexicon/social/coves/embed/image.json
···
-
{
-
"lexicon": 1,
-
"id": "social.coves.embed.image",
-
"defs": {
-
"main": {
-
"type": "object",
-
"description": "Image embed with metadata",
-
"required": ["image"],
-
"properties": {
-
"image": {
-
"type": "blob",
-
"accept": ["image/png", "image/jpeg", "image/webp", "image/gif"],
-
"maxSize": 10000000,
-
"description": "Image blob reference"
-
},
-
"alt": {
-
"type": "string",
-
"maxLength": 1000,
-
"description": "Alt text for accessibility"
-
},
-
"aspectRatio": {
-
"type": "ref",
-
"ref": "#aspectRatio"
-
}
-
}
-
},
-
"aspectRatio": {
-
"type": "object",
-
"description": "Image aspect ratio for client display",
-
"required": ["width", "height"],
-
"properties": {
-
"width": {
-
"type": "integer",
-
"minimum": 1
-
},
-
"height": {
-
"type": "integer",
-
"minimum": 1
-
}
-
}
-
}
-
}
-
}
···
+63
internal/atproto/lexicon/social/coves/embed/images.json
···
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.embed.images",
+
"defs": {
+
"main": {
+
"type": "object",
+
"description": "Image set embed supporting multiple images (max 8)",
+
"required": ["images"],
+
"properties": {
+
"images": {
+
"type": "array",
+
"minLength": 1,
+
"maxLength": 8,
+
"description": "Set of images in the post",
+
"items": {
+
"type": "ref",
+
"ref": "#image"
+
}
+
}
+
}
+
},
+
"image": {
+
"type": "object",
+
"description": "Individual image with metadata",
+
"required": ["image"],
+
"properties": {
+
"image": {
+
"type": "blob",
+
"accept": ["image/png", "image/jpeg", "image/webp", "image/gif"],
+
"maxSize": 10000000,
+
"description": "Image blob reference"
+
},
+
"alt": {
+
"type": "string",
+
"maxLength": 1000,
+
"description": "Alt text for accessibility"
+
},
+
"aspectRatio": {
+
"type": "ref",
+
"ref": "#aspectRatio",
+
"description": "Aspect ratio for client-side rendering optimization"
+
}
+
}
+
},
+
"aspectRatio": {
+
"type": "object",
+
"description": "Image aspect ratio for client display",
+
"required": ["width", "height"],
+
"properties": {
+
"width": {
+
"type": "integer",
+
"minimum": 1,
+
"description": "Width component of aspect ratio"
+
},
+
"height": {
+
"type": "integer",
+
"minimum": 1,
+
"description": "Height component of aspect ratio"
+
}
+
}
+
}
+
}
+
}
+8 -3
internal/atproto/lexicon/social/coves/federation/post.json
···
"main": {
"type": "object",
"description": "Reference to original federated post",
-
"required": ["platform"],
"properties": {
"platform": {
"type": "string",
-
"knownValues": ["bluesky", "lemmy", "mastodon"],
"description": "Platform the post originated from"
},
"uri": {
"type": "string",
"format": "uri",
-
"description": "Original URI of the post"
},
"id": {
"type": "string",
"description": "Platform-specific post ID"
}
}
}
···
"main": {
"type": "object",
"description": "Reference to original federated post",
+
"required": ["platform", "uri"],
"properties": {
"platform": {
"type": "string",
+
"knownValues": ["bluesky", "lemmy", "atproto"],
"description": "Platform the post originated from"
},
"uri": {
"type": "string",
"format": "uri",
+
"description": "Original URI of the post (at:// URI for atproto platforms)"
},
"id": {
"type": "string",
"description": "Platform-specific post ID"
+
},
+
"originalCreatedAt": {
+
"type": "string",
+
"format": "datetime",
+
"description": "Timestamp when originally posted on source platform"
}
}
}
-106
internal/atproto/lexicon/social/coves/post/article.json
···
-
{
-
"lexicon": 1,
-
"id": "social.coves.post.article",
-
"defs": {
-
"main": {
-
"type": "record",
-
"description": "An article/link post",
-
"key": "tid",
-
"record": {
-
"type": "object",
-
"required": ["community", "title", "url", "createdAt"],
-
"properties": {
-
"community": {
-
"type": "string",
-
"format": "at-identifier",
-
"description": "DID or handle of the community this was posted to"
-
},
-
"title": {
-
"type": "string",
-
"maxGraphemes": 300,
-
"maxLength": 3000,
-
"description": "Post title"
-
},
-
"url": {
-
"type": "string",
-
"format": "uri",
-
"description": "URL of the linked article"
-
},
-
"domain": {
-
"type": "string",
-
"description": "Domain of the linked article (cached)"
-
},
-
"embed": {
-
"type": "ref",
-
"ref": "social.coves.embed.external",
-
"description": "Preview metadata for the link"
-
},
-
"autoGeneratedDescription": {
-
"type": "string",
-
"maxLength": 50000,
-
"description": "Optional Auto-generated text breakdown of article"
-
},
-
"content": {
-
"type": "string",
-
"maxLength": 50000,
-
"description": "Optional text content to accompany link"
-
},
-
"facets": {
-
"type": "array",
-
"description": "Rich text annotations",
-
"items": {
-
"type": "ref",
-
"ref": "social.coves.richtext.facet"
-
}
-
},
-
"tags": {
-
"type": "array",
-
"maxLength": 10,
-
"items": {
-
"type": "string",
-
"maxLength": 32
-
}
-
},
-
"nsfw": {
-
"type": "boolean",
-
"default": false
-
},
-
"contentLabels": {
-
"type": "array",
-
"description": "Self-applied content labels",
-
"items": {
-
"type": "string",
-
"knownValues": ["nsfw", "spoiler", "violence"],
-
"maxLength": 32
-
}
-
},
-
"federatedFrom": {
-
"type": "ref",
-
"ref": "social.coves.federation.post"
-
},
-
"location": {
-
"type": "ref",
-
"ref": "social.coves.actor.profile#geoLocation"
-
},
-
"crosspostOf": {
-
"type": "string",
-
"format": "at-uri",
-
"description": "If this is a crosspost, AT-URI of the post this is a crosspost of"
-
},
-
"crosspostChain": {
-
"type": "array",
-
"description": "Array of AT-URIs of all posts in the crosspost chain (including this one)",
-
"items": {
-
"type": "string",
-
"format": "at-uri"
-
}
-
},
-
"createdAt": {
-
"type": "string",
-
"format": "datetime"
-
}
-
}
-
}
-
}
-
}
-
}
···
+39 -87
internal/atproto/lexicon/social/coves/post/create.json
···
"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"
},
-
"textFacets": {
"type": "array",
-
"description": "Rich text annotations for body",
"items": {
"type": "ref",
"ref": "social.coves.richtext.facet"
}
},
-
"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"
}
}
}
···
{
"name": "InvalidContent",
"description": "Post content violates community rules"
}
]
}
···
"encoding": "application/json",
"schema": {
"type": "object",
+
"required": ["community", "postType"],
"properties": {
"community": {
"type": "string",
"format": "at-identifier",
"description": "DID or handle of the community to post in"
},
+
"postType": {
"type": "string",
+
"enum": ["text", "article", "image", "video", "microblog"],
"description": "Type of post to create"
},
"title": {
"type": "string",
"maxGraphemes": 300,
"maxLength": 3000,
+
"description": "Post title (optional for microblog, image, and video posts)"
},
+
"content": {
"type": "string",
+
"maxLength": 50000,
+
"description": "Post content - main text for text posts, description for media, etc."
},
+
"facets": {
"type": "array",
+
"description": "Rich text annotations for content",
"items": {
"type": "ref",
"ref": "social.coves.richtext.facet"
}
},
+
"embed": {
+
"type": "union",
+
"description": "Embedded content - images, videos, external links, or quoted posts",
+
"refs": [
+
"social.coves.embed.images",
+
"social.coves.embed.video",
+
"social.coves.embed.external",
+
"social.coves.embed.post"
+
]
},
+
"originalAuthor": {
+
"type": "ref",
+
"ref": "social.coves.post.record#originalAuthor",
+
"description": "For microblog posts - information about the original author"
},
+
"federatedFrom": {
+
"type": "ref",
+
"ref": "social.coves.federation.post",
+
"description": "Reference to original federated post (for microblog posts)"
},
+
"contentLabels": {
"type": "array",
+
"description": "Self-applied content labels",
"items": {
"type": "string",
+
"knownValues": ["nsfw", "spoiler", "violence"],
+
"maxLength": 32
+
}
},
+
"location": {
+
"type": "ref",
+
"ref": "social.coves.actor.profile#geoLocation",
+
"description": "Geographic location where post was created"
}
}
}
···
{
"name": "InvalidContent",
"description": "Post content violates community rules"
+
},
+
{
+
"name": "InvalidPostType",
+
"description": "Community does not allow this post type"
}
]
}
+18 -11
internal/atproto/lexicon/social/coves/post/get.json
···
},
"postView": {
"type": "object",
-
"required": ["uri", "cid", "author", "record", "community", "type", "createdAt"],
"properties": {
"uri": {
"type": "string",
···
"type": "ref",
"ref": "#communityRef"
},
-
"type": {
"type": "string",
"enum": ["text", "image", "video", "article", "microblog"]
},
···
"external": {
"type": "ref",
"ref": "#externalView"
-
},
-
"tags": {
-
"type": "array",
-
"items": {
-
"type": "string"
-
}
-
},
-
"nsfw": {
-
"type": "boolean"
},
"language": {
"type": "string",
···
"shareCount": {
"type": "integer",
"minimum": 0
}
}
},
···
"savedUri": {
"type": "string",
"format": "at-uri"
}
}
}
···
},
"postView": {
"type": "object",
+
"required": ["uri", "cid", "author", "record", "community", "postType", "createdAt"],
"properties": {
"uri": {
"type": "string",
···
"type": "ref",
"ref": "#communityRef"
},
+
"postType": {
"type": "string",
"enum": ["text", "image", "video", "article", "microblog"]
},
···
"external": {
"type": "ref",
"ref": "#externalView"
},
"language": {
"type": "string",
···
"shareCount": {
"type": "integer",
"minimum": 0
+
},
+
"tagCounts": {
+
"type": "object",
+
"description": "Aggregate counts of tags applied by community members",
+
"additionalProperties": {
+
"type": "integer",
+
"minimum": 0
+
}
}
}
},
···
"savedUri": {
"type": "string",
"format": "at-uri"
+
},
+
"tags": {
+
"type": "array",
+
"description": "Tags applied by the viewer to this post",
+
"items": {
+
"type": "string",
+
"maxLength": 32
+
}
}
}
}
+33 -24
internal/atproto/lexicon/social/coves/post/getFeed.json
···
"defs": {
"main": {
"type": "query",
-
"description": "Get a feed of posts",
"parameters": {
"type": "params",
"properties": {
···
"type": "string",
"format": "at-identifier",
"description": "Filter by specific community (DID or handle)"
},
"timeframe": {
"type": "string",
···
},
"feedPost": {
"type": "object",
-
"required": ["uri", "author", "community", "type", "createdAt"],
"properties": {
"uri": {
"type": "string",
···
"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",
···
"defs": {
"main": {
"type": "query",
+
"description": "Get a feed of posts with optional filtering by post type",
"parameters": {
"type": "params",
"properties": {
···
"type": "string",
"format": "at-identifier",
"description": "Filter by specific community (DID or handle)"
+
},
+
"postType": {
+
"type": "string",
+
"enum": ["text", "article", "image", "video", "microblog"],
+
"description": "Filter by a single post type"
+
},
+
"postTypes": {
+
"type": "array",
+
"items": {
+
"type": "string",
+
"enum": ["text", "article", "image", "video", "microblog"]
+
},
+
"description": "Filter by multiple post types"
},
"timeframe": {
"type": "string",
···
},
"feedPost": {
"type": "object",
+
"required": ["uri", "author", "community", "postType", "createdAt"],
"properties": {
"uri": {
"type": "string",
···
"type": "ref",
"ref": "social.coves.post.get#communityRef"
},
+
"postType": {
"type": "string",
+
"enum": ["text", "article", "image", "video", "microblog"],
+
"description": "Type of the post for UI rendering"
},
"title": {
"type": "string"
},
+
"content": {
"type": "string",
"maxLength": 500,
+
"description": "Truncated preview of the post content"
},
+
"embed": {
+
"type": "union",
+
"description": "Embedded content preview",
+
"refs": [
+
"social.coves.post.get#imagesView",
+
"social.coves.post.get#videoView",
+
"social.coves.post.get#externalView",
+
"social.coves.post.get#postView"
+
]
},
+
"originalAuthor": {
"type": "ref",
+
"ref": "social.coves.post.record#originalAuthor",
+
"description": "For microblog posts - original author info"
},
+
"contentLabels": {
"type": "array",
"items": {
"type": "string"
}
},
"createdAt": {
"type": "string",
-93
internal/atproto/lexicon/social/coves/post/image.json
···
-
{
-
"lexicon": 1,
-
"id": "social.coves.post.image",
-
"defs": {
-
"main": {
-
"type": "record",
-
"description": "An image post",
-
"key": "tid",
-
"record": {
-
"type": "object",
-
"required": ["community", "title", "images", "createdAt"],
-
"properties": {
-
"community": {
-
"type": "string",
-
"format": "at-identifier",
-
"description": "DID or handle of the community this was posted to"
-
},
-
"title": {
-
"type": "string",
-
"maxGraphemes": 300,
-
"maxLength": 3000,
-
"description": "Post title"
-
},
-
"images": {
-
"type": "array",
-
"minLength": 1,
-
"maxLength": 10,
-
"description": "Images in the post",
-
"items": {
-
"type": "ref",
-
"ref": "social.coves.embed.image"
-
}
-
},
-
"caption": {
-
"type": "string",
-
"maxLength": 10000,
-
"description": "Optional caption or description"
-
},
-
"captionFacets": {
-
"type": "array",
-
"description": "Rich text annotations for caption",
-
"items": {
-
"type": "ref",
-
"ref": "social.coves.richtext.facet"
-
}
-
},
-
"tags": {
-
"type": "array",
-
"maxLength": 10,
-
"items": {
-
"type": "string",
-
"maxLength": 32
-
}
-
},
-
"contentLabels": {
-
"type": "array",
-
"description": "Self-applied content labels",
-
"items": {
-
"type": "string",
-
"knownValues": ["nsfw", "spoiler", "violence"],
-
"maxLength": 32
-
}
-
},
-
"federatedFrom": {
-
"type": "ref",
-
"ref": "social.coves.federation.post"
-
},
-
"location": {
-
"type": "ref",
-
"ref": "social.coves.actor.profile#geoLocation"
-
},
-
"crosspostOf": {
-
"type": "string",
-
"format": "at-uri",
-
"description": "If this is a crosspost, AT-URI of the post this is a crosspost of"
-
},
-
"crosspostChain": {
-
"type": "array",
-
"description": "Array of AT-URIs of all posts in the crosspost chain (including this one)",
-
"items": {
-
"type": "string",
-
"format": "at-uri"
-
}
-
},
-
"createdAt": {
-
"type": "string",
-
"format": "datetime"
-
}
-
}
-
}
-
}
-
}
-
}
···
-136
internal/atproto/lexicon/social/coves/post/microblog.json
···
-
{
-
"lexicon": 1,
-
"id": "social.coves.post.microblog",
-
"defs": {
-
"main": {
-
"type": "record",
-
"description": "A microblog post (typically from federated platforms like Bluesky/Mastodon)",
-
"key": "tid",
-
"record": {
-
"type": "object",
-
"required": ["community", "content", "createdAt"],
-
"properties": {
-
"community": {
-
"type": "string",
-
"format": "at-identifier",
-
"description": "DID or handle of the community this was posted to"
-
},
-
"content": {
-
"type": "string",
-
"maxLength": 5000,
-
"description": "Microblog post content (plain text or markdown)"
-
},
-
"facets": {
-
"type": "array",
-
"description": "Rich text annotations",
-
"items": {
-
"type": "ref",
-
"ref": "social.coves.richtext.facet"
-
}
-
},
-
"title": {
-
"type": "string",
-
"maxLength": 300,
-
"description": "Optional title"
-
},
-
"hashtags": {
-
"type": "array",
-
"maxLength": 20,
-
"description": "Hashtags from the original post",
-
"items": {
-
"type": "string",
-
"maxLength": 100
-
}
-
},
-
"embed": {
-
"type": "union",
-
"description": "Embedded content (images, videos, links, quoted posts)",
-
"refs": [
-
"social.coves.embed.image",
-
"social.coves.embed.video",
-
"social.coves.embed.external",
-
"social.coves.embed.post"
-
]
-
},
-
"contentLabels": {
-
"type": "array",
-
"description": "Content warnings and labels",
-
"items": {
-
"type": "string",
-
"knownValues": ["nsfw", "spoiler", "violence"],
-
"maxLength": 32
-
}
-
},
-
"federatedFrom": {
-
"type": "ref",
-
"ref": "social.coves.federation.post",
-
"description": "Required - reference to original federated post"
-
},
-
"originalAuthor": {
-
"type": "object",
-
"description": "Information about the original author from federated platform",
-
"required": ["handle"],
-
"properties": {
-
"handle": {
-
"type": "string",
-
"maxLength": 253,
-
"description": "Original author's handle"
-
},
-
"displayName": {
-
"type": "string",
-
"maxLength": 640,
-
"description": "Original author's display name"
-
},
-
"did": {
-
"type": "string",
-
"format": "did",
-
"description": "Original author's DID (if available)"
-
},
-
"avatar": {
-
"type": "string",
-
"format": "uri",
-
"description": "URL to original author's avatar"
-
}
-
}
-
},
-
"replyTo": {
-
"type": "string",
-
"format": "at-uri",
-
"description": "If this is a reply, reference to the parent post"
-
},
-
"location": {
-
"type": "ref",
-
"ref": "social.coves.actor.profile#geoLocation"
-
},
-
"language": {
-
"type": "string",
-
"maxLength": 10,
-
"description": "Language code (e.g., 'en', 'es', 'fr')"
-
},
-
"crosspostOf": {
-
"type": "string",
-
"format": "at-uri",
-
"description": "If this is a crosspost, AT-URI of the post this is a crosspost of"
-
},
-
"crosspostChain": {
-
"type": "array",
-
"description": "Array of AT-URIs of all posts in the crosspost chain (including this one)",
-
"items": {
-
"type": "string",
-
"format": "at-uri"
-
}
-
},
-
"createdAt": {
-
"type": "string",
-
"format": "datetime"
-
},
-
"originalCreatedAt": {
-
"type": "string",
-
"format": "datetime",
-
"description": "Original creation time on the federated platform"
-
}
-
}
-
}
-
}
-
}
-
}
···
+124
internal/atproto/lexicon/social/coves/post/record.json
···
···
+
{
+
"lexicon": 1,
+
"id": "social.coves.post.record",
+
"defs": {
+
"main": {
+
"type": "record",
+
"description": "A unified post record supporting multiple content types",
+
"key": "tid",
+
"record": {
+
"type": "object",
+
"required": ["community", "postType", "createdAt"],
+
"properties": {
+
"community": {
+
"type": "string",
+
"format": "at-identifier",
+
"description": "DID or handle of the community this was posted to"
+
},
+
"postType": {
+
"type": "string",
+
"enum": ["text", "article", "image", "video", "microblog"],
+
"description": "Discriminator for post type to enable filtering and specialized rendering"
+
},
+
"title": {
+
"type": "string",
+
"maxGraphemes": 300,
+
"maxLength": 3000,
+
"description": "Post title (optional for microblog, image, and video posts)"
+
},
+
"content": {
+
"type": "string",
+
"maxLength": 50000,
+
"description": "Post content - main text for text posts, description for media, etc."
+
},
+
"facets": {
+
"type": "array",
+
"description": "Rich text annotations for content",
+
"items": {
+
"type": "ref",
+
"ref": "social.coves.richtext.facet"
+
}
+
},
+
"embed": {
+
"type": "union",
+
"description": "Embedded content - images, videos, external links, or quoted posts",
+
"refs": [
+
"social.coves.embed.images",
+
"social.coves.embed.video",
+
"social.coves.embed.external",
+
"social.coves.embed.post"
+
]
+
},
+
"originalAuthor": {
+
"type": "ref",
+
"ref": "#originalAuthor",
+
"description": "For microblog posts - information about the original author from federated platform"
+
},
+
"contentLabels": {
+
"type": "array",
+
"description": "Self-applied content labels",
+
"items": {
+
"type": "string",
+
"knownValues": ["nsfw", "spoiler", "violence"],
+
"maxLength": 32
+
}
+
},
+
"federatedFrom": {
+
"type": "ref",
+
"ref": "social.coves.federation.post",
+
"description": "Reference to original federated post (if applicable)"
+
},
+
"location": {
+
"type": "ref",
+
"ref": "social.coves.actor.profile#geoLocation",
+
"description": "Geographic location where post was created"
+
},
+
"crosspostOf": {
+
"type": "string",
+
"format": "at-uri",
+
"description": "If this is a crosspost, AT-URI of the post this is a crosspost of"
+
},
+
"crosspostChain": {
+
"type": "array",
+
"description": "Array of AT-URIs of all posts in the crosspost chain (including this one)",
+
"items": {
+
"type": "string",
+
"format": "at-uri"
+
}
+
},
+
"createdAt": {
+
"type": "string",
+
"format": "datetime"
+
}
+
}
+
}
+
},
+
"originalAuthor": {
+
"type": "object",
+
"description": "Information about the original author from a federated platform",
+
"required": ["handle"],
+
"properties": {
+
"did": {
+
"type": "string",
+
"format": "did",
+
"description": "Original author's DID (if available)"
+
},
+
"handle": {
+
"type": "string",
+
"maxLength": 253,
+
"description": "Original author's handle"
+
},
+
"displayName": {
+
"type": "string",
+
"maxLength": 640,
+
"description": "Original author's display name"
+
},
+
"avatar": {
+
"type": "string",
+
"format": "uri",
+
"description": "URL to original author's avatar"
+
}
+
}
+
}
+
}
+
}
-94
internal/atproto/lexicon/social/coves/post/text.json
···
-
{
-
"lexicon": 1,
-
"id": "social.coves.post.text",
-
"defs": {
-
"main": {
-
"type": "record",
-
"description": "A text post",
-
"key": "tid",
-
"record": {
-
"type": "object",
-
"required": ["community", "title", "createdAt"],
-
"properties": {
-
"community": {
-
"type": "string",
-
"format": "at-identifier",
-
"description": "DID or handle of the community this was posted to"
-
},
-
"title": {
-
"type": "string",
-
"maxGraphemes": 300,
-
"maxLength": 3000,
-
"description": "Post title"
-
},
-
"content": {
-
"type": "string",
-
"maxLength": 50000,
-
"description": "Markdown-formatted post content"
-
},
-
"facets": {
-
"type": "array",
-
"description": "Rich text annotations",
-
"items": {
-
"type": "ref",
-
"ref": "social.coves.richtext.facet"
-
}
-
},
-
"tags": {
-
"type": "array",
-
"maxLength": 10,
-
"description": "Post tags/categories",
-
"items": {
-
"type": "string",
-
"maxLength": 32
-
}
-
},
-
"contentLabels": {
-
"type": "array",
-
"description": "Self-applied content labels",
-
"items": {
-
"type": "string",
-
"knownValues": ["nsfw", "spoiler", "violence"],
-
"maxLength": 32
-
}
-
},
-
"federatedFrom": {
-
"type": "ref",
-
"ref": "social.coves.federation.post"
-
},
-
"location": {
-
"type": "ref",
-
"ref": "social.coves.actor.profile#geoLocation"
-
},
-
"embed": {
-
"type": "union",
-
"description": "Optional embedded content",
-
"refs": [
-
"social.coves.embed.image",
-
"social.coves.embed.video",
-
"social.coves.embed.external",
-
"social.coves.embed.post"
-
]
-
},
-
"crosspostOf": {
-
"type": "string",
-
"format": "at-uri",
-
"description": "If this is a crosspost, AT-URI of the post this is a crosspost of"
-
},
-
"crosspostChain": {
-
"type": "array",
-
"description": "Array of AT-URIs of all posts in the crosspost chain (including this one)",
-
"items": {
-
"type": "string",
-
"format": "at-uri"
-
}
-
},
-
"createdAt": {
-
"type": "string",
-
"format": "datetime"
-
}
-
}
-
}
-
}
-
}
-
}
···
+24 -15
internal/atproto/lexicon/social/coves/post/update.json
···
"maxLength": 3000,
"description": "Updated title"
},
-
"text": {
"type": "string",
-
"maxGraphemes": 10000,
-
"maxLength": 100000,
-
"description": "Updated body text"
},
-
"textFacets": {
"type": "array",
-
"description": "Updated rich text annotations",
"items": {
"type": "ref",
"ref": "social.coves.richtext.facet"
}
},
-
"tags": {
"type": "array",
-
"maxLength": 10,
"items": {
"type": "string",
-
"maxLength": 50
-
},
-
"description": "Updated tags"
-
},
-
"nsfw": {
-
"type": "boolean",
-
"description": "Updated NSFW status"
},
"editNote": {
"type": "string",
···
{
"name": "EditWindowExpired",
"description": "Edit window has expired (posts can only be edited within 24 hours)"
}
]
}
···
"maxLength": 3000,
"description": "Updated title"
},
+
"content": {
"type": "string",
+
"maxLength": 50000,
+
"description": "Updated content - main text for text posts, description for media, etc."
},
+
"facets": {
"type": "array",
+
"description": "Updated rich text annotations for content",
"items": {
"type": "ref",
"ref": "social.coves.richtext.facet"
}
},
+
"embed": {
+
"type": "union",
+
"description": "Updated embedded content (note: changing embed type may be restricted)",
+
"refs": [
+
"social.coves.embed.images",
+
"social.coves.embed.video",
+
"social.coves.embed.external",
+
"social.coves.embed.post"
+
]
+
},
+
"contentLabels": {
"type": "array",
+
"description": "Updated content labels",
"items": {
"type": "string",
+
"knownValues": ["nsfw", "spoiler", "violence"],
+
"maxLength": 32
+
}
},
"editNote": {
"type": "string",
···
{
"name": "EditWindowExpired",
"description": "Edit window has expired (posts can only be edited within 24 hours)"
+
},
+
{
+
"name": "InvalidUpdate",
+
"description": "Invalid update operation (e.g., changing post type)"
}
]
}
-92
internal/atproto/lexicon/social/coves/post/video.json
···
-
{
-
"lexicon": 1,
-
"id": "social.coves.post.video",
-
"defs": {
-
"main": {
-
"type": "record",
-
"description": "A video post",
-
"key": "tid",
-
"record": {
-
"type": "object",
-
"required": ["community", "title", "video", "createdAt"],
-
"properties": {
-
"community": {
-
"type": "string",
-
"format": "at-identifier",
-
"description": "DID or handle of the community this was posted to"
-
},
-
"title": {
-
"type": "string",
-
"maxGraphemes": 300,
-
"maxLength": 3000,
-
"description": "Post title"
-
},
-
"video": {
-
"type": "ref",
-
"ref": "social.coves.embed.video",
-
"description": "Video content"
-
},
-
"caption": {
-
"type": "string",
-
"maxLength": 10000,
-
"description": "Optional caption or description"
-
},
-
"captionFacets": {
-
"type": "array",
-
"description": "Rich text annotations for caption",
-
"items": {
-
"type": "ref",
-
"ref": "social.coves.richtext.facet"
-
}
-
},
-
"tags": {
-
"type": "array",
-
"maxLength": 10,
-
"items": {
-
"type": "string",
-
"maxLength": 32
-
}
-
},
-
"nsfw": {
-
"type": "boolean",
-
"default": false
-
},
-
"contentLabels": {
-
"type": "array",
-
"description": "Self-applied content labels",
-
"items": {
-
"type": "string",
-
"knownValues": ["nsfw", "spoiler", "violence"],
-
"maxLength": 32
-
}
-
},
-
"federatedFrom": {
-
"type": "ref",
-
"ref": "social.coves.federation.post"
-
},
-
"location": {
-
"type": "ref",
-
"ref": "social.coves.actor.profile#geoLocation"
-
},
-
"crosspostOf": {
-
"type": "string",
-
"format": "at-uri",
-
"description": "If this is a crosspost, AT-URI of the post this is a crosspost of"
-
},
-
"crosspostChain": {
-
"type": "array",
-
"description": "Array of AT-URIs of all posts in the crosspost chain (including this one)",
-
"items": {
-
"type": "string",
-
"format": "at-uri"
-
}
-
},
-
"createdAt": {
-
"type": "string",
-
"format": "datetime"
-
}
-
}
-
}
-
}
-
}
-
}
···