แจก Script ระบบจัดการ Google Calendar ผ่าน Line

อยากจะจัดการอีเวนต์ใน Google Calendar แต่ต้องสลับแอปไปมาให้วุ่นวาย?
หรืออยากให้ทีมงานในกลุ่ม LINE เห็นตารางงานประจำวันใน Google Calendar ได้โดยอัตโนมัติทุกเช้า?
โพสนี้ผมจะมาแจก Script ที่สามารถเชื่อมต่อ Google Calendar เข้ากับ LINE ได้อย่างง่ายดาย จัดการทุกอย่างได้ผ่านแอป LINE ที่ใช้งานอยู่เป็นประจำ!

ประโยชน์ของ Script นี้

  • รับการแจ้งเตือนตารางงานประจำวันใน LINE: ระบบจะแจ้งให้ทราบว่าวันนี้มีอีเวนต์หรืองานอะไรบ้างในตอนเช้า
  • เพิ่ม/ลบอีเวนต์ผ่าน LINE ได้ทันที: ไม่ต้องเปิดแอป Google Calendar สามารถพิมพ์คำสั่งใน LINE เพื่อสร้างหรืองานได้เลย
  • ทีมงานรับทราบข้อมูลพร้อมกัน: หากใช้ในกลุ่ม LINE สมาชิกในกลุ่มจะเห็นการเพิ่มหรือลบอีเวนต์ใหม่ๆ ได้ทันที

สิ่งที่ต้องเตรียมก่อนเริ่มต้นปรับแต่ง Script

  1. Calendar ของ Google Calendar ที่ต้องการจะเชื่อมกับระบบใน Script
  2. บัญชี LINE Official Account (LINE OA)

หลักจากที่เตรียมทุกอย่างพร้อมแล้วให้เราทำการสร้าง Script ใหม่ขึ้นมาใน Google App Script โดยการพิมพ์ script.new ที่ url ของ browser ก็จะพาทุกคนมาที่หน้านี้

Screenshot

หลักจากนั้นให้ทำการ copy script ด้านล่างนี้ไปวางที่หน้า Google App Script ของเราได้ทันที
โดย Script นี้จะเป็น script ที่ช่วยให้เราสามารถทำการเพิ่ม ลบ Event ในปฏิทิน Google Calendar ของเราผ่านทางไลน์

// === CONFIG ===
const LINE_TOKEN = 'YOUR_LINE_CHANNEL_ACCESS_TOKEN';
const LINE_USER_ID = 'YOUR_LINE_USER_ID'; // สำหรับ push message (กรณีส่งสรุป event รายวัน)
const CALENDAR_ID = 'primary'; // ใช้ 'primary' หรือ calendar ID เฉพาะก็ได้

// === MAIN ===
function doPost(e) {
  const data = JSON.parse(e.postData.contents);
  const message = data.events[0].message.text.trim();

  // ✅ ถ้าไม่ขึ้นต้นด้วย "สร้าง :" หรือ "ลบ :" → ไม่ตอบอะไรเลย
  if (!message.startsWith("สร้าง :") && !message.startsWith("ลบ :")) return;

  const calendar = CalendarApp.getCalendarById(CALENDAR_ID);

  // === 🗑 ลบ Event ===
  if (message.startsWith("ลบ :")) {
    const deleteName = message.match(/ลบ ?: ?(.*)/)?.[1]?.trim();
    if (!deleteName) return;

    const today = new Date();
    const next7 = new Date();
    next7.setDate(today.getDate() + 7);
    const events = calendar.getEvents(today, next7);
    const eventToDelete = events.find(e => e.getTitle() === deleteName);

    if (eventToDelete) {
      eventToDelete.deleteEvent();
      replyToLine(data, `🗑️ ลบ Event "${deleteName}" เรียบร้อยแล้ว`);
    } else {
      replyToLine(data, `⚠️ ไม่พบ Event ชื่อ "${deleteName}" ใน 7 วันข้างหน้า`);
    }
    return;
  }

  // === ✅ สร้าง Event ===
  const name = message.match(/สร้าง ?: ?(.*)/)?.[1]?.trim();
  const timeOnly = message.match(/(?:^|\n)เวลา ?: ?([0-9]{4}-[0-9]{2}-[0-9]{2})/)?.[1]?.trim();
  const start = message.match(/(?:^|\n)เวลาเริ่ม ?: ?(.*)/)?.[1]?.trim();
  const end = message.match(/(?:^|\n)เวลาจบ ?: ?(.*)/)?.[1]?.trim();

  if (!name) {
    replyToLine(data, "⚠️ กรุณาระบุชื่อ Event เช่น:\nสร้าง : ไปส่งของ");
    return;
  }

  if (start && end) {
    // ➕ แบบมีเวลา
    const startDate = new Date(start);
    const endDate = new Date(end);
    if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
      replyToLine(data, "⚠️ เวลาไม่ถูกต้อง กรุณาใช้:\nเวลาเริ่ม : yyyy-mm-dd HH:mm\nเวลาจบ : yyyy-mm-dd HH:mm");
      return;
    }
    calendar.createEvent(name, startDate, endDate);
    replyToLine(data, `✅ สร้าง Event "${name}" เวลา ${formatTime(startDate)} - ${formatTime(endDate)} เรียบร้อยแล้ว`);
    return;
  }

  if (timeOnly) {
    // ➕ แบบทั้งวันในวันที่ระบุ
    const date = new Date(timeOnly);
    if (isNaN(date.getTime())) {
      replyToLine(data, "⚠️ วันที่ไม่ถูกต้อง โปรดใช้รูปแบบ: เวลา : yyyy-mm-dd");
      return;
    }
    calendar.createAllDayEvent(name, date);
    replyToLine(data, `✅ สร้าง Event "${name}" แบบทั้งวันในวันที่ ${formatDate(date)} เรียบร้อยแล้ว`);
    return;
  }

  // ➕ แบบทั้งวันวันนี้
  calendar.createAllDayEvent(name, new Date());
  replyToLine(data, `✅ สร้าง Event "${name}" แบบทั้งวันในวันนี้เรียบร้อยแล้ว`);
}

// === 🔁 ส่งข้อความกลับ LINE ===
function replyToLine(data, msg) {
  const replyToken = data.events[0].replyToken;
  const payload = {
    replyToken: replyToken,
    messages: [{ type: 'text', text: msg }]
  };

  UrlFetchApp.fetch('https://api.line.me/v2/bot/message/reply', {
    method: 'post',
    contentType: 'application/json',
    headers: {
      Authorization: 'Bearer ' + LINE_TOKEN
    },
    payload: JSON.stringify(payload)
  });
}

// === 🕓 ฟอร์แมตเวลา/วันที่ ===
function formatTime(date) {
  return Utilities.formatDate(date, "Asia/Bangkok", "HH:mm");
}

function formatDate(date) {
  return Utilities.formatDate(date, "Asia/Bangkok", "yyyy-MM-dd");
}

หลังจากนั้นเราจำเป็นที่จะต้องเปลี่ยนค่า 3 ค่าด้านบนสุดก่อนดังต่อไปนี้

  1. ค่า LINE_TOKEN ให้เราใส่ค่า Channel Access token จากหน้า Line Developer
  2. ค่า LINE_USER_ID เป็น id ของกลุ่มหรือ user line ที่จะให้ script ส่งข้อความแจ้งเตือนไป โดยเราสามารถนำ link webhook จาก webhook.site ไปผูกใน lineOA แล้วให้ใช้ user ที่เราต้องการจะส่งข้อมูลทักเข้าไปเพื่อแสดง userID ของ user นั้นๆได้เลย
  3. ค่า CALENDAR_ID ให้เราไปที่ Google Calendar ที่เพิ่งสร้าง คลิกจุด 3 จุดข้างชื่อปฏิทิน เลือก “การตั้งค่าและการแชร์” เลื่อนลงมาจะเจอ “รหัสปฏิทิน”

หลังจากที่เราเปลี่ยนค่าเรียบร้อยแล้วให้คลิกที่ “การทำให้ใช้งานได้” และเลือก “การทำให้ใช้งานได้รายการใหม่” เพื่อทำการสร้าง link สำหรับนำไปผูกใน webhook ในหน้า Line Developer ได้เลย

Screenshot

แค่นี้ระบบของเราก็สามารถใช้งานได้แล้ว โดยเคสในการใช้งานสามารถสั่งงานผ่านไลน์ของเราได้ดังต่อไปนี้เลย

รูปแบบตัวอย่างข้อความใน LINE
✅ ทั้งวันวันนี้สร้าง : เข้าร้านเร็ว
✅ ทั้งวันวันที่กำหนดสร้าง : ไปส่งของ
เวลา : 2025-05-22
✅ มีเวลาเริ่ม/จบสร้าง : ประชุมทีม
เวลาเริ่ม : 2025-05-22 13:00
เวลาจบ : 2025-05-22 14:30
🗑 ลบ Eventลบ : ประชุมทีม

ส่วนในกรณีต้องให้ระบุแจ้งเตือน Event ประจำวันเราสามารถทำการเพิ่ม script ดังต่อไปนี้ต่อในหน้า script ของเราได้ทันที

function sendDailyEvents() {
  const calendar = CalendarApp.getCalendarById(CALENDAR_ID);
  const today = new Date();
  const events = calendar.getEventsForDay(today);

  if (events.length === 0) {
    sendLinePush("📅 วันนี้ไม่มี Event นะครับ");
    return;
  }

  let msg = "📅 Event วันนี้:\n";
  events.forEach(event => {
    msg += `\n🕒 ${event.getTitle()}\nเวลา: ${formatTime(event.getStartTime())} - ${formatTime(event.getEndTime())}`;
  });

  sendLinePush(msg);
}

function sendLinePush(msg) {
  const payload = {
    to: LINE_USER_ID,
    messages: [{ type: 'text', text: msg }]
  };

  UrlFetchApp.fetch('https://api.line.me/v2/bot/message/push', {
    method: 'post',
    contentType: 'application/json',
    headers: {
      Authorization: 'Bearer ' + LINE_TOKEN
    },
    payload: JSON.stringify(payload)
  });
}

หลังจากนั้นเราก็สามารถทำการ Run function sendDailyEvents เพื่อทำการส่งข้อมูล event ทั้งหมดในวันนี้เข้า line ได้ทันที

โดยถ้าต้องการให้ระบบ Google App Script ทำการ run function sendDailyEvents ให้เราแบบอัตโนมัติ ก็ให้เราทำการสร้าง trigger ได้ที่บริเวณนี้ของหน้า Google App Script

Screenshot

หวังว่าโพสต์นี้จะเป็นประโยชน์นะครับ ลองนำไปตั้งค่าและใช้งานกันดู!

โดยถ้าต้องการดูวิธีการทำระบบจัดการ Google Calendar ผ่าน Line แบบ step by step ก็สามารถดูได้ที่คลิปดังต่อไปนี้เลยครับ

และถ้าอยากรู้ว่า script แบบนี้สร้างขึ้นมาได้ยังไงโดยใช้ AI ก็สามารถสมัครสมาชิกและดูคลิปต่อไปนี้ได้เลยครับ

💳 ชอบคลิปที่ช่วยเพิ่มประสิทธิภาพการทำงานแบบนี้สามารถสมัครสมาชิกช่องได้ที่ 
https://www.youtube.com/channel/UChxmhkD8uSSzUOkfMO_p5oQ/join

🎥 อุปกรณ์ที่ผมใช้

กล้อง Sony ZV-E10 kit 16-50mm
Mouse Logitech MX Master 3s
MacBook Air M2
ไมค์ wireless Saramonic Blink 500
เก้าอี้ Anda Seat X-Air Pro Ergonomic Gaming Chair
แขนจับจอ Anda Seat Stealth A6L Ergonomic Monitor Arm
ไมโครโฟน AKG Lyra
ไฟส่องหน้าจอ Xiaomi Light Bar

2 Comments

  1. I tried to run function sendDailyEvents() { and function sendLinePush(msg) {, but when i click run, it show error as below:

    Exception: Request failed for https://api.line.me returned code 401. Truncated server response: {“message”:”Authentication failed. Confirm that the access token in the authorization header is valid.”} (use muteHttpExceptions option to examine full response)
    sendLinePush @ Code.gs:128

    I dont know how to fix, please kindly help suggest.

Leave a Reply to Kelvin Cancel reply

Your email address will not be published. Required fields are marked *