diff --git a/config/message.js b/config/message.js
index 0a18305..8618c97 100644
--- a/config/message.js
+++ b/config/message.js
@@ -1,5 +1,5 @@
module.exports = {
- TELEGRAM_START: 'Hello! I am {{botName}} 🤖\n\nCommand:\n/price <symbol> <interval>\n/chart <symbol> <interval> <studies>\n/example\n\nFollow me on Twitter:\n@CryptoOpnBot\n\nWebSite:\ncrypto.opnbot.com\n\nGitHub:\nsource code\n',
+ TELEGRAM_START: 'Hello! I am {{botName}} 🤖\n\nCommand:\n/price <symbol> <interval>\n/chart <symbol> <interval> <studies>\n/fear_greed_index\n/example\n\nFollow me on Twitter:\n@CryptoOpnBot\n\nWebSite:\ncrypto.opnbot.com\n\nGitHub:\nsource code\n',
TELEGRAM_EXAMPLE: 'Example:\n\n/price\n/price tsla\n/price goog\n/price btcusdt\n/price btcusdt 1M\n/price bitfinex:ethusd\n/price bitfinex:ethusd all\n/price <symbol> <interval>\n\nSupport Intervals: 1d,1M,3M,1Y,5Y,all\n\n/chart\n/chart aapl\n/chart msft\n/chart btcusdt\n/chart btcusdt 15m\n/chart btcusdt 4h RSI;MA:50;MA:200\n/chart coinbase:ethusd 30m\n/chart coinbase:ethusd 1h MACD\n/chart <symbol> <interval> <studies>\n\nSupport Intervals: 1m,3m,5m,15m,30m,45m,1h,2h,3h,4h,1d,1w\n',
TOO_MANY_REQUEST: 'Too many request. Please try again later.',
INVALID_REQUEST: 'Invalid request. Try /example.',
diff --git a/src/telegram.js b/src/telegram.js
index 9a47548..347bfad 100644
--- a/src/telegram.js
+++ b/src/telegram.js
@@ -9,6 +9,7 @@ const CB_ACTION_PRICE_SYMBOL = 'price-symbol'
const CB_ACTION_CHART_SYMBOL = 'chart-symbol'
const CB_ACTION_CHART_INTERVAL = 'chart-interval'
const CB_ACTION_CHART_STUDIES = 'chart-studies'
+const CB_ACTION_FG_INDEX = 'fear-greed-index'
module.exports = (log, argv, version, setting) => {
const TelegramBot = require('@lib/telegram')
@@ -16,8 +17,6 @@ module.exports = (log, argv, version, setting) => {
const chatLimit = new NodeCache({ stdTTL: 60 }) // rate limit ttl per minute
const teleBot = new TelegramBot(argv.telegramToken, { polling: true })
- const BOT_NAME = process.env.BOT_NAME || setting.BOT_NAME
-
log.verbose('\nRunning Telegram Server ✓')
axios.defaults.headers.common['user-agent'] = `cryptoOpnBot/${version}`
@@ -35,6 +34,10 @@ module.exports = (log, argv, version, setting) => {
command: '/chart',
description: 'Advanced Chart.',
},
+ {
+ command: '/fear_greed_index',
+ description: 'Crypto Market Sentiment Index',
+ },
{
command: '/example',
description: 'Command examples.',
@@ -56,7 +59,7 @@ module.exports = (log, argv, version, setting) => {
if (text === '/start') {
return teleBot.sendMessage(
chat.id,
- MESSAGE.TELEGRAM_START.replace('{{botName}}', BOT_NAME),
+ MESSAGE.TELEGRAM_START.replace('{{botName}}', setting.BOT_NAME),
{
parse_mode: 'HTML',
}
@@ -69,7 +72,6 @@ module.exports = (log, argv, version, setting) => {
.then((res) =>
teleBot.sendPhoto(chat.id, res.data, {
caption: getPriceCaption(eSymbol),
- parse_mode: 'HTML',
reply_markup: {
inline_keyboard: getChunkInputObjs(
CB_ACTION_PRICE_SYMBOL,
@@ -88,7 +90,6 @@ module.exports = (log, argv, version, setting) => {
.then((res) =>
teleBot.sendPhoto(chat.id, res.data, {
caption: getChartCaption(eSymbol),
- parse_mode: 'HTML',
reply_markup: {
inline_keyboard: getChunkInputObjs(
CB_ACTION_CHART_SYMBOL,
@@ -109,7 +110,6 @@ module.exports = (log, argv, version, setting) => {
.then((res) =>
teleBot.sendPhoto(chat.id, res.data, {
caption: getPriceCaption(eSymbol, interval),
- parse_mode: 'HTML',
})
)
} else if (text?.startsWith('/chart')) {
@@ -123,7 +123,18 @@ module.exports = (log, argv, version, setting) => {
.then((res) =>
teleBot.sendPhoto(chat.id, res.data, {
caption: getChartCaption(eSymbol, interval, splitStudies),
- parse_mode: 'HTML',
+ })
+ )
+ } else if (text?.startsWith('/fear_greed_index')) {
+ return axios
+ .get(setting.CRYPTO_FEAR_GREED_INDEX_URL, {
+ responseType: 'arraybuffer',
+ })
+ .then((res) =>
+ teleBot.sendPhoto(chat.id, res.data, {
+ reply_markup: {
+ inline_keyboard: getInputReload(CB_ACTION_FG_INDEX),
+ },
})
)
} else if (text?.startsWith('/example')) {
@@ -202,6 +213,13 @@ module.exports = (log, argv, version, setting) => {
)
)
}
+ } else if (cbKey === CB_ACTION_FG_INDEX) {
+ return reqReloadEditMsgPhoto(
+ CB_ACTION_FG_INDEX,
+ setting.CRYPTO_FEAR_GREED_INDEX_URL,
+ chat.id,
+ message_id
+ )
} else {
throw Error('Unable to get symbol from callback query.')
}
@@ -300,8 +318,7 @@ module.exports = (log, argv, version, setting) => {
* @returns {String} price image caption
*/
function getPriceCaption(eSymbol, interval = null) {
- const url = getPriceImgApiUrl(eSymbol, interval) // external to use default size
- return `${eSymbol.toUpperCase()} ${interval || setting.DEFAULT_PRICE_INTERVAL}` // prettier-ignore
+ return `${eSymbol.toUpperCase()} ${interval || setting.DEFAULT_PRICE_INTERVAL}`
}
/**
@@ -311,11 +328,11 @@ module.exports = (log, argv, version, setting) => {
* @returns {String} chart image caption
*/
function getChartCaption(eSymbol, interval = null, studies = null) {
- const url = getChartImgApiUrl(eSymbol, interval, studies) // external to use default size
const dInterval = interval || setting.DEFAULT_CHART_INTERVAL
const dStudies = studies || setting.DEFAULT_CHART_STUDIES
const studyIds = lodash.uniq(dStudies.map((dStudy) => dStudy.split(':')[0]))
- return `${eSymbol.toUpperCase()} ${dInterval} ${studyIds.toString()}`
+
+ return `${eSymbol.toUpperCase()} ${dInterval} ${studyIds.toString()}`
}
/**
@@ -338,7 +355,6 @@ module.exports = (log, argv, version, setting) => {
.then((res) => {
const opt = getEditMsgPhotoOpt(chatId, msgId, res.data, {
caption: getPriceCaption(...inputs),
- parse_mode: 'HTML',
})
if (inputKeys) {
opt.qs.reply_markup = {
@@ -349,6 +365,28 @@ module.exports = (log, argv, version, setting) => {
})
}
+ /**
+ * @param {String} cbKey
+ * @param {String} url
+ * @param {Integer} chatId
+ * @param {Integer} msgId
+ * @returns {Promise}
+ */
+ function reqReloadEditMsgPhoto(cbKey, url, chatId, msgId) {
+ return axios
+ .get(url, {
+ responseType: 'arraybuffer',
+ })
+ .then((res) => {
+ const opt = getEditMsgPhotoOpt(chatId, msgId, res.data)
+
+ opt.qs.reply_markup = {
+ inline_keyboard: getInputReload(cbKey),
+ }
+ return teleBot._request('editMessageMedia', opt)
+ })
+ }
+
/**
* @param {Integer} chatId
* @param {Integer} msgId
@@ -366,7 +404,6 @@ module.exports = (log, argv, version, setting) => {
.then((res) => {
const opt = getEditMsgPhotoOpt(chatId, msgId, res.data, {
caption: getChartCaption(...inputs),
- parse_mode: 'HTML',
})
if (inputKeys) {
opt.qs.reply_markup = {
@@ -427,6 +464,21 @@ module.exports = (log, argv, version, setting) => {
]
}
+ /**
+ * @param {String} cbKey
+ * @returns {Array}
+ */
+ function getInputReload(cbKey) {
+ return [
+ [
+ {
+ text: '↻ ' + new Date().toISOString(), // must be a unique message (400 Bad Request: message is not modified)
+ callback_data: cbKey,
+ },
+ ],
+ ]
+ }
+
/**
* generate inline keyboard inputs
*