diff --git a/server/package.json b/server/package.json index 430552b70..2db90646c 100644 --- a/server/package.json +++ b/server/package.json @@ -14,13 +14,11 @@ "description": "", "dependencies": { "collections": "^5.1.13", - "express": "^4.21.1", "firebase-admin": "^12.7.0", "geofire-common": "^6.0.0", "socket.io": "^4.8.1" }, "devDependencies": { - "@types/express": "^5.0.0", "@types/jest": "^29.5.11", "@babel/preset-env": "^7.23.8", "@babel/preset-typescript": "^7.23.3", @@ -32,4 +30,4 @@ ".js" ] } -} +} \ No newline at end of file diff --git a/server/src/index.ts b/server/src/index.ts index d3215e501..46149f66d 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -1,6 +1,3 @@ -import { startRESTServer } from "./rest_server/rest_server" import { startSocketServer } from "./socket_server/socket_server" -// Unsure if REST server is even necessary for MVP; auth, managing database can be done on client with https://rnfirebase.io/ -//startRESTServer(); startSocketServer(); diff --git a/server/src/rest_server/rest_server.ts b/server/src/rest_server/rest_server.ts deleted file mode 100644 index fde871c85..000000000 --- a/server/src/rest_server/rest_server.ts +++ /dev/null @@ -1,42 +0,0 @@ -import express from "express"; -import usersRouter from "./routes/users/users"; - -export const startRESTServer = () => { - const port = Number(process.env.express_port) ?? 8081; - - const app = express(); - app.use(express.json()); - app.use(express.urlencoded({extended: true})); - - // TODO: ensure authorized - - const router = express.Router(); - - router.all("/", (req, res) => { - res.send("Echologator API") - res.status(200); - }); - - router.all("*", (req, res) => { - res.send("Path or method could not be found!"); - res.status(404); - }); - - // === REST APIs === - - // PATH: /users - // post - creates a new user - // put - updates an existing user - // delete - deletes a user - // get - returns a user's public info - router.use(usersRouter); - - // - - app.use(router); - app.listen(port, () => { - return console.log( - `[EXP] Listening for requests at http://127.0.0.1:${port}.` - ); - }); -} \ No newline at end of file diff --git a/server/src/rest_server/routes/users/post_create.ts b/server/src/rest_server/routes/users/post_create.ts deleted file mode 100644 index ada6946f6..000000000 --- a/server/src/rest_server/routes/users/post_create.ts +++ /dev/null @@ -1,5 +0,0 @@ -import usersRouter from "./users"; - -usersRouter.post("/users", async (req, res) => { - -}); \ No newline at end of file diff --git a/server/src/rest_server/routes/users/users.ts b/server/src/rest_server/routes/users/users.ts deleted file mode 100644 index c5da59eef..000000000 --- a/server/src/rest_server/routes/users/users.ts +++ /dev/null @@ -1,5 +0,0 @@ -import express from "express"; - -const usersRouter = express.Router(); - -export default usersRouter; \ No newline at end of file diff --git a/server/src/socket_server/firebase_methods.ts b/server/src/socket_server/firebase_methods.ts index 279b41d89..7463fd3ce 100644 --- a/server/src/socket_server/firebase_methods.ts +++ b/server/src/socket_server/firebase_methods.ts @@ -16,6 +16,10 @@ export const ensureUserAuthorized = async (token: any): Promise<[uid: string | u } export const getUserProfile = async (uid: string): Promise => { + return { + displayName: "Test Display Name", + profilePicture: 12, + } const userProfileSnapshot = await firebase.firestore().collection('users').doc(uid).get(); return userProfileSnapshot.data(); } \ No newline at end of file diff --git a/server/src/socket_server/methods/send_message.ts b/server/src/socket_server/methods/send_message.ts index 6defbb3a6..65e5e1755 100644 --- a/server/src/socket_server/methods/send_message.ts +++ b/server/src/socket_server/methods/send_message.ts @@ -4,8 +4,13 @@ import { ConnectionContext } from "../socket_server"; // Called when client sends a message export const sendMessage = (ctx: ConnectionContext, message: Message, ack: any): void => { + if (message.location === undefined) { + message.location = ctx.user.location; + } + const recipients = getActiveUsersInView(message.location); for (const recipient of recipients) { + if (recipient.uid == ctx.user.uid) continue; // skip sender recipient.socket.emit("message", message); } diff --git a/server/src/socket_server/regions.ts b/server/src/socket_server/regions.ts index 2d1973242..be2c7b420 100644 --- a/server/src/socket_server/regions.ts +++ b/server/src/socket_server/regions.ts @@ -13,10 +13,10 @@ export const viewDistanceMeters = 100; var regions = new SortedSet( null, function keysEqual(a: { key: any; }, b: { key: any; }) { - return a.key === b.key; + return b.key === a.key; }, function compareKeys(a: { key: string; }, b: { key: any; }) { - return a.key.localeCompare(b.key); + return b.key.localeCompare(a.key); } ); @@ -27,13 +27,18 @@ export const initRegions = () => { export const setActiveUserRegion = (activeUser: ActiveUser, oldLocation: Location | undefined, newLocation: Location): void => { if (oldLocation !== undefined) { // Remove user from previous geohash - delete regions[oldLocation.geohash][activeUser.uid]; + delete regions.get({ key: oldLocation.geohash, value: undefined }).value[activeUser.uid]; } - regions[newLocation.geohash][activeUser.uid] = activeUser; + if (!regions.has({ key: newLocation.geohash, value: undefined })) { + regions.push({ key: newLocation.geohash, value: {} }) + } + regions.get({ key: newLocation.geohash, value: undefined }).value[activeUser.uid] = activeUser; }; export const removeActiveUser = (activeUser: ActiveUser): void => { - delete regions[activeUser.location.geohash][activeUser.uid]; + if (activeUser.location.geohash == "") return; // User never sent an updateLocation message so they are not in the regions map + //if (!regions.has({ key: activeUser.location.geohash, value: undefined })) return; + delete regions.get({ key: activeUser.location.geohash, value: undefined }).value[activeUser.uid]; } export const getActiveUsersInView = function* (location: Location): Generator { @@ -46,14 +51,20 @@ export const getActiveUsersInView = function* (location: Location): Generator rightBoundGeohash) continue; + regions.splayIndex(index); while (geohash <= rightBoundGeohash) { - const activeUsers = regions[index].value; + const activeUsers = Object.values(regions.root.value.value); for (const activeUser of activeUsers) { // Run distance check to ensure users are actually in view, since geofire output is liberal if (isWithinRadiusMeters(location, activeUser.location, viewDistanceMeters)) { @@ -62,7 +73,8 @@ export const getActiveUsersInView = function* (location: Location): Generator= regions.length) break; - geohash = regions[++index]; + regions.splayIndex(++index); + geohash = regions.root.value.key; } } } \ No newline at end of file diff --git a/server/src/socket_server/socket_server.ts b/server/src/socket_server/socket_server.ts index 8c1ad1413..fce229935 100644 --- a/server/src/socket_server/socket_server.ts +++ b/server/src/socket_server/socket_server.ts @@ -2,7 +2,6 @@ import http from "http" import io from "socket.io"; import { ActiveUser } from "../types"; -import firebase from "firebase-admin"; import * as methods from "./methods"; import { initRegions, removeActiveUser } from "./regions"; import { ensureUserAuthorized, getUserProfile } from "./firebase_methods"; @@ -17,7 +16,7 @@ export interface ConnectionContext { export const startSocketServer = () => { initRegions(); - const port = Number(process.env.socket_port) ?? 8082; + const port = Number(process.env.socket_port ?? "8082"); const httpServer = http.createServer(); const socketServer = new io.Server(httpServer, { @@ -40,7 +39,7 @@ export const startSocketServer = () => { } console.log(`[WS] User <${uid}> authenticated.`); - + // // === Pull User Profile from Firebase === @@ -82,11 +81,11 @@ export const startSocketServer = () => { // === METHODS === - socket.on("ping", (ack: any) => methods.ping(ctx, ack)); + socket.on("ping", (_: any, ack: any) => methods.ping(ctx, ack)); socket.on("updateLocation", (location: any, ack: any) => methods.updateLocation(ctx, location, ack)) socket.on("sendMessage", (message: any, ack: any) => methods.sendMessage(ctx, message, ack)); - socket.on("getNearbyUsers", (callback: (nearbyUserUids: string[]) => void) => methods.getNearbyUsers(ctx, callback)); - socket.on("notifyUpdateProfile", (ack: any) => methods.notifyUpdateProfile(ctx, ack)); + socket.on("getNearbyUsers", (_: any, callback: (nearbyUserUids: string[]) => void) => methods.getNearbyUsers(ctx, callback)); + socket.on("notifyUpdateProfile", (_: any, ack: any) => methods.notifyUpdateProfile(ctx, ack)); // }); diff --git a/server/src/types/user_profile.ts b/server/src/types/user_profile.ts index 99330df0a..a30a8d5c9 100644 --- a/server/src/types/user_profile.ts +++ b/server/src/types/user_profile.ts @@ -1,4 +1,14 @@ export interface UserProfile { displayName: string, profilePicture: number, -} \ No newline at end of file +} + +// [ +// { +// uid: "uid", +// profile: { +// displayName: "Name", +// profilePicture: 2, +// } +// } +// ] \ No newline at end of file