-
Notifications
You must be signed in to change notification settings - Fork 0
/
common.mjs
235 lines (190 loc) · 6.35 KB
/
common.mjs
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/**
* 公用方法
*/
import fs from 'node:fs';
import { readdir, readFile, appendFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { Buffer } from 'node:buffer';
import md5 from 'md5';
class Common {
//构造函数,设置默认配置
constructor() {
this.configDir = resolve('conf/');
}
getTimestamp() {
return Math.floor(Date.now());
}
getTimestampInSeconds() {
return Math.floor(Date.now() / 1000);
}
getLocalTimeString(locales, timezone) {
if (typeof(locales) == 'undefined' || !locales) {
locales = 'zh-Hans-CN';
}
if (typeof(timezone) == 'undefined' || !timezone) {
timezone = 'Asia/Shanghai';
}
let date = new Date();
let option = {"timeZone": timezone};
return date.toLocaleString(locales, option);
}
sortDict(obj) { //dict按key排序
return Object.keys(obj).sort().reduce(function(result, key) {
result[key] = obj[key];
return result;
}, {});
}
sign(params, token) { //对参数做MD5签名
return md5( JSON.stringify(this.sortDict(params)) + token );
}
//从conf/目录读取配置文件内容
async getConfigFromJsonFile(filename) {
let data = null;
let filePath = this.configDir + `/${filename}`;
if (fs.existsSync(filePath)) {
try {
const contents = await readFile(filePath, { encoding: 'utf8' });
if (contents) {
data = JSON.parse(contents);
}
} catch (err) {
console.error(`[FAILED] get config content from %s failed, error: %s`, filePath, err.message);
}
}else {
console.error("[ERROR] file %s not exist.", filePath);
}
return data;
}
//判断语言代码是否符合国际标准
isIosLangCode(lang) {
return /^[a-z]{2}$/i.test(lang);
}
//判断国家代码是否符合国际标准
isIosCountryCode(country) {
return /^[a-z]{2}$/i.test(country);
}
//判断爬虫状态代码是否正确
isBotStatus(status) {
const codes = [
"idle",
"busy"
];
return codes.findIndex((item) => item == status) > -1;
}
//判断是否单位为毫秒的时间戳
isTimestamp(timestamp) {
try {
timestamp = parseInt(timestamp);
}catch(err) {
console.error('Timestamp %s is not a number!', timestamp);
}
return typeof(timestamp) == 'number' && /^1[0-9]{12}$/.test(timestamp);
}
//判断是否单位为秒的时间戳
isTimestampInSeconds(timestamp) {
try {
timestamp = parseInt(timestamp);
}catch(err) {
console.error('Timestamp %s is not a number!', timestamp);
}
return typeof(timestamp) == 'number' && /^1[0-9]{9}$/.test(timestamp);
}
//检查爬虫名字是否符合标准:6 - 32位字母和下划线的组合
isBotNameOk(bot_name) {
return /^\w{6,32}$/i.test(bot_name);
}
//检查爬虫支持的平台是否符合标准:用英文逗号间隔的最长3 - 100个字符的英文字符串
isPlatformsOk(platforms) {
return /^[\w,]{3,100}$/i.test(platforms);
}
//检查爬虫支持的合约是否符合标准:用英文逗号间隔的最长3 - 100个字符的英文字符串
isContractsOk(contracts) {
return /^[\w,]{3,100}$/i.test(contracts);
}
//检查爬虫提供方联系方式是否符合标准:6 - 50个非空白字符
isContactOk(contact) {
return /^\S{6,50}$/i.test(contact);
}
//检查url是否符合要求
isUrlOk(url) {
return /^http(s)?:\/\/[\w\-\.\/:\?\=]{6,100}$/i.test(url);
}
//检查uuid是否符合要求:6-32位的英文字符串
isUuidOk(uuid) {
return /^\w{6,32}$/i.test(uuid);
}
//检查task_id是否符合要求:uuid_timestamp
isTaskIdOk(task_id) {
let arr = task_id.split('_');
if (arr.length < 2) {
return false;
}
let uuid = arr[0];
let timestamp = arr[arr.length - 1];
if (arr.length > 2) {
uuid = task_id.replace(`_${timestamp}`, '');
}
return this.isUuidOk(uuid) && this.isTimestamp(timestamp);
}
//检查英文名等参数是否符合标准:5 - 32位字母和下划线的组合
isNormalName(name, minLength, maxLength) {
if (typeof(minLength) == 'undefined') {minLength = 6;}
if (typeof(maxLength) == 'undefined') {maxLength = 32;}
return /^\w+$/i.test(name) && name.length >= minLength && name.length <= maxLength;
}
getLogArguments() {
let args = [];
let localTime = this.getLocalTimeString('zh-Hans-CN', 'Asia/Shanghai');
if (arguments[0]) {
let logFormat = `[%s] ${arguments[0]}`;
args.push(logFormat);
args.push(localTime);
}
if (arguments && arguments.length > 1) {
for (const index in arguments) {
if (index > 0) {
args.push(arguments[index]);
}
}
}
return args;
}
log() {
let args = this.getLogArguments.apply(this, arguments);
console.log.apply(this, args);
return args;
}
info() {
let args = this.getLogArguments.apply(this, arguments);
console.info.apply(this, args);
return args;
}
warn() {
let args = this.getLogArguments.apply(this, arguments);
console.warn.apply(this, args);
return args;
}
error() {
let args = this.getLogArguments.apply(this, arguments);
console.error.apply(this, args);
return args;
}
byteSize(str) {
return Buffer.byteLength(str, 'utf8');
}
//保存log到指定文件
async saveLog(filePath, content) {
let saved = false;
try {
let saveRes = await appendFile(filePath, content);
if (saveRes == undefined) {
saved = true;
}
} catch (err) {
console.error(`Log save to %s failed: %s`, filePath, err.message);
}
return saved;
}
}
let commonFuns = new Common();
export default commonFuns;