日記

のみろぐ

主に競プロ日記です

AtCoder Virtual Contest Tweet ButtonっていうChrome拡張作ったよ!!

AtCoder Virtual Contest Tweet Button

まえがき

作ったものについて

f:id:nomikura:20181204221448p:plain
使用時のスクショ

概要

  • AtCoder Virtual Contest Tweet ButtonというChrome拡張機能を作りました
  • その名の通り、AtCoder Virtual Contestのコンテスト内容を簡単にツイートできるボタンです。

  • Chromeウェブストアからダウンロードできます。

  • AtCoder Virtual Contestのコンテストページで拡張機能のアイコンをクリックすると、内容が自動で補完されたツイート画面が表示されます。
  • 使ってみてね!!(急にフレンドリー)

作った動機

  • バーチャルコンテストを開くことをTwitterで呼びかけるとき、いちいちコンテスト内容を打つのが面倒だったので作った
  • たぶんnotさんにお願いすればツイートボタンを作っていただけたと思うのですが、どうしてもChrome拡張機能を作ってみたかったので作っちゃいました。ごめんなさい!!!

開発ログ

  • HTML, CSS, JSの知識があれば大丈夫という事前知識があったので楽勝だろうと思ってたけど意外と苦労した。
  • ソースコードGitHubに載ってます
  • 以下の文章はChrome拡張を1日触っただけの人間が書くものなので正確性は保証しません。

拡張機能の大枠を作る

  • 公式ページにはプロジェクトファイル内にmanifest.jsonを書けばとりあえず動くみたいなことが書いてあった。ここに次々と追加していく感じなんだろうなーといった感想だった。
  • ただ、公式ページではいきなり知らないAPI使い出すし、マニフェストファイルの書き方もピンことなかった。もっと簡単な例あるだろ...って感じだけど、Google天才集団の知能に僕が追いつけてないだけなので泣きながらググりまくりました。えーん。
  • ググりまくって、マニフェストファイルの書き方も少しわかってきたので、実装に移ります。

HTMLからコンテスト情報を取得する

  • これができないとなにもできないのでいちばん最初に取り掛かった
  • ツイートに必要な情報は、「タイトル」、「時間」、「説明」、「URL」の4つ。最初はペナルティ情報も必要だと思ったけどバチャにおいてペナルティは重要じゃないので省いた。
  • 該当部分のソースコードは以下のような感じ。
<h1 class="page-header">
    ゴリラジオ体操第141
    <small class="pull-right">ペナルティ5分 / 2018-12-05 06:25:00 ~ 2018-12-05 07:10:00</small>
</h1>
<p>基本的に平日毎朝、決まった時間にABCのB~Dをやってます。誰でも歓迎です!</p>
  • h1タグにpage-headerってクラス名がついている。なので、document.getElementsByClassName('page-header')とすればいい感じのデータが取れる。
  • コンテストの説明文は、h1タグの下にある。これを取ってくる方法をググったところ、nextElementSiblingというのがあった。headerTag.nextElementSiblingみたいなコードを書いたら説明文を取得できた。

アイコンのクリックを検知する

  • 当初はページ内にツイートボタンを置く予定だった。だが、HTMLの書き換えが原因でページの挙動がおかしくなったりするのがこわかった。なので、拡張機能のアイコンをクリックしたらツイートするウィンドウが表示される形式にしようと思った。
  • アイコンの検知は、バックグラウンドで行う。マニフェストファイルのbackgroundの項目にJSファイルを追加して、そこに実装する。バックグラウンドの処理はずっと走ってるらしい。なので、バックグラウンドでユーザーの動きを検知するんだろうなーって感想。
  • 実装はだいたい以下のような感じ。
chrome.browserAction.onClicked.addListener(() => {
    // クリックされた時の処理を書く    
);

ツイート画面を開く

  • アイコンのクリックを検知したらツイート画面を開く処理を書く。
  • ツイートを開くには大体以下のような感じの処理を書く。これを書くと、新しいウィンドウが開く。
const url = 'https://twitter.com/intent/tweet?text=' + 'ここにツイートする文章を入れる';
window.open(url, null, 'ここでウィンドウの大きさとかを指定');

HTMLから取得した情報をツイート画面に反映させる

  • これがいちばん大変だった。すべてバックグラウンドで処理できると思っていたが、これはファイルをまたいだ処理が必要だった。ファイルをまたいだ処理はAPIを使用して行う。
  • Chrome拡張でとっても役立つAPIのまとめ」と「Chrome拡張でruntime.sendMessageのコールバックがうまく動作しない理由」の2つの記事を元に処理を書いた。公式ドキュメントみてもよくわからん。
  • いろいろ頑張った結果、裏処理と表処理をつなぐコードは以下のようになった。バックグラウンドでクリックを検知すると、content側に処理を投げる。content側ではHTMLから情報を取得する処理が走る。そして、それをツイート画面に反映させる。おしまい。ちょっと説明が雑になったが、処理部分は全部書き終わった。

情報を送る側(background)

chrome.browserAction.onClicked.addListener((tab) => {
    chrome.tabs.sendMessage(tab.id, {
        command: "create_tweet",
    },
    (msg) => {
        console.log("result message: ", msg);
    })
});

情報を受け取る側(content)

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
    // 処理
});

Chromeウェブストアにアップロードする

感想

  • そんな感じで、無事アドカレ間に合いました!!よかった!!
  • 1日中拡張機能触ってたのですごい疲れた。
  • なかなか動かなかったりしたからすげー焦った。やばいwwおわんねえwwwwみたいな気持ちだった
  • その分、動いた時はくっそ嬉しかったですが
  • 今まで手が出せていなかった拡張機能だったけど、アドカレをきっかけに触ることができて満足。かぎつきくんありがとう!!

  • 自分の作ったものがストアに載るのすげー面白い。感動した。

  • またなにか作りたい気持ちになりましたとさ。

追記

  • 僕の思いがnotさんに通じたようで、AVCにツイートボタンが実装されました!!僕の拡張は忘れても僕のことは忘れないでください!! のみより
  • 公式のハッシュタグが#AtCoderVirtualContestだったので、ハッシュタグをそれに合わせました!(もともとは#AtCoder_Virtual_Contestだった。その際、manifest.jsonの記述を"version": "0.0.1"から"version": "0.0.2"に変更した。そうしないとアップロードでエラーが出た。