@waline/vercel 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waline/vercel",
3
- "version": "1.14.0",
3
+ "version": "1.15.0",
4
4
  "description": "vercel server for waline comment system",
5
5
  "keywords": [
6
6
  "waline",
@@ -42,7 +42,7 @@
42
42
  "think-model-mysql": "^1.1.7",
43
43
  "think-model-postgresql": "1.1.6",
44
44
  "think-model-sqlite": "^1.2.3",
45
- "think-mongo": "^2.1.2",
45
+ "think-mongo": "^2.2.1",
46
46
  "think-router-rest": "^1.0.5",
47
47
  "thinkjs": "^3.2.14",
48
48
  "ua-parser-js": "^1.0.2"
@@ -37,6 +37,8 @@ const {
37
37
  TG_TEMPLATE,
38
38
  WX_TEMPLATE,
39
39
  DISCORD_TEMPLATE,
40
+
41
+ LEVELS,
40
42
  } = process.env;
41
43
 
42
44
  let storage = 'leancloud';
@@ -104,6 +106,9 @@ module.exports = {
104
106
  disallowIPList: [],
105
107
  secureDomains: SECURE_DOMAINS ? SECURE_DOMAINS.split(/\s*,\s*/) : undefined,
106
108
  disableUserAgent: DISABLE_USERAGENT && !isFalse(DISABLE_USERAGENT),
109
+ levels: isFalse(LEVELS)
110
+ ? false
111
+ : LEVELS.split(/\s*,\s*/).map((v) => Number(v)),
107
112
  avatarProxy,
108
113
  oauthUrl,
109
114
  markdown,
@@ -305,6 +305,50 @@ module.exports = class extends BaseRest {
305
305
  );
306
306
  }
307
307
 
308
+ if (think.isArray(this.config('levels'))) {
309
+ const countWhere = {
310
+ status: ['NOT IN', ['waiting', 'spam']],
311
+ _complex: {},
312
+ };
313
+ if (user_ids.length) {
314
+ countWhere._complex.user_id = ['IN', user_ids];
315
+ }
316
+ const mails = Array.from(
317
+ new Set(comments.map(({ mail }) => mail).filter((v) => v))
318
+ );
319
+ if (mails.length) {
320
+ countWhere._complex.mail = ['IN', mails];
321
+ }
322
+ if (!think.isEmpty(countWhere._complex)) {
323
+ countWhere._complex._logic = 'or';
324
+ } else {
325
+ delete countWhere._complex;
326
+ }
327
+ const counts = await this.modelInstance.count(countWhere, {
328
+ group: ['user_id', 'mail'],
329
+ });
330
+ comments.forEach((cmt) => {
331
+ const countItem = (counts || []).find(({ mail, user_id }) => {
332
+ if (user_id) {
333
+ return user_id === cmt.user_id;
334
+ }
335
+ return mail === cmt.mail;
336
+ });
337
+
338
+ let level = 0;
339
+ if (countItem) {
340
+ const _level = think.findLastIndex(
341
+ this.config('levels'),
342
+ (l) => l <= countItem.count
343
+ );
344
+ if (_level !== -1) {
345
+ level = _level;
346
+ }
347
+ }
348
+ cmt.level = level;
349
+ });
350
+ }
351
+
308
352
  return this.json({
309
353
  page,
310
354
  totalPages: Math.ceil(rootCount / pageSize),
@@ -7,4 +7,15 @@ module.exports = {
7
7
  isPrevent(err) {
8
8
  return think.isError(err) && err.message === preventMessage;
9
9
  },
10
+ findLastIndex(arr, fn) {
11
+ for (let i = arr.length - 1; i >= 0; i--) {
12
+ const ret = fn(arr[i], i, arr);
13
+ if (!ret) {
14
+ continue;
15
+ }
16
+ return i;
17
+ }
18
+
19
+ return -1;
20
+ },
10
21
  };
@@ -10,6 +10,7 @@ const app = cloudbase.init({
10
10
 
11
11
  const db = app.database();
12
12
  const _ = db.command;
13
+ const $ = db.command.aggregate;
13
14
  const collections = {};
14
15
 
15
16
  module.exports = class extends Base {
@@ -90,10 +91,10 @@ module.exports = class extends Base {
90
91
  return filter;
91
92
  }
92
93
 
93
- where(instance, where) {
94
+ where(instance, where, method = 'where') {
94
95
  const filter = this.parseWhere(where);
95
96
  if (!where._complex) {
96
- return instance.where(filter);
97
+ return instance[method](filter);
97
98
  }
98
99
 
99
100
  const filters = [];
@@ -106,7 +107,7 @@ module.exports = class extends Base {
106
107
  ...filter,
107
108
  });
108
109
  }
109
- return instance.where(_[where._complex._logic](...filters));
110
+ return instance[method](_[where._complex._logic](...filters));
110
111
  }
111
112
 
112
113
  async _select(where, { desc, limit, offset, field } = {}) {
@@ -147,10 +148,24 @@ module.exports = class extends Base {
147
148
  return data;
148
149
  }
149
150
 
150
- async count(where = {}) {
151
- const instance = await this.collection(this.tableName);
152
- const { total } = await this.where(instance, where).count();
153
- return total;
151
+ async count(where = {}, { group } = {}) {
152
+ let instance = await this.collection(this.tableName);
153
+ if (!group) {
154
+ instance = this.where(instance, where);
155
+ const { total } = await instance.count();
156
+ return total;
157
+ }
158
+
159
+ const _id = {};
160
+ group.forEach((f) => {
161
+ _id[f] = `$${f}`;
162
+ });
163
+ instance = instance.aggregate();
164
+ this.where(instance, where, 'match');
165
+ instance = instance.group({ _id, count: $.sum(1) });
166
+ const { data } = await instance.end();
167
+
168
+ return data.map(({ _id, count }) => ({ ..._id, count }));
154
169
  }
155
170
 
156
171
  async add(data) {
@@ -184,16 +184,47 @@ module.exports = class extends Base {
184
184
  return data;
185
185
  }
186
186
 
187
- async count(where = {}) {
188
- const conditions = this.where(where);
189
- if (think.isArray(conditions)) {
190
- return Promise.all(
191
- conditions.map((condition) => this.count(condition))
192
- ).then((counts) => counts.reduce((a, b) => a + b, 0));
187
+ async count(where = {}, { group } = {}) {
188
+ if (!group) {
189
+ const conditions = this.where(where);
190
+ if (think.isArray(conditions)) {
191
+ return Promise.all(
192
+ conditions.map((condition) => this.count(condition))
193
+ ).then((counts) => counts.reduce((a, b) => a + b, 0));
194
+ }
195
+
196
+ const { count } = await this.instance.fetch(conditions);
197
+ return count;
193
198
  }
194
199
 
195
- const { count } = await this.instance.fetch(conditions);
196
- return count;
200
+ const counts = [];
201
+ for (let i = 0; i < group.length; i++) {
202
+ const groupName = group[i];
203
+ if (!where._complex || !Array.isArray(where._complex[groupName])) {
204
+ continue;
205
+ }
206
+
207
+ const groupFlatValue = {};
208
+ group.slice(0, i).forEach((group) => {
209
+ groupFlatValue[group] = null;
210
+ });
211
+
212
+ for (let j = 0; j < where._complex[groupName][1].length; j++) {
213
+ const groupWhere = {
214
+ ...where,
215
+ ...groupFlatValue,
216
+ _complex: undefined,
217
+ [groupName]: where._complex[groupName][1][j],
218
+ };
219
+ const num = await this.count(groupWhere);
220
+ counts.push({
221
+ ...groupFlatValue,
222
+ [groupName]: where._complex[groupName][1][j],
223
+ count: num,
224
+ });
225
+ }
226
+ }
227
+ return counts;
197
228
  }
198
229
 
199
230
  async add(data) {
@@ -287,10 +287,25 @@ module.exports = class extends Base {
287
287
  }
288
288
 
289
289
  // eslint-disable-next-line no-unused-vars
290
- async count(where = {}, options = {}) {
290
+ async count(where = {}, { group } = {}) {
291
291
  const instance = await this.collection(this.tableName);
292
292
  const data = this.where(instance, where);
293
- return data.length;
293
+ if (!group) {
294
+ return data.length;
295
+ }
296
+
297
+ const counts = {};
298
+ for (let i = 0; i < data.length; i++) {
299
+ const key = group.map((field) => data[field]).join();
300
+ if (!counts[key]) {
301
+ counts[key] = { count: 0 };
302
+ group.forEach((field) => {
303
+ counts[key][field] = data[field];
304
+ });
305
+ }
306
+ counts[key].count += 1;
307
+ }
308
+ return Object.keys(counts);
294
309
  }
295
310
 
296
311
  async add(
@@ -128,12 +128,47 @@ module.exports = class extends Base {
128
128
 
129
129
  async count(where = {}, options = {}) {
130
130
  const instance = this.where(this.tableName, where);
131
- return instance.count(options).catch((e) => {
132
- if (e.code === 101) {
133
- return 0;
131
+ if (!options.group) {
132
+ return instance.count(options).catch((e) => {
133
+ if (e.code === 101) {
134
+ return 0;
135
+ }
136
+ throw e;
137
+ });
138
+ }
139
+
140
+ // todo: query optimize
141
+ const counts = [];
142
+ for (let i = 0; i < options.group.length; i++) {
143
+ const groupName = options.group[i];
144
+ if (!where._complex || !Array.isArray(where._complex[groupName])) {
145
+ continue;
134
146
  }
135
- throw e;
136
- });
147
+
148
+ const groupFlatValue = {};
149
+ options.group.slice(0, i).forEach((group) => {
150
+ groupFlatValue[group] = null;
151
+ });
152
+
153
+ for (let j = 0; j < where._complex[groupName][1].length; j++) {
154
+ const groupWhere = {
155
+ ...where,
156
+ ...groupFlatValue,
157
+ _complex: undefined,
158
+ [groupName]: where._complex[groupName][1][j],
159
+ };
160
+ const num = await this.count(groupWhere, {
161
+ ...options,
162
+ group: undefined,
163
+ });
164
+ counts.push({
165
+ ...groupFlatValue,
166
+ [groupName]: where._complex[groupName][1][j],
167
+ count: num,
168
+ });
169
+ }
170
+ }
171
+ return counts;
137
172
  }
138
173
 
139
174
  async add(
@@ -114,10 +114,17 @@ module.exports = class extends Base {
114
114
  }));
115
115
  }
116
116
 
117
- async count(where = {}) {
117
+ async count(where = {}, { group } = {}) {
118
118
  const instance = this.mongo(this.tableName);
119
119
  this.where(instance, where);
120
- return instance.count();
120
+ if (group) {
121
+ instance.group(group);
122
+ }
123
+ const data = await instance.count({ raw: group });
124
+ if (!Array.isArray(data)) {
125
+ return data;
126
+ }
127
+ return data.map(({ _id, total: count }) => ({ ..._id, count }));
121
128
  }
122
129
 
123
130
  async add(data) {
@@ -50,10 +50,16 @@ module.exports = class extends Base {
50
50
  return data.map(({ id, ...cmt }) => ({ ...cmt, objectId: id }));
51
51
  }
52
52
 
53
- async count(where = {}) {
53
+ async count(where = {}, { group } = {}) {
54
54
  const instance = this.model(this.tableName);
55
55
  instance.where(this.parseWhere(where));
56
- return instance.count();
56
+ if (!group) {
57
+ return instance.count();
58
+ }
59
+
60
+ instance.field([...group, 'COUNT(*) as count']);
61
+ instance.group(group);
62
+ return instance.select();
57
63
  }
58
64
 
59
65
  async add(data) {
@@ -26,7 +26,13 @@ module.exports = class extends MySQL {
26
26
  async count(...args) {
27
27
  let result = await super.count(...args);
28
28
  try {
29
- result = parseInt(result);
29
+ if (Array.isArray(result)) {
30
+ result.forEach((r) => {
31
+ r.count = parseInt(r.count);
32
+ });
33
+ } else {
34
+ result = parseInt(result);
35
+ }
30
36
  } catch (e) {
31
37
  console.log(e);
32
38
  }