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 を開いてツイートできているか確認する
セールスポイント
一番のセールスポイントは、ブラウザを開いていればいつでもツイートできる点です
※ ただしブラウザは 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
Qiita とかで色々記事なっているが公式のチュートリアルが一番確実であり、わかりやすい
— - Bulma
最近気に入っている CSS ライブラリBulma is a free, open source CSS framework based on Flexbox and built with Sass. It's 100% responsive, fully modular, and available for free.
JS と依存関係がなく、非常に軽量で良き
— - Firebase Authentication
JS で Authon 認証したいよーを実装すると勝手にやってくれる
サーバ
- Firebase Cloud Functions
最近になってRESTを構築できるようになったのですね。驚きです
— - twitter
twitter API を簡単に呼ぶことができるライブラリTwitter API client library for node.js
つまづいたところやメモ
JavaScript
fetch() を使用して request をする
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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 で出力
1 |
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にしようするためのもの
です
onClick
html 内で button タグを定義するときに onClick で js で定義した関数を呼びたいときがあるができません
エラーをはきます
1 2 |
<!-- これだと呼ばれない --> <button onclick="myFunction()">Click me</button> |
エラーメッセージ
1 |
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); で呼ぶのが定石です
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<!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> |
Firebase 認証
Chrome 拡張 で Firebase から認証を受けるには、
- Firebse コンソールで Authentication の設定にて、認証ドメインリストに URI を追加
1chrome-extension://CHROME_EXTENSION_ID
※ CHROME_EXTENSION_ID : Chrome 拡張のID
— - Chrome 拡張 の manifest.json に https://apis.google.com という URL を content_security_policy ホワイトリストに追加
1"content_security_policy": https://apis.google.com",
をする必要があります
参考: https://firebase.google.com/docs/auth/web/twitter-login?hl=ja
初回起動
Chrome 拡張機能をインストールしたときや、App が更新されたときの一度だけスクリプトを実行するためには以下のものを呼び出す
1 2 3 |
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 - login して色々もらってくる
12$ firebase login$ firebase init functions //色々聞かれる firebaseのお導きのあるとおりに進む - functions/index.js にゴニョゴニョ書いていく
環境変数の確認・追加・削除
PROJECT_NAME : firebase のプロジェクト名
確認
1 |
$ firebase functions:config:get --project PROJECT_NAME |
追加
1 |
$ firebase functions:config:set someservice.key="THE API KEY" someservice.id="THE CLIENT ID" --project PROJECT_NAME |
以下のようにセットされる
1 2 3 4 5 6 |
{ "someservice" : { "key" : "THE API KEY", "id" : "THE CLIENT ID" } } |
削除
1 |
$ firebase functions:config:unset someservice --project PROJECT_NAME |
環境変数をプログラム内で呼び出す
例として以下のものが環境変数で定義されているとします
1 2 3 4 5 6 |
{ "consumer": { "secret": "CONSUMER_SECRET", "key": "CONSUMER_KEY" } } |
1 2 |
// consumer に定義されている key を使いたい const key = functions.config().consumer.key; |
参考: https://firebase.google.com/docs/functions/config-env?hl=ja
Cloud Functions から 外部 API へ Request
無料バージョンだ 外部 API を叩くことができない
そのため、定額バージョンが従量制バージョンに課金する必要がある
※ 公開できないのはこの制約があるためです
EX) エラーログ
1 2 |
{"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) エラーログ
1 |
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 を定義してあげる
1 2 3 4 5 6 7 |
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 のデプロイは大変時間がかかります
そのため、ローカルでサーバーを立てて検査をすることができます
コマンド
1 |
$ firebase emulators:start |
参考: https://firebase.google.com/docs/functions/local-emulator
実際に作ってみて
はじめて Chromej 拡張 App を作ってみました
もっと大変なのかと思いましたがそうでもなく、意外とぱぱっとつくることができました
サーバー側である Firebase も新しい使い方がわかって面白かったです
そして、今回作った App ですが個人的には満足です
利用としていた Twitter クライアントとなりました
これを使用して気兼ねなくメモをとったり独り言をいったり、わからなかった箇所の解決策をつぶやいたりしようと思います
そして、ブログに記事にすることでもっとブログ収益を増やしたいです