├── .dockerignore ├── .gitignore ├── bot.js ├── bot.ts ├── botFirebase.js ├── botFirebase.ts ├── data.json ├── package-lock.json ├── package.json ├── readme.md ├── server.js └── tsconfig.json /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | 4 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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(); -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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(); -------------------------------------------------------------------------------- /data.json: -------------------------------------------------------------------------------- 1 | { 2 | "-1002384250103": [ 3 | { 4 | "username": "@stevespiros", 5 | "date": "19-11" 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Birthday bot", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "@firebase/firestore": "^4.7.8", 9 | "dotenv": "^16.4.7", 10 | "express": "^4.21.2", 11 | "firebase": "^11.3.1", 12 | "grammy": "^1.34.1", 13 | "node-cron": "^3.0.3" 14 | }, 15 | "devDependencies": { 16 | "@types/firebase": "^2.4.32", 17 | "@types/node": "^22.13.0", 18 | "@types/node-cron": "^3.0.11", 19 | "typescript": "^5.7.3" 20 | } 21 | }, 22 | "node_modules/@firebase/analytics": { 23 | "version": "0.10.11", 24 | "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.11.tgz", 25 | "integrity": "sha512-zwuPiRE0+hgcS95JZbJ6DFQN4xYFO8IyGxpeePTV51YJMwCf3lkBa6FnZ/iXIqDKcBPMgMuuEZozI0BJWaLEYg==", 26 | "license": "Apache-2.0", 27 | "dependencies": { 28 | "@firebase/component": "0.6.12", 29 | "@firebase/installations": "0.6.12", 30 | "@firebase/logger": "0.4.4", 31 | "@firebase/util": "1.10.3", 32 | "tslib": "^2.1.0" 33 | }, 34 | "peerDependencies": { 35 | "@firebase/app": "0.x" 36 | } 37 | }, 38 | "node_modules/@firebase/analytics-compat": { 39 | "version": "0.2.17", 40 | "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.17.tgz", 41 | "integrity": "sha512-SJNVOeTvzdqZQvXFzj7yAirXnYcLDxh57wBFROfeowq/kRN1AqOw1tG6U4OiFOEhqi7s3xLze/LMkZatk2IEww==", 42 | "license": "Apache-2.0", 43 | "dependencies": { 44 | "@firebase/analytics": "0.10.11", 45 | "@firebase/analytics-types": "0.8.3", 46 | "@firebase/component": "0.6.12", 47 | "@firebase/util": "1.10.3", 48 | "tslib": "^2.1.0" 49 | }, 50 | "peerDependencies": { 51 | "@firebase/app-compat": "0.x" 52 | } 53 | }, 54 | "node_modules/@firebase/analytics-types": { 55 | "version": "0.8.3", 56 | "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz", 57 | "integrity": "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==", 58 | "license": "Apache-2.0" 59 | }, 60 | "node_modules/@firebase/app": { 61 | "version": "0.11.1", 62 | "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.11.1.tgz", 63 | "integrity": "sha512-Vz4DrNLPfDx3RwQf+4klXtu7OUYDO6xz2hlRyFawWskS7YqdtNzkDDxrqH20KDfjCF1lib46/NgchIj1+8h4wQ==", 64 | "license": "Apache-2.0", 65 | "dependencies": { 66 | "@firebase/component": "0.6.12", 67 | "@firebase/logger": "0.4.4", 68 | "@firebase/util": "1.10.3", 69 | "idb": "7.1.1", 70 | "tslib": "^2.1.0" 71 | }, 72 | "engines": { 73 | "node": ">=18.0.0" 74 | } 75 | }, 76 | "node_modules/@firebase/app-check": { 77 | "version": "0.8.11", 78 | "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.11.tgz", 79 | "integrity": "sha512-42zIfRI08/7bQqczAy7sY2JqZYEv3a1eNa4fLFdtJ54vNevbBIRSEA3fZgRqWFNHalh5ohsBXdrYgFqaRIuCcQ==", 80 | "license": "Apache-2.0", 81 | "dependencies": { 82 | "@firebase/component": "0.6.12", 83 | "@firebase/logger": "0.4.4", 84 | "@firebase/util": "1.10.3", 85 | "tslib": "^2.1.0" 86 | }, 87 | "engines": { 88 | "node": ">=18.0.0" 89 | }, 90 | "peerDependencies": { 91 | "@firebase/app": "0.x" 92 | } 93 | }, 94 | "node_modules/@firebase/app-check-compat": { 95 | "version": "0.3.18", 96 | "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.18.tgz", 97 | "integrity": "sha512-qjozwnwYmAIdrsVGrJk+hnF1WBois54IhZR6gO0wtZQoTvWL/GtiA2F31TIgAhF0ayUiZhztOv1RfC7YyrZGDQ==", 98 | "license": "Apache-2.0", 99 | "dependencies": { 100 | "@firebase/app-check": "0.8.11", 101 | "@firebase/app-check-types": "0.5.3", 102 | "@firebase/component": "0.6.12", 103 | "@firebase/logger": "0.4.4", 104 | "@firebase/util": "1.10.3", 105 | "tslib": "^2.1.0" 106 | }, 107 | "engines": { 108 | "node": ">=18.0.0" 109 | }, 110 | "peerDependencies": { 111 | "@firebase/app-compat": "0.x" 112 | } 113 | }, 114 | "node_modules/@firebase/app-check-interop-types": { 115 | "version": "0.3.3", 116 | "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz", 117 | "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==", 118 | "license": "Apache-2.0" 119 | }, 120 | "node_modules/@firebase/app-check-types": { 121 | "version": "0.5.3", 122 | "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz", 123 | "integrity": "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==", 124 | "license": "Apache-2.0" 125 | }, 126 | "node_modules/@firebase/app-compat": { 127 | "version": "0.2.50", 128 | "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.50.tgz", 129 | "integrity": "sha512-7yD362icKgjoNvFxwth420TNZgqCfuTJ28yQCdpyjC2fXyaZHhAbxVKnHEXGTAaUKSHWxsIy46lBKGi/x/Mflw==", 130 | "license": "Apache-2.0", 131 | "dependencies": { 132 | "@firebase/app": "0.11.1", 133 | "@firebase/component": "0.6.12", 134 | "@firebase/logger": "0.4.4", 135 | "@firebase/util": "1.10.3", 136 | "tslib": "^2.1.0" 137 | }, 138 | "engines": { 139 | "node": ">=18.0.0" 140 | } 141 | }, 142 | "node_modules/@firebase/app-types": { 143 | "version": "0.9.3", 144 | "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz", 145 | "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==", 146 | "license": "Apache-2.0" 147 | }, 148 | "node_modules/@firebase/auth": { 149 | "version": "1.9.0", 150 | "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.9.0.tgz", 151 | "integrity": "sha512-Xz2mbEYauF689qXG/4HppS2+/yGo9R7B6eNUBh3H2+XpAZTGdx8d8TFsW/BMTAK9Q95NB0pb1Bbvfx0lwofq8Q==", 152 | "license": "Apache-2.0", 153 | "dependencies": { 154 | "@firebase/component": "0.6.12", 155 | "@firebase/logger": "0.4.4", 156 | "@firebase/util": "1.10.3", 157 | "tslib": "^2.1.0" 158 | }, 159 | "engines": { 160 | "node": ">=18.0.0" 161 | }, 162 | "peerDependencies": { 163 | "@firebase/app": "0.x", 164 | "@react-native-async-storage/async-storage": "^1.18.1" 165 | }, 166 | "peerDependenciesMeta": { 167 | "@react-native-async-storage/async-storage": { 168 | "optional": true 169 | } 170 | } 171 | }, 172 | "node_modules/@firebase/auth-compat": { 173 | "version": "0.5.18", 174 | "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.18.tgz", 175 | "integrity": "sha512-dFBev8AMNb2AgIt9afwf/Ku4/0Wq9R9OFSeBB/xjyJt+RfQ9PnNWqU2oFphews23byLg6jle8twRA7iOYfRGRw==", 176 | "license": "Apache-2.0", 177 | "dependencies": { 178 | "@firebase/auth": "1.9.0", 179 | "@firebase/auth-types": "0.13.0", 180 | "@firebase/component": "0.6.12", 181 | "@firebase/util": "1.10.3", 182 | "tslib": "^2.1.0" 183 | }, 184 | "engines": { 185 | "node": ">=18.0.0" 186 | }, 187 | "peerDependencies": { 188 | "@firebase/app-compat": "0.x" 189 | } 190 | }, 191 | "node_modules/@firebase/auth-interop-types": { 192 | "version": "0.2.4", 193 | "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz", 194 | "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==", 195 | "license": "Apache-2.0" 196 | }, 197 | "node_modules/@firebase/auth-types": { 198 | "version": "0.13.0", 199 | "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.13.0.tgz", 200 | "integrity": "sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg==", 201 | "license": "Apache-2.0", 202 | "peerDependencies": { 203 | "@firebase/app-types": "0.x", 204 | "@firebase/util": "1.x" 205 | } 206 | }, 207 | "node_modules/@firebase/component": { 208 | "version": "0.6.12", 209 | "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.12.tgz", 210 | "integrity": "sha512-YnxqjtohLbnb7raXt2YuA44cC1wA9GiehM/cmxrsoxKlFxBLy2V0OkRSj9gpngAE0UoJ421Wlav9ycO7lTPAUw==", 211 | "license": "Apache-2.0", 212 | "dependencies": { 213 | "@firebase/util": "1.10.3", 214 | "tslib": "^2.1.0" 215 | }, 216 | "engines": { 217 | "node": ">=18.0.0" 218 | } 219 | }, 220 | "node_modules/@firebase/data-connect": { 221 | "version": "0.3.0", 222 | "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.3.0.tgz", 223 | "integrity": "sha512-inbLq0JyQD/d02Al3Lso0Hc8z1BVpB3dYSMFcQkeKhYyjn5bspLczLdasPbCOEUp8MOkLblLZhJuRs7Q/spFnw==", 224 | "license": "Apache-2.0", 225 | "dependencies": { 226 | "@firebase/auth-interop-types": "0.2.4", 227 | "@firebase/component": "0.6.12", 228 | "@firebase/logger": "0.4.4", 229 | "@firebase/util": "1.10.3", 230 | "tslib": "^2.1.0" 231 | }, 232 | "peerDependencies": { 233 | "@firebase/app": "0.x" 234 | } 235 | }, 236 | "node_modules/@firebase/database": { 237 | "version": "1.0.12", 238 | "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.12.tgz", 239 | "integrity": "sha512-psFl5t6rSFHq3i3fnU1QQlc4BB9Hnhh8TgEqvQlPPm8kDLw8gYxvjqYw3c5CZW0+zKR837nwT6im/wtJUivMKw==", 240 | "license": "Apache-2.0", 241 | "dependencies": { 242 | "@firebase/app-check-interop-types": "0.3.3", 243 | "@firebase/auth-interop-types": "0.2.4", 244 | "@firebase/component": "0.6.12", 245 | "@firebase/logger": "0.4.4", 246 | "@firebase/util": "1.10.3", 247 | "faye-websocket": "0.11.4", 248 | "tslib": "^2.1.0" 249 | }, 250 | "engines": { 251 | "node": ">=18.0.0" 252 | } 253 | }, 254 | "node_modules/@firebase/database-compat": { 255 | "version": "2.0.3", 256 | "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.3.tgz", 257 | "integrity": "sha512-uHGQrSUeJvsDfA+IyHW5O4vdRPsCksEzv4T4Jins+bmQgYy20ZESU4x01xrQCn/nzqKHuQMEW99CoCO7D+5NiQ==", 258 | "license": "Apache-2.0", 259 | "dependencies": { 260 | "@firebase/component": "0.6.12", 261 | "@firebase/database": "1.0.12", 262 | "@firebase/database-types": "1.0.8", 263 | "@firebase/logger": "0.4.4", 264 | "@firebase/util": "1.10.3", 265 | "tslib": "^2.1.0" 266 | }, 267 | "engines": { 268 | "node": ">=18.0.0" 269 | } 270 | }, 271 | "node_modules/@firebase/database-types": { 272 | "version": "1.0.8", 273 | "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.8.tgz", 274 | "integrity": "sha512-6lPWIGeufhUq1heofZULyVvWFhD01TUrkkB9vyhmksjZ4XF7NaivQp9rICMk7QNhqwa+uDCaj4j+Q8qqcSVZ9g==", 275 | "license": "Apache-2.0", 276 | "dependencies": { 277 | "@firebase/app-types": "0.9.3", 278 | "@firebase/util": "1.10.3" 279 | } 280 | }, 281 | "node_modules/@firebase/firestore": { 282 | "version": "4.7.8", 283 | "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.8.tgz", 284 | "integrity": "sha512-eDvVJ/I5vSmIdGmLHJAK1OcviigIxjjia6i5/AkMFq6vZMt7CBXA0B5Xz9pGRCZ7WewFcsCbK1ZUQoYJ91+Cew==", 285 | "license": "Apache-2.0", 286 | "dependencies": { 287 | "@firebase/component": "0.6.12", 288 | "@firebase/logger": "0.4.4", 289 | "@firebase/util": "1.10.3", 290 | "@firebase/webchannel-wrapper": "1.0.3", 291 | "@grpc/grpc-js": "~1.9.0", 292 | "@grpc/proto-loader": "^0.7.8", 293 | "tslib": "^2.1.0" 294 | }, 295 | "engines": { 296 | "node": ">=18.0.0" 297 | }, 298 | "peerDependencies": { 299 | "@firebase/app": "0.x" 300 | } 301 | }, 302 | "node_modules/@firebase/firestore-compat": { 303 | "version": "0.3.43", 304 | "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.43.tgz", 305 | "integrity": "sha512-zxg7YS07XQnTetGs3GADM/eA6HB4vWUp+Av4iugmTbft0fQxuTSnGm7ifctaYuR7VMTPckU9CW+oFC9QUNSYvg==", 306 | "license": "Apache-2.0", 307 | "dependencies": { 308 | "@firebase/component": "0.6.12", 309 | "@firebase/firestore": "4.7.8", 310 | "@firebase/firestore-types": "3.0.3", 311 | "@firebase/util": "1.10.3", 312 | "tslib": "^2.1.0" 313 | }, 314 | "engines": { 315 | "node": ">=18.0.0" 316 | }, 317 | "peerDependencies": { 318 | "@firebase/app-compat": "0.x" 319 | } 320 | }, 321 | "node_modules/@firebase/firestore-types": { 322 | "version": "3.0.3", 323 | "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz", 324 | "integrity": "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==", 325 | "license": "Apache-2.0", 326 | "peerDependencies": { 327 | "@firebase/app-types": "0.x", 328 | "@firebase/util": "1.x" 329 | } 330 | }, 331 | "node_modules/@firebase/functions": { 332 | "version": "0.12.2", 333 | "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.12.2.tgz", 334 | "integrity": "sha512-iKpFDoCYk/Qm+Qwv5ynRb9/yq64QOt0A0+t9NuekyAZnSoV56kSNq/PmsVmBauar5SlmEjhHk6QKdMBP9S0gXA==", 335 | "license": "Apache-2.0", 336 | "dependencies": { 337 | "@firebase/app-check-interop-types": "0.3.3", 338 | "@firebase/auth-interop-types": "0.2.4", 339 | "@firebase/component": "0.6.12", 340 | "@firebase/messaging-interop-types": "0.2.3", 341 | "@firebase/util": "1.10.3", 342 | "tslib": "^2.1.0" 343 | }, 344 | "engines": { 345 | "node": ">=18.0.0" 346 | }, 347 | "peerDependencies": { 348 | "@firebase/app": "0.x" 349 | } 350 | }, 351 | "node_modules/@firebase/functions-compat": { 352 | "version": "0.3.19", 353 | "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.19.tgz", 354 | "integrity": "sha512-uw4tR8NcJCDu86UD63Za8A8SgFgmAVFb1XsGlkuBY7gpLyZWEFavWnwRkZ/8cUwpqUhp/SptXFZ1WFJSnOokLw==", 355 | "license": "Apache-2.0", 356 | "dependencies": { 357 | "@firebase/component": "0.6.12", 358 | "@firebase/functions": "0.12.2", 359 | "@firebase/functions-types": "0.6.3", 360 | "@firebase/util": "1.10.3", 361 | "tslib": "^2.1.0" 362 | }, 363 | "engines": { 364 | "node": ">=18.0.0" 365 | }, 366 | "peerDependencies": { 367 | "@firebase/app-compat": "0.x" 368 | } 369 | }, 370 | "node_modules/@firebase/functions-types": { 371 | "version": "0.6.3", 372 | "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz", 373 | "integrity": "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==", 374 | "license": "Apache-2.0" 375 | }, 376 | "node_modules/@firebase/installations": { 377 | "version": "0.6.12", 378 | "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.12.tgz", 379 | "integrity": "sha512-ES/WpuAV2k2YtBTvdaknEo7IY8vaGjIjS3zhnHSAIvY9KwTR8XZFXOJoZ3nSkjN1A5R4MtEh+07drnzPDg9vaw==", 380 | "license": "Apache-2.0", 381 | "dependencies": { 382 | "@firebase/component": "0.6.12", 383 | "@firebase/util": "1.10.3", 384 | "idb": "7.1.1", 385 | "tslib": "^2.1.0" 386 | }, 387 | "peerDependencies": { 388 | "@firebase/app": "0.x" 389 | } 390 | }, 391 | "node_modules/@firebase/installations-compat": { 392 | "version": "0.2.12", 393 | "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.12.tgz", 394 | "integrity": "sha512-RhcGknkxmFu92F6Jb3rXxv6a4sytPjJGifRZj8MSURPuv2Xu+/AispCXEfY1ZraobhEHTG5HLGsP6R4l9qB5aA==", 395 | "license": "Apache-2.0", 396 | "dependencies": { 397 | "@firebase/component": "0.6.12", 398 | "@firebase/installations": "0.6.12", 399 | "@firebase/installations-types": "0.5.3", 400 | "@firebase/util": "1.10.3", 401 | "tslib": "^2.1.0" 402 | }, 403 | "peerDependencies": { 404 | "@firebase/app-compat": "0.x" 405 | } 406 | }, 407 | "node_modules/@firebase/installations-types": { 408 | "version": "0.5.3", 409 | "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz", 410 | "integrity": "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==", 411 | "license": "Apache-2.0", 412 | "peerDependencies": { 413 | "@firebase/app-types": "0.x" 414 | } 415 | }, 416 | "node_modules/@firebase/logger": { 417 | "version": "0.4.4", 418 | "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", 419 | "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", 420 | "license": "Apache-2.0", 421 | "dependencies": { 422 | "tslib": "^2.1.0" 423 | }, 424 | "engines": { 425 | "node": ">=18.0.0" 426 | } 427 | }, 428 | "node_modules/@firebase/messaging": { 429 | "version": "0.12.16", 430 | "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.16.tgz", 431 | "integrity": "sha512-VJ8sCEIeP3+XkfbJA7410WhYGHdloYFZXoHe/vt+vNVDGw8JQPTQSVTRvjrUprEf5I4Tbcnpr2H34lS6zhCHSA==", 432 | "license": "Apache-2.0", 433 | "dependencies": { 434 | "@firebase/component": "0.6.12", 435 | "@firebase/installations": "0.6.12", 436 | "@firebase/messaging-interop-types": "0.2.3", 437 | "@firebase/util": "1.10.3", 438 | "idb": "7.1.1", 439 | "tslib": "^2.1.0" 440 | }, 441 | "peerDependencies": { 442 | "@firebase/app": "0.x" 443 | } 444 | }, 445 | "node_modules/@firebase/messaging-compat": { 446 | "version": "0.2.16", 447 | "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.16.tgz", 448 | "integrity": "sha512-9HZZ88Ig3zQ0ok/Pwt4gQcNsOhoEy8hDHoGsV1am6ulgMuGuDVD2gl11Lere2ksL+msM12Lddi2x/7TCqmODZw==", 449 | "license": "Apache-2.0", 450 | "dependencies": { 451 | "@firebase/component": "0.6.12", 452 | "@firebase/messaging": "0.12.16", 453 | "@firebase/util": "1.10.3", 454 | "tslib": "^2.1.0" 455 | }, 456 | "peerDependencies": { 457 | "@firebase/app-compat": "0.x" 458 | } 459 | }, 460 | "node_modules/@firebase/messaging-interop-types": { 461 | "version": "0.2.3", 462 | "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz", 463 | "integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==", 464 | "license": "Apache-2.0" 465 | }, 466 | "node_modules/@firebase/performance": { 467 | "version": "0.7.0", 468 | "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.7.0.tgz", 469 | "integrity": "sha512-L91PwYuiJdKXKSRqsWNicvTppAJVzKjye03UlegeD6TkpKjb93T8AmJ9B0Mt0bcWHCNtnnRBCdSCvD2U9GZDjw==", 470 | "license": "Apache-2.0", 471 | "dependencies": { 472 | "@firebase/component": "0.6.12", 473 | "@firebase/installations": "0.6.12", 474 | "@firebase/logger": "0.4.4", 475 | "@firebase/util": "1.10.3", 476 | "tslib": "^2.1.0", 477 | "web-vitals": "^4.2.4" 478 | }, 479 | "peerDependencies": { 480 | "@firebase/app": "0.x" 481 | } 482 | }, 483 | "node_modules/@firebase/performance-compat": { 484 | "version": "0.2.13", 485 | "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.13.tgz", 486 | "integrity": "sha512-pB0SMQj2TLQ6roDcX0YQDWvUnVgsVOl0VnUvyT/VBdCUuQYDHobZsPEuQsoEqmPA44KS/Gl0oyKqf+I8UPtRgw==", 487 | "license": "Apache-2.0", 488 | "dependencies": { 489 | "@firebase/component": "0.6.12", 490 | "@firebase/logger": "0.4.4", 491 | "@firebase/performance": "0.7.0", 492 | "@firebase/performance-types": "0.2.3", 493 | "@firebase/util": "1.10.3", 494 | "tslib": "^2.1.0" 495 | }, 496 | "peerDependencies": { 497 | "@firebase/app-compat": "0.x" 498 | } 499 | }, 500 | "node_modules/@firebase/performance-types": { 501 | "version": "0.2.3", 502 | "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz", 503 | "integrity": "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==", 504 | "license": "Apache-2.0" 505 | }, 506 | "node_modules/@firebase/remote-config": { 507 | "version": "0.5.0", 508 | "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.5.0.tgz", 509 | "integrity": "sha512-weiEbpBp5PBJTHUWR4GwI7ZacaAg68BKha5QnZ8Go65W4oQjEWqCW/rfskABI/OkrGijlL3CUmCB/SA6mVo0qA==", 510 | "license": "Apache-2.0", 511 | "dependencies": { 512 | "@firebase/component": "0.6.12", 513 | "@firebase/installations": "0.6.12", 514 | "@firebase/logger": "0.4.4", 515 | "@firebase/util": "1.10.3", 516 | "tslib": "^2.1.0" 517 | }, 518 | "peerDependencies": { 519 | "@firebase/app": "0.x" 520 | } 521 | }, 522 | "node_modules/@firebase/remote-config-compat": { 523 | "version": "0.2.12", 524 | "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.12.tgz", 525 | "integrity": "sha512-91jLWPtubIuPBngg9SzwvNCWzhMLcyBccmt7TNZP+y1cuYFNOWWHKUXQ3IrxCLB7WwLqQaEu7fTDAjHsTyBsSw==", 526 | "license": "Apache-2.0", 527 | "dependencies": { 528 | "@firebase/component": "0.6.12", 529 | "@firebase/logger": "0.4.4", 530 | "@firebase/remote-config": "0.5.0", 531 | "@firebase/remote-config-types": "0.4.0", 532 | "@firebase/util": "1.10.3", 533 | "tslib": "^2.1.0" 534 | }, 535 | "peerDependencies": { 536 | "@firebase/app-compat": "0.x" 537 | } 538 | }, 539 | "node_modules/@firebase/remote-config-types": { 540 | "version": "0.4.0", 541 | "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.4.0.tgz", 542 | "integrity": "sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg==", 543 | "license": "Apache-2.0" 544 | }, 545 | "node_modules/@firebase/storage": { 546 | "version": "0.13.6", 547 | "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.6.tgz", 548 | "integrity": "sha512-BEJLYQzVgAoglRl5VRIRZ91RRBZgS/O37/PSGQJBYNuoLmFZUrtwrlLTOAwG776NlO9VQR+K2j15/36Lr2EqHA==", 549 | "license": "Apache-2.0", 550 | "dependencies": { 551 | "@firebase/component": "0.6.12", 552 | "@firebase/util": "1.10.3", 553 | "tslib": "^2.1.0" 554 | }, 555 | "engines": { 556 | "node": ">=18.0.0" 557 | }, 558 | "peerDependencies": { 559 | "@firebase/app": "0.x" 560 | } 561 | }, 562 | "node_modules/@firebase/storage-compat": { 563 | "version": "0.3.16", 564 | "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.16.tgz", 565 | "integrity": "sha512-EeMuok/s0r938lEomia8XILEqSYULm7HcYZ/GTZLDWur0kMf2ktuPVZiTdRiwEV3Iki7FtQO5txrQ/0pLRVLAw==", 566 | "license": "Apache-2.0", 567 | "dependencies": { 568 | "@firebase/component": "0.6.12", 569 | "@firebase/storage": "0.13.6", 570 | "@firebase/storage-types": "0.8.3", 571 | "@firebase/util": "1.10.3", 572 | "tslib": "^2.1.0" 573 | }, 574 | "engines": { 575 | "node": ">=18.0.0" 576 | }, 577 | "peerDependencies": { 578 | "@firebase/app-compat": "0.x" 579 | } 580 | }, 581 | "node_modules/@firebase/storage-types": { 582 | "version": "0.8.3", 583 | "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz", 584 | "integrity": "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==", 585 | "license": "Apache-2.0", 586 | "peerDependencies": { 587 | "@firebase/app-types": "0.x", 588 | "@firebase/util": "1.x" 589 | } 590 | }, 591 | "node_modules/@firebase/util": { 592 | "version": "1.10.3", 593 | "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.3.tgz", 594 | "integrity": "sha512-wfoF5LTy0m2ufUapV0ZnpcGQvuavTbJ5Qr1Ze9OJGL70cSMvhDyjS4w2121XdA3lGZSTOsDOyGhpoDtYwck85A==", 595 | "license": "Apache-2.0", 596 | "dependencies": { 597 | "tslib": "^2.1.0" 598 | }, 599 | "engines": { 600 | "node": ">=18.0.0" 601 | } 602 | }, 603 | "node_modules/@firebase/vertexai": { 604 | "version": "1.0.4", 605 | "resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.4.tgz", 606 | "integrity": "sha512-Nkf/r4u166b4Id6zrrW0Qtg1KyZpQvvYchtkebamnHtIfY+Qnt51I/sx4Saos/WrmO8SnrSU850LfmJ7pehYXg==", 607 | "license": "Apache-2.0", 608 | "dependencies": { 609 | "@firebase/app-check-interop-types": "0.3.3", 610 | "@firebase/component": "0.6.12", 611 | "@firebase/logger": "0.4.4", 612 | "@firebase/util": "1.10.3", 613 | "tslib": "^2.1.0" 614 | }, 615 | "engines": { 616 | "node": ">=18.0.0" 617 | }, 618 | "peerDependencies": { 619 | "@firebase/app": "0.x", 620 | "@firebase/app-types": "0.x" 621 | } 622 | }, 623 | "node_modules/@firebase/webchannel-wrapper": { 624 | "version": "1.0.3", 625 | "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz", 626 | "integrity": "sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==", 627 | "license": "Apache-2.0" 628 | }, 629 | "node_modules/@grammyjs/types": { 630 | "version": "3.18.0", 631 | "resolved": "https://registry.npmjs.org/@grammyjs/types/-/types-3.18.0.tgz", 632 | "integrity": "sha512-/VpQcT6Z0+Lw6H6jv2JvnDmqB1/9rjbFdDBlPBPUW3kQ1bWfjzfaiVk2+J2eiid3o3sLaPp3ZK0XjEI1gWNc3g==", 633 | "license": "MIT" 634 | }, 635 | "node_modules/@grpc/grpc-js": { 636 | "version": "1.9.15", 637 | "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", 638 | "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==", 639 | "license": "Apache-2.0", 640 | "dependencies": { 641 | "@grpc/proto-loader": "^0.7.8", 642 | "@types/node": ">=12.12.47" 643 | }, 644 | "engines": { 645 | "node": "^8.13.0 || >=10.10.0" 646 | } 647 | }, 648 | "node_modules/@grpc/proto-loader": { 649 | "version": "0.7.13", 650 | "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", 651 | "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", 652 | "license": "Apache-2.0", 653 | "dependencies": { 654 | "lodash.camelcase": "^4.3.0", 655 | "long": "^5.0.0", 656 | "protobufjs": "^7.2.5", 657 | "yargs": "^17.7.2" 658 | }, 659 | "bin": { 660 | "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" 661 | }, 662 | "engines": { 663 | "node": ">=6" 664 | } 665 | }, 666 | "node_modules/@protobufjs/aspromise": { 667 | "version": "1.1.2", 668 | "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", 669 | "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", 670 | "license": "BSD-3-Clause" 671 | }, 672 | "node_modules/@protobufjs/base64": { 673 | "version": "1.1.2", 674 | "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", 675 | "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", 676 | "license": "BSD-3-Clause" 677 | }, 678 | "node_modules/@protobufjs/codegen": { 679 | "version": "2.0.4", 680 | "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", 681 | "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", 682 | "license": "BSD-3-Clause" 683 | }, 684 | "node_modules/@protobufjs/eventemitter": { 685 | "version": "1.1.0", 686 | "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", 687 | "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", 688 | "license": "BSD-3-Clause" 689 | }, 690 | "node_modules/@protobufjs/fetch": { 691 | "version": "1.1.0", 692 | "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", 693 | "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", 694 | "license": "BSD-3-Clause", 695 | "dependencies": { 696 | "@protobufjs/aspromise": "^1.1.1", 697 | "@protobufjs/inquire": "^1.1.0" 698 | } 699 | }, 700 | "node_modules/@protobufjs/float": { 701 | "version": "1.0.2", 702 | "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", 703 | "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", 704 | "license": "BSD-3-Clause" 705 | }, 706 | "node_modules/@protobufjs/inquire": { 707 | "version": "1.1.0", 708 | "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", 709 | "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", 710 | "license": "BSD-3-Clause" 711 | }, 712 | "node_modules/@protobufjs/path": { 713 | "version": "1.1.2", 714 | "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", 715 | "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", 716 | "license": "BSD-3-Clause" 717 | }, 718 | "node_modules/@protobufjs/pool": { 719 | "version": "1.1.0", 720 | "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", 721 | "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", 722 | "license": "BSD-3-Clause" 723 | }, 724 | "node_modules/@protobufjs/utf8": { 725 | "version": "1.1.0", 726 | "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", 727 | "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", 728 | "license": "BSD-3-Clause" 729 | }, 730 | "node_modules/@types/firebase": { 731 | "version": "2.4.32", 732 | "resolved": "https://registry.npmjs.org/@types/firebase/-/firebase-2.4.32.tgz", 733 | "integrity": "sha512-WHuDkJq4PjH3HzmogWstX/r+/c0dGFq7F1fZ9LgT/B4zh/0fps0fUxLDNtuSJZ+PLIpm/EALBhcqZr0qtEy85g==", 734 | "dev": true, 735 | "license": "MIT" 736 | }, 737 | "node_modules/@types/node": { 738 | "version": "22.13.1", 739 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", 740 | "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", 741 | "license": "MIT", 742 | "dependencies": { 743 | "undici-types": "~6.20.0" 744 | } 745 | }, 746 | "node_modules/@types/node-cron": { 747 | "version": "3.0.11", 748 | "resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-3.0.11.tgz", 749 | "integrity": "sha512-0ikrnug3/IyneSHqCBeslAhlK2aBfYek1fGo4bP4QnZPmiqSGRK+Oy7ZMisLWkesffJvQ1cqAcBnJC+8+nxIAg==", 750 | "dev": true, 751 | "license": "MIT" 752 | }, 753 | "node_modules/abort-controller": { 754 | "version": "3.0.0", 755 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", 756 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", 757 | "license": "MIT", 758 | "dependencies": { 759 | "event-target-shim": "^5.0.0" 760 | }, 761 | "engines": { 762 | "node": ">=6.5" 763 | } 764 | }, 765 | "node_modules/accepts": { 766 | "version": "1.3.8", 767 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 768 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 769 | "license": "MIT", 770 | "dependencies": { 771 | "mime-types": "~2.1.34", 772 | "negotiator": "0.6.3" 773 | }, 774 | "engines": { 775 | "node": ">= 0.6" 776 | } 777 | }, 778 | "node_modules/ansi-regex": { 779 | "version": "5.0.1", 780 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 781 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 782 | "license": "MIT", 783 | "engines": { 784 | "node": ">=8" 785 | } 786 | }, 787 | "node_modules/ansi-styles": { 788 | "version": "4.3.0", 789 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 790 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 791 | "license": "MIT", 792 | "dependencies": { 793 | "color-convert": "^2.0.1" 794 | }, 795 | "engines": { 796 | "node": ">=8" 797 | }, 798 | "funding": { 799 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 800 | } 801 | }, 802 | "node_modules/array-flatten": { 803 | "version": "1.1.1", 804 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 805 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", 806 | "license": "MIT" 807 | }, 808 | "node_modules/body-parser": { 809 | "version": "1.20.3", 810 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 811 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 812 | "license": "MIT", 813 | "dependencies": { 814 | "bytes": "3.1.2", 815 | "content-type": "~1.0.5", 816 | "debug": "2.6.9", 817 | "depd": "2.0.0", 818 | "destroy": "1.2.0", 819 | "http-errors": "2.0.0", 820 | "iconv-lite": "0.4.24", 821 | "on-finished": "2.4.1", 822 | "qs": "6.13.0", 823 | "raw-body": "2.5.2", 824 | "type-is": "~1.6.18", 825 | "unpipe": "1.0.0" 826 | }, 827 | "engines": { 828 | "node": ">= 0.8", 829 | "npm": "1.2.8000 || >= 1.4.16" 830 | } 831 | }, 832 | "node_modules/body-parser/node_modules/debug": { 833 | "version": "2.6.9", 834 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 835 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 836 | "license": "MIT", 837 | "dependencies": { 838 | "ms": "2.0.0" 839 | } 840 | }, 841 | "node_modules/body-parser/node_modules/ms": { 842 | "version": "2.0.0", 843 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 844 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", 845 | "license": "MIT" 846 | }, 847 | "node_modules/bytes": { 848 | "version": "3.1.2", 849 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 850 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 851 | "license": "MIT", 852 | "engines": { 853 | "node": ">= 0.8" 854 | } 855 | }, 856 | "node_modules/call-bind-apply-helpers": { 857 | "version": "1.0.1", 858 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", 859 | "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", 860 | "license": "MIT", 861 | "dependencies": { 862 | "es-errors": "^1.3.0", 863 | "function-bind": "^1.1.2" 864 | }, 865 | "engines": { 866 | "node": ">= 0.4" 867 | } 868 | }, 869 | "node_modules/call-bound": { 870 | "version": "1.0.3", 871 | "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", 872 | "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", 873 | "license": "MIT", 874 | "dependencies": { 875 | "call-bind-apply-helpers": "^1.0.1", 876 | "get-intrinsic": "^1.2.6" 877 | }, 878 | "engines": { 879 | "node": ">= 0.4" 880 | }, 881 | "funding": { 882 | "url": "https://github.com/sponsors/ljharb" 883 | } 884 | }, 885 | "node_modules/cliui": { 886 | "version": "8.0.1", 887 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 888 | "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 889 | "license": "ISC", 890 | "dependencies": { 891 | "string-width": "^4.2.0", 892 | "strip-ansi": "^6.0.1", 893 | "wrap-ansi": "^7.0.0" 894 | }, 895 | "engines": { 896 | "node": ">=12" 897 | } 898 | }, 899 | "node_modules/color-convert": { 900 | "version": "2.0.1", 901 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 902 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 903 | "license": "MIT", 904 | "dependencies": { 905 | "color-name": "~1.1.4" 906 | }, 907 | "engines": { 908 | "node": ">=7.0.0" 909 | } 910 | }, 911 | "node_modules/color-name": { 912 | "version": "1.1.4", 913 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 914 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 915 | "license": "MIT" 916 | }, 917 | "node_modules/content-disposition": { 918 | "version": "0.5.4", 919 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 920 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 921 | "license": "MIT", 922 | "dependencies": { 923 | "safe-buffer": "5.2.1" 924 | }, 925 | "engines": { 926 | "node": ">= 0.6" 927 | } 928 | }, 929 | "node_modules/content-type": { 930 | "version": "1.0.5", 931 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 932 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 933 | "license": "MIT", 934 | "engines": { 935 | "node": ">= 0.6" 936 | } 937 | }, 938 | "node_modules/cookie": { 939 | "version": "0.7.1", 940 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", 941 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", 942 | "license": "MIT", 943 | "engines": { 944 | "node": ">= 0.6" 945 | } 946 | }, 947 | "node_modules/cookie-signature": { 948 | "version": "1.0.6", 949 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 950 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", 951 | "license": "MIT" 952 | }, 953 | "node_modules/debug": { 954 | "version": "4.4.0", 955 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 956 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 957 | "license": "MIT", 958 | "dependencies": { 959 | "ms": "^2.1.3" 960 | }, 961 | "engines": { 962 | "node": ">=6.0" 963 | }, 964 | "peerDependenciesMeta": { 965 | "supports-color": { 966 | "optional": true 967 | } 968 | } 969 | }, 970 | "node_modules/depd": { 971 | "version": "2.0.0", 972 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 973 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 974 | "license": "MIT", 975 | "engines": { 976 | "node": ">= 0.8" 977 | } 978 | }, 979 | "node_modules/destroy": { 980 | "version": "1.2.0", 981 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 982 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 983 | "license": "MIT", 984 | "engines": { 985 | "node": ">= 0.8", 986 | "npm": "1.2.8000 || >= 1.4.16" 987 | } 988 | }, 989 | "node_modules/dotenv": { 990 | "version": "16.4.7", 991 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", 992 | "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", 993 | "license": "BSD-2-Clause", 994 | "engines": { 995 | "node": ">=12" 996 | }, 997 | "funding": { 998 | "url": "https://dotenvx.com" 999 | } 1000 | }, 1001 | "node_modules/dunder-proto": { 1002 | "version": "1.0.1", 1003 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 1004 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 1005 | "license": "MIT", 1006 | "dependencies": { 1007 | "call-bind-apply-helpers": "^1.0.1", 1008 | "es-errors": "^1.3.0", 1009 | "gopd": "^1.2.0" 1010 | }, 1011 | "engines": { 1012 | "node": ">= 0.4" 1013 | } 1014 | }, 1015 | "node_modules/ee-first": { 1016 | "version": "1.1.1", 1017 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1018 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", 1019 | "license": "MIT" 1020 | }, 1021 | "node_modules/emoji-regex": { 1022 | "version": "8.0.0", 1023 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1024 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1025 | "license": "MIT" 1026 | }, 1027 | "node_modules/encodeurl": { 1028 | "version": "2.0.0", 1029 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 1030 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 1031 | "license": "MIT", 1032 | "engines": { 1033 | "node": ">= 0.8" 1034 | } 1035 | }, 1036 | "node_modules/es-define-property": { 1037 | "version": "1.0.1", 1038 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 1039 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 1040 | "license": "MIT", 1041 | "engines": { 1042 | "node": ">= 0.4" 1043 | } 1044 | }, 1045 | "node_modules/es-errors": { 1046 | "version": "1.3.0", 1047 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 1048 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 1049 | "license": "MIT", 1050 | "engines": { 1051 | "node": ">= 0.4" 1052 | } 1053 | }, 1054 | "node_modules/es-object-atoms": { 1055 | "version": "1.1.1", 1056 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 1057 | "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 1058 | "license": "MIT", 1059 | "dependencies": { 1060 | "es-errors": "^1.3.0" 1061 | }, 1062 | "engines": { 1063 | "node": ">= 0.4" 1064 | } 1065 | }, 1066 | "node_modules/escalade": { 1067 | "version": "3.2.0", 1068 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", 1069 | "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", 1070 | "license": "MIT", 1071 | "engines": { 1072 | "node": ">=6" 1073 | } 1074 | }, 1075 | "node_modules/escape-html": { 1076 | "version": "1.0.3", 1077 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 1078 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", 1079 | "license": "MIT" 1080 | }, 1081 | "node_modules/etag": { 1082 | "version": "1.8.1", 1083 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 1084 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 1085 | "license": "MIT", 1086 | "engines": { 1087 | "node": ">= 0.6" 1088 | } 1089 | }, 1090 | "node_modules/event-target-shim": { 1091 | "version": "5.0.1", 1092 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", 1093 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", 1094 | "license": "MIT", 1095 | "engines": { 1096 | "node": ">=6" 1097 | } 1098 | }, 1099 | "node_modules/express": { 1100 | "version": "4.21.2", 1101 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", 1102 | "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", 1103 | "license": "MIT", 1104 | "dependencies": { 1105 | "accepts": "~1.3.8", 1106 | "array-flatten": "1.1.1", 1107 | "body-parser": "1.20.3", 1108 | "content-disposition": "0.5.4", 1109 | "content-type": "~1.0.4", 1110 | "cookie": "0.7.1", 1111 | "cookie-signature": "1.0.6", 1112 | "debug": "2.6.9", 1113 | "depd": "2.0.0", 1114 | "encodeurl": "~2.0.0", 1115 | "escape-html": "~1.0.3", 1116 | "etag": "~1.8.1", 1117 | "finalhandler": "1.3.1", 1118 | "fresh": "0.5.2", 1119 | "http-errors": "2.0.0", 1120 | "merge-descriptors": "1.0.3", 1121 | "methods": "~1.1.2", 1122 | "on-finished": "2.4.1", 1123 | "parseurl": "~1.3.3", 1124 | "path-to-regexp": "0.1.12", 1125 | "proxy-addr": "~2.0.7", 1126 | "qs": "6.13.0", 1127 | "range-parser": "~1.2.1", 1128 | "safe-buffer": "5.2.1", 1129 | "send": "0.19.0", 1130 | "serve-static": "1.16.2", 1131 | "setprototypeof": "1.2.0", 1132 | "statuses": "2.0.1", 1133 | "type-is": "~1.6.18", 1134 | "utils-merge": "1.0.1", 1135 | "vary": "~1.1.2" 1136 | }, 1137 | "engines": { 1138 | "node": ">= 0.10.0" 1139 | }, 1140 | "funding": { 1141 | "type": "opencollective", 1142 | "url": "https://opencollective.com/express" 1143 | } 1144 | }, 1145 | "node_modules/express/node_modules/debug": { 1146 | "version": "2.6.9", 1147 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1148 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1149 | "license": "MIT", 1150 | "dependencies": { 1151 | "ms": "2.0.0" 1152 | } 1153 | }, 1154 | "node_modules/express/node_modules/ms": { 1155 | "version": "2.0.0", 1156 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1157 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", 1158 | "license": "MIT" 1159 | }, 1160 | "node_modules/faye-websocket": { 1161 | "version": "0.11.4", 1162 | "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", 1163 | "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", 1164 | "license": "Apache-2.0", 1165 | "dependencies": { 1166 | "websocket-driver": ">=0.5.1" 1167 | }, 1168 | "engines": { 1169 | "node": ">=0.8.0" 1170 | } 1171 | }, 1172 | "node_modules/finalhandler": { 1173 | "version": "1.3.1", 1174 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 1175 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 1176 | "license": "MIT", 1177 | "dependencies": { 1178 | "debug": "2.6.9", 1179 | "encodeurl": "~2.0.0", 1180 | "escape-html": "~1.0.3", 1181 | "on-finished": "2.4.1", 1182 | "parseurl": "~1.3.3", 1183 | "statuses": "2.0.1", 1184 | "unpipe": "~1.0.0" 1185 | }, 1186 | "engines": { 1187 | "node": ">= 0.8" 1188 | } 1189 | }, 1190 | "node_modules/finalhandler/node_modules/debug": { 1191 | "version": "2.6.9", 1192 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1193 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1194 | "license": "MIT", 1195 | "dependencies": { 1196 | "ms": "2.0.0" 1197 | } 1198 | }, 1199 | "node_modules/finalhandler/node_modules/ms": { 1200 | "version": "2.0.0", 1201 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1202 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", 1203 | "license": "MIT" 1204 | }, 1205 | "node_modules/firebase": { 1206 | "version": "11.3.1", 1207 | "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.3.1.tgz", 1208 | "integrity": "sha512-P4YVFM0Bm2d8aO61SCEMF8E1pYgieGLrmr/LFw7vs6sAMebwuwHt+Wug+1qL2fhAHWPwpWbCLsdJH8NQ+4Sw8Q==", 1209 | "license": "Apache-2.0", 1210 | "dependencies": { 1211 | "@firebase/analytics": "0.10.11", 1212 | "@firebase/analytics-compat": "0.2.17", 1213 | "@firebase/app": "0.11.1", 1214 | "@firebase/app-check": "0.8.11", 1215 | "@firebase/app-check-compat": "0.3.18", 1216 | "@firebase/app-compat": "0.2.50", 1217 | "@firebase/app-types": "0.9.3", 1218 | "@firebase/auth": "1.9.0", 1219 | "@firebase/auth-compat": "0.5.18", 1220 | "@firebase/data-connect": "0.3.0", 1221 | "@firebase/database": "1.0.12", 1222 | "@firebase/database-compat": "2.0.3", 1223 | "@firebase/firestore": "4.7.8", 1224 | "@firebase/firestore-compat": "0.3.43", 1225 | "@firebase/functions": "0.12.2", 1226 | "@firebase/functions-compat": "0.3.19", 1227 | "@firebase/installations": "0.6.12", 1228 | "@firebase/installations-compat": "0.2.12", 1229 | "@firebase/messaging": "0.12.16", 1230 | "@firebase/messaging-compat": "0.2.16", 1231 | "@firebase/performance": "0.7.0", 1232 | "@firebase/performance-compat": "0.2.13", 1233 | "@firebase/remote-config": "0.5.0", 1234 | "@firebase/remote-config-compat": "0.2.12", 1235 | "@firebase/storage": "0.13.6", 1236 | "@firebase/storage-compat": "0.3.16", 1237 | "@firebase/util": "1.10.3", 1238 | "@firebase/vertexai": "1.0.4" 1239 | } 1240 | }, 1241 | "node_modules/forwarded": { 1242 | "version": "0.2.0", 1243 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 1244 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 1245 | "license": "MIT", 1246 | "engines": { 1247 | "node": ">= 0.6" 1248 | } 1249 | }, 1250 | "node_modules/fresh": { 1251 | "version": "0.5.2", 1252 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 1253 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 1254 | "license": "MIT", 1255 | "engines": { 1256 | "node": ">= 0.6" 1257 | } 1258 | }, 1259 | "node_modules/function-bind": { 1260 | "version": "1.1.2", 1261 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 1262 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 1263 | "license": "MIT", 1264 | "funding": { 1265 | "url": "https://github.com/sponsors/ljharb" 1266 | } 1267 | }, 1268 | "node_modules/get-caller-file": { 1269 | "version": "2.0.5", 1270 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1271 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 1272 | "license": "ISC", 1273 | "engines": { 1274 | "node": "6.* || 8.* || >= 10.*" 1275 | } 1276 | }, 1277 | "node_modules/get-intrinsic": { 1278 | "version": "1.2.7", 1279 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", 1280 | "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", 1281 | "license": "MIT", 1282 | "dependencies": { 1283 | "call-bind-apply-helpers": "^1.0.1", 1284 | "es-define-property": "^1.0.1", 1285 | "es-errors": "^1.3.0", 1286 | "es-object-atoms": "^1.0.0", 1287 | "function-bind": "^1.1.2", 1288 | "get-proto": "^1.0.0", 1289 | "gopd": "^1.2.0", 1290 | "has-symbols": "^1.1.0", 1291 | "hasown": "^2.0.2", 1292 | "math-intrinsics": "^1.1.0" 1293 | }, 1294 | "engines": { 1295 | "node": ">= 0.4" 1296 | }, 1297 | "funding": { 1298 | "url": "https://github.com/sponsors/ljharb" 1299 | } 1300 | }, 1301 | "node_modules/get-proto": { 1302 | "version": "1.0.1", 1303 | "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 1304 | "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 1305 | "license": "MIT", 1306 | "dependencies": { 1307 | "dunder-proto": "^1.0.1", 1308 | "es-object-atoms": "^1.0.0" 1309 | }, 1310 | "engines": { 1311 | "node": ">= 0.4" 1312 | } 1313 | }, 1314 | "node_modules/gopd": { 1315 | "version": "1.2.0", 1316 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 1317 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 1318 | "license": "MIT", 1319 | "engines": { 1320 | "node": ">= 0.4" 1321 | }, 1322 | "funding": { 1323 | "url": "https://github.com/sponsors/ljharb" 1324 | } 1325 | }, 1326 | "node_modules/grammy": { 1327 | "version": "1.34.1", 1328 | "resolved": "https://registry.npmjs.org/grammy/-/grammy-1.34.1.tgz", 1329 | "integrity": "sha512-0ypt5d1bna8CqSANlDCg2ce1sx87oDm9gjyPRHWYpAgvjy3WYW9oEmMllAYCWCZ3vHDULW5x14jBMXai51ar0Q==", 1330 | "license": "MIT", 1331 | "dependencies": { 1332 | "@grammyjs/types": "3.18.0", 1333 | "abort-controller": "^3.0.0", 1334 | "debug": "^4.3.4", 1335 | "node-fetch": "^2.7.0" 1336 | }, 1337 | "engines": { 1338 | "node": "^12.20.0 || >=14.13.1" 1339 | } 1340 | }, 1341 | "node_modules/has-symbols": { 1342 | "version": "1.1.0", 1343 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 1344 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 1345 | "license": "MIT", 1346 | "engines": { 1347 | "node": ">= 0.4" 1348 | }, 1349 | "funding": { 1350 | "url": "https://github.com/sponsors/ljharb" 1351 | } 1352 | }, 1353 | "node_modules/hasown": { 1354 | "version": "2.0.2", 1355 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 1356 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 1357 | "license": "MIT", 1358 | "dependencies": { 1359 | "function-bind": "^1.1.2" 1360 | }, 1361 | "engines": { 1362 | "node": ">= 0.4" 1363 | } 1364 | }, 1365 | "node_modules/http-errors": { 1366 | "version": "2.0.0", 1367 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 1368 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 1369 | "license": "MIT", 1370 | "dependencies": { 1371 | "depd": "2.0.0", 1372 | "inherits": "2.0.4", 1373 | "setprototypeof": "1.2.0", 1374 | "statuses": "2.0.1", 1375 | "toidentifier": "1.0.1" 1376 | }, 1377 | "engines": { 1378 | "node": ">= 0.8" 1379 | } 1380 | }, 1381 | "node_modules/http-parser-js": { 1382 | "version": "0.5.9", 1383 | "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz", 1384 | "integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==", 1385 | "license": "MIT" 1386 | }, 1387 | "node_modules/iconv-lite": { 1388 | "version": "0.4.24", 1389 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 1390 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 1391 | "license": "MIT", 1392 | "dependencies": { 1393 | "safer-buffer": ">= 2.1.2 < 3" 1394 | }, 1395 | "engines": { 1396 | "node": ">=0.10.0" 1397 | } 1398 | }, 1399 | "node_modules/idb": { 1400 | "version": "7.1.1", 1401 | "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", 1402 | "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", 1403 | "license": "ISC" 1404 | }, 1405 | "node_modules/inherits": { 1406 | "version": "2.0.4", 1407 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1408 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1409 | "license": "ISC" 1410 | }, 1411 | "node_modules/ipaddr.js": { 1412 | "version": "1.9.1", 1413 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1414 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 1415 | "license": "MIT", 1416 | "engines": { 1417 | "node": ">= 0.10" 1418 | } 1419 | }, 1420 | "node_modules/is-fullwidth-code-point": { 1421 | "version": "3.0.0", 1422 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1423 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1424 | "license": "MIT", 1425 | "engines": { 1426 | "node": ">=8" 1427 | } 1428 | }, 1429 | "node_modules/lodash.camelcase": { 1430 | "version": "4.3.0", 1431 | "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", 1432 | "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", 1433 | "license": "MIT" 1434 | }, 1435 | "node_modules/long": { 1436 | "version": "5.3.0", 1437 | "resolved": "https://registry.npmjs.org/long/-/long-5.3.0.tgz", 1438 | "integrity": "sha512-5vvY5yF1zF/kXk+L94FRiTDa1Znom46UjPCH6/XbSvS8zBKMFBHTJk8KDMqJ+2J6QezQFi7k1k8v21ClJYHPaw==", 1439 | "license": "Apache-2.0" 1440 | }, 1441 | "node_modules/math-intrinsics": { 1442 | "version": "1.1.0", 1443 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 1444 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 1445 | "license": "MIT", 1446 | "engines": { 1447 | "node": ">= 0.4" 1448 | } 1449 | }, 1450 | "node_modules/media-typer": { 1451 | "version": "0.3.0", 1452 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1453 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 1454 | "license": "MIT", 1455 | "engines": { 1456 | "node": ">= 0.6" 1457 | } 1458 | }, 1459 | "node_modules/merge-descriptors": { 1460 | "version": "1.0.3", 1461 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 1462 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", 1463 | "license": "MIT", 1464 | "funding": { 1465 | "url": "https://github.com/sponsors/sindresorhus" 1466 | } 1467 | }, 1468 | "node_modules/methods": { 1469 | "version": "1.1.2", 1470 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1471 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 1472 | "license": "MIT", 1473 | "engines": { 1474 | "node": ">= 0.6" 1475 | } 1476 | }, 1477 | "node_modules/mime": { 1478 | "version": "1.6.0", 1479 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1480 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 1481 | "license": "MIT", 1482 | "bin": { 1483 | "mime": "cli.js" 1484 | }, 1485 | "engines": { 1486 | "node": ">=4" 1487 | } 1488 | }, 1489 | "node_modules/mime-db": { 1490 | "version": "1.52.0", 1491 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1492 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 1493 | "license": "MIT", 1494 | "engines": { 1495 | "node": ">= 0.6" 1496 | } 1497 | }, 1498 | "node_modules/mime-types": { 1499 | "version": "2.1.35", 1500 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1501 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1502 | "license": "MIT", 1503 | "dependencies": { 1504 | "mime-db": "1.52.0" 1505 | }, 1506 | "engines": { 1507 | "node": ">= 0.6" 1508 | } 1509 | }, 1510 | "node_modules/ms": { 1511 | "version": "2.1.3", 1512 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1513 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1514 | "license": "MIT" 1515 | }, 1516 | "node_modules/negotiator": { 1517 | "version": "0.6.3", 1518 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 1519 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 1520 | "license": "MIT", 1521 | "engines": { 1522 | "node": ">= 0.6" 1523 | } 1524 | }, 1525 | "node_modules/node-cron": { 1526 | "version": "3.0.3", 1527 | "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz", 1528 | "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==", 1529 | "license": "ISC", 1530 | "dependencies": { 1531 | "uuid": "8.3.2" 1532 | }, 1533 | "engines": { 1534 | "node": ">=6.0.0" 1535 | } 1536 | }, 1537 | "node_modules/node-fetch": { 1538 | "version": "2.7.0", 1539 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", 1540 | "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", 1541 | "license": "MIT", 1542 | "dependencies": { 1543 | "whatwg-url": "^5.0.0" 1544 | }, 1545 | "engines": { 1546 | "node": "4.x || >=6.0.0" 1547 | }, 1548 | "peerDependencies": { 1549 | "encoding": "^0.1.0" 1550 | }, 1551 | "peerDependenciesMeta": { 1552 | "encoding": { 1553 | "optional": true 1554 | } 1555 | } 1556 | }, 1557 | "node_modules/object-inspect": { 1558 | "version": "1.13.4", 1559 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", 1560 | "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", 1561 | "license": "MIT", 1562 | "engines": { 1563 | "node": ">= 0.4" 1564 | }, 1565 | "funding": { 1566 | "url": "https://github.com/sponsors/ljharb" 1567 | } 1568 | }, 1569 | "node_modules/on-finished": { 1570 | "version": "2.4.1", 1571 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1572 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1573 | "license": "MIT", 1574 | "dependencies": { 1575 | "ee-first": "1.1.1" 1576 | }, 1577 | "engines": { 1578 | "node": ">= 0.8" 1579 | } 1580 | }, 1581 | "node_modules/parseurl": { 1582 | "version": "1.3.3", 1583 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1584 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 1585 | "license": "MIT", 1586 | "engines": { 1587 | "node": ">= 0.8" 1588 | } 1589 | }, 1590 | "node_modules/path-to-regexp": { 1591 | "version": "0.1.12", 1592 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", 1593 | "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", 1594 | "license": "MIT" 1595 | }, 1596 | "node_modules/protobufjs": { 1597 | "version": "7.4.0", 1598 | "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", 1599 | "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", 1600 | "hasInstallScript": true, 1601 | "license": "BSD-3-Clause", 1602 | "dependencies": { 1603 | "@protobufjs/aspromise": "^1.1.2", 1604 | "@protobufjs/base64": "^1.1.2", 1605 | "@protobufjs/codegen": "^2.0.4", 1606 | "@protobufjs/eventemitter": "^1.1.0", 1607 | "@protobufjs/fetch": "^1.1.0", 1608 | "@protobufjs/float": "^1.0.2", 1609 | "@protobufjs/inquire": "^1.1.0", 1610 | "@protobufjs/path": "^1.1.2", 1611 | "@protobufjs/pool": "^1.1.0", 1612 | "@protobufjs/utf8": "^1.1.0", 1613 | "@types/node": ">=13.7.0", 1614 | "long": "^5.0.0" 1615 | }, 1616 | "engines": { 1617 | "node": ">=12.0.0" 1618 | } 1619 | }, 1620 | "node_modules/proxy-addr": { 1621 | "version": "2.0.7", 1622 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1623 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1624 | "license": "MIT", 1625 | "dependencies": { 1626 | "forwarded": "0.2.0", 1627 | "ipaddr.js": "1.9.1" 1628 | }, 1629 | "engines": { 1630 | "node": ">= 0.10" 1631 | } 1632 | }, 1633 | "node_modules/qs": { 1634 | "version": "6.13.0", 1635 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 1636 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 1637 | "license": "BSD-3-Clause", 1638 | "dependencies": { 1639 | "side-channel": "^1.0.6" 1640 | }, 1641 | "engines": { 1642 | "node": ">=0.6" 1643 | }, 1644 | "funding": { 1645 | "url": "https://github.com/sponsors/ljharb" 1646 | } 1647 | }, 1648 | "node_modules/range-parser": { 1649 | "version": "1.2.1", 1650 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1651 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 1652 | "license": "MIT", 1653 | "engines": { 1654 | "node": ">= 0.6" 1655 | } 1656 | }, 1657 | "node_modules/raw-body": { 1658 | "version": "2.5.2", 1659 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 1660 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 1661 | "license": "MIT", 1662 | "dependencies": { 1663 | "bytes": "3.1.2", 1664 | "http-errors": "2.0.0", 1665 | "iconv-lite": "0.4.24", 1666 | "unpipe": "1.0.0" 1667 | }, 1668 | "engines": { 1669 | "node": ">= 0.8" 1670 | } 1671 | }, 1672 | "node_modules/require-directory": { 1673 | "version": "2.1.1", 1674 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1675 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 1676 | "license": "MIT", 1677 | "engines": { 1678 | "node": ">=0.10.0" 1679 | } 1680 | }, 1681 | "node_modules/safe-buffer": { 1682 | "version": "5.2.1", 1683 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1684 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1685 | "funding": [ 1686 | { 1687 | "type": "github", 1688 | "url": "https://github.com/sponsors/feross" 1689 | }, 1690 | { 1691 | "type": "patreon", 1692 | "url": "https://www.patreon.com/feross" 1693 | }, 1694 | { 1695 | "type": "consulting", 1696 | "url": "https://feross.org/support" 1697 | } 1698 | ], 1699 | "license": "MIT" 1700 | }, 1701 | "node_modules/safer-buffer": { 1702 | "version": "2.1.2", 1703 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1704 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1705 | "license": "MIT" 1706 | }, 1707 | "node_modules/send": { 1708 | "version": "0.19.0", 1709 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 1710 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 1711 | "license": "MIT", 1712 | "dependencies": { 1713 | "debug": "2.6.9", 1714 | "depd": "2.0.0", 1715 | "destroy": "1.2.0", 1716 | "encodeurl": "~1.0.2", 1717 | "escape-html": "~1.0.3", 1718 | "etag": "~1.8.1", 1719 | "fresh": "0.5.2", 1720 | "http-errors": "2.0.0", 1721 | "mime": "1.6.0", 1722 | "ms": "2.1.3", 1723 | "on-finished": "2.4.1", 1724 | "range-parser": "~1.2.1", 1725 | "statuses": "2.0.1" 1726 | }, 1727 | "engines": { 1728 | "node": ">= 0.8.0" 1729 | } 1730 | }, 1731 | "node_modules/send/node_modules/debug": { 1732 | "version": "2.6.9", 1733 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1734 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1735 | "license": "MIT", 1736 | "dependencies": { 1737 | "ms": "2.0.0" 1738 | } 1739 | }, 1740 | "node_modules/send/node_modules/debug/node_modules/ms": { 1741 | "version": "2.0.0", 1742 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1743 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", 1744 | "license": "MIT" 1745 | }, 1746 | "node_modules/send/node_modules/encodeurl": { 1747 | "version": "1.0.2", 1748 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 1749 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 1750 | "license": "MIT", 1751 | "engines": { 1752 | "node": ">= 0.8" 1753 | } 1754 | }, 1755 | "node_modules/serve-static": { 1756 | "version": "1.16.2", 1757 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 1758 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 1759 | "license": "MIT", 1760 | "dependencies": { 1761 | "encodeurl": "~2.0.0", 1762 | "escape-html": "~1.0.3", 1763 | "parseurl": "~1.3.3", 1764 | "send": "0.19.0" 1765 | }, 1766 | "engines": { 1767 | "node": ">= 0.8.0" 1768 | } 1769 | }, 1770 | "node_modules/setprototypeof": { 1771 | "version": "1.2.0", 1772 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1773 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", 1774 | "license": "ISC" 1775 | }, 1776 | "node_modules/side-channel": { 1777 | "version": "1.1.0", 1778 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 1779 | "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 1780 | "license": "MIT", 1781 | "dependencies": { 1782 | "es-errors": "^1.3.0", 1783 | "object-inspect": "^1.13.3", 1784 | "side-channel-list": "^1.0.0", 1785 | "side-channel-map": "^1.0.1", 1786 | "side-channel-weakmap": "^1.0.2" 1787 | }, 1788 | "engines": { 1789 | "node": ">= 0.4" 1790 | }, 1791 | "funding": { 1792 | "url": "https://github.com/sponsors/ljharb" 1793 | } 1794 | }, 1795 | "node_modules/side-channel-list": { 1796 | "version": "1.0.0", 1797 | "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 1798 | "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 1799 | "license": "MIT", 1800 | "dependencies": { 1801 | "es-errors": "^1.3.0", 1802 | "object-inspect": "^1.13.3" 1803 | }, 1804 | "engines": { 1805 | "node": ">= 0.4" 1806 | }, 1807 | "funding": { 1808 | "url": "https://github.com/sponsors/ljharb" 1809 | } 1810 | }, 1811 | "node_modules/side-channel-map": { 1812 | "version": "1.0.1", 1813 | "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 1814 | "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 1815 | "license": "MIT", 1816 | "dependencies": { 1817 | "call-bound": "^1.0.2", 1818 | "es-errors": "^1.3.0", 1819 | "get-intrinsic": "^1.2.5", 1820 | "object-inspect": "^1.13.3" 1821 | }, 1822 | "engines": { 1823 | "node": ">= 0.4" 1824 | }, 1825 | "funding": { 1826 | "url": "https://github.com/sponsors/ljharb" 1827 | } 1828 | }, 1829 | "node_modules/side-channel-weakmap": { 1830 | "version": "1.0.2", 1831 | "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 1832 | "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 1833 | "license": "MIT", 1834 | "dependencies": { 1835 | "call-bound": "^1.0.2", 1836 | "es-errors": "^1.3.0", 1837 | "get-intrinsic": "^1.2.5", 1838 | "object-inspect": "^1.13.3", 1839 | "side-channel-map": "^1.0.1" 1840 | }, 1841 | "engines": { 1842 | "node": ">= 0.4" 1843 | }, 1844 | "funding": { 1845 | "url": "https://github.com/sponsors/ljharb" 1846 | } 1847 | }, 1848 | "node_modules/statuses": { 1849 | "version": "2.0.1", 1850 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1851 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 1852 | "license": "MIT", 1853 | "engines": { 1854 | "node": ">= 0.8" 1855 | } 1856 | }, 1857 | "node_modules/string-width": { 1858 | "version": "4.2.3", 1859 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1860 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1861 | "license": "MIT", 1862 | "dependencies": { 1863 | "emoji-regex": "^8.0.0", 1864 | "is-fullwidth-code-point": "^3.0.0", 1865 | "strip-ansi": "^6.0.1" 1866 | }, 1867 | "engines": { 1868 | "node": ">=8" 1869 | } 1870 | }, 1871 | "node_modules/strip-ansi": { 1872 | "version": "6.0.1", 1873 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1874 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1875 | "license": "MIT", 1876 | "dependencies": { 1877 | "ansi-regex": "^5.0.1" 1878 | }, 1879 | "engines": { 1880 | "node": ">=8" 1881 | } 1882 | }, 1883 | "node_modules/toidentifier": { 1884 | "version": "1.0.1", 1885 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1886 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 1887 | "license": "MIT", 1888 | "engines": { 1889 | "node": ">=0.6" 1890 | } 1891 | }, 1892 | "node_modules/tr46": { 1893 | "version": "0.0.3", 1894 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 1895 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", 1896 | "license": "MIT" 1897 | }, 1898 | "node_modules/tslib": { 1899 | "version": "2.8.1", 1900 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 1901 | "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", 1902 | "license": "0BSD" 1903 | }, 1904 | "node_modules/type-is": { 1905 | "version": "1.6.18", 1906 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1907 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1908 | "license": "MIT", 1909 | "dependencies": { 1910 | "media-typer": "0.3.0", 1911 | "mime-types": "~2.1.24" 1912 | }, 1913 | "engines": { 1914 | "node": ">= 0.6" 1915 | } 1916 | }, 1917 | "node_modules/typescript": { 1918 | "version": "5.7.3", 1919 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", 1920 | "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", 1921 | "dev": true, 1922 | "license": "Apache-2.0", 1923 | "bin": { 1924 | "tsc": "bin/tsc", 1925 | "tsserver": "bin/tsserver" 1926 | }, 1927 | "engines": { 1928 | "node": ">=14.17" 1929 | } 1930 | }, 1931 | "node_modules/undici-types": { 1932 | "version": "6.20.0", 1933 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", 1934 | "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", 1935 | "license": "MIT" 1936 | }, 1937 | "node_modules/unpipe": { 1938 | "version": "1.0.0", 1939 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1940 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 1941 | "license": "MIT", 1942 | "engines": { 1943 | "node": ">= 0.8" 1944 | } 1945 | }, 1946 | "node_modules/utils-merge": { 1947 | "version": "1.0.1", 1948 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1949 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 1950 | "license": "MIT", 1951 | "engines": { 1952 | "node": ">= 0.4.0" 1953 | } 1954 | }, 1955 | "node_modules/uuid": { 1956 | "version": "8.3.2", 1957 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", 1958 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", 1959 | "license": "MIT", 1960 | "bin": { 1961 | "uuid": "dist/bin/uuid" 1962 | } 1963 | }, 1964 | "node_modules/vary": { 1965 | "version": "1.1.2", 1966 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1967 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 1968 | "license": "MIT", 1969 | "engines": { 1970 | "node": ">= 0.8" 1971 | } 1972 | }, 1973 | "node_modules/web-vitals": { 1974 | "version": "4.2.4", 1975 | "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz", 1976 | "integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==", 1977 | "license": "Apache-2.0" 1978 | }, 1979 | "node_modules/webidl-conversions": { 1980 | "version": "3.0.1", 1981 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 1982 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", 1983 | "license": "BSD-2-Clause" 1984 | }, 1985 | "node_modules/websocket-driver": { 1986 | "version": "0.7.4", 1987 | "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", 1988 | "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", 1989 | "license": "Apache-2.0", 1990 | "dependencies": { 1991 | "http-parser-js": ">=0.5.1", 1992 | "safe-buffer": ">=5.1.0", 1993 | "websocket-extensions": ">=0.1.1" 1994 | }, 1995 | "engines": { 1996 | "node": ">=0.8.0" 1997 | } 1998 | }, 1999 | "node_modules/websocket-extensions": { 2000 | "version": "0.1.4", 2001 | "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", 2002 | "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", 2003 | "license": "Apache-2.0", 2004 | "engines": { 2005 | "node": ">=0.8.0" 2006 | } 2007 | }, 2008 | "node_modules/whatwg-url": { 2009 | "version": "5.0.0", 2010 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 2011 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 2012 | "license": "MIT", 2013 | "dependencies": { 2014 | "tr46": "~0.0.3", 2015 | "webidl-conversions": "^3.0.0" 2016 | } 2017 | }, 2018 | "node_modules/wrap-ansi": { 2019 | "version": "7.0.0", 2020 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2021 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2022 | "license": "MIT", 2023 | "dependencies": { 2024 | "ansi-styles": "^4.0.0", 2025 | "string-width": "^4.1.0", 2026 | "strip-ansi": "^6.0.0" 2027 | }, 2028 | "engines": { 2029 | "node": ">=10" 2030 | }, 2031 | "funding": { 2032 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2033 | } 2034 | }, 2035 | "node_modules/y18n": { 2036 | "version": "5.0.8", 2037 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 2038 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 2039 | "license": "ISC", 2040 | "engines": { 2041 | "node": ">=10" 2042 | } 2043 | }, 2044 | "node_modules/yargs": { 2045 | "version": "17.7.2", 2046 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", 2047 | "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", 2048 | "license": "MIT", 2049 | "dependencies": { 2050 | "cliui": "^8.0.1", 2051 | "escalade": "^3.1.1", 2052 | "get-caller-file": "^2.0.5", 2053 | "require-directory": "^2.1.1", 2054 | "string-width": "^4.2.3", 2055 | "y18n": "^5.0.5", 2056 | "yargs-parser": "^21.1.1" 2057 | }, 2058 | "engines": { 2059 | "node": ">=12" 2060 | } 2061 | }, 2062 | "node_modules/yargs-parser": { 2063 | "version": "21.1.1", 2064 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", 2065 | "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", 2066 | "license": "ISC", 2067 | "engines": { 2068 | "node": ">=12" 2069 | } 2070 | } 2071 | } 2072 | } 2073 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------