I'm building a telegram bot to remind me changing my car oil part 3
Welcome to the part 3 of my journey to create a telegram bot that will remind me changing my car oil.
Checkout part 1 (opens new window) and part 2 (opens new window) for context.
# Today was productive AF
- Today was productive AF
- Demo Preview
- Ask Questions and record answers
- Database Structure
- Project Structure
- Multiple Language support ❤ 🌎
- What next
# Demo Preview
I got the bot to ask questions and record answers. Here's a demo 👇!
Full demo can be found on Imugr 👉 https://imgur.com/a/gPkI95A (opens new window);
# Ask Questions and record answers
Oilly now can ask questions like, "what is your current mileage?", and make sure to correctly record the answers in the database.
# Telegram persistance problem
Unfortunately telegram wont let you send any custom data with the message you have to debend on the text you send to record answers and here where I get stuck for 3 hours trying to find a way around.
Let me explain the problem in another way:
When Oilly asks the user What is the current mileage in (km) as shown in your car dashboard? and waits for an answer there's no way for me to know wither the following text will be answer for this question or not because telegram doesn't return the message id in this case the question id, nor let you send custom data with the message.
bot.sendMessage(chat.id, "What is the current mileage in (km) as shown in your car dashboard?", {
reply_markup: {
// Options that doesn't contain custom data
},
});
1 cup of coffee and 21 Google results later I had this idea: Question Session .
# Question Session
When Oilly asks the user a question it opens a session for that user with a question id and waits for an answers, then the user type the answer and tap done.
# Database Structure
# Users Table (Collection)
Started with simple table that holds user information from the telegram user object (opens new window).
# Questions answers Table (Collection)
After every answer user have to tap Done to record the answer. A collection called questions_answers
will get the latest answer from question_sessions
collection and record answer in a document with a unique key telegramChatId_question_id
# Project Structure
I made some changes to the project structure like extracting every question logic into it's own file on questions
folder.
That helped me organinsing the code even more here's an example from the current-mileage.js
question file.
const askCurrentMileage = async (/** @type {TelegramBot.Chat}*/ chat) => {
bot.sendMessage(chat.id, lang.__('current_mileage_question'), {
reply_markup: {
force_reply: true,
selective: true,
input_field_placeholder: '25000',
},
});
// open question session
const questionSessionData = {
id: 1,
question: 'current_mileage_question',
answer: null,
created_at: serverTimestamp(),
};
await setDoc(doc(db, 'question_sessions', String(chat.id).toString()), { ...questionSessionData, created_at: serverTimestamp() });
bot.sendMessage(chat.id, lang.__('enter_correct_then_done'), {
reply_markup: {
inline_keyboard: [
[
{
text: lang.__('Done'),
callback_data: JSON.stringify({
type: 'done_answer',
value: 1,
}),
},
],
],
},
});
};
const validationLogicForCurrentMileage = (answer) => {
return isNumber(answer) && answer > 0;
};
# Multiple Language support ❤ 🌎
I believe that everyone no matter what lanague they speak deserve a chance to experience software at their native language.
Added language support using i18n
npm package (opens new window) and I intend to opensource this bot so other people can contribute to translating it!
# What next
- Implement the calculation algorithm.
- Implement the cronjobs logic.
- Deploy to vercel.
- Test
- Opensouce
To be continue...