add oportunity to change info

This commit is contained in:
leca 2024-08-13 18:21:54 +03:00
parent dc6c438c73
commit ab1fb6ef88
5 changed files with 295 additions and 151 deletions

View File

@ -71,6 +71,10 @@ const eraseUserMessages = async (roomid) => {
await db.query("DELETE FROM messages WHERE sender = $1 OR recipient = $1", [roomId]);
}
const eraseUserPfp = async (roomId) => {
await db.query("DELETE FROM media WHERE owner = $1 AND purpose = 'p'", [roomId]);
}
const selectProfilesForUser = async (roomId) => {
const { myrange, myinterest, mysex, myage, mycity } = (await db.query(`SELECT range AS myrange,
interest AS myinterest,
@ -238,5 +242,6 @@ export {
getCityNameByID,
getCountryNameByID,
doesUserExist,
createUser
createUser,
eraseUserPfp
};

View File

@ -33,10 +33,25 @@ import {
getUserLanguage,
findCity,
doesUserExist,
createUser
createUser,
eraseUserPfp,
getProfileInfo
} from './db.js';
import { processRequest, showRandomProfileToUser, showNewLikes } from "./interactions.js";
import {
processRequest,
showRandomProfileToUser,
showNewLikes,
wait_start,
range,
interest,
pictures,
loc,
age,
sex,
showProfileToUser,
showProfile
} from "./interactions.js";
import { db } from "./db.js";
@ -87,126 +102,76 @@ client.on("room.message", async (roomId, event) => {
switch (current_action) {
case "wait_start":
let a = answer.split(" ");
if (a[0] !== "!start") return;
if (a[1] !== "ru" && a[1] !== "en") return;
await setUserLanguage(roomId, a[1]);
i18n.locale = a[1];
await setUserState(roomId, "location");
await client.sendText(roomId, i18n.t(["setup", "location"]));
await wait_start(client, roomId, current_action, answer, false);
break;
case "wait_start_u":
await wait_start(client, roomId, current_action, answer, true);
break;
case "location":
let number = parseInt(answer);
if (!number) {
let cities = await findCity(answer);
await client.sendText(roomId, i18n.t(["setup", "choosecity"], {
number1: cities[0].id,
name1: cities[0].name,
country1: cities[0].country,
lat1: cities[0].lat,
lng1: cities[0].lng,
number2: cities[1].id,
name2: cities[1].name,
country2: cities[1].country,
lat2: cities[1].lat,
lng2: cities[1].lng,
number3: cities[2].id,
name3: cities[2].name,
country3: cities[2].country,
lat3: cities[2].lat,
lng3: cities[2].lng,
number4: cities[3].id,
name4: cities[3].name,
country4: cities[3].country,
lat4: cities[3].lat,
lng4: cities[3].lng,
number5: cities[4].id,
name5: cities[4].name,
country5: cities[4].country,
lat5: cities[4].lat,
lng5: cities[4].lng,
}));
} else {
await processRequest(client, roomId, current_action, number, 'range');
}
await loc(client, roomId, current_action, answer, false);
break;
case "location_u":
await loc(client, roomId, current_action, answer, true);
break;
case "range":
answer = parseInt(answer.split(" ")[0]);
if (!answer && answer != 0) {
await client.sendText(roomId, i18n.t(["setup", "range"]));
return;
}
await processRequest(client, roomId, current_action, answer, 'name');
await range(client, roomId, current_action, answer, false);
break;
case "range_u":
await range(client, roomId, current_action, answer, true);
break;
case "name":
await processRequest(client, roomId, current_action, answer, 'age');
break;
case "age":
answer = parseInt(answer);
if (!answer) {
await client.sendText(roomId, i18n.t(["setup", "age"]));
return;
}
case "name_u":
await processRequest(client, roomId, current_action, answer, 'menu');
break;
if (answer < 14) {
await client.sendText(roomId, i18n.t(["errors", "tooyoung"]));
await client.leaveRoom(roomId);
await fullEraseUser(roomId);
return;
}
await processRequest(client, roomId, current_action, answer, 'sex');
case "age":
await age(client, roomId, current_action, answer, false);
break;
case "age_u":
await age(client, roomId, current_action, answer, true);
break;
case "sex":
answer = answer.toLowerCase().trim();
if (answer.toLowerCase() != "male" && answer.toLowerCase() != "female") {
await client.sendText(roomId, i18n.t(["errors", "twosexes"]));
return;
}
await processRequest(client, roomId, current_action, answer[0], 'interest');
await sex(client, roomId, current_action, answer, false);
break;
case "sex_u":
await sex(client, roomId, current_action, answer, true);
break;
case "interest":
answer = answer.toLowerCase().trim();
if (answer != "male" && answer != "female" && answer != "both") {
await client.sendText(roomId, i18n.t(["errors", "didntunderstand"]));
return;
}
await processRequest(client, roomId, current_action, answer[0], 'description');
await interest(client, roomId, current_action, answer, false);
break;
case "interest_u":
await interest(client, roomId, current_action, answer, true);
break;
case "description":
await processRequest(client, roomId, current_action, answer, 'pictures');
break;
case "pictures":
if (event.content?.msgtype !== 'm.image' && event.content?.msgtype !== 'm.video') {
await client.sendText(roomId, i18n.t(["setup", "done"]));
await setUserState(roomId, 'view_profiles');
await showRandomProfileToUser(client, roomId);
} else {
let pictures_count = parseInt(await getAmountOfUserPictures(roomId));
if (pictures_count >= maxAmountOfPhotoesPerUser) {
await client.sendText(roomId, i18n.t(["errors", "toomuch"]));
await setUserState(roomId, 'view_profiles');
await showRandomProfileToUser(client, roomId);
} else {
let mxc = await uploadMediaFromEvent(client, event);
let type = convertMsgType(msgtype);
await appendUserPictures(roomId, mxc, type);
let pictures_count = await getAmountOfUserPictures(roomId);
if (pictures_count < maxAmountOfPhotoesPerUser) {
await client.sendText(roomId, i18n.t(["setup", "more"], { amount: String(maxAmountOfPhotoesPerUser - pictures_count) }));
} else {
await client.sendText(roomId, i18n.t(["setup", "enough"]));
await client.sendText(roomId, i18n.t(["setup", "done"]));
await setUserState(roomId, 'view_profiles');
await showRandomProfileToUser(client, roomId);
}
}
}
case "description_u":
await processRequest(client, roomId, current_action, answer, 'menu');
break;
case "pictures":
pictures(client, roomId, current_action, event, false);
break;
case "pictures_u":
pictures(client, roomId, current_action, event, true);
break;
case "language_u":
if (answer !== "ru" && answer !== "en") return;
await setUserLanguage(roomId, answer);
i18n.locale = answer;
await setUserState(roomId, "menu");
await client.sendText(roomId, i18n.t(["general", "menu"]));
break;
case "view_profiles":
if (answer == '👍️' || answer == '❤️' || answer == '1') {
let currently_viewing = await getUserCurrentlyViewingProfile(roomId);
@ -248,6 +213,11 @@ client.on("room.message", async (roomId, event) => {
break;
case 'menu':
switch (answer) {
case '0':
let profile = await getProfileInfo(roomId);
await showProfile(client, roomId, profile);
await client.sendText(roomId, i18n.t(["general", "menu"]));
break;
case '1':
await setUserState(roomId, 'view_profiles');
await showRandomProfileToUser(client, roomId);
@ -288,6 +258,42 @@ client.on("room.message", async (roomId, event) => {
}
await client.sendText(roomId, i18n.t(["general", "menu"]));
break;
case '4':
setUserState(roomId, 'location_u');
await client.sendText(roomId, i18n.t(["setup", "location"]));
break;
case '5':
setUserState(roomId, 'range_u');
await client.sendText(roomId, i18n.t(["setup", "range"]));
break;
case '6':
setUserState(roomId, 'name_u');
await client.sendText(roomId, i18n.t(["setup", "name"]));
break;
case '7':
setUserState(roomId, 'age_u');
await client.sendText(roomId, i18n.t(["setup", "age"]));
break;
case '8':
setUserState(roomId, 'sex_u');
await client.sendText(roomId, i18n.t(["setup", "sex"]));
break;
case '9':
setUserState(roomId, 'interest_u');
await client.sendText(roomId, i18n.t(["setup", "interest"]));
break;
case '10':
setUserState(roomId, 'description_u');
await client.sendText(roomId, i18n.t(["setup", "description"]));
break;
case '11':
await eraseUserPfp(roomId);
setUserState(roomId, 'pictures_u');
await client.sendText(roomId, i18n.t(["setup", "pictures"]));
break;
case '12':
setUserState(roomId, 'language_u');
await client.sendText(roomId, i18n.t(["setup", "language"]));
default:
await client.sendText(roomId, i18n.t(["errors", "didntunderstand"]));
await client.sendText(roomId, i18n.t(["general", "menu"]));

View File

@ -2,24 +2,34 @@ import {
logError,
logInfo,
readConfig,
uploadMediaFromEvent,
convertMsgType
} from './utils.js';
import {
appendUserPictures,
checkForMutualLike,
fullEraseUser,
getAmountOfUserPictures,
setUserLanguage,
getUserLanguage,
findCity,
db,
setUserState,
selectProfilesForUser,
setUserCurrentlyViewingProfile,
getProfileInfo,
getAllLikesForUser,
checkForMutualLike,
markLikeAsRead,
getUserLanguage,
getCountryNameByID,
getCityNameByID
} from "./db.js";
import fs from 'fs';
const config = readConfig();
const maxAmountOfPhotoesPerUser = config.maxAmountOfPhotoesPerUser;
import { I18n } from "i18n-js";
const i18n = new I18n({
@ -45,26 +55,21 @@ const processRequest = async (client, roomId, question, answer, nextQuestion) =>
await client.sendText(roomId, i18n.t(["errors", "toobig"]));
return;
}
await db.query(`UPDATE users SET ${question} = $1 WHERE room_id = $2`, [answer, roomId]);
let q = question.split("_")
if (q[1] == "u")
await db.query(`UPDATE users SET ${q[0]} = $1 WHERE room_id = $2`, [answer, roomId]);
else
await db.query(`UPDATE users SET ${question} = $1 WHERE room_id = $2`, [answer, roomId]);
await client.sendText(roomId, i18n.t(["general", "setopt"], { opt: answer }));
await client.sendText(roomId, i18n.t(["setup", nextQuestion]));
if (nextQuestion == "menu")
await client.sendText(roomId, i18n.t(["general", "menu"]));
else
await client.sendText(roomId, i18n.t(["setup", nextQuestion]));
setUserState(roomId, nextQuestion);
};
const showRandomProfileToUser = async (client, roomId) => {
let preferredLanguage = await getUserLanguage(roomId);
if (!preferredLanguage) preferredLanguage = i18n.defaultLocale;
i18n.locale = preferredLanguage;
let chosenProfile = await selectProfilesForUser(roomId);
if (!chosenProfile) {
await client.sendText(roomId, i18n.t(["errors", "noprofiles"]));
return;
}
const showProfile = async (client, roomId, chosenProfile) => {
chosenProfile.country = await getCountryNameByID(chosenProfile.location);
chosenProfile.city = await getCityNameByID(chosenProfile.location);
@ -73,7 +78,6 @@ const showRandomProfileToUser = async (client, roomId) => {
${chosenProfile.name}, ${chosenProfile.sex == 'm' ? 'male' : 'female'}, ${chosenProfile.age}.
${chosenProfile.description}`;
await setUserCurrentlyViewingProfile(roomId, chosenProfile.room_id);
await client.sendText(roomId, message);
if (chosenProfile.media) {
@ -91,7 +95,23 @@ ${chosenProfile.description}`;
});
}
}
}
const showRandomProfileToUser = async (client, roomId) => {
let preferredLanguage = await getUserLanguage(roomId);
if (!preferredLanguage) preferredLanguage = i18n.defaultLocale;
i18n.locale = preferredLanguage;
let chosenProfile = await selectProfilesForUser(roomId);
if (!chosenProfile) {
await client.sendText(roomId, i18n.t(["errors", "noprofiles"]));
return;
}
await showProfile(client, roomId, chosenProfile);
await setUserCurrentlyViewingProfile(roomId, chosenProfile.room_id);
await client.sendText(roomId, i18n.t(["general", "rate"]));
};
@ -102,35 +122,11 @@ const showProfileToUser = async (client, roomId, profileId) => {
let profileInfo = await getProfileInfo(profileId);
profileInfo.country = await getCountryNameByID(profileInfo.location);
profileInfo.city = await getCityNameByID(profileInfo.location);
let message =
`${profileInfo.country}, ${profileInfo.city}.
${profileInfo.name}, ${profileInfo.sex == 'm' ? 'male' : 'female'}, ${profileInfo.age}.
${profileInfo.description}`;
await client.sendText(roomId, i18n.t(["general", "showalike"]));
await client.sendText(roomId, message);
await showProfile(client, roomId, profileInfo);
if (profileInfo.media) {
for (let media of profileInfo.media) {
let msgtype;
if (media.type == 'p') {
msgtype = "m.image";
} else if (media.type == 'v') {
msgtype = "m.video";
}
await client.sendMessage(roomId, {
msgtype: msgtype,
body: "Profile media",
url: media.url
});
}
}
await client.sendText(roomId, i18n.t(["general", "mxid"], { mxid: profileInfo.mx_id }));
};
const showNewLikes = async (client, roomId) => {
@ -143,4 +139,139 @@ const showNewLikes = async (client, roomId) => {
}
};
export { processRequest, showRandomProfileToUser, showNewLikes, showProfileToUser };
const wait_start = async (client, roomId, current_action, answer, update) => {
let a = answer.split(" ");
if (a[0] !== "!start") return;
if (a[1] !== "ru" && a[1] !== "en") return;
await setUserLanguage(roomId, a[1]);
i18n.locale = a[1];
await setUserState(roomId, update ? "menu" : "location");
await client.sendText(roomId, i18n.t(["setup", "location"]));
}
const loc = async (client, roomId, current_action, answer, update) => {
let number = parseInt(answer);
if (!number) {
let cities = await findCity(answer);
await client.sendText(roomId, i18n.t(["setup", "choosecity"], {
number1: cities[0].id,
name1: cities[0].name,
country1: cities[0].country,
lat1: cities[0].lat,
lng1: cities[0].lng,
number2: cities[1].id,
name2: cities[1].name,
country2: cities[1].country,
lat2: cities[1].lat,
lng2: cities[1].lng,
number3: cities[2].id,
name3: cities[2].name,
country3: cities[2].country,
lat3: cities[2].lat,
lng3: cities[2].lng,
number4: cities[3].id,
name4: cities[3].name,
country4: cities[3].country,
lat4: cities[3].lat,
lng4: cities[3].lng,
number5: cities[4].id,
name5: cities[4].name,
country5: cities[4].country,
lat5: cities[4].lat,
lng5: cities[4].lng,
}));
} else {
await processRequest(client, roomId, current_action, number, update ? "menu" : "range");
}
}
const range = async (client, roomId, current_action, answer, update) => {
answer = parseInt(answer.split(" ")[0]);
if (!answer && answer != 0) {
await client.sendText(roomId, i18n.t(["setup", "range"]));
return;
}
await processRequest(client, roomId, current_action, answer, update ? "menu" : "name");
}
const age = async (client, roomId, current_action, answer, update) => {
answer = parseInt(answer);
if (!answer) {
await client.sendText(roomId, i18n.t(["setup", "age"]));
return;
}
if (answer < 14) {
await client.sendText(roomId, i18n.t(["errors", "tooyoung"]));
await client.leaveRoom(roomId);
await fullEraseUser(roomId);
return;
}
await processRequest(client, roomId, current_action, answer, update ? "menu" : "sex");
}
const sex = async (client, roomId, current_action, answer, update) => {
answer = answer.toLowerCase().trim();
if (answer.toLowerCase() != "male" && answer.toLowerCase() != "female") {
await client.sendText(roomId, i18n.t(["errors", "twosexes"]));
return;
}
await processRequest(client, roomId, current_action, answer[0], update ? "menu" : "interest");
}
const interest = async (client, roomId, current_action, answer, update) => {
answer = answer.toLowerCase().trim();
if (answer != "male" && answer != "female" && answer != "both") {
await client.sendText(roomId, i18n.t(["errors", "didntunderstand"]));
return;
}
await processRequest(client, roomId, current_action, answer[0], update ? "menu" : "description");
}
const pictures = async (client, roomId, current_action, event, update) => {
const msgtype = event.content.msgtype;
if (event.content?.msgtype !== 'm.image' && event.content?.msgtype !== 'm.video') {
await client.sendText(roomId, i18n.t(["setup", "done"]));
await setUserState(roomId, update ? "menu" : "view_profiles");
await showRandomProfileToUser(client, roomId);
} else {
let pictures_count = parseInt(await getAmountOfUserPictures(roomId));
if (pictures_count >= maxAmountOfPhotoesPerUser) {
await client.sendText(roomId, i18n.t(["errors", "toomuch"]));
await setUserState(roomId, update ? "menu" : "view_profiles");
await showRandomProfileToUser(client, roomId);
} else {
let mxc = await uploadMediaFromEvent(client, event);
let type = convertMsgType(msgtype);
await appendUserPictures(roomId, mxc, type);
let pictures_count = await getAmountOfUserPictures(roomId);
if (pictures_count < maxAmountOfPhotoesPerUser) {
await client.sendText(roomId, i18n.t(["setup", "more"], { amount: String(maxAmountOfPhotoesPerUser - pictures_count) }));
} else {
await client.sendText(roomId, i18n.t(["setup", "enough"]));
await client.sendText(roomId, i18n.t(["setup", "done"]));
await setUserState(roomId, update ? "menu" : "view_profiles");
await showRandomProfileToUser(client, roomId);
}
}
}
}
export {
processRequest,
showRandomProfileToUser,
showNewLikes,
showProfileToUser,
wait_start,
loc,
range,
age,
sex,
interest,
pictures,
showProfile
};

View File

@ -2,7 +2,7 @@
"general": {
"welcome": "Hello! I am a bot for new meetings in Matrix!\nTo start, please, type \"!start <language>\", where language are 'en' or 'ru'.\nI'll ask some questions to fill your profile. You can change that info later, if you will.\nThen, I'll start showing you another people's profiles.\nYou can like other profile, skip or send a message to the person.\nIf you mutually liked each other, you'll be given each other's MXID to start a DM.\nMy source code can be found on gitea: https://git.foxarmy.org/leca/heart2heart.\n\nGood luck!",
"rate": "Decide wether you like (👍️, ❤️ or 1), dislike (👎️, 💔 or 2) or wanna send a messsage (💌 or 3). Write '🏠️' or 4 to quit to menu. Any other response counts as dislike.",
"menu": "Pick an action:\n1) Start watching profiles\n2) Check for mutual likes\n3) Check for messages",
"menu": "Pick an action:\n0) Show your profile\n1) Start watching profiles\n2) Check for mutual likes\n3) Check for messages\n4) Change location\n5) Change range\n6) Change name\n7) Change age\n8) Change sex\n9) Change interest\n10) Change description\n11) Change pictures\n12) Change langage",
"newlikes": "You have new mutual like(s)! Go into menu (🏠️) to see!",
"showalike": "This person and you mutually liked each other!",
"mxid": "Go drop them a line! Their MXID is: %{mxid}",
@ -15,6 +15,7 @@
"setopt": "Got \"%{opt}\""
},
"setup": {
"language": "Write a locale name, for example \"ru\" or \"en\".",
"location": "Write a name of city you are living in. Write them in English. For example, 'Moscow', 'Washington', or 'Kyiv'.",
"choosecity": "These are 5 most similar names of cities. Pick a city by writing its number. If you are unsatisfied with results, write a name of your city in other way.\n%{number1}) %{name1}, %{country1}. (%{lat1}, %{lng1})\n%{number2}) %{name2}, %{country2}. (%{lat2}, %{lng2})\n%{number3}) %{name3}, %{country3}. (%{lat3}, %{lng3})\n%{number4}) %{name4}, %{country4}. (%{lat4}, %{lng4})\n%{number5}) %{name5}, %{country5}. (%{lat5}, %{lng5})",
"range": "Write a radius (in kilometers) of a circle you'd like to find people in (Write 0 if you don't care or small values to find people in your city only)",

View File

@ -2,7 +2,7 @@
"general": {
"welcome": "Привет! Я бот, который поможет вам найти новые знакомства в Матриксе!\nЧтобы начать, напишите \"!start <язык>\". Вместо <язык> вставьте ru или en.\nЯ спрошу несколько вопросов, чтобы заполнить ваш профиль. Вы сможете изменить информацию позже.\nПосле этого, я начну показывать вам профили других пользователей..\nВы можете лайкать, скипать чужие профили или отправлять им сообщения.\nЕсли вы взаимно лайкнули друг друг, вам будут показаны ваши MXID.\nМой исходный код можно найти на gitea: https://git.foxarmy.org/leca/heart2heart.\n\nУдачи!",
"rate": "Решите, нравится ли (👍️, ❤️ or 1), не нравится (👎️, 💔 or 2) или вы хотите отправить сообщение (💌 or 3). Напишите '🏠️' или 4 чтобы выйти в меню. Любой другой ответ считается как \"не нравится\".",
"menu": "Выберете действие:\n1) Начать просмотр профилей\n2) Проверить взаимные лайки\n3) Проверить сообщения",
"menu": "Выберете действие:\n0) Показать ваш профиль\n1) Начать просмотр профилей\n2) Проверить взаимные лайки\n3) Проверить сообщения\n4) Изменить местоположение\n5) Изменить радиус\n6) Изменить имя\n7) Изменить возраст\n8) Изменить пол\n9) Изменить интерес\n10) Изменить описание\n11) Изменить картинки профиля\n12) Изменить язык",
"newlikes": "У вас новый(-ие) взаимные лайк(и)! Выйдите в меню (🏠️) чтобы посмотреть!",
"showalike": "Этот человек и вы друг друга взаимно лайкнули!",
"mxid": "Идите и напишите этому человеку! MXID: %{mxid}",
@ -15,6 +15,7 @@
"setopt": "Записал \"%{opt}\""
},
"setup": {
"language": "Напишите название локали. например \"ru\" или \"en\".",
"location": "Напишите название города, в котором вы живёте. Используйте английский язык. например, 'Moscow', 'Washington', or 'Kyiv'.",
"choosecity": "Вот 5 наиболее похожих по названию городов. Чтобы выбрать город, напишите его номер. Если вы не удовлетворены результатами, напишите название города иначе.\n%{number1}) %{name1}, %{country1}. (%{lat1}, %{lng1})\n%{number2}) %{name2}, %{country2}. (%{lat2}, %{lng2})\n%{number3}) %{name3}, %{country3}. (%{lat3}, %{lng3})\n%{number4}) %{name4}, %{country4}. (%{lat4}, %{lng4})\n%{number5}) %{name5}, %{country5}. (%{lat5}, %{lng5})",
"range": "Напишите радиус (в километрвх), в котором вы хотели бы найти людей (Напишите 0, если вам не важен радиус или маленькие значения, если хотите найти людей только в своём городе)",