Skip to content

Commit

Permalink
add prettier
Browse files Browse the repository at this point in the history
  • Loading branch information
atabel committed Apr 17, 2017
1 parent 71a8b17 commit d3acf45
Show file tree
Hide file tree
Showing 9 changed files with 542 additions and 146 deletions.
47 changes: 19 additions & 28 deletions bot-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ const createClient = require('./chat-client');
const md5 = require('md5');
const {v4: createId} = require('uuid');

const getAvatar = (email) =>
`http://www.gravatar.com/avatar/${md5(email)}?s=48&d=identicon&r=PG`;
const getAvatar = email => `http://www.gravatar.com/avatar/${md5(email)}?s=48&d=identicon&r=PG`;

const createBotUser = (name) => {
const createBotUser = name => {
const id = createId();
const email = `bot_${id}@chatbot.com`;
const avatar = getAvatar(email);
Expand All @@ -19,22 +18,19 @@ const createBotUser = (name) => {
};
};

const createBot = (name) => {
const createBot = name => {
const botUser = createBotUser(name);
const client = createClient('BOT/' + encodeURIComponent(JSON.stringify(botUser)));

const sendMessage = (...args) =>
setTimeout(() => client.sendMessage(...args), 200);
const sendMessage = (...args) => setTimeout(() => client.sendMessage(...args), 200);

const respondWith = (getResponse) => (action, ...rest) => {
const text = typeof getResponse === 'function'
? getResponse(action, ...rest)
: getResponse;
const respondWith = getResponse => (action, ...rest) => {
const text = typeof getResponse === 'function' ? getResponse(action, ...rest) : getResponse;
const {receiver, sender} = action;
sendMessage(text, receiver === botUser.id ? sender : receiver);
};

const whenOneToOne = (fn) => (action, ...rest) => {
const whenOneToOne = fn => (action, ...rest) => {
if (action.receiver === botUser.id) {
fn(action, ...rest);
}
Expand All @@ -51,28 +47,23 @@ const createBot = (name) => {
};
};

const escapeRegExp = (string) =>
string.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1");
const escapeRegExp = string => string.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1');

const textMatchesSelector = (text, selector) => {
const matches = text.startsWith(selector);
const parsedText = matches
? text.replace(new RegExp(escapeRegExp(selector) + '\s*'), '')
: null;
const parsedText = matches ? text.replace(new RegExp(escapeRegExp(selector) + '\s*'), '') : null;
return [matches, parsedText];
};

const matches = (selectors) => (action) => {
const handled = Object.keys(selectors)
.filter(selector => selector !== 'default')
.some(selector => {
const {text} = action.payload;
const [matches, parsedText] = textMatchesSelector(text, selector);
if (matches) {
selectors[selector](action, parsedText);
}
return matches;
});
const matches = selectors => action => {
const handled = Object.keys(selectors).filter(selector => selector !== 'default').some(selector => {
const {text} = action.payload;
const [matches, parsedText] = textMatchesSelector(text, selector);
if (matches) {
selectors[selector](action, parsedText);
}
return matches;
});

if (!handled && 'default' in selectors) {
selectors['default'](action);
Expand All @@ -82,4 +73,4 @@ const matches = (selectors) => (action) => {
module.exports = {
createBot,
matches,
};
};
4 changes: 2 additions & 2 deletions bots/echo-bot.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const {createBot} = require('../bot-api');

const createEchoBot = (name) => {
const createEchoBot = name => {
const bot = createBot(name);
const {whenOneToOne, respondWith} = bot;
bot.on('message', whenOneToOne(respondWith(({payload}) => payload.text)));
return bot;
};

module.exports = createEchoBot;
module.exports = createEchoBot;
89 changes: 46 additions & 43 deletions bots/todo-bot.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,56 @@
const {createBot, matches} = require('../bot-api');

const createTodoBot = (name) => {
const createTodoBot = name => {
const todos = {};
const bot = createBot(name);
const {whenOneToOne, respondWith} = bot;

const printTodos = todosForUser =>
todosForUser.map((todo, idx) => `${idx + 1}. ${todo}`).join(',\n');

bot.on('message', matches({

'/todos': respondWith(({sender}) => {
const todosForUser = todos[sender];
if (todosForUser) {
return 'These are your todos: \n' + printTodos(todosForUser);
} else {
return "You don't have pending todos!";
}
}),

'/todo': respondWith(({sender}, newTodo) => {
const todosForUser = todos[sender] || [];
todos[sender] = [...todosForUser, newTodo]
return `New todo saved: "${newTodo}" \nPending: \n${printTodos(todos[sender])}`;
}),

'/done': respondWith(({sender}, idx) => {
const doneTodoIdx = parseInt(idx) - 1;
const todosForUser = todos[sender] || [];
const doneTodo = todosForUser[doneTodoIdx];
const pendingTodos = todosForUser.filter((todo, idx) => idx !== doneTodoIdx);
todos[sender] = pendingTodos;
return doneTodo
? `"${doneTodo}" marked as done \nPending: \n${printTodos(pendingTodos)}`
: todosForUser.length
? `You only have ${todosForUser.length} todos`
: "You don't have pending todos!";
}),

'/help': respondWith(() => [
'/todos lists the todos',
'/todo <whatever> adds a new todo',
'/done <number> marks a todo as done'
].join(',\n')),

default: whenOneToOne(respondWith('Type /help')),
}));
const printTodos = todosForUser => todosForUser.map((todo, idx) => `${idx + 1}. ${todo}`).join(',\n');

bot.on(
'message',
matches({
'/todos': respondWith(({sender}) => {
const todosForUser = todos[sender];
if (todosForUser) {
return 'These are your todos: \n' + printTodos(todosForUser);
} else {
return "You don't have pending todos!";
}
}),

'/todo': respondWith(({sender}, newTodo) => {
const todosForUser = todos[sender] || [];
todos[sender] = [...todosForUser, newTodo];
return `New todo saved: "${newTodo}" \nPending: \n${printTodos(todos[sender])}`;
}),

'/done': respondWith(({sender}, idx) => {
const doneTodoIdx = parseInt(idx) - 1;
const todosForUser = todos[sender] || [];
const doneTodo = todosForUser[doneTodoIdx];
const pendingTodos = todosForUser.filter((todo, idx) => idx !== doneTodoIdx);
todos[sender] = pendingTodos;
return doneTodo
? `"${doneTodo}" marked as done \nPending: \n${printTodos(pendingTodos)}`
: todosForUser.length
? `You only have ${todosForUser.length} todos`
: "You don't have pending todos!";
}),

'/help': respondWith(() =>
[
'/todos lists the todos',
'/todo <whatever> adds a new todo',
'/done <number> marks a todo as done',
].join(',\n')
),

default: whenOneToOne(respondWith('Type /help')),
})
);

return bot;
};

module.exports = createTodoBot;
module.exports = createTodoBot;
4 changes: 2 additions & 2 deletions chat-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const PRODUCTION_CHAT_SERVER = 'wss://react-chat-server.herokuapp.com';
const DEV_CHAT_SERVER = 'ws://localhost:8080';
const chatServerUrl = dev ? DEV_CHAT_SERVER : PRODUCTION_CHAT_SERVER;

const createClient = (token) => {
const createClient = token => {
let ws;
const listeners = {};

Expand Down Expand Up @@ -107,4 +107,4 @@ const createClient = (token) => {
};
};

module.exports = createClient;
module.exports = createClient;
16 changes: 6 additions & 10 deletions google-auth/google-id-token-verifier.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
const fetch = require('node-fetch');

const VALID_ISSUERS = [
'accounts.google.com',
'https://accounts.google.com',
];
const VALID_ISSUERS = ['accounts.google.com', 'https://accounts.google.com'];

const isValidIssuer = issuer =>
VALID_ISSUERS.indexOf(issuer) >= 0;
const isValidIssuer = issuer => VALID_ISSUERS.indexOf(issuer) >= 0;

const verifyAuthToken = clientId => token => {
if (!token) {
Expand All @@ -21,13 +17,13 @@ const verifyAuthToken = clientId => token => {
throw new Error('AuthError: Wrong issuer');
}
return tokenInfo;
}).catch(e => {
})
.catch(e => {
throw new Error('AuthError');
});
}
};

const createVerifier = ({clientId}) =>
verifyAuthToken(clientId)
const createVerifier = ({clientId}) => verifyAuthToken(clientId);

module.exports = createVerifier;
module.exports = createVerifier;
47 changes: 22 additions & 25 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@ const createUser = ({name, picture, given_name, email, family_name, sub}) => ({
name: given_name,
familyName: family_name,
email,
id: sub
id: sub,
});

const getUsersList = () =>
wss.clients.map(({upgradeReq: {user}}) => user);
const getUsersList = () => wss.clients.map(({upgradeReq: {user}}) => user);

const isUserAlreadyLoggedIn = user =>
getUsersList().some(({id}) => id === user.id);
const isUserAlreadyLoggedIn = user => getUsersList().some(({id}) => id === user.id);

const wss = new WebSocketServer({
port: SERVER_PORT,
Expand All @@ -29,34 +27,33 @@ const wss = new WebSocketServer({
const userJson = decodeURIComponent(token.substr('BOT/'.length));
console.log('register new bot: ', userJson);
try {
const user = JSON.parse(userJson)
const user = JSON.parse(userJson);
info.req.user = user;
cb(true);
} catch (e) {
cb(false, 401, 'Bad bot encoding');
}
} else {
verifyAuthToken(token).then(tokenInfo => {
const user = createUser(tokenInfo);
if (isUserAlreadyLoggedIn(user)) {
cb(false, 401, `Unauthorized: already logged!`);
} else {
info.req.user = user;
}
cb(true);
}).catch(e => {
cb(false, 401, `Unauthorized: ${e.message}`);
});
verifyAuthToken(token)
.then(tokenInfo => {
const user = createUser(tokenInfo);
if (isUserAlreadyLoggedIn(user)) {
cb(false, 401, `Unauthorized: already logged!`);
} else {
info.req.user = user;
}
cb(true);
})
.catch(e => {
cb(false, 401, `Unauthorized: ${e.message}`);
});
}
},
});

const plugins = [
require('./plugins/metadata-plugin'),
];
const plugins = [require('./plugins/metadata-plugin')];

const applyPlugins = event =>
plugins.reduce((event, plugin) => Promise.resolve(plugin(event)), event);
const applyPlugins = event => plugins.reduce((event, plugin) => Promise.resolve(plugin(event)), event);

const send = event => {
const {receiver, sender} = event;
Expand Down Expand Up @@ -92,16 +89,16 @@ const handleEvent = fromUser => eventJson => {
const notyfyDisconnection = user => () => {
console.log(`Offline: ${user.email} | #users: ${wss.clients.length}`);
send({type: 'disconnect', sender: 'server', receiver: 'all', payload: user.id});
}
};

wss.on('connection', ws => {
const {user} = ws.upgradeReq;
console.log(`Connect: ${user.email} | #users: ${wss.clients.length}`);

ws.on('message', handleEvent(user));
ws.on('close', notyfyDisconnection(user))
ws.on('close', notyfyDisconnection(user));

send({type: 'user', sender: user.id, receiver: 'all', payload: user});
});

console.log('listening on port ', SERVER_PORT);
console.log('listening on port ', SERVER_PORT);
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@
},
"scripts": {
"start": "pm2 start index.js --watch",
"log": "pm2 log index"
"log": "pm2 log index",
"precommit": "lint-staged",
"pretty": "./node_modules/.bin/prettier --tab-width 4 --single-quote --trailing-comma es5 --bracket-spacing false --print-width 120 --write"
},
"lint-staged": {
"*.js": ["pretty", "git add"]
},
"dependencies": {
"get-urls": "^5.0.1",
Expand All @@ -20,6 +25,9 @@
"ws": "^1.1.1"
},
"devDependencies": {
"pm2": "^2.0.19"
"husky": "^0.13.3",
"lint-staged": "^3.4.0",
"pm2": "^2.0.19",
"prettier": "^1.1.0"
}
}
6 changes: 3 additions & 3 deletions plugins/metadata-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const fetchMetadata = url =>

module.exports = fetchMetadata;

const addMetadata = (event) => {
const addMetadata = event => {
if (event.type !== 'message') {
return Promise.resolve(event);
}
Expand All @@ -36,8 +36,8 @@ const addMetadata = (event) => {
}

return fetchMetadata(urls[0])
.then((media) => merge(event, {payload: merge(event.payload, {media})}))
.then(media => merge(event, {payload: merge(event.payload, {media})}))
.catch(() => event);
};

module.exports = addMetadata;
module.exports = addMetadata;
Loading

0 comments on commit d3acf45

Please sign in to comment.