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

types.mddocs/

Common Types & Utilities

Core types and utility functions used throughout the library.

Core Types

ID

type ID string

ID is a type alias for entity identifiers. Mastodon uses string IDs that can be compared numerically.

Method:

func (i ID) Compare(j ID) int

Compares two Mastodon IDs. Returns:

  • -1 if i < j
  • 0 if i == j
  • 1 if i > j

Can be used with slices.SortFunc:

slices.SortFunc([]mastodon.ID{id1, id2}, mastodon.ID.Compare)

Method:

func (id *ID) UnmarshalJSON(data []byte) error

Custom JSON unmarshaling to handle both string and numeric IDs from the API.

Example:

id1 := mastodon.ID("123456")
id2 := mastodon.ID("789012")

comparison := id1.Compare(id2)
if comparison < 0 {
    fmt.Println("id1 is older than id2")
} else if comparison > 0 {
    fmt.Println("id1 is newer than id2")
} else {
    fmt.Println("IDs are equal")
}

// Sort IDs chronologically
ids := []mastodon.ID{"999", "123", "456"}
slices.SortFunc(ids, mastodon.ID.Compare)
// Result: ["123", "456", "999"]

Pagination

type Pagination struct {
    MaxID   ID
    SinceID ID
    MinID   ID
    Limit   int64
}

Pagination parameters for list queries using cursor-based pagination.

Fields:

  • MaxID - Return results older than this ID (scroll down/backward)
  • SinceID - Return results newer than this ID (check for updates)
  • MinID - Return results immediately newer than this ID (scroll up/forward)
  • Limit - Maximum number of results to return (default varies by endpoint)

Example:

// Initial fetch with limit
pg := &mastodon.Pagination{
    Limit: 40,
}
statuses, err := client.GetTimelineHome(ctx, pg)

// Get older statuses (scroll down)
if len(statuses) > 0 {
    pg.MaxID = statuses[len(statuses)-1].ID
    olderStatuses, err := client.GetTimelineHome(ctx, pg)
}

// Get newer statuses (check for updates)
pg = &mastodon.Pagination{
    SinceID: statuses[0].ID,
}
newerStatuses, err := client.GetTimelineHome(ctx, pg)

Mention

type Mention struct {
    URL      string
    Username string
    Acct     string
    ID       ID
}

Mention holds information for a mentioned account in a status.

Fields:

  • URL - Web URL for the mentioned account
  • Username - Local username (without domain)
  • Acct - Full username with domain (user@domain)
  • ID - Account ID

Example:

for _, mention := range status.Mentions {
    fmt.Printf("Mentioned: @%s (ID: %s)\n", mention.Acct, mention.ID)
}

Emoji

type Emoji struct {
    ShortCode       string
    StaticURL       string
    URL             string
    VisibleInPicker bool
}

Emoji holds information for custom emoji.

Fields:

  • ShortCode - Emoji shortcode (e.g., "blobcat")
  • StaticURL - URL for static (non-animated) version
  • URL - URL for animated version (if applicable)
  • VisibleInPicker - Whether emoji appears in picker

Example:

for _, emoji := range status.Emojis {
    fmt.Printf(":%s: - %s\n", emoji.ShortCode, emoji.URL)
}

Time Types

Unixtime

type Unixtime time.Time

Unixtime represents a Unix timestamp.

Method:

func (t *Unixtime) UnmarshalJSON(data []byte) error

Custom JSON unmarshaling for Unix timestamps.

Example:

week := time.Time(activity.Week)
fmt.Printf("Week of: %s\n", week.Format("2006-01-02"))

UnixTimeString

type UnixTimeString struct {
    time.Time
}

UnixTimeString represents a Unix timestamp encoded as a string in JSON.

Method:

func (u *UnixTimeString) UnmarshalJSON(b []byte) error

Custom JSON unmarshaling for string-encoded Unix timestamps.

Example:

day := time.Time(history.Day.Time)
fmt.Printf("Day: %s\n", day.Format("2006-01-02"))

Special Types

WriterResetter

type WriterResetter interface {
    io.Writer
    Reset()
}

WriterResetter is an interface that combines io.Writer with a Reset method. This is used internally for optimizing JSON encoding by reusing buffers.

Methods:

  • Write(p []byte) (n int, err error) - From io.Writer interface
  • Reset() - Resets the writer to be empty, allowing buffer reuse

Note: This is primarily an internal interface used by the Client for performance optimization. Most users will not need to interact with this type directly.

Sbool

type Sbool bool

Sbool is a boolean type that handles JSON string booleans (e.g., "true", "false").

Method:

func (s *Sbool) UnmarshalJSON(data []byte) error

Custom JSON unmarshaling to handle string booleans from API.

Example:

trueVal := mastodon.Sbool(true)
falseVal := mastodon.Sbool(false)

alerts := &mastodon.PushAlerts{
    Follow:    &trueVal,
    Mention:   &trueVal,
    Favourite: &falseVal,
    Reblog:    &falseVal,
}

APIError

type APIError struct {
    Message    string
    StatusCode int
    // contains filtered or unexported fields
}

APIError represents an error returned by the Mastodon API.

Method:

func (e *APIError) Error() string

Returns the error message as a string.

Example:

status, err := client.GetStatus(ctx, "nonexistent")
if err != nil {
    if apiErr, ok := err.(*mastodon.APIError); ok {
        fmt.Printf("API Error: %s (HTTP %d)\n", apiErr.Message, apiErr.StatusCode)

        switch apiErr.StatusCode {
        case 404:
            fmt.Println("Status not found")
        case 429:
            fmt.Println("Rate limited")
        case 401:
            fmt.Println("Authentication required")
        case 403:
            fmt.Println("Forbidden")
        case 500:
            fmt.Println("Server error")
        }
    } else {
        fmt.Printf("Error: %v\n", err)
    }
}

Utility Functions

String

func String(v string) *string

String is a helper function to get a pointer to a string value.

Example:

// For updating profile fields where nil means "don't change"
displayName := mastodon.String("New Display Name")
note := mastodon.String("Updated bio")

profile := &mastodon.Profile{
    DisplayName: displayName,
    Note:        note,
}

account, err := client.AccountUpdate(ctx, profile)

Base64Encode

func Base64Encode(file *os.File) (string, error)

Base64Encode returns the base64 data URI format string of the file.

Example:

file, err := os.Open("avatar.jpg")
if err != nil {
    log.Fatal(err)
}
defer file.Close()

encoded, err := mastodon.Base64Encode(file)
if err != nil {
    log.Fatal(err)
}

profile := &mastodon.Profile{
    Avatar: encoded,
}

account, err := client.AccountUpdate(ctx, profile)

Base64EncodeFileName

func Base64EncodeFileName(filename string) (string, error)

Base64EncodeFileName returns the base64 data URI format string of the file with the given filename.

Example:

encoded, err := mastodon.Base64EncodeFileName("header.jpg")
if err != nil {
    log.Fatal(err)
}

profile := &mastodon.Profile{
    Header: encoded,
}

account, err := client.AccountUpdate(ctx, profile)

Usage Examples

Example: ID Comparison and Sorting

func sortStatusesByID(statuses []*mastodon.Status) {
    // Sort statuses by ID (chronological order)
    slices.SortFunc(statuses, func(a, b *mastodon.Status) int {
        return a.ID.Compare(b.ID)
    })

    fmt.Println("Statuses sorted from oldest to newest")
}

func findNewestStatus(statuses []*mastodon.Status) *mastodon.Status {
    if len(statuses) == 0 {
        return nil
    }

    newest := statuses[0]
    for _, status := range statuses[1:] {
        if status.ID.Compare(newest.ID) > 0 {
            newest = status
        }
    }

    return newest
}

Example: Pagination Patterns

// Pattern 1: Load all pages
func loadAllStatuses(client *mastodon.Client) ([]*mastodon.Status, error) {
    ctx := context.Background()
    var allStatuses []*mastodon.Status

    pg := &mastodon.Pagination{Limit: 40}

    for {
        statuses, err := client.GetTimelineHome(ctx, pg)
        if err != nil {
            return nil, err
        }

        if len(statuses) == 0 {
            break
        }

        allStatuses = append(allStatuses, statuses...)

        // Get next page
        pg.MaxID = statuses[len(statuses)-1].ID
    }

    return allStatuses, nil
}

// Pattern 2: Load until condition
func loadUntilDate(client *mastodon.Client, until time.Time) ([]*mastodon.Status, error) {
    ctx := context.Background()
    var statuses []*mastodon.Status

    pg := &mastodon.Pagination{Limit: 40}

    for {
        batch, err := client.GetTimelineHome(ctx, pg)
        if err != nil {
            return nil, err
        }

        if len(batch) == 0 {
            break
        }

        for _, status := range batch {
            if status.CreatedAt.Before(until) {
                return statuses, nil // Reached target date
            }
            statuses = append(statuses, status)
        }

        pg.MaxID = batch[len(batch)-1].ID
    }

    return statuses, nil
}

// Pattern 3: Real-time updates
func pollForNewStatuses(client *mastodon.Client, lastID mastodon.ID) ([]*mastodon.Status, error) {
    ctx := context.Background()

    pg := &mastodon.Pagination{
        SinceID: lastID,
    }

    return client.GetTimelineHome(ctx, pg)
}

Example: Error Handling

func handleAPIError(err error) {
    if err == nil {
        return
    }

    apiErr, ok := err.(*mastodon.APIError)
    if !ok {
        // Not an API error (network error, etc.)
        log.Printf("Network or other error: %v", err)
        return
    }

    // Handle specific HTTP status codes
    switch apiErr.StatusCode {
    case 400:
        log.Printf("Bad request: %s", apiErr.Message)
    case 401:
        log.Fatal("Authentication required - check access token")
    case 403:
        log.Printf("Forbidden: %s", apiErr.Message)
    case 404:
        log.Printf("Not found: %s", apiErr.Message)
    case 422:
        log.Printf("Validation error: %s", apiErr.Message)
    case 429:
        log.Printf("Rate limited - please wait before retrying")
        time.Sleep(time.Minute)
    case 500, 502, 503:
        log.Printf("Server error: %s", apiErr.Message)
    default:
        log.Printf("API error %d: %s", apiErr.StatusCode, apiErr.Message)
    }
}

// Usage
status, err := client.PostStatus(ctx, toot)
handleAPIError(err)

Example: Working with Pointers

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

    // Only update display name, leave other fields unchanged
    profile := &mastodon.Profile{
        DisplayName: mastodon.String("New Name"),
        // Note is nil, so it won't be updated
        // Locked is nil, so it won't be updated
    }

    account, err := client.AccountUpdate(ctx, profile)
    if err != nil {
        return err
    }

    fmt.Printf("Updated display name to: %s\n", account.DisplayName)
    return nil
}

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

    // Set to empty string to clear
    empty := ""
    profile := &mastodon.Profile{
        DisplayName: &empty, // Not nil, so it will be updated to empty
    }

    account, err := client.AccountUpdate(ctx, profile)
    if err != nil {
        return err
    }

    fmt.Println("Cleared display name")
    return nil
}

Example: Base64 Encoding for Profile Images

func updateProfileImages(client *mastodon.Client, avatarPath, headerPath string) error {
    ctx := context.Background()

    // Encode avatar
    avatar, err := mastodon.Base64EncodeFileName(avatarPath)
    if err != nil {
        return fmt.Errorf("failed to encode avatar: %w", err)
    }

    // Encode header
    header, err := mastodon.Base64EncodeFileName(headerPath)
    if err != nil {
        return fmt.Errorf("failed to encode header: %w", err)
    }

    // Update profile
    profile := &mastodon.Profile{
        Avatar: avatar,
        Header: header,
    }

    account, err := client.AccountUpdate(ctx, profile)
    if err != nil {
        return err
    }

    fmt.Println("Updated profile images")
    fmt.Printf("  Avatar: %s\n", account.Avatar)
    fmt.Printf("  Header: %s\n", account.Header)

    return nil
}

Example: Custom Emoji Processing

func replaceCustomEmojis(content string, emojis []mastodon.Emoji) string {
    for _, emoji := range emojis {
        shortcode := ":" + emoji.ShortCode + ":"
        img := fmt.Sprintf(`<img src="%s" alt="%s" class="emoji">`,
            emoji.URL, emoji.ShortCode)
        content = strings.ReplaceAll(content, shortcode, img)
    }
    return content
}

// Usage
processedContent := replaceCustomEmojis(status.Content, status.Emojis)

Example: Mention Processing

func extractMentionedUsers(status *mastodon.Status) []string {
    var users []string
    for _, mention := range status.Mentions {
        users = append(users, mention.Acct)
    }
    return users
}

func isUserMentioned(status *mastodon.Status, username string) bool {
    for _, mention := range status.Mentions {
        if mention.Acct == username || mention.Username == username {
            return true
        }
    }
    return false
}

// Usage
mentions := extractMentionedUsers(status)
fmt.Printf("Status mentions: %v\n", mentions)

if isUserMentioned(status, "myusername") {
    fmt.Println("You were mentioned in this status!")
}

Type Conversion Helpers

// Convert time.Time to string for display
func formatTime(t time.Time) string {
    return t.Format("2006-01-02 15:04:05")
}

// Convert Sbool to regular bool
func sboolToBool(sb *mastodon.Sbool) bool {
    if sb == nil {
        return false
    }
    return bool(*sb)
}

// Create Sbool pointer from bool
func boolToSbool(b bool) *mastodon.Sbool {
    sb := mastodon.Sbool(b)
    return &sb
}

// Convert int to string for API parameters
func intToString(i int) string {
    return strconv.Itoa(i)
}

Best Practices

1. Use Type-Safe IDs

Always use the ID type for identifiers:

// Good
var statusID mastodon.ID = "123456"

// Avoid
var statusID string = "123456"

2. Handle Nil Pointers

Check for nil before dereferencing:

if status.Poll != nil {
    fmt.Printf("Poll has %d options\n", len(status.Poll.Options))
}

3. Use Pagination Consistently

Always use Pagination for list operations:

pg := &mastodon.Pagination{Limit: 40}
results, err := client.GetTimelineHome(ctx, pg)

4. Check API Errors

Always check for and handle API errors:

if err != nil {
    if apiErr, ok := err.(*mastodon.APIError); ok {
        // Handle API error
    }
    return err
}

5. Use Helper Functions

Use provided helpers for common operations:

// Use String helper for optional fields
profile.DisplayName = mastodon.String("New Name")

// Use Base64 helpers for images
avatar, _ := mastodon.Base64EncodeFileName("avatar.jpg")

Related Documentation

See also:

  • Accounts - Account types
  • Statuses - Status types
  • Authentication - Auth types
  • All other documentation files use these common types