Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 68 additions & 28 deletions functions/create-room/src/main.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,106 @@
import AppwriteService from "./appwrite.js";
import LivekitService from "./livekit.js";
import { throwIfMissing } from "./utils.js";
import { throwIfMissing, parseBody } from "./utils.js";

export default async ({ req, res, log, error }) => {
throwIfMissing(process.env, [
"APPWRITE_API_KEY",
"MASTER_DATABASE_ID",
"ROOMS_COLLECTION_ID",
"LIVEKIT_HOST",
"LIVEKIT_API_KEY",
"LIVEKIT_API_SECRET",
"LIVEKIT_SOCKET_URL",
]);
// Validate environment variables
try {
throwIfMissing(process.env, [
"APPWRITE_API_KEY",
"MASTER_DATABASE_ID",
"ROOMS_COLLECTION_ID",
"LIVEKIT_HOST",
"LIVEKIT_API_KEY",
"LIVEKIT_API_SECRET",
"LIVEKIT_SOCKET_URL",
]);
} catch (err) {
error("[ENV_ERROR] " + err.message);
return res.json({
success: false,
message: err.message,
}, 500);
}

const appwrite = new AppwriteService();
const livekit = new LivekitService();

let data;

// ✅ Safe parsing + validation
try {
throwIfMissing(JSON.parse(req.body), ["name", "adminUid", "tags"]);
data = parseBody(req.body);
throwIfMissing(data, ["name", "adminUid", "tags"]);
} catch (err) {
error(err.message);
return res.json({ msg: err.message }, 400);
error("[VALIDATION_ERROR] " + err.message);
return res.json({
success: false,
message: err.message,
}, 400);
}

const { name, description = "", adminUid, tags } = data;

try {
log(req);
const { name, description, adminUid, tags } = JSON.parse(req.body);
log("[CREATE_ROOM_REQUEST]", { name, adminUid, tags });

// create a new room on appwrite
// Create room in Appwrite
const newRoomdata = {
name,
description,
adminUid,
tags,
totalParticipants: 1,
};

const appwriteRoomId = await appwrite.createRoom(newRoomdata);
log(appwriteRoomId);
log("[APPWRITE_ROOM_CREATED]", appwriteRoomId);

// create a new livekit room
// Create room in LiveKit
const livekitRoomOptions = {
name: appwriteRoomId, // using appwrite room doc id as livekit room name
emptyTimeout: 300, // timeout in seconds
name: appwriteRoomId,
emptyTimeout: 300,
};

const livekitRoom = await livekit.createRoom(livekitRoomOptions);
log(livekitRoom);
log("[LIVEKIT_ROOM_CREATED]", livekitRoom);

// Creating a token for the admin
// Generate token for admin
const accessToken = livekit.generateToken(
appwriteRoomId,
adminUid,
true
);

// Add track-activity
await fetch("http://localhost/track-activity", {
method: "POST",
body: JSON.stringify({
eventType: "ROOM_CREATED",
userId: adminUid,
metadata: {
roomId: appwriteRoomId,
},
}),
});
Comment thread
Shweta-281 marked this conversation as resolved.

return res.json({
msg: "Room created Successfully",
livekit_room: livekitRoom,
livekit_socket_url: `${process.env.LIVEKIT_SOCKET_URL}`,
access_token: accessToken,
success: true,
message: "Room created successfully",
data: {
roomId: appwriteRoomId,
livekit_room: livekitRoom,
livekit_socket_url: process.env.LIVEKIT_SOCKET_URL,
access_token: accessToken,
},
});
} catch (e) {
error(String(e));
return res.json({ msg: "Room creation failed" }, 500);
error("[CREATE_ROOM_ERROR] " + String(e));

return res.json({
success: false,
message: "Room creation failed",
}, 500);
}

};
16 changes: 15 additions & 1 deletion functions/create-room/src/utils.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
export const throwIfMissing = (obj, keys) => {
const missing = [];

for (let key of keys) {
if (!(key in obj) || !obj[key]) {
if (!(key in obj) || obj[key] === undefined || obj[key] === null) {
missing.push(key);
}
}

if (missing.length > 0) {
throw new Error(`Missing required fields: ${missing.join(", ")}`);
}
};

export const parseBody = (body) => {
if (!body) {
throw new Error("Request body is empty");
}

try {
return JSON.parse(body);
} catch (err) {
throw new Error("Invalid JSON body");
}
}
48 changes: 34 additions & 14 deletions functions/database-cleaner/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,55 @@ import AppwriteService from "./appwrite.js";
import { throwIfMissing } from "./utils.js";

export default async (context) => {
throwIfMissing(process.env, [
"APPWRITE_API_KEY",
"ROOMS_COLLECTION_ID",
"PARTICIPANTS_COLLECTION_ID",
"ACTIVE_PAIRS_COLLECTION_ID",
"RETENTION_PERIOD_DAYS",
"VERIFICATION_DATABASE_ID",
"OTP_COLLECTION_ID",
]);
const { res, log, error } = context;

// Environment validation
try {
throwIfMissing(process.env, [
"APPWRITE_API_KEY",
"ROOMS_COLLECTION_ID",
"PARTICIPANTS_COLLECTION_ID",
"ACTIVE_PAIRS_COLLECTION_ID",
"RETENTION_PERIOD_DAYS",
"VERIFICATION_DATABASE_ID",
"OTP_COLLECTION_ID",
]);
} catch (err) {
error("[ENV_ERROR] " + err.message);
return res.json({
success: false,
message: err.message,
}, 500);
}
Comment thread
Shweta-281 marked this conversation as resolved.

const appwrite = new AppwriteService();

// Cleanup Participants
try {
await appwrite.cleanParticipantsCollection();
log("[CLEANUP] Participants collection cleaned");
} catch (e) {
context.error(String(e));
error("[CLEANUP_ERROR] Participants: " + String(e));
}

// Cleanup Active Pairs
try {
await appwrite.cleanActivePairsCollection();
log("[CLEANUP] Active pairs collection cleaned");
} catch (e) {
context.error(String(e));
error("[CLEANUP_ERROR] ActivePairs: " + String(e));
}

// Cleanup OTPs
try {
await appwrite.clearOldOTPs();
log("[CLEANUP] Old OTPs cleared");
} catch (e) {
context.error(String(e));
error("[CLEANUP_ERROR] OTP: " + String(e));
}

return context.res.send("Database Cleanup completed. And unnecessary OTPs are also cleared.");
};
return res.json({
success: true,
message: "Database cleanup completed and expired OTPs cleared",
});
Comment thread
Shweta-281 marked this conversation as resolved.
};
18 changes: 16 additions & 2 deletions functions/database-cleaner/src/utils.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
export const throwIfMissing = (obj, keys) => {
const missing = [];

for (let key of keys) {
if (!(key in obj) || (!obj[key] && obj[key] != 0)) {
if (!(key in obj) || obj[key] === undefined || obj[key] === null) {
missing.push(key);
}
}

if (missing.length > 0) {
throw new Error(`Missing required fields: ${missing.join(", ")}`);
}
};

export const parseBody = (body) => {
if (!body) {
throw new Error("Request body is empty");
}

try {
return JSON.parse(body);
} catch (err) {
throw new Error("Invalid JSON body");
}
};

export const getExpiryDate = () => {
const retentionPeriod = +(process.env.RETENTION_PERIOD_DAYS ?? 1);
const expiryDate = new Date();
expiryDate.setDate(expiryDate.getDate() - retentionPeriod);
return expiryDate.toISOString();
};
};
Loading