Complete location as a criteria for search

This commit is contained in:
2024-08-10 15:47:37 +03:00
parent 7220c6d2c2
commit 971d263d35
8 changed files with 42614 additions and 702 deletions

114
src/db.js
View File

@@ -19,7 +19,7 @@ const getClient = async () => {
if ((await client.query("SELECT * FROM cities")).rowCount < 6079) {
await client.query("DELETE FROM cities");
//Not sure if pg has support for such kind of things, sooooooooo
exec(`psql -h ${process.env.POSTGRES_HOST} -p ${process.env.POSTGRES_PORT} -d ${process.env.POSTGRES_DB} -U ${process.env.POSTGRES_USER} -f ./cities.sql`, (error) => {
if (error) logError(error);
@@ -61,33 +61,50 @@ const eraseUserMedia = async (roomId) => {
};
const selectProfilesForUser = async (roomId) => {
let myInterest = (await db.query("SELECT interest FROM users WHERE room_id = $1", [roomId])).rows[0].interest;
let mySex = (await db.query("SELECT sex FROM users WHERE room_id = $1", [roomId])).rows[0].sex;
let userAge = (await db.query("SELECT age FROM users WHERE room_id = $1", [roomId])).rows[0].age;
//Selecting profiles other than user's and with difference in age +-2.
let user;
if (myInterest === 'b') // both, no matter what sex
user = (await db.query(`SELECT
room_id, name, age, sex, description, country, city FROM users
WHERE
age::numeric <@ ANY(ARRAY[numrange($1 - 2, $1 + 2)])
AND room_id != $2
AND (interest = $3 OR interest = 'b')
ORDER BY RANDOM()
LIMIT 1`, [userAge, roomId, mySex])
).rows[0];
else {
user = (await db.query(`SELECT
room_id, name, age, sex, description, country, city FROM users
WHERE
age::numeric <@ ANY(ARRAY[numrange($1 - 2, $1 + 2)])
AND room_id != $2
AND sex = $3
AND (interest = $4 OR interest = 'b')
ORDER BY RANDOM()
LIMIT 1`, [userAge, roomId, myInterest, mySex])
).rows[0];
}
const { myrange, myinterest, mysex, myage, mycity, mycountry } = (await db.query(`SELECT range AS myrange,
interest AS myinterest,
sex AS mysex,
age AS myage,
city AS mycity,
country AS mycountry
FROM users WHERE room_id = $1`, [roomId])
).rows[0];
const { lat, lng } = (await db.query("SELECT lat, lng FROM cities WHERE name = $1 AND country = $2", [mycity, mycountry])).rows[0];
//Selecting profiles other than user's and fitting their needs
/*
2 * ASIN(SQRT(
POWER(SIN( (deg2rad(lat - $6::double precision)) / 2 ), 2)
+ COS(deg2rad(lat))
* COS(deg2rad($6::double precision))
* POWER(SIN(deg2rad(lng - $7::double precision)/2), 2)
))
* 6371 <= $5::double precision
*/
let user = (await db.query(`SELECT
room_id, name, age, sex, description, country, city FROM users
WHERE
age::numeric <@ ANY(ARRAY[numrange($1 - 2, $1 + 2)])
AND room_id != $2
AND ${myinterest !== 'b' ? "sex = $3" : "$3 = $3 AND $4 = $4 AND $5 = $5 AND $6 = $6 AND $7 = $7"}
AND ${myrange !== 0 ?
`city = ANY(ARRAY(SELECT name
FROM cities
WHERE name = ANY(ARRAY(SELECT name
FROM cities
WHERE
check_distance($6::double precision, $7::double precision, lat, lng, $5::double precision)
))
))`
:
`check_distance($6::double precision, $7::double precision, (SELECT lat FROM cities WHERE name = city AND cities.country = country), (SELECT lng FROM cities WHERE name = city AND cities.country = country), range)`
}
AND (range >= $5::double precision AND range != 0)
AND (interest = $4 OR interest = 'b')
ORDER BY RANDOM()
LIMIT 1`, [myage, roomId, myinterest, mysex, myrange, lat, lng])
).rows[0];
if (!user) return null;
let media = await getUserProfilePictures(user.room_id);
@@ -174,6 +191,43 @@ const getUserLanguage = async (roomId) => {
return (await db.query("SELECT language FROM users WHERE room_id = $1", [roomId])).rows[0].language;
}
const checkCountry = async (name) => {
let res = (await db.query(`SELECT country AS name, levenshtein(country, $1) AS similarity
FROM cities
ORDER BY similarity ASC
LIMIT 3`, [name])
).rows;
if (res[0].similarity == 0) { // 'similarity' is actually inversed. The less 'similarity', the more it similar. 0 means the same
return {
exists: true
};
}
return {
exists: false,
variants: res
};
}
const checkCity = async (name) => {
let res = (await db.query(`SELECT name, country, levenshtein(name, $1) AS similarity
FROM cities
ORDER BY similarity ASC
LIMIT 5`, [name])
).rows;
if (res[0].similarity == 0) {
return {
exists: true,
country: res[0].country
}
}
return {
exists: false,
variants: res
}
}
export {
eraseUser,
appendUserPictures,
@@ -196,5 +250,7 @@ export {
getUnreadMessages,
markMessageAsRead,
setUserLanguage,
getUserLanguage
getUserLanguage,
checkCountry,
checkCity
};

View File

@@ -32,7 +32,9 @@ import {
setUserState,
uploadMediaAsMessage,
setUserLanguage,
getUserLanguage
getUserLanguage,
checkCountry,
checkCity
} from './db.js';
import { processRequest, showRandomProfileToUser, showNewLikes } from "./interactions.js";
@@ -84,15 +86,41 @@ client.on("room.message", async (roomId, event) => {
break;
case "country":
let checkResultCountry = await checkCountry(answer);
if (!checkResultCountry.exists) {
console.log(checkResultCountry.variants)
await client.sendText(roomId, i18n.t(
["errors", "wrongcountry"],
{
first: checkResultCountry.variants[0].name,
second: checkResultCountry.variants[1].name,
third: checkResultCountry.variants[2].name
}
));
return;
}
await processRequest(client, roomId, current_action, answer, 'city');
break;
case "city":
let checkResultCity = await checkCity(answer);
if (!checkResultCity.exists) {
await client.sendText(roomId, i18n.t(
["errors", "wrongcity"],
{
first: checkResultCity.variants[0].name,
second: checkResultCity.variants[1].name,
third: checkResultCity.variants[2].name,
fourth: checkResultCity.variants[3].name,
fifth: checkResultCity.variants[4].name,
}
));
return;
}
await processRequest(client, roomId, current_action, answer, 'range');
break;
case "range":
answer = parseInt(answer.split(" ")[0]);
console.log(answer)
if (!answer) {
if (!answer && answer != 0) {
await client.sendText(roomId, i18n.t(["setup", "range"]));
return;
}
@@ -187,7 +215,7 @@ client.on("room.message", async (roomId, event) => {
return;
} else if (answer == '🏠️' || answer == '4') {
await client.sendText(roomId, messages.general.menu);
await client.sendText(roomId, i18n.t(["general", "menu"]));
await setUserState(roomId, 'menu');
return;
}

View File

@@ -87,8 +87,7 @@ ${chosenProfile.description}`;
}
}
await client.sendText(roomId, messages.general.rate);
await client.sendText(roomId, i18n.t(["general", "rate"]));
};
const showProfileToUser = async (client, roomId, profileId) => {