Merge pull request #2211 from freqtrade/dependabot/pip/develop/python-telegram-bot-12.0.0
Bump python-telegram-bot from 11.1.0 to 12.0.0
This commit is contained in:
commit
74578b8752
@ -4,12 +4,12 @@
|
|||||||
This module manage Telegram communication
|
This module manage Telegram communication
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Callable, Dict, List
|
from typing import Any, Callable, Dict
|
||||||
|
|
||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
from telegram import Bot, ParseMode, ReplyKeyboardMarkup, Update
|
from telegram import ParseMode, ReplyKeyboardMarkup, Update
|
||||||
from telegram.error import NetworkError, TelegramError
|
from telegram.error import NetworkError, TelegramError
|
||||||
from telegram.ext import CommandHandler, Updater
|
from telegram.ext import CommandHandler, Updater, CallbackContext
|
||||||
|
|
||||||
from freqtrade.__init__ import __version__
|
from freqtrade.__init__ import __version__
|
||||||
from freqtrade.rpc import RPC, RPCException, RPCMessageType
|
from freqtrade.rpc import RPC, RPCException, RPCMessageType
|
||||||
@ -31,7 +31,7 @@ def authorized_only(command_handler: Callable[..., None]) -> Callable[..., Any]:
|
|||||||
"""
|
"""
|
||||||
def wrapper(self, *args, **kwargs):
|
def wrapper(self, *args, **kwargs):
|
||||||
""" Decorator logic """
|
""" Decorator logic """
|
||||||
update = kwargs.get('update') or args[1]
|
update = kwargs.get('update') or args[0]
|
||||||
|
|
||||||
# Reject unauthorized messages
|
# Reject unauthorized messages
|
||||||
chat_id = int(self._config['telegram']['chat_id'])
|
chat_id = int(self._config['telegram']['chat_id'])
|
||||||
@ -79,7 +79,8 @@ class Telegram(RPC):
|
|||||||
registers all known command handlers
|
registers all known command handlers
|
||||||
and starts polling for message updates
|
and starts polling for message updates
|
||||||
"""
|
"""
|
||||||
self._updater = Updater(token=self._config['telegram']['token'], workers=0)
|
self._updater = Updater(token=self._config['telegram']['token'], workers=0,
|
||||||
|
use_context=True)
|
||||||
|
|
||||||
# Register command handler and start telegram message polling
|
# Register command handler and start telegram message polling
|
||||||
handles = [
|
handles = [
|
||||||
@ -96,7 +97,7 @@ class Telegram(RPC):
|
|||||||
CommandHandler('reload_conf', self._reload_conf),
|
CommandHandler('reload_conf', self._reload_conf),
|
||||||
CommandHandler('stopbuy', self._stopbuy),
|
CommandHandler('stopbuy', self._stopbuy),
|
||||||
CommandHandler('whitelist', self._whitelist),
|
CommandHandler('whitelist', self._whitelist),
|
||||||
CommandHandler('blacklist', self._blacklist, pass_args=True),
|
CommandHandler('blacklist', self._blacklist),
|
||||||
CommandHandler('edge', self._edge),
|
CommandHandler('edge', self._edge),
|
||||||
CommandHandler('help', self._help),
|
CommandHandler('help', self._help),
|
||||||
CommandHandler('version', self._version),
|
CommandHandler('version', self._version),
|
||||||
@ -175,7 +176,7 @@ class Telegram(RPC):
|
|||||||
self._send_msg(message)
|
self._send_msg(message)
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _status(self, bot: Bot, update: Update) -> None:
|
def _status(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /status.
|
Handler for /status.
|
||||||
Returns the current TradeThread status
|
Returns the current TradeThread status
|
||||||
@ -184,11 +185,8 @@ class Telegram(RPC):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Check if additional parameters are passed
|
if 'table' in context.args:
|
||||||
params = update.message.text.replace('/status', '').split(' ') \
|
self._status_table(update, context)
|
||||||
if update.message.text else []
|
|
||||||
if 'table' in params:
|
|
||||||
self._status_table(bot, update)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -221,13 +219,13 @@ class Telegram(RPC):
|
|||||||
messages.append("\n".join([l for l in lines if l]).format(**r))
|
messages.append("\n".join([l for l in lines if l]).format(**r))
|
||||||
|
|
||||||
for msg in messages:
|
for msg in messages:
|
||||||
self._send_msg(msg, bot=bot)
|
self._send_msg(msg)
|
||||||
|
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e), bot=bot)
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _status_table(self, bot: Bot, update: Update) -> None:
|
def _status_table(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /status table.
|
Handler for /status table.
|
||||||
Returns the current TradeThread status in table format
|
Returns the current TradeThread status in table format
|
||||||
@ -240,10 +238,10 @@ class Telegram(RPC):
|
|||||||
message = tabulate(df_statuses, headers='keys', tablefmt='simple')
|
message = tabulate(df_statuses, headers='keys', tablefmt='simple')
|
||||||
self._send_msg(f"<pre>{message}</pre>", parse_mode=ParseMode.HTML)
|
self._send_msg(f"<pre>{message}</pre>", parse_mode=ParseMode.HTML)
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e), bot=bot)
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _daily(self, bot: Bot, update: Update) -> None:
|
def _daily(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /daily <n>
|
Handler for /daily <n>
|
||||||
Returns a daily profit (in BTC) over the last n days.
|
Returns a daily profit (in BTC) over the last n days.
|
||||||
@ -254,8 +252,8 @@ class Telegram(RPC):
|
|||||||
stake_cur = self._config['stake_currency']
|
stake_cur = self._config['stake_currency']
|
||||||
fiat_disp_cur = self._config.get('fiat_display_currency', '')
|
fiat_disp_cur = self._config.get('fiat_display_currency', '')
|
||||||
try:
|
try:
|
||||||
timescale = int(update.message.text.replace('/daily', '').strip())
|
timescale = int(context.args[0])
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError, IndexError):
|
||||||
timescale = 7
|
timescale = 7
|
||||||
try:
|
try:
|
||||||
stats = self._rpc_daily_profit(
|
stats = self._rpc_daily_profit(
|
||||||
@ -272,12 +270,12 @@ class Telegram(RPC):
|
|||||||
],
|
],
|
||||||
tablefmt='simple')
|
tablefmt='simple')
|
||||||
message = f'<b>Daily Profit over the last {timescale} days</b>:\n<pre>{stats_tab}</pre>'
|
message = f'<b>Daily Profit over the last {timescale} days</b>:\n<pre>{stats_tab}</pre>'
|
||||||
self._send_msg(message, bot=bot, parse_mode=ParseMode.HTML)
|
self._send_msg(message, parse_mode=ParseMode.HTML)
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e), bot=bot)
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _profit(self, bot: Bot, update: Update) -> None:
|
def _profit(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /profit.
|
Handler for /profit.
|
||||||
Returns a cumulative profit statistics.
|
Returns a cumulative profit statistics.
|
||||||
@ -317,12 +315,12 @@ class Telegram(RPC):
|
|||||||
f"*Latest Trade opened:* `{latest_trade_date}`\n" \
|
f"*Latest Trade opened:* `{latest_trade_date}`\n" \
|
||||||
f"*Avg. Duration:* `{avg_duration}`\n" \
|
f"*Avg. Duration:* `{avg_duration}`\n" \
|
||||||
f"*Best Performing:* `{best_pair}: {best_rate:.2f}%`"
|
f"*Best Performing:* `{best_pair}: {best_rate:.2f}%`"
|
||||||
self._send_msg(markdown_msg, bot=bot)
|
self._send_msg(markdown_msg)
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e), bot=bot)
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _balance(self, bot: Bot, update: Update) -> None:
|
def _balance(self, update: Update, context: CallbackContext) -> None:
|
||||||
""" Handler for /balance """
|
""" Handler for /balance """
|
||||||
try:
|
try:
|
||||||
result = self._rpc_balance(self._config.get('fiat_display_currency', ''))
|
result = self._rpc_balance(self._config.get('fiat_display_currency', ''))
|
||||||
@ -339,7 +337,7 @@ class Telegram(RPC):
|
|||||||
|
|
||||||
# Handle overflowing messsage length
|
# Handle overflowing messsage length
|
||||||
if len(output + curr_output) >= MAX_TELEGRAM_MESSAGE_LENGTH:
|
if len(output + curr_output) >= MAX_TELEGRAM_MESSAGE_LENGTH:
|
||||||
self._send_msg(output, bot=bot)
|
self._send_msg(output)
|
||||||
output = curr_output
|
output = curr_output
|
||||||
else:
|
else:
|
||||||
output += curr_output
|
output += curr_output
|
||||||
@ -347,12 +345,12 @@ class Telegram(RPC):
|
|||||||
output += "\n*Estimated Value*:\n" \
|
output += "\n*Estimated Value*:\n" \
|
||||||
"\t`BTC: {total: .8f}`\n" \
|
"\t`BTC: {total: .8f}`\n" \
|
||||||
"\t`{symbol}: {value: .2f}`\n".format(**result)
|
"\t`{symbol}: {value: .2f}`\n".format(**result)
|
||||||
self._send_msg(output, bot=bot)
|
self._send_msg(output)
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e), bot=bot)
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _start(self, bot: Bot, update: Update) -> None:
|
def _start(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /start.
|
Handler for /start.
|
||||||
Starts TradeThread
|
Starts TradeThread
|
||||||
@ -361,10 +359,10 @@ class Telegram(RPC):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
msg = self._rpc_start()
|
msg = self._rpc_start()
|
||||||
self._send_msg('Status: `{status}`'.format(**msg), bot=bot)
|
self._send_msg('Status: `{status}`'.format(**msg))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _stop(self, bot: Bot, update: Update) -> None:
|
def _stop(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /stop.
|
Handler for /stop.
|
||||||
Stops TradeThread
|
Stops TradeThread
|
||||||
@ -373,10 +371,10 @@ class Telegram(RPC):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
msg = self._rpc_stop()
|
msg = self._rpc_stop()
|
||||||
self._send_msg('Status: `{status}`'.format(**msg), bot=bot)
|
self._send_msg('Status: `{status}`'.format(**msg))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _reload_conf(self, bot: Bot, update: Update) -> None:
|
def _reload_conf(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /reload_conf.
|
Handler for /reload_conf.
|
||||||
Triggers a config file reload
|
Triggers a config file reload
|
||||||
@ -385,10 +383,10 @@ class Telegram(RPC):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
msg = self._rpc_reload_conf()
|
msg = self._rpc_reload_conf()
|
||||||
self._send_msg('Status: `{status}`'.format(**msg), bot=bot)
|
self._send_msg('Status: `{status}`'.format(**msg))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _stopbuy(self, bot: Bot, update: Update) -> None:
|
def _stopbuy(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /stop_buy.
|
Handler for /stop_buy.
|
||||||
Sets max_open_trades to 0 and gracefully sells all open trades
|
Sets max_open_trades to 0 and gracefully sells all open trades
|
||||||
@ -397,10 +395,10 @@ class Telegram(RPC):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
msg = self._rpc_stopbuy()
|
msg = self._rpc_stopbuy()
|
||||||
self._send_msg('Status: `{status}`'.format(**msg), bot=bot)
|
self._send_msg('Status: `{status}`'.format(**msg))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _forcesell(self, bot: Bot, update: Update) -> None:
|
def _forcesell(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /forcesell <id>.
|
Handler for /forcesell <id>.
|
||||||
Sells the given trade at current price
|
Sells the given trade at current price
|
||||||
@ -409,16 +407,16 @@ class Telegram(RPC):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
trade_id = update.message.text.replace('/forcesell', '').strip()
|
trade_id = context.args[0] if len(context.args) > 0 else None
|
||||||
try:
|
try:
|
||||||
msg = self._rpc_forcesell(trade_id)
|
msg = self._rpc_forcesell(trade_id)
|
||||||
self._send_msg('Forcesell Result: `{result}`'.format(**msg), bot=bot)
|
self._send_msg('Forcesell Result: `{result}`'.format(**msg))
|
||||||
|
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e), bot=bot)
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _forcebuy(self, bot: Bot, update: Update) -> None:
|
def _forcebuy(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /forcebuy <asset> <price>.
|
Handler for /forcebuy <asset> <price>.
|
||||||
Buys a pair trade at the given or current price
|
Buys a pair trade at the given or current price
|
||||||
@ -427,16 +425,15 @@ class Telegram(RPC):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
message = update.message.text.replace('/forcebuy', '').strip().split()
|
pair = context.args[0]
|
||||||
pair = message[0]
|
price = float(context.args[1]) if len(context.args) > 1 else None
|
||||||
price = float(message[1]) if len(message) > 1 else None
|
|
||||||
try:
|
try:
|
||||||
self._rpc_forcebuy(pair, price)
|
self._rpc_forcebuy(pair, price)
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e), bot=bot)
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _performance(self, bot: Bot, update: Update) -> None:
|
def _performance(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /performance.
|
Handler for /performance.
|
||||||
Shows a performance statistic from finished trades
|
Shows a performance statistic from finished trades
|
||||||
@ -455,10 +452,10 @@ class Telegram(RPC):
|
|||||||
message = '<b>Performance:</b>\n{}'.format(stats)
|
message = '<b>Performance:</b>\n{}'.format(stats)
|
||||||
self._send_msg(message, parse_mode=ParseMode.HTML)
|
self._send_msg(message, parse_mode=ParseMode.HTML)
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e), bot=bot)
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _count(self, bot: Bot, update: Update) -> None:
|
def _count(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /count.
|
Handler for /count.
|
||||||
Returns the number of trades running
|
Returns the number of trades running
|
||||||
@ -475,10 +472,10 @@ class Telegram(RPC):
|
|||||||
logger.debug(message)
|
logger.debug(message)
|
||||||
self._send_msg(message, parse_mode=ParseMode.HTML)
|
self._send_msg(message, parse_mode=ParseMode.HTML)
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e), bot=bot)
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _whitelist(self, bot: Bot, update: Update) -> None:
|
def _whitelist(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /whitelist
|
Handler for /whitelist
|
||||||
Shows the currently active whitelist
|
Shows the currently active whitelist
|
||||||
@ -492,17 +489,17 @@ class Telegram(RPC):
|
|||||||
logger.debug(message)
|
logger.debug(message)
|
||||||
self._send_msg(message)
|
self._send_msg(message)
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e), bot=bot)
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _blacklist(self, bot: Bot, update: Update, args: List[str]) -> None:
|
def _blacklist(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /blacklist
|
Handler for /blacklist
|
||||||
Shows the currently active blacklist
|
Shows the currently active blacklist
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
|
||||||
blacklist = self._rpc_blacklist(args)
|
blacklist = self._rpc_blacklist(context.args)
|
||||||
|
|
||||||
message = f"Blacklist contains {blacklist['length']} pairs\n"
|
message = f"Blacklist contains {blacklist['length']} pairs\n"
|
||||||
message += f"`{', '.join(blacklist['blacklist'])}`"
|
message += f"`{', '.join(blacklist['blacklist'])}`"
|
||||||
@ -510,10 +507,10 @@ class Telegram(RPC):
|
|||||||
logger.debug(message)
|
logger.debug(message)
|
||||||
self._send_msg(message)
|
self._send_msg(message)
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e), bot=bot)
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _edge(self, bot: Bot, update: Update) -> None:
|
def _edge(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /edge
|
Handler for /edge
|
||||||
Shows information related to Edge
|
Shows information related to Edge
|
||||||
@ -522,12 +519,12 @@ class Telegram(RPC):
|
|||||||
edge_pairs = self._rpc_edge()
|
edge_pairs = self._rpc_edge()
|
||||||
edge_pairs_tab = tabulate(edge_pairs, headers='keys', tablefmt='simple')
|
edge_pairs_tab = tabulate(edge_pairs, headers='keys', tablefmt='simple')
|
||||||
message = f'<b>Edge only validated following pairs:</b>\n<pre>{edge_pairs_tab}</pre>'
|
message = f'<b>Edge only validated following pairs:</b>\n<pre>{edge_pairs_tab}</pre>'
|
||||||
self._send_msg(message, bot=bot, parse_mode=ParseMode.HTML)
|
self._send_msg(message, parse_mode=ParseMode.HTML)
|
||||||
except RPCException as e:
|
except RPCException as e:
|
||||||
self._send_msg(str(e), bot=bot)
|
self._send_msg(str(e))
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _help(self, bot: Bot, update: Update) -> None:
|
def _help(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /help.
|
Handler for /help.
|
||||||
Show commands of the bot
|
Show commands of the bot
|
||||||
@ -559,10 +556,10 @@ class Telegram(RPC):
|
|||||||
"*/help:* `This help message`\n" \
|
"*/help:* `This help message`\n" \
|
||||||
"*/version:* `Show version`"
|
"*/version:* `Show version`"
|
||||||
|
|
||||||
self._send_msg(message, bot=bot)
|
self._send_msg(message)
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _version(self, bot: Bot, update: Update) -> None:
|
def _version(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
Handler for /version.
|
Handler for /version.
|
||||||
Show version information
|
Show version information
|
||||||
@ -570,10 +567,9 @@ class Telegram(RPC):
|
|||||||
:param update: message update
|
:param update: message update
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
self._send_msg('*Version:* `{}`'.format(__version__), bot=bot)
|
self._send_msg('*Version:* `{}`'.format(__version__))
|
||||||
|
|
||||||
def _send_msg(self, msg: str, bot: Bot = None,
|
def _send_msg(self, msg: str, parse_mode: ParseMode = ParseMode.MARKDOWN) -> None:
|
||||||
parse_mode: ParseMode = ParseMode.MARKDOWN) -> None:
|
|
||||||
"""
|
"""
|
||||||
Send given markdown message
|
Send given markdown message
|
||||||
:param msg: message
|
:param msg: message
|
||||||
@ -581,7 +577,6 @@ class Telegram(RPC):
|
|||||||
:param parse_mode: telegram parse mode
|
:param parse_mode: telegram parse mode
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
bot = bot or self._updater.bot
|
|
||||||
|
|
||||||
keyboard = [['/daily', '/profit', '/balance'],
|
keyboard = [['/daily', '/profit', '/balance'],
|
||||||
['/status', '/status table', '/performance'],
|
['/status', '/status table', '/performance'],
|
||||||
@ -591,7 +586,7 @@ class Telegram(RPC):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
bot.send_message(
|
self._updater.bot.send_message(
|
||||||
self._config['telegram']['chat_id'],
|
self._config['telegram']['chat_id'],
|
||||||
text=msg,
|
text=msg,
|
||||||
parse_mode=parse_mode,
|
parse_mode=parse_mode,
|
||||||
@ -604,7 +599,7 @@ class Telegram(RPC):
|
|||||||
'Telegram NetworkError: %s! Trying one more time.',
|
'Telegram NetworkError: %s! Trying one more time.',
|
||||||
network_err.message
|
network_err.message
|
||||||
)
|
)
|
||||||
bot.send_message(
|
self._updater.bot.send_message(
|
||||||
self._config['telegram']['chat_id'],
|
self._config['telegram']['chat_id'],
|
||||||
text=msg,
|
text=msg,
|
||||||
parse_mode=parse_mode,
|
parse_mode=parse_mode,
|
||||||
|
@ -100,7 +100,7 @@ def test_authorized_only(default_conf, mocker, caplog) -> None:
|
|||||||
bot = FreqtradeBot(default_conf)
|
bot = FreqtradeBot(default_conf)
|
||||||
patch_get_signal(bot, (True, False))
|
patch_get_signal(bot, (True, False))
|
||||||
dummy = DummyCls(bot)
|
dummy = DummyCls(bot)
|
||||||
dummy.dummy_handler(bot=MagicMock(), update=update)
|
dummy.dummy_handler(update=update, context=MagicMock())
|
||||||
assert dummy.state['called'] is True
|
assert dummy.state['called'] is True
|
||||||
assert log_has('Executing handler: dummy_handler for chat_id: 0', caplog)
|
assert log_has('Executing handler: dummy_handler for chat_id: 0', caplog)
|
||||||
assert not log_has('Rejected unauthorized message from: 0', caplog)
|
assert not log_has('Rejected unauthorized message from: 0', caplog)
|
||||||
@ -117,7 +117,7 @@ def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> None:
|
|||||||
bot = FreqtradeBot(default_conf)
|
bot = FreqtradeBot(default_conf)
|
||||||
patch_get_signal(bot, (True, False))
|
patch_get_signal(bot, (True, False))
|
||||||
dummy = DummyCls(bot)
|
dummy = DummyCls(bot)
|
||||||
dummy.dummy_handler(bot=MagicMock(), update=update)
|
dummy.dummy_handler(update=update, context=MagicMock())
|
||||||
assert dummy.state['called'] is False
|
assert dummy.state['called'] is False
|
||||||
assert not log_has('Executing handler: dummy_handler for chat_id: 3735928559', caplog)
|
assert not log_has('Executing handler: dummy_handler for chat_id: 3735928559', caplog)
|
||||||
assert log_has('Rejected unauthorized message from: 3735928559', caplog)
|
assert log_has('Rejected unauthorized message from: 3735928559', caplog)
|
||||||
@ -136,7 +136,7 @@ def test_authorized_only_exception(default_conf, mocker, caplog) -> None:
|
|||||||
patch_get_signal(bot, (True, False))
|
patch_get_signal(bot, (True, False))
|
||||||
dummy = DummyCls(bot)
|
dummy = DummyCls(bot)
|
||||||
|
|
||||||
dummy.dummy_exception(bot=MagicMock(), update=update)
|
dummy.dummy_exception(update=update, context=MagicMock())
|
||||||
assert dummy.state['called'] is False
|
assert dummy.state['called'] is False
|
||||||
assert not log_has('Executing handler: dummy_handler for chat_id: 0', caplog)
|
assert not log_has('Executing handler: dummy_handler for chat_id: 0', caplog)
|
||||||
assert not log_has('Rejected unauthorized message from: 0', caplog)
|
assert not log_has('Rejected unauthorized message from: 0', caplog)
|
||||||
@ -194,12 +194,13 @@ def test_status(default_conf, update, mocker, fee, ticker, markets) -> None:
|
|||||||
for _ in range(3):
|
for _ in range(3):
|
||||||
freqtradebot.create_trades()
|
freqtradebot.create_trades()
|
||||||
|
|
||||||
telegram._status(bot=MagicMock(), update=update)
|
telegram._status(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
|
|
||||||
update.message.text = MagicMock()
|
context = MagicMock()
|
||||||
update.message.text.replace = MagicMock(return_value='table 2 3')
|
# /status table 2 3
|
||||||
telegram._status(bot=MagicMock(), update=update)
|
context.args = ["table", "2", "3"]
|
||||||
|
telegram._status(update=update, context=context)
|
||||||
assert status_table.call_count == 1
|
assert status_table.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
@ -228,13 +229,13 @@ def test_status_handle(default_conf, update, ticker, fee, markets, mocker) -> No
|
|||||||
|
|
||||||
freqtradebot.state = State.STOPPED
|
freqtradebot.state = State.STOPPED
|
||||||
# Status is also enabled when stopped
|
# Status is also enabled when stopped
|
||||||
telegram._status(bot=MagicMock(), update=update)
|
telegram._status(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'no active trade' in msg_mock.call_args_list[0][0][0]
|
assert 'no active trade' in msg_mock.call_args_list[0][0][0]
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
|
|
||||||
freqtradebot.state = State.RUNNING
|
freqtradebot.state = State.RUNNING
|
||||||
telegram._status(bot=MagicMock(), update=update)
|
telegram._status(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'no active trade' in msg_mock.call_args_list[0][0][0]
|
assert 'no active trade' in msg_mock.call_args_list[0][0][0]
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
@ -242,7 +243,7 @@ def test_status_handle(default_conf, update, ticker, fee, markets, mocker) -> No
|
|||||||
# Create some test data
|
# Create some test data
|
||||||
freqtradebot.create_trades()
|
freqtradebot.create_trades()
|
||||||
# Trigger status while we have a fulfilled order for the open trade
|
# Trigger status while we have a fulfilled order for the open trade
|
||||||
telegram._status(bot=MagicMock(), update=update)
|
telegram._status(update=update, context=MagicMock())
|
||||||
|
|
||||||
# close_rate should not be included in the message as the trade is not closed
|
# close_rate should not be included in the message as the trade is not closed
|
||||||
# and no line should be empty
|
# and no line should be empty
|
||||||
@ -280,13 +281,13 @@ def test_status_table_handle(default_conf, update, ticker, fee, markets, mocker)
|
|||||||
|
|
||||||
freqtradebot.state = State.STOPPED
|
freqtradebot.state = State.STOPPED
|
||||||
# Status table is also enabled when stopped
|
# Status table is also enabled when stopped
|
||||||
telegram._status_table(bot=MagicMock(), update=update)
|
telegram._status_table(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'no active order' in msg_mock.call_args_list[0][0][0]
|
assert 'no active order' in msg_mock.call_args_list[0][0][0]
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
|
|
||||||
freqtradebot.state = State.RUNNING
|
freqtradebot.state = State.RUNNING
|
||||||
telegram._status_table(bot=MagicMock(), update=update)
|
telegram._status_table(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'no active order' in msg_mock.call_args_list[0][0][0]
|
assert 'no active order' in msg_mock.call_args_list[0][0][0]
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
@ -294,7 +295,7 @@ def test_status_table_handle(default_conf, update, ticker, fee, markets, mocker)
|
|||||||
# Create some test data
|
# Create some test data
|
||||||
freqtradebot.create_trades()
|
freqtradebot.create_trades()
|
||||||
|
|
||||||
telegram._status_table(bot=MagicMock(), update=update)
|
telegram._status_table(update=update, context=MagicMock())
|
||||||
|
|
||||||
text = re.sub('</?pre>', '', msg_mock.call_args_list[-1][0][0])
|
text = re.sub('</?pre>', '', msg_mock.call_args_list[-1][0][0])
|
||||||
line = text.split("\n")
|
line = text.split("\n")
|
||||||
@ -346,8 +347,10 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
|
|||||||
trade.is_open = False
|
trade.is_open = False
|
||||||
|
|
||||||
# Try valid data
|
# Try valid data
|
||||||
update.message.text = '/daily 2'
|
# /daily 2
|
||||||
telegram._daily(bot=MagicMock(), update=update)
|
context = MagicMock()
|
||||||
|
context.args = ["2"]
|
||||||
|
telegram._daily(update=update, context=context)
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'Daily' in msg_mock.call_args_list[0][0][0]
|
assert 'Daily' in msg_mock.call_args_list[0][0][0]
|
||||||
assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0]
|
assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0]
|
||||||
@ -369,9 +372,10 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee,
|
|||||||
trade.close_date = datetime.utcnow()
|
trade.close_date = datetime.utcnow()
|
||||||
trade.is_open = False
|
trade.is_open = False
|
||||||
|
|
||||||
update.message.text = '/daily 1'
|
# /daily 1
|
||||||
|
context = MagicMock()
|
||||||
telegram._daily(bot=MagicMock(), update=update)
|
context.args = ["1"]
|
||||||
|
telegram._daily(update=update, context=context)
|
||||||
assert str(' 0.00018651 BTC') in msg_mock.call_args_list[0][0][0]
|
assert str(' 0.00018651 BTC') in msg_mock.call_args_list[0][0][0]
|
||||||
assert str(' 2.798 USD') in msg_mock.call_args_list[0][0][0]
|
assert str(' 2.798 USD') in msg_mock.call_args_list[0][0][0]
|
||||||
assert str(' 3 trades') in msg_mock.call_args_list[0][0][0]
|
assert str(' 3 trades') in msg_mock.call_args_list[0][0][0]
|
||||||
@ -398,16 +402,20 @@ def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None:
|
|||||||
# Try invalid data
|
# Try invalid data
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
freqtradebot.state = State.RUNNING
|
freqtradebot.state = State.RUNNING
|
||||||
update.message.text = '/daily -2'
|
# /daily -2
|
||||||
telegram._daily(bot=MagicMock(), update=update)
|
context = MagicMock()
|
||||||
|
context.args = ["-2"]
|
||||||
|
telegram._daily(update=update, context=context)
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'must be an integer greater than 0' in msg_mock.call_args_list[0][0][0]
|
assert 'must be an integer greater than 0' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
# Try invalid data
|
# Try invalid data
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
freqtradebot.state = State.RUNNING
|
freqtradebot.state = State.RUNNING
|
||||||
update.message.text = '/daily today'
|
# /daily today
|
||||||
telegram._daily(bot=MagicMock(), update=update)
|
context = MagicMock()
|
||||||
|
context.args = ["today"]
|
||||||
|
telegram._daily(update=update, context=context)
|
||||||
assert str('Daily Profit over the last 7 days') in msg_mock.call_args_list[0][0][0]
|
assert str('Daily Profit over the last 7 days') in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
|
|
||||||
@ -433,7 +441,7 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
|
|||||||
patch_get_signal(freqtradebot, (True, False))
|
patch_get_signal(freqtradebot, (True, False))
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._profit(bot=MagicMock(), update=update)
|
telegram._profit(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'no closed trade' in msg_mock.call_args_list[0][0][0]
|
assert 'no closed trade' in msg_mock.call_args_list[0][0][0]
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
@ -445,7 +453,7 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
|
|||||||
# Simulate fulfilled LIMIT_BUY order for trade
|
# Simulate fulfilled LIMIT_BUY order for trade
|
||||||
trade.update(limit_buy_order)
|
trade.update(limit_buy_order)
|
||||||
|
|
||||||
telegram._profit(bot=MagicMock(), update=update)
|
telegram._profit(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'no closed trade' in msg_mock.call_args_list[-1][0][0]
|
assert 'no closed trade' in msg_mock.call_args_list[-1][0][0]
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
@ -457,7 +465,7 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
|
|||||||
trade.close_date = datetime.utcnow()
|
trade.close_date = datetime.utcnow()
|
||||||
trade.is_open = False
|
trade.is_open = False
|
||||||
|
|
||||||
telegram._profit(bot=MagicMock(), update=update)
|
telegram._profit(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert '*ROI:* Close trades' in msg_mock.call_args_list[-1][0][0]
|
assert '*ROI:* Close trades' in msg_mock.call_args_list[-1][0][0]
|
||||||
assert '∙ `0.00006217 BTC (6.20%)`' in msg_mock.call_args_list[-1][0][0]
|
assert '∙ `0.00006217 BTC (6.20%)`' in msg_mock.call_args_list[-1][0][0]
|
||||||
@ -507,7 +515,7 @@ def test_telegram_balance_handle(default_conf, update, mocker, rpc_balance) -> N
|
|||||||
|
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._balance(bot=MagicMock(), update=update)
|
telegram._balance(update=update, context=MagicMock())
|
||||||
result = msg_mock.call_args_list[0][0][0]
|
result = msg_mock.call_args_list[0][0][0]
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert '*BTC:*' in result
|
assert '*BTC:*' in result
|
||||||
@ -536,7 +544,7 @@ def test_balance_handle_empty_response(default_conf, update, mocker) -> None:
|
|||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
freqtradebot.config['dry_run'] = False
|
freqtradebot.config['dry_run'] = False
|
||||||
telegram._balance(bot=MagicMock(), update=update)
|
telegram._balance(update=update, context=MagicMock())
|
||||||
result = msg_mock.call_args_list[0][0][0]
|
result = msg_mock.call_args_list[0][0][0]
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'All balances are zero.' in result
|
assert 'All balances are zero.' in result
|
||||||
@ -557,7 +565,7 @@ def test_balance_handle_empty_response_dry(default_conf, update, mocker) -> None
|
|||||||
|
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._balance(bot=MagicMock(), update=update)
|
telegram._balance(update=update, context=MagicMock())
|
||||||
result = msg_mock.call_args_list[0][0][0]
|
result = msg_mock.call_args_list[0][0][0]
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert "Running in Dry Run, balances are not available." in result
|
assert "Running in Dry Run, balances are not available." in result
|
||||||
@ -593,7 +601,7 @@ def test_balance_handle_too_large_response(default_conf, update, mocker) -> None
|
|||||||
|
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._balance(bot=MagicMock(), update=update)
|
telegram._balance(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count > 1
|
assert msg_mock.call_count > 1
|
||||||
# Test if wrap happens around 4000 -
|
# Test if wrap happens around 4000 -
|
||||||
# and each single currency-output is around 120 characters long so we need
|
# and each single currency-output is around 120 characters long so we need
|
||||||
@ -615,7 +623,7 @@ def test_start_handle(default_conf, update, mocker) -> None:
|
|||||||
|
|
||||||
freqtradebot.state = State.STOPPED
|
freqtradebot.state = State.STOPPED
|
||||||
assert freqtradebot.state == State.STOPPED
|
assert freqtradebot.state == State.STOPPED
|
||||||
telegram._start(bot=MagicMock(), update=update)
|
telegram._start(update=update, context=MagicMock())
|
||||||
assert freqtradebot.state == State.RUNNING
|
assert freqtradebot.state == State.RUNNING
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
|
|
||||||
@ -633,7 +641,7 @@ def test_start_handle_already_running(default_conf, update, mocker) -> None:
|
|||||||
|
|
||||||
freqtradebot.state = State.RUNNING
|
freqtradebot.state = State.RUNNING
|
||||||
assert freqtradebot.state == State.RUNNING
|
assert freqtradebot.state == State.RUNNING
|
||||||
telegram._start(bot=MagicMock(), update=update)
|
telegram._start(update=update, context=MagicMock())
|
||||||
assert freqtradebot.state == State.RUNNING
|
assert freqtradebot.state == State.RUNNING
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'already running' in msg_mock.call_args_list[0][0][0]
|
assert 'already running' in msg_mock.call_args_list[0][0][0]
|
||||||
@ -652,7 +660,7 @@ def test_stop_handle(default_conf, update, mocker) -> None:
|
|||||||
|
|
||||||
freqtradebot.state = State.RUNNING
|
freqtradebot.state = State.RUNNING
|
||||||
assert freqtradebot.state == State.RUNNING
|
assert freqtradebot.state == State.RUNNING
|
||||||
telegram._stop(bot=MagicMock(), update=update)
|
telegram._stop(update=update, context=MagicMock())
|
||||||
assert freqtradebot.state == State.STOPPED
|
assert freqtradebot.state == State.STOPPED
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'stopping trader' in msg_mock.call_args_list[0][0][0]
|
assert 'stopping trader' in msg_mock.call_args_list[0][0][0]
|
||||||
@ -671,7 +679,7 @@ def test_stop_handle_already_stopped(default_conf, update, mocker) -> None:
|
|||||||
|
|
||||||
freqtradebot.state = State.STOPPED
|
freqtradebot.state = State.STOPPED
|
||||||
assert freqtradebot.state == State.STOPPED
|
assert freqtradebot.state == State.STOPPED
|
||||||
telegram._stop(bot=MagicMock(), update=update)
|
telegram._stop(update=update, context=MagicMock())
|
||||||
assert freqtradebot.state == State.STOPPED
|
assert freqtradebot.state == State.STOPPED
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'already stopped' in msg_mock.call_args_list[0][0][0]
|
assert 'already stopped' in msg_mock.call_args_list[0][0][0]
|
||||||
@ -689,7 +697,7 @@ def test_stopbuy_handle(default_conf, update, mocker) -> None:
|
|||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
assert freqtradebot.config['max_open_trades'] != 0
|
assert freqtradebot.config['max_open_trades'] != 0
|
||||||
telegram._stopbuy(bot=MagicMock(), update=update)
|
telegram._stopbuy(update=update, context=MagicMock())
|
||||||
assert freqtradebot.config['max_open_trades'] == 0
|
assert freqtradebot.config['max_open_trades'] == 0
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'No more buy will occur from now. Run /reload_conf to reset.' \
|
assert 'No more buy will occur from now. Run /reload_conf to reset.' \
|
||||||
@ -709,7 +717,7 @@ def test_reload_conf_handle(default_conf, update, mocker) -> None:
|
|||||||
|
|
||||||
freqtradebot.state = State.RUNNING
|
freqtradebot.state = State.RUNNING
|
||||||
assert freqtradebot.state == State.RUNNING
|
assert freqtradebot.state == State.RUNNING
|
||||||
telegram._reload_conf(bot=MagicMock(), update=update)
|
telegram._reload_conf(update=update, context=MagicMock())
|
||||||
assert freqtradebot.state == State.RELOAD_CONF
|
assert freqtradebot.state == State.RELOAD_CONF
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'reloading config' in msg_mock.call_args_list[0][0][0]
|
assert 'reloading config' in msg_mock.call_args_list[0][0][0]
|
||||||
@ -742,8 +750,10 @@ def test_forcesell_handle(default_conf, update, ticker, fee,
|
|||||||
# Increase the price and sell it
|
# Increase the price and sell it
|
||||||
mocker.patch('freqtrade.exchange.Exchange.get_ticker', ticker_sell_up)
|
mocker.patch('freqtrade.exchange.Exchange.get_ticker', ticker_sell_up)
|
||||||
|
|
||||||
update.message.text = '/forcesell 1'
|
# /forcesell 1
|
||||||
telegram._forcesell(bot=MagicMock(), update=update)
|
context = MagicMock()
|
||||||
|
context.args = ["1"]
|
||||||
|
telegram._forcesell(update=update, context=context)
|
||||||
|
|
||||||
assert rpc_mock.call_count == 2
|
assert rpc_mock.call_count == 2
|
||||||
last_msg = rpc_mock.call_args_list[-1][0][0]
|
last_msg = rpc_mock.call_args_list[-1][0][0]
|
||||||
@ -796,8 +806,10 @@ def test_forcesell_down_handle(default_conf, update, ticker, fee,
|
|||||||
trade = Trade.query.first()
|
trade = Trade.query.first()
|
||||||
assert trade
|
assert trade
|
||||||
|
|
||||||
update.message.text = '/forcesell 1'
|
# /forcesell 1
|
||||||
telegram._forcesell(bot=MagicMock(), update=update)
|
context = MagicMock()
|
||||||
|
context.args = ["1"]
|
||||||
|
telegram._forcesell(update=update, context=context)
|
||||||
|
|
||||||
assert rpc_mock.call_count == 2
|
assert rpc_mock.call_count == 2
|
||||||
|
|
||||||
@ -842,8 +854,10 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, markets, mocker
|
|||||||
freqtradebot.create_trades()
|
freqtradebot.create_trades()
|
||||||
rpc_mock.reset_mock()
|
rpc_mock.reset_mock()
|
||||||
|
|
||||||
update.message.text = '/forcesell all'
|
# /forcesell all
|
||||||
telegram._forcesell(bot=MagicMock(), update=update)
|
context = MagicMock()
|
||||||
|
context.args = ["all"]
|
||||||
|
telegram._forcesell(update=update, context=context)
|
||||||
|
|
||||||
assert rpc_mock.call_count == 4
|
assert rpc_mock.call_count == 4
|
||||||
msg = rpc_mock.call_args_list[0][0][0]
|
msg = rpc_mock.call_args_list[0][0][0]
|
||||||
@ -882,24 +896,29 @@ def test_forcesell_handle_invalid(default_conf, update, mocker) -> None:
|
|||||||
|
|
||||||
# Trader is not running
|
# Trader is not running
|
||||||
freqtradebot.state = State.STOPPED
|
freqtradebot.state = State.STOPPED
|
||||||
update.message.text = '/forcesell 1'
|
# /forcesell 1
|
||||||
telegram._forcesell(bot=MagicMock(), update=update)
|
context = MagicMock()
|
||||||
|
context.args = ["1"]
|
||||||
|
telegram._forcesell(update=update, context=context)
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'not running' in msg_mock.call_args_list[0][0][0]
|
assert 'not running' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
# No argument
|
# No argument
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
freqtradebot.state = State.RUNNING
|
freqtradebot.state = State.RUNNING
|
||||||
update.message.text = '/forcesell'
|
context = MagicMock()
|
||||||
telegram._forcesell(bot=MagicMock(), update=update)
|
context.args = []
|
||||||
|
telegram._forcesell(update=update, context=context)
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'invalid argument' in msg_mock.call_args_list[0][0][0]
|
assert 'invalid argument' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
# Invalid argument
|
# Invalid argument
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
freqtradebot.state = State.RUNNING
|
freqtradebot.state = State.RUNNING
|
||||||
update.message.text = '/forcesell 123456'
|
# /forcesell 123456
|
||||||
telegram._forcesell(bot=MagicMock(), update=update)
|
context = MagicMock()
|
||||||
|
context.args = ["123456"]
|
||||||
|
telegram._forcesell(update=update, context=context)
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'invalid argument' in msg_mock.call_args_list[0][0][0]
|
assert 'invalid argument' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
@ -921,8 +940,10 @@ def test_forcebuy_handle(default_conf, update, markets, mocker) -> None:
|
|||||||
patch_get_signal(freqtradebot, (True, False))
|
patch_get_signal(freqtradebot, (True, False))
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
update.message.text = '/forcebuy ETH/BTC'
|
# /forcebuy ETH/BTC
|
||||||
telegram._forcebuy(bot=MagicMock(), update=update)
|
context = MagicMock()
|
||||||
|
context.args = ["ETH/BTC"]
|
||||||
|
telegram._forcebuy(update=update, context=context)
|
||||||
|
|
||||||
assert fbuy_mock.call_count == 1
|
assert fbuy_mock.call_count == 1
|
||||||
assert fbuy_mock.call_args_list[0][0][0] == 'ETH/BTC'
|
assert fbuy_mock.call_args_list[0][0][0] == 'ETH/BTC'
|
||||||
@ -931,8 +952,10 @@ def test_forcebuy_handle(default_conf, update, markets, mocker) -> None:
|
|||||||
# Reset and retry with specified price
|
# Reset and retry with specified price
|
||||||
fbuy_mock = MagicMock(return_value=None)
|
fbuy_mock = MagicMock(return_value=None)
|
||||||
mocker.patch('freqtrade.rpc.RPC._rpc_forcebuy', fbuy_mock)
|
mocker.patch('freqtrade.rpc.RPC._rpc_forcebuy', fbuy_mock)
|
||||||
update.message.text = '/forcebuy ETH/BTC 0.055'
|
# /forcebuy ETH/BTC 0.055
|
||||||
telegram._forcebuy(bot=MagicMock(), update=update)
|
context = MagicMock()
|
||||||
|
context.args = ["ETH/BTC", "0.055"]
|
||||||
|
telegram._forcebuy(update=update, context=context)
|
||||||
|
|
||||||
assert fbuy_mock.call_count == 1
|
assert fbuy_mock.call_count == 1
|
||||||
assert fbuy_mock.call_args_list[0][0][0] == 'ETH/BTC'
|
assert fbuy_mock.call_args_list[0][0][0] == 'ETH/BTC'
|
||||||
@ -955,7 +978,7 @@ def test_forcebuy_handle_exception(default_conf, update, markets, mocker) -> Non
|
|||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
update.message.text = '/forcebuy ETH/Nonepair'
|
update.message.text = '/forcebuy ETH/Nonepair'
|
||||||
telegram._forcebuy(bot=MagicMock(), update=update)
|
telegram._forcebuy(update=update, context=MagicMock())
|
||||||
|
|
||||||
assert rpc_mock.call_count == 1
|
assert rpc_mock.call_count == 1
|
||||||
assert rpc_mock.call_args_list[0][0][0] == 'Forcebuy not enabled.'
|
assert rpc_mock.call_args_list[0][0][0] == 'Forcebuy not enabled.'
|
||||||
@ -995,7 +1018,7 @@ def test_performance_handle(default_conf, update, ticker, fee,
|
|||||||
|
|
||||||
trade.close_date = datetime.utcnow()
|
trade.close_date = datetime.utcnow()
|
||||||
trade.is_open = False
|
trade.is_open = False
|
||||||
telegram._performance(bot=MagicMock(), update=update)
|
telegram._performance(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'Performance' in msg_mock.call_args_list[0][0][0]
|
assert 'Performance' in msg_mock.call_args_list[0][0][0]
|
||||||
assert '<code>ETH/BTC\t6.20% (1)</code>' in msg_mock.call_args_list[0][0][0]
|
assert '<code>ETH/BTC\t6.20% (1)</code>' in msg_mock.call_args_list[0][0][0]
|
||||||
@ -1021,7 +1044,7 @@ def test_count_handle(default_conf, update, ticker, fee, markets, mocker) -> Non
|
|||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
freqtradebot.state = State.STOPPED
|
freqtradebot.state = State.STOPPED
|
||||||
telegram._count(bot=MagicMock(), update=update)
|
telegram._count(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'not running' in msg_mock.call_args_list[0][0][0]
|
assert 'not running' in msg_mock.call_args_list[0][0][0]
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
@ -1030,7 +1053,7 @@ def test_count_handle(default_conf, update, ticker, fee, markets, mocker) -> Non
|
|||||||
# Create some test data
|
# Create some test data
|
||||||
freqtradebot.create_trades()
|
freqtradebot.create_trades()
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
telegram._count(bot=MagicMock(), update=update)
|
telegram._count(update=update, context=MagicMock())
|
||||||
|
|
||||||
msg = '<pre> current max total stake\n--------- ----- -------------\n' \
|
msg = '<pre> current max total stake\n--------- ----- -------------\n' \
|
||||||
' 1 {} {}</pre>'\
|
' 1 {} {}</pre>'\
|
||||||
@ -1052,7 +1075,7 @@ def test_whitelist_static(default_conf, update, mocker) -> None:
|
|||||||
|
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._whitelist(bot=MagicMock(), update=update)
|
telegram._whitelist(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert ('Using whitelist `StaticPairList` with 4 pairs\n`ETH/BTC, LTC/BTC, XRP/BTC, NEO/BTC`'
|
assert ('Using whitelist `StaticPairList` with 4 pairs\n`ETH/BTC, LTC/BTC, XRP/BTC, NEO/BTC`'
|
||||||
in msg_mock.call_args_list[0][0][0])
|
in msg_mock.call_args_list[0][0][0])
|
||||||
@ -1073,7 +1096,7 @@ def test_whitelist_dynamic(default_conf, update, mocker) -> None:
|
|||||||
|
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._whitelist(bot=MagicMock(), update=update)
|
telegram._whitelist(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert ('Using whitelist `VolumePairList` with 4 pairs\n`ETH/BTC, LTC/BTC, XRP/BTC, NEO/BTC`'
|
assert ('Using whitelist `VolumePairList` with 4 pairs\n`ETH/BTC, LTC/BTC, XRP/BTC, NEO/BTC`'
|
||||||
in msg_mock.call_args_list[0][0][0])
|
in msg_mock.call_args_list[0][0][0])
|
||||||
@ -1090,13 +1113,17 @@ def test_blacklist_static(default_conf, update, mocker) -> None:
|
|||||||
|
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._blacklist(bot=MagicMock(), update=update, args=[])
|
telegram._blacklist(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert ("Blacklist contains 2 pairs\n`DOGE/BTC, HOT/BTC`"
|
assert ("Blacklist contains 2 pairs\n`DOGE/BTC, HOT/BTC`"
|
||||||
in msg_mock.call_args_list[0][0][0])
|
in msg_mock.call_args_list[0][0][0])
|
||||||
|
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
telegram._blacklist(bot=MagicMock(), update=update, args=["ETH/BTC"])
|
|
||||||
|
# /blacklist ETH/BTC
|
||||||
|
context = MagicMock()
|
||||||
|
context.args = ["ETH/BTC"]
|
||||||
|
telegram._blacklist(update=update, context=context)
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert ("Blacklist contains 3 pairs\n`DOGE/BTC, HOT/BTC, ETH/BTC`"
|
assert ("Blacklist contains 3 pairs\n`DOGE/BTC, HOT/BTC, ETH/BTC`"
|
||||||
in msg_mock.call_args_list[0][0][0])
|
in msg_mock.call_args_list[0][0][0])
|
||||||
@ -1115,7 +1142,7 @@ def test_edge_disabled(default_conf, update, mocker) -> None:
|
|||||||
|
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._edge(bot=MagicMock(), update=update)
|
telegram._edge(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert "Edge is not enabled." in msg_mock.call_args_list[0][0][0]
|
assert "Edge is not enabled." in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
@ -1137,7 +1164,7 @@ def test_edge_enabled(edge_conf, update, mocker) -> None:
|
|||||||
|
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._edge(bot=MagicMock(), update=update)
|
telegram._edge(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert '<b>Edge only validated following pairs:</b>\n<pre>' in msg_mock.call_args_list[0][0][0]
|
assert '<b>Edge only validated following pairs:</b>\n<pre>' in msg_mock.call_args_list[0][0][0]
|
||||||
assert 'Pair Winrate Expectancy Stoploss' in msg_mock.call_args_list[0][0][0]
|
assert 'Pair Winrate Expectancy Stoploss' in msg_mock.call_args_list[0][0][0]
|
||||||
@ -1154,7 +1181,7 @@ def test_help_handle(default_conf, update, mocker) -> None:
|
|||||||
|
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._help(bot=MagicMock(), update=update)
|
telegram._help(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert '*/help:* `This help message`' in msg_mock.call_args_list[0][0][0]
|
assert '*/help:* `This help message`' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
@ -1169,7 +1196,7 @@ def test_version_handle(default_conf, update, mocker) -> None:
|
|||||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
|
||||||
telegram._version(bot=MagicMock(), update=update)
|
telegram._version(update=update, context=MagicMock())
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert '*Version:* `{}`'.format(__version__) in msg_mock.call_args_list[0][0][0]
|
assert '*Version:* `{}`'.format(__version__) in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
@ -1395,9 +1422,11 @@ def test__send_msg(default_conf, mocker) -> None:
|
|||||||
bot = MagicMock()
|
bot = MagicMock()
|
||||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
telegram._updater = MagicMock()
|
||||||
|
telegram._updater.bot = bot
|
||||||
|
|
||||||
telegram._config['telegram']['enabled'] = True
|
telegram._config['telegram']['enabled'] = True
|
||||||
telegram._send_msg('test', bot)
|
telegram._send_msg('test')
|
||||||
assert len(bot.method_calls) == 1
|
assert len(bot.method_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
@ -1407,9 +1436,11 @@ def test__send_msg_network_error(default_conf, mocker, caplog) -> None:
|
|||||||
bot.send_message = MagicMock(side_effect=NetworkError('Oh snap'))
|
bot.send_message = MagicMock(side_effect=NetworkError('Oh snap'))
|
||||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||||
telegram = Telegram(freqtradebot)
|
telegram = Telegram(freqtradebot)
|
||||||
|
telegram._updater = MagicMock()
|
||||||
|
telegram._updater.bot = bot
|
||||||
|
|
||||||
telegram._config['telegram']['enabled'] = True
|
telegram._config['telegram']['enabled'] = True
|
||||||
telegram._send_msg('test', bot)
|
telegram._send_msg('test')
|
||||||
|
|
||||||
# Bot should've tried to send it twice
|
# Bot should've tried to send it twice
|
||||||
assert len(bot.method_calls) == 2
|
assert len(bot.method_calls) == 2
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# mainly used for Raspberry pi installs
|
# mainly used for Raspberry pi installs
|
||||||
ccxt==1.18.1115
|
ccxt==1.18.1115
|
||||||
SQLAlchemy==1.3.8
|
SQLAlchemy==1.3.8
|
||||||
python-telegram-bot==11.1.0
|
python-telegram-bot==12.0.0
|
||||||
arrow==0.14.6
|
arrow==0.14.6
|
||||||
cachetools==3.1.1
|
cachetools==3.1.1
|
||||||
requests==2.22.0
|
requests==2.22.0
|
||||||
|
Loading…
Reference in New Issue
Block a user