chore(lint): update eslint configuration, re-lint

chore(gitignore): don't ignore src/types
This commit is contained in:
Mahdi Dibaiee 2016-03-28 20:40:59 +04:30
parent a357cd7368
commit c76eb0c64d
12 changed files with 87 additions and 132 deletions

View File

@ -1,59 +1,13 @@
{ {
"parser": "babel-eslint",
"extends": "airbnb/base",
"root": true,
"env": { "env": {
"es6": true, "node": true
"browser": true
},
"ecmaFeatures": {
"modules": true
},
"globals": {
"exports": true,
"require": true,
"ViewHelpers": true,
"is": true,
"Components": true,
"XPCOMUtils": true,
"EventEmitter": true,
"add_task": true,
"info": true,
"createHost": true,
"promiseTab": true,
"ok": true,
"TEST_URI_ROOT": true,
"TargetFactory": true,
"gBrowser": true,
"gDevTools": true
}, },
"rules": { "rules": {
"comma-dangle": [2, "never"], "comma-dangle": 0,
"no-underscore-dangle": 0, "no-param-reassign": 0,
"no-cond-assign": 0, "no-console": 0
"no-undef": 0,
"no-console": 0,
"no-reserved-keys": 2,
"valid-jsdoc": [2, {
"requireReturn": false,
"requireParamDescription": false,
"requireReturnDescription": false
}],
"max-len": [1, 80],
"no-use-before-define": 0,
"no-self-compare": 1,
"no-sequences": 0,
"radix": 2,
"wrap-iife": 2,
"indent": [2, 2],
"brace-style": [2, "1tbs"],
"comma-style": [2, "last"],
"no-lonely-if": 2,
"no-multiple-empty-lines": [2, {"max": 2}],
"quotes": 0,
"space-after-keywords": [2, "always"],
"space-before-blocks": [2, "always"],
"space-infix-ops": [2, { "int32Hint": false }],
"strict": 0,
"global-strict": 0,
"no-new": 0,
"camelcase": 0
} }
} }

7
.gitignore vendored
View File

@ -1,3 +1,7 @@
build
types
!src/types
# Logs # Logs
logs logs
*.log *.log
@ -30,6 +34,3 @@ node_modules
test.js test.js
.DS_Store .DS_Store
build
types

View File

@ -1,6 +1,6 @@
{ {
"name": "telegram-api", "name": "telegram-api",
"version": "0.7.0", "version": "0.7.1",
"description": "Control Telegram bots easily using the new Telegram API", "description": "Control Telegram bots easily using the new Telegram API",
"main": "build/index.js", "main": "build/index.js",
"scripts": { "scripts": {
@ -39,13 +39,16 @@
"unirest": "0.4.2" "unirest": "0.4.2"
}, },
"devDependencies": { "devDependencies": {
"babel-eslint": "6.0.0",
"babel-plugin-add-module-exports": "^0.1.2", "babel-plugin-add-module-exports": "^0.1.2",
"babel-preset-es2015": "^6.6.0", "babel-preset-es2015": "^6.6.0",
"eslint-config-airbnb": "6.2.0",
"grunt": "^0.4.5", "grunt": "^0.4.5",
"grunt-babel": "^6.0.0", "grunt-babel": "^6.0.0",
"grunt-contrib-clean": "^1.0.0", "grunt-contrib-clean": "^1.0.0",
"grunt-contrib-copy": "^1.0.0", "grunt-contrib-copy": "^1.0.0",
"grunt-contrib-watch": "^1.0.0", "grunt-contrib-watch": "^1.0.0",
"grunt-copy": "^0.1.0" "grunt-copy": "^0.1.0",
"grunt-eslint": "18.0.0"
} }
} }

View File

@ -20,7 +20,7 @@ export default class API {
} }
API.prototype.request = function request(method, data) { API.prototype.request = function request(method, data) {
return fetch(this.token + '/' + method, data); return fetch(`${this.token}/${method}`, data);
}; };
const methods = ['getMe', 'sendMessage', 'forwardMessage', 'sendPhoto', const methods = ['getMe', 'sendMessage', 'forwardMessage', 'sendPhoto',
@ -29,7 +29,7 @@ const methods = ['getMe', 'sendMessage', 'forwardMessage', 'sendPhoto',
'getUpdates', 'setWebhook']; 'getUpdates', 'setWebhook'];
methods.forEach(method => { methods.forEach(method => {
API.prototype[method] = function(data) { API.prototype[method] = function(data) { //eslint-disable-line
return this.request(method, data); return this.request(method, data);
}; };
}); });

View File

@ -8,6 +8,32 @@ const REQUIRED = 0;
const OPTIONAL = 1; const OPTIONAL = 1;
const REST = 2; const REST = 2;
function escape(symbols, append = '') {
return symbols.split('').map(symbol =>
(ESCAPABLE.indexOf(symbol) ? `\\${symbol}` : symbol) + append
).join('');
}
const TYPES = {
number: '\\d',
word: '\\S'
};
function getFormat(type = 'word', param = 'required') {
const t = TYPES[type];
switch (param) { // eslint-disable-line
case 'required':
return `(${t}+)`;
case 'optional':
return `(${t}+)?`;
case 'rest':
return '(.*)';
}
return '';
}
/** /**
* Parses a message for arguments, based on format * Parses a message for arguments, based on format
* *
@ -41,74 +67,49 @@ export default function argumentParser(format, string) {
format = format.replace(/[^\s]+/, '').trim(); format = format.replace(/[^\s]+/, '').trim();
if (!format) { if (!format) {
return {args: {}, params: {}}; return { args: {}, params: {} };
} }
let indexes = [], let indexes = [];
params = {}; const params = {};
format = format.replace(/\s/g, '\\s*'); format = format.replace(/\s/g, '\\s*');
format = format.replace(FORMAT_REQUIRED, format = format.replace(FORMAT_REQUIRED,
(f, symbols, arg, type = 'word', offset) => { (f, symbols, arg, type = 'word', offset) => {
indexes.push({arg, offset}); indexes.push({ arg, offset });
params[arg] = REQUIRED; params[arg] = REQUIRED;
return (escape(symbols) + getFormat(type, 'required')).trim(); return (escape(symbols) + getFormat(type, 'required')).trim();
}); });
format = format.replace(FORMAT_OPTIONAL, format = format.replace(FORMAT_OPTIONAL,
(f, symbols, arg, type = 'word', offset) => { (f, symbols, arg, type = 'word', offset) => {
indexes.push({arg, offset}); indexes.push({ arg, offset });
params[arg] = OPTIONAL; params[arg] = OPTIONAL;
return (escape(symbols, '?') + getFormat(type, 'optional')).trim(); return (escape(symbols, '?') + getFormat(type, 'optional')).trim();
}); });
format = format.replace(FORMAT_REST, (full, arg, offset) => { format = format.replace(FORMAT_REST, (full, arg, offset) => {
indexes.push({offset, arg}); indexes.push({ offset, arg });
params[arg] = REST; params[arg] = REST;
return getFormat(null, 'rest'); return getFormat(null, 'rest');
}); });
if (!string) { if (!string) {
return {args: {}, params}; return { args: {}, params };
} }
indexes = indexes.sort((a, b) => { indexes = indexes.sort((a, b) =>
return a.offset < b.offset ? -1 : 1; (a.offset < b.offset ? -1 : 1)
}); );
const regex = new RegExp(format); const regex = new RegExp(format);
const matched = regex.exec(string).slice(1); const matched = regex.exec(string).slice(1);
const object = {}; const object = {};
for (let [index, match] of matched.entries()) { for (const [index, match] of matched.entries()) {
const argument = indexes[index]; const argument = indexes[index];
object[argument.arg] = match; object[argument.arg] = match;
} }
return {args: object, params}; return { args: object, params };
}
function escape(symbols, append = '') {
return symbols.split('').map(symbol => {
return (ESCAPABLE.indexOf(symbol) ? `\\${symbol}` : symbol) + append;
}).join('');
}
const TYPES = {
'number': '\\d',
'word': '\\S'
};
function getFormat(type = 'word', param = 'required') {
const t = TYPES[type];
switch (param) {
case 'required':
return `(${t}+)`;
case 'optional':
return `(${t}+)?`;
case 'rest':
return `(.*)`;
}
} }

View File

@ -4,14 +4,14 @@ export default function fetch(path, data = {}) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const files = {}; const files = {};
for (let key of Object.keys(data)) { for (const key of Object.keys(data)) {
if (data[key].file) { if (data[key].file) {
files[key] = data[key].file; files[key] = data[key].file;
delete data[key]; delete data[key];
} }
} }
unirest.post('https://api.telegram.org/bot' + path) unirest.post(`https://api.telegram.org/bot${path}`)
.field(data) .field(data)
.attach(files) .attach(files)
.end(response => { .end(response => {

View File

@ -1,6 +1,6 @@
import https from 'http'; import https from 'http';
import qs from 'qs'; import qs from 'qs';
import {getBody} from './fetch'; import { getBody } from './fetch';
const DEFAULTS = { const DEFAULTS = {
server: {}, server: {},
@ -11,14 +11,12 @@ export default function webhook(options = {}, bot) {
options = Object.assign(DEFAULTS, options); options = Object.assign(DEFAULTS, options);
return bot.api.setWebhook(options.url).then(() => { return bot.api.setWebhook(options.url).then(() => {
bot._webhookServer = https.createServer(options.server, (req, res) =>
bot._webhookServer = https.createServer(options.server, (req, res) => { getBody(req).then(data => {
return getBody(req).then(data => {
bot.emit('update', qs.parse(data).result); bot.emit('update', qs.parse(data).result);
res.end('OK'); res.end('OK');
}); })
}).listen(options.port); ).listen(options.port);
}); });
} }

View File

@ -3,7 +3,7 @@ import API from './functions/api';
import webhook from './functions/webhook'; import webhook from './functions/webhook';
import poll from './functions/poll'; import poll from './functions/poll';
import argumentParser from './functions/argument-parser'; import argumentParser from './functions/argument-parser';
import {EventEmitter} from 'events'; import { EventEmitter } from 'events';
import Message from './types/Message'; import Message from './types/Message';
import File from './types/File'; import File from './types/File';
import Keyboard from './types/Keyboard'; import Keyboard from './types/Keyboard';
@ -31,7 +31,7 @@ export default class Bot extends EventEmitter {
* Create and connect to a new bot * Create and connect to a new bot
* @param {object} options Bot properties. * @param {object} options Bot properties.
*/ */
constructor(options = {update: {}}) { constructor(options = { update: {} }) {
super(); super();
if (!options.token) { if (!options.token) {
@ -80,9 +80,9 @@ export default class Bot extends EventEmitter {
if (hook) { if (hook) {
return webhook(hook, this); return webhook(hook, this);
} else {
return poll(this);
} }
return poll(this);
}); });
} }
@ -182,7 +182,7 @@ export default class Bot extends EventEmitter {
res.message.text = text; res.message.text = text;
} }
let ev = this._userEvents.find(({pattern}) => pattern.test(text)); const ev = this._userEvents.find(({ pattern }) => pattern.test(text));
if (!ev) { if (!ev) {
this.emit('command-notfound', res.message); this.emit('command-notfound', res.message);
@ -194,12 +194,12 @@ export default class Bot extends EventEmitter {
return; return;
} }
let {params, args} = ev.parse(res.message.text); const { params, args } = ev.parse(res.message.text);
res.message.args = args; res.message.args = args;
const requiredParams = Object.keys(params).filter(param => { const requiredParams = Object.keys(params).filter(param =>
return params[param] === REQUIRED && !args[param]; params[param] === REQUIRED && !args[param]
}); );
if (!requiredParams.length) { if (!requiredParams.length) {
ev.listener(res.message); ev.listener(res.message);
@ -208,7 +208,7 @@ export default class Bot extends EventEmitter {
const bot = this; const bot = this;
function* getAnswer() { function* getAnswer() {
for (let param of requiredParams) { for (const param of requiredParams) {
const msg = new Message().to(res.message.chat.id) const msg = new Message().to(res.message.chat.id)
.text(`Enter value for ${param}`); .text(`Enter value for ${param}`);
yield bot.send(msg).then(answer => { yield bot.send(msg).then(answer => {

View File

@ -1,4 +1,4 @@
import {EventEmitter} from 'events'; import { EventEmitter } from 'events';
const ANSWER_THRESHOLD = 10; const ANSWER_THRESHOLD = 10;
@ -29,8 +29,8 @@ export default class Base extends EventEmitter {
*/ */
send(bot) { send(bot) {
if (this._keyboard) { if (this._keyboard) {
const reply_markup = JSON.stringify(this._keyboard.getProperties()); const replyMarkup = JSON.stringify(this._keyboard.getProperties());
this.properties.reply_markup = reply_markup; this.properties.reply_markup = replyMarkup;
} }
let messageId; let messageId;
@ -49,15 +49,15 @@ export default class Base extends EventEmitter {
bot.on('update', function listener(result) { bot.on('update', function listener(result) {
answers += result.length; answers += result.length;
const update = result.find(({message}) => { const update = result.find(({ message }) => {
// if in a group, there will be a reply to this message // if in a group, there will be a reply to this message
if (chat < 0) { if (chat < 0) {
return message.chat.id === chat return message.chat.id === chat
&& message.reply_to_message && message.reply_to_message
&& message.reply_to_message.message_id === messageId; && message.reply_to_message.message_id === messageId;
} else {
return message.chat.id === chat;
} }
return message.chat.id === chat;
}); });
if (update) { if (update) {

View File

@ -20,9 +20,7 @@ export default class BulkMessage extends Message {
* @return {object} returns the message object * @return {object} returns the message object
*/ */
to(...args) { to(...args) {
const chats = args.reduce((a, b) => { const chats = args.reduce((a, b) => a.concat(b), []);
return a.concat(b);
}, []);
this.chats = chats; this.chats = chats;
return this; return this;

View File

@ -37,12 +37,12 @@ export default class File extends Base {
*/ */
file(file, fileType) { file(file, fileType) {
if (fileType) { if (fileType) {
this.properties[fileType] = {file: file}; this.properties[fileType] = { file };
return this; return this;
} }
let [type, extension] = mime.lookup(file).split('/'); let [type, extension] = mime.lookup(file).split('/'); // eslint-disable-line
if (type === 'image') { if (type === 'image') {
type = 'photo'; type = 'photo';
} }
@ -55,7 +55,7 @@ export default class File extends Base {
type = 'document'; type = 'document';
} }
this.properties[type] = {file: file}; this.properties[type] = { file };
this.method = `send${type[0].toUpperCase() + type.slice(1)}`; this.method = `send${type[0].toUpperCase() + type.slice(1)}`;

View File

@ -15,7 +15,7 @@ export default class Question extends Message {
constructor(options = {}) { constructor(options = {}) {
super(options); super(options);
let kb = new Keyboard().force().oneTime().selective(); const kb = new Keyboard().force().oneTime().selective();
this.keyboard(kb); this.keyboard(kb);
this.answers(options.answers); this.answers(options.answers);
@ -60,10 +60,10 @@ export default class Question extends Message {
if (answer) { if (answer) {
this.emit('question:answer', answer, message); this.emit('question:answer', answer, message);
return message; return message;
} else {
this.emit('question:invalid', message);
throw message;
} }
this.emit('question:invalid', message);
throw message;
}); });
} }
} }