0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GAS で席替えをするLINEBotを作成した

Last updated at Posted at 2022-05-03

成果物

LINE上で「席替え!」とチャットすると、席替え結果を返すBot。
席替えは毎日実施される。
アイコンは拾い物。
Thanks!(https://iconbu.com/illust/4427)
席替え成果.jpg

背景

会社の研修中、交流のため「毎回同じところに座らないように。」とのことで作成。

もう少し詳しく

初めは、LINEのあみだくじで行っていたが、あみだくじの作成が面倒に。
LINEBOTのが楽?!と思いつき、作成。
事前に同期に相談していなかったが、スムーズに導入してもらえる。

作成時間

前日の晩に、「(LINEのあみだくじが)面倒くさい」と聞き、翌朝作成。
作業時間。1時間強。(褒めたい)

以前、飲食店向けのLINEBotを作成していたこともあり、早くできた。
GASはお仕事で少しやっていたので問題なし。

シート

シート名 内容
name 1行目、席替えしたい人の名前。
recode 席替えの履歴。A列、日付。B~列、席替え結果。
log エラーの記録。

この3つのシートを作ればOK。

やり方

後日追記
1.スプレッドシートを準備する。
2.名前を記入する。
3.ソースコードをコピペする。

スプレッドシートから「拡張機能」>「Apps Script」>コピペ。>Ctrl + s で保存。
4.「create」をトリガーで「毎日」「9時」に実行する。
左側のバーから「トリガー」>「トリガーを追加」

※このままでは動きません。LINE、トークンについてはまた。

ソースコード

全体

関数名 説明
create スプレッドシートから名前を取得して席替え。プロパティに保存。トリガーで毎朝9時に実施する。
getMessages プロパティの席替えリストをLINEメッセージに変換し返却。
doPost LINEからメッセージを受信すると起動。「席替え!」を受信すると席替え内容を返す。

工夫

BOT動作時に、シートから直接取得すると時間がかかるので、propertyServiceを利用して時短。

コード.js
/**
 * @description スプレッドシートから名前を取得して席替え。プロパティに保存。トリガーで毎朝9時に実施する。
 */
function create() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const [names] = ss.getSheetByName('name').getDataRange().getValues();
  /**
   * @description 席替え参加者リスト
   * @param {string[]}
   */
  console.log(names)
  //配列をランダムに入れ替える
  for (let i = names.length - 1; i > 0; i--) {
    let r = Math.floor(Math.random() * (i + 1));
    let tmp = names[i]
    names[i] = names[r]
    names[r] = tmp
  }
  console.log(names)
  const d = new Date()
  d.setDate(d.getDate() + 1)
  console.log(d)

  //明日の日付とともにシートに保存する。
  const date = Utilities.formatDate(d, Session.getScriptTimeZone(), "yyyy/MM/dd")
  const values = [[date, ...names]]
  const sh = ss.getSheetByName('recode')
  const lr = sh.getLastRow();//スプレッドシートの最終行を取得
  sh.getRange(lr + 1, 1, values.length, values[0].length).setValues(values);//貼付

  //データをプロパティに保存する
  const json = JSON.stringify(values);
  PropertiesService.getScriptProperties().setProperty('seki', json);
}
/**
 * @description プロパティの席替えリストをLINEメッセージに変換し返却。
 */
function getMessages() {
  //プロパティから名前のランダムリスト+日付を取得
  const json = PropertiesService.getScriptProperties().getProperty('seki');
  const [values] = JSON.parse(json);
  const v = values.reduce((a, x, i) => {
    if(i ===0) return [...a, x]
    const nn = i+". " +x
    return[...a, nn]
  }, [])
  //ラインに投下される形
  const text = v.join('\n');
  const messages = [
    {
      type: "text",
      text: "せきがえんぬ~"
    },
    {
      type: "text",
      text,
    }]
  console.log(messages)
  return messages;
}
/**
 * @description LINEからメッセージを受信すると起動。「席替え!」を受信すると席替え内容を返す。
 */
function doPost(e) {
  try {
    const event = JSON.parse(e.postData.contents).events[0];
    console.log(event)
    if(event["type"] !== 'message' || event["message"]["type"] !== "text"){
      return;
    }
    const sendedText = event["message"]["text"]; //送信テキスト
    console.log(sendedText)
    const t = ["席替え!", "せきがえ!"]
    if(!t.includes(sendedText)) {
      return;
    }
    const url = 'https://api.line.me/v2/bot/message/reply';
    const ACCESS_TOKEN = PropertiesService.getScriptProperties().getProperty('token');
    if (!ACCESS_TOKEN) {
      console.error('no token')
      return;
    }
    const messages = getMessages();
    const replyToken = event["replyToken"];
    const options = {
      "headers": {
        "Content-Type": "application/json; charset=UTF-8",
        "Authorization": 'Bearer ' + ACCESS_TOKEN
      },
      "method": "post",
      "payload": JSON.stringify({ replyToken, messages }),
      muteHttpExceptions: true
    };
    var response = UrlFetchApp.fetch(url, options);
    if (response.getResponseCode !== 200) {
      console.error("error!")
      return
    }
  } catch (e) {
    console.log(e)
    const s = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('log')
    const lr = s.getLastRow()
    s.getRange(lr + 1, 1).setValue(JSON.stringify(e))
  }
  return ContentService
    .createTextOutput(JSON.stringify({ 'content': 'post ok' }))
    .setMimeType(ContentService.MimeType.JSON);
}


感想

名前順をシャッフルしてくれるので、席替え以外の用途にも使ってもらえました。
嬉しき。

研修中のインフラとして当然のように使われる存在になったので、作ってよかったです。

改善

席を見やすくすることも考えたりしましたが、研修を乗り切ったのでひとまず終了。

参考

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?