make chats allow file uploading
This commit is contained in:
+137
-5
@@ -15,12 +15,32 @@ export default {
|
||||
`CREATE INDEX IF NOT EXISTS msg_by_client ON messages(client_id, timestamp)`
|
||||
);
|
||||
} catch (_) {}
|
||||
|
||||
const cols = ctx.db
|
||||
.prepare(`PRAGMA table_info(messages)`)
|
||||
.all()
|
||||
.map((r) => r.name);
|
||||
if (!cols.includes("attachment_name")) {
|
||||
try {
|
||||
ctx.db.exec(`ALTER TABLE messages ADD COLUMN attachment_name TEXT`);
|
||||
} catch (_) {}
|
||||
}
|
||||
if (!cols.includes("attachment_mime")) {
|
||||
try {
|
||||
ctx.db.exec(`ALTER TABLE messages ADD COLUMN attachment_mime TEXT`);
|
||||
} catch (_) {}
|
||||
}
|
||||
if (!cols.includes("attachment_data")) {
|
||||
try {
|
||||
ctx.db.exec(`ALTER TABLE messages ADD COLUMN attachment_data BLOB`);
|
||||
} catch (_) {}
|
||||
}
|
||||
},
|
||||
|
||||
onEvent(ctx, clientId, event, payload) {
|
||||
if (event === "chat_message") {
|
||||
const ts = Date.now();
|
||||
ctx.db
|
||||
const info = ctx.db
|
||||
.prepare(
|
||||
`INSERT INTO messages(client_id, sender, direction, text, timestamp) VALUES (?, ?, ?, ?, ?)`
|
||||
)
|
||||
@@ -32,6 +52,7 @@ export default {
|
||||
ts
|
||||
);
|
||||
ctx.broadcast("new_message", {
|
||||
id: Number(info.lastInsertRowid),
|
||||
clientId,
|
||||
sender: payload.from || "Unknown",
|
||||
direction: "from_target",
|
||||
@@ -39,6 +60,41 @@ export default {
|
||||
timestamp: ts,
|
||||
});
|
||||
}
|
||||
if (event === "chat_attachment") {
|
||||
const ts = Date.now();
|
||||
const name = payload.name || "file";
|
||||
const mime = payload.mime || "application/octet-stream";
|
||||
let buf = null;
|
||||
try {
|
||||
buf = Buffer.from(payload.dataB64 || "", "base64");
|
||||
} catch (_) {
|
||||
buf = null;
|
||||
}
|
||||
if (!buf || buf.length === 0) return;
|
||||
const info = ctx.db
|
||||
.prepare(
|
||||
`INSERT INTO messages(client_id, sender, direction, text, timestamp, attachment_name, attachment_mime, attachment_data) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
)
|
||||
.run(
|
||||
clientId,
|
||||
payload.from || "Unknown",
|
||||
"from_target",
|
||||
"",
|
||||
ts,
|
||||
name,
|
||||
mime,
|
||||
buf
|
||||
);
|
||||
ctx.broadcast("new_message", {
|
||||
id: Number(info.lastInsertRowid),
|
||||
clientId,
|
||||
sender: payload.from || "Unknown",
|
||||
direction: "from_target",
|
||||
text: "",
|
||||
timestamp: ts,
|
||||
attachment: { name, mime, size: buf.length },
|
||||
});
|
||||
}
|
||||
if (event === "chat_opened") {
|
||||
ctx.broadcast("chat_status", { clientId, status: "opened" });
|
||||
}
|
||||
@@ -51,26 +107,102 @@ export default {
|
||||
get_history(ctx, params) {
|
||||
return ctx.db
|
||||
.prepare(
|
||||
`SELECT * FROM messages WHERE client_id = ? ORDER BY timestamp ASC LIMIT 500`
|
||||
`SELECT id, client_id, sender, direction, text, timestamp,
|
||||
attachment_name, attachment_mime,
|
||||
CASE WHEN attachment_data IS NULL THEN 0 ELSE length(attachment_data) END AS attachment_size
|
||||
FROM messages WHERE client_id = ? ORDER BY timestamp ASC LIMIT 500`
|
||||
)
|
||||
.all(params.clientId);
|
||||
.all(params.clientId)
|
||||
.map((r) => ({
|
||||
id: r.id,
|
||||
clientId: r.client_id,
|
||||
sender: r.sender,
|
||||
direction: r.direction,
|
||||
text: r.text,
|
||||
timestamp: r.timestamp,
|
||||
attachment: r.attachment_name
|
||||
? {
|
||||
name: r.attachment_name,
|
||||
mime: r.attachment_mime,
|
||||
size: r.attachment_size,
|
||||
}
|
||||
: null,
|
||||
}));
|
||||
},
|
||||
|
||||
get_attachment(ctx, params) {
|
||||
const row = ctx.db
|
||||
.prepare(
|
||||
`SELECT attachment_name, attachment_mime, attachment_data FROM messages WHERE id = ?`
|
||||
)
|
||||
.get(params.id);
|
||||
if (!row || !row.attachment_data) {
|
||||
return { ok: false, error: "not found" };
|
||||
}
|
||||
const buf = Buffer.isBuffer(row.attachment_data)
|
||||
? row.attachment_data
|
||||
: Buffer.from(row.attachment_data);
|
||||
return {
|
||||
ok: true,
|
||||
name: row.attachment_name,
|
||||
mime: row.attachment_mime,
|
||||
dataB64: buf.toString("base64"),
|
||||
};
|
||||
},
|
||||
|
||||
store_message(ctx, params) {
|
||||
const ts = Date.now();
|
||||
ctx.db
|
||||
const info = ctx.db
|
||||
.prepare(
|
||||
`INSERT INTO messages(client_id, sender, direction, text, timestamp) VALUES (?, ?, ?, ?, ?)`
|
||||
)
|
||||
.run(params.clientId, params.sender, "to_target", params.text, ts);
|
||||
ctx.broadcast("new_message", {
|
||||
id: Number(info.lastInsertRowid),
|
||||
clientId: params.clientId,
|
||||
sender: params.sender,
|
||||
direction: "to_target",
|
||||
text: params.text,
|
||||
timestamp: ts,
|
||||
});
|
||||
return { ok: true, timestamp: ts };
|
||||
return { ok: true, id: Number(info.lastInsertRowid), timestamp: ts };
|
||||
},
|
||||
|
||||
store_attachment(ctx, params) {
|
||||
const ts = Date.now();
|
||||
const name = params.name || "file";
|
||||
const mime = params.mime || "application/octet-stream";
|
||||
let buf = null;
|
||||
try {
|
||||
buf = Buffer.from(params.dataB64 || "", "base64");
|
||||
} catch (_) {}
|
||||
if (!buf || buf.length === 0) {
|
||||
return { ok: false, error: "empty data" };
|
||||
}
|
||||
const info = ctx.db
|
||||
.prepare(
|
||||
`INSERT INTO messages(client_id, sender, direction, text, timestamp, attachment_name, attachment_mime, attachment_data) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
)
|
||||
.run(
|
||||
params.clientId,
|
||||
params.sender,
|
||||
"to_target",
|
||||
"",
|
||||
ts,
|
||||
name,
|
||||
mime,
|
||||
buf
|
||||
);
|
||||
ctx.broadcast("new_message", {
|
||||
id: Number(info.lastInsertRowid),
|
||||
clientId: params.clientId,
|
||||
sender: params.sender,
|
||||
direction: "to_target",
|
||||
text: "",
|
||||
timestamp: ts,
|
||||
attachment: { name, mime, size: buf.length },
|
||||
});
|
||||
return { ok: true, id: Number(info.lastInsertRowid), timestamp: ts };
|
||||
},
|
||||
|
||||
clear_history(ctx, params) {
|
||||
|
||||
Reference in New Issue
Block a user