or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

accounts.mdauthentication.mdconversations.mdfilters.mdindex.mdinstance.mdlists.mdmedia.mdnotifications.mdpolls.mdreports.mdsearch.mdstatuses.mdstreaming.mdtags.mdtimelines.mdtypes.md
tile.json

lists.mddocs/

List Management

Complete list operations for organizing followed accounts into custom timelines.

Overview

Lists allow you to organize followed accounts into custom groups and view their statuses in separate timelines. Only accounts you already follow can be added to lists.

Types

List

type List struct {
    ID    ID
    Title string
}

List is metadata for a list of users.

Fields:

  • ID - Unique list identifier
  • Title - Display name of the list

List Operations

GetLists { .api }

func (c *Client) GetLists(ctx context.Context) ([]*List, error)

Returns all lists for the current user.

Parameters:

  • ctx - Context for cancellation/timeout

Returns: Slice of List objects or error

Example:

lists, err := client.GetLists(ctx)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("You have %d lists:\n", len(lists))
for _, list := range lists {
    fmt.Printf("  %s (ID: %s)\n", list.Title, list.ID)
}

GetList { .api }

func (c *Client) GetList(ctx context.Context, id ID) (*List, error)

Returns a list by ID.

Parameters:

  • ctx - Context for cancellation/timeout
  • id - List ID to retrieve

Returns: List object or error

Example:

list, err := client.GetList(ctx, "123456")
if err != nil {
    log.Fatal(err)
}
fmt.Printf("List: %s\n", list.Title)

CreateList { .api }

func (c *Client) CreateList(ctx context.Context, title string) (*List, error)

Creates a new list with a given title.

Parameters:

  • ctx - Context for cancellation/timeout
  • title - Name for the new list

Returns: Created List object or error

Example:

list, err := client.CreateList(ctx, "Go Developers")
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Created list: %s (ID: %s)\n", list.Title, list.ID)

RenameList { .api }

func (c *Client) RenameList(ctx context.Context, id ID, title string) (*List, error)

Renames a list.

Parameters:

  • ctx - Context for cancellation/timeout
  • id - List ID to rename
  • title - New title for the list

Returns: Updated List object or error

Example:

list, err := client.RenameList(ctx, "123456", "Golang Developers")
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Renamed list to: %s\n", list.Title)

DeleteList { .api }

func (c *Client) DeleteList(ctx context.Context, id ID) error

Deletes a list.

Parameters:

  • ctx - Context for cancellation/timeout
  • id - List ID to delete

Returns: Error if operation fails

Example:

err := client.DeleteList(ctx, "123456")
if err != nil {
    log.Fatal(err)
}
fmt.Println("List deleted successfully")

List Membership

GetListAccounts { .api }

func (c *Client) GetListAccounts(ctx context.Context, id ID) ([]*Account, error)

Returns the accounts in a given list.

Parameters:

  • ctx - Context for cancellation/timeout
  • id - List ID

Returns: Slice of Account objects or error

Example:

accounts, err := client.GetListAccounts(ctx, "123456")
if err != nil {
    log.Fatal(err)
}

fmt.Printf("List contains %d accounts:\n", len(accounts))
for _, account := range accounts {
    fmt.Printf("  @%s - %s\n", account.Acct, account.DisplayName)
}

AddToList { .api }

func (c *Client) AddToList(ctx context.Context, list ID, accounts ...ID) error

Adds accounts to a list. Only accounts already followed by the user can be added to a list.

Parameters:

  • ctx - Context for cancellation/timeout
  • list - List ID
  • accounts - One or more account IDs to add

Returns: Error if operation fails

Example:

// Add single account
err := client.AddToList(ctx, "123456", "789")
if err != nil {
    log.Fatal(err)
}

// Add multiple accounts
err = client.AddToList(ctx, "123456", "789", "012", "345")
if err != nil {
    log.Fatal(err)
}
fmt.Println("Accounts added to list")

Important: You can only add accounts you already follow. If you try to add an account you don't follow, the operation will fail.

RemoveFromList { .api }

func (c *Client) RemoveFromList(ctx context.Context, list ID, accounts ...ID) error

Removes accounts from a list.

Parameters:

  • ctx - Context for cancellation/timeout
  • list - List ID
  • accounts - One or more account IDs to remove

Returns: Error if operation fails

Example:

// Remove single account
err := client.RemoveFromList(ctx, "123456", "789")
if err != nil {
    log.Fatal(err)
}

// Remove multiple accounts
err = client.RemoveFromList(ctx, "123456", "789", "012")
if err != nil {
    log.Fatal(err)
}
fmt.Println("Accounts removed from list")

Usage Examples

Example: Create List and Add Members

func createDevelopersList(client *mastodon.Client) error {
    ctx := context.Background()

    // Create the list
    list, err := client.CreateList(ctx, "Go Developers")
    if err != nil {
        return err
    }

    fmt.Printf("Created list: %s (ID: %s)\n", list.Title, list.ID)

    // Search for accounts to add
    accounts, err := client.AccountsSearch(ctx, "golang", 10)
    if err != nil {
        return err
    }

    // Follow accounts and add to list
    for _, account := range accounts {
        // Follow the account first
        _, err := client.AccountFollow(ctx, account.ID)
        if err != nil {
            log.Printf("Failed to follow @%s: %v", account.Acct, err)
            continue
        }

        // Add to list
        err = client.AddToList(ctx, list.ID, account.ID)
        if err != nil {
            log.Printf("Failed to add @%s to list: %v", account.Acct, err)
            continue
        }

        fmt.Printf("Added @%s to list\n", account.Acct)
    }

    return nil
}

Example: List All Lists with Members

func displayAllLists(client *mastodon.Client) error {
    ctx := context.Background()

    lists, err := client.GetLists(ctx)
    if err != nil {
        return err
    }

    for _, list := range lists {
        fmt.Printf("\n%s (ID: %s)\n", list.Title, list.ID)
        fmt.Println(strings.Repeat("-", len(list.Title)+10))

        accounts, err := client.GetListAccounts(ctx, list.ID)
        if err != nil {
            log.Printf("Error getting accounts: %v", err)
            continue
        }

        if len(accounts) == 0 {
            fmt.Println("  (empty)")
        } else {
            for _, account := range accounts {
                fmt.Printf("  @%s - %s\n", account.Acct, account.DisplayName)
            }
        }
    }

    return nil
}

Example: Bulk Add Followers to List

func addFollowersToList(client *mastodon.Client, listID mastodon.ID, maxCount int) error {
    ctx := context.Background()

    // Get current user
    me, err := client.GetAccountCurrentUser(ctx)
    if err != nil {
        return err
    }

    // Get following list
    following, err := client.GetAccountFollowing(ctx, me.ID, &mastodon.Pagination{Limit: int64(maxCount)})
    if err != nil {
        return err
    }

    // Collect account IDs
    var accountIDs []mastodon.ID
    for _, account := range following {
        accountIDs = append(accountIDs, account.ID)
    }

    // Add all accounts to list
    if len(accountIDs) > 0 {
        err = client.AddToList(ctx, listID, accountIDs...)
        if err != nil {
            return err
        }
        fmt.Printf("Added %d accounts to list\n", len(accountIDs))
    }

    return nil
}

Example: Manage List Membership

type ListManager struct {
    client *mastodon.Client
}

func (lm *ListManager) CreateTopicList(ctx context.Context, topic string) (*mastodon.List, error) {
    return lm.client.CreateList(ctx, topic)
}

func (lm *ListManager) AddAccountsByTag(ctx context.Context, listID mastodon.ID, hashtag string, limit int) error {
    // Search for statuses with hashtag
    results, err := lm.client.Search(ctx, "#"+hashtag, false)
    if err != nil {
        return err
    }

    // Extract unique accounts
    accountMap := make(map[mastodon.ID]bool)
    var accountIDs []mastodon.ID

    for _, status := range results.Statuses {
        if !accountMap[status.Account.ID] {
            accountMap[status.Account.ID] = true
            accountIDs = append(accountIDs, status.Account.ID)

            if len(accountIDs) >= limit {
                break
            }
        }
    }

    // Follow and add to list
    for _, accountID := range accountIDs {
        // Follow first
        _, err := lm.client.AccountFollow(ctx, accountID)
        if err != nil {
            log.Printf("Failed to follow %s: %v", accountID, err)
            continue
        }

        // Add to list
        err = lm.client.AddToList(ctx, listID, accountID)
        if err != nil {
            log.Printf("Failed to add %s to list: %v", accountID, err)
        }
    }

    return nil
}

func (lm *ListManager) CleanupList(ctx context.Context, listID mastodon.ID) error {
    // Get list members
    accounts, err := lm.client.GetListAccounts(ctx, listID)
    if err != nil {
        return err
    }

    // Get current relationships
    accountIDs := make([]string, len(accounts))
    for i, acc := range accounts {
        accountIDs[i] = string(acc.ID)
    }

    relationships, err := lm.client.GetAccountRelationships(ctx, accountIDs)
    if err != nil {
        return err
    }

    // Remove accounts we're no longer following
    var toRemove []mastodon.ID
    for _, rel := range relationships {
        if !rel.Following {
            toRemove = append(toRemove, rel.ID)
        }
    }

    if len(toRemove) > 0 {
        err = lm.client.RemoveFromList(ctx, listID, toRemove...)
        if err != nil {
            return err
        }
        fmt.Printf("Removed %d accounts from list\n", len(toRemove))
    }

    return nil
}

Example: View List Timeline

func viewListTimeline(client *mastodon.Client, listID mastodon.ID) error {
    ctx := context.Background()

    // Get list info
    list, err := client.GetList(ctx, listID)
    if err != nil {
        return err
    }

    fmt.Printf("Timeline for: %s\n", list.Title)
    fmt.Println(strings.Repeat("=", 50))

    // Get list timeline
    statuses, err := client.GetTimelineList(ctx, listID, nil)
    if err != nil {
        return err
    }

    for _, status := range statuses {
        fmt.Printf("\n@%s at %s:\n",
            status.Account.Acct, status.CreatedAt.Format("2006-01-02 15:04"))
        fmt.Printf("%s\n", status.Content)
    }

    return nil
}

Example: Export List Configuration

type ListExport struct {
    Title    string   `json:"title"`
    Accounts []string `json:"accounts"`
}

func exportList(client *mastodon.Client, listID mastodon.ID) (*ListExport, error) {
    ctx := context.Background()

    // Get list details
    list, err := client.GetList(ctx, listID)
    if err != nil {
        return nil, err
    }

    // Get list members
    accounts, err := client.GetListAccounts(ctx, listID)
    if err != nil {
        return nil, err
    }

    // Create export
    export := &ListExport{
        Title:    list.Title,
        Accounts: make([]string, len(accounts)),
    }

    for i, account := range accounts {
        export.Accounts[i] = account.Acct
    }

    return export, nil
}

func importList(client *mastodon.Client, export *ListExport) error {
    ctx := context.Background()

    // Create list
    list, err := client.CreateList(ctx, export.Title)
    if err != nil {
        return err
    }

    // Add each account
    for _, acct := range export.Accounts {
        // Lookup account
        account, err := client.AccountLookup(ctx, acct)
        if err != nil {
            log.Printf("Failed to lookup @%s: %v", acct, err)
            continue
        }

        // Follow if not already following
        rel, err := client.GetAccountRelationships(ctx, []string{string(account.ID)})
        if err != nil || len(rel) == 0 {
            log.Printf("Failed to check relationship for @%s", acct)
            continue
        }

        if !rel[0].Following {
            _, err = client.AccountFollow(ctx, account.ID)
            if err != nil {
                log.Printf("Failed to follow @%s: %v", acct, err)
                continue
            }
        }

        // Add to list
        err = client.AddToList(ctx, list.ID, account.ID)
        if err != nil {
            log.Printf("Failed to add @%s to list: %v", acct, err)
        }
    }

    fmt.Printf("Imported list: %s with %d accounts\n", list.Title, len(export.Accounts))
    return nil
}

Best Practices

1. Check Following Status

Always ensure you follow an account before adding to a list:

// Check if following
relationships, err := client.GetAccountRelationships(ctx, []string{string(accountID)})
if err != nil || len(relationships) == 0 || !relationships[0].Following {
    // Follow first
    _, err = client.AccountFollow(ctx, accountID)
    if err != nil {
        return err
    }
}

// Then add to list
err = client.AddToList(ctx, listID, accountID)

2. Handle Errors Gracefully

Not all accounts can be added to lists:

for _, accountID := range accountIDs {
    err := client.AddToList(ctx, listID, accountID)
    if err != nil {
        log.Printf("Failed to add %s: %v (might not be following)", accountID, err)
        continue
    }
}

3. Batch Operations

Add multiple accounts at once for efficiency:

// Better: add multiple at once
err := client.AddToList(ctx, listID, account1, account2, account3)

// Less efficient: individual adds
client.AddToList(ctx, listID, account1)
client.AddToList(ctx, listID, account2)
client.AddToList(ctx, listID, account3)

4. Maintain List Integrity

Periodically clean up lists by removing unfollowed accounts:

func cleanupLists(client *mastodon.Client) error {
    lists, _ := client.GetLists(ctx)
    for _, list := range lists {
        cleanupList(client, list.ID)
    }
    return nil
}

5. Use Descriptive Names

Create lists with clear, descriptive titles:

// Good
client.CreateList(ctx, "Go Programming")
client.CreateList(ctx, "Local Artists")

// Less clear
client.CreateList(ctx, "List 1")
client.CreateList(ctx, "Misc")

Related Types

See also:

  • Accounts - For account operations
  • Timelines - For viewing list timelines
  • Streaming - For streaming list events
  • Types - For ID and other common types