Skip to content

Commit

Permalink
Merge pull request #361 from TAMUSHPE/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
mestrada03 authored May 28, 2024
2 parents 320f4b7 + 481548a commit f2ce3aa
Show file tree
Hide file tree
Showing 72 changed files with 3,230 additions and 1,339 deletions.
25 changes: 14 additions & 11 deletions functions/src/events.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as functions from 'firebase-functions';
import { db } from './firebaseConfig';
import { SHPEEvent, SHPEEventLog } from './types'
import { GeoPoint, Timestamp } from 'firebase-admin/firestore';
import { MillisecondTimes } from './timeUtils';
import { SHPEEvent, SHPEEventLog } from './types/events'
import { MillisecondTimes } from './helpers/timeUtils';

/**
* Converts an angle in degrees to radians
Expand Down Expand Up @@ -33,14 +33,15 @@ const geographicDistance = (pos1: GeoPoint, pos2: GeoPoint): number => {

const a = (Math.sin(deltaPhi / 2.0) ** 2) + Math.cos(phi1) * Math.cos(phi2) * (Math.sin(deltaLambda / 2.0) ** 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

return EARTH_RADIUS * c;
}

/**
* Handles a request from a user to sign into an event.
*/
export const eventSignIn = functions.https.onCall(async (data, context) => {
const uid = data.uid || context.auth?.uid;
if (!context.auth) {
throw new functions.https.HttpsError("unauthenticated", "Function cannot be called without authentication.");
} else if (typeof data !== "object" || typeof data.eventID !== "string" || typeof data.location !== "object") {
Expand All @@ -54,9 +55,9 @@ export const eventSignIn = functions.https.onCall(async (data, context) => {
}
console.info(data.location);
// Used to check if user has already signed into event
const eventLogDocRef = db.collection(`events/${data.eventID}/logs`).doc(context.auth.uid);
const eventLogDocRef = db.collection(`events/${data.eventID}/logs`).doc(uid);
const eventLog: SHPEEventLog = (await eventLogDocRef.get()).data() ?? {
uid: context.auth.uid,
uid: uid,
eventId: eventDocRef.id,
creationTime: Timestamp.fromMillis(Date.now()),
verified: true,
Expand All @@ -68,7 +69,7 @@ export const eventSignIn = functions.https.onCall(async (data, context) => {
else if (event.endTime && (event.endTime.toMillis() + (event.endTimeBuffer ?? 0)) < Date.now()) {
throw new functions.https.HttpsError("deadline-exceeded", "Event has already ended.");
}
else if (event.startTime && (event.startTime.toMillis() - (event.endTimeBuffer ?? 0) > Date.now())) {
else if (event.startTime && (event.startTime.toMillis() - (event.startTimeBuffer ?? 0) > Date.now())) {
throw new functions.https.HttpsError("failed-precondition", "Event has not started.")
}
else if (event.geolocation && event.geofencingRadius) {
Expand Down Expand Up @@ -96,7 +97,7 @@ export const eventSignIn = functions.https.onCall(async (data, context) => {

// Sets log in both event and user collection and ensures both happen by the end of the function.
await eventLogDocRef.set(eventLog, { merge: true });
await db.collection(`users/${context.auth.uid}/event-logs`).doc(data.eventID).set(eventLog, { merge: true });
await db.collection(`users/${uid}/event-logs`).doc(data.eventID).set(eventLog, { merge: true });

return { success: true };
});
Expand All @@ -106,6 +107,8 @@ export const eventSignIn = functions.https.onCall(async (data, context) => {
* Handles a request from a user to sign out of an event.
*/
export const eventSignOut = functions.https.onCall(async (data, context) => {
const uid = data.uid || context.auth?.uid;

if (!context.auth) {
throw new functions.https.HttpsError("unauthenticated", "Function cannot be called without authentication.");
} else if (typeof data !== "object" || typeof data.eventID !== "string" || typeof data.location !== "object") {
Expand All @@ -119,9 +122,9 @@ export const eventSignOut = functions.https.onCall(async (data, context) => {
}

// Used to check if user has already signed into event
const eventLogDocRef = db.collection(`events/${data.eventID}/logs`).doc(context.auth.uid);
const eventLogDocRef = db.collection(`events/${data.eventID}/logs`).doc(uid);
const eventLog: SHPEEventLog = (await eventLogDocRef.get()).data() ?? {
uid: context.auth.uid,
uid: uid,
eventId: eventDocRef.id,
creationTime: Timestamp.fromMillis(Date.now()),
verified: true,
Expand All @@ -133,7 +136,7 @@ export const eventSignOut = functions.https.onCall(async (data, context) => {
else if (event.endTime && (event.endTime.toMillis() + (event.endTimeBuffer ?? 0)) < Date.now()) {
throw new functions.https.HttpsError("deadline-exceeded", "Event has already ended.");
}
else if (event.startTime && (event.startTime.toMillis() - (event.endTimeBuffer ?? 0) > Date.now())) {
else if (event.startTime && (event.startTime.toMillis() - (event.startTimeBuffer ?? 0) > Date.now())) {
throw new functions.https.HttpsError("failed-precondition", "Event has not started.")
}
else if (event.geolocation && event.geofencingRadius) {
Expand Down Expand Up @@ -174,7 +177,7 @@ export const eventSignOut = functions.https.onCall(async (data, context) => {

// Sets log in both event and user collection and ensures both happen by the end of the function.
await eventLogDocRef.set(eventLog, { merge: true });
await db.collection(`users/${context.auth.uid}/event-logs`).doc(data.eventID).set(eventLog, { merge: true });
await db.collection(`users/${uid}/event-logs`).doc(data.eventID).set(eventLog, { merge: true });

return { success: true };
});
42 changes: 40 additions & 2 deletions functions/src/timeUtils.ts → functions/src/helpers/timeUtils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
/** This is the server side representation of an timeUtils.
* This document should be changed to match MobileApp/src/helper/timeUtils.ts
**/

/**
* Set of constants which can be used to do math with milliseconds
*/
export abstract class MillisecondTimes {
static readonly YEAR = 31556952000;
static readonly MONTH = 2629746000;
static readonly WEEK = 604800000;
static readonly DAY = 86400000;
static readonly HOUR = 3600000;
static readonly MINUTE = 60000;
Expand Down Expand Up @@ -31,7 +36,7 @@ export const formatDate = (date: Date): string => {
const month = monthNames[date.getMonth()];
const year = date.getFullYear();

return `${month} ${day} ${year}`;
return `${month} ${day}, ${year}`;
}

/**
Expand All @@ -43,7 +48,7 @@ export const formatTime = (date: Date): string => {
const hour = date.getHours();
const minute = date.getMinutes();

return `${hour % 12}:${minute.toString().padStart(2, '0')} ${hour > 11 ? "PM" : "AM"}`
return `${hour % 12 == 0 ? 12 : hour % 12}:${minute.toString().padStart(2, '0')} ${hour > 11 ? "PM" : "AM"}`
}

/**
Expand All @@ -55,3 +60,36 @@ export const formatDateTime = (date: Date): string => {
return `${formatDate(date)}, ${formatTime(date)} GMT${date.getTimezoneOffset() < 0 ? "+" : "-"}${(date.getTimezoneOffset() / 60).toString().padStart(2, '0')}`
}

export const formatEventDate = (startTime: Date, endTime: Date) => {
const isSameDay = startTime.getDate() === endTime.getDate() &&
startTime.getMonth() === endTime.getMonth() &&
startTime.getFullYear() === endTime.getFullYear();

const isSameMonth = startTime.getMonth() === endTime.getMonth() &&
startTime.getFullYear() === endTime.getFullYear();

const isSameYear = startTime.getFullYear() === endTime.getFullYear();
const formatMonthDayOnly = (date: Date): string => {
const day = date.getDate();
const month = monthNames[date.getMonth()];

return `${month} ${day}`;
}

const formatDayYearOnly = (date: Date): string => {
const day = date.getDate();
const year = date.getFullYear();

return `${day} ${year}`;
}

if (isSameDay) {
return `${formatDate(startTime)}`;
} else if (isSameMonth) {
return `${formatMonthDayOnly(startTime)}-${formatDayYearOnly(endTime)}`;
} else if (isSameYear) {
return `${formatMonthDayOnly(startTime)}-${formatDate(endTime)}`;
} else {
return `${formatDate(startTime)} - ${formatDate(endTime)}`;
}
};
5 changes: 3 additions & 2 deletions functions/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export { notifyUpcomingEvents, sendNotificationOfficeHours, sendNotificationMemberSHPE, sendNotificationCommitteeRequest, sendNotificationResumeConfirm } from "./pushNotification";
export { updateRanksScheduled, updateRanksOnCall, updateUserPoints, updateAllUserPoints } from "./pointSheet";
export { updateRanksScheduled, updateRanksOnCall, updateUserPoints, updateAllUserPoints, scheduledUpdateAllPoints } from "./pointSheet";
export { updateCommitteeCount } from "./committees";
export { resetOfficeScheduler, resetOfficeOnCall } from "./officeReset";
// export { resetOfficeScheduler } from "./officeReset";
export { resetOfficeOnCall } from "./officeReset";
export { zipResume } from "./resume";
export { updateUserRole } from "./roles";
export { checkUsernameUniqueness } from "./checkUsername";
Expand Down
23 changes: 21 additions & 2 deletions functions/src/pointSheet.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as functions from 'firebase-functions';
import { db } from "./firebaseConfig"
import { RankChange } from "./types";
import { AggregateField } from 'firebase-admin/firestore';
import { db } from "./firebaseConfig"


type RankChange = "increased" | "decreased" | "same";

/** Determines rank change based on current and new ranks.
* - "increased" means that the overall rank *value* is lower than before
Expand Down Expand Up @@ -169,3 +171,20 @@ export const updateAllUserPoints = functions.https.onCall(async (_, context) =>
throw new functions.https.HttpsError("aborted", `Issue occured while attempting to update user document: ${err}`);
});
});

export const scheduledUpdateAllPoints = functions.pubsub.schedule('0 5 * * *').timeZone('America/Chicago').onRun(async (context) => {
try {
const snapshot = await db.collection('users').get();
const updatePromises = snapshot.docs.map(async (document) => {
return document.ref.set({
points: await calculateUserPoints(document.id),
pointsThisMonth: await calculateUserPointsThisMonth(document.id),
}, { merge: true });
});
await Promise.all(updatePromises);
return { success: true };
} catch (err) {
throw new functions.https.HttpsError("aborted", `Issue occurred while attempting to update user documents: ${err}`);
}
});

2 changes: 1 addition & 1 deletion functions/src/pushNotification.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as functions from 'firebase-functions';
import { db } from './firebaseConfig';
import { Expo, ExpoPushMessage } from 'expo-server-sdk';
import { SHPEEvent } from './types';
import { SHPEEvent } from './types/events';
/**
* Fetches the Expo push tokens of a member.
*
Expand Down
2 changes: 1 addition & 1 deletion functions/src/resume.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as functions from 'firebase-functions';
import archiver from 'archiver';
import { bucket, db } from './firebaseConfig';
import archiver from 'archiver';


const generateSignedUrl = async (fileName: string) => {
Expand Down
Empty file removed functions/src/resumeZip.ts
Empty file.
2 changes: 1 addition & 1 deletion functions/src/roles.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { auth } from "./firebaseConfig"
import * as functions from 'firebase-functions';
import { auth } from "./firebaseConfig"

/**
* Given a request header containing a `uid` and `roles` object, sets a user's custom claims to given `roles` object.
Expand Down
Loading

0 comments on commit f2ce3aa

Please sign in to comment.