Togetterからツイートをコピーするボタンを追加するユーザースクリプト

# <i class="fa fa-cubes"></i> 駄文

ドーモ=皆さん。
今日は12月24日ですね。
何の日かご存じでしょうか。
そう、かの惨劇、マルノウチ抗争が起きた日です。

ニンジャスレイヤー面白いですね。
皆さん読んでいますでしょうか。

私事ですが、小説を横書きで読むことが苦手です。
なので、テキスト化してビューワーで縦書き表示で読んでいるのですが…
まとめて頂いているTogetterのコピーがかなり面倒くさい。

1. 続きを読むがあるか最下部チェック
2. あるなら選択して続きを読み込む
3. 上から選択すると最初のアイコンを含めづらいので下からツイート選択してコピー
4. メモ帳に貼り付け 
5. 続きがあるなら下に戻って次のページへ移動

ニンジャスレイヤーのまとめは１話がだいたい
((デフォルト25 + 続きを読むで25のツイート)×数ページ)×セクション数(#n)
で構成されているので、その回数上の工程が必要でした。ﾖﾑﾏｴﾆﾂｶﾚﾙ…
あまりにやる気がでなくてテキスト化した話は４ヶ月で11本でした。

そこで、
[JavaScript - Qiitaのコードにコピーボタンを追加するユーザースクリプト - Qiita]
を何回でも流用して、ボタン一発でコピーしようということに。
完成したら２部完結までさくっとテキスト化できました。

# <i class="fa fa-cogs"></i> 動作確認環境

`Windows7` + `Firefox44` + `Greasemonkey`
今回も
`Firefox`のスクラッチパッド機能で開発→`Greasemonkey`へ貼り付け
なので、`Greasemonkey`依存は無いはずです。

コピーができないブラウザでもコピー補助としてツイート選択状態にしてみましたが…
手習いでアロー関数使ってみたので、極端に古いバージョンでは動かないかも。

Togetterに関してはニンジャスレイヤー関係のまとめでいくつか。
無編集が多かったので、Togetterの編集機能次第ではうまく取得できないかもしれません。
また、Togetterには未登録の状態で動かしました。

# <i class="fa fa-desktop"></i> デモ

![togetter-user-script-compressor.gif](https://qiita-image-store.s3.amazonaws.com/0/62354/e7abf02a-1a64-68c7-e900-8d495625f54d.gif)


# <i class="fa fa-code"></i> コード

[Togetter_add_copy_twitte_box_button.user.js]

```js:Togetter_add_copy_twitte_box_button.user.js

// ==UserScript==
// @name        togetter copy
// @namespace   khsk
// @include     http://togetter.com/li/*
// @include     https://togetter.com/li/*
// @version     1
// @grant       none
// ==/UserScript==
console.time('togetter')
// コピーとは無関係な個人的レイアウト調整
document.getElementById('social_floating_box').style.display = 'none'
document.getElementById('subheader').style.display = 'none'
document.getElementsByClassName('header_social_box') [0].style.display = 'none'
document.getElementsByClassName('side_box side_line_box editor_recommend') [0].style.display = 'none'
document.getElementsByClassName('social_box') [0].style.display = 'none'
//document.getElementsByClassName('alert alert-info') [0].style.display = 'none'
//document.getElementsByClassName('info_action') [0].style.display = 'none'
document.getElementsByClassName('favorite_user_box') [0].style.display = 'none'
document.getElementsByClassName('ad_list_top') [0].style.display = 'none'
document.getElementsByClassName('inner_right') [0].style.display = 'none'

// Firefox40までは未実装でもtrueが来てしまうので注意
var supportedCopy = document.queryCommandSupported('copy')

// コピー関数
var copyOrSelectedTweet = (node, endPoint) => {
  // NOTICE ユーザーが手動で選択している部分もコピーするので、嫌ならば先に選択解除を挟む
  // コピー対象を選択状態にする
  var range = document.createRange()
  range.setStart(node, 0)
  range.setEnd(node, endPoint)
  window.getSelection().addRange(range)
  if (!supportedCopy) {
    // コピーできないなら選択状態で終了 手動でコピーしてね
    return
  }
  try {
    document.execCommand('copy')
  } catch (e) {
    // 非対応なら例外が出る Firefox40までなど
    alert('copyに失敗しました')
  }
  // 選択を解除する
  window.getSelection().removeAllRanges();
  
  // NOTICE コピーが完了しました的テキストを出してもいいかも
}

// 続きを読む
var continueBtn = document.querySelector('.more_tweet_box > a:nth-child(1)')
if (continueBtn) {
  // 2ページ目以降対策で続きを読み込む
  continueBtn.click()
}

// 続き読み込み分へも適用するのでこの順序
// 各ツイートの返信 RT お気に入り (テキストに余分な改行が入るし、手動選択時に邪魔だったけど、最近改善されている見たい。けど不要なので非表示)
Array.prototype.forEach.call(document.getElementsByClassName('status'), (item) => {
  item.style.display = 'none'
});

// コピー or 全選択ボタン
var b = document.createElement('button')
b.innerHTML = supportedCopy ? 'コピー' : '全選択'
b.style.marginTop = '5px'
b.addEventListener('click', () => {
  var tb = document.getElementsByClassName('tweet_box') [0]
  switch (tb.childElementCount) {
    case 2:
      // 続きを読むなし
      // ツイートリスト + script
      copyOrSelectedTweet(tb, tb.childNodes.length - 1)
      break
    case 4:
      // 続きを読むあり + ペジネーションなし                           or 続きを読むなし + ペジネーション(ペジネーションラスト)
      // ツイートリスト + script + 続きのscript + 続きのツイートリスト  or ツイートリスト + script + ペジネーション + 表示数変更
      if (tb.children[tb.children.length - 1].tagName == 'UL') {
        //  続きを読むあり + ペジネーションなし
        copyOrSelectedTweet(tb, tb.childNodes.length)
      } else if (tb.children[tb.children.length - 1].tagName == 'DIV') {
        // 続きを読むなし + ペジネーション(ペジネーションラスト)
        copyOrSelectedTweet(tb, tb.childNodes.length - 5)
      } else {
        alert('想定外')
      }
      break
    case 6:
      // 続きを読むあり + ペジネーションあり
      // ツイートリスト + script + 続きのscript + 続きのツイートリスト + ペジネーション + 表示数変更
      copyOrSelectedTweet(tb, tb.childNodes.length - 5)
      if (typeof (pagination) == 'undefined') {
        // 上部にペジネーションコピー
        // paginationはグローバルに宣言し、再作成を防ぐ
        pagination = tb.children[tb.children.length - 2].cloneNode(true)
        pagination.style.display = 'inline'
        document.getElementsByClassName('title_box') [0].appendChild(pagination)
      }
      break
    default:
      alert('想定外')
      break
  }
})
document.getElementsByClassName('title_box') [0].appendChild(b)
console.timeEnd('togetter')


```



SNS系しない人なので、個人的な非表示部分も入っちゃってます。

# <i class="fa fa-graduation-cap"></i> まとめ

* わかったこと
 * 全体の前後に２行ずつ改行が入る
 * 各行の先頭にスペースが4つ入る  
   理由は謎です
 * 各ツイート、続きを読むの連結部には改行区切りなどが起こらない  
   (実装当時は改行入りすぎで四苦八苦したり一部妥協した記憶があるが、今は平気そう？)
 * 発言者と日時が入り、完璧にテキストのみは取得できない  
   (スペースも合わせてSublime Textの正規表現などで加工してねスタイル)
 * コピー未対応時の動作は検証していない
 * 選択範囲の終わりは実はよくわかっていない  
   余計な改行になる#textnodeを含まないような調整をしましたが、仕組みがわからず、1ずつずらして現在の値に設定しています
 * 画面を開いた時点で、自動的に続きが読み込まれる
 * もっと最適な、ニンジャスレイヤーで検証済みなツールがあること  
   [ログ取得ツール » Blog Archive » togetter→EPUB変換].[^1]  
   こ、こっちはブラウザのみでできることがウリですしはい…
* そしてこれからわかること
  * それはまだ……混沌の中。

***

アカウント表示があるほうがライブ感があっていいですね。
たまに入るお知らせや謝罪も面白いので、結構そのままで読んでいます。

 [ログ取得ツール » Blog Archive » togetter→EPUB変換]:http://wtnb.mydns.jp/wordpress/archives/5841
[JavaScript - Qiitaのコードにコピーボタンを追加するユーザースクリプト - Qiita]:http://qiita.com/khsk/items/27a80755d883521ecd73

[^1]: リンク先にもありますが、昔は続きを読むがCookie必須で泣いた思い出。ちょくちょく変更されているようです。
[Togetter_add_copy_twitte_box_button.user.js]:https://gist.github.com/khsk/1b9dd13efebe282ec506/raw/3951daba4bf96d4fe527791fa5f10a980fc26324/Togetter_add_copy_twitte_box_button.user.js