Skip to content
This repository was archived by the owner on Dec 10, 2022. It is now read-only.

Commit 8d507dd

Browse files
committed
Enhance the app to see multiple mentions in one message
Enabled the code to process multiple occurances of the ++/-- syntax in one message iteratively thus handling score updates for multiple recipients in one message. Changed the handler for selfPlus to be processed within the handlePlusMinus handler an simply not increment the score while providing the disapproving random message to the instigator.
1 parent 6fa326b commit 8d507dd

File tree

4 files changed

+161
-98
lines changed

4 files changed

+161
-98
lines changed

src/events.js

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,36 @@ const slack = require( './slack' ),
1717
const camelCase = require( 'lodash.camelcase' );
1818

1919
/**
20+
* Handles a plus or minus against a user, and then notifies the channel of the new score.
2021
* Handles an attempt by a user to 'self plus' themselves, which includes both logging the attempt
2122
* and letting the user know it wasn't successful.
2223
*
23-
* @param {object} user The ID of the user (Uxxxxxxxx) who tried to self plus.
24-
* @param {object} channel The ID of the channel (Cxxxxxxxx for public channels or Gxxxxxxxx for
25-
* private channels - aka groups) that the message was sent from.
26-
* @return {Promise} A Promise to send a Slack message back to the requesting channel.
27-
*/
28-
const handleSelfPlus = ( user, channel ) => {
29-
console.log( user + ' tried to alter their own score.' );
30-
const message = messages.getRandomMessage( operations.operations.SELF, user );
31-
return slack.sendMessage( message, channel );
32-
};
33-
34-
/**
35-
* Handles a plus or minus against a user, and then notifies the channel of the new score.
36-
*
37-
* @param {string} item The Slack user ID (if user) or name (if thing) of the item being
38-
* operated on.
39-
* @param {string} operation The mathematical operation performed on the item's score.
24+
* @param {object} mentions Array of parsed objects from a Slack message with objects containing
25+
* the Slack user ID (if user) or name (if thing) of the item being
26+
* operated on and the +/- operation performed on the item's score.
27+
* @param {object} user The ID of the user (Uxxxxxxxx) who sent the message.
4028
* @param {object} channel The ID of the channel (Cxxxxxxxx for public channels or Gxxxxxxxx for
4129
* private channels - aka groups) that the message was sent from.
4230
* @return {Promise} A Promise to send a Slack message back to the requesting channel after the
4331
* points have been updated.
4432
*/
45-
const handlePlusMinus = async( item, operation, channel ) => {
46-
const score = await points.updateScore( item, operation ),
47-
operationName = operations.getOperationName( operation ),
48-
message = messages.getRandomMessage( operationName, item, score );
33+
const handlePlusMinus = async( mentions, user, channel ) => {
34+
35+
const messageLines = [];
36+
for ( const mention of mentions ) {
37+
38+
// Handle self plus as an event avoiding incrementing the score
39+
if ( mention.item === user && '+' === mention.operation ) {
40+
console.log( user + ' tried to alter their own score.' );
41+
messageLines.push( messages.getRandomMessage( operations.operations.SELF, user ) );
42+
} else {
43+
const score = await points.updateScore( mention.item, mention.operation ),
44+
operationName = operations.getOperationName( mention.operation );
45+
messageLines.push( messages.getRandomMessage( operationName, mention.item, score ) );
46+
}
47+
}
4948

50-
return slack.sendMessage( message, channel );
49+
return slack.sendMessage( messageLines.join( '\n' ), channel );
5150
};
5251

5352
/**
@@ -122,20 +121,14 @@ const handlers = {
122121
message: ( event ) => {
123122

124123
// Extract the relevant data from the message text.
125-
const { item, operation } = helpers.extractPlusMinusEventData( event.text );
126-
127-
if ( ! item || ! operation ) {
128-
return false;
129-
}
124+
const mentions = helpers.extractPlusMinusEventData( event.text );
130125

131-
// Bail if the user is trying to ++ themselves...
132-
if ( item === event.user && '+' === operation ) {
133-
handleSelfPlus( event.user, event.channel );
126+
if ( ! mentions ) {
134127
return false;
135128
}
136129

137130
// Otherwise, let's go!
138-
return handlePlusMinus( item, operation, event.channel );
131+
return handlePlusMinus( mentions, event.user, event.channel );
139132

140133
}, // Message event.
141134

@@ -225,7 +218,6 @@ const handleEvent = ( event, request ) => {
225218
}; // HandleEvent.
226219

227220
module.exports = {
228-
handleSelfPlus,
229221
handlePlusMinus,
230222
sayThankyou,
231223
sendHelp,

src/helpers.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,22 +55,32 @@ const extractCommand = ( message, commands ) => {
5555
* We take the operation down to one character, and also support — due to iOS' replacement of --.
5656
*
5757
* @param {string} text The message text sent through in the event.
58-
* @returns {object} An object containing both the 'item' being referred to - either a Slack user
59-
* ID (eg. 'U12345678') or the name of a 'thing' (eg. 'NameOfThing'); and the
60-
* 'operation' being done on it - expressed as a valid mathematical operation
61-
* (i.e. + or -).
58+
* @returns {object} An array of objects containing both the 'item' being referred to - either a
59+
* Slack user ID (eg. 'U12345678') or the name of a 'thing' (eg. 'NameOfThing');
60+
* and the 'operation' being done on it - expressed as a valid mathematical
61+
* operation (i.e. + or -).
6262
*/
6363
const extractPlusMinusEventData = ( text ) => {
64-
const data = text.match( /@([A-Za-z0-9]+?)>?\s*(\+{2}|-{2}|{1})/ );
64+
const matchAll = /@([A-Za-z0-9]+?)>?\s*(\+{2}|-{2}|{1})/g;
65+
const matchOne = /@([A-Za-z0-9]+?)>?\s*(\+{2}|-{2}|{1})/;
6566

66-
if ( ! data ) {
67+
const matches = text.match( matchAll );
68+
69+
if ( null === matches ) {
6770
return false;
6871
}
6972

70-
return {
71-
item: data[1],
72-
operation: data[2].substring( 0, 1 ).replace( '—', '-' )
73-
};
73+
const data = [];
74+
for ( const match of matches ) {
75+
const parts = match.match( matchOne );
76+
data.push(
77+
{
78+
item: parts[1],
79+
operation: parts[2].substring( 0, 1 ).replace( '—', '-' )
80+
}
81+
);
82+
}
83+
return data;
7484

7585
}; // ExtractPlusMinusEventData.
7686

tests/events.js

Lines changed: 73 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,38 @@ beforeEach( () => {
3737
slack.sendMessage.mockClear();
3838
});
3939

40-
describe( 'handleSelfPlus', () => {
40+
describe( 'handlePlusMinus', () => {
4141

4242
const user = 'U12345678',
43-
channel = 'C12345678';
43+
item = 'SomeRandomThing',
44+
item2 = 'SomeOtherThing',
45+
channel = 'C12345678',
46+
score = 5;
47+
48+
/** @returns {integer} Returns a fake score. */
49+
const updateScoreMock = () => {
50+
return score;
51+
};
4452

4553
it( 'logs an attempt by a user to increment their own score', () => {
46-
events.handleSelfPlus( user, channel );
54+
const mentions = [
55+
{
56+
item: user,
57+
operation: '+'
58+
}
59+
];
60+
events.handlePlusMinus( mentions, user, channel );
4761
expect( console.log ).toHaveBeenCalledTimes( 1 );
4862
});
4963

5064
it( 'gets a message from the \'self plus\' collection', () => {
51-
events.handleSelfPlus( user, channel );
65+
const mentions = [
66+
{
67+
item: user,
68+
operation: '+'
69+
}
70+
];
71+
events.handlePlusMinus( mentions, user, channel );
5272

5373
expect( messages.getRandomMessage )
5474
.toHaveBeenCalledTimes( 1 )
@@ -62,26 +82,19 @@ describe( 'handleSelfPlus', () => {
6282
slack.sendMessage = jest.fn();
6383
slack.setSlackClient( slackClientMock );
6484

65-
events.handleSelfPlus( user, channel );
85+
const mentions = [
86+
{
87+
item: user,
88+
operation: '+'
89+
}
90+
];
91+
events.handlePlusMinus( mentions, user, channel );
6692

6793
expect( slack.sendMessage )
6894
.toHaveBeenCalledTimes( 1 )
6995
.toHaveBeenCalledWith( expect.stringContaining( user ), channel );
7096
});
7197

72-
});
73-
74-
describe( 'handlePlusMinus', () => {
75-
76-
const item = 'SomeRandomThing',
77-
channel = 'C12345678',
78-
score = 5;
79-
80-
/** @returns {integer} Returns a fake score. */
81-
const updateScoreMock = () => {
82-
return score;
83-
};
84-
8598
it( 'calls the score updater to update an item\'s score', () => {
8699
const slack = require( '../src/slack' ),
87100
points = require( '../src/points' ),
@@ -90,11 +103,24 @@ describe( 'handlePlusMinus', () => {
90103
slack.setSlackClient( slackClientMock );
91104
points.updateScore = jest.fn();
92105

93-
events.handlePlusMinus( item, '+', channel );
106+
const operation = '+';
107+
const mentions = [
108+
{
109+
item,
110+
operation
111+
},
112+
{
113+
item: item2,
114+
operation
115+
}
116+
];
117+
events.handlePlusMinus( mentions, user, channel ).then( () => {
118+
expect( points.updateScore )
119+
.toHaveBeenCalledTimes( 2 )
120+
.toHaveBeenNthCalledWith( 1, item, '+' )
121+
.toHaveBeenNthCalledWith( 2, item2, '+' );
122+
});
94123

95-
expect( points.updateScore )
96-
.toHaveBeenCalledTimes( 1 )
97-
.toHaveBeenCalledWith( item, '+' );
98124
});
99125

100126
it.each([ [ 'plus', '+' ], [ 'minus', '-' ] ])(
@@ -111,10 +137,21 @@ describe( 'handlePlusMinus', () => {
111137
points.updateScore = jest.fn( updateScoreMock );
112138
messages.getRandomMessage = jest.fn();
113139

114-
return events.handlePlusMinus( item, operation, channel ).then( () => {
140+
const mentions = [
141+
{
142+
item,
143+
operation
144+
},
145+
{
146+
item: item2,
147+
operation
148+
}
149+
];
150+
return events.handlePlusMinus( mentions, user, channel ).then( () => {
115151
expect( messages.getRandomMessage )
116-
.toHaveBeenCalledTimes( 1 )
117-
.toHaveBeenCalledWith( operationName, item, score );
152+
.toHaveBeenCalledTimes( 2 )
153+
.toHaveBeenNthCalledWith( 1, operationName, item, score )
154+
.toHaveBeenNthCalledWith( 2, operationName, item2, score );
118155
});
119156
}
120157
);
@@ -130,7 +167,17 @@ describe( 'handlePlusMinus', () => {
130167
points.updateScore = jest.fn();
131168
slack.sendMessage = jest.fn();
132169

133-
return events.handlePlusMinus( item, '+', channel ).then( () => {
170+
const mentions = [
171+
{
172+
item,
173+
operation: '+'
174+
},
175+
{
176+
item: item2,
177+
operation: '+'
178+
}
179+
];
180+
return events.handlePlusMinus( mentions, user, channel ).then( () => {
134181
expect( slack.sendMessage )
135182
.toHaveBeenCalledTimes( 1 )
136183
.toHaveBeenCalledWith( expect.stringContaining( item ), channel );
@@ -161,16 +208,6 @@ describe( 'handlers.message', () => {
161208
expect( handlers.message( event ) ).toBeFalse();
162209
});
163210

164-
it( 'returns false if a user trying to ++ themselves', () => {
165-
const event = {
166-
type: eventType,
167-
text: '<@U12345678>++',
168-
user: 'U12345678'
169-
};
170-
171-
expect( handlers.message( event ) ).toBeFalse();
172-
});
173-
174211
}); // HandleMessageEvent.
175212

176213
describe( 'handlers.appMention', () => {

tests/helpers.js

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -74,31 +74,53 @@ describe( 'extractPlusMinusEventData', () => {
7474
});
7575

7676
it( 'extracts a \'thing\' and operation from the start of a message', () => {
77-
expect( helpers.extractPlusMinusEventData( '@SomethingRandom++ that was awesome' ) ).toEqual({
78-
item: 'SomethingRandom',
79-
operation: '+'
80-
});
77+
expect( helpers.extractPlusMinusEventData( '@SomethingRandom++ that was awesome' ) ).toEqual([
78+
{
79+
item: 'SomethingRandom',
80+
operation: '+'
81+
}
82+
]);
8183
});
8284

8385
it( 'extracts a user and operation from the start of a message', () => {
84-
expect( helpers.extractPlusMinusEventData( '<@U87654321>++ that was awesome' ) ).toEqual({
85-
item: 'U87654321',
86-
operation: '+'
87-
});
86+
expect( helpers.extractPlusMinusEventData( '<@U87654321>++ that was awesome' ) ).toEqual([
87+
{
88+
item: 'U87654321',
89+
operation: '+'
90+
}
91+
]);
8892
});
8993

9094
it( 'extracts data in the middle of a message', () => {
91-
expect( helpers.extractPlusMinusEventData( 'Hey @SomethingRandom++ you\'re great' ) ).toEqual({
92-
item: 'SomethingRandom',
93-
operation: '+'
94-
});
95+
expect( helpers.extractPlusMinusEventData( 'Hey @SomethingRandom++ you\'re great' ) ).toEqual([
96+
{
97+
item: 'SomethingRandom',
98+
operation: '+'
99+
}
100+
]);
95101
});
96102

97103
it( 'extracts data at the end of a message', () => {
98-
expect( helpers.extractPlusMinusEventData( 'Awesome work @SomethingRandom++' ) ).toEqual({
99-
item: 'SomethingRandom',
100-
operation: '+'
101-
});
104+
expect( helpers.extractPlusMinusEventData( 'Awesome work @SomethingRandom++' ) ).toEqual([
105+
{
106+
item: 'SomethingRandom',
107+
operation: '+'
108+
}
109+
]);
110+
});
111+
112+
it( 'extracts multiple mentions in one message', () => {
113+
const multiMentions = 'Thing one @SomethingRandom++ and thing two @SomethingElse--';
114+
expect( helpers.extractPlusMinusEventData( multiMentions ) ).toEqual([
115+
{
116+
item: 'SomethingRandom',
117+
operation: '+'
118+
},
119+
{
120+
item: 'SomethingElse',
121+
operation: '-'
122+
}
123+
]);
102124
});
103125

104126
const itemsToMatch = [
@@ -149,10 +171,12 @@ describe( 'extractPlusMinusEventData', () => {
149171

150172
it( testName, () => {
151173
const result = helpers.extractPlusMinusEventData( messageText );
152-
expect( result ).toEqual({
153-
item: item.expected,
154-
operation: operation.expected
155-
});
174+
expect( result ).toEqual([
175+
{
176+
item: item.expected,
177+
operation: operation.expected
178+
}
179+
]);
156180
});
157181

158182
} // For iterator.

0 commit comments

Comments
 (0)