Skip to content
Merged
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
206 changes: 60 additions & 146 deletions backend/controllers/chat.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,49 @@ import { validateMessagePayload } from "../utils/messageValidation.js";

function buildConversationMetadata() {
return {
conversationTimestamp:
new Date().toISOString(),
conversationTimestamp: new Date().toISOString(),
};
}

function normalizeMessagePayload(
payload
) {
function normalizeMessagePayload(payload) {
return {
...payload,
...buildConversationMetadata(),
};
}

function isStaleConversationUpdate(
timestamp
) {
if (!timestamp) {
return false;
}
function isStaleConversationUpdate(timestamp) {
if (!timestamp) return false;

const ageMinutes =
(Date.now() -
new Date(
timestamp
).getTime()) /
60000;
(Date.now() - new Date(timestamp).getTime()) / 60000;

return ageMinutes > 60;
}

function buildSessionContinuity(
messages = []
) {
function buildSessionContinuity(messages = []) {
return {
continuityProtected: true,
messageCount:
messages.length,
lastUpdated:
new Date().toISOString(),
messageCount: messages.length,
lastUpdated: new Date().toISOString(),
};
}

function buildContextSynchronizationMetadata(
messages = []
) {
function buildContextSynchronizationMetadata(messages = []) {
return {
synchronizationEnabled: true,
contextVersion:
messages.length,
reconciliationTimestamp:
Date.now(),
contextVersion: messages.length,
reconciliationTimestamp: Date.now(),
lifecycleValidated: true,
};
}

function reconcileConversationContext(
payload
) {
function reconcileConversationContext(payload) {
return {
...payload,
reconciliationId:
`${Date.now()}-${Math.random()
.toString(36)
.slice(2, 8)}`,
reconciliationId: `${Date.now()}-${Math.random()
.toString(36)
.slice(2, 8)}`,
synchronized: true,
};
}
Expand All @@ -76,43 +54,30 @@ export const getMessages = async (req, res) => {
const { data, error } = await supabase
.from("messages")
.select("*")
.order("created_at", {
ascending: true,
});
.order("created_at", { ascending: true });

if (error) {
console.error(
"Supabase error in getMessages:",
error
);
console.error("Supabase error in getMessages:", error);

return res.status(500).json({
error:
"Failed to retrieve messages.",
error: "Failed to retrieve messages.",
});
}

const continuity =
buildSessionContinuity(
data || []
);
const safeData = data || [];

const continuity = buildSessionContinuity(safeData);
const synchronizationMetadata =
buildContextSynchronizationMetadata(
data || []
);
buildContextSynchronizationMetadata(safeData);

res.json({
messages: data,
messages: safeData,
continuity,
synchronizationMetadata,
});
};

export const sendMessage = async (
req,
res
) => {
export const sendMessage = async (req, res) => {
try {
const {
text,
Expand All @@ -122,69 +87,42 @@ export const sendMessage = async (
conversationTimestamp,
} = req.body;

console.log("Incoming:", {
text,
username,
image,
audio,
});

if (
isStaleConversationUpdate(
conversationTimestamp
)
) {
if (isStaleConversationUpdate(conversationTimestamp)) {
return res.status(409).json({
error:
"Conversation context expired",
error: "Conversation context expired",
});
}

const authHeader =
req.headers.authorization;
const authHeader = req.headers.authorization;

if (
!authHeader?.startsWith(
"Bearer "
)
) {
if (!authHeader?.startsWith("Bearer ")) {
return res.status(401).json({
error:
"Authentication required",
error: "Authentication required",
});
}

const token =
authHeader.split(" ")[1];
const token = authHeader.split(" ")[1];

const {
data: { user },
error: authError,
} = await supabase.auth.getUser(
token
);
} = await supabase.auth.getUser(token);

if (
authError ||
!user
) {
if (authError || !user) {
return res.status(403).json({
error:
"Unauthorized user",
error: "Unauthorized user",
});
}

const validationError =
validateMessagePayload({
text,
image,
audio,
});
const validationError = validateMessagePayload({
text,
image,
audio,
});

if (validationError) {
return res.status(400).json({
error:
validationError,
error: validationError,
});
}

Expand All @@ -199,67 +137,43 @@ export const sendMessage = async (
})
);

const { data, error } =
await supabase
.from("messages")
.insert([
{
text:
normalizedPayload.text,
username:
normalizedPayload.username,
image:
normalizedPayload.image,
audio:
normalizedPayload.audio,
status:
normalizedPayload.status,
},
])
.select();
const { data, error } = await supabase
.from("messages")
.insert([
{
text: normalizedPayload.text,
username: normalizedPayload.username,
image: normalizedPayload.image,
audio: normalizedPayload.audio,
status: normalizedPayload.status,
},
])
.select();

if (error) {
console.error(
"Supabase error in sendMessage:",
error
);
console.error("Supabase error in sendMessage:", error);

return res.status(500).json({
error:
"Failed to send message.",
error: "Failed to send message.",
});
}

const io =
req.app.get("io");
const io = req.app.get("io");
io?.emit("newMessage", data?.[0]);

io.emit(
"newMessage",
data[0]
);

const synchronizationMetadata =
buildContextSynchronizationMetadata(
data || []
);
const syncMeta =
buildContextSynchronizationMetadata(data || []);

res.json({
messages: data,
continuity:
buildSessionContinuity(
data || []
),
synchronizationMetadata,
continuity: buildSessionContinuity(data || []),
synchronizationMetadata: syncMeta,
});
} catch (err) {
console.error(
"Server crash:",
err
);
console.error("Server crash:", err);

res.status(500).json({
error:
"Server error",
error: "Server error",
});
}
};
Loading