Guest User

Untitled

a guest
Sep 24th, 2025
9
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.22 KB | None | 0 0
  1. Frontend (don't mind the fieldTypes):
  2.  
  3. export async function processActivities(
  4.   // eslint-disable-next-line u/typescript-eslint/no-explicit-any
  5.   data: any[],
  6.   fieldTypes: Record<string, string>
  7. ): Promise<void> {
  8.   try {
  9.     await setDoc(doc(firestore, '_tools_', 'activitiesProcessor'), fieldTypes, { merge: true });
  10.  
  11.     const limit = pLimit(5); // only 5 in flight
  12.     const promises = [];
  13.  
  14.     const processActivity = httpsCallable(backendFunctions, 'processActivity');
  15.  
  16.     for (const activityData of data) {
  17.       promises.push(limit(() => processActivity({ activityData, fieldTypes })));
  18.     }
  19.     await Promise.all(promises);
  20.     console.log('Activities processed successfully');
  21.   } catch (err) {
  22.     console.error('Failed to process activities', err);
  23.   }
  24. }
  25. --------------------------------------------------------------------------------------------
  26. Backend (again, don't mind the fieldTypes. activityData is mostly strings and pictures (3 to 5 per activity) that needs processing):
  27.  
  28. import * as admin from "firebase-admin";
  29. import * as functions from "firebase-functions/v2/https";
  30. import { getDownloadURL } from "firebase-admin/storage";
  31. import * as sharp from "sharp";
  32. import { v4 as uuidv4 } from "uuid";
  33.  
  34. export const processActivity = functions.onCall(
  35.   {
  36.     memory: "4GiB",
  37.     timeoutSeconds: 3600,
  38.   },
  39.   async (request) => {
  40.     const { activityData, fieldTypes } = request.data;
  41.  
  42.     const activityId = activityData["custom ID"];
  43.     const picturesArray = activityData.pictures
  44.       .split(",")
  45.       .map((url: string) => url.trim());
  46.     const hashTagArray = activityData.hashtag
  47.       .split(",")
  48.       .map((hashtag: string) => hashtag.trim());
  49.  
  50.     console.log("activityData", activityData);
  51.     console.log("fieldTypes", fieldTypes);
  52.     console.log("activityId", activityId);
  53.     console.log("picturesArray", picturesArray);
  54.     console.log("hashTagArray", hashTagArray);
  55.  
  56.     const storage = admin.storage();
  57.     const db = admin.firestore();
  58.  
  59.     const processedUrls: string[] = []; // for frontend (includes errors)
  60.     const uploadedUrls: string[] = []; // for Firestore (only successful uploads)
  61.  
  62.     for (const url of picturesArray) {
  63.       try {
  64.         // download original image
  65.         const response = await fetch(url);
  66.         const buffer = Buffer.from(await response.arrayBuffer());
  67.  
  68.         // process image with sharp
  69.         const processedBuffer = await sharp(buffer)
  70.           .resize({ height: 2000, withoutEnlargement: true })
  71.           .webp({ quality: 80 })
  72.           .toBuffer();
  73.  
  74.         // generate unique file name
  75.         const fileName = `resizedPicturesTest/${activityId}/${uuidv4()}.webp`;
  76.         console.log("fileName", fileName);
  77.  
  78.         const file = storage.bucket().file(fileName);
  79.  
  80.         // upload to Firebase Storage
  81.         await file.save(processedBuffer, {
  82.           metadata: { contentType: "image/webp" },
  83.         });
  84.  
  85.         // get download URL from Storage (admin SDK)
  86.         const downloadUrl = await getDownloadURL(file);
  87.         console.log("downloadUrl", downloadUrl);
  88.  
  89.         // push to both arrays
  90.         processedUrls.push(downloadUrl);
  91.         uploadedUrls.push(downloadUrl);
  92.       } catch (err) {
  93.         console.error("Failed to process", url, err);
  94.  
  95.         // add an error message only for frontend
  96.         processedUrls.push(`Failed to process image: ${url}`);
  97.       }
  98.     }
  99.  
  100.     console.log("processedUrls", processedUrls);
  101.  
  102.     // write only successful uploads to Firestore
  103.     if (activityId && uploadedUrls.length > 0) {
  104.       try {
  105.         const docRef = db.collection("activities_test").doc(activityId);
  106.  
  107.         await docRef.set(
  108.           { pictures: admin.firestore.FieldValue.arrayUnion(...uploadedUrls) },
  109.           { merge: true }
  110.         );
  111.         console.log(`Firestore updated for document: ${activityId}`);
  112.       } catch (err) {
  113.         console.error("Failed to write URLs to Firestore", err);
  114.       }
  115.     }
  116.  
  117.     return { urls: processedUrls };
  118.   }
  119. );
Advertisement
Add Comment
Please, Sign In to add comment