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

Commit

Permalink
Use the Slack bot's configured name for the web template title
Browse files Browse the repository at this point in the history
  • Loading branch information
tdmalone committed Aug 19, 2018
1 parent 5710667 commit 94d43ba
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const handleGet = async( request, response ) => {
// TODO: This should probably be split out into a separate function of sorts, like handlePost.
case '/leaderboard':
if ( helpers.isTimeBasedTokenStillValid( request.query.token, request.query.ts ) ) {
response.send( await leaderboard.getForWeb() );
response.send( await leaderboard.getForWeb( request ) );
} else {
response
.status( HTTP_403 )
Expand Down
6 changes: 3 additions & 3 deletions src/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ const sayThankyou = ( event ) => {
*/
const sendHelp = ( event ) => {

const botUserId = event.text.match( /<@(U[A-Z0-9]{8})>/ )[1];
const botUserID = helpers.extractUserID( event.text );

const message = (
'Sure, here\'s what I can do:\n\n' +
'• `@Someone++`: Add points to a user or a thing\n' +
'• `@Someone--`: Subtract points from a user or a thing\n' +
'• `<@' + botUserId + '> leaderboard`: Display the leaderboard\n' +
'• `<@' + botUserId + '> help`: Display this message\n\n' +
'• `<@' + botUserID + '> leaderboard`: Display the leaderboard\n' +
'• `<@' + botUserID + '> help`: Display this message\n\n' +
'You\'ll need to invite me to a channel before I can recognise ' +
'`++` and `--` commands in it.\n\n' +
'If you\'re a developer, you can teach me new things! ' +
Expand Down
30 changes: 26 additions & 4 deletions src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

'use strict';

const slack = require( './slack' );

const fs = require( 'fs' ),
crypto = require( 'crypto' ),
handlebars = require( 'handlebars' );
Expand Down Expand Up @@ -70,6 +72,19 @@ const extractPlusMinusEventData = ( text ) => {
operation: data[2].substring( 0, 1 ).replace( '—', '-' )
};

}; // ExtractPlusMinusEventData.

/**
* Extracts a valid Slack user ID from a string of text.
*
* @param {string} text The string in question.
* @returns {string} The first matched Slack user ID in the string, or an empty string if a match
* could not be found.
* @see ::isUser
*/
const extractUserID = ( text ) => {
const match = text.match( /U[A-Z0-9]{8}/ );
return match ? match[0] : '';
};

/**
Expand Down Expand Up @@ -144,6 +159,7 @@ const isTimeBasedTokenStillValid = ( token, ts ) => {
*
* @param {string} item The string in question.
* @returns {Boolean} Whether or not the string is a Slack user ID.
* @see ::extractUserID()
*/
const isUser = ( item ) => {
return item.match( /U[A-Z0-9]{8}/ ) ? true : false;
Expand Down Expand Up @@ -173,10 +189,13 @@ const maybeLinkItem = ( item ) => {
* standard variables referenced in the header and footer, such as
* 'title'. See the contents of ./html/ for more details. Some
* variables may have defaults provided, which can be overridden.
* @param {object} request Optional. The Express request object that resulted in this
* rendering job being run. Can be used to provide additional context
* to the templates.
* @returns {string} HTML ready to be rendered in the browser.
* @see https://handlebarsjs.com/
*/
const render = ( templatePath = '', context = {}) => {
const render = async( templatePath, context = {}, request = {}) => {

// Retrieve the header and footer HTML, if we don't already have it in memory.
if ( ! templates.header ) templates.header = fs.readFileSync( 'src/html/header.html', 'utf8' );
Expand All @@ -190,9 +209,11 @@ const render = ( templatePath = '', context = {}) => {

/* eslint-disable camelcase */ // Handlebars templates commonly use snake_case instead.
const defaults = {

// TODO: Get this from bot's name settings in the Slack users list.
site_title: 'PlusPlus++ That Works'
site_title: (
request.query.botUser ?
await slack.getUserName( request.query.botUser ) :
'Working PlusPlus++'
)
};
/* eslint-enable camelcase */

Expand All @@ -204,6 +225,7 @@ const render = ( templatePath = '', context = {}) => {
module.exports = {
extractCommand,
extractPlusMinusEventData,
extractUserID,
getTimeBasedToken,
getTimestamp,
isPlural,
Expand Down
29 changes: 20 additions & 9 deletions src/leaderboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,30 @@ const slack = require( './slack' ),
points = require( './points' ),
helpers = require( './helpers' );

const querystring = require( 'querystring' );

/**
* Gets the URL for the full leaderboard, including a token to ensure that it is only viewed by
* someone who has access to this Slack team.
*
* @param {string} hostname The hostname this app is being served on.
* @param {object} request The Express request object that resulted in this handler being run.
* @returns {string} The leaderboard URL, which will be picked up in ../index.js when called.
*/
const getLeaderboardUrl = ( hostname ) => {
const ts = helpers.getTimestamp(),
token = helpers.getTimeBasedToken( ts ),
url = 'https://' + hostname + '/leaderboard?token=' + token + '&ts=' + ts;
const getLeaderboardUrl = ( request ) => {

const hostname = request.headers.host,
ts = helpers.getTimestamp();

const params = {
token: helpers.getTimeBasedToken( ts ),
ts,
botUser: helpers.extractUserID( request.body.event.text )
};

const url = 'https://' + hostname + '/leaderboard?' + querystring.stringify( params );
return url;
};

}; // GetLeaderboardUrl.

/**
* Ranks items by their scores, returning them in a human readable list complete with emoji for the
Expand Down Expand Up @@ -127,7 +137,7 @@ const getForSlack = async( event, request ) => {

const messageText = (
'Here you go. ' +
'Or see the <' + getLeaderboardUrl( request.headers.host ) + '|whole list>.'
'Or see the <' + getLeaderboardUrl( request ) + '|whole list>.'
);

const message = {
Expand Down Expand Up @@ -159,9 +169,10 @@ const getForSlack = async( event, request ) => {
/**
* Retrieves and returns HTML for the full leaderboard, for displaying on the web.
*
* @param {object} request The Express request object that resulted in this handler being run.
* @returns {string} HTML for the browser.
*/
const getForWeb = async() => {
const getForWeb = async( request ) => {

const scores = await points.retrieveTopScores(),
users = await rankItems( scores, 'users', 'object' ),
Expand All @@ -173,7 +184,7 @@ const getForWeb = async() => {
title: 'Leaderboard'
};

return helpers.render( 'src/html/leaderboard.html', data );
return helpers.render( 'src/html/leaderboard.html', data, request );

}; // GetForWeb.

Expand Down
7 changes: 6 additions & 1 deletion tests/leaderboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ describe( 'getLeaderboardUrl', () => {

const MILLISECONDS_TO_SECONDS = 1000;

const leaderboardUrl = leaderboard.getLeaderboardUrl( 'example.com' ),
const request = {
headers: { host: 'test.local' },
body: { event: { text: '<@U00000000> test' } }
};

const leaderboardUrl = leaderboard.getLeaderboardUrl( request ),
parsedUrl = new URL( leaderboardUrl ),
token = parsedUrl.searchParams.get( 'token' ),
ts = parsedUrl.searchParams.get( 'ts' ),
Expand Down

0 comments on commit 94d43ba

Please sign in to comment.