diff --git a/cmd/server/main.go b/cmd/server/main.go index e590943..b7ddac6 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -7,12 +7,14 @@ import ( "Coves/internal/atproto/identity" "Coves/internal/atproto/jetstream" "Coves/internal/core/aggregators" + "Coves/internal/core/blobs" "Coves/internal/core/comments" "Coves/internal/core/communities" "Coves/internal/core/communityFeeds" "Coves/internal/core/discover" "Coves/internal/core/posts" "Coves/internal/core/timeline" + "Coves/internal/core/unfurl" "Coves/internal/core/users" "bytes" "context" @@ -281,9 +283,24 @@ func main() { aggregatorService := aggregators.NewAggregatorService(aggregatorRepo, communityService) log.Println("✅ Aggregator service initialized") + // Initialize unfurl cache repository + unfurlRepo := unfurl.NewRepository(db) + + // Initialize blob upload service + blobService := blobs.NewBlobService(defaultPDS) + + // Initialize unfurl service with configuration + unfurlService := unfurl.NewService( + unfurlRepo, + unfurl.WithTimeout(10*time.Second), + unfurl.WithUserAgent("CovesBot/1.0 (+https://coves.social)"), + unfurl.WithCacheTTL(24*time.Hour), + ) + log.Println("✅ Unfurl and blob services initialized") + // Initialize post service (with aggregator support) postRepo := postgresRepo.NewPostRepository(db) - postService := posts.NewPostService(postRepo, communityService, aggregatorService, defaultPDS) + postService := posts.NewPostService(postRepo, communityService, aggregatorService, blobService, unfurlService, defaultPDS) // Initialize vote repository (used by Jetstream consumer for indexing) voteRepo := postgresRepo.NewVoteRepository(db) diff --git a/internal/core/posts/interfaces.go b/internal/core/posts/interfaces.go index df9091a..2a07ca5 100644 --- a/internal/core/posts/interfaces.go +++ b/internal/core/posts/interfaces.go @@ -1,6 +1,12 @@ package posts -import "context" +import ( + "context" +) + +// Service constructor accepts optional blobs.Service and unfurl.Service for embed enhancement. +// When unfurlService is provided, external embeds will be automatically enriched with metadata. +// When blobService is provided, thumbnails from unfurled URLs will be uploaded as blobs. // Service defines the business logic interface for posts // Coordinates between Repository, community service, and PDS diff --git a/internal/core/posts/post.go b/internal/core/posts/post.go index 10f8ec8..51fa4d9 100644 --- a/internal/core/posts/post.go +++ b/internal/core/posts/post.go @@ -50,6 +50,7 @@ type CreatePostRequest struct { Title *string `json:"title,omitempty"` Content *string `json:"content,omitempty"` Embed map[string]interface{} `json:"embed,omitempty"` + ThumbnailURL *string `json:"thumbnailUrl,omitempty"` Labels *SelfLabels `json:"labels,omitempty"` Community string `json:"community"` AuthorDID string `json:"authorDid"` @@ -121,6 +122,7 @@ type CommunityRef struct { DID string `json:"did"` Handle string `json:"handle"` Name string `json:"name"` + PDSURL string `json:"-"` // Not exposed to API, used for blob URL transformation } // PostStats represents aggregated statistics