Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0752b48

Browse files
committed
fix stateful regexp by removing continued search
1 parent 873e6f0 commit 0752b48

File tree

4 files changed

+90
-57
lines changed

4 files changed

+90
-57
lines changed

handler.js

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,20 @@ function destination(message) {
3232
}
3333

3434
function handler(config, data, message) {
35-
try {
36-
if(mine(content(message), config.prefix) &&
37-
config.whitelisted.indexOf(roomName(message)) != -1) {
38-
const processor = reload(config.processor)
39-
if(!data.tickets) {
40-
data.tickets = processor.load(data.store)
41-
}
42-
const reply = processor.process(data.tickets, {
43-
content: cleanContent(config.prefix, message),
44-
prefix: config.prefix,
45-
roomName: roomName(message),
46-
userName: userName(message),
47-
})
48-
processor.store(config.store, data.tickets)
49-
destination(message).say(reply)
35+
if(mine(content(message), config.prefix) &&
36+
config.whitelisted.indexOf(roomName(message)) != -1) {
37+
const processor = reload(config.processor)
38+
if(!(data.tickets instanceof Object)) {
39+
data.tickets = processor.load(config.store)
5040
}
51-
} catch(err) {
52-
destination(message).say(err)
41+
const reply = processor.process(data.tickets, {
42+
content: cleanContent(config.prefix, message),
43+
prefix: config.prefix,
44+
roomName: roomName(message),
45+
userName: userName(message),
46+
})
47+
processor.store(config.store, data.tickets)
48+
destination(message).say(reply)
5349
}
5450
}
5551

support.js

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
const fs = require('fs')
44
const path = require('path')
55

6+
function TicketError(message) {
7+
this.name = 'TicketError';
8+
this.message = message || 'Ticketing error';
9+
this.stack = (new Error()).stack;
10+
}
11+
TicketError.prototype = Object.create(Error.prototype);
12+
TicketError.prototype.constructor = TicketError;
13+
614
const Sample = {
715
assignee: null,
816
closed: null,
@@ -17,76 +25,68 @@ const Sample = {
1725
const actions = [
1826
{
1927
action: (_tickets, _message) => 'DEFAULT ACTION',
20-
regexp: /^$/gi,
28+
regexp: /^$/i,
2129
reply: (message, _output) => `Yes ${message.userName}?`,
2230
},
2331
{
2432
action: (_tickets, _message) => help(),
25-
regexp: /help/gi,
33+
regexp: /help/i,
2634
reply: (message, output) => `\n${output}`,
2735
},
2836
{
2937
action: (tickets, _message, id) => closeTicket(tickets, id),
30-
regexp: /close #([0-9]*)/gi,
38+
regexp: /close #([0-9]*)/i,
3139
reply: (message, output) => `ticket #${output.id} is closed`,
3240
},
3341
{
3442
action: (tickets, message, content) =>
3543
openTicket(tickets, message, content),
36-
regexp: /please (.*)/gi,
44+
regexp: /please (.*)/i,
3745
reply: (message, output) => `will ${output.content} (ticket #${output.id})`,
3846
},
3947
{
4048
action: (tickets, _message, id) => findTicket(tickets, id),
41-
regexp: /show #([0-9]*)/gi,
49+
regexp: /show #([0-9]*)/i,
4250
reply: (message, output) => showTicket(output),
4351
},
4452
{
4553
action: (tickets, message, id) => assign(tickets, id, message.userName),
46-
regexp: /take #([0-9]*)/gi,
54+
regexp: /take #([0-9]*)/i,
4755
reply: (message, output) => `ticket #${output.id} is assigned to ${output.assignee}`,
4856
},
4957
{
5058
/* eslint-disable max-params */
5159
action: (tickets, _message, id, assignee) => assign(tickets, id, assignee),
52-
regexp: /assign #([0-9]*) to (\w*)/gi,
60+
regexp: /assign #([0-9]*) to (\w*)/i,
5361
reply: (message, output) => `ticket #${output.id} is assigned to ${output.assignee}`,
5462
},
5563
{
5664
action: (tickets, _message) => tickets,
57-
regexp: /debug/gi,
65+
regexp: /debug/i,
5866
reply: (message, output) => JSON.stringify(output, null, 4),
5967
},
6068
{
6169
action: (tickets, _message) => tickets,
62-
regexp: /todo/gi,
70+
regexp: /todo/i,
6371
reply: (message, output) => showTickets(output, ['open']),
6472
},
6573
{
6674
action: (tickets, _message) => tickets,
67-
regexp: /history/gi,
75+
regexp: /history/i,
6876
reply: (message, output) => showTickets(output, ['open', 'closed']),
6977
},
7078
{
7179
action: (tickets, _message) => forget(tickets),
72-
regexp: /forget it/gi,
80+
regexp: /forget it/i,
7381
reply: (message, output) => `deleted ${output} tickets`,
7482
},
7583
{
7684
action: (tickets, _message, type) => gimme(type),
77-
regexp: /gimme\s*a*n*\s*(\w*)/gi,
85+
regexp: /gimme\s*a*n*\s*(\w*)/i,
7886
reply: (message, output) => `${message.userName} ${output[0].toLowerCase()}${output.substr(1)}`,
7987
},
8088
]
8189

82-
function TicketError(message) {
83-
this.name = 'TicketError';
84-
this.message = message || 'Ticketing error';
85-
this.stack = (new Error()).stack;
86-
}
87-
TicketError.prototype = Object.create(Error.prototype);
88-
TicketError.prototype.constructor = TicketError;
89-
9090
function createTicket() {
9191
return JSON.parse(JSON.stringify(Sample))
9292
}
@@ -169,17 +169,22 @@ function getRandomInt(min, max) {
169169
var sources = {}
170170

171171
function gimme(type) {
172+
const typePath = path.basename(`${type}.txt`)
173+
/* eslint-disable no-sync */
174+
if(!fs.existsSync(typePath)) {
175+
throw new TicketError(`I don't know how to give you ${type}!`)
176+
}
172177
if(!sources[type]) {
173178
/* eslint-disable no-sync */
174-
const content = fs.readFileSync(path.basename(`${type}.txt`))
179+
const content = fs.readFileSync(typePath)
175180
sources[type] = content.toString().split('\n')
176181
}
177182
const saying = sources[type][getRandomInt(0, sources[type].length)]
178183
return saying
179184
}
180185

181186
/**
182-
* Callback for find.
187+
* Callback for Array.find.
183188
* @param action action object
184189
* @this object with content and result
185190
* @returns true if match regexp, false otherwise
@@ -201,14 +206,18 @@ function process(tickets, message) {
201206
result: null
202207
}
203208
const action = actions.find(searchRegexp, findParams)
209+
204210
var reply;
205211
if(action) {
206-
var output = action.action(tickets, message, ...findParams.result)
207-
// If(!(output instanceof Object) && !output) {
208-
// Reply = `${JSON.stringify(action)} did not return any output`
209-
// } else {
212+
try {
213+
var output = action.action(tickets, message, ...findParams.result)
210214
reply = `${action.reply.bind(output)(message, output)}`
211-
// }
215+
} catch(e) {
216+
if(e instanceof TicketError) {
217+
return e.message
218+
}
219+
throw e
220+
}
212221
} else {
213222
reply = `I don't understand: ${message.content}, can you try again?`
214223
}
@@ -227,16 +236,25 @@ function store(storePath, tickets) {
227236
}
228237

229238
function load(storePath) {
230-
try {
239+
/* eslint-disable no-sync */
240+
if(fs.existsSync(storePath)) {
231241
/* eslint-disable no-sync */
232-
const datastore = fs.readFileSync(storePath)
233-
return JSON.parse(datastore)
234-
} catch(e) {
235-
return createTickets()
242+
const datastore = fs.readFileSync(storePath).toString()
243+
try {
244+
return JSON.parse(datastore)
245+
} catch(e) {
246+
if(e instanceof SyntaxError) {
247+
throw new TicketError(`invalid content of file: ${storePath}`)
248+
} else {
249+
throw e
250+
}
251+
}
236252
}
253+
return createTickets()
237254
}
238255

239256
module.exports = {
257+
TicketError,
240258
createTickets,
241259
load,
242260
openTicket,

test/handler_test.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict'
22

33
const handler = require('../handler')
4-
const assert = require('assert')
4+
const assert = require('chai').assert
55
const tmp = require('tmp');
66

77
/* eslint-disable max-params */
@@ -19,7 +19,8 @@ function createWeChatyMessage(fromName, roomTopic, content, say) {
1919
}
2020
}
2121

22-
const TEST_FILE = tmp.fileSync().name
22+
/* eslint-disable no-sync */
23+
const TEST_FILE = tmp.tmpNameSync()
2324

2425
const config = {
2526
'management': 'Agora - management',
@@ -33,17 +34,27 @@ const config = {
3334

3435

3536
describe('handler', function() {
36-
it('reloads if file is updated', function(done) {
37+
it('handles multiple class and storage', function() {
3738
const data = {}
38-
function say(message) {
39-
assert.equal(message, '#candra: will add ticket (ticket #1)')
40-
done()
39+
var sayValue = null
40+
function say(msg) {
41+
sayValue = msg
4142
}
4243
const message = createWeChatyMessage(
4344
'Ricky',
4445
'test room',
4546
'candra please add ticket',
4647
say)
48+
49+
// First ticket
50+
handler(config, data, message)
51+
assert.equal(sayValue, '#candra: will add ticket (ticket #1)')
52+
assert.instanceOf(data.tickets['1'], Object)
53+
54+
// Second ticket
4755
handler(config, data, message)
56+
assert.equal(sayValue, '#candra: will add ticket (ticket #2)')
57+
assert.equal(data.tickets.lastId, 2)
58+
assert.instanceOf(data.tickets['2'], Object)
4859
})
4960
})

test/support_test.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const support = require('../support')
44
const assert = require('chai').assert
5+
const tmp = require('tmp');
56

67
const sample = {
78
content: 'please get markers',
@@ -33,6 +34,8 @@ function message(content) {
3334
return msg
3435
}
3536

37+
const TEST_FILE = tmp.fileSync().name
38+
3639
describe('support', function() {
3740
it('ping', function() {
3841
const reply = support.process(tickets, message(''))
@@ -67,11 +70,16 @@ describe('support', function() {
6770

6871
it('gimme a compliment', function() {
6972
const reply = support.process(tickets, message('gimme a compliment'))
70-
assert.equal(reply.substr(-1, 1), '.')
73+
assert.match(reply, /[\.!\?]$/)
7174
})
7275

7376
it('gimme something that does not exist', function() {
7477
const reply = support.process(tickets, message('gimme a unknown'))
75-
assert.isTrue(reply.endsWith('can you try again?'))
78+
assert.equal(reply, "I don't know how to give you unknown!")
79+
})
80+
81+
it('load and store working', function() {
82+
support.store(TEST_FILE, {var: 4})
83+
assert.equal(support.load(TEST_FILE).var, 4)
7684
})
7785
})

0 commit comments

Comments
 (0)