twitter-api-v2

Twitter API v2.0 的轻量级跨平台封装库

1. 指南 ?

本库提供了在 DartFlutter 应用中最简单的方式来使用 Twitter API v2.0

请给这个项目一些 ❤️ 并给它点星支持。

我们还提供 twitter_oauth2_pkce,用于在使用 Twitter API 时方便地进行 OAuth 2.0 PKCE 认证

1.1. 特点 ✨

Twitter API v2.0 的 **封装库**。

✅ **轻松集成** 到 Dart & Flutter 应用。

✅ 提供具有 **保证安全类型** 的响应对象。

✅ 支持 **所有 API 端点**。

✅ 支持 **所有请求参数和响应字段**。

✅ 支持 **高性能流式** 端点。

✅ 支持 **expansions** 和 **fields** 功能。

✅ **文档齐全** 且 **测试充分**。

✅ 支持强大的 **自动重试**。

1.2. 入门 ⚡

1.2.1. 安装库

使用 Dart

 dart pub add twitter_api_v2

或使用 Flutter

 flutter pub add twitter_api_v2

1.2.2. 导入

import 'package:twitter_api_v2/twitter_api_v2';

1.2.3. 实现

import 'dart:async';

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  //! You need to get keys and tokens at https://developer.twitter.com
  final twitter = v2.TwitterApi(
    //! Authentication with OAuth2.0 is the default.
    //!
    //! Note that to use endpoints that require certain user permissions,
    //! such as Tweets and Likes, you need a token issued by OAuth2.0 PKCE.
    //!
    //! The easiest way to achieve authentication with OAuth 2.0 PKCE is
    //! to use [twitter_oauth2_pkce](https://pub.dev/packages/twitter_oauth2_pkce)!
    bearerToken: 'YOUR_TOKEN_HERE',

    //! Or perhaps you would prefer to use the good old OAuth1.0a method
    //! over the OAuth2.0 PKCE method. Then you can use the following code
    //! to set the OAuth1.0a tokens.
    //!
    //! However, note that some endpoints cannot be used for OAuth 1.0a method
    //! authentication.
    oauthTokens: v2.OAuthTokens(
      consumerKey: 'YOUR_CONSUMER_KEY_HERE',
      consumerSecret: 'YOUR_CONSUMER_SECRET_HERE',
      accessToken: 'YOUR_ACCESS_TOKEN_HERE',
      accessTokenSecret: 'YOUR_ACCESS_TOKEN_SECRET_HERE',
    ),

    //! Automatic retry is available when a TimeoutException occurs when
    //! communicating with the API.
    retryConfig: v2.RetryConfig.interval(
      maxAttempts: 5,
      intervalInSeconds: 3,
    ),

    //! The default timeout is 10 seconds.
    timeout: Duration(seconds: 20),
  );

  try {
    // Get the authenticated user's profile.
    final me = await twitter.usersService.lookupMe();
    // Get the tweets associated with the search query.
    final tweets = await twitter.tweetsService.searchRecent(
      query: '#ElonMusk',
      maxResults: 20,
      // You can expand the search result.
      expansions: [
        v2.TweetExpansion.authorId,
        v2.TweetExpansion.inReplyToUserId,
      ],
      tweetFields: [
        v2.TweetField.conversationId,
        v2.TweetField.publicMetrics,
      ],
      userFields: [
        v2.UserField.location,
        v2.UserField.verified,
        v2.UserField.entities,
        v2.UserField.publicMetrics,
      ],
    );

    await twitter.tweetsService.createLike(
      userId: me.data.id,
      tweetId: tweets.data.first.id,
    );

    // High-performance Volume Stream endpoint is available.
    final volumeStream = await twitter.tweetsService.connectVolumeStream();
    await for (final response in volumeStream.handleError(print)) {
      print(response);
    }

    // Also high-performance Filtered Stream endpoint is available.
    await twitter.tweetsService.createFilteringRules(
      rules: [
        v2.FilteringRuleParam(value: '#ElonMusk'),
        v2.FilteringRuleParam(value: '#Tesla'),
        v2.FilteringRuleParam(value: '#SpaceX'),
      ],
    );

    final filteredStream = await twitter.tweetsService.connectFilteredStream();
    await for (final response in filteredStream.handleError(print)) {
      print(response.data);
      print(response.matchingRules);
    }
  } on TimeoutException catch (e) {
    print(e);
  } on v2.UnauthorizedException catch (e) {
    print(e);
  } on v2.RateLimitExceededException catch (e) {
    print(e);
  } on v2.TwitterException catch (e) {
    print(e.response.headers);
    print(e.body);
    print(e);
  }
}

1.3. 支持的端点 ?

1.3.1. 推文服务

1.3.1.1. 推文

端点 方法名
POST /2/tweets createTweet
DELETE /2/tweets/:id destroyTweet

1.3.1.2. 点赞

端点 方法名
POST /2/users/:id/likes createLike
DELETE /2/users/:id/likes/:tweet_id destroyLike
GET /2/tweets/:id/liking_users lookupLikingUsers
GET /2/users/:id/liked_tweets lookupLikedTweets

1.3.1.3. 转推

端点 方法名
POST /2/users/:id/retweets createRetweet
DELETE /2/users/:id/retweets/:source_tweet_id destroyRetweet
GET /2/tweets/:id/retweeted_by lookupRetweetedUsers

1.3.1.4. 引用推文

端点 方法名
GET /2/tweets/:id/quote_tweets lookupQuoteTweets

1.3.1.5. 搜索推文

端点 方法名
GET /2/tweets/search/all searchAll
GET /2/tweets/search/recent searchRecent

1.3.1.6. 查询推文

端点 方法名
GET /2/tweets lookupByIds
GET /2/tweets/:id lookupById

1.3.1.7. 推文计数

端点 方法名
GET /2/tweets/counts/all countAll
GET /2/tweets/counts/recent countRecent

1.3.1.8. 书签

端点 方法名
POST /2/users/:id/bookmarks createBookmark
DELETE /2/users/:id/bookmarks/:tweet_id destroyBookmark
GET /2/users/:id/bookmarks lookupBookmarks

1.3.1.9. 时间线

端点 方法名
GET /2/users/:id/mentions lookupMentions
GET /2/users/:id/tweets lookupTweets
GET /2/users/:id/timelines/reverse_chronological lookupHomeTimeline

1.3.1.10. 隐藏回复

端点 方法名
PUT /2/tweets/:id/hidden createHiddenReply
PUT /2/tweets/:id/hidden destroyHiddenReply

1.3.1.11. 容量流

端点 方法名
GET /2/tweets/sample/stream connectVolumeStream

1.3.1.12. 过滤流

端点 方法名
POST /2/tweets/search/stream/rules createFilteringRules
GET /2/tweets/search/stream/rules lookupFilteringRules
GET /2/tweets/search/stream connectFilteredStream

1.3.2. 用户服务

1.3.2.1. 关注

端点 方法名
POST /2/users/:id/following createFollow
DELETE /2/users/:source_user_id/following/:target_user_id destroyFollow
GET /2/users/:id/followers lookupFollowers
GET /2/users/:id/following lookupFollowings

1.3.2.2. 查询用户

端点 方法名
GET /2/users lookupByIds
GET /2/users/:id lookupById
GET /2/users/by lookupByNames
GET /2/users/by/username/:username lookupByName
GET /2/users/me lookupMe

1.3.2.3. 用户屏蔽

端点 方法名
POST /2/users/:id/muting createMute
DELETE /2/users/:source_user_id/muting/:target_user_id destroyMute
GET /2/users/:id/muting lookupMutingUsers

1.3.2.4. 拉黑

端点 方法名
POST /2/users/:id/blocking createBlock
DELETE /2/users/:source_user_id/blocking/:target_user_id destroyBlock
GET /2/users/:id/blocking lookupBlockingUsers

1.3.3. Spaces 服务

1.3.3.1. 搜索 Spaces

端点 方法名
GET /2/spaces/search search

1.3.3.2. 查询 Spaces

端点 方法名
GET /2/spaces lookupByIds
GET /2/spaces/:id lookupById
GET /2/spaces/:id/buyers lookupBuyers
GET /2/spaces/:id/tweets lookupTweets
GET /2/spaces/by/creator_ids lookupByCreatorIds

1.3.4. Lists 服务

1.3.4.1. 查询 Lists

端点 方法名
GET /2/lists/:id lookupById
GET /2/users/:id/owned_lists lookupOwnedBy

1.3.4.2. Pinning

端点 方法名
POST /2/users/:id/pinned_lists createPinnedList
DELETE /2/users/:id/pinned_lists/:list_id destroyPinnedList
GET /2/users/:id/pinned_lists lookupPinnedLists

1.3.4.3. 推文查询

端点 方法名
GET /2/lists/:id/tweets lookupTweets

1.3.4.4. List 管理

端点 方法名
POST /2/lists createPublicList
POST /2/lists createPrivateList
DELETE /2/lists/:id destroyList
PUT /2/lists/:id updateListAsPublic
PUT /2/lists/:id updateListAsPrivate

1.3.4.5. Follows

端点 方法名
POST /2/users/:id/followed_lists createFollow
DELETE /2/users/:id/followed_lists/:list_id destroyFollow
GET /2/lists/:id/followers lookupFollowers
GET /2/users/:id/followed_lists lookupFollowedLists

1.3.4.6. Members

端点 方法名
POST /2/lists/:id/members createMember
DELETE /2/lists/:id/members/:user_id destroyMember
GET /2/lists/:id/members lookupMembers
GET /2/users/:id/list_memberships lookupMemberships

1.3.5. Compliance 服务

1.3.5.1. Batch Compliance

端点 方法名
POST /2/compliance/jobs createJob
GET /2/compliance/jobs lookupJobs
GET /2/compliance/jobs/:id lookupJob

1.4. 技巧 ?

1.4.1. 方法名

twitter_api_v2 使用以下标准前缀,具体取决于端点特性。因此,找到与您想用的端点对应的方法非常容易!

前缀 描述
lookup 此前缀附加到引用推文、用户等的端点。
search 此前缀附加到执行广泛搜索的端点。
connect 此前缀附加到高性能流式端点。
count 此前缀附加到计算特定项的端点。
create 此前缀附加到执行创建状态的端点,例如 TweetFollow
destroy 此前缀附加到执行销毁状态的端点,例如 TweetFollow
update 此前缀附加到执行更新状态的端点。

1.4.2. 生成仅应用 Bearer Token

twitter_api_v2 提供生成/查找您的仅应用 Bearer Token 的实用程序。

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final bearerToken = await v2.OAuthUtils.generateAppOnlyBearerToken(
    consumerKey: 'YOUR_CONSUMER_KEY',
    consumerSecret: 'YOUR_CONSUMER_SECRET',
  );

  print(bearerToken);
}

1.4.3. 请求中的 Null 参数

在此库中,请求时不需要的参数,即可选参数,被定义为可为空的。
但是,开发人员在使用此库发送请求时,无需意识到 Null 参数。

这意味着值为 Null 的参数在发送请求之前会被安全地删除并忽略。

例如,在以下请求中,指定为 Null 的参数将被忽略。

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(bearerToken: 'YOUR_TOKEN_HERE');

  await twitter.tweetsService.createTweet(
    text: 'Hello, World!',
    // These parameters are ignored at request because they are null.
    mediaIds: null,
    expansions: null,
  );
}

1.4.4. 使用 expansions 展开对象字段

例如,可能出现数据仅包含 ID 的情况,而您想检索与该 ID 关联的数据对象。在这种情况下,称为 expansionsTwitter API v2.0 规范非常有用,并且本库支持该规范。

基本上,它可以在执行 GET 通信的端点中使用,例如 lookupsearch 处理。某些字段也可能包含在 TwitterResponseincludes 属性中。

您可以如下使用 expansions

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(bearerToken: 'YOUR_TOKEN_HERE');

  try {
    final tweets = await twitter.tweetsService.searchRecent(
      query: '#ElonMusk',
      // Specify fields you need!
      expansions: [
        v2.TweetExpansion.authorId,
        v2.TweetExpansion.inReplyToUserId,
      ],
    );

    print(tweets);
  } on v2.TwitterException catch (e) {
    print(e);
  }
}

您可以从 官方文档 查看有关 expansions 的更多详细信息。

1.4.5. 使用 fields 展开对象字段

Twitter API v2.0 支持一个非常有趣的规范,允许用户根据情况控制每个端点响应对象中包含的数据量。它称为 fields,并且本库支持此规范。

基本上,它可以在执行 GET 通信的端点中使用,例如 lookupsearch 处理。某些字段也可能包含在 TwitterResponseincludes 字段中。

您可以如下使用 fields

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(bearerToken: 'YOUR_TOKEN_HERE');

  try {
    final tweets = await twitter.tweetsService.searchRecent(
      query: '#ElonMusk',
      maxResults: 20,
      expansions: v2.TweetExpansion.values,
      tweetFields: [
        v2.TweetField.conversationId,
        v2.TweetField.publicMetrics,
      ],
      userFields: [
        v2.UserField.location,
        v2.UserField.publicMetrics,
      ],
    );

    print(tweets);
  } on v2.TwitterException catch (e) {
    print(e);
  }
}

笔记

某些字段必须与 expansions 结合使用。

您可以从 官方文档 查看有关 fields 的更多详细信息。

1.4.6. OAuth 2.0 Authorization Code Flow with PKCE

Twitter API v2.0 支持使用 OAuth 2.0 PKCE 的认证方法,它允许使用 Twitter API v2.0 的应用程序用户请求授权以获得最小必需的 scope 操作。

由于 OAuth2.0 PKCE 认证需要通过浏览器,twitter_api_v2 为与 CLI 应用程序的兼容性不提供此规范。相反,我们提供 twitter_oauth2_pkce,一个适用于 Flutter 应用的库。

twitter_oauth2_pkcetwitter_api_v2 100% 兼容,可以一起使用。您可以从以下链接查看更多详细信息。

此外,请参考以下结合了 twitter_api_v2twitter_oauth2_pkce 的简单示例 Flutter 应用程序。

1.4.7. 更改超时时长

该库为所有 API 通信指定了默认 10 秒 的超时时间。

但是,有时您可能希望指定任意超时时长。如果存在这种需求,可以按如下方式指定任意超时时长。

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() {
 final twitter = v2.TwitterApi(
    bearerToken: 'YOUR_TOKEN_HERE',

    //! The default timeout is 10 seconds.
    timeout: Duration(seconds: 5),
  );
}

1.4.8. 超时时重试

由于该库与外部系统通信的性质,由于不可避免的通信故障或请求发送到的服务器的临时崩溃,可能会发生超时。

当发生此类超时时,一个有效的对策通常是在一定间隔后再次发送请求。而 twitter_api_v2 提供了一个 **自动重试** 功能来解决这个问题。

twitter_api_v2 提供了两种自动重试方法。

  1. 按固定间隔重试
  2. 使用指数退避算法重试

1.4.8.1. 按固定间隔重试

按固定间隔重试很容易想象。例如,如果发生超时并且假设请求重试 3 次,等待 5 秒然后再次发送请求,则可以定义如下。

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(
    bearerToken: 'YOUR_TOKEN_HERE',

    //! Add these lines.
    retryConfig: v2.RetryConfig.interval(
      maxAttempts: 3,
      intervalInSeconds: 5,
    ),
  );
}

1.4.8.2. 使用指数退避算法重试

尽管如上例所示,通过按固定间隔执行重试可以有效,但在请求发送到的服务器出现故障时,按固定间隔发送大量请求是应该避免的。即使网络或服务器已经宕机,重试过程也会通过增加负载来使情况更加糟糕。

这些问题的解决方案是为每次重试指数地增加间隔。此外,添加随机数可以防止服务器由于同时重试处理而导致的负载增加。

这是一种称为 Exponential Backoff 的算法,twitter_api_v2 支持允许轻松使用此算法的规范。可以通过如下定义 RetryConfig 来将指数退避算法应用于重试。

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(
    bearerToken: 'YOUR_TOKEN_HERE',

    //! Add these lines.
    retryConfig: v2.RetryConfig.exponentialBackOff(
      maxAttempts: 3,
    ),
  );
}

在上述实现中,间隔随着重试次数的增加而增加,这可以用公式 2 ^ retryCount 来表示。

1.4.8.3. 重试时执行操作

在重试时输出日志,并通过弹出窗口通知用户已执行重试会很有用。因此,twitter_api_v2 提供了可以在重试执行时执行任意处理的回调。

可以按如下方式实现。

import 'package:twitter_api_v2/twitter_api_v2.dart' as v2;

Future<void> main() async {
  final twitter = v2.TwitterApi(
    bearerToken: 'YOUR_TOKEN_HERE',
    retryConfig: v2.RetryConfig.interval(
      maxAttempts: 3,
      intervalInSeconds: 5,

      //! Add this line.
      onExecute: (context) => print('Retrying... ${context.retryCount} times.'),
    ),
  );
}

传递给回调的 RetryContext 包含有关重试的信息。

1.4.9. 抛出异常

twitter_api_v2 提供了一个方便的异常对象,用于轻松处理来自 Twitter API v2.0 的异常响应和错误。

异常 描述
TwitterException 最基本的异常对象。例如,它可以用于查找已被删除的推文等。
UnauthorizedException 当使用指定的访问令牌进行身份验证失败时抛出。
RateLimitExceededException 当请求速率限制被超出时抛出。

GitHub

https://github.com/twitter-dart/twitter-api-v2