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
Bài đăng này đã không được cập nhật trong 3 năm
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_tkb
là id
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 đó:
- Nếu
week_mod == 0 || week_mod == 6
thì ngày hôm nay là cuối tuần gánmessage = "Hôm nay là cuối tuần chịu khó tập thể dục đi";
- 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
Là được =))
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ỉ ?
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

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
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
cho em hỏi các bước cụ thể để lấy chat id thông qua graph api fb được không ạ
Để 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
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
query như nào v ạ
nói rõ hơn được k ad
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.
Mình có comment ở trên rồi bạn nhé bạn có thể tham khảo
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 ạ:
.
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 ạ.
@hung000 Bạn có thể làm theo cách này nhé
Mình đang gặp vấn đề như bạn, Bạn có thẻ giải đáp giúp mình được không?
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
Ghê chưa!!! Ghê Chưa !!!!






Chat bot, giật tít quá bạn
Thực ra là Cronjob đúng hơn
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
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

dạ, cảm ơn a ạ!
@ngocduong A cho e xin code với
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
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é
không biết với cập nhất mới từ FB thì sửa lỗi như thế nào ạ
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 !!!!!!!!
( cmt này lên vào tối 14/03/2020
)
bạn phải làm các bước như bác ở trên ấy có hướng dẫn đấy
Tức là vẫn đang send được nó về messenger phải không nhỉ ?
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)
Mong mọi người hướng dẫn giúp mình ạ, thanks!!
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ỏ"
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 được
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
bạn hướng dẫn tạo chatbot thông báo thời tiết đi ạ :v