Мне, иногда, приходится конвертировать регистр текста. Раньше, я пользовался сторонними сервисами, но понял, что иметь под рукой такой конвертер регистров в телеграм будет приятней. Использовать буду Google Apps Script и функции с недавно опубликованной статьи о способах конвертирования регистра в JS.
Погнали!
Первым делом идем регистрировать бота.
Детально описано здесь: Создание нового бота в Телеграм (Telegram Bot)
Создаем новую Google Таблицу по ссылке https://docs.google.com/spreadsheets/.
Это будет наша мини база данных, в которой мы будем собирать информацию о пользователях и логи.
Переименовываем и открываем в верхнем меню Расширения → Apps Script.
Развёртывание приложения
Кликаем Начать развертывание
→ Новое развертывание
.
Выбираем тип развертывания → Веб-приложение
Пишем Описание
(не обязательно), выбираем У кого есть доступ
→ Все
(!это важно) и кликаем Начать развертывание
.
Скопируем адрес URL приложения, кликнув по кнопке ОК
Управление развертываниями
Важно: после каждого изменения в коде, чтобы протестировать бота, необходимо сделать новую версию развертывание веб-приложения.
Кликаем по кнопке Начать развертывание
→ Управление развертываниями
.
Кликаем по иконке Редактирование
и выбираем из списка Новая версия
.
Config.gs
Создадим новый файл скрипта с названием config.gs
. Здесь, в объекте config
, будут хранится все переменные по нашему проекту.
Код с комментариями
const config = {
// id таблицы берем с url таблицы Convert Case Bot:
// 1 часть адреса: https://docs.google.com/spreadsheets/d/
// 2 часть - id: 1g67JUOchcKAYbGEr1Ey3JG9olM1NqUZSWXsnIMYB_CM
// 3 часть адреса: /edit#gid=0
spreadsheet: '1QBoDWMy7UkxlYmjIPKp0S4hVonPLC_yZK7WB-IitfTI',
// Вставляем адрес URL приложения которое мы скопировали на предыдущем шаге
webUrl: "https://script.google.com/macros/s/v94KAKfycbwMq6R_3NwycbltDnmNJsBTepj_imr-mtatV1_uLj3Vw2xowQtsdyc79h6z2J8Qaur/exec",
// Вставляем токен телеграм бота
tokenTelegram: "5909769673:BBGjXRGbyaa8y99xfpAs3gTSrvmDweI-vBs",
// Здесь ничего не меняем
apiUrlTelegram: "https://api.telegram.org/bot",
sheets: {
// Указываем имя листа с пользователями
sheetUsers: "users",
// Указываем имя листа для логов
sheetLog: "log",
},
// Для удобства я вынес номера колонок в которых будут храниться данные пользователей
db: {
uid: 1,
name: 2,
userName: 3,
created_at: 4,
updated_at: 5,
},
// Описываю все команды, на которые будет реагировать бот
botCommands: {
start: "/start",
},
}
Код без комментариев
const config = {
spreadsheet: '1QBoDWMy7UkxlYmjIPKp0S4hVonPLC_yZK7WB-IitfTI',
webUrl: "https://script.google.com/macros/s/v94KAKfycbwMq6R_3NwycbltDnmNJsBTepj_imr-mtatV1_uLj3Vw2xowQtsdyc79h6z2J8Qaur/exec",
tokenTelegram: "5909769673:BBGjXRGbyaa8y99xfpAs3gTSrvmDweI-vBs",
apiUrlTelegram: "https://api.telegram.org/bot",
sheets: {
sheetUsers: "users",
sheetLog: "log",
},
db: {
uid: 1,
name: 2,
userName: 3,
created_at: 4,
updated_at: 5,
},
botCommands: {
start: "/start",
},
}
Устанавливаем webhook
Создаем новый файл скрипта helper.gs
.
Запишем в него две функции: установку вебхука и его удаление:
function setWebhook(){
let response = UrlFetchApp.fetch(config.apiUrlTelegram + config.tokenTelegram + '/setWebhook?url=' + config.webUrl);
Logger.log('telegram response status is ' + response.getContentText());
}
function removeWebhook(){
let response = UrlFetchApp.fetch(config.apiUrlTelegram + config.tokenTelegram + '/setWebhook?url=');
Logger.log('telegram response status is ' + response.getContentText());
}
Сохраняем проект. Из списка выбираем функцию setWebhook
и кликаем Выполнить
:
Появляется окошко авторизации. Кликаем Проверить разрешения
:
Дальнейшие действия я указал стрелками на скринах ниже:
После предоставления разрешений, в Журнале выполнений у вас должна появится запись:
Пишем бота
Создаем новый файл скрипта bot.gs
.
Функция doPost(e)
будет принимать отправленную информацию с нашего телеграм бота.
Парсим ответ и сохраняем его в переменную ctx
function doPost(e) {
const ctx = JSON.parse(e.postData.contents);
}
Открываем наш документ по ID на листе с название log
. В первую ячейку будем заносить ctx
:
function doPost(e) {
const ctx = JSON.parse(e.postData.contents);
const ss = SpreadsheetApp.openById(config.spreadsheet);
const sheetLog = ss.getSheetByName(config.sheets.sheetLog);
sheetLog.getRange(1, 1).setValue(JSON.stringify(ctx, null, 5));
}
Теперь мы видим наглядно, что нам возвращает телеграм:
Инлайн клавиатура (Inline Keyboard)
Создаем новый файл скрипта keyboard.gs
.
Инлайн клавиатура передается как массив массивов которые состоят из инлайн кнопок.
Один массив — один ряд кнопок.
Инлайн кнопка это объект, который включает в себя ключи text
и callback_data
.
Значения callback_data
обязательно должны быть уникальны, потому что мы будем слушать нажатие кнопок именно по этому значению.
const inlineKeyboard = {
'inline_keyboard': [
[
{ 'text': "ВЕРХНИЙ РЕГИСТР", 'callback_data': "formatUpper" },
{ 'text': "нижний регистр", 'callback_data': "formatLower" }
],
[
{ 'text': "Заглавные Буквы", 'callback_data': "formatTitle" },
{ 'text': "иНВЕРСИЯ рЕГИСТРА", 'callback_data': "formatInverse" }
],
[
{ 'text': "Сделать. Как в предложении.", 'callback_data': "formatSentence" }
],
]
}
Функции
Создаем новый файл скрипта functions.gs
в котором будут храниться все наши функции.
Отправка сообщения — sendMessage
function sendMessage(chat_id, textMessage, keyboard) {
const options = {
method: 'post',
payload: {
method: 'sendMessage',
chat_id: String(chat_id),
text: textMessage,
parse_mode: 'HTML',
disable_web_page_preview: true,
reply_markup: JSON.stringify(keyboard)
}
}
UrlFetchApp.fetch(config.apiUrlTelegram + config.tokenTelegram + "/", options);
}
Удаление сообщения — deleteMessage
function deleteMessage(chat_id, message_id) {
const options = {
method: 'post',
payload: {
method: 'deleteMessage',
chat_id: String(chat_id),
message_id: message_id,
parse_mode: 'HTML',
disable_web_page_preview: true,
}
}
UrlFetchApp.fetch(config.apiUrlTelegram + config.tokenTelegram + "/", options);
}
Отправка уведомления — toastMessage
function toastMessage(cbqId, toastText) {
const options = {
method: 'post',
payload: {
callback_query_id: cbqId,
show_alert: false,
method: 'answerCallbackQuery',
text: toastText,
parse_mode: 'HTML',
}
}
UrlFetchApp.fetch(config.apiUrlTelegram + config.tokenTelegram + "/", options);
}
Функция добавления пользователя в базу данных — saveUser
function saveUser(user) {
const sheet = SpreadsheetApp.openById(config.spreadsheet).getSheetByName(config.sheets.sheetUsers)
const row = getRowByUid(sheet, user.uid);
const date = new Date();
if (row) {
sheet.getRange(row, config.db.name).setValue(user.firstName + " " + user.lastName)
sheet.getRange(row, config.db.userName).setValue(user.userName)
sheet.getRange(row, config.db.updated_at).setValue(date.toString())
} else {
sheet.appendRow(
[
user.uid,
user.firstName + " " + user.lastName,
user.userName,
date.toString(),
date.toString()
]
)
}
}
Поиска номера строки по id пользователя — getRowByUid
function getRowByUid(sheet, uid, range_ = "A1:A") {
const range = sheet.getRange(range_);
const result = range.createTextFinder(uid).matchEntireCell(true).findNext();
return result ? result.getRow() : null;
}
Далее идут функции, работу которых я описывал в статье Как изменить регистр текста в JS — JavaScript.
Конвертирование в верхний регистр — formatUpper
function formatUpper(str) {
return str.toUpperCase();
}
Конвертирование в нижний регистр — formatLower
function formatLower(str) {
return str.toLowerCase();
}
Каждое слово с заглавной буквы — formatTitle
function formatTitle(str) {
let rows = str.toLowerCase().split("\n");
let result = "";
rows.forEach(function (row) {
let words = row.split(" ");
let wordsResult = "";
words.forEach(function (word) {
word ? (wordsResult += " " + word.split("")[0].toUpperCase() + word.slice(1)) : "";
});
result += wordsResult.trim() + "\n";
});
return result;
}
Инверсия регистра — formatInverse
function formatInverse(str) {
function isLower(variable) { return variable.toLowerCase() == variable }
function isUpper(variable) { return variable.toUpperCase() == variable }
let text = "";
let char;
for (var i = 0; i < str.length; i++) {
char = str.charAt(i);
if (isLower(char)) { char = char.toUpperCase() } else { if (isUpper(char)) char = char.toLowerCase() }
text += char
}
return text
}
Конвертирование в формат предложений: новая строка с заглавной буквы — formatSentence
function formatSentence(str) {
return str.toLowerCase().replace(/((^\s*\D|[\.\!\?\n]\s*\D))/g, function (c) {
return c.toUpperCase();
});
}
На этом с функциями все.
Во второй части осталось разобраться с логикой.