弓仲研究室では料理部への出欠について、自作BOTを利用しています。
技術スタックとしてはGAS + Slack APIを使ってます。
毎週月曜9時に、以下のようなメッセージが自動的に送られてきます。
GASはGoogle系サービスに非常に相性がいいので、自分はGmailをGASで監視させて
ChatGPTにメール本文を分析してもらって、予定をGoogleカレンダーに自動登録させています。
(就活などスケジュール管理が大変なときに使いたかった。)
*興味があれば井口まで。
M2 井口
以下のコードをGASに貼り付けてSlack APIからトークンを取得すると送れるようになります。
const SLACK_BOT_TOKEN = ‘xoxb-197************’; // 取得したBot Tokenに置き換えてください
const CHANNEL_ID = ‘C***************’; // メッセージを送信したいチャンネルのIDに置き換えてください
function sendSurveyMessages() {
sendCookClubMessage();
sendDrinkClubMessage();
}
function sendCookClubMessage() {
const cookClubPayload = {
channel: CHANNEL_ID,
text: ‘料理部アンケート’, // メッセージの代替テキスト
blocks: [
{
“type”: “header”,
“text”: {
“type”: “plain_text”,
“text”: “🍳 今週の料理部参加アンケート”,
“emoji”: true
}
},
{
“type”: “divider”
},
{
“type”: “section”,
“text”: {
“type”: “mrkdwn”,
“text”: “*今週の料理部に参加希望の方は火曜昼までにリアクションをお願いします。* (複数可・5つの内、一番多い日で実施)”
}
},
{
“type”: “section”,
“fields”: [
{
“type”: “mrkdwn”,
“text”: “1️⃣ 火曜 夜 (17:30~)”
},
{
“type”: “mrkdwn”,
“text”: “2️⃣ 水曜 昼 (12:00~)”
},
{
“type”: “mrkdwn”,
“text”: “3️⃣ 水曜 夜 (17:30~)”
},
{
“type”: “mrkdwn”,
“text”: “4️⃣ 木曜 昼 (12:00~)”
},
{
“type”: “mrkdwn”,
“text”: “5️⃣ 木曜 夜 (17:30~)”
}
]
},
{
“type”: “context”,
“elements”: [
{
“type”: “mrkdwn”,
“text”: “参加希望の方は対応するリアクションを付けてください!”
}
]
}
]
};
const options = {
method: ‘post’,
contentType: ‘application/json’,
headers: {
‘Authorization’: `Bearer ${SLACK_BOT_TOKEN}`
},
payload: JSON.stringify(cookClubPayload)
};
try {
const response = UrlFetchApp.fetch(‘https://slack.com/api/chat.postMessage’, options);
const responseData = JSON.parse(response.getContentText());
if (!responseData.ok) {
Logger.log(‘Error posting Cook Club message: ‘ + responseData.error);
return;
}
const ts = responseData.ts; // メッセージのタイムスタンプ
const channel = responseData.channel; // チャンネルID
// リアクションを追加(one ~ five)
const cookEmojis = [‘one’, ‘two’, ‘three’, ‘four’, ‘five’];
addReactions(channel, ts, cookEmojis);
} catch (error) {
Logger.log(‘Error posting Cook Club message: ‘ + error.message);
}
}
function sendDrinkClubMessage() {
const drinkClubPayload = {
channel: CHANNEL_ID,
text: ‘お酒部アンケート’, // メッセージの代替テキスト
blocks: [
{
“type”: “header”,
“text”: {
“type”: “plain_text”,
“text”: “🍺 今週のお酒部参加アンケート”,
“emoji”: true
}
},
{
“type”: “divider”
},
{
“type”: “section”,
“text”: {
“type”: “mrkdwn”,
“text”: “*今週のお酒部にも参加希望の方はリアクションをお願いします。* 料理付き・居酒屋の可能性も有り\n6️⃣ 金曜 夜 (17:30~) \n7️⃣ 金曜以外の夜なら参加希望”
}
},
{
“type”: “context”,
“elements”: [
{
“type”: “mrkdwn”,
“text”: “参加希望の方は対応するリアクションを付けてください!”
}
]
}
]
};
const options = {
method: ‘post’,
contentType: ‘application/json’,
headers: {
‘Authorization’: `Bearer ${SLACK_BOT_TOKEN}`
},
payload: JSON.stringify(drinkClubPayload)
};
try {
const response = UrlFetchApp.fetch(‘https://slack.com/api/chat.postMessage’, options);
const responseData = JSON.parse(response.getContentText());
if (!responseData.ok) {
Logger.log(‘Error posting Drink Club message: ‘ + responseData.error);
return;
}
const ts = responseData.ts; // メッセージのタイムスタンプ
const channel = responseData.channel; // チャンネルID
// リアクションを追加(six)
const drinkEmojis = [‘six’, ‘seven’];
addReactions(channel, ts, drinkEmojis);
} catch (error) {
Logger.log(‘Error posting Drink Club message: ‘ + error.message);
}
}
function addReactions(channel, ts, emojis) {
emojis.forEach(function(emoji) {
const reactionPayload = {
name: emoji,
channel: channel,
timestamp: ts
};
const options = {
method: ‘post’,
contentType: ‘application/json’,
headers: {
‘Authorization’: `Bearer ${SLACK_BOT_TOKEN}`
},
payload: JSON.stringify(reactionPayload)
};
try {
const response = UrlFetchApp.fetch(‘https://slack.com/api/reactions.add’, options);
const responseData = JSON.parse(response.getContentText());
if (!responseData.ok) {
Logger.log(`Error adding reaction :${emoji}: – ${responseData.error}`);
} else {
Logger.log(`Added reaction :${emoji}:`);
}
} catch (error) {
Logger.log(`Error adding reaction :${emoji}: – ${error.message}`);
}
// Slackのレート制限を避けるために少し待つ(0.5秒)
Utilities.sleep(500);
});
}