跳到主要內容

使用 Node.js、Telebot 從無到有開發比特幣 (Bitcoin)、加密貨幣查價報價機器人 (Telegram Bot)



Telegram Bot 可以說是 Telegram 的一大特色,它本身提供了很好的 API 供開發者製作自己的機器人,功能也不侷限於聊天、回答問題,能使用不同程式語言 (Python、Javascript...等) 來去跟遠端伺服器互動,抓取訊息給使用者,所以就有人做出了播報新聞的 Bot,而這次就要做一個非常非常簡單版的比特幣、加密貨幣查價機器人,將會用 Node.js 的 Request 套件去和 Coinmarketcap 所提供的 API 互動。


首先要先在 Telegram 這端建立自己的 Bot,到 @BotFather 這個機器人老爸按照指示生成一個機器人,並將 Token 代碼複製起來供等會對接使用。


再來就要建置開發的環境了,你可以選擇在本機上 Host 這個機器人,或是使用 GCPAWS 等雲端主機來架設就不必一直開機了。


curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs
那這邊以建立在本機為例 (其實都是一樣的啦),Windows 系統直接到官網下載並安裝 Node.js 8.9.4 LTS ,或在 Linux 就是使用上述指令即可完成安裝 Node.js。


cd 你想要安裝 Telegram Bot 的路徑
npm install telebot --save
npm install request
然後在你想要的路徑創建一個 Telegram Bot 的資料夾,CD 到該資料夾後使用上述指令安裝 Telebot 這個方便你開發 Telegram 機器人的架構以及 Request 套件。(基本上 6 版後的 Node.js 都內建 NPM,可以直接安裝)


然後在資料夾內新建一個 BOT.js 檔,整個資料夾看起來應該會像上圖一樣。


var TeleBot = require('telebot');
var bot = new TeleBot('你的 Bot Token');
var request = require('request');
/*BOT 腳本開始*/


/*BOT 腳本結束*/
bot.connect();
接著使用文字編輯器或你習慣的編輯器開啟 BOT.js,將上面的程式碼修改成你的 Bot Token 並貼上,而之後機器人要運行的腳本就可以撰寫在開始與結束之間,其實現在這樣 Bot 已經可以運作了,只是不會有任何反應。


var price,symbol;  //定義兩個變數供使用

bot.on('/BTC', msg => {  //收到 /BTC 指令時傳訊息
  let fromId = msg.chat.id;
  let Name = msg.from.username;  

  request.get("https://api.coinmarketcap.com/v1/ticker/bitcoin",  //從 CMC 抓取資料
    function(error, response, body) {  
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ Name }, ${ symbol } : $${ price }`);  //傳送訊息
  });
});
接著就是重點了,照上方的腳本它先定義兩個變數 (price、symbol) 供之後使用,以及 msg.chat.id 代表發送訊息的 ID,它會自動抓取是要發在群組、私訊...等,這是 Telegram 的訊息規則不能更改,msg.from.username 則是會調用使用者 ID,讓機器人在回訊息時可以順便 Tag 對方。後續就是會從 CMC 抓取比特幣的價格再輸出 (bot.sendMessage) 到對話中。


直接看圖可能更好理解,就是你打 /BTC,它就會 Tag 你再回報價格。


到目前為止你的腳本應該會長的像這樣了,這已經是完全可以使用,在群組或個人訊息收到 /BTC 指令就會自動回報價格。


node BOT.js
在你的路徑下使用上述指令就可以啟動機器人了,能到 Telegram 測試看看它會不會回話。





但如果只能查 BTC 一個當然不夠啊,當然你可以一個一個慢慢新增,只要更改 Coinmarketcap 的 API 網址就可以了,可以參考 CMC 的文件或直接複製我用好的版本,已經包含十大貨幣和一些我有在關注的 Altcoin。

var TeleBot = require('telebot');
var bot = new TeleBot('你的 Bot Token');
var request = require('request');


var price,symbol;

bot.on('/BTC', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;

  request.get("https://api.coinmarketcap.com/v1/ticker/bitcoin",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/ETH', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;

  request.get("https://api.coinmarketcap.com/v1/ticker/ethereum",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/LTC', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;
  request.get("https://api.coinmarketcap.com/v1/ticker/litecoin",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/XMR', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;
  request.get("https://api.coinmarketcap.com/v1/ticker/monero",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/XRP', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;
  request.get("https://api.coinmarketcap.com/v1/ticker/ripple",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/BCH', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;
  request.get("https://api.coinmarketcap.com/v1/ticker/bitcoin-cash",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/NEO', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;
  request.get("https://api.coinmarketcap.com/v1/ticker/neo",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/ADA', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;
  request.get("https://api.coinmarketcap.com/v1/ticker/cardano",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/IOTA', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;
  request.get("https://api.coinmarketcap.com/v1/ticker/iota",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/EOS', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;
  request.get("https://api.coinmarketcap.com/v1/ticker/eos",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/XLM', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;
  request.get("https://api.coinmarketcap.com/v1/ticker/stellar",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/DASH', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;
  request.get("https://api.coinmarketcap.com/v1/ticker/dash",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/ETN', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;
  request.get("https://api.coinmarketcap.com/v1/ticker/electroneum",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});
bot.on('/BNB', msg => {
  let fromId = msg.chat.id;
  let firstName = msg.from.username;
  let reply = msg.message_id;
  request.get("https://api.coinmarketcap.com/v1/ticker/binance-coin",
    function(error, response, body) {
    price = JSON.parse(body)[0].price_usd;
symbol = JSON.parse(body)[0].symbol;
      return bot.sendMessage(fromId, `@${ firstName }, ${ symbol } : $${ price }`);
  });
});

bot.connect();
這或許不是最聰明正確的寫法,但反正你叫它它會回,也不會報錯價那就好啦,不要太計較。如果對 Telegram Bot 有興趣可以參考官方的 API 文件,以及去看看 Telebot 這個以 Node.js 為底方便你使用的版本。 



留言



這個網誌中的熱門文章

Linux (Ubuntu) 查詢硬碟容量、剩餘大小指令

在 Ubuntu Desktop 版本或有安裝 GUI 像 Xfce 的 Server 版本當然可以直接從圖形介面查看硬碟容量和已經使用的大小, 但如果是在純 CLI 版本或使用 SSH 連線時呢?那就需要用到指令了。 顯示硬碟容量、已使用、可用大小。 df -h 查詢資料夾所占硬碟的大小。 du -h 查詢檔案大小 ls -l

吃光硬碟讀寫的大怪獸 - Superfetch 是什麼?可以關嗎?

Superfetch 是 Windows 內建的硬碟快取功能,它會預先將檔案讀取起來到 Ram 裡方便稍後做使用,所以常常在工作管理員內都可以看到 Superfetch 往往占掉了不少的硬碟使用量,那這樣的情形是好的嗎?其實理論上並不會有太大影響,畢竟 Superfetch 只是將等會要讀取的內容先預置在 Ram 中,如果不趁硬碟負載小的時候優先讀取,之後反而可能忙不過來呢。當然如果你是使用 SSD 的話可能會為使用壽命擔心, 高頻率的讀取可能加速固態硬碟老化,那在讀取速度原本就很快的 SSD 當然就相對的沒有必要開啟 Superfetch 了。 Superfetch 在電腦待機時吃掉大部分硬碟使用量是很常有的事。 要關閉也很簡單, Win+R > services.msc 打開「服務」,找到 Superfetch。 右鍵 > 內容,將它更改為「 已停用 」後確定即可。

TLS / SSL 金鑰轉檔,「.crt / .key」如何轉成「.pem」?( OpenSSL 教學)

不管是哪個 Certificate Authority (CA) 發的憑證多半金鑰檔都是給「.crt / .key」格式的檔案,像是「ca_bundle.crt」、「 certificate.crt」和「.private.key」這種檔案, 但是在實際使用 (Nginx、Apache...等伺服器) 卻會需要的是「.pem」檔 ,那要怎麼轉換呢?其實可以直接使用 OpenSSL 這個軟體和幾行指令來達成。 OpenSSL 官方網站 :  https://www.openssl.org 下載頁面 :  https://www.openssl.org/source sudo apt-get install openssl 以 Linux (Ubuntu / Debian ...等) 為例,可以直接使用 apt-get 指令下載安裝 OpenSSL,如果是其他系統可以參考官方網站的說明。 openssl rsa -in private.key -text > private.pem openssl x509 -inform PEM -in certificate.crt > certificate.pem openssl x509 -inform PEM -in ca_bundle.crt > ca_bundle.pem 以前述所提到的「ca_bundle.crt」、「 certificate.crt」和「.private.key」三個檔案為例,就可以用上方的指令完成轉檔,其實同副檔名的轉檔指令都相同,所以兩個「.crt」的指令其實是重複的,也要記得套換成自己的檔案名稱。 如果需要申請免費的 SSL 憑證也可以參考之前介紹過的 SSL For Free ,它是使用「Let's Encrypt」核發的憑證,以及如果覺得申請憑證和定期更新太麻煩,也可以考慮自動化的 Caddy Server 能自動幫網站升級 HTTPS。