Skip to content

Instantly share code, notes, and snippets.

@joeljerushan
Created January 27, 2025 03:24
Show Gist options
  • Save joeljerushan/4a9a7ee40dba0fdd27e6fa8d74a1a81e to your computer and use it in GitHub Desktop.
Save joeljerushan/4a9a7ee40dba0fdd27e6fa8d74a1a81e to your computer and use it in GitHub Desktop.
Telegram Bot API
import express from 'express';
import dotenv from 'dotenv';
import { Telegraf } from 'telegraf';
import { DateTime } from 'luxon';
import { MongoClient } from 'mongodb';
dotenv.config();
// MongoDB Connection Setup
const URI = process.env.ATLAS_URI;
const client = new MongoClient(URI, {});
const db = client.db('appdev');
const dbcod = client.db('cod');
const userStates = {};
const router = express.Router();
// Initialize the Telegram bot using the token from the .env file
const bot = new Telegraf(process.env.TELEGRAM_BOT_TOKEN);
// Helper function to check if the user already exists in the database
async function getUserFromDB(userId) {
return await dbcod.collection('users').findOne({ userId });
}
// Helper function to save user data to MongoDB
async function saveUserToDB(userId, username, timezone = null) {
const existingUser = await getUserFromDB(userId);
if (!existingUser) {
await dbcod.collection('users').insertOne({
userId,
username,
timezone,
createdAt: new Date(),
});
} else if (timezone && !existingUser.timezone) {
// If timezone is provided but not yet saved for the user, update it
await dbcod
.collection('users')
.updateOne({ userId }, { $set: { timezone } });
}
}
// Helper function to save playtime request data to MongoDB
async function savePlaytimeToDB(
userId,
username,
timezone,
requestedTime,
convertedTimes
) {
await dbcod.collection('users_playtime').insertOne({
userId,
username,
timezone,
requestedTime,
convertedTimes,
createdAt: new Date(),
});
}
// Automatically start the interaction by checking user timezone
bot.start(async (ctx) => {
const userId = ctx.from.id;
const username = ctx.from.username;
// Check if the user already exists in the database
const user = await getUserFromDB(userId);
if (user && user.timezone) {
// If the user has already selected a timezone, greet them and allow time input
userStates[userId] = {
timeZone: user.timezone,
state: 'waitingForTime',
};
await ctx.reply(
`Hey, ${username}!\nPlease enter the time (e.g., 08:15, 815, 8, 08, 0815):`
);
} else {
// If user is new or hasn't selected a timezone, save their details and ask for timezone
await saveUserToDB(userId, username);
ctx.reply(
`πŸ‘‹ Hello ${username}! Call of Duty Play Time Converter Bot.\n🌍 Select your time zone:`,
{
reply_markup: {
inline_keyboard: [
[
{
text: 'πŸ‡±πŸ‡° Sri Lanka',
callback_data: 'Asia/Colombo',
},
],
[{ text: 'πŸ‡§πŸ‡­ Bahrain', callback_data: 'Asia/Bahrain' }],
[
{
text: 'πŸ‡©πŸ‡° Denmark',
callback_data: 'Europe/Copenhagen',
},
],
[{ text: 'πŸ‡¦πŸ‡ͺ Dubai', callback_data: 'Asia/Dubai' }],
],
},
}
);
userStates[userId] = { state: 'waitingForTimeZone' };
}
});
// Handle the timezone selection (from inline buttons)
bot.on('callback_query', async (ctx) => {
const userId = ctx.from.id;
const stateData = userStates[userId];
if (stateData && stateData.state === 'waitingForTimeZone') {
const timeZone = ctx.callbackQuery.data;
const username = ctx.from.username;
await saveUserToDB(userId, username, timeZone);
userStates[userId] = { timeZone, state: 'waitingForTime' };
await ctx.reply('Enter the time (e.g., 08:15, 815, 8, 08, 0815):');
}
});
// Utility function to normalize time input
function normalizeTime(inputTime) {
inputTime = inputTime.trim();
if (/^\d{1,2}$/.test(inputTime)) {
return inputTime.padStart(2, '0') + ':00';
} else if (/^\d{3}$/.test(inputTime)) {
return inputTime.padStart(4, '0').replace(/(\d{2})(\d{2})/, '$1:$2');
} else if (/^\d{4}$/.test(inputTime)) {
return inputTime.replace(/(\d{2})(\d{2})/, '$1:$2');
} else if (/^\d{1,2}:\d{2}$/.test(inputTime)) {
return inputTime;
}
return null;
}
// Utility function to parse the user input time and timezone
function parseUserTime(inputTime, timeZone) {
const time = inputTime.trim();
const parsedTime = DateTime.fromFormat(time, 'HH:mm', {
zone: timeZone,
});
if (parsedTime.isValid) {
return parsedTime;
}
console.error('Invalid time format:', time);
return null;
}
// Function to convert the time to other time zones
function convertToOtherTimeZones(timeInUserZone) {
return {
bahrain: timeInUserZone.setZone('Asia/Bahrain').toFormat('HH:mm'),
denmark: timeInUserZone.setZone('Europe/Copenhagen').toFormat('HH:mm'),
dubai: timeInUserZone.setZone('Asia/Dubai').toFormat('HH:mm'),
sriLanka: timeInUserZone.setZone('Asia/Colombo').toFormat('HH:mm'),
};
}
// Listen for time input from user
bot.on('text', async (ctx) => {
const userId = ctx.from.id;
const stateData = userStates[userId];
if (stateData && stateData.timeZone) {
let userInput = ctx.message.text.trim();
const timeZone = stateData.timeZone;
userInput = normalizeTime(userInput);
if (!userInput) {
ctx.reply(
'Invalid time input. Provide the time (e.g., 08:15, 815, 8, 08, 0815).'
);
return;
}
const parsedTime = parseUserTime(userInput, timeZone);
if (parsedTime) {
const convertedTimes = convertToOtherTimeZones(
parsedTime,
timeZone
);
const username = ctx.from.username;
await savePlaytimeToDB(
userId,
username,
timeZone,
userInput,
convertedTimes
);
const today = DateTime.now().toFormat('cccc, dd LLL yyyy');
return ctx.reply(
`\`\`\`\nToday's Proposal (${today}) is:\n` +
`πŸ‡§πŸ‡­ Bahrain: ${convertedTimes.bahrain}\n` +
`πŸ‡©πŸ‡° Denmark: ${convertedTimes.denmark}\n` +
`πŸ‡¦πŸ‡ͺ Dubai: ${convertedTimes.dubai}\n` +
`πŸ‡±πŸ‡° Sri Lanka: ${convertedTimes.sriLanka}\n` +
`\`\`\``,
{ parse_mode: 'MarkdownV2' }
);
} else {
ctx.reply(
'Invalid time input. Provide the time in a valid format (e.g., 08:15, 815, 8, 08, 0815).'
);
}
} else {
ctx.reply('Please select a timezone first.');
}
});
// Start the bot
router.use('/start-bot', (req, res) => {
bot.launch();
res.send('Telegram bot started successfully!');
});
export { router as default, db, dbcod, client };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment