以前、「Chatworkのメッセージをスプレッドシートに保存しよう」という記事を全2回でお届けしました。ただ、Google Apps Scripts(GAS)に馴染みのない方がサクッと使用するにはまわりくどい書き方だったなと思うので、まとめ的に本記事を書いてみます。
注意点と事前準備
今回Chatwork APIを利用して過去メッセージを取得しますが、注意点として、過去メッセージ全部をAPIで取得することはそもそもChatwork APIの仕様上の制限でできません。APIで取得できるのは最新の100件のみです。遠い過去は振り返らないでおきましょう。
続いて、事前準備ですが、Chatwork APIの操作にはAPIトークンとルームIDが必要です(2022/12/09現在)。
APIトークンの確認
APIトークンの確認は以下の手順で行います。
- Chatwork画面右上の「利用者名」をクリック
- メニューの「サービス連携」を選択
- 左側のメニューから「APIトークン」を選択
- APIトークンを控える
ルームIDの確認
続いてルームIDを確認します。ルームIDは、文字通りチャットルームごとに割当られたIDです。
ルームIDは、Chatworkの該当ルームにアクセスした際のURLの末尾に記載があります。
これで事前準備はOKです。
ログ記録用のスプレッドシートを作成する
続いては、メッセージのログ記録用のスプレッドシートを作成します。以下の仕様通りにシートを作成していきます。
- 名前は任意(例:ChatWork メッセージバックアップ etc)
- サンプルコードをコピペする場合は、LogとErrorsという名前のシートをそれぞれ作成
- Logシートの1行目には「message_id, account_id, 名前, アイコン, メッセージ, 送信日時, 更新日時」というヘッダー項目を入力
- Errorsシートの1行目には「日付, エラー」というヘッダー項目を入力
以上でシートの準備は完了です。
Google Apps Scriptのプロジェクトファイルを作成する
Chatworkのメッセージ履歴をスプレッドシートに記録していくには、Google Apps Script(GAS)というGoogleのサービスで利用できるスクリプト言語を使用します。
こちらはJavaScriptベースのプログラミング言語です。
GASを使用するにはまずプロジェクトファイルを作成します。
- スプレッドシートのメニューから拡張機能を選択
- Apps Scriptを選択
- 無題のプロジェクトが作成されるので、任意の名前をつける
これでGASを書く準備は整いました。
Chatworkのトーク履歴をGoogleスプレッドシートに記録するGAS
ここからが本題です。ほぼそのままコピペできる「Chatworkのトーク履歴をGoogleスプレッドシートに記録するGAS」を紹介します。
ちなみに、このスクリプトの詳しい解説は、先にあげた「Chatworkのメッセージをスプレッドシートに保存しよう」で紹介しています。中身に興味がある方はそちらの記事をお読みください。
/* Chatworkの新着メッセージをスプレッドシートに書き出す関数 */
function chatworkMessagesLogger() {
// アクティブなスプレッドシートを取得
const ss = SpreadsheetApp.getActiveSpreadsheet();
// トークン・ルームID
const token = 'APIトークンをここに記入';
const roomId = 'ルームIDをここに記入';
const url = `https://api.chatwork.com/v2/rooms/${roomId}/messages?force=0`;
const params = {
method: 'GET',
headers: {
'Accept': 'application/json',
'x-chatworktoken': token
}
};
const response = UrlFetchApp.fetch(url, params);
const json = response.getContentText();
// 新着メッセージがない場合は処理終了
if (json === '') { return };
// エラーの場合はエーラ履歴シートにログを残して終了
if (json.errors) {
const errors = json.errors.join(); // 配列の要素を連結
const now = new Date(); // 記録日時
const sheetErrors = ss.getSheetByName('Errors');
sheetErrors.appendRow(now, errors); // エラーログを追加
return
};
// 新着メッセージがある場合のみ以下の処理が実行される
const aryMessage = JSON.parse(json); // メッセージオブジェクトを格納した配列
// プロパティ名を指定して各値を取り出した新しい二次元配列を生成
const ary2D = aryMessage.map(message => {
// 更新時間が0(未更新)の場合は空文字列にそれ以外はUNIX時間をDateオブジェクトに
let updateTime = new Date(message.update_time * 1000);
if (message.update_time === 0) { updateTime = '' };
return [
message.message_id,
message.account.account_id,
message.account.name,
'=IMAGE("' + message.account.avatar_image_url + '",4,40,40)',
message.body,
new Date(message.send_time * 1000), // UNIX時間の単位は「秒」Dateオブジェクトは「ミリ秒」単位 *1000
updateTime
];
});
// アクティブなスプレッドシートのシート名'Log'のシートを取得して二次元配列の値をシートの最終行に追加する
const sheetLog = ss.getSheetByName('Log');
const lastRow = sheetLog.getLastRow(); // 最終行番号を取得
const range = sheetLog.getRange(lastRow + 1, 1, ary2D.length, ary2D[0].length);
range.setValues(ary2D);
}
このスクリプトを先程作成したプロジェクトファイルにコピペします。
まず、初期状態で表示されているfunction… という部分を削除して真っ白にします。そして上記のスクリプトを貼り付けます。
保存は、今どきの若い人には何を意味するアイコンかわからないと言われる…保存アイコンをクリックしてください。
APIトークンとルームIDをスクリプトに記入する
!!注意!!
APIトークンとルームIDが第3者に知られてしまうと、自分のアカウントが乗っ取りにあったのと同じ状況になります。このスプレッドシート自体を誰かに共有した場合もスクリプトに直接入力したトークンなどが知られてしまうので、後述するようにトークンを隠すか、別のスプレッドシート(スクリプトは記入されていない)からIMPORTRANGE関数でメッセージ履歴を呼び出して、そのシートを共有するなどしてください。
今回は、とにかく簡単にメッセージのバックアップを取ることを目的にしますので、ひとまずスクリプト内に直接入力します。
スクリプトの8-9行目の部分のシングルクォーテーションで囲われた部分に先程確認したAPIトークンとルームIDを入力します。
const token = 'APIトークンをここに記入';
const roomId = 'ルームIDをここに記入';
トークンとルームIDを入力したら保存ボタンを忘れずに。Windowsのctrl + s や Macの⌘ + s のショートカットキーでも保存できます。
スクリプトを実行してみる(初回)
いよいよスクリプトを実行します。スクリプトエディター(GASを編集する画面)のメニューで今回作成したchatworkMessagesLoggerという関数が選択されていることを確認して左側の実行ボタンを押します。
スクリプトを初めて実行すると権限確認のためのアラートが表示されます。ここを画面の指示に従ってスクリプトを実行できるように権限を設定します。
コードのコピペとトークン及びルームIDの転記に間違いがなければスクリプトエディターの下の実行ログのウインドウに実行完了の表示が出るはずです。
エラーなく実行が完了するとLogシートにメッセージが取得できているはずです。
トリガーで定期実行する
このままでは、手動でこのchatworkMessagesLoggerという関数を実行した時にしかメッセージが取得されませんので、GASのトリガー機能を使って定期実行するように設定します。
スクリプトエディタの左側にあるメニューの時計マークをクリックするとトリガーの設定が可能になります。トリガーメニューの右下にあるトリガーを追加をクリックします。
実行する関数を選択の部分でchatworkMessagesLoggerが選択されていることを確認の上、イベントのソースを選択の欄で「スプレッドシートから」を「時間主導型」に変更します。
時間主導型のトリガーは、分、時間、日、週、月という刻みで実行タイミングが設定できます。分刻みでメッセージをバックアップしなければならない…みたいなことはないと思うので1日1回バックアップとる運用で良いかなと思います。
ちなみに、個人的にはそこまでメッセージのやりとりをしないので週1バックアップにしています。
日付ベースの場合は、実行時間をChatworkがメンテナンスとかしなさそう&まだユーザーが稼働しなさそうな時刻に設定するのがオススメです。
Chatworkのトーク履歴をGoogleスプレッドシートに記録するGASは一応完成です。
トークンをどう秘匿するか
先にも書いたように、このシートそのものを共有してしまうと自分自身のトークンが流出してしまう懸念があります。Chatworkのメッセージ履歴の記録は、士業の方が無料ユーザーのクライアントさんにメッセージ履歴を共有したいというニーズだと思うので、トークンを流出させずにこのシートの内容を共有する方法を考えないといけません。
方法論としては
- APIトークンをユーザープロパティに格納する
- 別のスプレッドシートからIMPORTRANGE関数で元のシートの情報を呼び出す
- クライアント自身でこの記事のスプレッドシートとスクリプトを作成してもらう
が考えられます。
プロパティサービスを利用する
このプロパティサービスとは、スクリプト内に直書きしたくない情報などを別の場所に格納する機能のことです。今回は、煩雑になるため詳しく説明はしません。プロパティサービスを利用する場合はユーザープロパティ(設定したユーザーしか読み出せない)を使用してトークンを格納するのがオススメです。
プロパティサービスについて参考となる記事
【初心者向けGAS】プロパティストアの概要とスクリプトプロパティの入力方法
【GAS】プロパティサービスについてまとめる
Google Apps Scriptで使う情報はプロパティを利用しよう【GAS】
別シートからIMPORTRANGE関数を利用する
取り急ぎオススメなのはこの方法です。 クライアントとの共有用に別のシートをもう1枚作成し、そのシートからメッセージ履歴を取得したシートを呼び出して表示させると言う方法です。
IMPORTRANGE関数に関しては検索すれば沢山解説記事があるので、こちらも詳細は割愛します!
取り急ぎ別のスプレッドシートの任意のシートのA1セルに以下を入力すると呼び出せるはずです。
※ message_idとaccount_idは多くのクライアントユーザーには不要な情報なので表示から除外しました。
=IMPORTRANGE("メッセージ履歴を取得したスプレッドシートのURL","Log!C:F")
クライアント自身でこの記事のスプレッドシートとスクリプトを作成してもらう
最終手段はこれです。クライアント自身が見れるルームやメッセージしか取得できないので、変なメッセージが漏洩してしまうということはありません。セットアップが面倒ですが…
おわりに
ということでコピペでOKな「Chatworkのメッセージをスプレッドシートに保存しよう」のまとめ記事をお送りしました。
Chatworkの過去のメッセージなんて見ないよ…って思っていたのですが、40日はやっぱり短いですよね。せめて●lack並に90日にしてほしかった。
どなたかのお役に立てれば幸いです。
もし実際に活用された方がいらっしゃったらTwitterなどで感想いただけると嬉しいです。
シリーズ目次
- Chatworkのメッセージをスプレッドシートに保存しよう その1 – 最新の100件のメッセージを書き出す
- Chatworkのメッセージをスプレッドシートに保存しよう その2 – 表示を整え新着メッセージのみを定期的に追加する
- 【まとめ】コピペでOK!?Chatworkのトーク履歴をGoogleスプレッドシートに記録するGAS
Google Apps Scriptを勉強したい方へ
この記事を見て、GASを勉強したいなと思われた方はぜひノンプログラマーのためのスキルアップ研究会(通称 ノンプロ研)にご参加ください。私も未経験からこの学習コミュニティに参加し、講座を受講したことでGASが書けるようになりました。
学習コミュニティ「ノンプログラマーのためのスキルアップ研究会」
挫折しがちなプログラミングの学習も、コミュニティの力で継続できます。ノンプロ研でお待ちしております!
Amazon欲しい物リスト公開しています。
開発者のモチベーションアップのためにAmazon欲しい物リストを公開しております。役に立ったよ!という方の感謝の気持ちで何かいただけるのであれば嬉しいです笑