jublonet/codebird-php

轻松访问Twitter REST API、Direct Messages API、Account Activity API、TON(对象树)API和Twitter Ads API——所有这些功能都可通过一个PHP库实现。

4.0.0-beta.1 2018-08-16 00:07 UTC

README

轻松访问Twitter REST API、Direct Messages API、Account Activity API、TON(对象树)API和Twitter Ads API——所有这些功能都可通过一个PHP库实现。

版权(C)2010-2018 Jublo Limited support@jublo.net

本程序是自由软件:您可以自由重新分发和/或修改它,前提是必须遵守由自由软件基金会发布的GNU通用公共许可证的条款,许可证版本为3,或者(根据您的选择)任何更高版本的许可证。

本程序的分发是希望它有用,但没有提供任何保证;甚至没有关于其适销性或适用于特定目的的隐含保证。有关详细信息,请参阅GNU通用公共许可证。

您应该已经随本程序收到GNU通用公共许可证的一份副本。如果没有收到,请参阅https://gnu.ac.cn/licenses/

Codacy Badge Coverage Status Travis Status

要求

  • PHP 7.1.0或更高版本
  • OpenSSL扩展

摘要

使用Codebird从PHP代码连接到Twitter REST API、Streaming API、Collections API、TON(对象树)API和Twitter Ads API——只需使用一个库。Codebird支持完整的3方OAuth以及仅应用OAuth。

认证

要代表特定Twitter用户(遵循OAuth 1.0a)认证API请求,请查看以下步骤

require_once ('codebird.php');
\Codebird\Codebird::setConsumerKey('YOURKEY', 'YOURSECRET'); // static, see README

$cb = \Codebird\Codebird::getInstance();

如果您已经有了OAuth令牌和密钥,可以设置它们

$cb->setToken('YOURTOKEN', 'YOURTOKENSECRET');

或者按照以下方式认证

session_start();

if (! isset($_SESSION['oauth_token'])) {
  // get the request token
  $reply = $cb->oauth_requestToken([
    'oauth_callback' => 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']
  ]);

  // store the token
  $cb->setToken($reply->oauth_token, $reply->oauth_token_secret);
  $_SESSION['oauth_token'] = $reply->oauth_token;
  $_SESSION['oauth_token_secret'] = $reply->oauth_token_secret;
  $_SESSION['oauth_verify'] = true;

  // redirect to auth website
  $auth_url = $cb->oauth_authorize();
  header('Location: ' . $auth_url);
  die();

} elseif (isset($_GET['oauth_verifier']) && isset($_SESSION['oauth_verify'])) {
  // verify the token
  $cb->setToken($_SESSION['oauth_token'], $_SESSION['oauth_token_secret']);
  unset($_SESSION['oauth_verify']);

  // get the access token
  $reply = $cb->oauth_accessToken([
    'oauth_verifier' => $_GET['oauth_verifier']
  ]);

  // store the token (which is different from the request token!)
  $_SESSION['oauth_token'] = $reply->oauth_token;
  $_SESSION['oauth_token_secret'] = $reply->oauth_token_secret;

  // send to same URL, without oauth GET parameters
  header('Location: ' . basename(__FILE__));
  die();
}

// assign access token on each page load
$cb->setToken($_SESSION['oauth_token'], $_SESSION['oauth_token_secret']);

注销

如果您想注销当前用户(在不创建新Codebird对象的情况下登录不同用户),只需调用logout()方法。

$cb->logout();

Codebird还支持直接调用oauth/invalidate_token方法

$reply = $cb->oauth_invalidateToken([
    'access_token'        => '1234',
    'access_token_secret' => '5678'
]);

仅应用认证

一些API方法也支持在应用级别进行认证。这对于获取与特定Twitter用户无直接关系但适用于Twitter生态系统的数据(例如search/tweets)很有用。

要获取仅应用的承载令牌,请调用相应的API

$reply = $cb->oauth2_token();
$bearer_token = $reply->access_token;

强烈建议您将获取的承载令牌存储在数据库中。没有必要在每次页面加载时重新获取令牌,因为只有在调用oauth2/invalidate_token方法时它才会失效。

如果您已经有了令牌,告诉Codebird使用它

\Codebird\Codebird::setBearerToken('YOURBEARERTOKEN');

在这种情况下,您不需要设置消费者密钥和密钥。有关使用仅应用认证发送API请求的示例,请参阅“用法示例”部分。

关于您的回调URL

Twitter对可以用于回调URL的URL非常严格。例如,即使是“www”子域的存在也必须与您在https://developer.twitter.com/en/apps中的应用设置中指定的域名匹配。

将API方法映射到Codebird函数调用

从最后一个示例中可以看出,Twitter的API方法映射到Codebird函数调用有一套通用方法。一般规则如下

  1. 对于Twitter API方法中的每个斜杠,在Codebird函数中使用下划线。

示例: statuses/update映射到Codebird::statuses_update()

  1. 在Twitter API方法中的每个下划线处,在Codebird函数中使用驼峰命名法。

示例: statuses/home_timeline 映射到 Codebird::statuses_homeTimeline()

  1. 对于方法中的每个参数模板,在Codebird函数中使用大写字母。同时,别忘了在你的参数列表中包含该参数。

示例

  • statuses/show/:id 映射到 Codebird::statuses_show_ID('id=12345')
  • users/profile_image/:screen_name 映射到 Codebird::users_profileImage_SCREEN_NAME('screen_name=jublonet')

使用示例

当你有访问令牌时,调用API很简单

$cb->setToken($_SESSION['oauth_token'], $_SESSION['oauth_token_secret']); // see above

$reply = (array) $cb->statuses_homeTimeline();
print_r($reply);

发推文就像这样简单

$reply = $cb->statuses_update('status=Whohoo, I just Tweeted!');

⚠️ 确保对包含查询保留字符的任何参数值进行urlencode,例如推文中的 & 符号:

$reply = $cb->statuses_update('status=' . urlencode('Fish & chips'));
// will result in this:
$reply = $cb->statuses_update('status=Fish+%26+chips');

在大多数情况下,将所有参数作为一个数组给出更简单,因为不需要编码

$params = [
  'status' => 'Fish & chips'
];
$reply = $cb->statuses_update($params);
$params = [
  'status' => 'I love London',
  'lat'    => 51.5033,
  'long'   => 0.1197
];
$reply = $cb->statuses_update($params);
$params = [
  'screen_name' => 'jublonet'
];
$reply = $cb->users_show($params);

这是使用上述代码发送的推文结果

仅应用认证的请求

要发送没有用户访问令牌的API请求(仅应用认证),在方法调用中添加第二个参数,如下所示

$reply = $cb->search_tweets('q=Twitter', true);

请注意,并非所有API方法都支持仅应用认证。

HTTP方法(GET、POST、DELETE等)

在调用Twitter API时,永远不必担心使用哪种HTTP方法(动词)。Codebird足够智能,可以自己找出。

响应代码

API给出的HTTP响应代码包含在任何返回值中。您可以在返回对象的httpstatus属性中找到它。

处理速率限制

基本上,Codebird将其留给您来处理Twitter的速率限制。库返回HTTP状态代码,因此您可以检测到速率限制。

建议您检查$reply->httpstatus属性是否为400,并与Twitter API检查您是否目前正在被速率限制。有关更多信息,请参阅速率限制常见问题解答

除非您的返回格式是JSON,否则如果Twitter API以速率限制HTTP头响应,您将在返回数据的$reply->rate属性中收到速率限制详情。

返回格式

API调用的默认返回格式是PHP对象。对于返回多个数据的API方法(如statuses/home_timeline),您应该将回复转换为数组,如下所示

$reply = $cb->statuses_homeTimeline();
$data = (array) $reply;

根据您的选择,您也可能直接获得PHP数组

$cb->setReturnFormat(CODEBIRD_RETURNFORMAT_ARRAY);

Twitter API原生响应为JSON(JS对象表示法)。要获取JSON字符串,设置相应的返回格式

$cb->setReturnFormat(CODEBIRD_RETURNFORMAT_JSON);

上传图片和视频

Twitter将接受以下媒体类型,所有这些类型都受Codebird支持

  • PNG
  • JPEG
  • BMP
  • WebP
  • GIF
  • 动画GIF
  • 视频

推文媒体可以通过两步过程上传

首先,您将每个媒体发送到Twitter。对于图片,操作如下

// these files to upload. You can also just upload 1 image!
$media_files = [
  'bird1.jpg', 'bird2.jpg', 'bird3.jpg'
];
// will hold the uploaded IDs
$media_ids = [];

foreach ($media_files as $file) {
  // upload all media files
  $reply = $cb->media_upload([
    'media' => $file
  ]);
  // and collect their IDs
  $media_ids[] = $reply->media_id_string;
}

上传视频需要您分块发送数据。有关此内容的下一节将介绍。

其次,您将所有图片收集到的媒体id附加到对statuses/update的调用中,如下所示

// convert media ids to string list
$media_ids = implode(',', $media_ids);

// send Tweet with these medias
$reply = $cb->statuses_update([
  'status' => 'These are some of my relatives.',
  'media_ids' => $media_ids
]);
print_r($reply);

这是使用上述代码发送的示例推文

有关上传媒体的更多文档可在Twitter开发者网站上找到。

远程文件

来自httphttps服务器的远程文件也受支持

$reply = $cb->media_upload(array(
  'media' => 'http://www.bing.com/az/hprichbg/rb/BilbaoGuggenheim_EN-US11232447099_1366x768.jpg'
));

⚠️ 包含Unicode字符的URL应进行标准化。一个示例标准化函数可以在http://stackoverflow.com/a/6059053/1816603找到

为了避免远程服务器响应缓慢导致的下载问题,您可以自定义远程下载超时,如下所示:

$cb->setRemoteDownloadTimeout(10000); // milliseconds

视频文件

上传视频到Twitter(≤ 15MB,MP4)需要您分块发送。您至少需要执行3次调用才能获取视频的media_id

  1. 发送一个INIT事件以获取一个media_id草稿。
  2. 使用APPEND事件上传您的块,每个块的大小最多为5MB。
  3. 发送一个FINALIZE事件将草稿转换为可用于推文的media_id
  4. 发布带有视频的推文。

以下是一个视频上传的示例:

$file       = 'demo-video.mp4';
$size_bytes = filesize($file);
$fp         = fopen($file, 'r');

// INIT the upload

$reply = $cb->media_upload([
  'command'     => 'INIT',
  'media_type'  => 'video/mp4',
  'total_bytes' => $size_bytes
]);

$media_id = $reply->media_id_string;

// APPEND data to the upload

$segment_id = 0;

while (! feof($fp)) {
  $chunk = fread($fp, 1048576); // 1MB per chunk for this sample

  $reply = $cb->media_upload([
    'command'       => 'APPEND',
    'media_id'      => $media_id,
    'segment_index' => $segment_id,
    'media'         => $chunk
  ]);

  $segment_id++;
}

fclose($fp);

// FINALIZE the upload

$reply = $cb->media_upload([
  'command'       => 'FINALIZE',
  'media_id'      => $media_id
]);

var_dump($reply);

if ($reply->httpstatus < 200 || $reply->httpstatus > 299) {
  die();
}

// if you have a field `processing_info` in the reply,
// use the STATUS command to check if the video has finished processing.

// Now use the media_id in a Tweet
$reply = $cb->statuses_update([
  'status'    => 'Twitter now accepts video uploads.',
  'media_ids' => $media_id
]);

有关Twitter开发者文档中接受的媒体格式的更多信息,请参阅这里

⚠️当分块上传视频时,即使media_id正确,您也可能遇到错误媒体id验证失败。这是已知的。请在Twitter社区论坛上查看。

Twitter流式API

流式API为开发者提供低延迟访问Twitter全球推文数据流。正确的流式客户端实现将推送表示推文和其他事件已发生的消息,而不涉及轮询REST端点所关联的任何开销。

要消费可用的Twitter流之一,请按照以下两个步骤操作:

  1. 设置一个回调函数,每当有新的流消息到达时都会被调用。

    Codebird也会每秒调用此函数一次,以便您处理任何待办任务,并给您机会在即使没有新消息出现的情况下取消流。

  2. 创建回调后,使用callable告诉Codebird。然后开始消费流。

// First, create a callback function:

function some_callback($message)
{
  // gets called for every new streamed message
  // gets called with $message = NULL once per second

  if ($message !== null) {
    print_r($message);
    flush();
  }

  // return false to continue streaming
  // return true to close the stream

  // close streaming after 1 minute for this simple sample
  // don't rely on globals in your code!
  if (time() - $GLOBALS['time_start'] >= 60) {
    return true;
  }

  return false;
}

// set the streaming callback in Codebird
$cb->setStreamingCallback('some_callback');

// any callable is accepted:
// $cb->setStreamingCallback(['MyClass', 'some_callback']);

// for canceling, see callback function body
// not considered good practice in real world!
$GLOBALS['time_start'] = time();

// Second, start consuming the stream:
$reply = $cb->statuses_filter();

// See the *Mapping API methods to Codebird function calls* section for method names.
// $reply = $cb->statuses_filter('track=Windows');

您应该能够使用setTimeout为流式API设置超时。此外,如果没有任何事件发生,您的回调将接收到空消息,您应该让您的函数返回true;以取消流。

在开发者文档网站上找到有关流式API的更多信息。

Twitter收藏、直接消息和账户活动API

收藏是一种您控制的时序,可以使用API手动精选和/或编程。

请密切关注收藏展示方式的差异——通常,它们将被分解成高效的对象,包含有关用户、推文和时序的信息,分组、简化并去除不必要的重复。

永远不要关心对这些特殊API的OAuth签名特性和POST和PUT调用JSON POST正文。Codebird为您承担这项工作,并会自动发送正确的Content-Type。

在Twitter API文档中了解更多关于收藏API的信息。有关直接消息API账户活动API的更多信息也可在此找到。

以下是一个使用Collections API添加推文的示例:

$reply = $cb->collections_entries_curate([
  'id' => 'custom-672852634622144512',
  'changes' => [
  ['op' => 'add', 'tweet_id' => '672727928262828032']
  ]
]);

var_dump($reply);

TON (Twitter Object Nest) API

TON(Twitter对象树)API 允许实施者将媒体和各种资产上传到Twitter。TON API根据文件大小支持非可恢复和可恢复的上传方法。对于小于64MB的文件,可以使用非可恢复上传。对于大于或等于64MB的文件,必须使用可恢复上传。可恢复上传需要小于64MB的块大小。

要访问TON API,请根据以下代码示例进行上传

单块上传

// single-chunk upload

$reply = $cb->ton_bucket_BUCKET([
  'bucket' => 'ta_partner',
  'Content-Type' => 'image/jpeg',
  'media' => $file
]);

var_dump($reply);

// use the Location header now...
echo $reply->Location;

如您在示例中看到的那样,Codebird会将特殊的TON API头重写为回复,因此您可以轻松访问它们。这也适用于分块上传的X-TON-Min-Chunk-SizeX-Ton-Max-Chunk-Size

多块上传

// multi-chunk upload
$file       = 'demo-video.mp4';
$size_bytes = filesize($file);
$fp         = fopen($file, 'r');

// INIT the upload

$reply = $cb->__call(
  'ton/bucket/BUCKET?resumable=true',
  [[ // note the double square braces when using __call
    'bucket' => 'ta_partner',
    'Content-Type' => 'video/mp4',
    'X-Ton-Content-Type' => 'video/mp4',
    'X-Ton-Content-Length' => $size_bytes
  ]]
);

$target = $reply->Location;
// something like: '/1.1/ton/bucket/ta_partner/SzFxGfAg_Zj.mp4?resumable=true&resumeId=28401873'
$match = [];

// match the location parts
preg_match('/ton\/bucket\/.+\/(.+)\?resumable=true&resumeId=(\d+)/', $target, $match);
list ($target, $file, $resumeId) = $match;

// APPEND data to the upload

$segment_id = 0;

while (! feof($fp)) {
  $chunk = fread($fp, 1048576); // 1MB per chunk for this sample

  // special way to call Codebird for the upload chunks
  $reply = $cb->__call(
    'ton/bucket/BUCKET/FILE?resumable=true&resumeId=RESUMEID',
    [[ // note the double square braces when using __call
      'bucket' => 'ta_partner',
      'file' => $file, // you get real filename from INIT, see above
      'Content-Type' => 'image/jpeg',
      'Content-Range' => 'bytes '
        . ($segment_id * 1048576) . '-' . strlen($chunk) . '/' . $size_bytes,
      'resumeId' => $resumeId,
      'media' => $chunk
    ]]
  );

  $segment_id++;
}

fclose($fp);

Twitter广告API

Twitter广告API 允许合作伙伴将其广告解决方案与其自己的Twitter广告平台集成。选定的合作伙伴有权创建自定义工具来管理和执行Twitter广告活动。

当访问广告API或广告沙盒API时,请通过在调用前加上ads_来访问。请注意,通常在URL参数中有替换,尤其是:account_id

提示:要访问广告沙盒API,使用如以下示例所示的ads_sandbox_前缀。

以下是一个调用Twitter广告API的示例

$reply = $cb->ads_accounts_ACCOUNT_ID_cards_appDownload([
  'account_id' => '123456789',
  'name' => 'Test',
  'app_country_code' => 'DE'
]);

多方法API调用

在Twitter广告API中,可以通过HTTP GETPOSTPUT和/或DELETE访问多个方法。虽然Codebird会尽力猜测您想要使用的HTTP动词,但最好还是自己提供提示,如下所示

$reply = $cb->ads_sandbox_accounts_ACCOUNT_ID_cards_imageConversation_CARD_ID([
  'httpmethod' => 'DELETE',
  'account_id' => '123456789',
  'card_id' => '2468013579'
]);

Codebird会自动从参数列表中删除httpmethod参数,并设置相应的HTTP动词。

我该如何……?

……使用多个Codebird实例?

默认情况下,Codebird与单个实例一起工作。这种编程范例称为单例

获取主Codebird对象的方法如下

$cb = \Codebird\Codebird::getInstance();

如果您需要同时向Twitter API发送多个用户的请求,Codebird也支持这一点。您不需要像上面那样获取实例,而是创建一个新对象

$cb1 = new \Codebird\Codebird;
$cb2 = new \Codebird\Codebird;

请注意,您的OAuth消费者密钥和密钥在多个Codebird实例之间是共享的,而OAuth请求和访问令牌及其密钥是共享的。

……访问用户的个人资料图片?

首先使用以下方式检索用户对象

$reply = $cb->users_show("screen_name=$username");

其中$username是要检索个人资料图片的账户的用户名。

然后从先前检索到的用户对象的profile_image_urlprofile_image_url_https索引获取值。

例如

$reply['profile_image_url']将返回不带https的个人资料图片url。

……获取用户ID、屏幕名称和有关当前用户的更多详细信息?

当用户从认证屏幕返回时,您需要使用OAuth验证器将获得的请求令牌交换为访问令牌。如“使用示例”部分所述,您使用对oauth/access_token的调用来完成此操作。

此方法调用对API的回复会告诉您有关刚刚登录的用户的信息。这些信息包含用户ID屏幕名称

查看以下返回数据

stdClass Object
(
  [oauth_token] => 14648265-rPn8EJwfB**********************
  [oauth_token_secret] => agvf3L3**************************
  [user_id] => 14648265
  [screen_name] => jublonet
  [httpstatus] => 200
)

如果您需要获取更多详细信息,例如用户的最新推文,您应该获取完整的用户实体。获取当前认证用户的用户实体的最简单方法是用account/verify_credentials API方法。在Codebird中,它的工作方式如下

$reply = $cb->account_verifyCredentials();
print_r($reply);

我建议在获取用户实体后将其缓存,因为account/verify_credentials方法每15分钟限制为15次调用。

……如何遍历带游标的搜索结果?

Twitter REST API使用一种称为“游标”的技术来分页大型结果集。游标将结果分为每页不超过5000个结果的页面,并提供了在这些页面之间前后移动的方法。

以下是使用Codebird遍历带游标的结果的方法。

  1. 获取带游标方法的第一个结果集
$result1 = $cb->followers_list();
  1. 要向前导航,获取next_cursor_str
$nextCursor = $result1->next_cursor_str;
  1. 如果$nextCursor不为0,使用此游标请求下一个结果页面
  if ($nextCursor > 0) {
    $result2 = $cb->followers_list('cursor=' . $nextCursor);
  }

要向后导航而不是向前,使用字段$resultX->previous_cursor_str而不是next_cursor_str

可能有必要在循环中使用游标。但是请注意,不要在速率限制时间段内向followers/list发送超出允许数量的请求,否则您将触发速率限制。

……使用Codebird的xAuth?

Codebird像Twitter使用的其他所有身份验证一样支持xAuth。请记住,您的应用程序需要白名单才能使用xAuth。

以下是一个示例

$reply = $cb->oauth_accessToken([
  'x_auth_username' => 'username',
  'x_auth_password' => '4h3_p4$$w0rd',
  'x_auth_mode' => 'client_auth'
]);

你是否收到奇怪的错误信息?如果用户已注册登录验证,服务器将返回一个包含自定义体的HTTP 401错误。如果您正在使用send_error_codes参数,您将在响应体中收到以下错误信息

<?xml version="1.0" encoding="UTF-8"?>
<errors>
<error code="231">User must verify login</error>
</errors>

否则,响应体将包含纯文本响应

User must verify login

当出现此错误时,建议用户在twitter.com上生成临时密码,并使用该密码完成对应用程序的登录。

……你知道 cacert.pem 是什么吗?

Twitter API的连接是通过安全SSL连接完成的。Codebird-php会检查Twitter API服务器是否有有效的SSL证书。有效的证书具有正确的签名链。cacert.pem文件包含所有根证书颁发机构公共证书的列表。您可以在http://curl.haxx.se/docs/caextract.html上找到有关此文件更多信息。

……为请求Twitter API设置超时?

Codebird在可用的情况下使用cURL库连接到Twitter。您可以在毫秒中指定连接超时和请求超时。

$cb->setConnectionTimeout(2000);
$cb->setTimeout(5000);

如果您未指定超时,codebird将使用以下值

  • 连接时间 = 3000 ms = 3 s
  • 超时 = 10000 ms = 10 s

……禁用cURL?

Codebird会自动检测您是否启用了PHP cURL扩展。如果没有,库将尝试通过套接字连接到Twitter。为了使其工作,PHP设置allow_url_fopen必须启用。

您还可以手动禁用cURL。使用以下调用

$cb->setUseCurl(false);

……使用代理?

Codebird允许为cURL句柄和套接字启用代理支持。

要激活代理模式,使用以下调用

$cb->setProxy('<host>', '<port>');

您还可以使用认证代理。使用以下调用

$cb->setProxy('<host>', '<port>');
$cb->setProxyAuthentication('<username>:<password>');

默认情况下,假设使用HTTP代理。要使用不同的代理类型,使用相应的CURLPROXY_*常量,如下所示

$cb->setProxy('<host>', '<port>', CURLPROXY_SOCKS5);

……引用推文?

引用推文与转发不同,因为您可以添加自己的文本。原始推文将显示在您的引用下方。要引用推文,请在您的引用中添加对原始推文的链接,如下所示

$original_tweet = [
  'id_str' => '684483801687392256',
  'user' => [
    'screen_name' => 'LarryMcTweet'
  ]
];
$original_tweet = (object) $original_tweet; // sample, get real Tweet from API

$id = $original_tweet->id_str; // use the `id_str` field because of long numbers
$screen_name = $original_tweet->user->screen_name;

// looks like this: https://twitter.com/LarryMcTweet/status/684483801687392256
$url = "https://twitter.com/$screen_name/status/$id";
$text = 'I’d like to quote a Tweet.'; // maximum length = 140 minus 24 (link length) minus 1 space

$reply = $cb->statuses_update([
  'status' => "$text $url"
]);