├── .dockerignore ├── .gitignore ├── data.json ├── server.js ├── package.json ├── readme.md ├── botFirebase.ts ├── botFirebase.js ├── bot.ts ├── bot.js └── tsconfig.json /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | 4 | -------------------------------------------------------------------------------- /data.json: -------------------------------------------------------------------------------- 1 | { 2 | "-1002384250103": [ 3 | { 4 | "username": "@stevespiros", 5 | "date": "19-11" 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | 3 | const app = express(); 4 | const PORT = process.env.PORT || 8000; 5 | 6 | // Health check endpoint 7 | app.get("/health", (req, res) => { 8 | res.status(200).send("OK"); 9 | }); 10 | 11 | // Start the server 12 | app.listen(PORT, () => { 13 | console.log(`Health check server running on port ${PORT}`); 14 | }); 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@types/firebase": "^2.4.32", 4 | "@types/node": "^22.13.0", 5 | "@types/node-cron": "^3.0.11", 6 | "typescript": "^5.7.3" 7 | }, 8 | "dependencies": { 9 | "@firebase/firestore": "^4.7.8", 10 | "dotenv": "^16.4.7", 11 | "express": "^4.21.2", 12 | "firebase": "^11.3.1", 13 | "grammy": "^1.34.1", 14 | "node-cron": "^3.0.3" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 🎉 Birthday Bot 2 | 3 | A Telegram bot that helps you keep track of and celebrate birthdays! 🎂 4 | 5 | ## 📱 Find bot at **@official_birthday_bot** 6 | 7 | ## 🚀 Features 8 | - `/start` - Start the bot and see a welcome message. 9 | - `/addbirthday` - Add a birthday to the list. 10 | - `/deletebirthday` - Remove a birthday from the list. 11 | - `/upcomingbirthdays [time range]` - View upcoming birthdays within a given time range. 12 | - `/listbirthdays` - Show all saved birthdays. 13 | - Automatically sends birthday wishes on the special day! 🎈 14 | 15 | --- 16 | 17 | ## 📦 Installation & Setup 18 | 19 | ### **1️⃣ Clone the Repository** 20 | ```sh 21 | git clone https://github.com/Brooksolomon/Birthday-bot.git 22 | cd Birthday-bot 23 | ``` 24 | 25 | ### **2️⃣ Install Dependencies** 26 | ```sh 27 | npm install 28 | ``` 29 | 30 | ### **3️⃣ Configure Environment Variables** 31 | Create a `.env` file in the root directory and add the following: 32 | ```env 33 | BOT_TOKEN=your-telegram-bot-token 34 | FIREBASE_API_KEY=your-firebase-api-key 35 | FIREBASE_AUTH_DOMAIN=your-firebase-auth-domain 36 | FIREBASE_PROJECT_ID=your-firebase-project-id 37 | FIREBASE_STORAGE_BUCKET=your-firebase-storage-bucket 38 | FIREBASE_MESSAGING_SENDER_ID=your-firebase-messaging-sender-id 39 | FIREBASE_APP_ID=your-firebase-app-id 40 | FIREBASE_MEASUREMENT_ID=your-firebase-measuerment-id 41 | ``` 42 | Make sure **not** to share your API keys! 43 | 44 | ### **4️⃣Compile and Run the Bot** 45 | ```sh 46 | npx tsc 47 | node bot.js 48 | ``` 49 | 50 | --- 51 | 52 | ## 🤝 Contributing 53 | We welcome contributions to improve **Birthday Bot**! Follow these steps to contribute: 54 | 55 | ### **1️⃣ Fork the Repository** 56 | Click on the **Fork** button at the top-right of this repo to create your own copy. 57 | 58 | ### **2️⃣ Clone Your Fork** 59 | ```sh 60 | git clone https://github.com/your-username/Birthday-bot.git 61 | cd Birthday-bot 62 | ``` 63 | 64 | ### **3️⃣ Create a New Branch** 65 | ```sh 66 | git checkout -b feature-name 67 | ``` 68 | 69 | ### **4️⃣ Make Your Changes** 70 | Modify the code and add your improvements. 71 | 72 | ### **5️⃣ Commit Your Changes** 73 | ```sh 74 | git add . 75 | git commit -m "Added new feature" 76 | ``` 77 | 78 | ### **6️⃣ Push to Your Fork** 79 | ```sh 80 | git push origin feature-name 81 | ``` 82 | 83 | ### **7️⃣ Submit a Pull Request** 84 | Go to the **original repo** and create a **Pull Request** from your fork. 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /botFirebase.ts: -------------------------------------------------------------------------------- 1 | import { initializeApp } from "firebase/app"; 2 | import { getFirestore, collection, addDoc, setDoc, doc, query, where, getDoc, getDocs, deleteDoc } from 'firebase/firestore/lite'; 3 | import dotenv from "dotenv"; 4 | dotenv.config(); 5 | 6 | // Firebase configuration 7 | const firebaseConfig = { 8 | apiKey: process.env.FIREBASE_API_KEY, 9 | authDomain: process.env.FIREBASE_AUTH_DOMAIN, 10 | projectId: process.env.FIREBASE_PROJECT_ID, 11 | storageBucket: process.env.FIREBASE_STORAGE_BUCKET, 12 | messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID, 13 | appId: process.env.FIREBASE_APP_ID, 14 | measurementId: process.env.FIREBASE_MEASUREMENT_ID 15 | }; 16 | 17 | const app = initializeApp(firebaseConfig); 18 | const db = getFirestore(app); 19 | async function addBirthday(chatId: string, username: string, date: string) { 20 | const chatRef = doc(db, "chats", chatId); 21 | const chatDoc = await getDoc(chatRef); 22 | 23 | let birthdays: { username: string; date: string }[] = []; 24 | if (chatDoc.exists()) { 25 | birthdays = chatDoc.data()?.birthdays || []; 26 | } 27 | 28 | // Check for duplicates 29 | const duplicate = birthdays.some(birthday => birthday.username === username && birthday.date === date); 30 | if (duplicate) { 31 | return `Birthday for ${username} on ${date} already exists.`; 32 | } 33 | 34 | birthdays.push({ username, date }); 35 | await setDoc(chatRef, { birthdays }); 36 | 37 | return `Added birthday for ${username}`; 38 | } 39 | 40 | async function deleteBirthday(chatId: string, username: string) { 41 | const chatRef = doc(db, "chats", chatId); 42 | const chatDoc = await getDoc(chatRef); 43 | 44 | if (!chatDoc.exists()) { 45 | return 'No birthdays found for this chat'; 46 | } 47 | 48 | const birthdays: { username: string; date: string }[] = chatDoc.data()?.birthdays || []; 49 | const updatedBirthdays = birthdays.filter(birthday => birthday.username !== username); 50 | 51 | if (updatedBirthdays.length === birthdays.length) { 52 | return `No birthday found for ${username}`; 53 | } 54 | 55 | await setDoc(chatRef, { birthdays: updatedBirthdays }); 56 | 57 | return `Successfully deleted birthday for ${username}`; 58 | } 59 | 60 | async function getBirthdays (chatId: string) { 61 | const chatRef = doc(db, "chats", chatId); 62 | const chatDoc = await getDoc(chatRef); 63 | 64 | if (!chatDoc.exists()) { 65 | return []; 66 | } 67 | 68 | return chatDoc.data()?.birthdays || []; 69 | } 70 | 71 | async function getUpcomingBirthdays(chatId: string, range: "1w" | "1m" | "3m") { 72 | const chatRef = doc(db, "chats", chatId); 73 | const chatDoc = await getDoc(chatRef); 74 | 75 | if (!chatDoc.exists()) { 76 | return []; 77 | } 78 | 79 | const birthdays: { username: string; date: string }[] = chatDoc.data()?.birthdays || []; 80 | const now = new Date(); 81 | const start = new Date(now); 82 | let end = new Date(now); 83 | 84 | if (range === "1w") { 85 | end.setDate(now.getDate() + 7); 86 | } else if (range === "1m") { 87 | end.setMonth(now.getMonth() + 1); 88 | } else if (range === "3m") { 89 | end.setMonth(now.getMonth() + 3); 90 | } 91 | return birthdays.filter(birthday => { 92 | const [day, month] = birthday.date.split("-").map(Number); 93 | const birthdayDate = new Date(now.getFullYear(), month - 1, day); 94 | return birthdayDate >= start && birthdayDate <= end; 95 | }); 96 | } 97 | 98 | async function getAllBirthdays() { 99 | const chatRef = collection(db, "chats"); 100 | const chatDocs = await getDocs(chatRef); 101 | const birthdays = chatDocs.docs.reduce((acc, doc) => { 102 | acc[doc.id] = doc.data().birthdays || []; 103 | return acc; 104 | }, {} as { [key: string]: { username: string; date: string }[] }); 105 | 106 | return birthdays; 107 | } 108 | 109 | export const FireFunc = { 110 | addBirthday, 111 | deleteBirthday, 112 | getBirthdays, 113 | getUpcomingBirthdays, 114 | getAllBirthdays 115 | // checkBirthdays 116 | } 117 | 118 | async function run() { 119 | // await addBirthday('123', '@Alice', '14-02'); 120 | 121 | } 122 | 123 | run(); -------------------------------------------------------------------------------- /botFirebase.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | var __importDefault = (this && this.__importDefault) || function (mod) { 12 | return (mod && mod.__esModule) ? mod : { "default": mod }; 13 | }; 14 | Object.defineProperty(exports, "__esModule", { value: true }); 15 | exports.FireFunc = void 0; 16 | const app_1 = require("firebase/app"); 17 | const lite_1 = require("firebase/firestore/lite"); 18 | const dotenv_1 = __importDefault(require("dotenv")); 19 | dotenv_1.default.config(); 20 | // Firebase configuration 21 | const firebaseConfig = { 22 | apiKey: process.env.FIREBASE_API_KEY, 23 | authDomain: process.env.FIREBASE_AUTH_DOMAIN, 24 | projectId: process.env.FIREBASE_PROJECT_ID, 25 | storageBucket: process.env.FIREBASE_STORAGE_BUCKET, 26 | messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID, 27 | appId: process.env.FIREBASE_APP_ID, 28 | measurementId: process.env.FIREBASE_MEASUREMENT_ID 29 | }; 30 | const app = (0, app_1.initializeApp)(firebaseConfig); 31 | const db = (0, lite_1.getFirestore)(app); 32 | function addBirthday(chatId, username, date) { 33 | return __awaiter(this, void 0, void 0, function* () { 34 | var _a; 35 | const chatRef = (0, lite_1.doc)(db, "chats", chatId); 36 | const chatDoc = yield (0, lite_1.getDoc)(chatRef); 37 | let birthdays = []; 38 | if (chatDoc.exists()) { 39 | birthdays = ((_a = chatDoc.data()) === null || _a === void 0 ? void 0 : _a.birthdays) || []; 40 | } 41 | // Check for duplicates 42 | const duplicate = birthdays.some(birthday => birthday.username === username && birthday.date === date); 43 | if (duplicate) { 44 | return `Birthday for ${username} on ${date} already exists.`; 45 | } 46 | birthdays.push({ username, date }); 47 | yield (0, lite_1.setDoc)(chatRef, { birthdays }); 48 | return `Added birthday for ${username}`; 49 | }); 50 | } 51 | function deleteBirthday(chatId, username) { 52 | return __awaiter(this, void 0, void 0, function* () { 53 | var _a; 54 | const chatRef = (0, lite_1.doc)(db, "chats", chatId); 55 | const chatDoc = yield (0, lite_1.getDoc)(chatRef); 56 | if (!chatDoc.exists()) { 57 | return 'No birthdays found for this chat'; 58 | } 59 | const birthdays = ((_a = chatDoc.data()) === null || _a === void 0 ? void 0 : _a.birthdays) || []; 60 | const updatedBirthdays = birthdays.filter(birthday => birthday.username !== username); 61 | if (updatedBirthdays.length === birthdays.length) { 62 | return `No birthday found for ${username}`; 63 | } 64 | yield (0, lite_1.setDoc)(chatRef, { birthdays: updatedBirthdays }); 65 | return `Successfully deleted birthday for ${username}`; 66 | }); 67 | } 68 | function getBirthdays(chatId) { 69 | return __awaiter(this, void 0, void 0, function* () { 70 | var _a; 71 | const chatRef = (0, lite_1.doc)(db, "chats", chatId); 72 | const chatDoc = yield (0, lite_1.getDoc)(chatRef); 73 | if (!chatDoc.exists()) { 74 | return []; 75 | } 76 | return ((_a = chatDoc.data()) === null || _a === void 0 ? void 0 : _a.birthdays) || []; 77 | }); 78 | } 79 | function getUpcomingBirthdays(chatId, range) { 80 | return __awaiter(this, void 0, void 0, function* () { 81 | var _a; 82 | const chatRef = (0, lite_1.doc)(db, "chats", chatId); 83 | const chatDoc = yield (0, lite_1.getDoc)(chatRef); 84 | if (!chatDoc.exists()) { 85 | return []; 86 | } 87 | const birthdays = ((_a = chatDoc.data()) === null || _a === void 0 ? void 0 : _a.birthdays) || []; 88 | const now = new Date(); 89 | const start = new Date(now); 90 | let end = new Date(now); 91 | if (range === "1w") { 92 | end.setDate(now.getDate() + 7); 93 | } 94 | else if (range === "1m") { 95 | end.setMonth(now.getMonth() + 1); 96 | } 97 | else if (range === "3m") { 98 | end.setMonth(now.getMonth() + 3); 99 | } 100 | return birthdays.filter(birthday => { 101 | const [day, month] = birthday.date.split("-").map(Number); 102 | const birthdayDate = new Date(now.getFullYear(), month - 1, day); 103 | return birthdayDate >= start && birthdayDate <= end; 104 | }); 105 | }); 106 | } 107 | function getAllBirthdays() { 108 | return __awaiter(this, void 0, void 0, function* () { 109 | const chatRef = (0, lite_1.collection)(db, "chats"); 110 | const chatDocs = yield (0, lite_1.getDocs)(chatRef); 111 | const birthdays = chatDocs.docs.reduce((acc, doc) => { 112 | acc[doc.id] = doc.data().birthdays || []; 113 | return acc; 114 | }, {}); 115 | return birthdays; 116 | }); 117 | } 118 | exports.FireFunc = { 119 | addBirthday, 120 | deleteBirthday, 121 | getBirthdays, 122 | getUpcomingBirthdays, 123 | getAllBirthdays 124 | // checkBirthdays 125 | }; 126 | function run() { 127 | return __awaiter(this, void 0, void 0, function* () { 128 | // await addBirthday('123', '@Alice', '14-02'); 129 | }); 130 | } 131 | run(); 132 | -------------------------------------------------------------------------------- /bot.ts: -------------------------------------------------------------------------------- 1 | import { Bot } from "grammy"; 2 | import cron from "node-cron"; 3 | import dotenv from "dotenv"; 4 | dotenv.config(); 5 | import { FireFunc } from "./botFirebase"; 6 | 7 | 8 | 9 | const botToken = process.env.BOT_TOKEN; 10 | if (!botToken) { 11 | throw new Error("BOT_TOKEN is not defined in the environment variables"); 12 | } 13 | const bot = new Bot(botToken); 14 | interface Message{ 15 | username : string, 16 | date:string, 17 | } 18 | interface ChatData{ 19 | [chatId: string]: Message[]; 20 | } 21 | 22 | 23 | const birthdayMessages = [ 24 | "🎂 Wishing you a day filled with love, laughter, and all your favorite things. Happy Birthday, {username}! 🎉", 25 | "🎉 May this special day bring you endless joy and happiness. Have a fantastic birthday, {username}! 🥳", 26 | "🥳 Happy Birthday, {username}! May this year be your best one yet, filled with success, love, and adventure! 🎈", 27 | "🎁 Sending you warm hugs and lots of love on your special day, {username}. Hope it's as amazing as you are! ❤️", 28 | "🎊 Another year older, wiser, and even more awesome! Happy Birthday, {username}! Have a fantastic day! 🎂", 29 | "🌟 Wishing you a birthday that's as special and wonderful as you are, {username}. Have an amazing day! 🎉", 30 | "🎈 May all your dreams and wishes come true this year, {username}. Have a spectacular birthday! 🥳", 31 | "🎂 Cheers to another year of blessings and new opportunities, {username}. Wishing you happiness always! 🎊", 32 | "🎉 On your special day, I hope you're surrounded by love, laughter, and everything that makes you happy. Happy Birthday, {username}! 🎁", 33 | "🥳 Today is all about you, {username}! Enjoy your day to the fullest! Wishing you a year full of happiness and success. 🎂", 34 | "🎊 May today bring you endless joy and may the year ahead be full of wonderful surprises, {username}! Happy Birthday! 🎈", 35 | "🎉 Wishing you sunshine, love, and laughter on your birthday, {username}! May this be your best year yet! 🥳", 36 | "🥂 Here's to another amazing year ahead, {username}! May your birthday be filled with all the things you love most. 🎂", 37 | "🎈 Happy Birthday, {username}! May today be as bright and beautiful as your smile. Keep shining! 🌟", 38 | "🎂 Hope this birthday brings you closer to all your dreams, {username}. Have a fantastic day ahead! 🥳", 39 | "🎊 The world is a better place with you in it, {username}. Wishing you a day filled with love and joy! ❤️", 40 | "🎉 May this birthday be the start of a wonderful year ahead. Enjoy your special day, {username}! 🎂", 41 | "🥳 Another year of greatness ahead! Wishing you the happiest of birthdays, {username}! 🎈", 42 | "🎁 Your kindness and warmth make the world brighter. Happy Birthday, {username}! Hope your day is as wonderful as you! 🌟", 43 | "🎂 Sending you all the love and happiness in the world, {username}. Have an amazing birthday! 🥳", 44 | "🎈 Wishing you a birthday that's as fun and fantastic as you are, {username}! Enjoy your day to the fullest! 🎉", 45 | "🥂 May today be a celebration of all the amazing things that make you special, {username}! Happy Birthday! 🎊", 46 | "🎉 Every moment with you is special, but today is extra special. Happy Birthday, {username}! Have a blast! 🎂", 47 | "🎈 May your birthday be filled with love, joy, and unforgettable memories, {username}. Cheers to another great year! 🥳", 48 | "🎊 Another trip around the sun, another chance to make amazing memories. Happy Birthday, {username}! 🎁", 49 | "🎂 Wishing you laughter, love, and everything wonderful on your birthday, {username}. Have an incredible day! 🎉", 50 | "🎈 Your presence is a gift to the world, {username}. Wishing you the happiest birthday ever! 🥂", 51 | "🥳 May this year bring you all the happiness and success you deserve, {username}. Have an amazing birthday! 🎂", 52 | "🎊 You make the world a brighter place. Hope your birthday is just as bright and joyful, {username}! 🎉", 53 | "🎁 Every birthday is a new beginning. Wishing you endless possibilities and happiness, {username}! 🥳", 54 | "🎈 The best things in life are yet to come! Enjoy your special day to the fullest, {username}! 🎂", 55 | "🎉 You bring joy to so many people. May today bring that same joy back to you, {username}! Happy Birthday! 🎊", 56 | "🎂 A wonderful person like you deserves the best birthday ever! Hope you have a fantastic day, {username}! 🥳", 57 | "🎊 Life is a journey, and yours is truly inspiring! Wishing you an amazing year ahead, {username}! 🎁", 58 | "🥂 Every candle on your cake is a wish come true. Hope all your dreams come true too, {username}! 🎂", 59 | "🎉 Happy Birthday, {username}! May this year be full of love, laughter, and success! 🎊", 60 | "🎈 On this day, a star was born! Keep shining, {username}! Wishing you the happiest of birthdays! 🎂", 61 | "🥳 Cheers to another year of making unforgettable memories, {username}! Hope your day is fantastic! 🎊", 62 | "🎂 Wishing you nothing but love and happiness today and always, {username}. Have a fantastic birthday! 🎉", 63 | "🎈 May your birthday be filled with good vibes, great friends, and unforgettable moments, {username}! 🥂", 64 | "🎊 Sending you warm wishes and lots of love on your special day, {username}. Hope it’s the best one yet! 🎁", 65 | "🎂 Life is a gift, and so are you! Hope your birthday is as amazing as you are, {username}! 🎉", 66 | "🥳 Today is all about celebrating YOU! Wishing you a wonderful birthday, {username}! 🎊", 67 | "🎈 Birthdays come and go, but amazing people like you make the world a better place! Happy Birthday, {username}! 🎁", 68 | "🎉 May this day bring you closer to your dreams, {username}. Wishing you happiness and success always! 🎂", 69 | "🎊 Wishing you a birthday filled with love, joy, and all the cake you can eat, {username}! 🥳", 70 | "🎂 Your kindness and positivity inspire everyone around you, {username}. Have a truly fantastic birthday! 🎉", 71 | "🎈 May your birthday be as bright and joyful as your beautiful soul, {username}! 🎁", 72 | "🎊 No matter how many birthdays come and go, you’ll always be young at heart, {username}! Stay awesome! 🎂" 73 | ]; 74 | 75 | const sendBirthdayMessage = async (chatId: string, username: string) => { 76 | // Select a random message 77 | const message = birthdayMessages[Math.floor(Math.random() * birthdayMessages.length)] 78 | .replace("{username}", username); 79 | 80 | try { 81 | await bot.api.sendMessage(chatId, message); 82 | console.log(`Sent birthday message to ${username}`); 83 | } catch (error) { 84 | console.log(`Failed to send message to ${username}: ${error}`); 85 | } 86 | }; 87 | 88 | const checkBirthdays = async () => { 89 | console.log("Checking birthdays..."); 90 | const today = new Date(); 91 | const todayFormatted = `${String(today.getDate()).padStart(2, '0')}-${String(today.getMonth() + 1).padStart(2, '0')}`; 92 | const birthdays: ChatData = await FireFunc.getAllBirthdays(); 93 | 94 | Object.keys(birthdays).forEach(chatId => { 95 | birthdays[chatId].forEach(birthday => { 96 | if (birthday.date === todayFormatted) { 97 | sendBirthdayMessage(chatId, birthday.username); 98 | } 99 | }); 100 | }); 101 | }; 102 | 103 | 104 | 105 | 106 | bot.command("start", (ctx) => ctx.reply("Welcome! Up and running.")); 107 | 108 | // Function to validate the date format (dd-mm) 109 | function isValidDate(date:string): boolean { 110 | const dateRegex = /^(0[1-9]|[12][0-9]|3[01])-(0[1-9]|1[0-2])$/; // dd-mm format 111 | return dateRegex.test(date); 112 | } 113 | 114 | // Handle /addbirthday command 115 | bot.command("addbirthday", (ctx) => { 116 | if (!ctx.message || !ctx.message.text) { 117 | return ctx.reply("⚠️ Unable to process the message."); 118 | } 119 | const text = ctx.message.text.trim(); 120 | const args = text.split(" "); 121 | 122 | if (args.length !== 3 || !args[1].startsWith("@")) { 123 | return ctx.reply("⚠️ Incorrect format!\nUse: `/addbirthday @username dd-mm`", { parse_mode: "Markdown" }); 124 | } 125 | 126 | const username = args[1]; 127 | const date = args[2]; 128 | 129 | if (!isValidDate(date)) { 130 | return ctx.reply("⚠️ Invalid date format!\nPlease enter the date in `dd-mm` format. (e.g., `05-09` for 5th Sept)", { parse_mode: "Markdown" }); 131 | } 132 | console.log(); 133 | 134 | FireFunc.addBirthday(String(ctx.message.chat.id), username, date) 135 | .then(response => ctx.reply(response || "Birthday added successfully")) 136 | .catch(error => ctx.reply(`Failed to add birthday: ${error}`)); 137 | }); 138 | 139 | bot.command("deletebirthday", (ctx) => { 140 | if (!ctx.message || !ctx.message.text) { 141 | return ctx.reply("⚠️ Unable to process the message."); 142 | } 143 | const text = ctx.message.text.trim(); 144 | const args = text.split(" "); 145 | 146 | if (args.length !== 2 || !args[1].startsWith("@")) { 147 | return ctx.reply("⚠️ Incorrect format!\nUse: `/deletebirthday @username`", { parse_mode: "Markdown" }); 148 | } 149 | 150 | const username = args[1]; 151 | const chatId = String(ctx.message.chat.id); 152 | 153 | FireFunc.deleteBirthday(String(ctx.message.chat.id), username) 154 | .then(response => ctx.reply(response || "Birthday deleted successfully")) 155 | .catch(error => ctx.reply(`Failed to delete birthday: ${error}`)); 156 | }); 157 | 158 | bot.command("upcomingbirthdays", async (ctx) => { 159 | if (!ctx.message || !ctx.message.text) { 160 | return ctx.reply("⚠️ Unable to process the message."); 161 | } 162 | const text = ctx.message.text.trim(); 163 | const args = text.split(" "); 164 | 165 | if (args.length !== 2) { 166 | return ctx.reply("⚠️ Incorrect format!\nUse: `/upcomingbirthdays 1w or 1m or 3m`", { parse_mode: "Markdown" }); 167 | } 168 | 169 | const range = args[1]; 170 | const chatId = String(ctx.message.chat.id); 171 | if (range!=="1w" && range!=="1m" && range!=="3m") { 172 | return ctx.reply("⚠️ Incorrect format!\nUse: `/upcomingbirthdays 1w or 1m or 3m`", { parse_mode: "Markdown" }); 173 | } 174 | const upcomingBirthdays = await FireFunc.getUpcomingBirthdays(chatId, range as "1w" | "1m" | "3m"); 175 | 176 | 177 | if (upcomingBirthdays.length === 0) { 178 | return ctx.reply("🎉 No upcoming birthdays found!"); 179 | } 180 | 181 | const message = upcomingBirthdays.map((b) => `👤 ${b.username} - ${b.date}`).join("\n"); 182 | ctx.reply(`🎉 Upcoming birthdays:\n${message}`); 183 | }); 184 | 185 | bot.command("listbirthdays", async (ctx) => { 186 | if (!ctx.message || !ctx.message.text) { 187 | return ctx.reply("⚠️ Unable to process the message."); 188 | } 189 | const chatId = String(ctx.message.chat.id); 190 | const birthdays =await FireFunc.getBirthdays(chatId); 191 | 192 | if (birthdays.length === 0) { 193 | return ctx.reply("🎉 No birthdays found!"); 194 | } 195 | 196 | const message = birthdays.map((b: { username: any; date: any; }) => `👤 ${b.username} - ${b.date}`).join("\n"); 197 | ctx.reply(`🎉 Birthdays:\n${message}`); 198 | 199 | }); 200 | cron.schedule('0 5 * * *', checkBirthdays); 201 | bot.start(); -------------------------------------------------------------------------------- /bot.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | var __importDefault = (this && this.__importDefault) || function (mod) { 12 | return (mod && mod.__esModule) ? mod : { "default": mod }; 13 | }; 14 | Object.defineProperty(exports, "__esModule", { value: true }); 15 | const grammy_1 = require("grammy"); 16 | const node_cron_1 = __importDefault(require("node-cron")); 17 | const dotenv_1 = __importDefault(require("dotenv")); 18 | dotenv_1.default.config(); 19 | const botFirebase_1 = require("./botFirebase"); 20 | const botToken = process.env.BOT_TOKEN; 21 | if (!botToken) { 22 | throw new Error("BOT_TOKEN is not defined in the environment variables"); 23 | } 24 | const bot = new grammy_1.Bot(botToken); 25 | const birthdayMessages = [ 26 | "🎂 Wishing you a day filled with love, laughter, and all your favorite things. Happy Birthday, {username}! 🎉", 27 | "🎉 May this special day bring you endless joy and happiness. Have a fantastic birthday, {username}! 🥳", 28 | "🥳 Happy Birthday, {username}! May this year be your best one yet, filled with success, love, and adventure! 🎈", 29 | "🎁 Sending you warm hugs and lots of love on your special day, {username}. Hope it's as amazing as you are! ❤️", 30 | "🎊 Another year older, wiser, and even more awesome! Happy Birthday, {username}! Have a fantastic day! 🎂", 31 | "🌟 Wishing you a birthday that's as special and wonderful as you are, {username}. Have an amazing day! 🎉", 32 | "🎈 May all your dreams and wishes come true this year, {username}. Have a spectacular birthday! 🥳", 33 | "🎂 Cheers to another year of blessings and new opportunities, {username}. Wishing you happiness always! 🎊", 34 | "🎉 On your special day, I hope you're surrounded by love, laughter, and everything that makes you happy. Happy Birthday, {username}! 🎁", 35 | "🥳 Today is all about you, {username}! Enjoy your day to the fullest! Wishing you a year full of happiness and success. 🎂", 36 | "🎊 May today bring you endless joy and may the year ahead be full of wonderful surprises, {username}! Happy Birthday! 🎈", 37 | "🎉 Wishing you sunshine, love, and laughter on your birthday, {username}! May this be your best year yet! 🥳", 38 | "🥂 Here's to another amazing year ahead, {username}! May your birthday be filled with all the things you love most. 🎂", 39 | "🎈 Happy Birthday, {username}! May today be as bright and beautiful as your smile. Keep shining! 🌟", 40 | "🎂 Hope this birthday brings you closer to all your dreams, {username}. Have a fantastic day ahead! 🥳", 41 | "🎊 The world is a better place with you in it, {username}. Wishing you a day filled with love and joy! ❤️", 42 | "🎉 May this birthday be the start of a wonderful year ahead. Enjoy your special day, {username}! 🎂", 43 | "🥳 Another year of greatness ahead! Wishing you the happiest of birthdays, {username}! 🎈", 44 | "🎁 Your kindness and warmth make the world brighter. Happy Birthday, {username}! Hope your day is as wonderful as you! 🌟", 45 | "🎂 Sending you all the love and happiness in the world, {username}. Have an amazing birthday! 🥳", 46 | "🎈 Wishing you a birthday that's as fun and fantastic as you are, {username}! Enjoy your day to the fullest! 🎉", 47 | "🥂 May today be a celebration of all the amazing things that make you special, {username}! Happy Birthday! 🎊", 48 | "🎉 Every moment with you is special, but today is extra special. Happy Birthday, {username}! Have a blast! 🎂", 49 | "🎈 May your birthday be filled with love, joy, and unforgettable memories, {username}. Cheers to another great year! 🥳", 50 | "🎊 Another trip around the sun, another chance to make amazing memories. Happy Birthday, {username}! 🎁", 51 | "🎂 Wishing you laughter, love, and everything wonderful on your birthday, {username}. Have an incredible day! 🎉", 52 | "🎈 Your presence is a gift to the world, {username}. Wishing you the happiest birthday ever! 🥂", 53 | "🥳 May this year bring you all the happiness and success you deserve, {username}. Have an amazing birthday! 🎂", 54 | "🎊 You make the world a brighter place. Hope your birthday is just as bright and joyful, {username}! 🎉", 55 | "🎁 Every birthday is a new beginning. Wishing you endless possibilities and happiness, {username}! 🥳", 56 | "🎈 The best things in life are yet to come! Enjoy your special day to the fullest, {username}! 🎂", 57 | "🎉 You bring joy to so many people. May today bring that same joy back to you, {username}! Happy Birthday! 🎊", 58 | "🎂 A wonderful person like you deserves the best birthday ever! Hope you have a fantastic day, {username}! 🥳", 59 | "🎊 Life is a journey, and yours is truly inspiring! Wishing you an amazing year ahead, {username}! 🎁", 60 | "🥂 Every candle on your cake is a wish come true. Hope all your dreams come true too, {username}! 🎂", 61 | "🎉 Happy Birthday, {username}! May this year be full of love, laughter, and success! 🎊", 62 | "🎈 On this day, a star was born! Keep shining, {username}! Wishing you the happiest of birthdays! 🎂", 63 | "🥳 Cheers to another year of making unforgettable memories, {username}! Hope your day is fantastic! 🎊", 64 | "🎂 Wishing you nothing but love and happiness today and always, {username}. Have a fantastic birthday! 🎉", 65 | "🎈 May your birthday be filled with good vibes, great friends, and unforgettable moments, {username}! 🥂", 66 | "🎊 Sending you warm wishes and lots of love on your special day, {username}. Hope it’s the best one yet! 🎁", 67 | "🎂 Life is a gift, and so are you! Hope your birthday is as amazing as you are, {username}! 🎉", 68 | "🥳 Today is all about celebrating YOU! Wishing you a wonderful birthday, {username}! 🎊", 69 | "🎈 Birthdays come and go, but amazing people like you make the world a better place! Happy Birthday, {username}! 🎁", 70 | "🎉 May this day bring you closer to your dreams, {username}. Wishing you happiness and success always! 🎂", 71 | "🎊 Wishing you a birthday filled with love, joy, and all the cake you can eat, {username}! 🥳", 72 | "🎂 Your kindness and positivity inspire everyone around you, {username}. Have a truly fantastic birthday! 🎉", 73 | "🎈 May your birthday be as bright and joyful as your beautiful soul, {username}! 🎁", 74 | "🎊 No matter how many birthdays come and go, you’ll always be young at heart, {username}! Stay awesome! 🎂" 75 | ]; 76 | const sendBirthdayMessage = (chatId, username) => __awaiter(void 0, void 0, void 0, function* () { 77 | // Select a random message 78 | const message = birthdayMessages[Math.floor(Math.random() * birthdayMessages.length)] 79 | .replace("{username}", username); 80 | try { 81 | yield bot.api.sendMessage(chatId, message); 82 | console.log(`Sent birthday message to ${username}`); 83 | } 84 | catch (error) { 85 | console.log(`Failed to send message to ${username}: ${error}`); 86 | } 87 | }); 88 | const checkBirthdays = () => __awaiter(void 0, void 0, void 0, function* () { 89 | console.log("Checking birthdays..."); 90 | const today = new Date(); 91 | const todayFormatted = `${String(today.getDate()).padStart(2, '0')}-${String(today.getMonth() + 1).padStart(2, '0')}`; 92 | const birthdays = yield botFirebase_1.FireFunc.getAllBirthdays(); 93 | Object.keys(birthdays).forEach(chatId => { 94 | birthdays[chatId].forEach(birthday => { 95 | if (birthday.date === todayFormatted) { 96 | sendBirthdayMessage(chatId, birthday.username); 97 | } 98 | }); 99 | }); 100 | }); 101 | bot.command("start", (ctx) => ctx.reply("Welcome! Up and running.")); 102 | // Function to validate the date format (dd-mm) 103 | function isValidDate(date) { 104 | const dateRegex = /^(0[1-9]|[12][0-9]|3[01])-(0[1-9]|1[0-2])$/; // dd-mm format 105 | return dateRegex.test(date); 106 | } 107 | // Handle /addbirthday command 108 | bot.command("addbirthday", (ctx) => { 109 | if (!ctx.message || !ctx.message.text) { 110 | return ctx.reply("⚠️ Unable to process the message."); 111 | } 112 | const text = ctx.message.text.trim(); 113 | const args = text.split(" "); 114 | if (args.length !== 3 || !args[1].startsWith("@")) { 115 | return ctx.reply("⚠️ Incorrect format!\nUse: `/addbirthday @username dd-mm`", { parse_mode: "Markdown" }); 116 | } 117 | const username = args[1]; 118 | const date = args[2]; 119 | if (!isValidDate(date)) { 120 | return ctx.reply("⚠️ Invalid date format!\nPlease enter the date in `dd-mm` format. (e.g., `05-09` for 5th Sept)", { parse_mode: "Markdown" }); 121 | } 122 | console.log(); 123 | botFirebase_1.FireFunc.addBirthday(String(ctx.message.chat.id), username, date) 124 | .then(response => ctx.reply(response || "Birthday added successfully")) 125 | .catch(error => ctx.reply(`Failed to add birthday: ${error}`)); 126 | }); 127 | bot.command("deletebirthday", (ctx) => { 128 | if (!ctx.message || !ctx.message.text) { 129 | return ctx.reply("⚠️ Unable to process the message."); 130 | } 131 | const text = ctx.message.text.trim(); 132 | const args = text.split(" "); 133 | if (args.length !== 2 || !args[1].startsWith("@")) { 134 | return ctx.reply("⚠️ Incorrect format!\nUse: `/deletebirthday @username`", { parse_mode: "Markdown" }); 135 | } 136 | const username = args[1]; 137 | const chatId = String(ctx.message.chat.id); 138 | botFirebase_1.FireFunc.deleteBirthday(String(ctx.message.chat.id), username) 139 | .then(response => ctx.reply(response || "Birthday deleted successfully")) 140 | .catch(error => ctx.reply(`Failed to delete birthday: ${error}`)); 141 | }); 142 | bot.command("upcomingbirthdays", (ctx) => __awaiter(void 0, void 0, void 0, function* () { 143 | if (!ctx.message || !ctx.message.text) { 144 | return ctx.reply("⚠️ Unable to process the message."); 145 | } 146 | const text = ctx.message.text.trim(); 147 | const args = text.split(" "); 148 | if (args.length !== 2) { 149 | return ctx.reply("⚠️ Incorrect format!\nUse: `/upcomingbirthdays 1w or 1m or 3m`", { parse_mode: "Markdown" }); 150 | } 151 | const range = args[1]; 152 | const chatId = String(ctx.message.chat.id); 153 | if (range !== "1w" && range !== "1m" && range !== "3m") { 154 | return ctx.reply("⚠️ Incorrect format!\nUse: `/upcomingbirthdays 1w or 1m or 3m`", { parse_mode: "Markdown" }); 155 | } 156 | const upcomingBirthdays = yield botFirebase_1.FireFunc.getUpcomingBirthdays(chatId, range); 157 | if (upcomingBirthdays.length === 0) { 158 | return ctx.reply("🎉 No upcoming birthdays found!"); 159 | } 160 | const message = upcomingBirthdays.map((b) => `👤 ${b.username} - ${b.date}`).join("\n"); 161 | ctx.reply(`🎉 Upcoming birthdays:\n${message}`); 162 | })); 163 | bot.command("listbirthdays", (ctx) => __awaiter(void 0, void 0, void 0, function* () { 164 | if (!ctx.message || !ctx.message.text) { 165 | return ctx.reply("⚠️ Unable to process the message."); 166 | } 167 | const chatId = String(ctx.message.chat.id); 168 | const birthdays = yield botFirebase_1.FireFunc.getBirthdays(chatId); 169 | if (birthdays.length === 0) { 170 | return ctx.reply("🎉 No birthdays found!"); 171 | } 172 | const message = birthdays.map((b) => `👤 ${b.username} - ${b.date}`).join("\n"); 173 | ctx.reply(`🎉 Birthdays:\n${message}`); 174 | })); 175 | node_cron_1.default.schedule('0 5 * * *', checkBirthdays); 176 | bot.start(); 177 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "commonjs", /* Specify what module code is generated. */ 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 39 | // "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */ 40 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 41 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 42 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 43 | // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ 44 | // "resolveJsonModule": true, /* Enable importing .json files. */ 45 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 46 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 47 | 48 | /* JavaScript Support */ 49 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 50 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 51 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 52 | 53 | /* Emit */ 54 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 55 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 56 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 57 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 59 | // "noEmit": true, /* Disable emitting files from a compilation. */ 60 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 61 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 62 | // "removeComments": true, /* Disable emitting comments. */ 63 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 64 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 65 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 66 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 67 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 68 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 69 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 70 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 71 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 72 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 73 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 74 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 75 | 76 | /* Interop Constraints */ 77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 79 | // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ 80 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 81 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 82 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 83 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 84 | 85 | /* Type Checking */ 86 | "strict": true, /* Enable all strict type-checking options. */ 87 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 88 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 89 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 90 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 91 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 92 | // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ 93 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 94 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 95 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 96 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 97 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 98 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 99 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 100 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 101 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 102 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 103 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 104 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 105 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 106 | 107 | /* Completeness */ 108 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 109 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 110 | } 111 | } 112 | --------------------------------------------------------------------------------