Complete list operations for organizing followed accounts into custom timelines.
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.
type List struct {
ID ID
Title string
}List is metadata for a list of users.
Fields:
ID - Unique list identifierTitle - Display name of the listfunc (c *Client) GetLists(ctx context.Context) ([]*List, error)Returns all lists for the current user.
Parameters:
ctx - Context for cancellation/timeoutReturns: 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)
}func (c *Client) GetList(ctx context.Context, id ID) (*List, error)Returns a list by ID.
Parameters:
ctx - Context for cancellation/timeoutid - List ID to retrieveReturns: List object or error
Example:
list, err := client.GetList(ctx, "123456")
if err != nil {
log.Fatal(err)
}
fmt.Printf("List: %s\n", list.Title)func (c *Client) CreateList(ctx context.Context, title string) (*List, error)Creates a new list with a given title.
Parameters:
ctx - Context for cancellation/timeouttitle - Name for the new listReturns: 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)func (c *Client) RenameList(ctx context.Context, id ID, title string) (*List, error)Renames a list.
Parameters:
ctx - Context for cancellation/timeoutid - List ID to renametitle - New title for the listReturns: 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)func (c *Client) DeleteList(ctx context.Context, id ID) errorDeletes a list.
Parameters:
ctx - Context for cancellation/timeoutid - List ID to deleteReturns: Error if operation fails
Example:
err := client.DeleteList(ctx, "123456")
if err != nil {
log.Fatal(err)
}
fmt.Println("List deleted successfully")func (c *Client) GetListAccounts(ctx context.Context, id ID) ([]*Account, error)Returns the accounts in a given list.
Parameters:
ctx - Context for cancellation/timeoutid - List IDReturns: 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)
}func (c *Client) AddToList(ctx context.Context, list ID, accounts ...ID) errorAdds accounts to a list. Only accounts already followed by the user can be added to a list.
Parameters:
ctx - Context for cancellation/timeoutlist - List IDaccounts - One or more account IDs to addReturns: 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.
func (c *Client) RemoveFromList(ctx context.Context, list ID, accounts ...ID) errorRemoves accounts from a list.
Parameters:
ctx - Context for cancellation/timeoutlist - List IDaccounts - One or more account IDs to removeReturns: 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")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
}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
}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
}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
}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
}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
}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)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
}
}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)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
}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")See also: