GASを使い、Chatwork(チャットワーク)でほぼ時刻どおりに予約した投稿を送信できる機能をつくりました。
※2019/02/10更新
送信したユーザにも通知が届くよう修正しました(メッセージ送信に self_unread 追加)
※2020/03/10更新
V8ランタイム対応のためコード修正しました。
※2021/3/14更新
古めかしい&わかりにくい記述だったため、全体的にコードを書き換えました。
使い方
スプレッドシートで①日時と②ルームIDと③投稿するメッセージを指定すれば、ほぼ時刻どおりに予約した投稿を送信できます。
GASのトリガ機能を利用し、トリガ実行時点で時刻を過ぎているものを自動で投稿します。指定した時刻どおりではなく、トリガが実行された時刻に投稿されるので、「ほぼ」時刻どおりという表現になっています。
日時は「yyyy/mm/dd hh:mm:ss」という形式で時刻までしっかり指定してください。
ちなみに、「ルームID」というのは、チャットワークのURLにある末尾の数字です。
これをコピペして使用してください。
作り方
1.Googleドライブでスプレッドシートを作成します。
2.上部のメニューから、ツール > スクリプトエディタを開きます。
3.このページの下部にあるGASのコード(全部で90行くらい)をコピペします。
4.コード上の方にあるチャットワークAPIトークンにご自分のトークンを入力して保存します。
(チャットワークAPIトークンの取得方法はこちら。)
5. myFunction を一度実行し、諸々の実行許可をしておきます。
6. トリガを設定します。10分おきくらいがおすすめです。
あとは、スプレッドシートに戻って①日時と②ルームIDと③投稿内容を指定しておくと、定期的なトリガ実行時に予定時刻を過ぎたものが自動で投稿されます。
注意点など
ちなみに、暴走を防ぐため、日付が昨日よりも古い場合は投稿しないようになっています。
投稿済みか否かはD列(投稿日時)に値が入っているかで確認していますので、ここを空欄にすると再び投稿する対象になります。
GASのコード
以下がスクリプトエディタにコピペするコードです。
チャットワークAPIトークンの書き換えをお忘れなく。
/*---- 初期設定ここから ----*/
// チャットワークAPIトークンを設定
var CHATWORK_TOKEN = 'xxxxxxxxxxxxxxxxxxxx';
// 設定用シートのシート名
var SHEETNAME = 'シート1';
/*---- 初期設定ここまで ----*/
// 管理用メニューを追加
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('管理用')
.addItem('いますぐ実行', 'myFunction')
.addToUi();
}
// 予約投稿のメインのファンクション
function myFunction(){
// スプレッドシート読込
const book = SpreadsheetApp.getActiveSpreadsheet();
const sheet = book.getSheetByName(SHEETNAME);
const records = getRecords(sheet);
// シート書き出し配列を定義
const values = [];
// 現在の日時取得
const now = new Date();
const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
// 1行目はフィールド名を挿入
values[0] = [ '日時', 'ルームID', 'メッセージ', '投稿日時' ];
// 内容を2行目以降に追加
for ( let obj of records ) {
// メッセージ送信
if( obj.msg && obj.room_id && obj.sent_date == "" && obj.estimated_date > yesterday && obj.estimated_date < now ){
sendMessage( obj.room_id, obj.msg );
obj.sent_date = now;
}
const line = [ obj.estimated_date, obj.room_id, obj.msg, obj.sent_date ];
values.push( line );
}
// シートをクリア
sheet.clearContents();
// シートに貼付け
sheet.getRange(1,1,values.length,values[0].length).setValues( values );
}
// シートを読み込んでjson形式で返す
function getRecords( sheet ) {
// シートを読み込んで二次元配列を返す
var values = readSheet(sheet);
if( values == false ) return false;
// オブジェクトをつくる
var records = [];
for(var i=0; i<values.length; i++) {
var record = new Object();
record.estimated_date = values[i][0];
record.room_id = values[i][1];
record.msg = values[i][2];
record.sent_date = values[i][3];
records.push(record);
}
return records;
}
// シートを読み込んで二次元配列を返す
function readSheet(sheet){
var lastRow = sheet.getLastRow();
if( lastRow <= 1 ) return false;
var rowIndex = 2;
var colStartIndex = 1;
var colNum = 4;
var range = sheet.getRange(rowIndex, colStartIndex, lastRow, colNum);
var values = range.getValues();
return values;
}
// メッセージ送信
function sendMessage(room_id, body){
var params = {
headers : {"X-ChatWorkToken" : CHATWORK_TOKEN},
method : "post",
payload : {
body : body,
self_unread : "1"
}
};
var url = "https://api.chatwork.com/v2/rooms/" + room_id + "/messages";
UrlFetchApp.fetch(url, params);
}
まとめ
今回はスプレッドシートを使ってチャットワークに予約投稿する機能でした。
お手伝いしている会社さんでは、kintoneで投稿内容を管理して、あらかじめ設定した複数のグループチャットに同時に予約投稿する、ということも実現しています。
よりパワーアップした機能を実装したい方はお問い合わせフォームからご相談ください。
コメント
こんにちは
この一連の詐欺用ですが・・うまくいきません。
作り方の5番目
. myFunction を一度実行し、諸々の実行許可をしておきます。
ここで先に行きません
TypeError: null のメソッド「getSheetByName」を呼び出せません。(行 49、ファイル「コード」)
このようなひょうじになります。
何が原点でしょうか??
ご質問ありがとうございます!
エラーを見る限り、シート名の指定が違うような感じがしますが、いかがでしょうか。
> 6. トリガを設定します。10分おきくらいがおすすめです。
上記の手順まで行い、
スプレッドシートで日時とルームID、投稿内容を指定したのですがmyFunctionを実行すると
“`
https://api.chatwork.com のリクエストに失敗しました(エラー: 401)。サーバー応答の一部: {“errors”:[“Invalid API Token”]}(応答の全文を見るには muteHttpExceptions オプションを使用してください)(行 93、ファイル「コード」)
“`
上記のようなエラーが発生し、うまく動作しません。
解決方法をお教えいただくことは可能でしょうか?
コメントありがとうございます!
Invalid API Token なので、チャットワークのAPIトークンが無効というエラーですね。
そもそもAPIトークンのコピペで間違っているか、もしくは送信しようとしているチャットルームに送信する権限がないアカウントのトークンを使っている可能性が考えられるかと思います。
ご確認ください。
こんにちは。
教えてください。
このコードはスプレッドシートからチャットワークへメッセージを送るというプログラムですが
当社ではスプレッドシートからgoogle chatへメッセージを予約投稿したいと思っています。
chat側の設定で
webhook→チャットルームのURLを取得しましたがこれをどう置き換えれば良いのかわかりません。
このプログラムが使えたら万能かと思います。
教えていただけないでしょうか?
a-fujiさま
回答が大変遅くなり申し訳ございません。
Google Chatは利用したことがないのですが、こちらのページのように書き換えていただくと使用できるかと思います。
https://webree.jp/article/gas-hangoutchat/
ご確認ください。
こちらのコードを使用したのですが、無事使用できました。
ただ、定期的(1ヶ月周期くらい)にシート1に記載している
内容がすべて消える現象が発生しています。
これは何が原因になっているかわかりますでしょうか。
コメントありがとうございます!
// シートをクリア
sheet.clearContents();
と
// シートに貼付け
sheet.getRange(1,1,values.length,values[0].length).setValues( values );
の間でエラーが発生するとシートが消えたままの状態で終了してしまうのが要因かと思います。
未検証ですが、
// シートをクリア
sheet.clearContents();
を
// シートに貼付け
sheet.getRange(1,1,values.length,values[0].length).setValues( values );
のすぐ上に移動してあげると防止できるかもしれません。
お試しいただければと思います。
ありがとうございます。
こちらのコードを使用しています。
5分ごとにトリガーを引いているのですが、この前1度だけ
投稿予定日前にトリガーが止まってしまい、投稿できていない
現象が起こりました。こちらはなにが原因となっているかわかりますでしょうか。
コメントありがとうございます!
トリガーが止まってしまったというのは、実行がエラーで失敗してしまったということでしょうか。
エラーのメッセージやログなどがあるとヒントがあるかもしれません。
https://script.google.com/home/triggers を開き、該当するトリガーの「失敗した実行」のログを確認することができます。
ご確認いただけると幸いです。
はじめまして。こちらのコードを使わせていただこうと、コードを全て貼り付けたのですが、下記のエラーが出ております。
何が原因かわかりますでしょうか?
TypeError: json.forEach is not a function
myFunction @ 無題.gs:34
34行目は下記の記述です。
json.forEach(function(obj) {
// メッセージ送信
if( obj.msg && obj.room_id && obj.sent_date == “” && obj.estimated_date > yesterday && obj.estimated_date < now ){
sendMessage( obj.room_id, obj.msg );
obj.sent_date = now;
}
var line = [ obj.estimated_date, obj.room_id, obj.msg, obj.sent_date ];
values.push( line );
});
ゆみさま
コメントありがとうございます!
返信遅くなりすみません。。
事象を再現できなかったのですが、本日コードを全面的に手直ししましたので、再度チャレンジしていただけると幸いです。
よろしくお願いします!
いきなりのご質問申し訳ございません。
順番通り設定し、トリガーも実行されているのですが
メッセージが届かないのですが要因としては
どのようなものがありますでしょうか?よろしくお願いいたします。
ゆうたろうさま
コメントありがとうございます!
返信遅くなりすみません。。
> メッセージが届かない
原因としてはスプレッドシート側の問題が考えられます。
・A列の日時が正しく入っていない
・A列の日時が昨日より前
・B列のルームIDが正しく入っていない
・D列の投稿日時に何か入力されている
なお、本日コードを全面的に手直ししましたので、再度チャレンジしていただけると幸いです。
よろしくお願いします!