# go-twitter-api gRPC 完整参考 > Go 实现的 X(Twitter)客户端协议执行器,通过 gRPC 为 Python 应用提供异步调用能力。 ## Service 清单 | Service | 平台 | RPC 数 | 说明 | | --- | --- | --- | --- | | `AndroidApi` | android | 1 | AndroidApi is the Android client-protocol surface. One endpoint = one RPC; Login is the sanctioned cross-endpoint exception (a login state machine that must atomically mint + verify session credentials). | | `MediaApi` | android | 1 | MediaApi is the Android media-upload surface (upload.x.com). | | `PostsApi` | android | 8 | PostsApi is the Android post-authoring + engagement surface (api.x.com GraphQL). | | `TimelineApi` | android | 2 | TimelineApi is the Android timeline-read surface. | | `UsersApi` | android | 4 | UsersApi is the Android profile-read surface. | ## RPC 签名 | RPC | 请求 | 响应 | proto 文件 | | --- | --- | --- | --- | | `AndroidApi/Login` | `LoginRequest` | `LoginResponse` | `android.proto` | | `MediaApi/UploadMedia` | `UploadMediaRequest` | `UploadMediaResponse` | `media.proto` | | `PostsApi/CreatePost` | `CreatePostRequest` | `CreatePostResponse` | `posts.proto` | | `PostsApi/DeletePost` | `DeletePostRequest` | `DeletePostResponse` | `posts.proto` | | `PostsApi/Like` | `EngageRequest` | `EngageResponse` | `posts.proto` | | `PostsApi/Quote` | `QuoteRequest` | `CreatePostResponse` | `posts.proto` | | `PostsApi/Reply` | `ReplyRequest` | `CreatePostResponse` | `posts.proto` | | `PostsApi/Retweet` | `EngageRequest` | `EngageResponse` | `posts.proto` | | `PostsApi/Unlike` | `EngageRequest` | `EngageResponse` | `posts.proto` | | `PostsApi/Unretweet` | `EngageRequest` | `EngageResponse` | `posts.proto` | | `TimelineApi/HomeTimeline` | `HomeTimelineRequest` | `TimelineResponse` | `timeline.proto` | | `TimelineApi/UserTweets` | `UserTweetsRequest` | `TimelineResponse` | `timeline.proto` | | `UsersApi/Me` | `MeRequest` | `UserResponse` | `users.proto` | | `UsersApi/ProfileAnalytics` | `ProfileAnalyticsRequest` | `RawResponse` | `users.proto` | | `UsersApi/ProfileModules` | `ProfileModulesRequest` | `RawResponse` | `users.proto` | | `UsersApi/UserByRestID` | `UserByRestIDRequest` | `UserResponse` | `users.proto` | ## 消息定义 ### twitter.android.v1.Account | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `username` (#1) | `string` | - | - | | `password` (#2) | `string` | - | plaintext — server-side only, never logged | | `totp_seed` (#3) | `string` | - | plaintext 2FA secret; optional | ### twitter.android.v1.AndroidAccountState > AndroidAccountState is the full round-trip identity for the android namespace. Mirrors identity.AndroidAccountState (OAuth 1.0a session). | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `account` (#1) | `Account`(见消息定义) | - | - | | `device` (#2) | `AndroidDevice`(见消息定义) | - | - | | `app_version` (#3) | `string` | - | - | | `proxy` (#4) | `string` | - | - | | `session` (#5) | `AndroidSession`(见消息定义) | - | - | ### twitter.android.v1.AndroidDevice | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `client_uuid` (#1) | `string` | - | - | | `device_id` (#2) | `string` | - | - | | `ad_id` (#3) | `string` | - | - | | `model` (#4) | `string` | - | - | | `manufacturer` (#5) | `string` | - | - | | `brand` (#6) | `string` | - | - | | `board` (#7) | `string` | - | - | | `os_version` (#8) | `string` | - | - | | `build_year` (#9) | `string` | - | - | | `language` (#10) | `string` | - | - | | `timezone` (#11) | `string` | - | - | | `sec_patch` (#12) | `string` | - | - | | `limit_ad_tracking` (#13) | `string` | - | - | | `attest_token` (#14) | `string` | - | - | ### twitter.android.v1.AndroidSession | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `oauth_token` (#1) | `string` | - | - | | `oauth_secret` (#2) | `string` | - | plaintext — server-side only, never logged | | `cookies` (#3) | `string` | repeated | - | | `user_id` (#4) | `string` | - | - | | `screen_name` (#5) | `string` | - | - | ### twitter.android.v1.CreatePostRequest | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | | `text` (#2) | `string` | - | - | | `media_ids` (#3) | `string` | repeated | - | ### twitter.android.v1.CreatePostResponse | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | refreshed round-trip state (charter §3) | | `tweet` (#2) | `Tweet`(见消息定义) | - | - | ### twitter.android.v1.DeletePostRequest | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | | `tweet_id` (#2) | `string` | - | - | ### twitter.android.v1.DeletePostResponse | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | ### twitter.android.v1.EngageRequest > EngageRequest is the shared input for like/unlike/retweet/unretweet. For Unretweet, tweet_id is the ORIGINAL (source) tweet id. | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | | `tweet_id` (#2) | `string` | - | - | ### twitter.android.v1.EngageResponse | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | refreshed round-trip state (charter §3) | ### twitter.android.v1.HomeTimelineRequest | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | ### twitter.android.v1.LoginRequest | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `username` (#1) | `string` | - | - | | `password` (#2) | `string` | - | - | | `totp` (#3) | `string` | - | totp is the current 2FA code; empty when the account has no 2FA. | | `version` (#4) | `string` | optional | version selects the client build (default latest); optional. | | `proxy` (#5) | `string` | optional | proxy dials upstream through this URL (http/https/socks5); optional. | | `attest_account_id` (#6) | `string` | optional | attest_account_id binds attestation during the guest phase; optional. | ### twitter.android.v1.LoginResponse | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | ### twitter.android.v1.MeRequest | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | ### twitter.android.v1.ProfileAnalyticsRequest | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | | `rest_id` (#2) | `string` | - | - | | `from_time` (#3) | `string` | - | RFC3339 Z | | `to_time` (#4) | `string` | - | - | ### twitter.android.v1.ProfileModulesRequest | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | | `rest_id` (#2) | `string` | - | - | ### twitter.android.v1.QuoteRequest | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | | `quoted_tweet_id` (#2) | `string` | - | - | | `text` (#3) | `string` | - | - | | `media_ids` (#4) | `string` | repeated | - | ### twitter.android.v1.RawResponse > RawResponse round-trips state + the untouched GraphQL data (raw fallback). | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | | `raw_json` (#2) | `string` | - | - | ### twitter.android.v1.ReplyRequest | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | | `in_reply_to_tweet_id` (#2) | `string` | - | - | | `text` (#3) | `string` | - | - | | `media_ids` (#4) | `string` | repeated | - | ### twitter.android.v1.TimelineResponse | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | refreshed round-trip state (charter §3) | | `raw_json` (#2) | `string` | - | untouched GraphQL timeline payload | ### twitter.common.v1.Tweet > Tweet is a posted/read tweet. Structured key fields + raw_json fallback (charter interview #8: 关键字段 + 保留 raw) — on GraphQL schema drift, parse raw_json instead of changing this message. CreatePost fills only tweet_id; reads (B3) fill the rest. | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `tweet_id` (#1) | `string` | - | rest_id | | `text` (#2) | `string` | - | - | | `user_id` (#3) | `string` | - | author rest_id | | `screen_name` (#4) | `string` | - | - | | `created_at` (#5) | `int64` | - | unix seconds; 0 if unknown | | `favorite_count` (#6) | `int64` | - | - | | `retweet_count` (#7) | `int64` | - | - | | `reply_count` (#8) | `int64` | - | - | | `quote_count` (#9) | `int64` | - | - | | `view_count` (#10) | `int64` | - | - | | `raw_json` (#15) | `string` | - | raw_json is the untouched GraphQL tweet_results payload (drift safety). | ### twitter.android.v1.UploadMediaRequest | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | | `data` (#2) | `bytes` | - | raw image bytes | | `mime_type` (#3) | `string` | - | default image/jpeg | | `media_category` (#4) | `string` | - | default tweet_image | ### twitter.android.v1.UploadMediaResponse | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | refreshed round-trip state (charter §3) | | `media_id` (#2) | `string` | - | - | ### twitter.common.v1.User > User is a read profile (B3). Structured key fields + raw_json fallback. | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `user_id` (#1) | `string` | - | rest_id | | `screen_name` (#2) | `string` | - | - | | `name` (#3) | `string` | - | - | | `description` (#4) | `string` | - | - | | `followers_count` (#5) | `int64` | - | - | | `following_count` (#6) | `int64` | - | - | | `tweet_count` (#7) | `int64` | - | - | | `verified` (#8) | `bool` | - | - | | `raw_json` (#15) | `string` | - | - | ### twitter.android.v1.UserByRestIDRequest | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | | `rest_id` (#2) | `string` | - | - | ### twitter.android.v1.UserResponse | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | refreshed round-trip state (charter §3) | | `user` (#2) | `User`(见消息定义) | - | - | ### twitter.android.v1.UserTweetsRequest | 字段 | 类型 | 约束 | 说明 | | --- | --- | --- | --- | | `state` (#1) | `AndroidAccountState`(见消息定义) | - | - | | `rest_id` (#2) | `string` | - | - | ## 原始 Proto 以下是契约的唯一事实来源,可直接用 protoc 生成任意语言的 stub。 ### android.proto ```protobuf syntax = "proto3"; // Android (TwitterAndroid) platform service. Platform = service (charter §6, // scheme A): AndroidApi / IosApi / WebApi are separate services; platform- // specific state (OAuth 1.0a here) never mixes cross-platform, so no oneof/union. package twitter.android.v1; option go_package = "github.com/robin528919/go-twitter-api/gen/go/androidpb;androidpb"; // AndroidApi is the Android client-protocol surface. One endpoint = one RPC; // Login is the sanctioned cross-endpoint exception (a login state machine that // must atomically mint + verify session credentials). service AndroidApi { // Login runs the full Android cold-start login and returns the complete // AndroidAccountState. The caller MUST persist the returned device — later // RPCs must not regenerate it. rpc Login(LoginRequest) returns (LoginResponse); } message LoginRequest { string username = 1; string password = 2; // totp is the current 2FA code; empty when the account has no 2FA. string totp = 3; // version selects the client build (default latest); optional. optional string version = 4; // proxy dials upstream through this URL (http/https/socks5); optional. optional string proxy = 5; // attest_account_id binds attestation during the guest phase; optional. optional string attest_account_id = 6; } message LoginResponse { AndroidAccountState state = 1; } // AndroidAccountState is the full round-trip identity for the android namespace. // Mirrors identity.AndroidAccountState (OAuth 1.0a session). message AndroidAccountState { Account account = 1; AndroidDevice device = 2; string app_version = 3; string proxy = 4; AndroidSession session = 5; } message Account { string username = 1; string password = 2; // plaintext — server-side only, never logged string totp_seed = 3; // plaintext 2FA secret; optional } message AndroidDevice { string client_uuid = 1; string device_id = 2; string ad_id = 3; string model = 4; string manufacturer = 5; string brand = 6; string board = 7; string os_version = 8; string build_year = 9; string language = 10; string timezone = 11; string sec_patch = 12; string limit_ad_tracking = 13; string attest_token = 14; } message AndroidSession { string oauth_token = 1; string oauth_secret = 2; // plaintext — server-side only, never logged repeated string cookies = 3; string user_id = 4; string screen_name = 5; } ``` ### common.proto ```protobuf syntax = "proto3"; // Common cross-platform business inputs / pagination shared by all platform // services (charter §6: pure business inputs live here to avoid tri-writing; // platform-specific state does NOT — that stays in each platform's proto). package twitter.common.v1; option go_package = "github.com/robin528919/go-twitter-api/gen/go/commonpb;commonpb"; // PageInfo is the forward cursor for streaming/paginated reads (timeline, etc.). // Present now as the shared pagination contract; Login does not use it. message PageInfo { // cursor to resume from; empty starts at the top. string cursor = 1; // max items to return; 0 = server default. int32 count = 2; } // Tweet is a posted/read tweet. Structured key fields + raw_json fallback // (charter interview #8: 关键字段 + 保留 raw) — on GraphQL schema drift, parse // raw_json instead of changing this message. CreatePost fills only tweet_id; // reads (B3) fill the rest. message Tweet { string tweet_id = 1; // rest_id string text = 2; string user_id = 3; // author rest_id string screen_name = 4; int64 created_at = 5; // unix seconds; 0 if unknown int64 favorite_count = 6; int64 retweet_count = 7; int64 reply_count = 8; int64 quote_count = 9; int64 view_count = 10; // raw_json is the untouched GraphQL tweet_results payload (drift safety). string raw_json = 15; } // User is a read profile (B3). Structured key fields + raw_json fallback. message User { string user_id = 1; // rest_id string screen_name = 2; string name = 3; string description = 4; int64 followers_count = 5; int64 following_count = 6; int64 tweet_count = 7; bool verified = 8; string raw_json = 15; } ``` ### media.proto ```protobuf syntax = "proto3"; // Android media upload (charter interview #9: 独立 UploadMedia RPC → media_id; // CreatePost(text, media_ids) 组合). The segmented INIT→APPEND→FINALIZE flow runs // inside one RPC (single endpoint family = one RPC, charter §2). package twitter.android.v1; option go_package = "github.com/robin528919/go-twitter-api/gen/go/androidpb;androidpb"; import "android.proto"; // MediaApi is the Android media-upload surface (upload.x.com). service MediaApi { // UploadMedia runs the segmented INIT→APPEND→FINALIZE flow and returns a // media_id for CreatePost. Returns the refreshed state (attest re-minted). rpc UploadMedia(UploadMediaRequest) returns (UploadMediaResponse); } message UploadMediaRequest { AndroidAccountState state = 1; bytes data = 2; // raw image bytes string mime_type = 3; // default image/jpeg string media_category = 4; // default tweet_image } message UploadMediaResponse { AndroidAccountState state = 1; // refreshed round-trip state (charter §3) string media_id = 2; } ``` ### posts.proto ```protobuf syntax = "proto3"; // Android posts: create/delete (B1). Engagement (reply/quote/like/retweet) is // added in B2 on this same service. One endpoint = one RPC (charter §2); every // RPC takes and returns the full AndroidAccountState (round-trip, charter §3). package twitter.android.v1; option go_package = "github.com/robin528919/go-twitter-api/gen/go/androidpb;androidpb"; import "android.proto"; import "common.proto"; // PostsApi is the Android post-authoring + engagement surface (api.x.com GraphQL). service PostsApi { // CreatePost publishes text (+ optional media_ids from UploadMedia). rpc CreatePost(CreatePostRequest) returns (CreatePostResponse); // DeletePost deletes a tweet by id. rpc DeletePost(DeletePostRequest) returns (DeletePostResponse); // Reply posts text as a reply to a tweet (returns the new tweet). rpc Reply(ReplyRequest) returns (CreatePostResponse); // Quote posts text quoting a tweet (returns the new tweet). rpc Quote(QuoteRequest) returns (CreatePostResponse); // Like favorites a tweet. rpc Like(EngageRequest) returns (EngageResponse); // Unlike removes a favorite. rpc Unlike(EngageRequest) returns (EngageResponse); // Retweet reposts a tweet. rpc Retweet(EngageRequest) returns (EngageResponse); // Unretweet removes a repost (tweet_id = the ORIGINAL/source tweet id). rpc Unretweet(EngageRequest) returns (EngageResponse); } message CreatePostRequest { AndroidAccountState state = 1; string text = 2; repeated string media_ids = 3; } message CreatePostResponse { AndroidAccountState state = 1; // refreshed round-trip state (charter §3) twitter.common.v1.Tweet tweet = 2; } message DeletePostRequest { AndroidAccountState state = 1; string tweet_id = 2; } message DeletePostResponse { AndroidAccountState state = 1; } message ReplyRequest { AndroidAccountState state = 1; string in_reply_to_tweet_id = 2; string text = 3; repeated string media_ids = 4; } message QuoteRequest { AndroidAccountState state = 1; string quoted_tweet_id = 2; string text = 3; repeated string media_ids = 4; } // EngageRequest is the shared input for like/unlike/retweet/unretweet. For // Unretweet, tweet_id is the ORIGINAL (source) tweet id. message EngageRequest { AndroidAccountState state = 1; string tweet_id = 2; } message EngageResponse { AndroidAccountState state = 1; // refreshed round-trip state (charter §3) } ``` ### timeline.proto ```protobuf syntax = "proto3"; // Android timeline reads (B3). Timelines are large/volatile GraphQL trees, so // they round-trip as raw_json (charter interview #8: raw 兜底); callers parse // what they need. One endpoint = one RPC (charter §2). package twitter.android.v1; option go_package = "github.com/robin528919/go-twitter-api/gen/go/androidpb;androidpb"; import "android.proto"; // TimelineApi is the Android timeline-read surface. service TimelineApi { // HomeTimeline returns the launch home feed (raw). rpc HomeTimeline(HomeTimelineRequest) returns (TimelineResponse); // UserTweets returns a user's own posts timeline (raw). rpc UserTweets(UserTweetsRequest) returns (TimelineResponse); } message HomeTimelineRequest { AndroidAccountState state = 1; } message UserTweetsRequest { AndroidAccountState state = 1; string rest_id = 2; } message TimelineResponse { AndroidAccountState state = 1; // refreshed round-trip state (charter §3) string raw_json = 2; // untouched GraphQL timeline payload } ``` ### users.proto ```protobuf syntax = "proto3"; // Android user/profile reads (B3). Me/UserByRestID return a structured User // (key fields + raw_json); profile modules/analytics return raw_json (charter // interview #8: 关键字段 + 保留 raw). One endpoint = one RPC (charter §2). package twitter.android.v1; option go_package = "github.com/robin528919/go-twitter-api/gen/go/androidpb;androidpb"; import "android.proto"; import "common.proto"; // UsersApi is the Android profile-read surface. service UsersApi { // Me returns the logged-in user's own profile. rpc Me(MeRequest) returns (UserResponse); // UserByRestID returns a profile by numeric rest_id. rpc UserByRestID(UserByRestIDRequest) returns (UserResponse); // ProfileModules returns the raw profile-page modules. rpc ProfileModules(ProfileModulesRequest) returns (RawResponse); // ProfileAnalytics returns raw impressions over [from_time,to_time] (RFC3339 Z). rpc ProfileAnalytics(ProfileAnalyticsRequest) returns (RawResponse); } message MeRequest { AndroidAccountState state = 1; } message UserByRestIDRequest { AndroidAccountState state = 1; string rest_id = 2; } message UserResponse { AndroidAccountState state = 1; // refreshed round-trip state (charter §3) twitter.common.v1.User user = 2; } message ProfileModulesRequest { AndroidAccountState state = 1; string rest_id = 2; } message ProfileAnalyticsRequest { AndroidAccountState state = 1; string rest_id = 2; string from_time = 3; // RFC3339 Z string to_time = 4; } // RawResponse round-trips state + the untouched GraphQL data (raw fallback). message RawResponse { AndroidAccountState state = 1; string raw_json = 2; } ``` (版本 v0.2.3 · SDK 0.2.3 · 镜像 0.2.3 · 提交 71157c1dd2d8)