प्रोहोस्टर > Блог > प्रशासन > R मध्ये टेलीग्राम बॉट लिहिणे (भाग 4): बॉटशी सुसंगत, तार्किक संवाद तयार करणे
R मध्ये टेलीग्राम बॉट लिहिणे (भाग 4): बॉटशी सुसंगत, तार्किक संवाद तयार करणे
जर तुम्ही आधीचे वाचले असेल तीन लेख या मालिकेतून, नंतर कीबोर्डसह संपूर्ण टेलीग्राम बॉट्स कसे लिहायचे हे तुम्हाला आधीच माहित आहे.
या लेखात, आपण एक बॉट कसा लिहायचा ते शिकू जे एक सुसंगत संवाद राखेल. त्या. बॉट तुम्हाला प्रश्न विचारेल आणि तुमची काही माहिती एंटर करण्याची प्रतीक्षा करेल. तुम्ही प्रविष्ट केलेल्या डेटावर अवलंबून, बॉट काही क्रिया करेल.
तसेच या लेखात आपण बॉटच्या हुड अंतर्गत डेटाबेस कसा वापरायचा ते शिकू, आमच्या उदाहरणात ते SQLite असेल, परंतु आपण इतर कोणतेही DBMS वापरू शकता. मध्ये आर भाषेतील डेटाबेसशी संवाद साधण्याबद्दल मी अधिक तपशीलवार लिहिले हा लेख.
"आर मध्ये टेलिग्राम बॉट लिहिणे" या मालिकेतील सर्व लेख
बॉट आपल्याकडून डेटाची विनंती करण्यासाठी आणि आपण कोणतीही माहिती प्रविष्ट करण्याची प्रतीक्षा करण्यासाठी, आपल्याला संवादाची वर्तमान स्थिती रेकॉर्ड करण्याची आवश्यकता असेल. हे करण्याचा सर्वोत्तम मार्ग म्हणजे काही प्रकारचे एम्बेडेड डेटाबेस वापरणे, जसे की SQLite.
त्या. तर्क खालीलप्रमाणे असेल. आम्ही बॉट पद्धतीला कॉल करतो आणि बॉट क्रमाने आमच्याकडून काही माहितीची विनंती करतो आणि प्रत्येक टप्प्यावर ही माहिती प्रविष्ट होण्याची प्रतीक्षा करतो आणि ती तपासू शकतो.
आम्ही शक्य तितका सोपा बॉट लिहू, प्रथम ते तुमचे नाव, नंतर तुमचे वय विचारेल आणि प्राप्त झालेला डेटा डेटाबेसमध्ये सेव्ह करेल. वय विचारताना, प्रविष्ट केलेला डेटा मजकूर नसून संख्या आहे हे तपासेल.
अशा साध्या संवादात फक्त तीन अवस्था असतील:
start ही बॉटची सामान्य स्थिती आहे, ज्यामध्ये तो तुमच्याकडून कोणत्याही माहितीची अपेक्षा करत नाही
प्रतीक्षा_नाव - राज्य ज्यामध्ये नाव प्रविष्ट करण्याची बॉट प्रतीक्षा करतो
wait_age ही अशी स्थिती आहे ज्यामध्ये बॉट तुमचे वय, पूर्ण वर्षांची संख्या एंटर होण्याची वाट पाहतो.
बॉट बिल्डिंग प्रक्रिया
लेखादरम्यान, आम्ही चरण-दर-चरण एक बॉट तयार करू; संपूर्ण प्रक्रिया खालीलप्रमाणे योजनाबद्धपणे चित्रित केली जाऊ शकते:
आम्ही एक बॉट कॉन्फिगरेशन तयार करतो ज्यामध्ये आम्ही काही सेटिंग्ज संग्रहित करू. आमच्या बाबतीत, बॉट टोकन आणि डेटाबेस फाइलचा मार्ग.
आम्ही एक पर्यावरण व्हेरिएबल तयार करतो ज्यामध्ये बॉटसह प्रकल्पाचा मार्ग संग्रहित केला जाईल.
आम्ही डेटाबेस स्वतः तयार करतो आणि अनेक फंक्शन्स बनवतो जेणेकरून बॉट त्याच्याशी संवाद साधू शकेल.
आम्ही बॉट पद्धती लिहितो, म्हणजे. ती कार्ये करेल.
संदेश फिल्टर जोडत आहे. ज्याच्या मदतीने बॉट चॅटच्या सध्याच्या स्थितीनुसार आवश्यक पद्धतींमध्ये प्रवेश करेल.
आम्ही हँडलर जोडतो जे आवश्यक बॉट पद्धतींसह आदेश आणि संदेश जोडतील.
चला बॉट लाँच करूया.
बॉट प्रकल्प रचना
सोयीसाठी, आम्ही आमच्या बॉटचा कोड, आणि इतर संबंधित फाइल्स, खालील संरचनेत विभागू.
बॉट.आर — आमच्या बॉटचा मुख्य कोड
db_bot_function.R डेटाबेससह कार्य करण्यासाठी फंक्शन्ससह कोडचा एक ब्लॉक
bot_methods.R - बॉट पद्धतींचा कोड
message_filters.R - संदेश फिल्टर
हँडलर.आर - हाताळणारे
config.cfg - बॉट कॉन्फिगरेशन
create_db_data.sql डेटाबेसमध्ये चॅट डेटासह टेबल तयार करण्यासाठी SQL स्क्रिप्ट
create_db_state.sql डेटाबेसमध्ये वर्तमान चॅट स्थितीचे सारणी तयार करण्यासाठी SQL स्क्रिप्ट
कॉन्फिगरेशनमध्ये आम्ही बॉट टोकन आणि डेटाबेसचा मार्ग लिहितो, म्हणजे. bot.db फाइलवर; आम्ही पुढील चरणात फाइल स्वतः तयार करू.
अधिक जटिल बॉट्ससाठी, आपण अधिक जटिल कॉन्फिग्स तयार करू शकता, याशिवाय, ini कॉन्फिगरेशन लिहिणे आवश्यक नाही, आपण JSON सह इतर कोणतेही स्वरूप वापरू शकता.
पर्यावरण व्हेरिएबल तयार करा
प्रत्येक PC वर, बॉट प्रोजेक्ट असलेले फोल्डर वेगवेगळ्या डिरेक्टरीमध्ये आणि वेगवेगळ्या ड्राइव्हवर स्थित असू शकते, म्हणून कोडमध्ये प्रोजेक्ट फोल्डरचा मार्ग पर्यावरण व्हेरिएबलद्वारे सेट केला जाईल. TG_BOT_PATH.
पर्यावरण व्हेरिएबल तयार करण्याचे अनेक मार्ग आहेत, सर्वात सोपा म्हणजे ते फाइलमध्ये लिहिणे .रेन्विरॉन.
तुम्ही कमांड वापरून ही फाइल तयार किंवा संपादित करू शकता file.edit(path.expand(file.path("~", ".Renviron"))). ते कार्यान्वित करा आणि फाइलमध्ये एक ओळ जोडा:
TG_BOT_PATH=C:/ПУТЬ/К/ВАШЕМУ/ПРОЕКТУ
पुढे फाईल सेव्ह करा .रेन्विरॉन आणि RStudio रीस्टार्ट करा.
डेटाबेस तयार करणे
पुढील पायरी म्हणजे डेटाबेस तयार करणे. आम्हाला 2 टेबल्सची आवश्यकता असेल:
chat_data — बॉटने वापरकर्त्याकडून विनंती केलेला डेटा
chat_state — सर्व चॅटची वर्तमान स्थिती
तुम्ही खालील SQL क्वेरी वापरून ही सारणी तयार करू शकता:
CREATE TABLE chat_data (
chat_id BIGINT PRIMARY KEY
UNIQUE,
name TEXT,
age INTEGER
);
CREATE TABLE chat_state (
chat_id BIGINT PRIMARY KEY
UNIQUE,
state TEXT
);
जर तुम्ही बॉट प्रोजेक्ट येथून डाउनलोड केला असेल GitHub, नंतर डेटाबेस तयार करण्यासाठी तुम्ही R मध्ये खालील कोड वापरू शकता.
# Скрипт создания базы данных
library(DBI) # интерфейс для работы с СУБД
library(configr) # чтение конфига
library(readr) # чтение текстовых SQL файлов
library(RSQLite) # драйвер для подключения к SQLite
# директория проекта
setwd(Sys.getenv('TG_BOT_PATH'))
# чтение конфига
cfg <- read.config('config.cfg')
# подключение к SQLite
con <- dbConnect(SQLite(), cfg$db_settings$db_path)
# Создание таблиц в базе
dbExecute(con, statement = read_file('create_db_data.sql'))
dbExecute(con, statement = read_file('create_db_state.sql'))
डेटाबेससह कार्य करण्यासाठी कार्ये लिहिणे
आमच्याकडे आधीच कॉन्फिगरेशन फाइल तयार आहे आणि डेटाबेस तयार केला आहे. आता तुम्हाला या डेटाबेसमध्ये डेटा वाचण्यासाठी आणि लिहिण्यासाठी फंक्शन्स लिहिण्याची आवश्यकता आहे.
आपण येथून प्रकल्प डाउनलोड केल्यास GitHub, नंतर तुम्ही फाइलमधील फंक्शन्स शोधू शकता db_bot_function.R.
डेटाबेससह कार्य करण्यासाठी फंक्शन कोड
# ###########################################################
# Function for work bot with database
# получить текущее состояние чата
get_state <- function(chat_id) {
con <- dbConnect(SQLite(), cfg$db_settings$db_path)
chat_state <- dbGetQuery(con, str_interp("SELECT state FROM chat_state WHERE chat_id == ${chat_id}"))$state
return(unlist(chat_state))
dbDisconnect(con)
}
# установить текущее состояние чата
set_state <- function(chat_id, state) {
con <- dbConnect(SQLite(), cfg$db_settings$db_path)
# upsert состояние чата
dbExecute(con,
str_interp("
INSERT INTO chat_state (chat_id, state)
VALUES(${chat_id}, '${state}')
ON CONFLICT(chat_id)
DO UPDATE SET state='${state}';
")
)
dbDisconnect(con)
}
# запись полученных данных в базу
set_chat_data <- function(chat_id, field, value) {
con <- dbConnect(SQLite(), cfg$db_settings$db_path)
# upsert состояние чата
dbExecute(con,
str_interp("
INSERT INTO chat_data (chat_id, ${field})
VALUES(${chat_id}, '${value}')
ON CONFLICT(chat_id)
DO UPDATE SET ${field}='${value}';
")
)
dbDisconnect(con)
}
# read chat data
get_chat_data <- function(chat_id, field) {
con <- dbConnect(SQLite(), cfg$db_settings$db_path)
# upsert состояние чата
data <- dbGetQuery(con,
str_interp("
SELECT ${field}
FROM chat_data
WHERE chat_id = ${chat_id};
")
)
dbDisconnect(con)
return(data[[field]])
}
आम्ही 4 साधी कार्ये तयार केली:
get_state() - डेटाबेसमधून वर्तमान चॅट स्थिती मिळवा
set_state() डेटाबेसवर वर्तमान चॅट स्थिती लिहा
get_chat_data() - वापरकर्त्याने पाठवलेला डेटा प्राप्त करा
सर्व फंक्शन्स अगदी सोपी आहेत, ते कमांड वापरून डेटाबेसमधील डेटा वाचतात dbGetQuery(), किंवा वचनबद्ध UPSERT कार्य (विद्यमान डेटा बदलणे किंवा डेटाबेसमध्ये नवीन डेटा लिहिणे), फंक्शन वापरून dbExecute().
UPSERT ऑपरेशनसाठी वाक्यरचना खालीलप्रमाणे आहे:
INSERT INTO chat_data (chat_id, ${field})
VALUES(${chat_id}, '${value}')
ON CONFLICT(chat_id)
DO UPDATE SET ${field}='${value}';
त्या. आमच्या टेबल फील्डमध्ये chat_id एक विशिष्टता मर्यादा आहे आणि टेबलची प्राथमिक की आहे. सुरुवातीला, आम्ही टेबलमध्ये माहिती जोडण्याचा प्रयत्न करतो, आणि सध्याच्या चॅटसाठी डेटा आधीच उपस्थित असल्यास आम्हाला एक त्रुटी येते, अशा परिस्थितीत आम्ही या चॅटसाठी माहिती अद्यतनित करतो.
पुढे, आपण ही फंक्शन्स बॉटच्या पद्धती आणि फिल्टरमध्ये वापरू.
बॉट पद्धती
आमचा बॉट तयार करण्याची पुढील पायरी म्हणजे पद्धती तयार करणे. आपण येथून प्रकल्प डाउनलोड केल्यास GitHub, नंतर सर्व पद्धती फाईलमध्ये आहेत bot_methods.R.
बॉट पद्धत कोड
# ###########################################################
# bot methods
# start dialog
start <- function(bot, update) {
#
# Send query
bot$sendMessage(update$message$chat_id,
text = "Введи своё имя")
# переключаем состояние диалога в режим ожидания ввода имени
set_state(chat_id = update$message$chat_id, state = 'wait_name')
}
# get current chat state
state <- function(bot, update) {
chat_state <- get_state(update$message$chat_id)
# Send state
bot$sendMessage(update$message$chat_id,
text = unlist(chat_state))
}
# reset dialog state
reset <- function(bot, update) {
set_state(chat_id = update$message$chat_id, state = 'start')
}
# enter username
enter_name <- function(bot, update) {
uname <- update$message$text
# Send message with name
bot$sendMessage(update$message$chat_id,
text = paste0(uname, ", приятно познакомится, я бот!"))
# Записываем имя в глобальную переменную
#username <<- uname
set_chat_data(update$message$chat_id, 'name', uname)
# Справшиваем возраст
bot$sendMessage(update$message$chat_id,
text = "Сколько тебе лет?")
# Меняем состояние на ожидание ввода имени
set_state(chat_id = update$message$chat_id, state = 'wait_age')
}
# enter user age
enter_age <- function(bot, update) {
uage <- as.numeric(update$message$text)
# проверяем было введено число или нет
if ( is.na(uage) ) {
# если введено не число то переспрашиваем возраст
bot$sendMessage(update$message$chat_id,
text = "Ты ввёл некорректные данные, введи число")
} else {
# если введено число сообщаем что возраст принят
bot$sendMessage(update$message$chat_id,
text = "ОК, возраст принят")
# записываем глобальную переменную с возрастом
#userage <<- uage
set_chat_data(update$message$chat_id, 'age', uage)
# сообщаем какие данные были собраны
username <- get_chat_data(update$message$chat_id, 'name')
userage <- get_chat_data(update$message$chat_id, 'age')
bot$sendMessage(update$message$chat_id,
text = paste0("Тебя зовут ", username, " и тебе ", userage, " лет. Будем знакомы"))
# возвращаем диалог в исходное состояние
set_state(chat_id = update$message$chat_id, state = 'start')
}
}
आम्ही 5 पद्धती तयार केल्या:
प्रारंभ करा - एक संवाद सुरू करा
राज्य - वर्तमान चॅट स्थिती मिळवा
रीसेट — वर्तमान चॅट स्थिती रीसेट करा
enter_name — बॉट तुमचे नाव विचारतो
enter_age — बॉट तुमचे वय विचारते
पद्धत start तुमचे नाव विचारते आणि चॅट स्थिती बदलते प्रतीक्षा_नाव, म्हणजे तुमचे नाव टाकण्यासाठी स्टँडबाय.
पुढे, तुम्ही नाव पाठवा आणि त्यावर पद्धतीनुसार प्रक्रिया केली जाईल enter_name, बॉट तुम्हाला अभिवादन करतो, प्राप्त झालेले नाव डेटाबेसमध्ये लिहितो आणि चॅट राज्यावर स्विच करतो प्रतीक्षा_वय.
या टप्प्यावर, बॉटची अपेक्षा आहे की आपण आपले वय प्रविष्ट केले पाहिजे. तुम्ही तुमचे वय पाठवता, बॉट मेसेज तपासतो, जर तुम्ही नंबरऐवजी काही मजकूर पाठवला तर ते असे म्हणेल: Ты ввёл некорректные данные, введи число, आणि तुमचा डेटा पुन्हा एंटर करण्याची तुमची प्रतीक्षा करेल. जर तुम्ही नंबर पाठवला असेल, तर बॉट कळवेल की त्याने तुमचे वय स्वीकारले आहे, प्राप्त झालेला डेटा डेटाबेसमध्ये लिहा, तुमच्याकडून प्राप्त झालेल्या सर्व डेटाचा अहवाल देईल आणि चॅट स्थिती त्याच्या मूळ स्थितीत परत करेल, म्हणजे. व्ही start.
पद्धत कॉल करून state आपण कोणत्याही वेळी वर्तमान चॅट स्थितीची विनंती करू शकता, आणि वापरून reset गप्पा त्याच्या मूळ स्थितीत परत करा.
संदेश फिल्टर
आमच्या बाबतीत, बॉट तयार करताना हा सर्वात महत्वाचा भाग आहे. मेसेज फिल्टरच्या मदतीने बॉटला समजेल की त्याला तुमच्याकडून कोणती माहिती अपेक्षित आहे आणि त्यावर प्रक्रिया कशी करावी.
वर प्रकल्पात GitHub फिल्टर फाइलमध्ये नोंदणीकृत आहेत message_filters.R.
संदेश फिल्टर कोड:
# ###########################################################
# message state filters
# фильтр сообщений в состоянии ожидания имени
MessageFilters$wait_name <- BaseFilter(function(message) {
get_state( message$chat_id ) == "wait_name"
}
)
# фильтр сообщений в состоянии ожидания возраста
MessageFilters$wait_age <- BaseFilter(function(message) {
get_state( message$chat_id ) == "wait_age"
}
)
फिल्टरमध्ये आपण पूर्वी लिहिलेले फंक्शन वापरतो get_state(), चॅटच्या वर्तमान स्थितीची विनंती करण्यासाठी. या फंक्शनसाठी फक्त 1 युक्तिवाद, चॅट आयडी आवश्यक आहे.
पुढील फिल्टर प्रतीक्षा_नाव चॅट स्थितीत असताना संदेशांवर प्रक्रिया करते wait_name, आणि त्यानुसार फिल्टर प्रतीक्षा_वय चॅट स्थितीत असताना संदेशांवर प्रक्रिया करते wait_age.
हाताळणारे
हँडलर्स असलेली फाइल कॉल केली जाते हँडलर.आर, आणि खालील कोड आहे:
# ###########################################################
# handlers
# command handlers
start_h <- CommandHandler('start', start)
state_h <- CommandHandler('state', state)
reset_h <- CommandHandler('reset', reset)
# message handlers
## !MessageFilters$command - означает что команды данные обработчики не обрабатывают,
## только текстовые сообщения
wait_age_h <- MessageHandler(enter_age, MessageFilters$wait_age & !MessageFilters$command)
wait_name_h <- MessageHandler(enter_name, MessageFilters$wait_name & !MessageFilters$command)
प्रथम आम्ही कमांड हँडलर तयार करतो जे तुम्हाला डायलॉग सुरू करण्यासाठी, ते रीसेट करण्यासाठी आणि वर्तमान स्थितीची क्वेरी करण्यासाठी पद्धती चालवण्यास अनुमती देईल.
पुढे, आम्ही मागील चरणात तयार केलेले फिल्टर वापरून 2 संदेश हँडलर तयार करतो आणि त्यांना एक फिल्टर जोडतो. !MessageFilters$command, जेणेकरून आम्ही कोणत्याही चॅट स्थितीत कमांड वापरू शकतो.
बॉट लाँच कोड
आता आमच्याकडे लॉन्च करण्यासाठी सर्वकाही तयार आहे, बॉट लॉन्च करण्यासाठी मुख्य कोड फाइलमध्ये आहे बॉट.आर.
library(telegram.bot)
library(tidyverse)
library(RSQLite)
library(DBI)
library(configr)
# переходим в папку проекта
setwd(Sys.getenv('TG_BOT_PATH'))
# читаем конфиг
cfg <- read.config('config.cfg')
# создаём экземпляр бота
updater <- Updater(cfg$bot_settings$bot_token)
# Загрузка компонентов бота
source('db_bot_function.R') # функции для работы с БД
source('bot_methods.R') # методы бота
source('message_filters.R') # фильтры сообщений
source('handlers.R') # обработчики сообщений
# Добавляем обработчики в диспетчер
updater <- updater +
start_h +
wait_age_h +
wait_name_h +
state_h +
reset_h
# Запускаем бота
updater$start_polling()
परिणामी, आम्हाला हा बॉट मिळाला:
आदेश वापरून कधीही /state आम्ही सध्याच्या चॅट स्थितीबद्दल आणि कमांड वापरून क्वेरी करू शकतो /reset गप्पा त्याच्या मूळ स्थितीत परत करा आणि पुन्हा संवाद सुरू करा.
निष्कर्ष
या लेखात, आम्ही बॉटमध्ये डेटाबेस कसा वापरायचा आणि चॅट स्थिती रेकॉर्ड करून सातत्यपूर्ण तार्किक संवाद कसे तयार करायचे ते शोधून काढले.
या प्रकरणात, आम्ही सर्वात प्राचीन उदाहरण पाहिले, जेणेकरुन तुम्हाला असे बॉट्स तयार करण्याची कल्पना समजणे सोपे होईल; व्यवहारात, तुम्ही बरेच जटिल संवाद तयार करू शकता.
या मालिकेतील पुढील लेखात, आपण बॉट वापरकर्त्यांच्या विविध पद्धती वापरण्याचे अधिकार कसे प्रतिबंधित करायचे ते शिकू.