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

Commit 72cbdfe

Browse files
committed
Enhance the app to see multiple mentions in one message
1 parent 1998cde commit 72cbdfe

File tree

4 files changed

+93
-85
lines changed

4 files changed

+93
-85
lines changed

src/events.js

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,35 @@ 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 mathematical 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+
var messageLines = [];
36+
for (const mention of mentions) {
37+
// Handle self plus as an event avoiding incrementing the score
38+
if ( mention.item === user && '+' === mention.operation ) {
39+
console.log( user + ' tried to alter their own score.' );
40+
messageLines.push(messages.getRandomMessage( operations.operations.SELF, user ));
41+
} else {
42+
const score = await points.updateScore( mention.item, mention.operation ),
43+
operationName = operations.getOperationName( mention.operation );
44+
messageLines.push(messages.getRandomMessage( operationName, mention.item, score ));
45+
}
46+
}
4947

50-
return slack.sendMessage( message, channel );
48+
return slack.sendMessage( messageLines.join("\n"), channel );
5149
};
5250

5351
/**
@@ -122,20 +120,14 @@ const handlers = {
122120
message: ( event ) => {
123121

124122
// 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-
}
123+
const mentions = helpers.extractPlusMinusEventData( event.text );
130124

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

137129
// Otherwise, let's go!
138-
return handlePlusMinus( item, operation, event.channel );
130+
return handlePlusMinus( mentions, event.user, event.channel );
139131

140132
}, // Message event.
141133

@@ -225,7 +217,6 @@ const handleEvent = ( event, request ) => {
225217
}; // HandleEvent.
226218

227219
module.exports = {
228-
handleSelfPlus,
229220
handlePlusMinus,
230221
sayThankyou,
231222
sendHelp,

src/helpers.js

Lines changed: 17 additions & 7 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
58+
* @returns {object} An array of objects containing both the 'item' being referred to - either a Slack user
5959
* ID (eg. 'U12345678') or the name of a 'thing' (eg. 'NameOfThing'); and the
6060
* 'operation' being done on it - expressed as a valid mathematical operation
6161
* (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 ( matches == null ) {
6770
return false;
6871
}
6972

70-
return {
71-
item: data[1],
72-
operation: data[2].substring( 0, 1 ).replace( '—', '-' )
73-
};
73+
var 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: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,28 @@ 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 = [ { item: user, operation: '+' } ];
55+
events.handlePlusMinus( mentions, user, channel );
4756
expect( console.log ).toHaveBeenCalledTimes( 1 );
4857
});
4958

5059
it( 'gets a message from the \'self plus\' collection', () => {
51-
events.handleSelfPlus( user, channel );
60+
const mentions = [ { item: user, operation: '+' } ];
61+
events.handlePlusMinus( mentions, user, channel );
5262

5363
expect( messages.getRandomMessage )
5464
.toHaveBeenCalledTimes( 1 )
@@ -62,26 +72,14 @@ describe( 'handleSelfPlus', () => {
6272
slack.sendMessage = jest.fn();
6373
slack.setSlackClient( slackClientMock );
6474

65-
events.handleSelfPlus( user, channel );
75+
const mentions = [ { item: user, operation: '+' } ];
76+
events.handlePlusMinus( mentions, user, channel );
6677

6778
expect( slack.sendMessage )
6879
.toHaveBeenCalledTimes( 1 )
6980
.toHaveBeenCalledWith( expect.stringContaining( user ), channel );
7081
});
7182

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-
8583
it( 'calls the score updater to update an item\'s score', () => {
8684
const slack = require( '../src/slack' ),
8785
points = require( '../src/points' ),
@@ -90,11 +88,14 @@ describe( 'handlePlusMinus', () => {
9088
slack.setSlackClient( slackClientMock );
9189
points.updateScore = jest.fn();
9290

93-
events.handlePlusMinus( item, '+', channel );
91+
const mentions = [ { item: item, operation: '+' }, { item: item2, operation: '+' } ];
92+
events.handlePlusMinus( mentions, user, channel ).then( () => {
93+
expect( points.updateScore )
94+
.toHaveBeenCalledTimes( 2 )
95+
.toHaveBeenNthCalledWith( 1, item, '+' )
96+
.toHaveBeenNthCalledWith( 2, item2, '+' );
97+
});
9498

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

100101
it.each([ [ 'plus', '+' ], [ 'minus', '-' ] ])(
@@ -111,10 +112,12 @@ describe( 'handlePlusMinus', () => {
111112
points.updateScore = jest.fn( updateScoreMock );
112113
messages.getRandomMessage = jest.fn();
113114

114-
return events.handlePlusMinus( item, operation, channel ).then( () => {
115+
const mentions = [ { item: item, operation: operation }, { item: item2, operation: operation } ];
116+
return events.handlePlusMinus( mentions, user, channel ).then( () => {
115117
expect( messages.getRandomMessage )
116-
.toHaveBeenCalledTimes( 1 )
117-
.toHaveBeenCalledWith( operationName, item, score );
118+
.toHaveBeenCalledTimes( 2 )
119+
.toHaveBeenNthCalledWith( 1, operationName, item, score )
120+
.toHaveBeenNthCalledWith( 2, operationName, item2, score );
118121
});
119122
}
120123
);
@@ -130,7 +133,8 @@ describe( 'handlePlusMinus', () => {
130133
points.updateScore = jest.fn();
131134
slack.sendMessage = jest.fn();
132135

133-
return events.handlePlusMinus( item, '+', channel ).then( () => {
136+
const mentions = [ { item: item, operation: '+' }, { item: item2, operation: '+' } ]
137+
return events.handlePlusMinus( mentions, user, channel ).then( () => {
134138
expect( slack.sendMessage )
135139
.toHaveBeenCalledTimes( 1 )
136140
.toHaveBeenCalledWith( expect.stringContaining( item ), channel );
@@ -161,16 +165,6 @@ describe( 'handlers.message', () => {
161165
expect( handlers.message( event ) ).toBeFalse();
162166
});
163167

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-
174168
}); // HandleMessageEvent.
175169

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

tests/helpers.js

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,31 +74,44 @@ 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({
77+
expect( helpers.extractPlusMinusEventData( '@SomethingRandom++ that was awesome' ) ).toEqual([{
7878
item: 'SomethingRandom',
7979
operation: '+'
80-
});
80+
}]);
8181
});
8282

8383
it( 'extracts a user and operation from the start of a message', () => {
84-
expect( helpers.extractPlusMinusEventData( '<@U87654321>++ that was awesome' ) ).toEqual({
84+
expect( helpers.extractPlusMinusEventData( '<@U87654321>++ that was awesome' ) ).toEqual([{
8585
item: 'U87654321',
8686
operation: '+'
87-
});
87+
}]);
8888
});
8989

9090
it( 'extracts data in the middle of a message', () => {
91-
expect( helpers.extractPlusMinusEventData( 'Hey @SomethingRandom++ you\'re great' ) ).toEqual({
91+
expect( helpers.extractPlusMinusEventData( 'Hey @SomethingRandom++ you\'re great' ) ).toEqual([{
9292
item: 'SomethingRandom',
9393
operation: '+'
94-
});
94+
}]);
9595
});
9696

9797
it( 'extracts data at the end of a message', () => {
98-
expect( helpers.extractPlusMinusEventData( 'Awesome work @SomethingRandom++' ) ).toEqual({
98+
expect( helpers.extractPlusMinusEventData( 'Awesome work @SomethingRandom++' ) ).toEqual([{
9999
item: 'SomethingRandom',
100100
operation: '+'
101-
});
101+
}]);
102+
});
103+
104+
it( 'extracts multiple mentions in one message', () => {
105+
expect( helpers.extractPlusMinusEventData( 'Thing one @SomethingRandom++ and thing two @SomethingElse--' ) ).toEqual([
106+
{
107+
item: 'SomethingRandom',
108+
operation: '+'
109+
},
110+
{
111+
item: 'SomethingElse',
112+
operation: '-'
113+
}
114+
]);
102115
});
103116

104117
const itemsToMatch = [
@@ -149,10 +162,10 @@ describe( 'extractPlusMinusEventData', () => {
149162

150163
it( testName, () => {
151164
const result = helpers.extractPlusMinusEventData( messageText );
152-
expect( result ).toEqual({
165+
expect( result ).toEqual([{
153166
item: item.expected,
154167
operation: operation.expected
155-
});
168+
}]);
156169
});
157170

158171
} // For iterator.

0 commit comments

Comments
 (0)