-
Notifications
You must be signed in to change notification settings - Fork 1
/
storage.js
85 lines (65 loc) · 1.77 KB
/
storage.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
const Datastore = require('nedb')
const crypto = require('crypto')
const SECOND = 1000
const HOUR = 60 * SECOND
const DAY = 24 * HOUR
const CompactionTimeout = 10 * SECOND
const sha256 = (x) =>
crypto.createHash('sha256').update(x, 'utf8').digest('hex')
const now = () => new Date().getTime()
class Storage {
constructor(filename = './storage.db', autoload = true) {
this._db = new Datastore({ filename, autoload })
}
async close() {
this._db.persistence.compactDatafile()
return new Promise((resolve) => {
this._db.on('compaction.done', () => {
this._db.removeAllListeners('compaction.done')
resolve()
})
setTimeout(() => {
resolve()
}, CompactionTimeout)
})
}
async isValid(username, addr, limit = 2, span = DAY) {
username = sha256(username)
addr = sha256(addr)
const totalUsername = await this._query(username, span)
const totalAddr = await this._query(addr, span)
if (totalUsername < limit && totalAddr < limit) {
return true
}
return false
}
async saveData(username, addr) {
username = sha256(username)
addr = sha256(addr)
await this._insert(username)
await this._insert(addr)
return true
}
async _insert(item) {
const timestamp = now()
return new Promise((resolve, reject) => {
this._db.insert({ item, timestamp }, (err) => {
if (err) reject(err)
resolve()
})
})
}
async _query(item, span) {
const timestamp = now()
const query = {
$and: [{ item }, { timestamp: { $gt: timestamp - span } }],
}
return new Promise((resolve, reject) => {
this._db.find(query, (err, docs) => {
if (err) reject()
resolve(docs.length)
})
})
}
}
module.exports = Storage