306 lines
7.9 KiB
JavaScript
306 lines
7.9 KiB
JavaScript
const { Client } = require("pg");
|
|
const crypto = require("crypto");
|
|
require("dotenv").config();
|
|
const client = new Client({
|
|
user: process.env.PG_USER,
|
|
password: process.env.PG_PASSWORD,
|
|
database: process.env.PG_DATABASE,
|
|
host: process.env.PG_HOST,
|
|
port: 5433,
|
|
});
|
|
|
|
client
|
|
.connect()
|
|
.then(() => {
|
|
createTables()
|
|
.then(() => console.log("Tables created successfully"))
|
|
.catch((e) => console.error("Failed to create tables ", e));
|
|
console.log(
|
|
`Successfully connected to database: ${process.env.PG_DATABASE}`,
|
|
);
|
|
})
|
|
.catch((err) =>
|
|
console.error(
|
|
`Failed to connect to database: ${process.env.PG_DATABASE}, ${err}`,
|
|
),
|
|
);
|
|
|
|
// Creating database tables
|
|
async function createTables() {
|
|
try {
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS accounts (
|
|
username VARCHAR(20) NOT NULL UNIQUE,
|
|
password VARCHAR(128) NOT NULL,
|
|
user_id VARCHAR(128) PRIMARY KEY,
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
`);
|
|
} catch (e) {
|
|
console.error("Failed to create accounts table ", e);
|
|
}
|
|
|
|
try {
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS messages (
|
|
sender VARCHAR(128) NOT NULL,
|
|
recipient VARCHAR(128) NOT NULL,
|
|
message VARCHAR(10000) NOT NULL,
|
|
timestamp TIMESTAMPTZ DEFAULT NOW(),
|
|
message_id SERIAL PRIMARY KEY,
|
|
attachment VARCHAR(1000),
|
|
UNIQUE (sender, recipient, message_id)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_messages_conversation
|
|
ON messages (sender, recipient, message_id ASC);
|
|
`);
|
|
} catch (e) {
|
|
console.error("Failed to create messages table ", e);
|
|
}
|
|
try {
|
|
await client.query(`
|
|
CREATE TABLE IF NOT EXISTS contacts (
|
|
username VARCHAR(20) NOT NULL,
|
|
usernameContact VARCHAR(20) NOT NULL,
|
|
read BOOLEAN NOT NULL,
|
|
lastActive VARCHAR(100) NOT NULL,
|
|
CONSTRAINT unique_username_contact UNIQUE (username, usernameContact)
|
|
);
|
|
`);
|
|
} catch (e) {
|
|
console.error("Failed to create messages table ", e);
|
|
}
|
|
}
|
|
|
|
async function insertUser(username, password) {
|
|
const user_id = crypto.randomUUID();
|
|
|
|
const query = `
|
|
INSERT INTO accounts (username, password, user_id)
|
|
VALUES ($1, $2, $3);
|
|
`;
|
|
try {
|
|
await client.query(query, [username, password, user_id]);
|
|
} catch (e) {
|
|
console.error("Failed to insert user ", e);
|
|
}
|
|
}
|
|
|
|
async function getUserId(username) {
|
|
const query = `
|
|
SELECT user_id FROM accounts
|
|
WHERE username = $1;
|
|
`;
|
|
try {
|
|
const result = await client.query(query, [username]);
|
|
console.log("GETUSERID: ", result.rows[0].user_id);
|
|
return result.rows[0].user_id;
|
|
} catch (e) {
|
|
console.error("Failed to get user id", e);
|
|
}
|
|
}
|
|
async function insertMessage(sender, recipient, message) {
|
|
const query = `
|
|
INSERT INTO messages (sender, recipient, message)
|
|
VALUES ($1, $2, $3)
|
|
RETURNING message, timestamp, message_id;
|
|
`;
|
|
try {
|
|
const results = await client.query(query, [sender, recipient, message]);
|
|
return results.rows[0];
|
|
} catch (e) {
|
|
console.error("Failed to insert message ", e);
|
|
}
|
|
}
|
|
|
|
async function getMessages(username, recipient, limit = 50, cursor = 0) {
|
|
console.log(
|
|
`getMessages for Username: ${username}, recipient: ${recipient}, limit: ${limit}, cursor: ${cursor}`,
|
|
);
|
|
let query;
|
|
let params;
|
|
|
|
if (cursor) {
|
|
query = `
|
|
SELECT * FROM messages
|
|
WHERE ((sender = $1 AND recipient = $2) OR (sender = $2 AND recipient = $1))
|
|
AND message_id < $3
|
|
ORDER BY message_id DESC
|
|
LIMIT $4;
|
|
`;
|
|
params = [username, recipient, cursor, limit];
|
|
} else {
|
|
query = `
|
|
SELECT * FROM messages
|
|
WHERE (sender = $1 AND recipient = $2) OR (sender = $2 AND recipient = $1)
|
|
ORDER BY message_id DESC
|
|
LIMIT $3;
|
|
`;
|
|
params = [username, recipient, limit];
|
|
}
|
|
|
|
try {
|
|
const results = await client.query(query, params);
|
|
let messages = results.rows;
|
|
if (!cursor) {
|
|
messages = messages.reverse();
|
|
}
|
|
|
|
return messages;
|
|
} catch (e) {
|
|
console.error("Failed to get messages ", e);
|
|
}
|
|
}
|
|
|
|
async function checkUserExist(username) {
|
|
const query = `
|
|
SELECT 1 FROM accounts
|
|
WHERE LOWER(username) = LOWER($1)
|
|
LIMIT 1;
|
|
`;
|
|
|
|
try {
|
|
const result = await client.query(query, [username]);
|
|
return result.rows.length > 0;
|
|
} catch (e) {
|
|
console.error("Failed to check if user exist ", e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async function getPassword(username) {
|
|
console.log(`Get password for: ${username}`);
|
|
const query = `
|
|
SELECT password FROM accounts
|
|
WHERE LOWER(username) = LOWER($1);
|
|
`;
|
|
try {
|
|
const result = await client.query(query, [username]);
|
|
return result.rows[0].password;
|
|
} catch (e) {
|
|
console.error("Failed to get user password ", e);
|
|
}
|
|
}
|
|
|
|
async function changePassword(username, newPassword) {
|
|
const query = `
|
|
UPDATE accounts
|
|
SET password = $1
|
|
WHERE username = $2;
|
|
`;
|
|
try {
|
|
await client.query(query, [newPassword, username]);
|
|
} catch (e) {
|
|
console.error("Failed to change password ", e);
|
|
}
|
|
}
|
|
|
|
async function insertContact(username, usernameContact, read) {
|
|
const timestamp = getTime();
|
|
console.log(
|
|
`insertContact username: ${username}, usernameContact: ${usernameContact}, read: ${read}`,
|
|
);
|
|
|
|
const query = `
|
|
INSERT INTO contacts (username, usernameContact, lastActive, read)
|
|
VALUES ($1, $2, $3, $4)
|
|
ON CONFLICT ON CONSTRAINT unique_username_contact
|
|
DO NOTHING;
|
|
`;
|
|
try {
|
|
await client.query(query, [username, usernameContact, timestamp, read]);
|
|
} catch (e) {
|
|
console.error("Failed to insert contact ", e);
|
|
}
|
|
}
|
|
|
|
async function getContacts(username) {
|
|
const query = `
|
|
SELECT usernameContact, read FROM contacts
|
|
WHERE username = $1
|
|
ORDER BY lastActive ASC;
|
|
`;
|
|
try {
|
|
const result = await client.query(query, [username]);
|
|
return result.rows;
|
|
} catch (e) {
|
|
console.error("Failed to get contacts ", e);
|
|
}
|
|
}
|
|
|
|
async function deleteContact(username, usernamecontact) {
|
|
const query = `
|
|
DELETE FROM contacts
|
|
WHERE (LOWER(username) = LOWER($1) AND LOWER(usernamecontact) = LOWER($2))
|
|
RETURNING *;
|
|
`;
|
|
try {
|
|
const result = await client.query(query, [username, usernamecontact]);
|
|
if (result.rowCount === 0) {
|
|
console.log("No matching contact found with:", {
|
|
username,
|
|
usernamecontact,
|
|
});
|
|
} else {
|
|
console.log("Successfully deleted contact");
|
|
}
|
|
} catch (e) {
|
|
console.error("Failed to remove contact ", e);
|
|
}
|
|
}
|
|
|
|
async function updateContactStatus(username, usernamecontact, read) {
|
|
const query = `
|
|
UPDATE contacts SET read = $1
|
|
WHERE username = $2 AND usernamecontact = $3
|
|
`;
|
|
try {
|
|
await client.query(query, [read, username, usernamecontact]);
|
|
await updateContactLastActive(username, usernamecontact);
|
|
console.log("Successfully updated contact status");
|
|
} catch (e) {
|
|
console.error("Failed to update contact status ", e);
|
|
}
|
|
}
|
|
|
|
async function updateContactLastActive(username, usernamecontact) {
|
|
const timestamp = getTime();
|
|
const query = `
|
|
UPDATE contacts SET lastActive = $1
|
|
WHERE username = $2 AND usernamecontact = $3
|
|
`;
|
|
try {
|
|
await client.query(query, [timestamp, username, usernamecontact]);
|
|
console.log("Successfully updated contact last active time");
|
|
} catch (e) {
|
|
console.error("Failed to update contact last active time");
|
|
}
|
|
}
|
|
|
|
function getTime() {
|
|
const now = new Date();
|
|
const year = now.getFullYear();
|
|
const month = ("0" + (now.getMonth() + 1)).slice(-2);
|
|
const day = ("0" + now.getDate()).slice(-2);
|
|
|
|
const hour = ("0" + now.getHours()).slice(-2);
|
|
const minute = ("0" + now.getMinutes()).slice(-2);
|
|
const second = ("0" + now.getSeconds()).slice(-2);
|
|
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
|
|
}
|
|
module.exports = {
|
|
client,
|
|
insertUser,
|
|
insertMessage,
|
|
checkUserExist,
|
|
changePassword,
|
|
getPassword,
|
|
insertContact,
|
|
deleteContact,
|
|
getMessages,
|
|
getUserId,
|
|
getContacts,
|
|
updateContactStatus,
|
|
updateContactLastActive,
|
|
};
|