Compare commits
No commits in common. "04077d95f466e527a6b5c26e859fe7c04865ac8a" and "a89ff0f30ced242bf5db794dbc339bae2af4e9e7" have entirely different histories.
04077d95f4
...
a89ff0f30c
@ -1,83 +0,0 @@
|
||||
trigger:
|
||||
- master
|
||||
|
||||
pool:
|
||||
vmImage: "ubuntu-latest"
|
||||
|
||||
variables:
|
||||
major: $(VERSION_MAJOR)
|
||||
minor: $(VERSION_MINOR)
|
||||
prefix: $[format('{0}.{1}', variables['major'], variables['minor'])]
|
||||
patch: $[counter(variables['prefix'], 100)]
|
||||
buildNumber: $(major).$(minor).$(patch)
|
||||
|
||||
steps:
|
||||
- task: PowerShell@2
|
||||
displayName: "Setting build version"
|
||||
inputs:
|
||||
targetType: "inline"
|
||||
script: |
|
||||
Write-Host "##vso[build.updatebuildnumber]${{ parameters.buildNumber }}"
|
||||
|
||||
- task: NodeTool@0
|
||||
displayName: "Install Node"
|
||||
inputs:
|
||||
version: "20"
|
||||
|
||||
- task: Npm@1
|
||||
displayName: "npm install"
|
||||
inputs:
|
||||
command: "install"
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: "Set version in package.json"
|
||||
inputs:
|
||||
targetType: "inline"
|
||||
script: |
|
||||
$pkg = Get-Content -Path "$(System.DefaultWorkingDirectory)/functions/package.json" -Raw | ConvertFrom-Json
|
||||
$pkg.version = "${{ parameters.buildNumber }}"
|
||||
$pkg | ConvertTo-Json -Depth 100 | Set-Content -Path "$(System.DefaultWorkingDirectory)/functions/package.json"
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: "Copy .env.example to .env"
|
||||
inputs:
|
||||
script: |
|
||||
cp "$(System.DefaultWorkingDirectory)/functions/.env.example" "$(System.DefaultWorkingDirectory)/functions/.env"
|
||||
|
||||
- task: ReplaceTokens@3
|
||||
displayName: "Replace tokens in .env file"
|
||||
inputs:
|
||||
targetFiles: "$(System.DefaultWorkingDirectory)/functions/.env"
|
||||
tokenPrefix: "#{"
|
||||
tokenSuffix: "}#"
|
||||
|
||||
- task: Npm@1
|
||||
displayName: "npm run build"
|
||||
inputs:
|
||||
command: "custom"
|
||||
workingDir: "$(System.DefaultWorkingDirectory)/functions"
|
||||
customCommand: "run build"
|
||||
|
||||
- task: DeleteFiles@1
|
||||
displayName: "Remove node_modules, *.log files, src directory from functions directory"
|
||||
inputs:
|
||||
SourceFolder: "$(System.DefaultWorkingDirectory)/functions"
|
||||
Contents: |
|
||||
node_modules/**
|
||||
*.log
|
||||
src/**
|
||||
|
||||
- task: ArchiveFiles@2
|
||||
displayName: "Archive functions directory"
|
||||
inputs:
|
||||
rootFolderOrFile: "$(System.DefaultWorkingDirectory)/functions"
|
||||
includeRootFolder: false
|
||||
archiveFile: "$(System.DefaultWorkingDirectory)/fitlien-services-$(buildNumber).zip"
|
||||
compression: "zip"
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: "Copy archive to staging directory"
|
||||
inputs:
|
||||
SourceFolder: "$(System.DefaultWorkingDirectory)"
|
||||
Contents: "fitlien-services-$(buildNumber).zip"
|
||||
TargetFolder: "$(System.ArtifactsDirectory)"
|
||||
@ -1,6 +0,0 @@
|
||||
MAILGUN_API_KEY=#{MAILGUN_API_KEY}#
|
||||
MAILGUN_SERVER=#{MAILGUN_SERVER}#
|
||||
MAILGUN_FROM_ADDRESS=#{MAILGUN_FROM_ADDRESS}#
|
||||
TWILIO_ACCOUNT_SID=AC5cfaae728ba68fb1aa6756d973b6e32b
|
||||
TWILIO_AUTH_TOKEN=886ed704c7918078f361f5f88b42ffc0
|
||||
TWILIO_PHONE_NUMBER=+12315005309
|
||||
114
functions/package-lock.json
generated
114
functions/package-lock.json
generated
@ -1,20 +1,16 @@
|
||||
{
|
||||
"name": "functions",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "functions",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"firebase-admin": "^12.6.0",
|
||||
"firebase-functions": "^6.0.1",
|
||||
"form-data": "^4.0.1",
|
||||
"html-to-text": "^9.0.5",
|
||||
"long": "4.0.0",
|
||||
"mailgun.js": "^10.4.0",
|
||||
"twilio": "^5.4.0"
|
||||
"mailgun.js": "^10.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"firebase-functions-test": "^3.1.0",
|
||||
@ -768,12 +764,6 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@grpc/proto-loader/node_modules/long": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz",
|
||||
"integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@istanbuljs/load-nyc-config": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
||||
@ -2202,11 +2192,6 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.13",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
|
||||
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
@ -2752,9 +2737,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/firebase-functions": {
|
||||
"version": "6.3.2",
|
||||
"resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-6.3.2.tgz",
|
||||
"integrity": "sha512-FC3A1/nhqt1ZzxRnj5HZLScQaozAcFSD/vSR8khqSoFNOfxuXgwJS6ZABTB7+v+iMD5z6Mmxw6OfqITUBuI7OQ==",
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-6.2.0.tgz",
|
||||
"integrity": "sha512-vfyyVHS8elxplzEQ9To+NaINRPFUsDasQrasTa2eFJBYSPzdhkw6rwLmvwyYw622+ze+g4sDIb14VZym+afqXQ==",
|
||||
"dependencies": {
|
||||
"@types/cors": "^2.8.5",
|
||||
"@types/express": "^4.17.21",
|
||||
@ -4434,9 +4419,9 @@
|
||||
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
|
||||
},
|
||||
"node_modules/long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
|
||||
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
@ -4474,9 +4459,9 @@
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
},
|
||||
"node_modules/mailgun.js": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-10.4.0.tgz",
|
||||
"integrity": "sha512-YrdaZEAJwwjXGBTfZTNQ1LM7tmkdUaz2NpZEu7+zULcG4Wrlhd7cWSNZW0bxT3bP48k5N0mZWz8C2f9gc2+Geg==",
|
||||
"version": "10.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-10.3.0.tgz",
|
||||
"integrity": "sha512-HJPmninRDGlzs8izNyfM/hbvefz6ol1gqeZ+doiumEHli7kGCrLlK6hURsq6oLjDoTNwgS37CUDhBPQy7x5PeQ==",
|
||||
"dependencies": {
|
||||
"axios": "^1.7.4",
|
||||
"base-64": "^1.0.0",
|
||||
@ -5044,11 +5029,6 @@
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/protobufjs/node_modules/long": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz",
|
||||
"integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng=="
|
||||
},
|
||||
"node_modules/proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||
@ -5250,11 +5230,6 @@
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"node_modules/scmp": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz",
|
||||
"integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q=="
|
||||
},
|
||||
"node_modules/selderee": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz",
|
||||
@ -5778,67 +5753,6 @@
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
|
||||
},
|
||||
"node_modules/twilio": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/twilio/-/twilio-5.4.0.tgz",
|
||||
"integrity": "sha512-kEmxzdOLTzXzUEXIkBVwT1Itxlbp+rtGrQogNfPtSE3EjoEsxrxB/9tdMIEbrsioL8CzTk/+fiKNJekAyHxjuQ==",
|
||||
"dependencies": {
|
||||
"axios": "^1.7.4",
|
||||
"dayjs": "^1.11.9",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"qs": "^6.9.4",
|
||||
"scmp": "^2.1.0",
|
||||
"xmlbuilder": "^13.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/twilio/node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/twilio/node_modules/debug": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/twilio/node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/twilio/node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
},
|
||||
"node_modules/type-detect": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||
@ -6085,14 +5999,6 @@
|
||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "13.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz",
|
||||
"integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==",
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
{
|
||||
"name": "functions",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"build:watch": "tsc --watch",
|
||||
@ -19,9 +18,7 @@
|
||||
"firebase-functions": "^6.0.1",
|
||||
"form-data": "^4.0.1",
|
||||
"html-to-text": "^9.0.5",
|
||||
"long": "4.0.0",
|
||||
"mailgun.js": "^10.4.0",
|
||||
"twilio": "^5.4.0"
|
||||
"mailgun.js": "^10.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"firebase-functions-test": "^3.1.0",
|
||||
|
||||
@ -1,16 +1,10 @@
|
||||
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) => {
|
||||
export const sendEmail = onRequest((request, response) => {
|
||||
const mailgun = new Mailgun(formData);
|
||||
const mailGunClient = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY });
|
||||
|
||||
@ -36,100 +30,3 @@ export const sendEmail = onRequest((request: Request, response: express.Response
|
||||
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;
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -2,8 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"module": "NodeNext",
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"moduleResolution": "node16",
|
||||
"moduleResolution": "nodenext",
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"outDir": "lib",
|
||||
|
||||
2530
package-lock.json
generated
2530
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,8 +0,0 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.10.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"firebase-functions": "^6.2.0"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user