Make

気軽にTwitterにメモできるChrome拡張機能を作ってみた

Make
この記事は約13分で読めます。
スポンサーリンク

Twitter が大好きな私です

一日の半分以上はTwitterを閲覧またはツイートしていると思います

よかったらフォローしてください @momijinn_aka

 

日頃からもっと気軽にメモ程度にツイートできたらなぁと考えてました

そこで、Twitter を開かなくても手軽にツイートできる APP を作ってみました

この記事では、実際に作ってみたものとその概要をまとめたものです

作ったアプリケーション

作ったものは Chrome 拡張機能として動作し、ツイートのみに特化した APP ( ChromeExtenstionTweet ) です

言葉だけでは分かりづらいので動画をはります

00:06 qiita.com を開く
00:15 App を起動
00:16 ”Share URL” のスイッチをクリックして表示しているURLをシェアするようにする
00:20 適当なメッセージを入れてツイート
00:21 ツイートが成功すると “Memo”ボタンの左に “Success” が表示される
00:25 ホームボタンをクリックして google.com を開く
00:33 適当なメッセージを入れてツイート
00:41 Twitter を開いてツイートできているか確認する

ChromeExtenstionTweet

セールスポイント

一番のセールスポイントは、ブラウザを開いていればいつでもツイートできる点です
※ ただしブラウザは Chrome のみ

わざわざ Twitter のサイトに行かなくてよいです

 

また見た目も少し工夫しており、ツイートしている感じを出さないようにしています

周りからはメモをとっていると思われるようにしています

 

このような見た目にした理由として、公共の場や職場でも周りの目を気にせずツイートしたいからです

上記の場にてTwitterを開くのはかなり抵抗があります

しかし、ブラウジングしていたときに有益な情報があったりするとメモとしてツイートしたい気持ちになります

「Google Docs や Ever Note とかじゃだめなの?」と思うかもしれませんが、答えは NO です

いつでも見えるところにないとメモを忘れてしまいます

私はいつも使うのが Twitter なので Twitter に残しておきたいです

 

いつも見るTwitterに参考となった記事や解決方法を残しておき、帰宅後に見返し、そしてブログや Qiita 等の記事にちゃんとまとめたほうが自分のためになりますし、他の方たちにとっても有益になると思います

構成図

構成図は下の図のようになっています

ごりごりに Firebase を使用しています

Firebase Authentication で Twitter の Authon 認証を行っています

Firebase で簡単に Authon 認証が作れるので大変便利です

 

また、Firebase Cloud Functions で REST サーバを構築し、Twitter へツイートを投稿しています

 

自分で実装した部分は Firebase の REST サーバと クライアントである Chrome 拡張機能の2箇所です

使用したライブラリやAPI等

今回は諸事情により、現時点(2019/09/23)においてプログラムを公開しない予定です
※ 諸事情の理由は、下記のつまづきメモに記載あり

そのため使用したライブラリ等々を記載してきます

クライアント

  • Chrome Extension
    https://developer.chrome.com/extensions
    Qiita とかで色々記事なっているが公式のチュートリアルが一番確実であり、わかりやすい
  • Bulma
    https://bulma.io/
    最近気に入っている CSS ライブラリ
    JS と依存関係がなく、非常に軽量で良き
  • Firebase Authentication
    https://firebase.google.com/docs/auth/?hl=ja
    JS で Authon 認証したいよーを実装すると勝手にやってくれる

サーバ

  • Firebase Cloud Functions
    https://firebase.google.com/docs/functions/?hl=ja
    最近になってRESTを構築できるようになったのですね。驚きです
  • twitter
    https://www.npmjs.com/package/twitter
    twitter API を簡単に呼ぶことができるライブラリ

つまづいたところやメモ

JavaScript

fetch() を使用して request をする
fetch(Url, {
    method: "POST",
    body: JSON.stringify(Data),
    headers: {
      'Content-Type': 'application/json'
    }
  }).then(res => res.json())
    .then(res => {
      if (res.status === 200) {
        console.log("status 200");
      } else {
        console.log("not status 200");
      }
     

    })
    .catch(err => {
      console.log("err");
    })

response code が 200 以外でも サーバーからもらったものとして判断するため、400 や 401等のサーバーエラーは catch には行かない

 

参考: https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch#Uploading_JSON_data

Object型に入っているすべての要素を console.log で出力
console.log( JSON.stringify(obj) );

 

参考: https://qiita.com/ms2sato/items/27e82d6d881fce012459

Chrome Extension

page_action と browser_action の違い

Chrome 拡張 は manifest.json の中に Permission や バックグラウンドで実効するスクリプトを定義してあげる

その中に page_action と browser_action がある

2つの違いは、

page_action: 常に利用するためのもの
browser_action: 特定URLにしようするためのもの

です

 

参考: https://stackoverflow.com/questions/44712495/what-are-the-differences-between-page-action-and-browser-action/44713058

onClick

html 内で button タグを定義するときに onClick で js で定義した関数を呼びたいときがあるができません

エラーをはきます

<!-- これだと呼ばれない -->
<button onclick="myFunction()">Click me</button>

エラーメッセージ

Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src 'self' blob: filesystem: chrome-extension-resource:". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.

 

button タグに id を定義してあげて js 内に addEventListener(“click”,func); で呼ぶのが定石です

<!DOCTYPE html>
<html lang="ja">
<body>
  <button id="submit">submit</button>
</body>

<script>
  const submit = document.getElementById("submit");

  submit.addEventListener("click",() =>{
    console.log("click");
  });

</script>
</html>

 

参考: https://stackoverflow.com/questions/36324333/refused-to-execute-inline-event-handler-because-it-violates-csp-sandbox/36349056

Firebase 認証

Chrome 拡張 で Firebase から認証を受けるには、

  1. Firebse コンソールで Authentication の設定にて、認証ドメインリストに URI を追加
    chrome-extension://CHROME_EXTENSION_ID

    ※ CHROME_EXTENSION_ID : Chrome 拡張のID

  2. Chrome 拡張 の manifest.json に https://apis.google.com という URL を content_security_policy ホワイトリストに追加
    "content_security_policy": https://apis.google.com",

をする必要があります

 

参考: https://firebase.google.com/docs/auth/web/twitter-login?hl=ja

初回起動

Chrome 拡張機能をインストールしたときや、App が更新されたときの一度だけスクリプトを実行するためには以下のものを呼び出す

chrome.runtime.onInstalled.addListener(() => {
 console.log("init");
}

 

参考: https://developer.chrome.com/extensions/background_pages#initialization

Firebase Cloud Functions

Cloud Functions を開発する
  1. ライブラリをゲット
    $ npm install -g firebase-tools
  2. login して色々もらってくる
    $ firebase login
    $ firebase init functions //色々聞かれる firebaseのお導きのあるとおりに進む
  3. functions/index.js にゴニョゴニョ書いていく
環境変数の確認・追加・削除

PROJECT_NAME : firebase のプロジェクト名

確認

$ firebase functions:config:get --project PROJECT_NAME

 

追加

$ firebase functions:config:set someservice.key="THE API KEY" someservice.id="THE CLIENT ID" --project PROJECT_NAME

以下のようにセットされる

{
 "someservice" : {
  "key" : "THE API KEY",
  "id" : "THE CLIENT ID"
 }
}

 

削除

$ firebase functions:config:unset someservice --project PROJECT_NAME

 

参考: https://stackoverflow.com/questions/45820280/how-to-unset-firebase-cloud-functions-environment-variable

環境変数をプログラム内で呼び出す

例として以下のものが環境変数で定義されているとします

{
  "consumer": {
    "secret": "CONSUMER_SECRET",
    "key": "CONSUMER_KEY"
  }
}
// consumer に定義されている key を使いたい
const key = functions.config().consumer.key;

 

参考: https://firebase.google.com/docs/functions/config-env?hl=ja

Cloud Functions から 外部 API へ Request

無料バージョンだ 外部 API を叩くことができない

そのため、定額バージョンが従量制バージョンに課金する必要がある

※ 公開できないのはこの制約があるためです

EX) エラーログ

{"errno":"EAI_AGAIN","code":"EAI_AGAIN","syscall":"getaddrinfo","hostname":"api.twitter.com","host":"api.twitter.com","port":443}
Billing account not configured. External network is not accessible and quotas are severely limited. Configure billing account to remove these restrictions
cors を導入

cors を導入していないと firebae から Response をもらうときにエラーがでる

cors に準拠してないよばーかばーかといわれます

EX) エラーログ

Access to fetch at 'https://us-central1-****' from origin 'chrome-extension://****' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

 

手っ取り早い方法は unctions.https.onRequest{} 関数内の直近に cors を定義してあげる

const cors = require('cors')({ origin: true });

exports.hoge = functions.https.onRequest((req, res) => {
 cors(req, res, () => {
   res.status(200).send({"res": "ok" });
 });
});

 

参考: https://qiita.com/seya/items/0f12bd09c8e856123bc3

テスト

Cloud Functions のデプロイは大変時間がかかります

そのため、ローカルでサーバーを立てて検査をすることができます

 

コマンド

$ firebase emulators:start

 

参考: https://firebase.google.com/docs/functions/local-emulator

実際に作ってみて

はじめて Chromej 拡張 App を作ってみました

もっと大変なのかと思いましたがそうでもなく、意外とぱぱっとつくることができました

サーバー側である Firebase も新しい使い方がわかって面白かったです

 

そして、今回作った App ですが個人的には満足です

利用としていた Twitter クライアントとなりました

これを使用して気兼ねなくメモをとったり独り言をいったり、わからなかった箇所の解決策をつぶやいたりしようと思います

そして、ブログに記事にすることでもっとブログ収益を増やしたいです

コメント

タイトルとURLをコピーしました