-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlibrary.js
122 lines (114 loc) · 3.42 KB
/
library.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
'use strict';
const createCache = require.main.require('./src/cacheCreate');
const db = require.main.require('./src/database');
const posts = require.main.require('./src/posts');
const user = require.main.require('./src/user');
const topics = require.main.require('./src/topics');
const winston = require.main.require('winston');
const twoWayBlock = {};
const cache = createCache({
name: 'nodebb-plugin-two-way-block',
max: 1024,
maxSize: 4096,
sizeCalculation: n => n.length || 1,
ttl: 1000 * 60 * 60 * 24,
});
twoWayBlock.addBlock = async function (data) {
const { uid, targetUid } = data;
await db.sortedSetAdd(`uid:${targetUid}:blocked_by_uids`, Date.now(), uid);
cache.delete(parseInt(targetUid, 10));
};
twoWayBlock.removeBlock = async function (data) {
const { uid, targetUid } = data;
await db.sortedSetRemove(`uid:${targetUid}:blocked_by_uids`, uid);
cache.delete(parseInt(targetUid, 10));
};
twoWayBlock.filterBlocks = async function (data) {
const { set, property, uid } = data;
const blockedByUids = await twoWayBlock.list(uid);
const isPlain = typeof set[0] !== 'object';
data.set = set.filter(
item => !blockedByUids.has(parseInt(isPlain ? item : item[property], 10))
);
return data;
};
twoWayBlock.list = async function (uid) {
uid = parseInt(uid, 10);
const cached = cache.get(uid);
if (cached?.length) {
return new Set(cached);
}
const blockedBy = await db.getSortedSetRange(
`uid:${uid}:blocked_by_uids`,
0,
-1
);
const blockedBySet = new Set(blockedBy.map(blocked_by_uid => parseInt(blocked_by_uid, 10)).filter(Boolean));
cache.set(uid, blockedBySet);
return blockedBySet;
};
twoWayBlock.filterTeasers = async function (data) {
try {
const blockedByUids = await twoWayBlock.list(data.uid);
if (data.teasers && data.teasers.length > 0) {
data.teasers = await Promise.all(
data.teasers.map((postData) => {
if (!postData) return undefined;
return blockedByUids.has(parseInt(postData.user ? postData.user.uid : postData.uid, 10)) ?
getPreviousNonBlockedPost(postData, blockedByUids) :
postData;
})
);
}
} catch (e) {
winston.error(
`[nodebb-plugin-two-way-block] encountered an error while processing teasers: ${e.stack}`
);
if (!(e instanceof TypeError)) {
throw e;
}
}
return data;
};
async function getPreviousNonBlockedPost(postData, blockedSet) {
let isBlocked = false;
let prevPost = postData;
const postsPerIteration = 5;
let start = 0;
let stop = start + postsPerIteration - 1;
let checkedAllReplies = false;
function checkBlocked(post) {
const isPostBlocked = blockedSet.has(parseInt(post.uid, 10));
prevPost = !isPostBlocked ? post : prevPost;
return isPostBlocked;
}
do {
/* eslint-disable no-await-in-loop */
let pids = await db.getSortedSetRevRange(
`tid:${postData.tid}:posts`,
start,
stop
);
if (!pids.length) {
checkedAllReplies = true;
const mainPid = await topics.getTopicField(postData.tid, 'mainPid');
pids = [mainPid];
}
const prevPosts = await posts.getPostsFields(pids, [
'pid',
'uid',
'timestamp',
'tid',
'content',
]);
isBlocked = prevPosts.every(checkBlocked);
start += postsPerIteration;
stop = start + postsPerIteration - 1;
} while (isBlocked && prevPost && prevPost.pid && !checkedAllReplies);
if (isBlocked) {
return undefined;
}
prevPost.user = await user.getUserFields(prevPost.uid, ['uid', 'username', 'userslug', 'picture']);
return prevPost;
}
module.exports = twoWayBlock;