+55

Viết một ứng dụng Chat Bot nhắc lịch học chưa bao giờ dễ dàng đến thế với Google Script

Tình huống

Ngày trước khi còn học cấp 3, mình hay có thói quen nhớ thời khóa biểu, tuy nhiên khi lên đại học thì thói quen đó không còn nữa, một phần vì thời khóa biểu ở đại học có cơ số thứ cần để nhớ (mã môn, tên môn, phòng học, blabla ...), cũng một phần vì lười nữa 😂.Vì vậy mà mình rất thường xuyên quên lịch học, đôi khi còn giật mình không biết là hôm nay có phải đi học không.

Thế rồi mình nảy ra ý định viết một con Chat Bot nhắc lịch học chạy hàng ngày để không phải bận tâm hôm nay học môn gì nữa.Tuy nhiên khi ấy lập trình cũng chưa thạo, biết bập bẹ ít javascript thôi, nên việc viết một con ChatBot rồi deploy lên server là một điều mà mình không thực sự nghĩ đến. Trong số các pro trong lớp thì có một cậu bạn viết bằng Google Script đồng thời cũng demo luôn cho mình cách hoạt động, thế là mình ngộ ra bao nhiêu chân lý, cuối cùng tìm hiểu và đã làm được 👏👏

Giật tít vậy thôi, chứ thật ra Chat Bot của mình chỉ là một function viết bằng Google Script thôi 😂. Chúng ta cùng tìm hiểu xem Google Script là gì và vì sao lại có thể viết được ChatBot với nó nhé :v


Google Script là gì?

Google Script - đọc qua cái tên thì ta cũng có thể mường tượng được chức năng của nó: là 1 ngôn ngữ lập trình dựa trên Javascript với trình biên tập, biên dịch đều nằm trên máy chủ của Google. Với công cụ này bạn có thể lập trình để thao tác, can thiệp trực tiếp đến các dịch vụ của Google. Ngoài ra còn cơ số các chức năng hay ho khác nữa, trong số đó thì có việc thực thi một function với thời gian nhất định trong một ngày, mình đã lợi dụng điểm này để đẩy thông báo lịch học.


Bắt đầu viết code thôi

Giao diện của Google App Script sẽ trông như thế này Nhấn vào nút Dự án mới để tiến hành viết Code

Ban đầu tất nhiên là phải xây dựng database cho con Bot rồi. Ở đây mình sử dụng google sheet để làm database.

Nội dung của sheet này như sau: Vì đây là thời khóa biểu học kì một của mình nên chỉ có từ tháng 8 đến tháng 12 thôi.

Có database rồi vậy làm thế nào để có thể đọc được dữ liệu từ sheet đây? Đây chính là lúc phát huy thế mạnh của Google Script. Chúng ta có thể đọc file sheet với function sau

SpreadsheetApp.openById(file_tkb)

Các bạn có thể xem chi tiết tại đây https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app

Trong đó file_tkbid của sheet database nó được lấy như trong hình ở bên dưới


Tiếp theo chúng ta sẽ đi xây dựng logic đọc sheet để có thể lấy đúng dữ liệu mong muốn:

  var today = new Date();
  var first = new Date(today.getFullYear(), 6, 29);
  var theDay = Math.round(((today - first) / (1000 * 60 * 60 * 24)) + .5, 0);

Ở đoạn code trên mình lấy ra ngày hiện tại (today), ngày đầu tiên của tuần đầu tiên học kì mới (first ở đây là ngày 29 tháng 7), sau đó tính xem ngày hôm nay cách ngày đầu tiên đi học bao nhiêu ngày (theDay).

Tiếp theo lần lượt tạo ra các biến sau

  var week_1 = theDay/7;
  var week_mod = theDay%7;
  var week_col;
  var week_row;
  var message;

Trong đó:

  1. Nếu week_mod == 0 || week_mod == 6 thì ngày hôm nay là cuối tuần gán message = "Hôm nay là cuối tuần chịu khó tập thể dục đi";
  2. Ngược lại ta có:
   week_col = parseInt(week_1)+1;
   week_row = week_mod;
   var real_col = week_col+2;
   var real_row = ((week_row-1)*3+2);

Ví dụ cho dễ hiểu một chút:

Giả sử hôm nay là ngày 20/12/2019 thì ta có theDay = 145, week_mod = 5 vậy có nghĩa là thứ 6. real_col = 23 ; real_row = 14 chúng ta sẽ bắt đầu lấy dât trong sheet ở cột 23, dòng 14.


Để lấy data mình sử dụng đoạn code như sau:

    var file_tkb = YOUR_SHEET_ID;
    var ss = SpreadsheetApp.openById(file_tkb);
    var url = ss.getUrl();
    var a = ss.getSheets()[0].getSheetValues(real_row+1, real_col, 1, 1);
    var study_code = a[0][0];

Khi đã có vị trí của data trong sheet thì lấy dữ liệu ra bằng function getSheetValues, các bạn có thể xem chi tiết tại đây nhé https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet Ở đây dữ liệu trả về là một mảng 2 chiều, ta thu được study_code = a[0][0], đây chính là mã môn học mà chúng ta cần.


Tạo từ điển tương ứng cho mã môn học vừa nhận được

  var DICTIONARY = {
    "AT6": "An toàn điện toán đám mây",
    "TM5": "Chứng thực điện tử",
    "TM6": "Phòng chống và điều tra tội phạm máy tính",
    "TM7": "An toàn Internet & TM điện tử",
    "AT5": "Quản trị an toàn hệ thống"
  }

Vậy là đã có đủ thông tin để gửi tin nhắn rồi format lại message gửi đi một chút cho hợp lý

if(study_code != "") {
 var study_name = DICTIONARY[study_code];
 if (study_name == undefined) {
   message = "Opps!!!\nLát nữa cậu phải học môn có mã là "+ study_code +" từ 18h đến 21h đấy nhé!!";
   message = message + "\nVui lòng update lại từ điển để mình có thể biết được tên môn";
   message = message + "\nNếu mã môn trên là sai, hãy xem lại thời khóa biểu tại: "+ url;
 } else {
   message = "Hê lô mai phen :))\nLát nữa cậu phải học môn "+ study_name + " từ 18h đến 21h đấy nhé!!";
 }
} else {
 message = "Hôm nay cậu được nghỉ đấy (tunghoa)";
}
if (week_mod == 3) {
 message = message + "\nHôm nay cũng là thứ 4, 21h đi đá bóng nhé";
}

Tiếp theo là bước gửi tin nhắn với message ở trên. Ở đây mình sử dụng Chatwork, Messenger Facebook, Telegram để nhận tin nhắn thông báo.

Gửi tin nhắn về Chatwork

Để có thể gửi tin nhắn về chatwork thì trước tiên chúng ta phải có API_KEY của Chatwork. Mình đã đọc document của chatwork thì thấy để có thể mention một người vào tin nhắn thì phải sử dụng webhook, tuy nhiên function của mình đang không hoạt động theo cơ chế này, vì thế mà mình sử dụng một mẹo nhỏ như sau:

function send_to_chatwork(textMessage) {
  var room_id = "170443428"
  var API_TOKEN = YOUR_API_CHATWORK
  var baseText = "[toall] Boss \n" + textMessage //private user [To:3797875]
  var headers = {
    "X-ChatWorkToken": API_TOKEN
  }
  var payload = {
    "body": baseText
  }
  var options = {
    "method": "post",
    "headers": headers,
    "payload": payload,
    "muteHttpExceptions": true
  }
  UrlFetchApp.fetch("https://api.chatwork.com/v2/rooms/" + room_id + "/messages?force=0", options);
  Logger.log("Send Chatwork ok");
}

Tạo riêng cho mình và Bot một room chat, sau đó add hai người vào trong đoạn tin nhắn gửi đến thì thêm đoạn text [toall] vậy là tất cả thành viên trong room đã được mention vào message 😎


Gửi tin nhắn qua Messenger và Telegram

Telegram:

function send_to_telegram(textMessage){
  var payload = {
    "method": "sendMessage",
    "chat_id": YOUR_CHAT_ID,
    "text": textMessage,
    "parse_mode": "HTML"
  }
  
  var data = {
    "method": "post",
    "payload": payload
  }
  var API_TOKEN = YOUR_API_BOT_TELEGRAM;
  UrlFetchApp.fetch('https://api.telegram.org/bot' + API_TOKEN + '/', data);
  Logger.log("Send Telegram ok");
}

Messenger

function send_to_facebook(textMessage) {
  var recipient_ids = [YOUR_CHAT_ID];
  var API_TOKEN = YOUR_GRAPH_API_FACEBOOK
  for (var j = 0; j < recipient_ids.length; j++) {
    var messageData = {
      "recipient": {
        "id": recipient_ids[j]
      },
      "message": {
        "text": textMessage
      }
    }
    var JSONdMessageData = {}
    for(var i in messageData){
      JSONdMessageData[i] = JSON.stringify(messageData[i])
    }
    var payload = JSONdMessageData
    // payload.access_token = API_TOKEN
    var options = {
      "method": "post",
      "payload": payload
    }
    
    UrlFetchApp.fetch("https://graph.facebook.com/v5.0/me/messages?access_token=" + API_TOKEN, options);
  }
  Logger.log("Send Facebook ok");
}

Đối với Telegram chúng ta phải tạo một con Bot Telegram và lấy YOUR_CHAT_ID thông qua YOUR_API_BOT_TELEGRAM của con bot đó các bạn có thể xem hướng dẫn tại đây

Đối với Messenger thì chúng ta cần tạo ra một Page cho Bot, sau đó gửi cho Page một tin nhắn để có thể lấy được YOUR_CHAT_ID thông qua YOUR_GRAPH_API_FACEBOOK, còn về chi tiết thì mình không hướng dẫn nữa để tránh dài dòng, nếu thực sự quan tâm thì có thể tham khảo các bài viết khác liên quan đến Graph API Facebook


Cuối cùng là việc setting cho function của mình chạy hàng ngày vào một khung giờ nhất định

Ở đây chọn tên function cần thực thi để chạy hàng ngày


Vậy là các bạn đã hiểu về cách hoạt động của Bot rồi nhỉ 😃).

Tùy vào sự sáng tạo mà có thể viết được Bot có chức năng khác nhau, ở đây mình có viết thêm chức năng báo thời tiết nữa.


Và đây là thành quả


Bài viết của mình đến đây là kết thúc hy vọng sẽ giúp ích và mang lại niềm vui cho mọi người. Tuy nhiên khi viết xong bài này khái niệm về ChatBot của mình có vẻ như đang bị lẫn lộn 😂😂, bởi vì ChatBot có thể reply message tự động khi mà nhận được message đến, hiện tại thì Bot của mình chưa làm được điều đó, thực chất nó chỉ là một Function có chức năng đẩy message trong một khoảng thời gian thôi.

Vậy bạn hiểu khái niệm ChatBot là như thế nào, nếu mình đang hiểu sai thì comment cho mình biết nhé 😞😞



All rights reserved

Bình luận

Đăng nhập để bình luận
Avatar
@anhquanhh4
thg 12 25, 2019 7:27 SA

Là được =))

Avatar
@simple1805
thg 12 30, 2019 1:58 SA

Bài viết khá hay, tiết kiệm được kha khá chi phí server 😄 Bạn cho mình hỏi mình muốn setting chạy vào 1 khung giờ cụ thể các ngày trong tuần (từ thứ 2 đến thứ 6) thì có các nào setting không nhỉ ?

Avatar
@TruongVanPhong
thg 12 30, 2019 2:40 SA

Có vẻ như google chỉ cho phép settings cho chạy một ngày 1 lần trong 1 khoảng thời gian như ở trên mình nói. Tuy nhiên vẫn có cách để settings như ý của bạn. Bạn có thể clone project ra nhiều sau đó setting mỗi project chạy một ngày trong tuần vào mỗi giờ nhất định, có vẻ sẽ trông như thế này 😀 Screenshot from 2019-12-30 09-39-44.png

Avatar
@simple1805
thg 12 30, 2019 2:44 SA

Còn một cái nữa là hạn chế của cơ chế set time. Ví dụ như ảnh bạn config thời gian từ 6 giờ sáng đến 7h sáng, nó không cố định được thời gian gửi mess đó. Mình muốn config chạy send mess vào 06:00 chặng hạn nhưng mình config 6-7h thì tận 6h23 nó mới gửi tin nhắn

Avatar
@TruongVanPhong
thg 12 30, 2019 3:11 SA

Cảm ơn bạn đã góp ý, hi vọng trong thời gian tới google sẽ phát triển thêm tính năng này 👍

Avatar
@haduyenthang
thg 12 31, 2019 1:08 CH

cho em hỏi các bước cụ thể để lấy chat id thông qua graph api fb được không ạ

Avatar
@TruongVanPhong
thg 1 3, 2020 12:50 SA

Để lấy được chat id thông qua graph api fb thì cần có Access token, bạn có thể tham khảo ở đây https://viblo.asia/p/facebook-graph-api-maGK7mPMlj2 hoặc https://viblo.asia/p/huong-dan-lam-facebook-fanpage-chatbot-voi-nodejs-RQqKLvqNl7z

Sau đó bạn gửi cho Page một tin nhắn (Facebook chỉ cho phép gửi tin nhắn từ pge tới user thôi), vào https://developers.facebook.com/tools/explorer/?method=GET&path=me&version=v5.0 bạn sẽ được giao diện như hình dưới và tiến hành query ra tất cả tin nhắn của page => có chat_id của user image.png

Còn query thế nào thì bạn có thể tự tìm hiểu nhé, rất là dễ dàng thôi, chúc bạn thành công

Avatar
@hung000
thg 3 2, 2020 5:54 SA

query như nào v ạ 😦 nói rõ hơn được k ad

Avatar
@HHPxme
thg 1 1, 2020 3:16 CH

Có thể chỉ mình cách lấy YOUR_CHAT_ID và YOUR_GRAPH_API_FACEBOOK không ? Đến chỗ đó thì mình không biết phải làm thế nào nữa.

Avatar
@TruongVanPhong
thg 1 3, 2020 12:51 SA

Mình có comment ở trên rồi bạn nhé bạn có thể tham khảo

Avatar

Chào anh ạ. Em rất thích bài viết của anh ạ, em xin cảm ơn. Em đã lấy được [YOUR_CHAT_ID] từ tools explorer của Facebook, đi kèm với đó là Access Token. Em có một số câu hỏi muốn hỏi anh ạ: app1.JPG.

  1. Theo em tìm hiểu được thì Access Token chỉ tồn tại được một khoảng thời gian thôi, như vậy mình sẽ phải update lại token phải k ạ ?
  2. Em đã test với tools explore với cùng một YOUR_CHAT_ID giống bên Google App Script và em đã nhận được message ngay sau đó. Em đã lấy id đó paste qua bên Script và lấy cùng 1 Access Token nhưng không có tin nhắn nào gửi về cả. Em kh biết em có hiểu sai cái gì đó không app2.JPG.

3.Em không biết đây có phải là lý do không nhưng nó báo ra một lỗi như sau: " Error: Exception: Không thể tìm nạp url vì quá nhiều lưu lượng truy cập đang được gửi tới URL đã chỉ định. " Em dùng nguyên phần phương thức " send_to_facebook " của anh ạ, chỉ thêm id và token vào thôi. Em đã tìm trên mạng nhưng vẫn chưa tìm được lời giải cho lỗi này ._.

Mong anh có thể giải đáp những thắc mắc trên giúp em, em rất cảm kích ^_^. Em cảm ơn anh nhiều ạ.

Xem thêm (10)
Avatar

@hung000 Bạn có thể làm theo cách này nhé

Avatar
@TungHinh
thg 4 11, 2020 2:28 SA

Mình đang gặp vấn đề như bạn, Bạn có thẻ giải đáp giúp mình được không?

Avatar
@namhodang11040
thg 1 4, 2020 12:25 CH

mình không phải dân lập trình nhưng rất muốn có 1 con bot giống v, bạn có thể xin code toàn bộ code không bị ngắt quoãng được không. mình cảm ơn

Avatar
@ngovannghia
thg 1 7, 2020 9:31 SA

Ghê chưa!!! Ghê Chưa !!!! 😀👍😀👍😀😍😍

Avatar

Avatar
@codebetterme
thg 1 8, 2020 11:02 SA

Chat bot, giật tít quá bạn 😄 Thực ra là Cronjob đúng hơn

Avatar
@TruongVanPhong
thg 1 10, 2020 9:33 SA

Avatar
@ngocduong
thg 1 8, 2020 11:37 SA

cho em hỏi: function myFunction là mình chỉ viết mấy hàm get data từ Sheets, còn function send_to_telegram mình viết ngoài phải không ạ, e viết riêng khi chạy nó ko get được dữ liệu nó gửi về nguyên ngày tháng năm Capture.PNG

Avatar
@ngocduong
thg 1 8, 2020 11:45 SA

cho em hỏi ngu thêm 1 cái nữa : là em lấy ngày là bắt đầu từ đầu năm 2020 vậy làm sao get getSheetValues (real_row, real_col, 3, 1) cho đúng, ở dưới là lịch làm việc và code của em ạ! Và khi chạy hàm để thực thi, chỉ cần chạy hàm myFunction thôi hay là chạy thêm hàm send_to_telegram 3.PNG 2.PNG

Xem thêm (3)
Avatar
@ngocduong
thg 1 21, 2020 6:30 CH

dạ, cảm ơn a ạ!

Avatar
@wasabixxx
thg 3 1, 2020 10:20 SA

@ngocduong A cho e xin code với

Avatar
@nihilism.core
thg 1 11, 2020 4:16 CH

as.png Lỗi này là sao hả bạn?

Avatar
@xatkumaulank
thg 7 8, 2020 2:44 CH

bạn kéo xuống sẽ thấy phần nâng cao ấn vào đó, rồi chọn kết nối không an toàn gì gì đấy mk cũng ko nhớ nữa :v Là đc

Avatar
@nhana31999
thg 1 11, 2020 6:22 CH
Avatar
@YBT
thg 1 30, 2020 7:46 SA
Avatar
@TruongVanPhong
thg 1 31, 2020 1:57 SA

Vấn đề này mình có comment ở trên rồi, bạn có thể tham khảo ở những comment trên nhé

Avatar
@YBT
thg 3 7, 2020 3:28 CH

không biết với cập nhất mới từ FB thì sửa lỗi như thế nào ạ

Avatar
Avatar

KHÔNG BIẾT BẠN NÀO CÒN ĐỌC HAY CỐ GẮNG LÀM THEO TUTORIAL NÀY KHÔNG NHƯNG MÌNH ĐANG LÀM THỬ, MẤY BỮA NAY TÌM MÃI VẪN K FIX ĐƯỢC CHỖ NÀY, LÚC SEND VỀ MESSENGER CỨ BÁO ID "me" does not exist, có ai ở đây giúp mình với !!!!!!!! InkedChú thích 2020-03-14 202729_LI.jpg

Avatar

( cmt này lên vào tối 14/03/2020 😕 )

Avatar
@bappit17
thg 4 6, 2020 2:34 SA

bạn phải làm các bước như bác ở trên ấy có hướng dẫn đấy

Avatar

Tức là vẫn đang send được nó về messenger phải không nhỉ ?

Avatar
@bappit17
thg 4 4, 2020 3:41 SA

Mình có lấy một vài id facbook của một vài bạn khác, nhưng một thời gian nếu bạn ấy không tương tác với bot (mình đoán là vậy) thì nó không cho gởi, bị báo lỗi ngay cái id facbook đó (lỗi như hình) loi.PNG

Mong mọi người hướng dẫn giúp mình ạ, thanks!!

Avatar
@TungHinh
thg 4 11, 2020 2:08 SA

Em thấy bài viết rất hay . Em làm theo các bước trên nhưng gặp lỗi này mong được giải đáp ạ Em gặp lỗi ở dòng thứ 23 "Hàng bắt đàu phạm vi quá nhỏ" Annotation 2020-04-11 090627.jpg

Avatar
@YBT
thg 9 2, 2020 2:24 SA

HELP!!!!!!! em gửi cho fb thì thi thoảng fb lại đổi chính sách lằng ngoằng quá, bác có thể bỏ chút thời gian hướng dẫn với zalo không ạ? tại chatwork không có bong bóng chat, e muốn thông báo có bong bóng chat tiện hơn mà mày mò code cho zalo trên này thì được mà nhúng vào google script không đượcUntitled.png

Avatar
@zhongshan21
thg 9 4, 2020 12:29 SA

mình cũng đã làm thử nhưng bot của mình lại không chạy bạn có thể hướng dẫn mình k photo_2020-09-04_07-29-14.jpg

Avatar
@hoandz
thg 9 19, 2020 8:03 SA

bạn hướng dẫn tạo chatbot thông báo thời tiết đi ạ :v

Avatar
@levancanh
thg 12 30, 2020 4:20 CH

Capture.PNG cho mình hỏi cái recipient_ids là cái chổ mình khoanh fai không ạ

Avatar
+55
Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí