-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathutils.js
155 lines (141 loc) · 3.54 KB
/
utils.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
"use strict";
const assert = require('assert');
const fs = require('fs');
const statechanges = require('./static/js/statechanges.js');
function installGlobals() {
const globalFunctions = {
check: function(errorHandler, okHandler) {
return function(err, val) {
if (!err) {
okHandler(val);
} else {
errorHandler(err);
}
}
},
silentFail: function(okHandler) {
return function(err, val) {
if (!err) {
okHandler.call(global, val);
} else {
// not so silent right now
console.log('silentFail caught error:', err);
}
}
},
indices: function* (len) {
for (let i = 0; i < len; i++) {
yield i;
}
},
indicesReverse: function* (len) {
for (let i = len - 1; i >= 0; i--) {
yield i;
}
}
};
Object.keys(globalFunctions).forEach(function(functionName) {
global[functionName] = globalFunctions[functionName];
});
}
function parseCtcpMessage(str) {
const match = str.match(/^\u0001([^\s]+)(?: (.+))?\u0001$/);
if (match) {
return {command: match[1].toUpperCase(), args: (typeof match[2] === 'undefined' ? null : match[2])};
} else {
return null;
}
}
function toCtcp(command, args) {
let ret = String.fromCharCode(1);
ret += command.toUpperCase();
if (typeof args !== 'undefined') {
ret += ' ' + args;
}
ret += String.fromCharCode(1);
return ret;
}
// note: we only validate the nick!user@host format and not what characters can or cannot be in each
// on failure to match, we assume str is a server origin
function parseOrigin(str) {
const match = str.match(/^([^!]+?)!([^@]+?)@(.+?)$/);
if (match) {
return new ClientOrigin(match[1], match[2], match[3]);
} else {
return new ServerOrigin(str);
}
}
// Possible channel types: & # + ! . ~
function parseTarget(str) {
let match;
if (str.match(/^[#&+.~][^\s]{1,99}|![A-Z0-5]{5}[^\s]{1,94}$/)) {
return new ChannelTarget(str);
} else if (match = str.match(/^([a-z_\-\[\]\\^{}|`][a-z0-9_\-\[\]\\^{}|`]*)(?:@([^@]+))?$/i)) {
return new ClientTarget(match[1], match[2]);
} else {
return null;
}
}
function withParsedTarget(targetName, cb) {
const maybeTarget = parseTarget(targetName);
if (maybeTarget instanceof ChannelTarget ||
maybeTarget instanceof ClientTarget) {
cb(null, maybeTarget);
} else {
cb(new Error(`Failed to parse as a channel or client target: ${targetName}`));
}
}
function parseKeyEqValue(str) {
const eqPos = str.indexOf('=');
if (eqPos >= 0) {
return {
key: str.substring(0, eqPos),
val: str.substring(eqPos + 1)
}
} else {
return {
key: str,
val: null
}
}
}
function readJsonFile(filePath, cb) {
fs.readFile(filePath, check(cb, function(data) {
let err = null;
let config = null;
try {
config = JSON.parse(data);
} catch(e) {
err = e;
}
cb(err, config);
}));
}
function ensureRequiredFields(obj, fields) {
fields.forEach(function(field) {
if (!(field in obj)) {
throw new Error(`Missing required field: ${field}`)
}
});
}
function findFirst(arr, f) {
for (let val of arr) {
if (f(val)) {
return val;
}
}
return null;
}
exports.installGlobals = installGlobals;
exports.parseCtcpMessage = parseCtcpMessage;
exports.toCtcp = toCtcp;
exports.parseOrigin = parseOrigin;
exports.parseTarget = parseTarget;
exports.withParsedTarget = withParsedTarget;
exports.parseKeyEqValue = parseKeyEqValue;
exports.readJsonFile = readJsonFile;
exports.ensureRequiredFields = ensureRequiredFields;
exports.findFirst = findFirst;
// from statechanges
exports.equalsIgnoreCase = statechanges.utils.equalsIgnoreCase;
exports.setNotInChannel = statechanges.utils.setNotInChannel;