Skip to content

Commit f65ed64

Browse files
authored
Merge pull request JaredPotter#9 from JaredPotter/version-9
Version 9
2 parents 6b5948b + 693d5b2 commit f65ed64

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+33083
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This project requires the `.env` file created in section 2.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"hosting": {
3+
"public": "build",
4+
"ignore": [
5+
"firebase.json",
6+
"**/.*",
7+
"**/node_modules/**"
8+
],
9+
"rewrites": [
10+
{
11+
"source": "**",
12+
"destination": "/index.html"
13+
}
14+
]
15+
},
16+
"emulators": {
17+
"functions": {
18+
"port": 5001
19+
},
20+
"hosting": {
21+
"port": 5000
22+
},
23+
"ui": {
24+
"enabled": true
25+
}
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const functions = require("firebase-functions");
2+
const admin = require("firebase-admin");
3+
4+
const FIREBASE_STORAGE_BUCKET = "fir-recipes-15644.appspot.com";
5+
6+
const apiFirebaseOptions = {
7+
...functions.config().firebase,
8+
credential: admin.credential.applicationDefault(),
9+
};
10+
11+
admin.initializeApp(apiFirebaseOptions);
12+
13+
const firestore = admin.firestore();
14+
const settings = { timestampsInSnapshots: true };
15+
16+
firestore.settings(settings);
17+
18+
const storageBucket = admin.storage().bucket(FIREBASE_STORAGE_BUCKET);
19+
const auth = admin.auth();
20+
21+
module.exports = { functions, auth, firestore, storageBucket, admin };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
const FirebaseConfig = require("./FirebaseConfig");
2+
const recipesApi = require("./recipesApi");
3+
const functions = FirebaseConfig.functions;
4+
const firestore = FirebaseConfig.firestore;
5+
const storageBucket = FirebaseConfig.storageBucket;
6+
const admin = FirebaseConfig.admin;
7+
8+
exports.api = functions.https.onRequest(recipesApi);
9+
10+
exports.onCreateRecipe = functions.firestore
11+
.document("recipes/{recipeId}")
12+
.onCreate(async (snapshot) => {
13+
const countDocRef = firestore.collection("recipeCounts").doc("all");
14+
const countDoc = await countDocRef.get();
15+
16+
if (countDoc.exists) {
17+
countDocRef.update({ count: admin.firestore.FieldValue.increment(1) });
18+
} else {
19+
countDocRef.set({ count: 1 });
20+
}
21+
22+
const recipe = snapshot.data();
23+
24+
if (recipe.isPublished) {
25+
const countPublishedDocRef = firestore
26+
.collection("recipeCounts")
27+
.doc("published");
28+
const countPublishedDoc = await countPublishedDocRef.get();
29+
30+
if (countPublishedDoc.exists) {
31+
countPublishedDocRef.update({
32+
count: admin.firestore.FieldValue.increment(1),
33+
});
34+
} else {
35+
countPublishedDocRef.set({ count: 1 });
36+
}
37+
}
38+
});
39+
40+
exports.onUpdateRecipe = functions.firestore
41+
.document("recipes/{recipeId}")
42+
.onUpdate(async (changes) => {
43+
const oldRecipe = changes.before.data();
44+
const newRecipe = changes.after.data();
45+
46+
let publishCount = 0;
47+
48+
if (!oldRecipe.isPublished && newRecipe.isPublished) {
49+
publishCount += 1;
50+
} else if (oldRecipe.isPublished && !newRecipe.isPublished) {
51+
publishCount -= 1;
52+
}
53+
54+
if (publishCount !== 0) {
55+
const publishedCountDocRef = firestore
56+
.collection("recipeCounts")
57+
.doc("published");
58+
59+
const publishedCountDoc = await publishedCountDocRef.get();
60+
61+
if (publishedCountDoc.exists) {
62+
publishedCountDocRef.update({
63+
count: admin.firestore.FieldValue.increment(publishCount),
64+
});
65+
} else {
66+
if (publishCount > 0) {
67+
publishedCountDocRef.set({ count: publishCount });
68+
} else {
69+
publishedCountDocRef.set({ count: 0 });
70+
}
71+
}
72+
}
73+
});
74+
75+
exports.onDeleteRecipe = functions.firestore
76+
.document("recipes/{recipeId}")
77+
.onDelete(async (snapshot) => {
78+
const recipe = snapshot.data();
79+
const imageUrl = recipe.imageUrl;
80+
81+
if (imageUrl) {
82+
const decodedUrl = decodeURIComponent(imageUrl);
83+
const startIndex = decodedUrl.indexOf("/o/") + 3;
84+
const endIndex = decodedUrl.indexOf("?");
85+
const fullFilePath = decodedUrl.substring(startIndex, endIndex);
86+
const file = storageBucket.file(fullFilePath);
87+
88+
console.log(`Attemping to delete: ${fullFilePath}`);
89+
90+
try {
91+
await file.delete();
92+
console.log("Successfully deleted image.");
93+
} catch (error) {
94+
console.log(`Failed to delete file: ${error.message}`);
95+
}
96+
97+
const countDocRef = firestore.collection("recipeCounts").doc("all");
98+
const countDoc = await countDocRef.get();
99+
100+
if (countDoc.exists) {
101+
countDocRef.update({ count: admin.firestore.FieldValue.increment(-1) });
102+
} else {
103+
countDocRef.set({ count: 0 });
104+
}
105+
106+
const recipe = snapshot.data();
107+
108+
if (recipe.isPublished) {
109+
const countPublishedDocRef = firestore
110+
.collection("recipeCounts")
111+
.doc("published");
112+
const countPublishedDoc = await countPublishedDocRef.get();
113+
114+
if (countPublishedDoc.exists) {
115+
countPublishedDocRef.update({
116+
count: admin.firestore.FieldValue.increment(-1),
117+
});
118+
} else {
119+
countPublishedDocRef.set({ count: 0 });
120+
}
121+
}
122+
}
123+
});
124+
125+
// https://crontab.guru/
126+
127+
const runtimeOptions = {
128+
timeoutSeconds: 300,
129+
memory: "256MB",
130+
};
131+
132+
exports.dailyCheckRecipePublishDate = functions
133+
.runWith(runtimeOptions)
134+
.pubsub.schedule("0 0 * * *")
135+
.onRun(async () => {
136+
console.log("dailyCheckRecipePublishDate() called - time to check");
137+
138+
const snapshot = await firestore
139+
.collection("recipes")
140+
.where("isPublished", "==", false)
141+
.get();
142+
143+
snapshot.forEach(async (doc) => {
144+
const data = doc.data();
145+
const now = Date.now() / 1000;
146+
const isPublished = data.publishDate._seconds <= now ? true : false;
147+
148+
if (isPublished) {
149+
console.log(`Recipe: ${data.name} is now published!`);
150+
151+
firestore.collection("recipes").doc(doc.id).set(
152+
{
153+
isPublished,
154+
},
155+
{
156+
merge: true,
157+
}
158+
);
159+
}
160+
});
161+
});
162+
163+
console.log("SERVER STARTED!");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "functions",
3+
"description": "Cloud Functions for Firebase",
4+
"scripts": {
5+
"serve": "firebase emulators:start --only functions",
6+
"shell": "firebase functions:shell",
7+
"start": "npm run shell",
8+
"deploy": "firebase deploy --only functions",
9+
"logs": "firebase functions:log"
10+
},
11+
"engines": {
12+
"node": "12"
13+
},
14+
"main": "index.js",
15+
"dependencies": {
16+
"firebase-admin": "^9.2.0",
17+
"firebase-functions": "^3.11.0"
18+
},
19+
"devDependencies": {
20+
"firebase-functions-test": "^0.2.0"
21+
},
22+
"private": true
23+
}

0 commit comments

Comments
 (0)