Skip to content

Releases: tirthpatell/threads-go

v1.9.0

18 Apr 00:22
991530c

Choose a tag to compare

Security-focused release. Hardens OAuth against login CSRF (CWE-352) and tightens log redaction, ownership checks, and rate-limit thread-safety. Contains API breakage on the auth surface only.

Breaking changes

  • Authenticator.GetAuthURL now returns (authURL, state, err) instead of just a URL string. Callers must persist state (session/cookie) and pass it back on exchange.

  • Authenticator.ExchangeCodeForToken now requires (ctx, code, expectedState, receivedState). The two states are compared with crypto/subtle.ConstantTimeCompare before any network call; mismatch or empty values return a ValidationError.

    Migration: see examples/authentication/main.go.

Security fixes

  • OAuth state CSRF (HIGH, CWE-352): state is generated with crypto/rand and surfaced to the caller; the predictable time-based fallback was removed (fail-closed on rand errors).
  • Debug-log redaction: access_token, client_secret, input_token, code, and refresh_token are redacted from request URLs before logging.
  • validatePostOwnership: prefers numeric owner ID over username and fails closed on empty identifiers — previously two empty strings compared equal and silently authorised deletion.
  • DisableRateLimiting / EnableRateLimiting: the HTTPClient's limiter is now an atomic.Pointer so toggling from one goroutine is race-safe against an in-flight request on another.

CI / chores

  • Bump schneegans/dynamic-badges-action v1.7.0 → v1.8.0 (supersedes #25).
  • Bump codecov/codecov-action v5 → v6 (supersedes #26).
  • Drop TestIntegration_GIFPosts — Tenor API deprecated.

Full Changelog: v1.8.0...v1.9.0

v1.8.0

21 Mar 01:02
96c064a

Choose a tag to compare

Breaking Changes

This release includes source-incompatible changes to exported interfaces and types. Code that implements these interfaces (e.g., mocks, test wrappers) or reads these fields will need updates.

Change Before After
PostDeleter.DeletePost return error (string, error) — returns deleted_id
PostReader.GetUserMentions param *PaginationOptions *PostsOptions — adds since/until support
Post.ReplyAudience type string ReplyAudience (typed constant)
Post.HideStatus type string HideStatus (typed constant)
Post.TextEntities type []TextEntity *TextEntitiesResponse (API returns {"data": [...]} wrapper)

New Features

  • App Access Tokens — GetAppAccessToken() and GetAppAccessTokenShorthand() for app-level auth (e.g., oEmbed API)
  • Ghost Posts on interface — GetUserGhostPosts added to PostReader interface
  • Mentions time filtering — GetUserMentions now supports since/until unix timestamp parameters
  • Response media type constants — MediaTypeResponseText (TEXT_POST), MediaTypeResponseCarousel (CAROUSEL_ALBUM), MediaTypeAudio, MediaTypeRepostFacade
  • Typed reply/hide constants — ReplyAudience (5 values) and HideStatus (6 values) for type-safe response handling
  • Geo-gating error codes — ErrCodeFeatureNotAvailable, ErrCodeGeoGatingInvalidCountryCodes
  • Container error constants — 10 typed ContainerErr* constants for programmatic error handling

Bug Fixes

  • Post struct missing fields — Added IsSpoilerMedia, TextEntities, TextAttachment, AllowlistedCountryCodes, LocationID, Location
  • User.RecentlySearchedKeywords — Fixed type from []string to []RecentSearch (struct with Query/Timestamp) and wired field mapping
  • User.IsEligibleForGeoGating — Added missing boolean field
  • TotalValue.LinkURL — Added for per-link click metric breakdowns
  • ContainerBuilder.SetIsGhostPost — Now order-independent with SetMediaType; SetIsGhostPost(false) correctly clears the flag

Validation Improvements

  • Poll options: require sequential ordering (D requires C), reject whitespace-only options, enforce 1–25 char length
  • Alt text: enforce 1000-character max on image/video posts
  • Text styling: validate style values against allowed set (bold, italic, highlight, underline, strikethrough)
  • Timestamps: since/until validated against MinSearchTimestamp on all endpoints (GetUserPostsWithOptions, GetUserMentions, GetPublicProfilePosts, GetUserReplies), with since <= until ordering check
  • ValidatePostsOptions centralizes pagination + timestamp validation

Documentation

  • Rate limit formula (4800 × Impressions) and per-operation defaults documented on QuotaConfig
  • views/shares insight metrics marked as "in development" per API docs
  • DeletePost documents 100/24hr limit and threads_delete scope requirement
  • GetAppAccessToken notes RFC 6749 deviation (GET exposes client_secret)

Other

  • Version constant updated from 1.1.0 to 1.8.0 (was stale; aligns with release tags)
  • Test coverage improvements across all new code paths
  • Replace Dependabot with govulncheck, increase coverage to 93.6%, add Codecov

Full Changelog: v1.7.1...v1.8.0

v1.7.1

13 Mar 22:54
7cc9522

Choose a tag to compare

What's Changed

  • fix: use unicode character count for text length validation by @shyuan in #18
  • fix: library improvements - bug fixes, tests, and coverage badge by @tirthpatell in #19
  • fix: restrict GITHUB_TOKEN permissions in CI workflows by @tirthpatell in #20
  • docs: update README, examples, and docs for recent API features by @tirthpatell in #21

New Contributors

Full Changelog: v1.7.0...v1.7.1

v1.7.0

13 Mar 01:05
5280c7f

Choose a tag to compare

What's Changed

  • fix: improve retry logic, error metadata, and container lifecycle by @tirthpatell in #17

Full Changelog: v1.6.0...v1.7.0

v1.6.0

06 Mar 00:43
0344dca

Choose a tag to compare

What's Changed

  • feat: Add March 2026 API updates and fix carousel ordering by @tirthpatell in #16

Full Changelog: v1.5.0...v1.6.0

v1.5.0

16 Feb 02:22
3140d4a

Choose a tag to compare

What's Changed

Full Changelog: v1.4.0...v1.5.0

v1.4.0

11 Feb 03:18
7fc2a62

Choose a tag to compare

What's Changed

Full Changelog: v1.3.0...v1.4.0

v1.3.0

19 Jan 23:03
d8392f2

Choose a tag to compare

What's Changed

Full Changelog: v1.2.0...v1.3.0

v1.2.0

16 Dec 01:52
823e052

Choose a tag to compare

What's Changed

Feature: Changelog Updates (Nov-Dec 2025)

  1. Ghost Posts (Dec 15, 2025)
  • Creation:
    • Added IsGhostPost field to TextPostContent.
    • Updated ContainerBuilder to support the is_ghost_post parameter.
    • Implemented validation to ensure ghost posts cannot be replies.
  • Retrieval:
    • Added GetUserGhostPosts(ctx, userID, opts) method to posts_read.go, targeting the specific GET /{user-id}/ghost_posts endpoint.
    • Updated Post struct with GhostPostStatus and GhostPostExpirationTimestamp.
    • Defined GhostPostFields constant to request the correct fields.
  1. Link Limits (Dec 8, 2025)
  • Validation:
    • Added MaxLinks = 5 constant.
    • Implemented ValidateLinkCount in Validator to enforce the 5-link limit.
    • The validation logic correctly counts unique URLs and integrates link_attachment (counting it only if it differs from URLs in the text body), strictly following API documentation
      examples.
    • Applied this validation to Text, Image, Video, and Carousel post content.
  1. Follower Discovery Limits (Nov 20, 2025)
  • Verification: Verified that the client's existing dynamic rate limiting handles the reduced follower discovery limit (1,000 -> 100) correctly via X-RateLimit-Limit headers without
    requiring code changes.

Full Changelog: v1.1.0...v1.2.0

v1.1.0

25 Nov 03:18
51d5c61

Choose a tag to compare

Versioning Note

  • Starting with this release, threads-go is adopting proper https://semver.org/. Previously, patch versions were incorrectly bumped for new features.
  • This release jumps from v1.0.4 to v1.1.0 to reflect the new feature additions.

New Features

  • GIF Attachment Support
    • You can now attach GIFs to text posts using the Threads API gif_attachment parameter. Tenor is currently the only supported GIF provider.

Note: GIFs can only be attached to text-only posts (not image, video, or carousel posts).


What's Changed

  • build(deps): bump actions/checkout from 5 to 6 in /.github/workflows by @dependabot in #8
  • feat: add GIF attachment support for text posts by @tirthpatell in #9

Full Changelog: v1.0.4...v1.1.0