import { onRequest } from "firebase-functions/v2/https"; import { Request } from "firebase-functions/v2/https"; import { onDocumentCreated } from 'firebase-functions/v2/firestore'; import * as admin from 'firebase-admin'; import * as express from "express"; import * as logger from "firebase-functions/logger"; const formData = require('form-data'); const Mailgun = require('mailgun.js'); const { convert } = require('html-to-text'); const twilio = require('twilio') export const sendEmail = onRequest((request: Request, response: express.Response) => { const mailgun = new Mailgun(formData); const mailGunClient = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY }); const toAddress = request.body.toAddress; const subject = request.body.subject; const message = request.body.message; const options = { wordwrap: 130, }; const textMessage = convert(message, options); mailGunClient.messages.create(process.env.MAILGUN_SERVER, { from: process.env.MAILGUN_FROM_ADDRESS, to: toAddress, subject: subject, text: textMessage, html: message }).then((res: any) => { logger.info(res); response.send(res); }).catch((err: any) => { logger.error(err); response.send(err); }); }); export const sendSMS = onRequest((request: Request, response: express.Response) => { const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN); const { to, body } = request.body; client.messages .create({ body: body, from: process.env.TWILIO_PHONE_NUMBER, to: to }) .then((message: any) => { logger.info('SMS sent successfully:', message.sid); response.json({ success: true, messageId: message.sid }); }) .catch((error: any) => { logger.error('Error sending SMS:', error); response.status(500).json({ success: false, error: error.message }); }); }); interface Invitation { email: string; phoneNumber: string; gymName: string; invitedByName: string; } export const sendInvitationNotification = onDocumentCreated( 'invitations/{invitationId}', async (event) => { const invitation = event.data?.data() as Invitation; const invitationId = event.params.invitationId; if (!invitation) { console.error('Invitation data is missing.'); return null; } try { const userQuery = await admin .firestore() .collection('users') .where('email', '==', invitation.email) .where('phoneNumber', '==', invitation.phoneNumber) .limit(1) .get(); if (userQuery.empty) { console.log( `User not found for email: ${invitation.email} and phone: ${invitation.phoneNumber}.` ); return null; } const user = userQuery.docs[0].data(); const fcmToken = user.fcmToken; if (!fcmToken) { console.log(`FCM token not found for user: ${invitation.email}.`); return null; } const message: admin.messaging.Message = { notification: { title: 'New Gym Invitation', body: `${invitation.invitedByName} has invited you to join ${invitation.gymName}`, }, data: { type: 'invitation', invitationId: invitationId, gymName: invitation.gymName, senderName: invitation.invitedByName, }, android: { priority: 'high', notification: { channelId: 'invitations_channel', priority: 'high', defaultSound: true, defaultVibrateTimings: true, icon: '@mipmap/ic_launcher', clickAction: 'FLUTTER_NOTIFICATION_CLICK', }, }, token: fcmToken, }; await admin.messaging().send(message); console.log(`Invitation notification sent to ${invitation.email}.`); return null; } catch (error) { console.error('Error sending invitation notification:', error); return null; } } );