Compare commits
3 Commits
a89ff0f30c
...
04077d95f4
| Author | SHA1 | Date | |
|---|---|---|---|
| 04077d95f4 | |||
| cff02bcc03 | |||
|
|
c92befa9a4 |
83
fitlien-services-pipeline.yaml
Normal file
83
fitlien-services-pipeline.yaml
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
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)"
|
||||||
6
functions/.env.example
Normal file
6
functions/.env.example
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
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,16 +1,20 @@
|
|||||||
{
|
{
|
||||||
"name": "functions",
|
"name": "functions",
|
||||||
|
"version": "0.0.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "functions",
|
"name": "functions",
|
||||||
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"firebase-admin": "^12.6.0",
|
"firebase-admin": "^12.6.0",
|
||||||
"firebase-functions": "^6.0.1",
|
"firebase-functions": "^6.0.1",
|
||||||
"form-data": "^4.0.1",
|
"form-data": "^4.0.1",
|
||||||
"html-to-text": "^9.0.5",
|
"html-to-text": "^9.0.5",
|
||||||
"mailgun.js": "^10.3.0"
|
"long": "4.0.0",
|
||||||
|
"mailgun.js": "^10.4.0",
|
||||||
|
"twilio": "^5.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"firebase-functions-test": "^3.1.0",
|
"firebase-functions-test": "^3.1.0",
|
||||||
@ -764,6 +768,12 @@
|
|||||||
"node": ">=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": {
|
"node_modules/@istanbuljs/load-nyc-config": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
|
||||||
@ -2192,6 +2202,11 @@
|
|||||||
"node": ">= 8"
|
"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": {
|
"node_modules/debug": {
|
||||||
"version": "2.6.9",
|
"version": "2.6.9",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
@ -2737,9 +2752,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/firebase-functions": {
|
"node_modules/firebase-functions": {
|
||||||
"version": "6.2.0",
|
"version": "6.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-6.3.2.tgz",
|
||||||
"integrity": "sha512-vfyyVHS8elxplzEQ9To+NaINRPFUsDasQrasTa2eFJBYSPzdhkw6rwLmvwyYw622+ze+g4sDIb14VZym+afqXQ==",
|
"integrity": "sha512-FC3A1/nhqt1ZzxRnj5HZLScQaozAcFSD/vSR8khqSoFNOfxuXgwJS6ZABTB7+v+iMD5z6Mmxw6OfqITUBuI7OQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/cors": "^2.8.5",
|
"@types/cors": "^2.8.5",
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
@ -4419,9 +4434,9 @@
|
|||||||
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
|
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
|
||||||
},
|
},
|
||||||
"node_modules/long": {
|
"node_modules/long": {
|
||||||
"version": "5.2.3",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||||
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
|
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||||
},
|
},
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
@ -4459,9 +4474,9 @@
|
|||||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||||
},
|
},
|
||||||
"node_modules/mailgun.js": {
|
"node_modules/mailgun.js": {
|
||||||
"version": "10.3.0",
|
"version": "10.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-10.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-10.4.0.tgz",
|
||||||
"integrity": "sha512-HJPmninRDGlzs8izNyfM/hbvefz6ol1gqeZ+doiumEHli7kGCrLlK6hURsq6oLjDoTNwgS37CUDhBPQy7x5PeQ==",
|
"integrity": "sha512-YrdaZEAJwwjXGBTfZTNQ1LM7tmkdUaz2NpZEu7+zULcG4Wrlhd7cWSNZW0bxT3bP48k5N0mZWz8C2f9gc2+Geg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.7.4",
|
"axios": "^1.7.4",
|
||||||
"base-64": "^1.0.0",
|
"base-64": "^1.0.0",
|
||||||
@ -5029,6 +5044,11 @@
|
|||||||
"node": ">=12.0.0"
|
"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": {
|
"node_modules/proxy-addr": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||||
@ -5230,6 +5250,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"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": {
|
"node_modules/selderee": {
|
||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz",
|
||||||
@ -5753,6 +5778,67 @@
|
|||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
|
"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": {
|
"node_modules/type-detect": {
|
||||||
"version": "4.0.8",
|
"version": "4.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||||
@ -5999,6 +6085,14 @@
|
|||||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
"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": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "functions",
|
"name": "functions",
|
||||||
|
"version": "0.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"build:watch": "tsc --watch",
|
"build:watch": "tsc --watch",
|
||||||
@ -18,7 +19,9 @@
|
|||||||
"firebase-functions": "^6.0.1",
|
"firebase-functions": "^6.0.1",
|
||||||
"form-data": "^4.0.1",
|
"form-data": "^4.0.1",
|
||||||
"html-to-text": "^9.0.5",
|
"html-to-text": "^9.0.5",
|
||||||
"mailgun.js": "^10.3.0"
|
"long": "4.0.0",
|
||||||
|
"mailgun.js": "^10.4.0",
|
||||||
|
"twilio": "^5.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"firebase-functions-test": "^3.1.0",
|
"firebase-functions-test": "^3.1.0",
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
import { onRequest } from "firebase-functions/v2/https";
|
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";
|
import * as logger from "firebase-functions/logger";
|
||||||
|
|
||||||
const formData = require('form-data');
|
const formData = require('form-data');
|
||||||
const Mailgun = require('mailgun.js');
|
const Mailgun = require('mailgun.js');
|
||||||
const { convert } = require('html-to-text');
|
const { convert } = require('html-to-text');
|
||||||
|
const twilio = require('twilio')
|
||||||
|
|
||||||
export const sendEmail = onRequest((request, response) => {
|
export const sendEmail = onRequest((request: Request, response: express.Response) => {
|
||||||
const mailgun = new Mailgun(formData);
|
const mailgun = new Mailgun(formData);
|
||||||
const mailGunClient = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY });
|
const mailGunClient = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY });
|
||||||
|
|
||||||
@ -30,3 +36,100 @@ export const sendEmail = onRequest((request, response) => {
|
|||||||
response.send(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
@ -2,7 +2,8 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "NodeNext",
|
"module": "NodeNext",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"moduleResolution": "nodenext",
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"moduleResolution": "node16",
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"outDir": "lib",
|
"outDir": "lib",
|
||||||
|
|||||||
2530
package-lock.json
generated
Normal file
2530
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
8
package.json
Normal file
8
package.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^22.10.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"firebase-functions": "^6.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user