-
Notifications
You must be signed in to change notification settings - Fork 9
/
ReputationManager.js
173 lines (145 loc) · 6.62 KB
/
ReputationManager.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
'use strict';
const db = require.main.require('./src/database'),
winston = require.main.require('winston'),
UserVotingPermissions = require('./UserVotingPermissions.js');
let ReputationManager = function (Config) {
this.userCanUpvotePost = async function (user, post) {
let userPermissions = new UserVotingPermissions(Config, db, user, post);
try {
await userPermissions.votingAllowedInCategory();
await userPermissions.hasEnoughPostsToUpvote();
await userPermissions.isOldEnoughToUpvote();
await userPermissions.hasVotedTooManyPostsInThread();
await userPermissions.hasVotedAuthorTooManyTimesThisMonth();
await userPermissions.hasVotedTooManyTimesToday();
await userPermissions.postIsNotTooOld();
return {
'allowed': true
};
} catch (err) {
throw {
'allowed': false,
'reason': err.reason,
'params': err.params
};
}
};
this.userCanDownvotePost = async function (user, post) {
let userPermissions = new UserVotingPermissions(Config, db, user, post);
try {
await userPermissions.votingAllowedInCategory();
await userPermissions.hasDownvotedTooManyTimesToday();
await userPermissions.hasEnoughPostsToDownvote();
await userPermissions.isOldEnoughToDownvote();
await userPermissions.hasEnoughReputationToDownvote();
await userPermissions.hasVotedTooManyPostsInThread();
await userPermissions.hasVotedAuthorTooManyTimesThisMonth();
await userPermissions.hasVotedTooManyTimesToday();
await userPermissions.postIsNotTooOld();
return {
'allowed': true
};
} catch (err) {
throw {
'allowed': false,
'reason': err.reason,
'params': err.params
};
}
};
this.calculateUpvoteWeight = function (user) {
let extraRate = Config.upvoteExtraPercentage() / 100;
let weight = Math.floor(user.reputation * extraRate);
if (weight < 0) weight = 0;
if (weight > Config.maxUpvoteWeight()) {
weight = Config.maxUpvoteWeight();
}
winston.verbose('[plugin-reputation-rules][calculateUpvoteWeight] current voter reputation: ' + user.reputation+ ', upvote extra weight: ' + weight);
return weight;
};
this.calculateDownvoteWeight = function (user) {
let extraRate = Config.downvoteExtraPercentage() / 100;
let weight = Math.floor(user.reputation * extraRate);
if (weight < 0) weight = 0;
if (weight > Config.maxDownvoteWeight()) {
weight = Config.maxDownvoteWeight();
}
winston.verbose('[plugin-reputation-rules][calculateDownvoteWeight] current voter reputation: ' + user.reputation+ ', downvote extra weight: ' + weight);
return weight;
};
this.logVote = async function (vote) {
vote.undone = false;
winston.verbose('[plugin-reputation-rules][logVote] type: ' + vote.type + ', voterId: ' + vote.voterId+ ', authorId: ' + vote.authorId + ', extra amount: ' + vote.amount);
//save main object and its key in secondary sets
await saveMainVoteLog(vote);
await saveThreadVoteLog(vote);
await saveAuthorVoteLog(vote);
await saveUserVoteLog(vote);
return vote;
};
this.logVoteUndone = async function (vote) {
vote.undone = true;
winston.verbose('[logVoteUndone] voterId: ' + vote.voterId+ ', authorId: ' + vote.authorId);
//update main object and remove its key from secondary sets
await updateMainVoteLog(vote, 'undone', true);
await removeThreadVoteLog(vote);
await removeAuthorVoteLog(vote);
await removeUserVoteLog(vote);
return vote;
};
this.findVoteLog = async function (user, author, post) {
let voteIdentifier = Config.getMainLogId(user.uid, author.uid, post.tid, post.pid);
return await db.getObject(voteIdentifier);
};
async function saveMainVoteLog(vote) {
let key = Config.getMainLogId(vote.voterId, vote.authorId, vote.topicId, vote.postId);
await db.setObject(key, vote);
}
async function updateMainVoteLog(vote, field, value) {
let key = Config.getMainLogId(vote.voterId, vote.authorId, vote.topicId, vote.postId);
await db.setObjectField(key, field, value);
}
async function saveThreadVoteLog(vote) {
let key = Config.getPerThreadLogId(vote.voterId, vote.topicId);
let value = Config.getMainLogId(vote.voterId, vote.authorId, vote.topicId, vote.postId);
await setAdd(key, value);
}
async function saveAuthorVoteLog(vote) {
let key = Config.getPerAuthorLogId(vote.voterId, vote.authorId);
let value = Config.getMainLogId(vote.voterId, vote.authorId, vote.topicId, vote.postId);
await setAdd(key, value);
}
async function saveUserVoteLog(vote) {
let userKey = Config.getPerUserLogId(vote.voterId);
let userAndVoteTypeKey = Config.getPerUserAndTypeLogId(vote.voterId, vote.type);
let value = Config.getMainLogId(vote.voterId, vote.authorId, vote.topicId, vote.postId);
await setAdd(userKey, value);
await setAdd(userAndVoteTypeKey, value);
}
async function removeThreadVoteLog(vote) {
let key = Config.getPerThreadLogId(vote.voterId, vote.topicId);
let value = Config.getMainLogId(vote.voterId, vote.authorId, vote.topicId, vote.postId);
await setRemove(key, value);
}
async function removeAuthorVoteLog(vote) {
let key = Config.getPerAuthorLogId(vote.voterId, vote.authorId);
let value = Config.getMainLogId(vote.voterId, vote.authorId, vote.topicId, vote.postId);
await setRemove(key, value);
}
async function removeUserVoteLog(vote) {
let userKey = Config.getPerUserLogId(vote.voterId);
let userUpvoteKey = Config.getPerUserAndTypeLogId(vote.voterId, 'upvote');
let userDownvoteKey = Config.getPerUserAndTypeLogId(vote.voterId, 'downvote');
let value = Config.getMainLogId(vote.voterId, vote.authorId, vote.topicId, vote.postId);
await setRemove(userKey, value);
await setRemove(userUpvoteKey, value);
await setRemove(userDownvoteKey, value);
}
async function setAdd(key, value) {
await db.setAdd(key, value);
}
async function setRemove(key, value) {
await db.setRemove(key, value);
}
};
module.exports = ReputationManager;