Nulis bot telegram ing R (bagean 4): Nggawe dialog sing konsisten lan logis karo bot

Yen sampeyan wis maca sadurunge telung artikel saka seri iki, sampeyan wis ngerti carane nulis bot telegram lengkap karo keyboard.

Ing artikel iki, kita bakal sinau carane nulis bot sing bakal njaga dialog sing konsisten. Sing. Bot bakal takon sampeyan lan ngenteni sampeyan ngetik sawetara informasi. Gumantung ing data sing sampeyan lebokake, bot bakal nindakake sawetara tumindak.

Uga ing artikel iki kita bakal sinau carane nggunakake database ing hood saka bot, ing conto kita bakal SQLite, nanging sampeyan bisa nggunakake sembarang DBMS liyane. Aku nulis luwih rinci babagan sesambungan karo database ing basa R ing artikel iki.

Nulis bot telegram ing R (bagean 4): Nggawe dialog sing konsisten lan logis karo bot

Kabeh artikel saka seri "Nulis bot telegram ing R"

  1. Kita nggawe bot lan digunakake kanggo ngirim pesen ing telegram
  2. Tambah dhukungan printah lan saringan pesen menyang bot
  3. Cara nambah dhukungan keyboard menyang bot
  4. Nggawe dialog sing konsisten lan logis karo bot

Isi

Yen sampeyan kasengsem ing analisis data, sampeyan bisa uga kasengsem ing sandi telegram и youtube saluran. Sebagéyan gedhé isiné dikhususaké kanggo basa R.

  1. Pambuka
  2. Proses mbangun bot
  3. Struktur proyek bot
  4. Konfigurasi bot
  5. Nggawe variabel lingkungan
  6. Nggawe database
  7. Nulis fungsi kanggo nggarap database
  8. Metode bot
  9. Filter-filter pesen
  10. Pawang
  11. Kode peluncuran bot
  12. kesimpulan

Pambuka

Supaya bot njaluk data saka sampeyan lan ngenteni sampeyan ngetik informasi apa wae, sampeyan kudu ngrekam kahanan dialog saiki. Cara paling apik kanggo nindakake iki yaiku nggunakake sawetara jinis database sing dipasang, kayata SQLite.

Sing. Logika bakal kaya ing ngisor iki. Kita nelpon cara bot, lan bot sequentially njaluk sawetara informasi saka kita, lan ing saben langkah ngenteni informasi iki kanggo ngetik lan bisa mriksa.

Kita bakal nulis bot sing paling gampang, pisanan bakal takon jeneng sampeyan, banjur umur sampeyan, lan bakal nyimpen data sing ditampa menyang database. Nalika takon umur, bakal mriksa manawa data sing dilebokake yaiku nomer lan dudu teks.

Dialog prasaja kuwi mung bakal duwe telung negara:

  1. wiwitan iku kahanan normal saka bot, kang ora nyana informasi saka sampeyan
  2. wait_name - negara ing ngendi bot ngenteni jeneng kanggo ngetik
  3. wait_age minangka negara ing ngendi bot ngenteni umur sampeyan, jumlah taun lengkap.

Proses mbangun bot

Sajrone artikel kasebut, kita bakal nggawe bot langkah demi langkah; kabeh proses bisa digambarake kanthi skema kaya ing ngisor iki:
Nulis bot telegram ing R (bagean 4): Nggawe dialog sing konsisten lan logis karo bot

  1. Kita nggawe konfigurasi bot sing bakal nyimpen sawetara setelan. Ing kasus kita, token bot, lan path menyang file database.
  2. Kita nggawe variabel lingkungan ing ngendi path menyang proyek karo bot bakal disimpen.
  3. Kita nggawe database dhewe, lan sawetara fungsi supaya bot bisa sesambungan karo.
  4. Kita nulis cara bot, i.e. fungsi sing bakal ditindakake.
  5. Nambahake saringan pesen. Kanthi bantuan bot bakal ngakses cara sing dibutuhake, gumantung saka kahanan obrolan saiki.
  6. Kita nambah panangan sing bakal nyambungake printah lan pesen kanthi cara bot sing dibutuhake.
  7. Ayo miwiti bot.

Struktur proyek bot

Kanggo penak, kita bakal dibagi kode bot kita, lan file liyane sing gegandhengan, menyang struktur ing ngisor iki.

  • bot.R — kode utama bot kita
  • db_bot_function.R - blok kode kanthi fungsi kanggo nggarap database
  • bot_methods.R - kode metode bot
  • pesen_filter.R - saringan pesen
  • pawang.R - pawang
  • config.cfg - konfigurasi bot
  • create_db_data.sql — Skrip SQL kanggo nggawe tabel karo data chatting ing database
  • create_db_state.sql — Skrip SQL kanggo nggawe tabel status chatting saiki ing database
  • bot.db - database bot

Sampeyan bisa ndeleng kabeh proyek bot, utawa скачать saka sandi repositori ing GitHub.

Konfigurasi bot

Kita bakal nggunakake biasanipun minangka config a file iki, wangun ing ngisor iki:

[bot_settings]
bot_token=ТОКЕН_ВАШЕГО_БОТА

[db_settings]
db_path=C:/ПУТЬ/К/ПАПКЕ/ПРОЕКТА/bot.db

Ing konfigurasi kita nulis token bot lan path menyang database, i.e. menyang file bot.db, kita bakal nggawe file kasebut dhewe ing langkah sabanjure.

Kanggo bot sing luwih rumit, sampeyan bisa nggawe konfigurasi sing luwih rumit, saliyane, ora perlu nulis konfigurasi iki, sampeyan bisa nggunakake format liyane kalebu JSON.

Nggawe variabel lingkungan

Ing saben PC, folder karo proyek bot bisa ditemokake ing direktori sing beda-beda lan ing drive sing beda-beda, saengga ing kode path menyang folder proyek bakal disetel liwat variabel lingkungan TG_BOT_PATH.

Ana sawetara cara kanggo nggawe variabel lingkungan, sing paling gampang yaiku nulis ing file .Renviron.

Sampeyan bisa nggawe utawa ngowahi file iki nggunakake printah file.edit(path.expand(file.path("~", ".Renviron"))). Jalanake lan tambahake siji baris menyang file:

TG_BOT_PATH=C:/ПУТЬ/К/ВАШЕМУ/ПРОЕКТУ

Sabanjure, simpen file kasebut .Renviron lan miwiti maneh RStudio.

Nggawe database

Langkah sabanjure yaiku nggawe database. Kita butuh 2 tabel:

  • chat_data - data sing dijaluk bot saka pangguna
  • chat_state — kahanan saiki kabeh chats

Sampeyan bisa nggawe tabel iki nggunakake query SQL ing ngisor iki:

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
);

Yen sampeyan ngundhuh proyek bot saka GitHub, banjur kanggo nggawe database sampeyan bisa nggunakake kode ing ngisor iki ing 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'))

Nulis fungsi kanggo nggarap database

Kita wis duwe file konfigurasi siap lan database digawe. Saiki sampeyan kudu nulis fungsi kanggo maca lan nulis data menyang database iki.

Yen sampeyan ndownload proyek saka GitHub, banjur sampeyan bisa nemokake fungsi ing file db_bot_function.R.

Kode fungsi kanggo nggarap database

# ###########################################################
# 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]])

}

Kita nggawe 4 fungsi prasaja:

  • get_state() — njaluk status chatting saiki saka database
  • set_state() — nulis status chatting saiki kanggo database
  • get_chat_data() - nampa data sing dikirim dening pangguna
  • set_chat_data() - ngrekam data sing ditampa saka pangguna

Kabeh fungsi cukup prasaja, padha maca data saka database nggunakake printah dbGetQuery(), utawa komitmen UPSERT operasi (ngganti data sing wis ana utawa nulis data anyar menyang database), nggunakake fungsi kasebut dbExecute().

Sintaks kanggo operasi UPSERT kaya ing ngisor iki:

INSERT INTO chat_data (chat_id, ${field})
VALUES(${chat_id}, '${value}') 
ON CONFLICT(chat_id) 
DO UPDATE SET ${field}='${value}';

Sing. ing lapangan tabel kita chat_id nduweni kendala keunikan lan minangka kunci utama tabel. Kaping pisanan, kita nyoba nambah informasi menyang meja, lan kita entuk kesalahan yen data kanggo obrolan saiki wis ana, mula mung nganyari informasi kanggo obrolan iki.

Sabanjure, kita bakal nggunakake fungsi kasebut ing metode lan saringan bot.

Metode bot

Langkah sabanjure kanggo mbangun bot kita yaiku nggawe metode. Yen sampeyan ngundhuh proyek saka GitHub, banjur kabeh cara ana ing file bot_methods.R.

Kode metode bot

# ###########################################################
# 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')
  }

}

Kita nggawe 5 cara:

  • miwiti - Miwiti dialog
  • negara - Entuk status chatting saiki
  • reset - Reset status chatting saiki
  • enter_name - Bot takon jeneng sampeyan
  • enter_age - Bot takon umur sampeyan

Cara start takon jeneng, lan ngganti status chatting kanggo ngenteni_jeneng, i.e. kanggo siyaga kanggo ngetik jeneng sampeyan.

Sabanjure, sampeyan ngirim jeneng lan diproses kanthi cara enter_name, bot menehi salam, nulis jeneng sing ditampa menyang database, lan ngalih chatting menyang negara ngenteni_umur.

Ing tataran iki, bot ngarepake sampeyan mlebu umur sampeyan. Sampeyan ngirim umur sampeyan, bot mriksa pesen kasebut, yen sampeyan ngirim sawetara teks tinimbang nomer, bakal ujar: Ты ввёл некорректные данные, введи число, lan bakal ngenteni sampeyan ngetik maneh data sampeyan. Yen sampeyan ngirim nomer, bot bakal nglaporake yen wis nampa umur sampeyan, nulis data sing ditampa menyang database, laporan kabeh data sing ditampa saka sampeyan lan bali status chatting menyang posisi asline, yaiku. V start.

Kanthi nelpon cara state sampeyan bisa njaluk status chatting saiki sawayah-wayah, lan nggunakake reset bali chatting menyang negara asline.

Filter-filter pesen

Ing kasus kita, iki minangka salah sawijining bagean sing paling penting kanggo mbangun bot. Kanthi bantuan saringan pesen, bot bakal ngerti informasi apa sing dikarepake saka sampeyan lan carane kudu diproses.

Ing proyek ing GitHub saringan didaftar ing file pesen_filter.R.

Kode Filter pesen:

# ###########################################################
# 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"
}
)

Ing saringan kita nggunakake fungsi sing wis ditulis sadurunge get_state(), kanggo njaluk status obrolan saiki. Fungsi iki mung mbutuhake 1 argumen, chat id.

Filter sabanjure ngenteni_jeneng pangolahan pesen nalika chatting ing negara wait_name, lan manut Filter ngenteni_umur pangolahan pesen nalika chatting ing negara wait_age.

Pawang

File karo handler diarani pawang.R, lan nduweni kode ing ngisor iki:

# ###########################################################
# 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)

Kaping pisanan, kita nggawe panangan perintah sing bakal ngidini sampeyan mbukak cara kanggo miwiti dialog, ngreset, lan takon kahanan saiki.

Sabanjure, kita nggawe 2 pawang pesen nggunakake saringan sing digawe ing langkah sadurunge, lan nambah filter kanggo wong-wong mau !MessageFilters$command, supaya kita bisa nggunakake printah ing sembarang negara chatting.

Kode peluncuran bot

Saiki kita duwe kabeh siap diluncurake, kode utama kanggo ngluncurake bot ana ing file kasebut bot.R.

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()

Akibaté, kita entuk bot iki:
Nulis bot telegram ing R (bagean 4): Nggawe dialog sing konsisten lan logis karo bot

Ing sembarang wektu nggunakake printah /state kita bisa takon status chatting saiki, lan nggunakake printah /reset bali chatting menyang negara asli lan miwiti dialog maneh.

kesimpulan

Ing artikel iki, kita ngerti carane nggunakake database ing bot, lan carane mbangun dialog logis urutan kanthi ngrekam status chatting.

Ing kasus iki, kita ndeleng conto sing paling primitif, supaya luwih gampang sampeyan ngerti ide nggawe bot kasebut; ing praktik, sampeyan bisa nggawe dialog sing luwih rumit.

Ing artikel sabanjure ing seri iki, kita bakal sinau carane mbatesi hak pangguna bot kanggo nggunakake macem-macem cara.

Source: www.habr.com

Add a comment