implemented messages
This commit is contained in:
parent
a691dec2e8
commit
10994b6612
|
@ -5,7 +5,12 @@
|
||||||
"menu": "Pick an action:\n1) Start watching profiles\n2) Check for mutual likes\n3) Check for messages",
|
"menu": "Pick an action:\n1) Start watching profiles\n2) Check for mutual likes\n3) Check for messages",
|
||||||
"newlikes": "You have new mutual like(s)! Go into menu (🏠️) to see!",
|
"newlikes": "You have new mutual like(s)! Go into menu (🏠️) to see!",
|
||||||
"showalike": "This person and you mutually liked each other!",
|
"showalike": "This person and you mutually liked each other!",
|
||||||
"mxid": "Go drop them a line! Their MXID is: "
|
"mxid": "Go drop them a line! Their MXID is: ",
|
||||||
|
"message": "Write one message to this person or upload one picture/video to send them!",
|
||||||
|
"newmessage": "You've got new message(s)! Go to a menu (🏠️) to see!",
|
||||||
|
"showmessage": " sent you this: ",
|
||||||
|
"nonewmessages": "You have no new messages!",
|
||||||
|
"messagesent": "You message was sent!"
|
||||||
},
|
},
|
||||||
"setup": {
|
"setup": {
|
||||||
"country": "Write a name of country you are living in. Prefer local language. For example, 'Россия', 'United States' or 'Україна'.",
|
"country": "Write a name of country you are living in. Prefer local language. For example, 'Россия', 'United States' or 'Україна'.",
|
||||||
|
@ -28,6 +33,8 @@
|
||||||
"twosexes": "There are only two sexes! Please, choose your biological one.",
|
"twosexes": "There are only two sexes! Please, choose your biological one.",
|
||||||
"didntunderstand": "I cannot understand your answer. Please, read my question again and answer!",
|
"didntunderstand": "I cannot understand your answer. Please, read my question again and answer!",
|
||||||
"notimplemented": "This feature is not yet implemented! Please, keep track of my updates at https://git.foxarmy.org/leca/heart2heart. Bother your admins to update, if released! ;)",
|
"notimplemented": "This feature is not yet implemented! Please, keep track of my updates at https://git.foxarmy.org/leca/heart2heart. Bother your admins to update, if released! ;)",
|
||||||
"noprofiles": "There are no profiles left for you! I'm sorry. Please, come back later!"
|
"noprofiles": "There are no profiles left for you! I'm sorry. Please, come back later!",
|
||||||
|
"alreadymessaged": "You have already messaged that person. Your message was not sent!"
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -31,5 +31,8 @@ CREATE TABLE IF NOT EXISTS messages (
|
||||||
sender VARCHAR(64), -- link to room_id
|
sender VARCHAR(64), -- link to room_id
|
||||||
recipient VARCHAR(64), -- link to room_id
|
recipient VARCHAR(64), -- link to room_id
|
||||||
type CHAR, -- 't' for text, 'p' for picture and 'v' for video
|
type CHAR, -- 't' for text, 'p' for picture and 'v' for video
|
||||||
content VARCHAR(128) -- will contain a url if media and text if the message is just a text
|
content VARCHAR(128), -- will contain a url if media and text if the message is just a text
|
||||||
);
|
read BOOLEAN DEFAULT FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS unique_messages ON messages(sender, recipient);
|
||||||
|
|
47
src/db.js
47
src/db.js
|
@ -1,5 +1,6 @@
|
||||||
import pg from 'pg';
|
import pg from 'pg';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import { convertMsgType } from './utils.js';
|
||||||
|
|
||||||
const { Client } = pg;
|
const { Client } = pg;
|
||||||
|
|
||||||
|
@ -56,24 +57,24 @@ const selectProfilesForUser = async (roomId) => {
|
||||||
//Selecting profiles other than user's and with difference in age +-2.
|
//Selecting profiles other than user's and with difference in age +-2.
|
||||||
let user;
|
let user;
|
||||||
if (myInterest === 'b') // both, no matter what sex
|
if (myInterest === 'b') // both, no matter what sex
|
||||||
user = (await db.query(`SELECT
|
user = (await db.query(`SELECT
|
||||||
room_id, name, age, sex, description, country, city FROM users
|
room_id, name, age, sex, description, country, city FROM users
|
||||||
WHERE
|
WHERE
|
||||||
age::numeric <@ ANY(ARRAY[numrange($1 - 2, $1 + 2)])
|
age::numeric <@ ANY(ARRAY[numrange($1 - 2, $1 + 2)])
|
||||||
AND room_id != $2
|
AND room_id != $2
|
||||||
AND (interest = $3 OR interest = 'b')
|
AND (interest = $3 OR interest = 'b')
|
||||||
ORDER BY RANDOM()
|
ORDER BY RANDOM()
|
||||||
LIMIT 1`, [userAge, roomId, mySex])
|
LIMIT 1`, [userAge, roomId, mySex])
|
||||||
).rows[0];
|
).rows[0];
|
||||||
else {
|
else {
|
||||||
user = (await db.query(`SELECT
|
user = (await db.query(`SELECT
|
||||||
room_id, name, age, sex, description, country, city FROM users
|
room_id, name, age, sex, description, country, city FROM users
|
||||||
WHERE
|
WHERE
|
||||||
age::numeric <@ ANY(ARRAY[numrange($1 - 2, $1 + 2)])
|
age::numeric <@ ANY(ARRAY[numrange($1 - 2, $1 + 2)])
|
||||||
AND room_id != $2
|
AND room_id != $2
|
||||||
AND sex = $3
|
AND sex = $3
|
||||||
AND (interest = $4 OR interest = 'b')
|
AND (interest = $4 OR interest = 'b')
|
||||||
ORDER BY RANDOM()
|
ORDER BY RANDOM()
|
||||||
LIMIT 1`, [userAge, roomId, myInterest, mySex])
|
LIMIT 1`, [userAge, roomId, myInterest, mySex])
|
||||||
).rows[0];
|
).rows[0];
|
||||||
}
|
}
|
||||||
|
@ -137,6 +138,24 @@ const getAllLikesForUser = async (roomId) => {
|
||||||
const markLikeAsRead = async (roomId, recipient,) => {
|
const markLikeAsRead = async (roomId, recipient,) => {
|
||||||
await db.query("UPDATE likes SET read = TRUE WHERE sender = $1 AND recipient = $2", [roomId, recipient]);
|
await db.query("UPDATE likes SET read = TRUE WHERE sender = $1 AND recipient = $2", [roomId, recipient]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const uploadMediaAsMessage = async (roomId, type, mxc) => {
|
||||||
|
await db.query("INSERT INTO media(owner, type, purpose, url) VALUES ($1, $2, 'm', $3)", [roomId, convertMsgType(type), mxc]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const insertMessageIntoDB = async (roomId, recipient, type, content) => {
|
||||||
|
let rowAmount = (await db.query("INSERT INTO messages (sender, recipient, type, content) VALUES ($1, $2, $3, $4) ON CONFLICT(sender, recipient) DO NOTHING RETURNING *", [roomId, recipient, convertMsgType(type), content])).rowCount;
|
||||||
|
return rowAmount == 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getUnreadMessages = async (roomId) => {
|
||||||
|
return (await db.query("SELECT (SELECT mx_id FROM users WHERE room_id = sender LIMIT 1), sender, type, content FROM messages WHERE recipient = $1 AND read = FALSE", [roomId])).rows
|
||||||
|
};
|
||||||
|
|
||||||
|
const markMessageAsRead = async (roomId, recipient) => {
|
||||||
|
return (await db.query("UPDATE messages SET read = TRUE WHERE sender = $1 AND recipient = $2", [roomId, recipient]));
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
eraseUser,
|
eraseUser,
|
||||||
appendUserPictures,
|
appendUserPictures,
|
||||||
|
@ -153,5 +172,9 @@ export {
|
||||||
getAllLikesForUser,
|
getAllLikesForUser,
|
||||||
markLikeAsRead,
|
markLikeAsRead,
|
||||||
eraseUserLikes,
|
eraseUserLikes,
|
||||||
eraseUserMedia
|
eraseUserMedia,
|
||||||
|
uploadMediaAsMessage,
|
||||||
|
insertMessageIntoDB,
|
||||||
|
getUnreadMessages,
|
||||||
|
markMessageAsRead
|
||||||
};
|
};
|
81
src/index.js
81
src/index.js
|
@ -9,10 +9,12 @@ import {
|
||||||
import { StoreType } from "@matrix-org/matrix-sdk-crypto-nodejs";
|
import { StoreType } from "@matrix-org/matrix-sdk-crypto-nodejs";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
convertMsgType,
|
||||||
logError,
|
logError,
|
||||||
logInfo,
|
logInfo,
|
||||||
readConfig,
|
readConfig,
|
||||||
readMessages
|
readMessages,
|
||||||
|
uploadMediaFromEvent
|
||||||
} from './utils.js';
|
} from './utils.js';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -24,8 +26,12 @@ import {
|
||||||
eraseUserMedia,
|
eraseUserMedia,
|
||||||
getAmountOfUserPictures,
|
getAmountOfUserPictures,
|
||||||
getCurrentUserAction,
|
getCurrentUserAction,
|
||||||
|
getUnreadMessages,
|
||||||
getUserCurrentlyViewingProfile,
|
getUserCurrentlyViewingProfile,
|
||||||
setUserState
|
insertMessageIntoDB,
|
||||||
|
markMessageAsRead,
|
||||||
|
setUserState,
|
||||||
|
uploadMediaAsMessage
|
||||||
} from './db.js';
|
} from './db.js';
|
||||||
|
|
||||||
import { processRequest, showRandomProfileToUser, showNewLikes } from "./interactions.js";
|
import { processRequest, showRandomProfileToUser, showNewLikes } from "./interactions.js";
|
||||||
|
@ -52,13 +58,13 @@ client.on("room.message", async (roomId, event) => {
|
||||||
|
|
||||||
let current_action = await getCurrentUserAction(roomId);
|
let current_action = await getCurrentUserAction(roomId);
|
||||||
let answer = event.content.body;
|
let answer = event.content.body;
|
||||||
|
let msgtype = event.content.msgtype
|
||||||
|
|
||||||
switch (current_action) {
|
switch (current_action) {
|
||||||
case "wait_start":
|
case "wait_start":
|
||||||
if (answer !== "!start") return;
|
if (answer !== "!start") return;
|
||||||
await setUserState(roomId, "country");
|
await setUserState(roomId, "country");
|
||||||
await client.sendText(roomId, messages.setup.country);
|
await client.sendText(roomId, messages.setup.country);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "country":
|
case "country":
|
||||||
await processRequest(client, roomId, current_action, answer, 'city');
|
await processRequest(client, roomId, current_action, answer, 'city');
|
||||||
|
@ -115,16 +121,8 @@ client.on("room.message", async (roomId, event) => {
|
||||||
await setUserState(roomId, 'view_profiles');
|
await setUserState(roomId, 'view_profiles');
|
||||||
await showRandomProfileToUser(client, roomId);
|
await showRandomProfileToUser(client, roomId);
|
||||||
} else {
|
} else {
|
||||||
const message = new MessageEvent(event);
|
let mxc = await uploadMediaFromEvent(client, event);
|
||||||
const fileEvent = new MessageEvent(message.raw);
|
let type = convertMsgType(msgtype);
|
||||||
const decrypted = await client.crypto.decryptMedia(fileEvent.content.file);
|
|
||||||
const mxc = await client.uploadContent(decrypted);
|
|
||||||
let type;
|
|
||||||
if (event.content.msgtype === "m.image") {
|
|
||||||
type = 'p';
|
|
||||||
} else if (event.content.msgtype === "m.video") {
|
|
||||||
type = 'v';
|
|
||||||
}
|
|
||||||
await appendUserPictures(roomId, mxc, type);
|
await appendUserPictures(roomId, mxc, type);
|
||||||
let pictures_count = await getAmountOfUserPictures(roomId);
|
let pictures_count = await getAmountOfUserPictures(roomId);
|
||||||
if (pictures_count < maxAmountOfPhotoesPerUser) {
|
if (pictures_count < maxAmountOfPhotoesPerUser) {
|
||||||
|
@ -148,17 +146,35 @@ client.on("room.message", async (roomId, event) => {
|
||||||
await client.sendText(currently_viewing, messages.general.newlikes);
|
await client.sendText(currently_viewing, messages.general.newlikes);
|
||||||
}
|
}
|
||||||
} else if (answer == '💌' || answer == '3') {
|
} else if (answer == '💌' || answer == '3') {
|
||||||
await client.sendText(roomId, messages.errors.notimplemented);
|
await setUserState(roomId, 'send_message');
|
||||||
|
await client.sendText(roomId, messages.general.message);
|
||||||
|
return;
|
||||||
} else if (answer == '🏠️' || answer == '4') {
|
} else if (answer == '🏠️' || answer == '4') {
|
||||||
await client.sendText(roomId, messages.general.menu);
|
await client.sendText(roomId, messages.general.menu);
|
||||||
await setUserState(roomId, 'menu')
|
await setUserState(roomId, 'menu');
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await showRandomProfileToUser(client, roomId);
|
await showRandomProfileToUser(client, roomId);
|
||||||
break;
|
break;
|
||||||
case 'send_message':
|
case 'send_message':
|
||||||
|
let recipient = await getUserCurrentlyViewingProfile(roomId);
|
||||||
|
let content;
|
||||||
|
if (msgtype == "m.image" || msgtype == "m.video") {
|
||||||
|
let mxc = await uploadMediaFromEvent(client, event);
|
||||||
|
await uploadMediaAsMessage(roomId, msgtype, mxc);
|
||||||
|
content = mxc;
|
||||||
|
} else {
|
||||||
|
content = answer;
|
||||||
|
}
|
||||||
|
if (await insertMessageIntoDB(roomId, recipient, msgtype, content)) {
|
||||||
|
await client.sendText(recipient, messages.general.newmessage);
|
||||||
|
await client.sendText(roomId, messages.general.messagesent);
|
||||||
|
} else {
|
||||||
|
await client.sendText(roomId, messages.errors.alreadymessaged);
|
||||||
|
}
|
||||||
|
await setUserState(roomId, 'view_profiles');
|
||||||
|
await showRandomProfileToUser(client, roomId);
|
||||||
break;
|
break;
|
||||||
case 'menu':
|
case 'menu':
|
||||||
switch (answer) {
|
switch (answer) {
|
||||||
|
@ -171,11 +187,38 @@ client.on("room.message", async (roomId, event) => {
|
||||||
await client.sendText(roomId, messages.general.menu);
|
await client.sendText(roomId, messages.general.menu);
|
||||||
break;
|
break;
|
||||||
case '3':
|
case '3':
|
||||||
await setUserState(roomId, 'send_message');
|
let unreadMessages = await getUnreadMessages(roomId);
|
||||||
await client.sendText(roomId, messages.errors.notimplemented);
|
if (!unreadMessages || unreadMessages.length == 0) {
|
||||||
|
await client.sendText(roomId, messages.general.nonewmessages);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await client.sendText(roomId, "Messages:");
|
||||||
|
for (let message of unreadMessages) {
|
||||||
|
await client.sendText(roomId, message.mx_id + messages.general.showmessage);
|
||||||
|
if (message.type == "t") {
|
||||||
|
await client.sendText(roomId, message.content)
|
||||||
|
} else if (message.type == "p" || message.type == "v") {
|
||||||
|
let msgtype;
|
||||||
|
|
||||||
|
if (message.type == "p") {
|
||||||
|
msgtype = "m.image"
|
||||||
|
} else if (message.type == "v") {
|
||||||
|
msgtype = "m.video";
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.sendMessage(roomId, {
|
||||||
|
msgtype: msgtype,
|
||||||
|
body: "Message",
|
||||||
|
url: message.content
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await markMessageAsRead(message.sender, roomId);
|
||||||
|
}
|
||||||
|
await client.sendText(roomId, messages.general.menu);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
await client.sendText(roomId, messages.errors.didntunderstand);
|
await client.sendText(roomId, messages.errors.didntunderstand);
|
||||||
|
await client.sendText(roomId, messages.general.menu);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
30
src/utils.js
30
src/utils.js
|
@ -1,4 +1,11 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import {
|
||||||
|
EncryptionAlgorithm,
|
||||||
|
MatrixClient,
|
||||||
|
MessageEvent,
|
||||||
|
RustSdkCryptoStorageProvider,
|
||||||
|
SimpleFsStorageProvider,
|
||||||
|
} from "matrix-bot-sdk";
|
||||||
|
|
||||||
const configPath = './config.json';
|
const configPath = './config.json';
|
||||||
const messagesPath = './messages.json';
|
const messagesPath = './messages.json';
|
||||||
|
@ -41,4 +48,25 @@ const readMessages = () => {
|
||||||
return JSON.parse(fs.readFileSync(messagesPath));
|
return JSON.parse(fs.readFileSync(messagesPath));
|
||||||
};
|
};
|
||||||
|
|
||||||
export {readMessages, readConfig, logError, logInfo};
|
const uploadMediaFromEvent = async (client, event) => {
|
||||||
|
const message = new MessageEvent(event);
|
||||||
|
const fileEvent = new MessageEvent(message.raw);
|
||||||
|
const decrypted = await client.crypto.decryptMedia(fileEvent.content.file);
|
||||||
|
const mxc = await client.uploadContent(decrypted);
|
||||||
|
return mxc;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertMsgType = (msgtype) => {
|
||||||
|
switch (msgtype) {
|
||||||
|
case "m.image":
|
||||||
|
return "p";
|
||||||
|
case "m.video":
|
||||||
|
return "v";
|
||||||
|
case "m.text":
|
||||||
|
return "t";
|
||||||
|
default:
|
||||||
|
return msgtype;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { readMessages, readConfig, logError, logInfo, uploadMediaFromEvent, convertMsgType };
|
Loading…
Reference in New Issue