Skip to content

Commit

Permalink
Updated Blame Command
Browse files Browse the repository at this point in the history
Continuing work on #125
Closes #155
Continuing work on #122
  • Loading branch information
Ian Mitchell committed Jan 23, 2016
1 parent b66cc13 commit d29f060
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 82 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ language: node_js
node_js:
- stable
before_install:
- openssl aes-256-cbc -K $encrypted_8216d40451d0_key -iv $encrypted_8216d40451d0_iv -in config.json.enc -out config.json -d
- openssl aes-256-cbc -K $encrypted_8216d40451d0_key -iv $encrypted_8216d40451d0_iv
-in config.json.enc -out config.json -d
Binary file modified config.json.enc
Binary file not shown.
133 changes: 59 additions & 74 deletions src/commands/blame.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,97 +6,82 @@ import colors from 'irc-colors';
import moment from 'moment';

const log = debug('Blame');
const SHOWTIMES_URL = `${config.showtimes.server}`;

export class Blame extends Command {
message(from, to, text) {
const blameRegex = /^[.!](?:show|blame)\s(.+)$/i;
const blame = text.match(blameRegex);

if (blame) {
return new Promise((resolve, reject) => {
this.blameRequest(from, to, blame[1]).then(response => {
this.send(to, response);
return resolve();
}, error => {
this.send(to, 'Error connecting to Deschtimes');
log(`Error: ${error.message}`);
return reject(error);
});
return this.blameRequest(from, to, blame[1]).then(response => {
this.send(to, response);
}, error => {
this.send(to, error.message);
log(`Error: ${error.message}`);
return error;
});
} else if (text.trim().toLowerCase() === '.blame') {
this.send(to, 'Please use: ".blame <show>" (ie, `.blame bokumachi`)');
}

// Needed for tests
return new Promise(resolve => resolve());
}

blameRequest(from, to, show, names = false) {
blameRequest(from, to, show, useNames = false) {
log(`Blame request by ${from} in ${to} for ${show}`);

return new Promise((resolve, reject) => {
let uri = `${SHOWTIMES_URL}/blame.json?`;
uri += `irc=${encodeURIComponent(to)}`;
uri += `&show=${encodeURIComponent(show.trim())}`;

fetch(uri).then(response => {
if (response.ok) {
response.json().then(data => {
let message = '';

if (data.message) {
message = data.message;
} else {
const updatedDate = moment(new Date(data.updated_at));
const airDate = moment(new Date(data.air_date));
const status = new Map();
let job;

data.status.forEach(staff => {
if (staff.finished) {
// Pending takes precedence
if (!status.get(staff.acronym)) {
status.set(staff.acronym, colors.bold.green(staff.acronym));
}
} else {
status.set(staff.acronym, colors.bold.red(staff.acronym));

if (!job) {
if (names) {
job = staff.staff;
} else {
job = staff.position;
}
}
}
});

if (job === undefined) {
job = 'release';
}

message = `Ep ${data.episode} of ${data.name}`;

if (updatedDate > airDate) {
message += ` is at ${job} (last update ${updatedDate.fromNow()}). `;
} else {
if (airDate > Date.now()) {
message += ' airs';
} else {
message += ' aired';
}

message += ` ${airDate.fromNow()}. `;
}

message += `[${[...status.values()].join(' ')}]`;
}

resolve(message);
});
} else {
response.json().then(data => reject(Error(data.message)));
let uri = `${config.showtimes.server}/blame.json?`;
uri += `irc=${encodeURIComponent(to)}`;
uri += `&show=${encodeURIComponent(show.trim())}`;

return fetch(uri).then(response => {
if (response.ok) {
return response.json().then(data => this.createMessage(data, useNames));
}

return response.json().then(data => {
log(`Blame Request Error: ${data}`);
Error(data.message);
});
}).catch(error => Error(error));
}

createMessage(json, useNames) {

This comment has been minimized.

Copy link
@IanMitchell

IanMitchell Jan 23, 2016

Owner

@kunaldes can you take a look at this method? Doesn't feel as clean as it could (the ternary operations), but not entirely sure how to refactor it.

This comment has been minimized.

Copy link
@kunaldes

kunaldes Jan 23, 2016

Collaborator

Eh, looks fine to me.

if (json.message) {
return json.message;
}

const updatedDate = moment(new Date(json.updated_at));
const airDate = moment(new Date(json.air_date));
const status = new Map();
let job = 'release';

let message = `Ep ${json.episode} of ${json.name}`;

json.status.forEach(staff => {
// Pending takes precedence
if (staff.finished && !status.has(staff.acronym)) {
status.set(staff.acronym, colors.bold.green(staff.acronym));
} else {
status.set(staff.acronym, colors.bold.red(staff.acronym));

if (job === 'release') {
job = useNames ? staff.staff : staff.position;
}
}).catch(error => reject(Error(error)));
}
});

if (updatedDate > airDate) {
message += ` is at ${job} (last update ${updatedDate.fromNow()}). `;
} else {
message += airDate > Date.now() ? ' airs' : ' aired';
message += ` ${airDate.fromNow()}. `;
}

message += `[${[...status.values()].join(' ')}]`;

return message;
}

help(from) {
Expand Down
4 changes: 1 addition & 3 deletions src/commands/youtube.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,7 @@ export class Youtube extends Command {
log(`YouTube Search Request Error: ${data}`);
return Error(`YouTube Search Request Error: ${data}`);
});
}).catch(error => {
return Error(error);
});
}).catch(error => Error(error));
}

help(from) {
Expand Down
105 changes: 105 additions & 0 deletions test/commands/test_blame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import 'babel-polyfill';
import { describe, before, afterEach, it } from 'mocha';
import assert from 'assert';
import { Client } from '../helpers.js';
import { Blame } from '../../src/commands/blame';

const client = new Client();
const blame = new Blame(client);

describe('Blame', () => {
describe('Triggers', () => {
afterEach(() => client.resetLog());

it('should respond to .blame trigger', () => {
return blame.message('Mocha', '#arx-7', '.blame').then(() => {
assert.notEqual(client.lastMessage, null);
});
});

it('should respond to .blame <show> trigger', () => {
return blame.message('Mocha', '#arx-7', '.blame aoty').then(() => {
assert.notEqual(client.lastMessage, null);
});
});

it('should respond to .show <show> trigger', () => {
return blame.message('Mocha', '#arx-7', '.show aoty').then(() => {
assert.notEqual(client.lastMessage, null);
});
});

it('should not activate in middle of phrase', () => {
return blame.message('Mocha', '#arx-7', 'test .blame aoty').then(() => {
assert.equal(client.lastMessage, null);
});
});

it('should be case insensitive', () => {
return blame.message('Mocha', '#arx-7', '.BLAME AOTY').then(() => {
assert.notEqual(client.lastMessage, null);
});
});
});

describe('General Usage', () => {
it('should respond in correct channel', () => {
return blame.message('Mocha', '#arx-7', '.blame AOTY').then(() => {
assert.equal(client.lastTarget, '#arx-7');
});
});

it('should respond with correct usage', () => {
return blame.message('Mocha', '#arx-7', '.blame').then(() => {
assert(client.lastMessage.startsWith('Please use:'), 'Incorrect usage information');
});
});
});

// To avoid repeatedly spamming endpoint, we only hit the API once. The
// lastMessage contains the results; these tests don't need fresh results.
describe('Message Formatting', () => {
before(() => blame.message('Mocha', '#arx-7', '.blame aoty'));

it('should should include show name', () => {
assert(client.lastMessage.includes("Desch's Slice of Life"), 'Show name not present');
});

it('should include episode number', () => {
assert(client.lastMessage.includes('Ep 7'), 'Episode number not present');
});

it('should use position acronym', () => {
assert(client.lastMessage.includes('TL'), 'TL acronym not present');
assert(!client.lastMessage.includes('Translator'), 'Translator position present');
});

it('should color completed positions green', () => {
assert(client.lastMessage.includes('\u0002QC'), 'QC not marked as complete');
});

it('should color incompleted positions red', () => {
assert(client.lastMessage.includes('\u0002TL'), 'TL not marked as incomplete');
});

it('should reduce multiple positions');

it('should indicate incomplete on mix jobs');

it('should not include staff names', () => {
assert(!client.lastMessage.includes('at Desch'), 'Staff name included');
assert(!client.lastMessage.includes('Fyurie'), 'Staff name included');
});

it('should include air date', () => {
let present = false;
present = client.lastMessage.includes('airs') || client.lastMessage.includes('aired');
assert(present, 'Air date not present');
});

// These tests require custom commands for test shows at different stages
it('should include last update');

it('should indicate release status');
});
});
4 changes: 0 additions & 4 deletions test/test_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
"ssl": false,
"userName": "chidori",
"admins": ["Desch", "Jukey", "Aoi-chan"],
"showtimes": {
"server": "http://localhost:3000",
"key": "secretpassword"
},
"channels": [
{
"name": "#arbalest",
Expand Down

0 comments on commit d29f060

Please sign in to comment.