lists

package
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 10, 2026 License: AGPL-3.0 Imports: 11 Imported by: 0

README

Lists Service

The Lists Service provides comprehensive list management functionality for the Lesser ActivityPub implementation. This service handles Mastodon-style user-created lists for organizing followed accounts and generating custom timelines.

Overview

Lists in Lesser allow users to:

  • Create custom lists with titles and replies policies
  • Add and remove accounts from their lists
  • View timelines containing only posts from list members
  • Manage list privacy (lists are private to their owners)

Core Operations

List Management
  • CreateList: Create a new list with title and replies policy
  • UpdateList: Modify list title and/or replies policy
  • DeleteList: Remove a list and all its memberships
  • GetList: Retrieve a specific list (owner only)
  • ListUserLists: Get all lists for a user with pagination
Membership Management
  • AddToList: Add an account to a list (owner only)
  • RemoveFromList: Remove an account from a list (owner only)
Timeline Generation
  • GetListTimeline: Retrieve posts from list members with pagination

Key Features

Privacy and Security
  • Owner-only Access: Only list owners can view, modify, or delete their lists
  • Private Lists: Lists are not discoverable by other users
  • Authorization Checks: All operations verify user permissions
Event Streaming

All list operations emit real-time events for streaming:

  • list.created - When a new list is created
  • list.updated - When list metadata is modified
  • list.deleted - When a list is deleted
  • list.member_added - When an account is added to a list
  • list.member_removed - When an account is removed from a list
Replies Policies

Lists support three replies policies:

  • followed - Show replies only from followed accounts
  • list - Show replies only from accounts in the list
  • none - Don't show any replies in the timeline

Command Patterns

CreateListCommand
type CreateListCommand struct {
    Username      string `json:"username" validate:"required"`
    Title         string `json:"title" validate:"required,min=1,max=100"`
    RepliesPolicy string `json:"replies_policy" validate:"oneof=followed list none"`
    CreatorID     string `json:"creator_id" validate:"required"`
}
UpdateListCommand
type UpdateListCommand struct {
    ListID        string `json:"list_id" validate:"required"`
    Title         string `json:"title,omitempty" validate:"omitempty,min=1,max=100"`
    RepliesPolicy string `json:"replies_policy,omitempty" validate:"omitempty,oneof=followed list none"`
    UpdaterID     string `json:"updater_id" validate:"required"`
}
AddToListCommand
type AddToListCommand struct {
    ListID        string `json:"list_id" validate:"required"`
    MemberUsername string `json:"member_username" validate:"required"`
    AdderID       string `json:"adder_id" validate:"required"`
}

Result Patterns

ListResult
type ListResult struct {
    List   *models.List        `json:"list"`
    Events []*streaming.Event `json:"events"`
}
TimelineResult
type TimelineResult struct {
    Statuses   []*models.Status                                 `json:"statuses"`
    Pagination *interfaces.PaginatedResult[*models.Status] `json:"pagination"`
    Events     []*streaming.Event                              `json:"events"`
}

Dependencies

  • ListRepository: Database operations for list storage and queries
  • NoteRepository: Status/note operations for timeline generation
  • Publisher: Event streaming for real-time updates
  • Logger: Structured logging for operations and errors

Error Handling

The service provides comprehensive error handling:

  • Validation Errors: Invalid input parameters
  • Authorization Errors: Unauthorized access attempts
  • Repository Errors: Database operation failures
  • Business Logic Errors: Constraint violations

Usage Example

// Create service
listService := NewService(listRepo, noteRepo, publisher, logger)

// Create a list
cmd := &CreateListCommand{
    Username:      "alice",
    Title:         "Close Friends",
    RepliesPolicy: "list",
    CreatorID:     "alice",
}

result, err := listService.CreateList(ctx, cmd)
if err != nil {
    log.Fatal(err)
}

// Add member to list
addCmd := &AddToListCommand{
    ListID:        result.List.ID,
    MemberUsername: "bob",
    AdderID:       "alice",
}

memberResult, err := listService.AddToList(ctx, addCmd)
if err != nil {
    log.Fatal(err)
}

// Get list timeline
timelineQuery := &GetListTimelineQuery{
    ListID:   result.List.ID,
    ViewerID: "alice",
    Pagination: interfaces.PaginationOptions{
        Limit: 20,
    },
}

timeline, err := listService.GetListTimeline(ctx, timelineQuery)
if err != nil {
    log.Fatal(err)
}

Testing

The service includes comprehensive tests covering:

  • ✅ All core operations (create, update, delete, membership)
  • ✅ Authorization and privacy checks
  • ✅ Validation error handling
  • ✅ Event emission verification
  • ✅ Edge cases and error scenarios
  • ✅ Mock repository patterns

Run tests with:

go test ./pkg/services/lists/... -v

Integration

This service integrates with:

  • API Layer: Mastodon-compatible list endpoints
  • Storage Layer: DynamoDB via ListRepository and NoteRepository
  • Streaming Layer: Real-time event publishing
  • Federation: ActivityPub list activity distribution (future)

Performance Considerations

  • Lazy Loading: List memberships loaded on-demand
  • Pagination: All list queries support cursor-based pagination
  • Event Batching: Multiple operations can be batched for efficiency
  • Timeline Caching: List timelines can be cached for performance

Documentation

Overview

Package lists provides the core Lists Service for the Lesser project's API alignment. This service handles all list operations including creation, management, membership, and timeline generation. It emits appropriate events for real-time streaming.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AddToListCommand

type AddToListCommand struct {
	ListID         string `json:"list_id" validate:"required"`
	MemberUsername string `json:"member_username" validate:"required"`
	AdderID        string `json:"adder_id" validate:"required"` // Must be the list owner
}

AddToListCommand contains data needed to add a member to a list

type CreateListCommand

type CreateListCommand struct {
	Username      string `json:"username" validate:"required"`
	Title         string `json:"title" validate:"required,min=1,max=100"`
	RepliesPolicy string `json:"replies_policy" validate:"oneof=followed list none"`
	CreatorID     string `json:"creator_id" validate:"required"` // Must be the list owner
}

CreateListCommand contains all data needed to create a new list

type DeleteListCommand

type DeleteListCommand struct {
	ListID    string `json:"list_id" validate:"required"`
	DeleterID string `json:"deleter_id" validate:"required"` // Must be the list owner
}

DeleteListCommand contains data needed to delete a list

type GetListMembersQuery

type GetListMembersQuery struct {
	ListID     string                       `json:"list_id" validate:"required"`
	ViewerID   string                       `json:"viewer_id" validate:"required"` // Must be list owner
	Pagination interfaces.PaginationOptions `json:"pagination"`
}

GetListMembersQuery contains parameters for retrieving list members

type GetListQuery

type GetListQuery struct {
	ListID   string `json:"list_id" validate:"required"`
	ViewerID string `json:"viewer_id"` // User requesting the list (for privacy checks)
}

GetListQuery contains parameters for retrieving a list

type GetListTimelineQuery

type GetListTimelineQuery struct {
	ListID     string                       `json:"list_id" validate:"required"`
	ViewerID   string                       `json:"viewer_id" validate:"required"` // Must be list owner or member
	Pagination interfaces.PaginationOptions `json:"pagination"`
}

GetListTimelineQuery contains parameters for retrieving a list timeline

type ListResult

type ListResult struct {
	List   *models.List       `json:"list"`
	Events []*streaming.Event `json:"events"`
}

ListResult contains a list and associated events that were emitted

type ListUserListsQuery

type ListUserListsQuery struct {
	Username   string                       `json:"username" validate:"required"`
	ViewerID   string                       `json:"viewer_id"` // User requesting the lists
	Pagination interfaces.PaginationOptions `json:"pagination"`
}

ListUserListsQuery contains parameters for listing a user's lists

type MembersResult

type MembersResult struct {
	Members    []*storage.Account                            `json:"members"`
	Pagination *interfaces.PaginatedResult[*storage.Account] `json:"pagination"`
	Events     []*streaming.Event                            `json:"events"`
}

MembersResult contains list members with pagination and events

type MembershipResult

type MembershipResult struct {
	Success bool               `json:"success"`
	Events  []*streaming.Event `json:"events"`
}

MembershipResult contains membership operation result and events

type RemoveFromListCommand

type RemoveFromListCommand struct {
	ListID         string `json:"list_id" validate:"required"`
	MemberUsername string `json:"member_username" validate:"required"`
	RemoverID      string `json:"remover_id" validate:"required"` // Must be the list owner
}

RemoveFromListCommand contains data needed to remove a member from a list

type Result

type Result struct {
	Lists      []*models.List                            `json:"lists"`
	Pagination *interfaces.PaginatedResult[*models.List] `json:"pagination"`
	Events     []*streaming.Event                        `json:"events"`
}

Result contains multiple lists with pagination and events

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service provides list operations

func NewService

func NewService(
	listRepo interfaces.ListRepository,
	statusRepo interfaces.StatusRepository,
	publisher streaming.Publisher,
	logger *zap.Logger,
) *Service

NewService creates a new Lists Service with the required dependencies

func (*Service) AddToList

func (s *Service) AddToList(ctx context.Context, cmd *AddToListCommand) (*MembershipResult, error)

AddToList adds an account to a list and emits events

func (*Service) CreateList

func (s *Service) CreateList(ctx context.Context, cmd *CreateListCommand) (*ListResult, error)

CreateList creates a new list, validates input, stores it, and emits events

func (*Service) DeleteList

func (s *Service) DeleteList(ctx context.Context, cmd *DeleteListCommand) error

DeleteList deletes a list and emits events

func (*Service) GetList

func (s *Service) GetList(ctx context.Context, query *GetListQuery) (*models.List, error)

GetList retrieves a single list with privacy checks

func (*Service) GetListMembers

func (s *Service) GetListMembers(ctx context.Context, query *GetListMembersQuery) (*MembersResult, error)

GetListMembers retrieves all members of a list with pagination

func (*Service) GetListTimeline

func (s *Service) GetListTimeline(ctx context.Context, query *GetListTimelineQuery) (*TimelineResult, error)

GetListTimeline retrieves posts from list members with pagination

func (*Service) ListUserLists

func (s *Service) ListUserLists(ctx context.Context, query *ListUserListsQuery) (*Result, error)

ListUserLists retrieves a user's lists with pagination

func (*Service) RemoveFromList

func (s *Service) RemoveFromList(ctx context.Context, cmd *RemoveFromListCommand) (*MembershipResult, error)

RemoveFromList removes an account from a list and emits events

func (*Service) UpdateList

func (s *Service) UpdateList(ctx context.Context, cmd *UpdateListCommand) (*ListResult, error)

UpdateList updates an existing list and emits events

type TimelineResult

type TimelineResult struct {
	Statuses   []*models.Status                            `json:"statuses"`
	Pagination *interfaces.PaginatedResult[*models.Status] `json:"pagination"`
	Events     []*streaming.Event                          `json:"events"`
}

TimelineResult contains timeline posts with pagination and events

type UpdateListCommand

type UpdateListCommand struct {
	ListID        string `json:"list_id" validate:"required"`
	Title         string `json:"title,omitempty" validate:"omitempty,min=1,max=100"`
	RepliesPolicy string `json:"replies_policy,omitempty" validate:"omitempty,oneof=followed list none"`
	UpdaterID     string `json:"updater_id" validate:"required"` // Must be the list owner
}

UpdateListCommand contains data needed to update an existing list

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL