<NME> telegram.js
<BEF> 'use strict';
const EventEmitter = require('eventemitter3');
const Request = require('request-promise');
const Agent = require('socks5-https-client/lib/Agent');
const Stream = require('stream');
const Path = require('path');

const Telegram = EventEmitter => class extends EventEmitter {
  constructor(token, proxy) {
    super();
    if (token === undefined) {
      throw new Error('Please provide a Telegram bot token when instantiating');
    }
    this._token = token;
    if(proxy !== undefined){
      this._useProxy = true;
      this._proxy = proxy;
    }
  }

  _request(method, params, formData) {
    if (arguments.length === 0 || typeof arguments[0] !== 'string') {
      throw new Error('Please provide method as a string');
    }

    // the 2nd, 3rd or 4th argument could be a callback
    let callback;
    if (typeof arguments[3] == 'function') {
      callback = arguments[3];
    } else if (typeof arguments[2] == 'function') {
      callback = arguments[2];
      formData = null;
    } else if (typeof arguments[1] == 'function') {
      callback = arguments[1];
      params = null;
    }

    let options = {
      uri: 'https://api.telegram.org/bot' + this._token + '/' + method,
      qs: params,
      formData: formData,
      simple: false,
      resolveWithFullResponse: true,
      forever: true
    };

    if(this._useProxy){
      options.strictSSL = true;
      options.agentClass = Agent;
      options.agentOptions = {
        socksHost: this._proxy.socksHost,
        socksPort: this._proxy.socksPort
      };
      if(this._proxy.socksUsername && this._proxy.socksPassword){
        options.agentOptions.socksUsername = this._proxy.socksUsername;
        options.agentOptions.socksPassword = this._proxy.socksPassword;
      }
    }

    return Request(options)
    .then(resp => {
      if (resp.statusCode !== 200) {
        throw new Error(resp.statusCode + ':\n'+ resp.body);
      }

      let updates = JSON.parse(resp.body);

      if (updates.ok) {
        if (callback) { 
          callback(null, updates);
        }

        return updates;
      }
      return null;
    })
    .catch(error => {
      if (callback) {
        callback(error);
      }
      else {
        throw error;
      }
    });
  }

  getMe(callback) {
    return this._request('getMe', callback);
  }

  getUpdates(offset, callback) {
    let params = {
      offset: offset,
      timeout: 10
    };

    return this._request('getUpdates', params, callback);
  }

  setWebhook(url, optionalParams, callback) {
    let params = {
      url: url
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('setWebhook', url, params, callback);
  }

  deleteWebhook(optionalParams, callback) {
    return this._request('deleteWebhook', optionalParams, callback);
  }

  getWebhookInfo(callback) {
    return this._request('getWebhookInfo', callback);
  }

  logOut(callback) {
    return this._request('logOut', callback);
  }

  close(callback) {
    return this._request('close', callback);
  }

  sendMessage(chatId, text, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      text: text
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams, callback);
    }

    return this._request('sendMessage', params, callback);
  }

  answerCallbackQuery(callbackQueryId, optionalParams, callback) {
    let params = {
      callback_query_id: callbackQueryId
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('answerCallbackQuery', params, callback);
  }

  setMyCommands(commands, callback) {
    return this._request('setMyCommands', commands, callback);
  }

  getMyCommands() {

    this._request('sendDocument', params);
  }
}

module.exports = Telegram;

    return this._request('copyMessage', params, callback);
  }

  sendPhoto(chatId, photo, optionalParams, callback) {
    let params;
    let formData;
  
    if (isReadableStream(photo)) {
      params = {
        chat_id: chatId
      };
      formData = {
        photo: photo
      };
    } else {
      params = {
        chat_id: chatId,
        photo: photo
      };
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendPhoto', params, formData, callback);
  }

  sendAudio(chatId, audio, optionalParams, callback) {
    let params;
    let formData;

    if (isReadableStream(audio)) {
      params = {
        chat_id: chatId
      };
      formData = {
        audio: audio
      };
    } else {
      params = {
        chat_id: chatId,
        audio: audio
      };
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendAudio', params, formData, callback);
  }

  sendDocument(chatId, document, optionalParams, callback) {
    let params;
    let formData;

    if (isReadableStream(document)) {
      params = {
        chat_id: chatId
      };
      formData = {
        document: document
      };
    } else {
      params = {
        chat_id: chatId,
        document: document
      };
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendDocument', params, formData, callback);
  }

  sendAnimation(chatId, animation, optionalParams, callback) {
    let params;
    let formData;

    if (isReadableStream(animation)) {
      params = {
        chat_id: chatId
      };
      formData = {
        animation: animation
      };
    } else {
      params = {
        chat_id: chatId,
        animation: animation
      };
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendAnimation', params, formData, callback);
  }

  // Polls

  sendPoll(chatId, question, pollOptions, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      question: question,
      options: pollOptions
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams, callback);
    }

    return this._request('sendPoll', params, callback);
  }

  stopPoll(chatId, messageId, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      message_id: messageId
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams, callback);
    }

    return this._request('stopPoll', params, callback);
  }

  // Stickers

  sendSticker(chatId, sticker, optionalParams, callback) {
    let params;
    let formData;

    if (isReadableStream(sticker)) {
      params = {
        chat_id: chatId
      };
      formData = {
        sticker: sticker
      };
    } else {
      params = {
        chat_id: chatId,
        sticker: sticker
      };
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendSticker', params, formData, callback);
  }

  getStickerSet(name, callback) {
    let params = {
      name: name
    }

    return this._request('getStickerSet', params, callback);
  }

  uploadStickerFile(userId, pngFile, callback) {
    let params = {
      user_id: userId,
    };

    let formData = {
      png_sticker: pngFile
    };

    return this._request('uploadStickerFile', params, formData, callback);
  }

  createNewStickerSet(userId, name, title, stickerFile, emojis, optionalParams, callback) {
    let params;
    let formData;

    if (isReadableStream(stickerFile)) {
      // stickerFile is a readableStream, check extension
      let ext = Path.extname(stickerFile.path);
      
      if (ext === '.png') {
        params = {
          user_id: userId,
          name: name,
          title: title,
          emojis: emojis
        };
        formData = {
          png_sticker: stickerFile
        };
      } else if (ext === '.tgs') {
        params = {
          user_id: userId,
          name: name,
          title: title,
          emojis: emojis
        };
        formData = {
          tgs_sticker: stickerFile
        };
      }
    } else {
      // stickerFile is a string, either a file_id or HTTP URL
      params = {
        user_id: userId,
        name: name,
        title: title,
        png_sticker: stickerFile,
        emojis: emojis
      };
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('createNewStickerSet', params, formData, callback);
  }

  addStickerToSet(userId, name, stickerFile, emojis, optionalParams, callback) {
    let params;
    let formData;

    if (isReadableStream(stickerFile)) {
      // stickerFile is a readableStream, check extension
      let ext = Path.extname(stickerFile.path);

      if (ext === '.png') {
        params = {
          user_id: userId,
          name: name,
          emojis: emojis
        };
        formData = {
          png_sticker: stickerFile
        };
      } else if (ext === '.tgs') {
        params = {
          user_id: userId,
          name: name,
          emojis: emojis
        };
        formData = {
          tgs_sticker: stickerFile
        };
      }
    } else {
      // stickerFile is a string, either a file_id or HTTP URL
      params = {
        user_id: userId,
        name: name,
        png_sticker: stickerFile,
        emojis: emojis
      };
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('addStickerToSet', params, formData, callback);
  }

  setStickerPositionInSet(sticker, position, callback) {
    let params = {
      sticker: sticker,
      position: position
    }

    return this._request('setStickerPositionInSet', params, callback);
  }

  deleteStickerFromSet(sticker, callback) {
    let params = {
      sticker: sticker
    }

    return this._request('deleteStickerFromSet', params, callback);
  }

  setStickerSetThumb(name, userId, thumbnailFile, callback) {
    let params;
    let formData;

    if (isReadableStream(thumbnailFile)) {
      // thumbnailFile is a readableStream, check extension
      let ext = Path.extname(thumbnailFile.path);

      if (ext === '.png') {
        params = {
          user_id: userId,
          name: name
        };
        formData = {
          thumb: thumbnailFile
        };
      } else if (ext === '.tgs') {
        params = {
          user_id: userId,
          name: name
        };
        formData = {
          thumb: thumbnailFile
        };
      }
    } else {
      // thumbnailFile is a string, either a file_id or HTTP URL
      params = {
        user_id: userId,
        name: name,
        thumb: thumbnailFile
      };
    }

    return this._request('setStickerSetThumb', params, formData, callback);
  }

  sendVideo(chatId, video, optionalParams, callback) {
    let params;
    let formData;

    if (isReadableStream(video)) {
      params = {
        chat_id: chatId
      };
      formData = {
        video: video
      };
    } else {
      params = {
        chat_id: chatId,
        video: video
      };
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendVideo', params, formData, callback);
  }

  sendVoice(chatId, voice, optionalParams, callback) {
    let params;
    let formData;

    if (isReadableStream(voice)) {
      params = {
        chat_id: chatId
      };
      formData = {
        voice: voice
      };
    } else {
      params = {
        chat_id: chatId,
        voice: voice
      };
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendVoice', params, formData, callback);
  }

  sendVideoNote(chatId, videoNote, optionalParams, callback) {
    let params;
    let formData;

    if (isReadableStream(videoNote)) {
      params = {
        chat_id: chatId
      };
      formData = {
        video_note: videoNote
      };
    } else {
      params = {
        chat_id: chatId,
        video_note: videoNote
      };
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendVideoNote', params, formData, callback);
  }

  sendMediaGroup(chatId, media, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      media: media
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendMediaGroup', params, callback);
  }

  sendLocation(chatId, lat, lon, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      latitude: lat,
      longitude: lon
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendLocation', params, callback);
  }

  editMessageLiveLocation(chatId, messageId, lat, lon, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      message_id: messageId,
      latitude: lat,
      longitude: lon
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('editMessageLiveLocation', params, callback);
  }

  editInlineMessageLiveLocation(inlineMessageId, lat, lon, optionalParams, callback) {
    let params = {
      inline_message_id: inlineMessageId,
      latitude: lat,
      longitude: lon
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('editMessageLiveLocation', params, callback);
  }

  stopMessageLiveLocation(chatId, messageId, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      message_id: messageId
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('stopMessageLiveLocation', params, callback);
  }

  stopInlineMessageLiveLocation(inlineMessageId, optionalParams, callback) {
    let params = {
      inline_message_id: inlineMessageId
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('stopMessageLiveLocation', params, callback);
  }

  sendVenue(chatId, lat, lon, title, address, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      latitude: lat,
      longitude: lon,
      title: title,
      address: address
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendVenue', params, callback);
  }

  sendContact(chatId, phoneNumber, firstName, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      phone_number: phoneNumber,
      first_name: firstName
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendContact', params, callback);
  }

  sendDice(chatId, optionalParams, callback) {
    let params = {
      chat_id: chatId
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendDice', params, callback);
  }

  sendChatAction(chatId, action, callback) {
    if (typeof action !== 'string') {
      throw new Error('sendChatAction method needs a string input');
    }

    let params = {
      chat_id: chatId,
      action: action
    };

    return this._request('sendChatAction', params, callback);
  }

  getUserProfilePhotos(userId, optionalParams, callback) {
    let params = {
      user_id: userId,
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('getUserProfilePhotos', params, callback);
  }

  getFile(fileId, callback) {
    let params = {
      file_id: fileId
    };

    return this._request('getFile', params, callback);
  }

  kickChatMember(chatId, userId, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      user_id: userId
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('kickChatMember', params, callback);
  }

  unbanChatMember(chatId, userId, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      user_id: userId
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('unbanChatMember', params, callback);
  }

  restrictChatMember(chatId, userId, permissions, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      user_id: userId,
      permissions: permissions
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('restrictChatMember', params, callback);
  }

  promoteChatMember(chatId, userId, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      user_id: userId
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('promoteChatMember', params, callback);
  }

  setChatAdministratorCustomTitle(chatId, userId, customTitle, callback) {
    let params = {
      chat_id: chatId,
      user_id: userId,
      custom_title: customTitle
    }

    return this._request('setChatAdministratorCustomTitle', params, callback);
  }

  setChatPermissions(chatId, permissions, callback) {
    let params = {
      chat_id: chatId,
      permissions: permissions
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('setChatPermissions', params, callback);
  }

  exportChatInviteLink(chatId, callback) {
    let params = {
      chat_id: chatId
    }

    return this._request('exportChatInviteLink', params, callback);
  }

  createChatInviteLink(chatId, optionalParams, callback) {
    let params = {
      chat_id: chatId
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('createChatInviteLink', params, callback);
  }

  editChatInviteLink(chatId, inviteLink, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      invite_link: inviteLink
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('editChatInviteLink', params, callback);
  }

  revokeChatInviteLink(chatId, inviteLink, callback) {
    let params = {
      chat_id: chatId,
      invite_link: inviteLink
    }

    return this._request('revokeChatInviteLink', params, callback);
  }

  setChatPhoto(chatId, photo, callback) {
    let params = {
      chat_id: chatId
    };

    let formData = {
      photo: photo
    };

    return this._request('setChatPhoto', params, formData, callback);
  }

  deleteChatPhoto(chatId, callback) {
    let params = {
      chat_id: chatId
    }

    return this._request('deleteChatPhoto', params, callback);
  }

  setChatTitle(chatId, title, callback) {
    let params = {
      chat_id: chatId,
      title: title
    }

    return this._request('setChatTitle', params, callback);
  }

  setChatDescription(chatId, description, callback) {
    let params = {
      chat_id: chatId,
      description: description
    }

    return this._request('setChatDescription', params, callback);
  }

  pinChatMessage(chatId, messageId, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      message_id: messageId
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('pinChatMessage', params, callback);
  }

  unpinChatMessage(chatId, optionalParams, callback) {
    let params = {
      chat_id: chatId
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('unpinChatMessage', params, callback);
  }

  unpinAllChatMessages(chatId, callback) {
    let params = {
      chat_id: chatId
    }

    return this._request('unpinAllChatMessages', params, callback);
  }

  leaveChat(chatId, callback) {
    let params = {
      chat_id: chatId
    };

    return this._request('leaveChat', params, callback);
  }

  getChat(chatId, callback) {
    let params = {
      chat_id: chatId
    };

    return this._request('getChat', params, callback);
  }

  getChatAdministrators(chatId, callback) {
    let params = {
      chat_id: chatId
    };

    return this._request('getChatAdministrators', params, callback);
  }

  getChatMembersCount(chatId, callback) {
    let params = {
      chat_id: chatId
    };

    return this._request('getChatMembersCount', params, callback);
  }

  getChatMember(chatId, userId, callback) {
    let params = {
      chat_id: chatId,
      user_id: userId
    };

    return this._request('getChatMember', params, callback);
  }

  setChatStickerSet(chatId, stickerSetName, callback) {
    let params = {
      chat_id: chatId,
      sticker_set_name: stickerSetName
    }

    return this._request('setChatStickerSet', params, callback);
  }

  deleteChatStickerSet(chatId, callback) {
    let params = {
      chat_id: chatId
    }

    return this._request('deleteChatStickerSet', params, callback);
  }

  // Payment

  sendInvoice(chatId, title, description, payload, providerToken, startParameter, currency, prices, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      title: title,
      description: description,
      payload: payload,
      provider_token: providerToken,
      start_parameter: startParameter,
      currency: currency,
      prices: prices
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendInvoice', params, callback);
  }

  answerShippingQuery(shippingQueryId, ok, callback) {
    let params = {
      shipping_query_id: shippingQueryId,
      ok: ok
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('answerShippingQuery', params, callback);
  }

  answerPreCheckoutQuery(preCheckoutQueryId, ok, errorMessage) {
    let params = {
      pre_checkout_query_id: preCheckoutQueryId,
      ok: ok,
      error_message: errorMessage
    };

    return this._request('answerShippingQuery', params, callback);
  }

  // Games

  sendGame(chatId, gameShortName, optionalParams, callback) {
    let params = {
      chat_id: chatId,
      game_short_name: gameShortName
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('sendGame', params, callback);
  }

  setGameScore(userId, score, optionalParams, callback) {
    let params = {
      user_id: userId,
      score: score
    }

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('setGameScore', params, callback);
  }

  getGameHighScores(userId, optionalParams, callback) {
    let params = {
      user_id: userId
    };

    if (typeof optionalParams == 'function') {
      callback = optionalParams;
    } else {
      Object.assign(params, optionalParams);
    }

    return this._request('getGameHighScores', params, callback);
  }
}

function isReadableStream(object) {
  return object instanceof Stream.Stream &&
    typeof object._read === "function" &&
    typeof object._readableState === "object"
}

module.exports = Telegram;

<MSG> Added all methods

<DFF> @@ -164,6 +164,167 @@ const Telegram = EventEmitter => class extends EventEmitter {
 
     this._request('sendDocument', params);
   }
+
+  sendSticker(chatId, sticker, optionalParams) {
+    let params = {
+      chat_id: chatId,
+      sticker: sticker
+    }
+
+    Object.assign(params, optionalParams);
+
+    this._request('sendSticker', params);
+  }
+
+  sendVideo(chatId, video, optionalParams) {
+    let params = {
+      chat_id: chatId,
+      video: video
+    }
+
+    Object.assign(params, optionalParams);
+
+    this._request('sendVideo', params);
+  }
+
+  sendVoice(chatId, voice, optionalParams) {
+    let params = {
+      chat_id: chatId,
+      voice: voice
+    }
+
+    Object.assign(params, optionalParams);
+
+    this._request('sendVoice', params);
+  }
+
+  sendLocation(chatId, lat, lon, optionalParams) {
+    let params = {
+      chat_id: chatId,
+      latitude: lat,
+      longitude: lon
+    }
+
+    Object.assign(params, optionalParams);
+
+    this._request('sendLocation', params);
+  }
+
+  sendVenue(chatId, lat, lon, title, address, optionalParams) {
+    let params = {
+      chat_id: chatId,
+      latitude: lat,
+      longitude: lon,
+      title: title,
+      address: address
+    }
+
+    Object.assign(params, optionalParams);
+
+    this._request('sendVenue', params);
+  }
+
+  sendContact(chatId, phoneNumber, firstName, optionalParams) {
+    let params = {
+      chat_id: chatId,
+      phone_number: phoneNumber,
+      first_name: firstName
+    }
+
+    Object.assign(params, optionalParams);
+
+    this._request('sendContact', params);
+  }
+
+  sendChatAction(chatId, action) {
+    if (typeof action !== 'string') {
+      throw new Error('sendChatAction method needs a string input');
+    }
+
+    let params = {
+      chat_id: chatId,
+      action: action
+    }
+
+    this._request('sendChatAction', params);
+  }
+
+  getUserProfilePhotos(userId, optionalParams) {
+    let params = {
+      user_id: userId,
+    }
+
+    Object.assign(params, optionalParams);
+
+    this._request('getUserProfilePhotos', params);
+  }
+
+  getFile(fileId) {
+    let params = {
+      file_id: fileId
+    }
+
+    this._request('getFile', params);
+  }
+
+  kickChatMember(chatId, userId) {
+    let params = {
+      chat_id: chatId,
+      user_id: userId
+    }
+
+    this._request('kickChatMember', params);
+  }
+
+  leaveChat(chatId) {
+    let params = {
+      chat_id: chatId
+    }
+
+    this._request('leaveChat', params);
+  }
+
+  unbanChatMember(chatId, userId) {
+    let params = {
+      chat_id: chatId,
+      user_id: userId
+    }
+
+    this._request('unbanChatMember', params);
+  }
+
+  getChat(chatId) {
+    let params = {
+      chat_id: chatId
+    }
+
+    this._request('getChat', params);
+  }
+
+  getChatAdministrators(chatId) {
+    let params = {
+      chat_id: chatId
+    }
+
+    this._request('getChatAdministrators', params);
+  }
+
+  getChatMembersCount(chatId) {
+    let params = {
+      chat_id: chatId
+    }
+
+    this._request('getChatMembersCount', params);
+  }
+
+  getChatMember(chatId, userId) {
+    let params = {
+      chat_id: chatId,
+      user_id: userId
+    }
+
+    this._request('getChatMember', params);
+  }
 }
 
 module.exports = Telegram;
\ No newline at end of file

{'commit': "diff --git a/examples/getUpdates.js b/examples/getUpdates.js\nindex 8bbf37a..d04b0ac 100644\n--- a/examples/getUpdates.js\n+++ b/examples/getUpdates.js\n@@ -7,6 +7,6 @@ telebot.on('message', (message) => {\n   telebot.sendMessage(message.chat.id, 'Message received');\n });\n \n-// // Call API\n+// Call API\n \n telebot.startPolling();\n\\ No newline at end of file\ndiff --git a/src/telegram.js b/src/telegram.js\nindex 4ebd548..3762bfe 100644\n--- a/src/telegram.js\n+++ b/src/telegram.js\n@@ -164,6 +164,167 @@ const Telegram = EventEmitter => class extends EventEmitter {\n \n     this._request('sendDocument', params);\n   }\n+\n+  sendSticker(chatId, sticker, optionalParams) {\n+    let params = {\n+      chat_id: chatId,\n+      sticker: sticker\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('sendSticker', params);\n+  }\n+\n+  sendVideo(chatId, video, optionalParams) {\n+    let params = {\n+      chat_id: chatId,\n+      video: video\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('sendVideo', params);\n+  }\n+\n+  sendVoice(chatId, voice, optionalParams) {\n+    let params = {\n+      chat_id: chatId,\n+      voice: voice\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('sendVoice', params);\n+  }\n+\n+  sendLocation(chatId, lat, lon, optionalParams) {\n+    let params = {\n+      chat_id: chatId,\n+      latitude: lat,\n+      longitude: lon\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('sendLocation', params);\n+  }\n+\n+  sendVenue(chatId, lat, lon, title, address, optionalParams) {\n+    let params = {\n+      chat_id: chatId,\n+      latitude: lat,\n+      longitude: lon,\n+      title: title,\n+      address: address\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('sendVenue', params);\n+  }\n+\n+  sendContact(chatId, phoneNumber, firstName, optionalParams) {\n+    let params = {\n+      chat_id: chatId,\n+      phone_number: phoneNumber,\n+      first_name: firstName\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('sendContact', params);\n+  }\n+\n+  sendChatAction(chatId, action) {\n+    if (typeof action !== 'string') {\n+      throw new Error('sendChatAction method needs a string input');\n+    }\n+\n+    let params = {\n+      chat_id: chatId,\n+      action: action\n+    }\n+\n+    this._request('sendChatAction', params);\n+  }\n+\n+  getUserProfilePhotos(userId, optionalParams) {\n+    let params = {\n+      user_id: userId,\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('getUserProfilePhotos', params);\n+  }\n+\n+  getFile(fileId) {\n+    let params = {\n+      file_id: fileId\n+    }\n+\n+    this._request('getFile', params);\n+  }\n+\n+  kickChatMember(chatId, userId) {\n+    let params = {\n+      chat_id: chatId,\n+      user_id: userId\n+    }\n+\n+    this._request('kickChatMember', params);\n+  }\n+\n+  leaveChat(chatId) {\n+    let params = {\n+      chat_id: chatId\n+    }\n+\n+    this._request('leaveChat', params);\n+  }\n+\n+  unbanChatMember(chatId, userId) {\n+    let params = {\n+      chat_id: chatId,\n+      user_id: userId\n+    }\n+\n+    this._request('unbanChatMember', params);\n+  }\n+\n+  getChat(chatId) {\n+    let params = {\n+      chat_id: chatId\n+    }\n+\n+    this._request('getChat', params);\n+  }\n+\n+  getChatAdministrators(chatId) {\n+    let params = {\n+      chat_id: chatId\n+    }\n+\n+    this._request('getChatAdministrators', params);\n+  }\n+\n+  getChatMembersCount(chatId) {\n+    let params = {\n+      chat_id: chatId\n+    }\n+\n+    this._request('getChatMembersCount', params);\n+  }\n+\n+  getChatMember(chatId, userId) {\n+    let params = {\n+      chat_id: chatId,\n+      user_id: userId\n+    }\n+\n+    this._request('getChatMember', params);\n+  }\n }\n \n module.exports = Telegram;\n\\ No newline at end of file\n", 'commit_subject': 'Added all methods', 'repo_name': 'edisonchee/slimbot', 'committer': {'name': 'Edison Chee', 'email': '27a0423afbbcfc08d54695da9f01ee33529d0ee9@live.com', 'time_sec': '1465028603', 'tz_offset': '480', 'date': {'seconds': '1465028603'}}, 'commit_tree': '1dc3fb6920d97ddd2381321b8ab7d809b62e5b0b', 'commit_message': 'Added all methods\n', 'language_name': 'JavaScript', 'license': 'mit', 'hunks': "@@ -164,6 +164,167 @@ const Telegram = EventEmitter => class extends EventEmitter {\n \n     this._request('sendDocument', params);\n   }\n+\n+  sendSticker(chatId, sticker, optionalParams) {\n+    let params = {\n+      chat_id: chatId,\n+      sticker: sticker\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('sendSticker', params);\n+  }\n+\n+  sendVideo(chatId, video, optionalParams) {\n+    let params = {\n+      chat_id: chatId,\n+      video: video\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('sendVideo', params);\n+  }\n+\n+  sendVoice(chatId, voice, optionalParams) {\n+    let params = {\n+      chat_id: chatId,\n+      voice: voice\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('sendVoice', params);\n+  }\n+\n+  sendLocation(chatId, lat, lon, optionalParams) {\n+    let params = {\n+      chat_id: chatId,\n+      latitude: lat,\n+      longitude: lon\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('sendLocation', params);\n+  }\n+\n+  sendVenue(chatId, lat, lon, title, address, optionalParams) {\n+    let params = {\n+      chat_id: chatId,\n+      latitude: lat,\n+      longitude: lon,\n+      title: title,\n+      address: address\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('sendVenue', params);\n+  }\n+\n+  sendContact(chatId, phoneNumber, firstName, optionalParams) {\n+    let params = {\n+      chat_id: chatId,\n+      phone_number: phoneNumber,\n+      first_name: firstName\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('sendContact', params);\n+  }\n+\n+  sendChatAction(chatId, action) {\n+    if (typeof action !== 'string') {\n+      throw new Error('sendChatAction method needs a string input');\n+    }\n+\n+    let params = {\n+      chat_id: chatId,\n+      action: action\n+    }\n+\n+    this._request('sendChatAction', params);\n+  }\n+\n+  getUserProfilePhotos(userId, optionalParams) {\n+    let params = {\n+      user_id: userId,\n+    }\n+\n+    Object.assign(params, optionalParams);\n+\n+    this._request('getUserProfilePhotos', params);\n+  }\n+\n+  getFile(fileId) {\n+    let params = {\n+      file_id: fileId\n+    }\n+\n+    this._request('getFile', params);\n+  }\n+\n+  kickChatMember(chatId, userId) {\n+    let params = {\n+      chat_id: chatId,\n+      user_id: userId\n+    }\n+\n+    this._request('kickChatMember', params);\n+  }\n+\n+  leaveChat(chatId) {\n+    let params = {\n+      chat_id: chatId\n+    }\n+\n+    this._request('leaveChat', params);\n+  }\n+\n+  unbanChatMember(chatId, userId) {\n+    let params = {\n+      chat_id: chatId,\n+      user_id: userId\n+    }\n+\n+    this._request('unbanChatMember', params);\n+  }\n+\n+  getChat(chatId) {\n+    let params = {\n+      chat_id: chatId\n+    }\n+\n+    this._request('getChat', params);\n+  }\n+\n+  getChatAdministrators(chatId) {\n+    let params = {\n+      chat_id: chatId\n+    }\n+\n+    this._request('getChatAdministrators', params);\n+  }\n+\n+  getChatMembersCount(chatId) {\n+    let params = {\n+      chat_id: chatId\n+    }\n+\n+    this._request('getChatMembersCount', params);\n+  }\n+\n+  getChatMember(chatId, userId) {\n+    let params = {\n+      chat_id: chatId,\n+      user_id: userId\n+    }\n+\n+    this._request('getChatMember', params);\n+  }\n }\n \n module.exports = Telegram;\n\\ No newline at end of file\n", 'addition_count': 161, 'deletion_count': 0, 'src_file': 'a/src/telegram.js', 'tgt_file': 'b/src/telegram.js', 'file_extension': '.js', 'before_file': '\'use strict\';\nconst EventEmitter = require(\'eventemitter3\');\nconst Request = require(\'request-promise\');\nconst Agent = require(\'socks5-https-client/lib/Agent\');\nconst Stream = require(\'stream\');\nconst Path = require(\'path\');\n\nconst Telegram = EventEmitter => class extends EventEmitter {\n  constructor(token, proxy) {\n    super();\n    if (token === undefined) {\n      throw new Error(\'Please provide a Telegram bot token when instantiating\');\n    }\n    this._token = token;\n    if(proxy !== undefined){\n      this._useProxy = true;\n      this._proxy = proxy;\n    }\n  }\n\n  _request(method, params, formData) {\n    if (arguments.length === 0 || typeof arguments[0] !== \'string\') {\n      throw new Error(\'Please provide method as a string\');\n    }\n\n    // the 2nd, 3rd or 4th argument could be a callback\n    let callback;\n    if (typeof arguments[3] == \'function\') {\n      callback = arguments[3];\n    } else if (typeof arguments[2] == \'function\') {\n      callback = arguments[2];\n      formData = null;\n    } else if (typeof arguments[1] == \'function\') {\n      callback = arguments[1];\n      params = null;\n    }\n\n    let options = {\n      uri: \'https://api.telegram.org/bot\' + this._token + \'/\' + method,\n      qs: params,\n      formData: formData,\n      simple: false,\n      resolveWithFullResponse: true,\n      forever: true\n    };\n\n    if(this._useProxy){\n      options.strictSSL = true;\n      options.agentClass = Agent;\n      options.agentOptions = {\n        socksHost: this._proxy.socksHost,\n        socksPort: this._proxy.socksPort\n      };\n      if(this._proxy.socksUsername && this._proxy.socksPassword){\n        options.agentOptions.socksUsername = this._proxy.socksUsername;\n        options.agentOptions.socksPassword = this._proxy.socksPassword;\n      }\n    }\n\n    return Request(options)\n    .then(resp => {\n      if (resp.statusCode !== 200) {\n        throw new Error(resp.statusCode + \':\\n\'+ resp.body);\n      }\n\n      let updates = JSON.parse(resp.body);\n\n      if (updates.ok) {\n        if (callback) { \n          callback(null, updates);\n        }\n\n        return updates;\n      }\n      return null;\n    })\n    .catch(error => {\n      if (callback) {\n        callback(error);\n      }\n      else {\n        throw error;\n      }\n    });\n  }\n\n  getMe(callback) {\n    return this._request(\'getMe\', callback);\n  }\n\n  getUpdates(offset, callback) {\n    let params = {\n      offset: offset,\n      timeout: 10\n    };\n\n    return this._request(\'getUpdates\', params, callback);\n  }\n\n  setWebhook(url, optionalParams, callback) {\n    let params = {\n      url: url\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'setWebhook\', url, params, callback);\n  }\n\n  deleteWebhook(optionalParams, callback) {\n    return this._request(\'deleteWebhook\', optionalParams, callback);\n  }\n\n  getWebhookInfo(callback) {\n    return this._request(\'getWebhookInfo\', callback);\n  }\n\n  logOut(callback) {\n    return this._request(\'logOut\', callback);\n  }\n\n  close(callback) {\n    return this._request(\'close\', callback);\n  }\n\n  sendMessage(chatId, text, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      text: text\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams, callback);\n    }\n\n    return this._request(\'sendMessage\', params, callback);\n  }\n\n  answerCallbackQuery(callbackQueryId, optionalParams, callback) {\n    let params = {\n      callback_query_id: callbackQueryId\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'answerCallbackQuery\', params, callback);\n  }\n\n  setMyCommands(commands, callback) {\n    return this._request(\'setMyCommands\', commands, callback);\n  }\n\n  getMyCommands() {\n\n    this._request(\'sendDocument\', params);\n  }\n}\n\nmodule.exports = Telegram;\n\n    return this._request(\'copyMessage\', params, callback);\n  }\n\n  sendPhoto(chatId, photo, optionalParams, callback) {\n    let params;\n    let formData;\n  \n    if (isReadableStream(photo)) {\n      params = {\n        chat_id: chatId\n      };\n      formData = {\n        photo: photo\n      };\n    } else {\n      params = {\n        chat_id: chatId,\n        photo: photo\n      };\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendPhoto\', params, formData, callback);\n  }\n\n  sendAudio(chatId, audio, optionalParams, callback) {\n    let params;\n    let formData;\n\n    if (isReadableStream(audio)) {\n      params = {\n        chat_id: chatId\n      };\n      formData = {\n        audio: audio\n      };\n    } else {\n      params = {\n        chat_id: chatId,\n        audio: audio\n      };\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendAudio\', params, formData, callback);\n  }\n\n  sendDocument(chatId, document, optionalParams, callback) {\n    let params;\n    let formData;\n\n    if (isReadableStream(document)) {\n      params = {\n        chat_id: chatId\n      };\n      formData = {\n        document: document\n      };\n    } else {\n      params = {\n        chat_id: chatId,\n        document: document\n      };\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendDocument\', params, formData, callback);\n  }\n\n  sendAnimation(chatId, animation, optionalParams, callback) {\n    let params;\n    let formData;\n\n    if (isReadableStream(animation)) {\n      params = {\n        chat_id: chatId\n      };\n      formData = {\n        animation: animation\n      };\n    } else {\n      params = {\n        chat_id: chatId,\n        animation: animation\n      };\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendAnimation\', params, formData, callback);\n  }\n\n  // Polls\n\n  sendPoll(chatId, question, pollOptions, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      question: question,\n      options: pollOptions\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams, callback);\n    }\n\n    return this._request(\'sendPoll\', params, callback);\n  }\n\n  stopPoll(chatId, messageId, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      message_id: messageId\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams, callback);\n    }\n\n    return this._request(\'stopPoll\', params, callback);\n  }\n\n  // Stickers\n\n  sendSticker(chatId, sticker, optionalParams, callback) {\n    let params;\n    let formData;\n\n    if (isReadableStream(sticker)) {\n      params = {\n        chat_id: chatId\n      };\n      formData = {\n        sticker: sticker\n      };\n    } else {\n      params = {\n        chat_id: chatId,\n        sticker: sticker\n      };\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendSticker\', params, formData, callback);\n  }\n\n  getStickerSet(name, callback) {\n    let params = {\n      name: name\n    }\n\n    return this._request(\'getStickerSet\', params, callback);\n  }\n\n  uploadStickerFile(userId, pngFile, callback) {\n    let params = {\n      user_id: userId,\n    };\n\n    let formData = {\n      png_sticker: pngFile\n    };\n\n    return this._request(\'uploadStickerFile\', params, formData, callback);\n  }\n\n  createNewStickerSet(userId, name, title, stickerFile, emojis, optionalParams, callback) {\n    let params;\n    let formData;\n\n    if (isReadableStream(stickerFile)) {\n      // stickerFile is a readableStream, check extension\n      let ext = Path.extname(stickerFile.path);\n      \n      if (ext === \'.png\') {\n        params = {\n          user_id: userId,\n          name: name,\n          title: title,\n          emojis: emojis\n        };\n        formData = {\n          png_sticker: stickerFile\n        };\n      } else if (ext === \'.tgs\') {\n        params = {\n          user_id: userId,\n          name: name,\n          title: title,\n          emojis: emojis\n        };\n        formData = {\n          tgs_sticker: stickerFile\n        };\n      }\n    } else {\n      // stickerFile is a string, either a file_id or HTTP URL\n      params = {\n        user_id: userId,\n        name: name,\n        title: title,\n        png_sticker: stickerFile,\n        emojis: emojis\n      };\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'createNewStickerSet\', params, formData, callback);\n  }\n\n  addStickerToSet(userId, name, stickerFile, emojis, optionalParams, callback) {\n    let params;\n    let formData;\n\n    if (isReadableStream(stickerFile)) {\n      // stickerFile is a readableStream, check extension\n      let ext = Path.extname(stickerFile.path);\n\n      if (ext === \'.png\') {\n        params = {\n          user_id: userId,\n          name: name,\n          emojis: emojis\n        };\n        formData = {\n          png_sticker: stickerFile\n        };\n      } else if (ext === \'.tgs\') {\n        params = {\n          user_id: userId,\n          name: name,\n          emojis: emojis\n        };\n        formData = {\n          tgs_sticker: stickerFile\n        };\n      }\n    } else {\n      // stickerFile is a string, either a file_id or HTTP URL\n      params = {\n        user_id: userId,\n        name: name,\n        png_sticker: stickerFile,\n        emojis: emojis\n      };\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'addStickerToSet\', params, formData, callback);\n  }\n\n  setStickerPositionInSet(sticker, position, callback) {\n    let params = {\n      sticker: sticker,\n      position: position\n    }\n\n    return this._request(\'setStickerPositionInSet\', params, callback);\n  }\n\n  deleteStickerFromSet(sticker, callback) {\n    let params = {\n      sticker: sticker\n    }\n\n    return this._request(\'deleteStickerFromSet\', params, callback);\n  }\n\n  setStickerSetThumb(name, userId, thumbnailFile, callback) {\n    let params;\n    let formData;\n\n    if (isReadableStream(thumbnailFile)) {\n      // thumbnailFile is a readableStream, check extension\n      let ext = Path.extname(thumbnailFile.path);\n\n      if (ext === \'.png\') {\n        params = {\n          user_id: userId,\n          name: name\n        };\n        formData = {\n          thumb: thumbnailFile\n        };\n      } else if (ext === \'.tgs\') {\n        params = {\n          user_id: userId,\n          name: name\n        };\n        formData = {\n          thumb: thumbnailFile\n        };\n      }\n    } else {\n      // thumbnailFile is a string, either a file_id or HTTP URL\n      params = {\n        user_id: userId,\n        name: name,\n        thumb: thumbnailFile\n      };\n    }\n\n    return this._request(\'setStickerSetThumb\', params, formData, callback);\n  }\n\n  sendVideo(chatId, video, optionalParams, callback) {\n    let params;\n    let formData;\n\n    if (isReadableStream(video)) {\n      params = {\n        chat_id: chatId\n      };\n      formData = {\n        video: video\n      };\n    } else {\n      params = {\n        chat_id: chatId,\n        video: video\n      };\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendVideo\', params, formData, callback);\n  }\n\n  sendVoice(chatId, voice, optionalParams, callback) {\n    let params;\n    let formData;\n\n    if (isReadableStream(voice)) {\n      params = {\n        chat_id: chatId\n      };\n      formData = {\n        voice: voice\n      };\n    } else {\n      params = {\n        chat_id: chatId,\n        voice: voice\n      };\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendVoice\', params, formData, callback);\n  }\n\n  sendVideoNote(chatId, videoNote, optionalParams, callback) {\n    let params;\n    let formData;\n\n    if (isReadableStream(videoNote)) {\n      params = {\n        chat_id: chatId\n      };\n      formData = {\n        video_note: videoNote\n      };\n    } else {\n      params = {\n        chat_id: chatId,\n        video_note: videoNote\n      };\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendVideoNote\', params, formData, callback);\n  }\n\n  sendMediaGroup(chatId, media, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      media: media\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendMediaGroup\', params, callback);\n  }\n\n  sendLocation(chatId, lat, lon, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      latitude: lat,\n      longitude: lon\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendLocation\', params, callback);\n  }\n\n  editMessageLiveLocation(chatId, messageId, lat, lon, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      message_id: messageId,\n      latitude: lat,\n      longitude: lon\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'editMessageLiveLocation\', params, callback);\n  }\n\n  editInlineMessageLiveLocation(inlineMessageId, lat, lon, optionalParams, callback) {\n    let params = {\n      inline_message_id: inlineMessageId,\n      latitude: lat,\n      longitude: lon\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'editMessageLiveLocation\', params, callback);\n  }\n\n  stopMessageLiveLocation(chatId, messageId, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      message_id: messageId\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'stopMessageLiveLocation\', params, callback);\n  }\n\n  stopInlineMessageLiveLocation(inlineMessageId, optionalParams, callback) {\n    let params = {\n      inline_message_id: inlineMessageId\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'stopMessageLiveLocation\', params, callback);\n  }\n\n  sendVenue(chatId, lat, lon, title, address, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      latitude: lat,\n      longitude: lon,\n      title: title,\n      address: address\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendVenue\', params, callback);\n  }\n\n  sendContact(chatId, phoneNumber, firstName, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      phone_number: phoneNumber,\n      first_name: firstName\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendContact\', params, callback);\n  }\n\n  sendDice(chatId, optionalParams, callback) {\n    let params = {\n      chat_id: chatId\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendDice\', params, callback);\n  }\n\n  sendChatAction(chatId, action, callback) {\n    if (typeof action !== \'string\') {\n      throw new Error(\'sendChatAction method needs a string input\');\n    }\n\n    let params = {\n      chat_id: chatId,\n      action: action\n    };\n\n    return this._request(\'sendChatAction\', params, callback);\n  }\n\n  getUserProfilePhotos(userId, optionalParams, callback) {\n    let params = {\n      user_id: userId,\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'getUserProfilePhotos\', params, callback);\n  }\n\n  getFile(fileId, callback) {\n    let params = {\n      file_id: fileId\n    };\n\n    return this._request(\'getFile\', params, callback);\n  }\n\n  kickChatMember(chatId, userId, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      user_id: userId\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'kickChatMember\', params, callback);\n  }\n\n  unbanChatMember(chatId, userId, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      user_id: userId\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'unbanChatMember\', params, callback);\n  }\n\n  restrictChatMember(chatId, userId, permissions, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      user_id: userId,\n      permissions: permissions\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'restrictChatMember\', params, callback);\n  }\n\n  promoteChatMember(chatId, userId, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      user_id: userId\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'promoteChatMember\', params, callback);\n  }\n\n  setChatAdministratorCustomTitle(chatId, userId, customTitle, callback) {\n    let params = {\n      chat_id: chatId,\n      user_id: userId,\n      custom_title: customTitle\n    }\n\n    return this._request(\'setChatAdministratorCustomTitle\', params, callback);\n  }\n\n  setChatPermissions(chatId, permissions, callback) {\n    let params = {\n      chat_id: chatId,\n      permissions: permissions\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'setChatPermissions\', params, callback);\n  }\n\n  exportChatInviteLink(chatId, callback) {\n    let params = {\n      chat_id: chatId\n    }\n\n    return this._request(\'exportChatInviteLink\', params, callback);\n  }\n\n  createChatInviteLink(chatId, optionalParams, callback) {\n    let params = {\n      chat_id: chatId\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'createChatInviteLink\', params, callback);\n  }\n\n  editChatInviteLink(chatId, inviteLink, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      invite_link: inviteLink\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'editChatInviteLink\', params, callback);\n  }\n\n  revokeChatInviteLink(chatId, inviteLink, callback) {\n    let params = {\n      chat_id: chatId,\n      invite_link: inviteLink\n    }\n\n    return this._request(\'revokeChatInviteLink\', params, callback);\n  }\n\n  setChatPhoto(chatId, photo, callback) {\n    let params = {\n      chat_id: chatId\n    };\n\n    let formData = {\n      photo: photo\n    };\n\n    return this._request(\'setChatPhoto\', params, formData, callback);\n  }\n\n  deleteChatPhoto(chatId, callback) {\n    let params = {\n      chat_id: chatId\n    }\n\n    return this._request(\'deleteChatPhoto\', params, callback);\n  }\n\n  setChatTitle(chatId, title, callback) {\n    let params = {\n      chat_id: chatId,\n      title: title\n    }\n\n    return this._request(\'setChatTitle\', params, callback);\n  }\n\n  setChatDescription(chatId, description, callback) {\n    let params = {\n      chat_id: chatId,\n      description: description\n    }\n\n    return this._request(\'setChatDescription\', params, callback);\n  }\n\n  pinChatMessage(chatId, messageId, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      message_id: messageId\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'pinChatMessage\', params, callback);\n  }\n\n  unpinChatMessage(chatId, optionalParams, callback) {\n    let params = {\n      chat_id: chatId\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'unpinChatMessage\', params, callback);\n  }\n\n  unpinAllChatMessages(chatId, callback) {\n    let params = {\n      chat_id: chatId\n    }\n\n    return this._request(\'unpinAllChatMessages\', params, callback);\n  }\n\n  leaveChat(chatId, callback) {\n    let params = {\n      chat_id: chatId\n    };\n\n    return this._request(\'leaveChat\', params, callback);\n  }\n\n  getChat(chatId, callback) {\n    let params = {\n      chat_id: chatId\n    };\n\n    return this._request(\'getChat\', params, callback);\n  }\n\n  getChatAdministrators(chatId, callback) {\n    let params = {\n      chat_id: chatId\n    };\n\n    return this._request(\'getChatAdministrators\', params, callback);\n  }\n\n  getChatMembersCount(chatId, callback) {\n    let params = {\n      chat_id: chatId\n    };\n\n    return this._request(\'getChatMembersCount\', params, callback);\n  }\n\n  getChatMember(chatId, userId, callback) {\n    let params = {\n      chat_id: chatId,\n      user_id: userId\n    };\n\n    return this._request(\'getChatMember\', params, callback);\n  }\n\n  setChatStickerSet(chatId, stickerSetName, callback) {\n    let params = {\n      chat_id: chatId,\n      sticker_set_name: stickerSetName\n    }\n\n    return this._request(\'setChatStickerSet\', params, callback);\n  }\n\n  deleteChatStickerSet(chatId, callback) {\n    let params = {\n      chat_id: chatId\n    }\n\n    return this._request(\'deleteChatStickerSet\', params, callback);\n  }\n\n  // Payment\n\n  sendInvoice(chatId, title, description, payload, providerToken, startParameter, currency, prices, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      title: title,\n      description: description,\n      payload: payload,\n      provider_token: providerToken,\n      start_parameter: startParameter,\n      currency: currency,\n      prices: prices\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendInvoice\', params, callback);\n  }\n\n  answerShippingQuery(shippingQueryId, ok, callback) {\n    let params = {\n      shipping_query_id: shippingQueryId,\n      ok: ok\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'answerShippingQuery\', params, callback);\n  }\n\n  answerPreCheckoutQuery(preCheckoutQueryId, ok, errorMessage) {\n    let params = {\n      pre_checkout_query_id: preCheckoutQueryId,\n      ok: ok,\n      error_message: errorMessage\n    };\n\n    return this._request(\'answerShippingQuery\', params, callback);\n  }\n\n  // Games\n\n  sendGame(chatId, gameShortName, optionalParams, callback) {\n    let params = {\n      chat_id: chatId,\n      game_short_name: gameShortName\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'sendGame\', params, callback);\n  }\n\n  setGameScore(userId, score, optionalParams, callback) {\n    let params = {\n      user_id: userId,\n      score: score\n    }\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'setGameScore\', params, callback);\n  }\n\n  getGameHighScores(userId, optionalParams, callback) {\n    let params = {\n      user_id: userId\n    };\n\n    if (typeof optionalParams == \'function\') {\n      callback = optionalParams;\n    } else {\n      Object.assign(params, optionalParams);\n    }\n\n    return this._request(\'getGameHighScores\', params, callback);\n  }\n}\n\nfunction isReadableStream(object) {\n  return object instanceof Stream.Stream &&\n    typeof object._read === "function" &&\n    typeof object._readableState === "object"\n}\n\nmodule.exports = Telegram;\n', 'message': 'Added all methods\n', 'author_name': 'Edison Chee', 'lang': 'js'}