Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 184 additions & 25 deletions controllers/photo.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,32 +306,61 @@ export async function find({ query, fieldSelect = {}, options = {}, populateUser
}

export function getNewPhotosLimit(user) {
let canCreate = 0;
const pfcount = user.pfcount;
return Math.max(0, getUserPhotosLimitMax(user) - user.pfcount);
}

export function getNewPhotosLimitCss(user) {
const limit = getUserPhotosLimitMax(user);

return limit <= 10 ? 'photoLimit1' : limit <= 20 ? 'photoLimit2' : limit <= 75 ? 'photoLimit3' : '';
}

export function getUserPhotosLimitMax(user) {
// return user photos limit
/* needed fields:
user.rules.photoNewLimit
user.ranks
user.pcount
*/
if (user.rules && _.isNumber(user.rules.photoNewLimit)) {
canCreate = Math.max(0, Math.min(user.rules.photoNewLimit, maxNewPhotosLimit) - pfcount);
} else if (user.ranks && (user.ranks.includes('mec_silv') || user.ranks.includes('mec_gold'))) {
// Silver and Gold metsenats have the maximum possible limit
canCreate = maxNewPhotosLimit - pfcount;
} else if (user.ranks && user.ranks.includes('mec')) {
// Metsenat has a limit of 150
canCreate = Math.max(0, 150 - pfcount);
} else if (user.pcount < 15) {
canCreate = Math.max(0, 10 - pfcount);
} else if (user.pcount < 25) {
canCreate = Math.max(0, 15 - pfcount);
} else if (user.pcount < 50) {
canCreate = Math.max(0, 20 - pfcount);
} else if (user.pcount < 200) {
canCreate = Math.max(0, 50 - pfcount);
} else if (user.pcount < 1000) {
canCreate = Math.max(0, 75 - pfcount);
} else if (user.pcount >= 1000) {
canCreate = Math.max(0, 150 - pfcount);
}

return canCreate;
return Math.min(user.rules.photoNewLimit, maxNewPhotosLimit);
}

// Silver and Gold metsenats have the maximum possible limit
if (user.ranks && (user.ranks.includes('mec_silv') || user.ranks.includes('mec_gold'))) {
return maxNewPhotosLimit;
}

// Metsenat has a limit of 150
if (user.ranks && user.ranks.includes('mec')) {
return 150;
}

if (user.pcount < 15) {
return 10;
}

if (user.pcount < 25) {
return 15;
}

if (user.pcount < 50) {
return 20;
}

if (user.pcount < 200) {
return 50;
}

if (user.pcount < 1000) {
return 75;
}

if (user.pcount >= 1000) {
return 150;
}

return 0;
}

/**
Expand Down Expand Up @@ -1508,6 +1537,70 @@ async function givePhotos({ filter, options: { skip = 0, limit = 40, random = fa
Photo.find(query, fieldsSelect, { lean: true, limit }).exec(),
Photo.countDocuments(countQuery).exec(),
]);
} else if (iAm && iAm.registered && iAm.user.role >= 5 &&
(!(filter.l === null) && filter.l || _.isEqual(filter.lf, [1]))) {
//aggregate вроде работает дольше по этому используем его только если необходимо

let aggQuery = [
{ $lookup: { from: 'users', localField: 'user', foreignField: '_id', as: 'user_info' } },
{ $match: query },
{ $set: { photoNewLimit: { $sum: '$user_info.rules.photoNewLimit' } } },
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему используется $sum, там же значение переменной - число?

Copy link
Copy Markdown
Contributor Author

@NetJorika NetJorika Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не очень знаток mongodb, но sum из-за того, что это агрегированный запрос.
Без $sum не работает, а что там другое может быть ума не приложу.

{ $set: { pcount: { $sum: '$user_info.pcount' } } },
{ $set: { pfcount: { $sum: '$user_info.pfcount' } } },
{ $set: { ranks: { $first: '$user_info.ranks' } } },
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$first не совсем понятно почему нужно только первое значение в массиве ranks?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это не первое значение в массиве, а первый массив ranks.
Запись юзера все равно будет одна.
Нужно как я понял использовать хоть какую-то функцию из-за агрегата.

{ $set: { photosLimit: { $sum: { $switch: {
branches: [
{ case: { $gt: ['$photoNewLimit', 0] }, then: { $min: ['$photoNewLimit', maxNewPhotosLimit] } },
{ case: { $in: [{ $max: '$ranks' }, ['mec_silv', 'mec_gold']] }, then: maxNewPhotosLimit },
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$max к строке применяется если я правильно понял? (до этого присвоили первое значение из массива { $set: { ranks: { $first: '$user_info.ranks' } } })

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$first в том случае возвращает первый массив а не первое значение в массиве.
Да, тут небольшой чит из-за тех значений, что есть в справочнике, очень удобно получилось.
Они прям в нужном порядке сортируются с помощью $max "adviser","mec","mec_gold","mec_silv" (у последних двух одинаковый лимит)

{ case: { $in: [{ $max: '$ranks' }, ['mec']] }, then: 150 },
{ case: { $lt: ['$pcount', 15] }, then: 10 },
{ case: { $lt: ['$pcount', 25] }, then: 15 },
{ case: { $lt: ['$pcount', 50] }, then: 20 },
{ case: { $lt: ['$pcount', 200] }, then: 50 },
{ case: { $lt: ['$pcount', 1000] }, then: 75 },
{ case: { $gte: ['$pcount', 1000] }, then: 150 },
],
} } } } },
];

if (_.isEqual(filter.lf, [1])) {
aggQuery = [
...aggQuery,
{ $match: { $expr: { $gte: ['$pfcount', '$photosLimit'] } } },
];
}

if (filter.l) {
aggQuery = [
...aggQuery,
{ $match: { photosLimit: { $lt: Number(filter.l.max) } } },
];
}

[photos, count] = await Promise.all([
Photo.aggregate([
... aggQuery,
{ $sort: { sdate: -1 } },
{ $skip: skip },
{ $limit: limit },
{ $project: { 'photosLimit': 1, 'pcount': 1, 'pfcount': 1, 'photoNewLimit': 1, 'ranks': 1, 'user_info.cid': 1, 'user_info.pfcount': 1, 'user_info.pcount': 1, 'user_info.ranks': 1, 'user_info.rules': 1, ...fieldsSelect } },
]),
Photo.aggregate([
...aggQuery,
{ $count: 'photos_count' },
]),
]);

// take count value
count = count.length ? count[0].photos_count : 0;
} else if (iAm && iAm.registered && iAm.user.role >= 5) {
//to show different colors make sence only for moderators
[photos, count] = await Promise.all([
Photo.find(query, fieldsSelect, { lean: true, skip, limit, sort: { sdate: -1 } })
.populate({ path: 'user', select: { pfcount: 1, pcount: 1, ranks: 1, rules: 1 } }
).exec(),
Photo.countDocuments(query).exec(),
]);
} else {
[photos, count] = await Promise.all([
Photo.find(query, fieldsSelect, { lean: true, skip, limit, sort: { sdate: -1 } }).exec(),
Expand All @@ -1527,6 +1620,13 @@ async function givePhotos({ filter, options: { skip = 0, limit = 40, random = fa
await this.call('photo.fillPhotosProtection', { photos, theyAreMine: itsMineGallery, setMyFlag: !userId });

for (const photo of photos) {
if (iAm.user.role >= 5 && photo.s <= 2) {
//set user limit for moderator view
photo.userPhotoLimitCss = getNewPhotosLimitCss(photo.user_info ? photo.user_info[0] : photo.user);
} else {
photo.userPhotoLimitCss = '';
}

photo._id = undefined;
photo.user = undefined;
photo.vdate = undefined;
Expand Down Expand Up @@ -1588,6 +1688,8 @@ async function givePhotos({ filter, options: { skip = 0, limit = 40, random = fa
s: buildQueryResult.s,
y: buildQueryResult.y,
c: buildQueryResult.c,
l: buildQueryResult.l,
lf: buildQueryResult.lf,
geo: filter.geo,
},
};
Expand Down Expand Up @@ -1615,7 +1717,7 @@ const givePublicNoGeoIndex = (function () {
};
}());

const filterProps = { geo: [], r: [], rp: [], rs: [], re: [], s: [], t: [], y: [], c: [] };
const filterProps = { geo: [], r: [], rp: [], rs: [], re: [], s: [], t: [], y: [], c: [], l: [], lf: [] };
const delimeterParam = '_';
const delimeterVal = '!';
export function parseFilter(filterString) {
Expand Down Expand Up @@ -1790,6 +1892,53 @@ export function parseFilter(filterString) {
}
}
}
} else if (filterParam === 'l') {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут комментарии в этой части diff не помешали бы, тяжело понять логику.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Добавил

filterVal = filterVal.split(delimeterVal);

if (Array.isArray(filterVal) && filterVal.length === 1) {
filterVal = filterVal.map(Number).sort();

// set l.max (max user limit) only if value l is choosen in link and between 1 and 9999
if (!_.isEqual(filterVal, [0])) {
const [l0] = filterVal;
const l = {};
let active = true;

if (l0 > 0 && l0 < 1e5) {
l.max = l0;
} else {
active = false;
}

if (active) {
result.l = l;
}
} else {
const l = {};

result.l = l;
}
}
} else if (filterParam === 'lf') {
filterVal = filterVal.split(delimeterVal);

if (Array.isArray(filterVal) && filterVal.length) {
result.lf = [];

for (filterValItem of filterVal) {
if (filterValItem) {
filterValItem = Number(filterValItem);

if (typesSet.has(filterValItem)) {
result.lf.push(filterValItem);
}
}
}

if (!result.lf.length) {
delete result.lf;
}
}
}
}
}
Expand Down Expand Up @@ -3163,6 +3312,16 @@ export function buildPhotosQuery(filter, forUserId, iAm, random) {
result.c = filter.c;
}

if (filter.l) {
// добавляется напрямую в агрегативной функции
result.l = filter.l;
}

if (filter.lf) {
// добавляется напрямую в агрегативной функции
result.lf = filter.lf;
}

if (random) {
if (!query) {
query = {};
Expand Down
Loading