-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
executable file
·174 lines (151 loc) · 5.91 KB
/
index.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
174
const { EventEmitter } = require("events")
const sqlite = require("sqlite")
const DBNAME = "farmer_ip_geo_asn"
module.exports = class extends EventEmitter {
constructor(){
super()
this.init()
}
// async farmer
async init(){
const Reader = require("@maxmind/geoip2-node").Reader;
this._ipasn = await Reader.open(__dirname + "/db/ipasn.mmdb", {})
this._ipgeo = await Reader.open(__dirname + "/db/ipgeo.mmdb", {})
this._sqlite = await sqlite.open(__dirname + "/db/farmerip.sqlite", {cache: true})
await this.initDB()
this.emit("load", this)
}
async initDB(){
await this._sqlite.all(`
CREATE TABLE IF NOT EXISTS ${DBNAME} (
farmerId TEXT PRIMARY KEY,
farmerIp TEXT NOT NULL,
farmerIpIsIpv6 BOOLEAN DEFAULT 0,
farmerAsn INTERGER DEFAULT 0,
farmerAsnName TEXT,
farmerCity INTERGER DEFAULT 0,
farmerCityName TEXT,
farmerCountry INTERGER DEFAULT 0,
farmerCountryName TEXT,
farmerEtc TEXT
)`)
}
async addFarmer(farmerId, farmerIp, farmerEtc = null){
const farmerIpIsIpv6 = this.isIpv6(farmerIp)
let asn,city,farmerAsn,farmerAsnName,farmerCity,farmerCityName,farmerCountry,farmerCountryName
try{
asn = await this._ipasn.asn(farmerIp)
farmerAsn = asn.autonomousSystemNumber || 0
farmerAsnName = asn.autonomousSystemOrganization
}catch(e){
farmerAsn = 0
farmerAsnName = JSON.stringify({})
}
try{
city = await this._ipgeo.city(farmerIp)
farmerCity = city.city.geonameId || 0
farmerCountry = city.country.geonameId || 0
farmerCityName = JSON.stringify(city.city)
farmerCountryName = JSON.stringify(city.country)
}catch(e){
farmerCity = 0
farmerCountry = 0
farmerCityName = JSON.stringify({})
farmerCountryName = JSON.stringify({})
}
await this._sqlite.all(`
REPLACE INTO ${DBNAME}
(farmerId, farmerIp, farmerIpIsIpv6, farmerAsn, farmerAsnName, farmerCity, farmerCityName, farmerCountry, farmerCountryName, farmerEtc)
VALUES
('${farmerId}', '${farmerIp}', ${farmerIpIsIpv6}, '${farmerAsn}', '${farmerAsnName}', '${farmerCity}', '${farmerCityName}', '${farmerCountry}', '${farmerCountryName}', '${farmerEtc}')
`)
}
async getNeighbor(userIp, number, SELECT_COLUMN = "farmerIp, farmerId"){
const userIpIsIpv6 = this.isIpv6(userIp)
let asn,city,userAsn,userCity,userCountry
try{
asn = await this._ipasn.asn(userIp)
userAsn = asn.autonomousSystemNumber || 0
}catch(e){
userAsn = 0
}
try{
city = await this._ipgeo.city(userIp)
userCity = city.city.geonameId || 0
userCountry = city.country.geonameId || 0
}catch(e){
userCity = 0
userCountry = 0
}
const query = []
const queryExactly = []
const queryCity = []
const queryAsn = []
const queryAsnOrCity = []
const queryCountry = []
const queryAll = []
const data = {
farmerEnough: true,query, queryExactly, queryCity, queryAsn, queryAsnOrCity, queryCountry, queryAll
}
let leftNumber = number
queryExactly.push(...await this._sqlite.all(`
SELECT ${SELECT_COLUMN} FROM ${DBNAME}
WHERE (farmerAsn = '${userAsn}' AND farmerCity = '${userCity}')
AND farmerIpIsIpv6 = ${userIpIsIpv6}
ORDER BY random()
LIMIT '${number}'
`))
query.push(...queryExactly)
leftNumber = number - queryExactly.length
if (leftNumber === 0) return data
queryCity.push(...await this._sqlite.all(`
SELECT ${SELECT_COLUMN} FROM ${DBNAME}
WHERE (farmerAsn != '${userAsn}' AND farmerCity = '${userCity}')
AND farmerIpIsIpv6 = ${userIpIsIpv6}
ORDER BY random()
LIMIT '${leftNumber}'
`))
queryAsn.push(...await this._sqlite.all(`
SELECT ${SELECT_COLUMN} FROM ${DBNAME}
WHERE (farmerAsn = '${userAsn}' AND farmerCity != '${userCity}')
AND farmerIpIsIpv6 = ${userIpIsIpv6}
ORDER BY random()
LIMIT '${leftNumber}'
`))
queryAsnOrCity.push(...await this._sqlite.all(`
SELECT ${SELECT_COLUMN} FROM ${DBNAME}
WHERE ((farmerAsn = '${userAsn}' AND farmerCity != '${userCity}') OR (farmerAsn != '${userAsn}' AND farmerCity = '${userCity}'))
AND farmerIpIsIpv6 = ${userIpIsIpv6}
ORDER BY random()
LIMIT '${leftNumber}'
`))
leftNumber -= queryAsnOrCity.length
query.push(...queryAsnOrCity)
if (leftNumber === 0) return data
queryCountry.push(...await this._sqlite.all(`
SELECT ${SELECT_COLUMN} FROM ${DBNAME}
WHERE (farmerAsn != '${userAsn}' AND farmerCity != '${userCity}' AND farmerCountry = '${userCountry}')
AND farmerIpIsIpv6 = ${userIpIsIpv6}
ORDER BY random()
LIMIT '${leftNumber}'
`))
leftNumber -= queryCountry.length
query.push(...queryCountry)
if (leftNumber === 0) return data
queryAll.push(...await this._sqlite.all(`
SELECT ${SELECT_COLUMN} FROM ${DBNAME}
WHERE (farmerAsn != '${userAsn}' AND farmerCity != '${userCity}' AND farmerCountry != '${userCountry}')
AND farmerIpIsIpv6 = ${userIpIsIpv6}
ORDER BY random()
LIMIT '${leftNumber}'
`))
leftNumber -= queryAll.length
query.push(...queryAll)
if (leftNumber === 0) return data
data.farmerEnough = false
return data
}
isIpv6(ip){
return !/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d+)?$/.test(ip)
}
}