Twitter / Upcoming changes to Tweets の日本語訳

2016/05/24 23:00(日本時間)に発表されたTwitterの仕様変更に関するAPIドキュメント [Upcoming changes to Tweets | Twitter Developers](https://dev.twitter.com/overview/api/upcoming-changes-to-tweets) (2016/5/25 14:00時点のもの ⇒ 随時更新)を抄訳してみました。

 - 原文が長すぎていまいちパッと把握できないので写経した感じです。
 - 正確な情報は必ず [原文](https://dev.twitter.com/overview/api/upcoming-changes-to-tweets) をご確認くださいね。
 - 2016/7/20: API変更点を要約した「概要」が原文に追加されていたので追記しました
 - 2016/9/14: 「最近の改訂」として投稿系の各パラメータやエラーコード(44,385)が原文に追加されていたので追記しました


----

# はじめに

本ドキュメントでは人々が140文字でより多くのことを表現できるようにする、つまり、
1) 公開された会話をTwitter上でより簡単にフォローできるようになり、会話を豊かにする
2) メディア自身を表現するための文字数を消費することなく、メディアを添付できるようにする
…ためのツイートへの一連の変更について概要を説明します。

これらの変更はTwitterプラットフォームの多くの側面に影響します。そのため、あなたの製品やアプリケーションの新ツイートフォーマットへの移行を手助けするため、技術資料を用意しています。以下の文章では予定されている技術的な変更点を見ていきます。


## 最近の改訂:

 - JSON サンプルツイートを追加
 - ツイート作成オプションの情報を追加 (特に ```attachment_url```, ```auto_populate_replies_metadata``` および ```exclude_reply_userids``` パラメータ)
 - 新たな状況に関連したエラーコードの情報を追加


# 概要

<!-- The following chart illustrates the differences between Tweet JSON objects in the various API endpoints (REST, streaming and Gnip), once the API changes described above are active. (If the formatting is difficult to read, please see the documentation and samples on our corresponding [Github repo](https://github.com/twitterdev/tweet-updates/blob/master/upcoming.html).) -->

下表では上記のAPI変更が有効になった場合の、各APIエンドポイント(REST, streaming and Gnip)におけるツイートのJSONオブジェクトの違いを表しています。
(訳注：原文では下表は画像形式で表現されており、その元となったHTMLが [Github repo](https://github.com/twitterdev/tweet-updates/blob/master/upcoming.html) にて提供されているのでそれを元に下表を作り直しています)

<table width="100%">
<thead>
<tr>
 <th width="10%"><b>モード</b></th>
 <th width="30%"><b>目的</b></th>
 <th width="10%"><b>有効性</b></th>
 <th width="30%"><b>詳細</b></th>
 <th width="20%"><b>サンプルツイート (JSON)</b></th>
</tr>
</thead>
<tbody>
<tr>
 <td><p>互換モード</p></td>
 <td><p>ツイートペイロードが全ての既存のシステム上で、ツイートコンテントに関係なく動作すること。</p></td>
 <td><p>全REST APIのデフォルト</p></td>
 <td>
  <ul>
   <li><code>text</code> フィールドは必要に応じて 140 文字で切り取られる</li>
   <li><code>truncated</code> フィールドは true</li>
   <li>いくつかの <code>entities</code> パラメータは有効な140文字内のもののみが含まれる</li>
  </ul>
 </td>
 <td>
  <ul>
   <li><a href="https://github.com/twitterdev/tweet-updates/blob/master/samples/compatibility_classic_13995.json">Classic tweet</a></li>
   <li><a href="https://github.com/twitterdev/tweet-updates/blob/master/samples/compatibility_classic_hidden_13797.json">Classic tweet w/ hidden text</a></li>
   <li><a href="https://github.com/twitterdev/tweet-updates/blob/master/samples/compatibility_extended_13996.json">Extended tweet</a></li>
  </ul>
 </td>
</tr>
<tr>
 <td><p>互換モードで <code>extended_tweet</code> がペイロードに追加されたもの</p></td>
 <td><p>後方互換性を維持するため(欠損なしに、ペイロードへの追加により)</p></td>
 <td><p>全てのストリーミングとGnip APIのデフォルト</p></td>
 <td>
  <ul>
   <li>ペイロードに新たな <code>extended_tweet</code> パラメータが追加され、下記を含む：
    <ul>
     <li><code>full_text</code></li>
     <li><code>display_text_range</code></li>
     <li><code>entities</code></li>
     <li><code>extended_entities</code></li>
    </ul>
  </ul>
 </td>
 <td>
  <ul>
   <li><a href="https://github.com/twitterdev/tweet-updates/blob/master/samples/compatibilityplus_classic_13994.json">Classic tweet</a></li>
   <li><a href="https://github.com/twitterdev/tweet-updates/blob/master/samples/compatibilityplus_classic_hidden_13797.json">Classic tweet w/ hidden text</a></li>
   <li><a href="https://github.com/twitterdev/tweet-updates/blob/master/samples/compatibilityplus_extended_13997.json">Extended tweet</a></li>
  </ul>
 </td>
</tr>
<tr>
 <td><p>拡張モード</p></td>
 <td><p>ツイートペイロードは140文字を超えたツイートをレンダリングするための全情報を含む</p></td>
 <td>
  <p>REST APIのみ: 次のパラメータをエンドポイントに追加すること: <code>tweet_mode=extended</code></p>
 </td>
 <td>
  <ul>
   <li><code>full_text</code> が <code>text</code> を置き換える</li>
   <li><code>truncated</code> フィールドは false</li>
   <li><code>display_text_range</code> は メンション/ツイート/エンティティ というツイート本文の各区分を表現する</li>
  </ul>
 </td>
 <td>
  <ul>
   <li><a href="https://github.com/twitterdev/tweet-updates/blob/master/samples/extended_classic_14002.json">Classic tweet</a></li>
   <li><a href="https://github.com/twitterdev/tweet-updates/blob/master/samples/extended_classic_hidden_13761.json">Classic tweet w/ hidden text</a></li>
   <li><a href="https://github.com/twitterdev/tweet-updates/blob/master/samples/extended_extended_14001.json">Extended tweet</a></li>
  </ul>
 </td>
</tr>
</tbody>
</table>




# 何が変わるの？

<!-- We are simplifying the way that replies work on Twitter by moving some of the “scaffolding” of Tweets into display elements so they no longer count towards the character limit within the Tweet. -->

いくつかのツイートの足場("scaffolding")を表示要素に移動することにより、Twitter上での返信作業を簡略化していきます。それによりそれらはもはやツイート内の文字数制限にカウントされなくなります。

 * 返信: 返信ツイートの開始位置にある「自動的に追加された」@ names は文字制限としてカウントされなくなります (但し、@メンション で始まる 新たな「非返信ツイート」はカウントされます、@メンションはユーザーによってツイート本文に明示的に追加されたものなので)。さらに、ユーザー名で始まる新ツイートはもはや、そのツイートを全フォロワーに届けるために [”.@” 形式](https://twitter.com/twitter/status/732659321536815104) を利用する必要はなくなります。

 * メディア添付: ツイートの末尾にある画像、動画、GIF、アンケート、引用ツイートおよびDMディープリンクのURLも同様に文字数制限にカウントされなくなります。(ツイート内に入力またはペーストされたURLは現在と同様に文字数制限にカウントされます)


この変更では、ツイート(具体的にはメンション)の一部として含まれるであろう特定の要素の数に新たな制限を導入します。

これらの変更は今後数ヶ月以内に提供されます。我々の目的は、開発者やパートナーにこのツイートフォーマットの変更を予告することであり、それにより彼らが製品やアプリケーションを適切に準備できるようにすることです。


# 互換性、これが開発者にとって何を意味するのか

サードパーティークライアントやAPIユーザーに対する前方および後方互換性は、我々によって主要な留意事項です。

今回の変更は多くの領域に影響します：

 - パブリックREST API と ストリーミングAPI
 - Ads API
 - Gnip データプロダクト
 - 表示プロダクト：例えば Fabric の Twitter Kit による埋め込みツイートやタイムライン(iOS, Android や Web に表示される)


# ツイートオブジェクトの変更点

ツイートペイロード内の以下の点が変更になります:

 - ツイート内の表示されるテキストは[140文字](https://dev.twitter.com/overview/api/counting-characters)を超えません。しかし、『ユーザー名や添付URLがツイート内の適切な位置に含まれている場合は』ツイートJSONオブジェクト全体のテキストコンテンツは140文字を超えることができます。開発者はアプリケーションに対する長さのハードコーディングを避けなければなりません。

 - テキストは論理的に3つの領域に分割されます:
   * ***隠れた*** プレフィックス領域(a ***hidden*** prefix region)は、1つまたは複数のスペースで区切られた @メンションを含み、それは表示文字の一部として表示されるものではなく、代わりにメタデータとして表示する必要があります。

   * 表示文字領域(a display text region)は、最大で長さが140文字のままです。

   * ***隠れた*** サフィックス領域(a ***hidden*** suffix region)は、1つの添付URLを含む場合があります。それは表示文字の一部として表示されるものではなく、代わりにメタデータとして表示する必要があります。この領域は、添付ファイルのリソースを識別する単一のURLのエンティティを含むために限定されています: 現在は 1～4 個の画像、GIF、動画、poll、引用ツイート、またはDMディープリンクです。

     - Note: URLs for Quote Tweet or DM deep links that are typed or pasted into a Tweet will still count against the character limit. The new attachment_url parameter on the POST statuses/update endpoint will enable valid link formats to be attached to a Tweet. They will not count against the character limit when this method is used.
     - Note: ツイートに入力、またはペーストされる 引用ツイートやDMディープリンクのURLは、今まで通り文字数制限にカウントされます。```POST statuses/update``` エンドポイントの新しい ```attachment_url``` パラメータにより適切なリンクフォーマットのURLをツイートに添付できるようになります。この方法を使えば、それらのURLは文字数制限にカウントされなくなります。

 - 隠れたプレフィックス・サフィックス領域を含む場合、ツイートオブジェクトは ツイート文字列として表示されるテキストエリアの開始・終了インデックスを識別する値を含むことになります。

 - サンプルペイロードは付録にあります。

<!--
     - Note: ツイートに入力、またはペーストされる 引用ツイートやDMディープリンクのURLは、いまだに文字数制限にカウントされます。近い将来、それらのURLをツイートに添付するための ```attachment_url``` パラメータを POST statuses/update エンドポイントに追加します。この方式によりそれらは文字数制限にカウントされなくなります。
-->


# どのように見えますか？

この図はツイートに対するハイレベルな(訳注：抽象度の高いという意味)変更を表しており、要素はユーザインタフェース的に隠されます。

![image00_0.png](https://qiita-image-store.s3.amazonaws.com/0/39221/1b03be4a-0518-5fe1-689a-c2ddb29ba2b2.png)

アプリ内やウェブ上に表示する場合、下記のフォーマットのように、隠れた@メンションはツイート本文の外側に表示すべきです。ツイートが複数名への返信の場合、直接の返信先となる発言者が優先されるべきです。

![image01_0.png](https://qiita-image-store.s3.amazonaws.com/0/39221/18de9679-5cca-2552-3f89-7e9475fd2bb6.png)


# 用語

 - **Classic Tweet** - テキストコンテンツの合計文字数が140文字を超えないツイートオブジェクト。新しいクライアントでは、先頭・末尾の両方またはいずれかの文字列が隠れるかもしれないし、隠れないかもしれないよ。

 - **Extended Tweet** - 隠れたエンティティ(例えば、@メンション で始まり、添付で終わる)を含み、テキストコンテンツの文字数が140文字を超えるツイートオブジェクト。表示テキスト領域(display text region)は140文字を超えてはなりません。


# レンダリングモード

ツイートJSONオブジェクトをAPIのクライアントに出力する際に2つのモード：**互換**モード(**compatibility** mode)と**拡張**モード(**extended** mode) が存在します。互換モードはパブリックREST APIやストリーミングAPI、Gnipプロダクトのデフォルトモードで、既存のクライアントを壊さないようにデザインされています。

REST API クライアントはリクエストパラメータにより拡張モードをオプトインできます。


<!-- In the future, an additional announcement will be made when the time is right to make a change for the rendering mode to default to extended mode. -->
将来的には、拡張モードをデフォルトのレンダリングモードとする適切な時期が来た際に、追加のアナウンスを行います。


# 互換モードのJSONレンダリング

互換モードでは、**Classic Tweets** は現在と全く同じようにレンダリングされます。

互換モードにおける **Extended Tweets** に対しては、下記のようになります：


 1. 既存の ```text``` フィールドは切り取られたツイートテキストを含み、その後に省略記号、スペース、そして自身のパーマリンクURLが続きます。合計文字数は140文字を超えません。

 2. 既存の ```truncated``` フィールドは ```true``` になります。

 3. 既存のentityフィールド (```mentions```, ```urls```, ```media```, など)は ```text``` に完全に含まれるエンティティのみが含まれます。各エンティティの ```from``` と ```to``` インデックスは ```text``` の正しいコードポイントでなければなりません。エンティティ内を切り取ってしまうのを避けるように切り取り点が設定されます。追加された「自身のパーマリンクURL」のURLエンティティがエンティティリストに追加されます。

 4. ペイロードには```extended_tweet```という新しいフィールドが含まれます(これはストリーミングAPI、Gnip API 特有のものです)。これは下記のサブフィールドを含みます：
   - ```full_text```: フルの、切り取られていないツイートを含みます
   - ```display_text_range```: 2つの Unicode コードポイントインデックスの配列で、表示できるツイートの開始(inclusive start)と終了(exclusive end)インデックスを表します。
   - ```entities/extended_entities```, etc.: 全てのエンティティです。

 5. 引用ツイートを埋め込んだ結果として、ツイートが引用ツイートのパーマリンクURLを含む場合、切り取られたtextにそのパーマリンクURLが含まれていなくても、引用ツイートは含まれます(訳注：quoted_tweet等の引用ツイート情報は含まれるという意味)。

 6. ツイートが添付cardの結果として、URLエンティティを含む場合、オリジナルのURLエンティティが切り取られたtextに含まれなくてもそのカードは含まれます。

 7. ネイティブメディアはエンティティとしてのみ表現されるため、それらは「切り取られたエンティティ一覧」からは失われることになります。しかしそれらは ```extended_tweet.entities``` に存在します。


# 拡張モードのJSONレンダリング

拡張モードでは **Classic Tweets** と **Extended Tweets** 共に 下記のようになります：


 1. ```text``` フィールドは含まれません。代わりにペイロードは ```full_text``` という名前のフィールドを含みます。これは切り取られていないツイート全体を含みます。

 2. ペイロードは ```display_text_range``` を含みます。これは2つの Unicode コードポイントインデックスの配列で、表示できるツイートの開始(inclusive start)と終了(exclusive end)インデックスを表します。

 3. ```truncated``` フィールドは ```false``` です。

 4. エンティティフィールドは全てのエンティティ(「隠された」「表示可能な」いずれも)を含みます。


# 制限

テキストのコンテンツには制限が存在します。これはエンドユーザー体験を改善し、高品質なコンテンツを促進するためです。新しいエンティティ制限を超過した場合、新しいAPIエラーコードとしてツイート作成時点で拒否されます。
これらの制限は全体の文字数に関わらず全てのツイートに強制されます。(これは既存のツイート作成をサポートするメソッドが変化することを意味します)

下記の数値が初期ガイドラインのものとなります。

 - ツイートテキスト全体: Unicode Normalization Form C 適用後で、3,000 Unicode コードポイントに制限されます。

 - @メンション: 非表示領域の1ツイート当たり50 @メンションに制限されます。これはサーバサイドで強制されるため、ユーザーはこの数を超過することはできません。

 - 既存のメディア添付数やサイズは変化しません (単一URLで4画像、または 1GIF、または1 動画を表現すること)。 Twitterアプリやウェブ経由(別名ネイティブメディアリンク)で添付したリンクはカウントされませんが、編集ボックスに入力またはペーストしたリンクはカウントされます。


# APIの変更点
## パブリック REST API エンドポイント

### ツイートの作成(Composition)

新しいツイートを***作る***REST APIのエンドポイント(```statuses/update```)は、ツイートが会話への返信である場合に新しいブール型パラメータを受け取ります: ```auto_populate_reply_metadata``` (```true``` : 有効, ```false``` : 無効, ```false``` がデフォルト)。既存の ```in_reply_to_status_id``` も指定される必要があります。オリジナルのステータス(訳注：返信先のツイート)から先頭の@メンション(mentions)が順に探索され、新しいツイートに追加されます。オリジナルのステータスが削除されている場合、その返信は失敗します。これは従来の振る舞い(削除済みツイートIDへの返信が可能であった)から変更となります。

```auto_populate_reply_metadata``` オプションについて修正しない古いクライアントのために、メンションはツイートボディに引き続き含まれ、サーバが新しいツイートをどのように表示するか決定します。

```auto_populate_reply_metadata``` オプションは会話が進むのに応じて @メンション(mentions) を上限に達するまでメタデータに追加していきます。そのリストの長さを編集するための追加オプション ```exclude_reply_user_ids``` オプションにより、返信から除外されるID(先頭の1つを除く)を指定することができます。このパラメータはオプションで、カンマ区切りのユーザIDリストで、サーバ側で生成される @メンション から除外されます。

留意すべきなのは、先頭の @メンションは in-reply-to-tweet-id の意味を壊すことがないように、削除することができないという点です。削除しようとした場合はこっそり無視されます。

URLをツイート本文としてカウントされないようにするために、新たに ```attachment_url``` パラメータが ```statuses/update``` で利用でき、これで URL をツイート本文に明示的に追加することなく添付することができます。このURLはツイートのパーマリンクか、[DM deep link](https://business.twitter.com/en/help/campaign-editing-and-optimization/public-to-private-conversation.html) でなければなりません。任意の、非Twitter URLはツイート本文に残さなければならず、それは140文字制限にカウントされます。
ツイートパーマリンクやDM deep linkではない URL が ```attachment_url``` パラメータに
URLs 渡された場合、ツイート作成は失敗し、例外を引き起こします。


### ツイートの取得(Consumption)

ツイートを***返す***エンドポイントは、新たに ```tweet_mode``` リクエストパラメータを受け取ります。

指定可能な値は ```compat``` と ```extended``` で、それぞれ互換モードと拡張モードを意味します。

デフォルトモード(パラメータが指定されない場合)は互換モードです。古いクライアントとその表示方法をサポートするためのものです。

パブリックREST APIの 互換モードでレンダリングされたツイートは、```extended_tweet``` フィールドを***含みません***。フルテキストを取得したいREST APIクライアントは、代わりにオプトインで拡張モードを利用してください。


### エラーコード

上記に記載した制限事項のため、新しいAPIレスポンスとエラーコードが導入されます。これらは上記リミット節に記載したコンテンツの新しい制限事項を反映しています。

|  |  |  |
|:--|:--|:--|
|44  | ```attachment_url``` パラメータが不正です | HTTP 400 に相当。指定されたURL値はこのツイートに添付することができるURLではありません。 |
|385  | 返信しようとしたツイートは削除済みか、見れなくなっています | HTTP 403 に相当。返信は存在するpublicツイートに対してのみ送信することが出来ます。 |
|386  | ツイートは許容されている添付型の数の上限を超えています  | HTTP 403 に相当。ツイートは1つの添付リソース(メディア, 引用ツイート, etc.) のみに制限されています。 |



## パブリックストリーム

ストリーミングAPIは、リクエストオプションを設定するためのクエリーパラメータに相当する機能を提供しません。従って、現時点ではストリーミングAPIは互換モードで全ツイートを提供します。

REST APIとは異なり、ストリーミングAPIではツイートは互換モードで提供され、extended tweet のために ```extended_tweet``` フィールドが含まれます。これは既存のクライアントが期待している既存の ```text``` フィールドより長いテキストを送信することで、既存のクライアントがぶっ壊れるのを避けるために、また、1つのストリームでデータ全体を提供するために必要となります。```extended_tweet``` フィールドがある場合、上記で説明したrangesも含みます。

<!-- Streaming API consumers should update their code to first check for the presence of the ```extended_tweet``` dictionary, and use that in preference to the truncated data as is applicable for their use case. When ```extended_tweet``` is not present, they must fall back to using the existing fields. -->
ストリーミングAPIコンシューマは、まず ```extended_tweet``` 要素が存在するかを確認し、自身のユースケースに応じて、それを切り取られたデータよりも優先して利用します。```extended_tweet``` が存在しない場合、既存のフィールドを利用するようにフォールバックする必要があります。

将来的には、拡張モードに切り替える日がアナウンスされ、それ以降はアプリは新しいツイートペイロードを処理することができるようにする必要があります。


## Gnip (REST and Streaming APIs)

In the case of Data products, both the REST and Streaming endpoints will follow a similar pattern to the public Streaming API, and the current versions of the data products APIs will render Tweets in compatibility mode, with the ```extended_tweet``` field.

The impact is intended to be a minimal, additive and opt-in, non-breaking change. Gnip customers will have to make a code change to “opt-in” to utilize the new additive fields when present. They may also want to prepare for the impacts of increased payload sizes, including storage and bandwidth implications.

In addition to payload changes, upon release of new Tweet payloads, Gnip operators and enrichments will begin to analyze the longer text and entities as opposed to the truncated version.


## Web, iOS, Android のツイート表示
### Web

widgets.js JavaScriptライブラリにより生成されたTwitterのWeb埋め込み生成物については、パブリッシャーによる追加の設定なしに、新ツイート表示フォーマットをサポートするように自動的に更新されます。


### iOS, Android

Twitter Kitライブラリの将来のバージョンは extended Tweets の取得と、新テンプレート内へのその結果の表示をサポートします。
アプリケーション開発者はそれが利用可能となった以降のTwitter Kit のバージョンに更新することを決め、アプリと新しいコードをビルドして、通常のアプリアップデート作業の一部としてその変更をリリースしてください。

### ツイートWeb Intent, Twitter Kit Tweet Composer

現時点ではツイートWeb Intentや、Twitter Kitに含まれるTweet Composer機能に対する変更は計画しておりません。


# 付録: APIペイロードのサンプル

<!-- The following examples demonstrate the differences between Tweet JSON objects in the REST API endpoints, once the API changes described above are active. -->

下記のサンプルは、上述のAPI変更が有効になった時点におけるREST APIエンドポイントのツイートJSONオブジェクトの違いを明示します。




>以降、JSONのサンプルは長いので[別の記事](http://qiita.com/takke/items/c80a687718fc65b0b5b9)にしました。
>下記のバリエーションのサンプルが載っています。
>- Classic Tweet, compatibility mode
- Classic Tweet, extended mode
- Classic Tweet, compatibility mode, hidden text
- Classic Tweet, extended mode, hidden text
- Extended Tweet, compatibility mode
- Extended Tweet, compatibility mode (streaming, with extended_tweet)
- Extended Tweet, extended mode
- Additive to Gnip ActivityStreams payload