From 05789c4b925d7c4b6c674be57335ccfb1134b5d5 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2019 13:44:52 +0000 Subject: [PATCH 1/5] Bump python-telegram-bot from 11.1.0 to 12.0.0 Bumps [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) from 11.1.0 to 12.0.0. - [Release notes](https://github.com/python-telegram-bot/python-telegram-bot/releases) - [Changelog](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/CHANGES.rst) - [Commits](https://github.com/python-telegram-bot/python-telegram-bot/compare/v11.1.0...v12.0.0) Signed-off-by: dependabot-preview[bot] --- requirements-common.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-common.txt b/requirements-common.txt index 92e4f42ef..7b6befaf6 100644 --- a/requirements-common.txt +++ b/requirements-common.txt @@ -2,7 +2,7 @@ # mainly used for Raspberry pi installs ccxt==1.18.1115 SQLAlchemy==1.3.8 -python-telegram-bot==11.1.0 +python-telegram-bot==12.0.0 arrow==0.14.6 cachetools==3.1.1 requests==2.22.0 From 9c60ab796df28f114405d7ba0cf8dda5307fe1a2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 2 Sep 2019 20:14:41 +0200 Subject: [PATCH 2/5] Adapt telegram api to new interface of telegram-bot-12.0.0 --- freqtrade/rpc/telegram.py | 101 +++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index fe4929780..a5e8265da 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -31,7 +31,7 @@ def authorized_only(command_handler: Callable[..., None]) -> Callable[..., Any]: """ def wrapper(self, *args, **kwargs): """ Decorator logic """ - update = kwargs.get('update') or args[1] + update = kwargs.get('update') or args[0] # Reject unauthorized messages chat_id = int(self._config['telegram']['chat_id']) @@ -79,7 +79,8 @@ class Telegram(RPC): registers all known command handlers 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 handles = [ @@ -175,7 +176,7 @@ class Telegram(RPC): self._send_msg(message) @authorized_only - def _status(self, bot: Bot, update: Update) -> None: + def _status(self, update: Update, context: CallbackContext) -> None: """ Handler for /status. Returns the current TradeThread status @@ -221,13 +222,13 @@ class Telegram(RPC): messages.append("\n".join([l for l in lines if l]).format(**r)) for msg in messages: - self._send_msg(msg, bot=bot) + self._send_msg(msg) except RPCException as e: - self._send_msg(str(e), bot=bot) + self._send_msg(str(e)) @authorized_only - def _status_table(self, bot: Bot, update: Update) -> None: + def _status_table(self, update: Update, context: CallbackContext) -> None: """ Handler for /status table. Returns the current TradeThread status in table format @@ -240,10 +241,10 @@ class Telegram(RPC): message = tabulate(df_statuses, headers='keys', tablefmt='simple') self._send_msg(f"
{message}
", parse_mode=ParseMode.HTML) except RPCException as e: - self._send_msg(str(e), bot=bot) + self._send_msg(str(e)) @authorized_only - def _daily(self, bot: Bot, update: Update) -> None: + def _daily(self, update: Update, context: CallbackContext) -> None: """ Handler for /daily Returns a daily profit (in BTC) over the last n days. @@ -272,12 +273,12 @@ class Telegram(RPC): ], tablefmt='simple') message = f'Daily Profit over the last {timescale} days:\n
{stats_tab}
' - self._send_msg(message, bot=bot, parse_mode=ParseMode.HTML) + self._send_msg(message, parse_mode=ParseMode.HTML) except RPCException as e: - self._send_msg(str(e), bot=bot) + self._send_msg(str(e)) @authorized_only - def _profit(self, bot: Bot, update: Update) -> None: + def _profit(self, update: Update, context: CallbackContext) -> None: """ Handler for /profit. Returns a cumulative profit statistics. @@ -317,12 +318,12 @@ class Telegram(RPC): f"*Latest Trade opened:* `{latest_trade_date}`\n" \ f"*Avg. Duration:* `{avg_duration}`\n" \ f"*Best Performing:* `{best_pair}: {best_rate:.2f}%`" - self._send_msg(markdown_msg, bot=bot) + self._send_msg(markdown_msg) except RPCException as e: - self._send_msg(str(e), bot=bot) + self._send_msg(str(e)) @authorized_only - def _balance(self, bot: Bot, update: Update) -> None: + def _balance(self, update: Update, context: CallbackContext) -> None: """ Handler for /balance """ try: result = self._rpc_balance(self._config.get('fiat_display_currency', '')) @@ -339,7 +340,7 @@ class Telegram(RPC): # Handle overflowing messsage length if len(output + curr_output) >= MAX_TELEGRAM_MESSAGE_LENGTH: - self._send_msg(output, bot=bot) + self._send_msg(output) output = curr_output else: output += curr_output @@ -347,12 +348,12 @@ class Telegram(RPC): output += "\n*Estimated Value*:\n" \ "\t`BTC: {total: .8f}`\n" \ "\t`{symbol}: {value: .2f}`\n".format(**result) - self._send_msg(output, bot=bot) + self._send_msg(output) except RPCException as e: - self._send_msg(str(e), bot=bot) + self._send_msg(str(e)) @authorized_only - def _start(self, bot: Bot, update: Update) -> None: + def _start(self, update: Update, context: CallbackContext) -> None: """ Handler for /start. Starts TradeThread @@ -361,10 +362,10 @@ class Telegram(RPC): :return: None """ msg = self._rpc_start() - self._send_msg('Status: `{status}`'.format(**msg), bot=bot) + self._send_msg('Status: `{status}`'.format(**msg)) @authorized_only - def _stop(self, bot: Bot, update: Update) -> None: + def _stop(self, update: Update, context: CallbackContext) -> None: """ Handler for /stop. Stops TradeThread @@ -373,10 +374,10 @@ class Telegram(RPC): :return: None """ msg = self._rpc_stop() - self._send_msg('Status: `{status}`'.format(**msg), bot=bot) + self._send_msg('Status: `{status}`'.format(**msg)) @authorized_only - def _reload_conf(self, bot: Bot, update: Update) -> None: + def _reload_conf(self, update: Update, context: CallbackContext) -> None: """ Handler for /reload_conf. Triggers a config file reload @@ -385,10 +386,10 @@ class Telegram(RPC): :return: None """ msg = self._rpc_reload_conf() - self._send_msg('Status: `{status}`'.format(**msg), bot=bot) + self._send_msg('Status: `{status}`'.format(**msg)) @authorized_only - def _stopbuy(self, bot: Bot, update: Update) -> None: + def _stopbuy(self, update: Update, context: CallbackContext) -> None: """ Handler for /stop_buy. Sets max_open_trades to 0 and gracefully sells all open trades @@ -397,10 +398,10 @@ class Telegram(RPC): :return: None """ msg = self._rpc_stopbuy() - self._send_msg('Status: `{status}`'.format(**msg), bot=bot) + self._send_msg('Status: `{status}`'.format(**msg)) @authorized_only - def _forcesell(self, bot: Bot, update: Update) -> None: + def _forcesell(self, update: Update, context: CallbackContext) -> None: """ Handler for /forcesell . Sells the given trade at current price @@ -412,13 +413,13 @@ class Telegram(RPC): trade_id = update.message.text.replace('/forcesell', '').strip() try: 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: - self._send_msg(str(e), bot=bot) + self._send_msg(str(e)) @authorized_only - def _forcebuy(self, bot: Bot, update: Update) -> None: + def _forcebuy(self, update: Update, context: CallbackContext) -> None: """ Handler for /forcebuy . Buys a pair trade at the given or current price @@ -433,10 +434,10 @@ class Telegram(RPC): try: self._rpc_forcebuy(pair, price) except RPCException as e: - self._send_msg(str(e), bot=bot) + self._send_msg(str(e)) @authorized_only - def _performance(self, bot: Bot, update: Update) -> None: + def _performance(self, update: Update, context: CallbackContext) -> None: """ Handler for /performance. Shows a performance statistic from finished trades @@ -455,10 +456,10 @@ class Telegram(RPC): message = 'Performance:\n{}'.format(stats) self._send_msg(message, parse_mode=ParseMode.HTML) except RPCException as e: - self._send_msg(str(e), bot=bot) + self._send_msg(str(e)) @authorized_only - def _count(self, bot: Bot, update: Update) -> None: + def _count(self, update: Update, context: CallbackContext) -> None: """ Handler for /count. Returns the number of trades running @@ -475,10 +476,10 @@ class Telegram(RPC): logger.debug(message) self._send_msg(message, parse_mode=ParseMode.HTML) except RPCException as e: - self._send_msg(str(e), bot=bot) + self._send_msg(str(e)) @authorized_only - def _whitelist(self, bot: Bot, update: Update) -> None: + def _whitelist(self, update: Update, context: CallbackContext) -> None: """ Handler for /whitelist Shows the currently active whitelist @@ -492,17 +493,17 @@ class Telegram(RPC): logger.debug(message) self._send_msg(message) except RPCException as e: - self._send_msg(str(e), bot=bot) + self._send_msg(str(e)) @authorized_only - def _blacklist(self, bot: Bot, update: Update, args: List[str]) -> None: + def _blacklist(self, update: Update, context: CallbackContext) -> None: """ Handler for /blacklist Shows the currently active blacklist """ try: - blacklist = self._rpc_blacklist(args) + blacklist = self._rpc_blacklist(context.args) message = f"Blacklist contains {blacklist['length']} pairs\n" message += f"`{', '.join(blacklist['blacklist'])}`" @@ -510,10 +511,10 @@ class Telegram(RPC): logger.debug(message) self._send_msg(message) except RPCException as e: - self._send_msg(str(e), bot=bot) + self._send_msg(str(e)) @authorized_only - def _edge(self, bot: Bot, update: Update) -> None: + def _edge(self, update: Update, context: CallbackContext) -> None: """ Handler for /edge Shows information related to Edge @@ -522,12 +523,12 @@ class Telegram(RPC): edge_pairs = self._rpc_edge() edge_pairs_tab = tabulate(edge_pairs, headers='keys', tablefmt='simple') message = f'Edge only validated following pairs:\n
{edge_pairs_tab}
' - self._send_msg(message, bot=bot, parse_mode=ParseMode.HTML) + self._send_msg(message, parse_mode=ParseMode.HTML) except RPCException as e: - self._send_msg(str(e), bot=bot) + self._send_msg(str(e)) @authorized_only - def _help(self, bot: Bot, update: Update) -> None: + def _help(self, update: Update, context: CallbackContext) -> None: """ Handler for /help. Show commands of the bot @@ -559,10 +560,10 @@ class Telegram(RPC): "*/help:* `This help message`\n" \ "*/version:* `Show version`" - self._send_msg(message, bot=bot) + self._send_msg(message) @authorized_only - def _version(self, bot: Bot, update: Update) -> None: + def _version(self, update: Update, context: CallbackContext) -> None: """ Handler for /version. Show version information @@ -570,10 +571,9 @@ class Telegram(RPC): :param update: message update :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, - parse_mode: ParseMode = ParseMode.MARKDOWN) -> None: + def _send_msg(self, msg: str, parse_mode: ParseMode = ParseMode.MARKDOWN) -> None: """ Send given markdown message :param msg: message @@ -581,7 +581,6 @@ class Telegram(RPC): :param parse_mode: telegram parse mode :return: None """ - bot = bot or self._updater.bot keyboard = [['/daily', '/profit', '/balance'], ['/status', '/status table', '/performance'], @@ -591,7 +590,7 @@ class Telegram(RPC): try: try: - bot.send_message( + self._updater.bot.send_message( self._config['telegram']['chat_id'], text=msg, parse_mode=parse_mode, @@ -604,7 +603,7 @@ class Telegram(RPC): 'Telegram NetworkError: %s! Trying one more time.', network_err.message ) - bot.send_message( + self._updater.bot.send_message( self._config['telegram']['chat_id'], text=msg, parse_mode=parse_mode, From 8cad90f9e6b884a04b9813814e730e864c8ba0da Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 2 Sep 2019 20:17:23 +0200 Subject: [PATCH 3/5] Adapt to new api --- freqtrade/rpc/telegram.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index a5e8265da..4b64ee31e 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -4,12 +4,12 @@ This module manage Telegram communication """ import logging -from typing import Any, Callable, Dict, List +from typing import Any, Callable, Dict 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.ext import CommandHandler, Updater +from telegram.ext import CommandHandler, Updater, CallbackContext from freqtrade.__init__ import __version__ from freqtrade.rpc import RPC, RPCException, RPCMessageType @@ -97,7 +97,7 @@ class Telegram(RPC): CommandHandler('reload_conf', self._reload_conf), CommandHandler('stopbuy', self._stopbuy), CommandHandler('whitelist', self._whitelist), - CommandHandler('blacklist', self._blacklist, pass_args=True), + CommandHandler('blacklist', self._blacklist), CommandHandler('edge', self._edge), CommandHandler('help', self._help), CommandHandler('version', self._version), @@ -185,11 +185,8 @@ class Telegram(RPC): :return: None """ - # Check if additional parameters are passed - params = update.message.text.replace('/status', '').split(' ') \ - if update.message.text else [] - if 'table' in params: - self._status_table(bot, update) + if 'table' in context.args: + self._status_table(update, context) return try: @@ -255,8 +252,8 @@ class Telegram(RPC): stake_cur = self._config['stake_currency'] fiat_disp_cur = self._config.get('fiat_display_currency', '') try: - timescale = int(update.message.text.replace('/daily', '').strip()) - except (TypeError, ValueError): + timescale = int(context.args[0]) + except (TypeError, ValueError, IndexError): timescale = 7 try: stats = self._rpc_daily_profit( From 3b15cce07a33d2bf2d27649a929e9f62ab310aec Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 2 Sep 2019 20:17:47 +0200 Subject: [PATCH 4/5] Handle arguments uniformly (by using context.args) --- freqtrade/rpc/telegram.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/freqtrade/rpc/telegram.py b/freqtrade/rpc/telegram.py index 4b64ee31e..d11fc02ab 100644 --- a/freqtrade/rpc/telegram.py +++ b/freqtrade/rpc/telegram.py @@ -407,7 +407,7 @@ class Telegram(RPC): :return: None """ - trade_id = update.message.text.replace('/forcesell', '').strip() + trade_id = context.args[0] if len(context.args) > 0 else None try: msg = self._rpc_forcesell(trade_id) self._send_msg('Forcesell Result: `{result}`'.format(**msg)) @@ -425,9 +425,8 @@ class Telegram(RPC): :return: None """ - message = update.message.text.replace('/forcebuy', '').strip().split() - pair = message[0] - price = float(message[1]) if len(message) > 1 else None + pair = context.args[0] + price = float(context.args[1]) if len(context.args) > 1 else None try: self._rpc_forcebuy(pair, price) except RPCException as e: From dc9fda76f351bf145b08445c964a8b4884e1663a Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 2 Sep 2019 20:42:39 +0200 Subject: [PATCH 5/5] Fix tests to adapt to new telegram-bot interface --- freqtrade/tests/rpc/test_rpc_telegram.py | 161 ++++++++++++++--------- 1 file changed, 96 insertions(+), 65 deletions(-) diff --git a/freqtrade/tests/rpc/test_rpc_telegram.py b/freqtrade/tests/rpc/test_rpc_telegram.py index 2f469643f..3820332b8 100644 --- a/freqtrade/tests/rpc/test_rpc_telegram.py +++ b/freqtrade/tests/rpc/test_rpc_telegram.py @@ -100,7 +100,7 @@ def test_authorized_only(default_conf, mocker, caplog) -> None: bot = FreqtradeBot(default_conf) patch_get_signal(bot, (True, False)) dummy = DummyCls(bot) - dummy.dummy_handler(bot=MagicMock(), update=update) + dummy.dummy_handler(update=update, context=MagicMock()) assert dummy.state['called'] is True assert log_has('Executing handler: dummy_handler for chat_id: 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) patch_get_signal(bot, (True, False)) dummy = DummyCls(bot) - dummy.dummy_handler(bot=MagicMock(), update=update) + dummy.dummy_handler(update=update, context=MagicMock()) assert dummy.state['called'] is False assert not log_has('Executing handler: dummy_handler for chat_id: 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)) dummy = DummyCls(bot) - dummy.dummy_exception(bot=MagicMock(), update=update) + dummy.dummy_exception(update=update, context=MagicMock()) assert dummy.state['called'] is False assert not log_has('Executing handler: dummy_handler for chat_id: 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): freqtradebot.create_trades() - telegram._status(bot=MagicMock(), update=update) + telegram._status(update=update, context=MagicMock()) assert msg_mock.call_count == 1 - update.message.text = MagicMock() - update.message.text.replace = MagicMock(return_value='table 2 3') - telegram._status(bot=MagicMock(), update=update) + context = MagicMock() + # /status table 2 3 + context.args = ["table", "2", "3"] + telegram._status(update=update, context=context) 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 # 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 'no active trade' in msg_mock.call_args_list[0][0][0] msg_mock.reset_mock() freqtradebot.state = State.RUNNING - telegram._status(bot=MagicMock(), update=update) + telegram._status(update=update, context=MagicMock()) assert msg_mock.call_count == 1 assert 'no active trade' in msg_mock.call_args_list[0][0][0] msg_mock.reset_mock() @@ -242,7 +243,7 @@ def test_status_handle(default_conf, update, ticker, fee, markets, mocker) -> No # Create some test data freqtradebot.create_trades() # 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 # 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 # 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 'no active order' in msg_mock.call_args_list[0][0][0] msg_mock.reset_mock() 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 'no active order' in msg_mock.call_args_list[0][0][0] msg_mock.reset_mock() @@ -294,7 +295,7 @@ def test_status_table_handle(default_conf, update, ticker, fee, markets, mocker) # Create some test data freqtradebot.create_trades() - telegram._status_table(bot=MagicMock(), update=update) + telegram._status_table(update=update, context=MagicMock()) text = re.sub('', '', msg_mock.call_args_list[-1][0][0]) line = text.split("\n") @@ -346,8 +347,10 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee, trade.is_open = False # Try valid data - update.message.text = '/daily 2' - telegram._daily(bot=MagicMock(), update=update) + # /daily 2 + context = MagicMock() + context.args = ["2"] + telegram._daily(update=update, context=context) assert msg_mock.call_count == 1 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] @@ -369,9 +372,10 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order, fee, trade.close_date = datetime.utcnow() trade.is_open = False - update.message.text = '/daily 1' - - telegram._daily(bot=MagicMock(), update=update) + # /daily 1 + context = MagicMock() + 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(' 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] @@ -398,16 +402,20 @@ def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None: # Try invalid data msg_mock.reset_mock() freqtradebot.state = State.RUNNING - update.message.text = '/daily -2' - telegram._daily(bot=MagicMock(), update=update) + # /daily -2 + context = MagicMock() + context.args = ["-2"] + telegram._daily(update=update, context=context) assert msg_mock.call_count == 1 assert 'must be an integer greater than 0' in msg_mock.call_args_list[0][0][0] # Try invalid data msg_mock.reset_mock() freqtradebot.state = State.RUNNING - update.message.text = '/daily today' - telegram._daily(bot=MagicMock(), update=update) + # /daily today + 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] @@ -433,7 +441,7 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee, patch_get_signal(freqtradebot, (True, False)) telegram = Telegram(freqtradebot) - telegram._profit(bot=MagicMock(), update=update) + telegram._profit(update=update, context=MagicMock()) assert msg_mock.call_count == 1 assert 'no closed trade' in msg_mock.call_args_list[0][0][0] 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 trade.update(limit_buy_order) - telegram._profit(bot=MagicMock(), update=update) + telegram._profit(update=update, context=MagicMock()) assert msg_mock.call_count == 1 assert 'no closed trade' in msg_mock.call_args_list[-1][0][0] 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.is_open = False - telegram._profit(bot=MagicMock(), update=update) + telegram._profit(update=update, context=MagicMock()) assert msg_mock.call_count == 1 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] @@ -507,7 +515,7 @@ def test_telegram_balance_handle(default_conf, update, mocker, rpc_balance) -> N telegram = Telegram(freqtradebot) - telegram._balance(bot=MagicMock(), update=update) + telegram._balance(update=update, context=MagicMock()) result = msg_mock.call_args_list[0][0][0] assert msg_mock.call_count == 1 assert '*BTC:*' in result @@ -536,7 +544,7 @@ def test_balance_handle_empty_response(default_conf, update, mocker) -> None: telegram = Telegram(freqtradebot) 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] assert msg_mock.call_count == 1 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._balance(bot=MagicMock(), update=update) + telegram._balance(update=update, context=MagicMock()) result = msg_mock.call_args_list[0][0][0] assert msg_mock.call_count == 1 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._balance(bot=MagicMock(), update=update) + telegram._balance(update=update, context=MagicMock()) assert msg_mock.call_count > 1 # Test if wrap happens around 4000 - # 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 assert freqtradebot.state == State.STOPPED - telegram._start(bot=MagicMock(), update=update) + telegram._start(update=update, context=MagicMock()) assert freqtradebot.state == State.RUNNING 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 assert freqtradebot.state == State.RUNNING - telegram._start(bot=MagicMock(), update=update) + telegram._start(update=update, context=MagicMock()) assert freqtradebot.state == State.RUNNING assert msg_mock.call_count == 1 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 assert freqtradebot.state == State.RUNNING - telegram._stop(bot=MagicMock(), update=update) + telegram._stop(update=update, context=MagicMock()) assert freqtradebot.state == State.STOPPED assert msg_mock.call_count == 1 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 assert freqtradebot.state == State.STOPPED - telegram._stop(bot=MagicMock(), update=update) + telegram._stop(update=update, context=MagicMock()) assert freqtradebot.state == State.STOPPED assert msg_mock.call_count == 1 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) 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 msg_mock.call_count == 1 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 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 msg_mock.call_count == 1 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 mocker.patch('freqtrade.exchange.Exchange.get_ticker', ticker_sell_up) - update.message.text = '/forcesell 1' - telegram._forcesell(bot=MagicMock(), update=update) + # /forcesell 1 + context = MagicMock() + context.args = ["1"] + telegram._forcesell(update=update, context=context) assert rpc_mock.call_count == 2 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() assert trade - update.message.text = '/forcesell 1' - telegram._forcesell(bot=MagicMock(), update=update) + # /forcesell 1 + context = MagicMock() + context.args = ["1"] + telegram._forcesell(update=update, context=context) 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() rpc_mock.reset_mock() - update.message.text = '/forcesell all' - telegram._forcesell(bot=MagicMock(), update=update) + # /forcesell all + context = MagicMock() + context.args = ["all"] + telegram._forcesell(update=update, context=context) assert rpc_mock.call_count == 4 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 freqtradebot.state = State.STOPPED - update.message.text = '/forcesell 1' - telegram._forcesell(bot=MagicMock(), update=update) + # /forcesell 1 + context = MagicMock() + context.args = ["1"] + telegram._forcesell(update=update, context=context) assert msg_mock.call_count == 1 assert 'not running' in msg_mock.call_args_list[0][0][0] # No argument msg_mock.reset_mock() freqtradebot.state = State.RUNNING - update.message.text = '/forcesell' - telegram._forcesell(bot=MagicMock(), update=update) + context = MagicMock() + context.args = [] + telegram._forcesell(update=update, context=context) assert msg_mock.call_count == 1 assert 'invalid argument' in msg_mock.call_args_list[0][0][0] # Invalid argument msg_mock.reset_mock() freqtradebot.state = State.RUNNING - update.message.text = '/forcesell 123456' - telegram._forcesell(bot=MagicMock(), update=update) + # /forcesell 123456 + context = MagicMock() + context.args = ["123456"] + telegram._forcesell(update=update, context=context) assert msg_mock.call_count == 1 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)) telegram = Telegram(freqtradebot) - update.message.text = '/forcebuy ETH/BTC' - telegram._forcebuy(bot=MagicMock(), update=update) + # /forcebuy ETH/BTC + context = MagicMock() + context.args = ["ETH/BTC"] + telegram._forcebuy(update=update, context=context) assert fbuy_mock.call_count == 1 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 fbuy_mock = MagicMock(return_value=None) mocker.patch('freqtrade.rpc.RPC._rpc_forcebuy', fbuy_mock) - update.message.text = '/forcebuy ETH/BTC 0.055' - telegram._forcebuy(bot=MagicMock(), update=update) + # /forcebuy ETH/BTC 0.055 + context = MagicMock() + context.args = ["ETH/BTC", "0.055"] + telegram._forcebuy(update=update, context=context) assert fbuy_mock.call_count == 1 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) 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_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.is_open = False - telegram._performance(bot=MagicMock(), update=update) + telegram._performance(update=update, context=MagicMock()) assert msg_mock.call_count == 1 assert 'Performance' in msg_mock.call_args_list[0][0][0] assert 'ETH/BTC\t6.20% (1)' 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) freqtradebot.state = State.STOPPED - telegram._count(bot=MagicMock(), update=update) + telegram._count(update=update, context=MagicMock()) assert msg_mock.call_count == 1 assert 'not running' in msg_mock.call_args_list[0][0][0] msg_mock.reset_mock() @@ -1030,7 +1053,7 @@ def test_count_handle(default_conf, update, ticker, fee, markets, mocker) -> Non # Create some test data freqtradebot.create_trades() msg_mock.reset_mock() - telegram._count(bot=MagicMock(), update=update) + telegram._count(update=update, context=MagicMock()) msg = '
  current    max    total stake\n---------  -----  -------------\n' \
           '        1      {}          {}
'\ @@ -1052,7 +1075,7 @@ def test_whitelist_static(default_conf, update, mocker) -> None: telegram = Telegram(freqtradebot) - telegram._whitelist(bot=MagicMock(), update=update) + telegram._whitelist(update=update, context=MagicMock()) assert msg_mock.call_count == 1 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]) @@ -1073,7 +1096,7 @@ def test_whitelist_dynamic(default_conf, update, mocker) -> None: telegram = Telegram(freqtradebot) - telegram._whitelist(bot=MagicMock(), update=update) + telegram._whitelist(update=update, context=MagicMock()) assert msg_mock.call_count == 1 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]) @@ -1090,13 +1113,17 @@ def test_blacklist_static(default_conf, update, mocker) -> None: telegram = Telegram(freqtradebot) - telegram._blacklist(bot=MagicMock(), update=update, args=[]) + telegram._blacklist(update=update, context=MagicMock()) assert msg_mock.call_count == 1 assert ("Blacklist contains 2 pairs\n`DOGE/BTC, HOT/BTC`" in msg_mock.call_args_list[0][0][0]) 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 ("Blacklist contains 3 pairs\n`DOGE/BTC, HOT/BTC, ETH/BTC`" 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._edge(bot=MagicMock(), update=update) + telegram._edge(update=update, context=MagicMock()) assert msg_mock.call_count == 1 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._edge(bot=MagicMock(), update=update) + telegram._edge(update=update, context=MagicMock()) assert msg_mock.call_count == 1 assert 'Edge only validated following pairs:\n
' 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._help(bot=MagicMock(), update=update)
+    telegram._help(update=update, context=MagicMock())
     assert msg_mock.call_count == 1
     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)
     telegram = Telegram(freqtradebot)
 
-    telegram._version(bot=MagicMock(), update=update)
+    telegram._version(update=update, context=MagicMock())
     assert msg_mock.call_count == 1
     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()
     freqtradebot = get_patched_freqtradebot(mocker, default_conf)
     telegram = Telegram(freqtradebot)
+    telegram._updater = MagicMock()
+    telegram._updater.bot = bot
 
     telegram._config['telegram']['enabled'] = True
-    telegram._send_msg('test', bot)
+    telegram._send_msg('test')
     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'))
     freqtradebot = get_patched_freqtradebot(mocker, default_conf)
     telegram = Telegram(freqtradebot)
+    telegram._updater = MagicMock()
+    telegram._updater.bot = bot
 
     telegram._config['telegram']['enabled'] = True
-    telegram._send_msg('test', bot)
+    telegram._send_msg('test')
 
     # Bot should've tried to send it twice
     assert len(bot.method_calls) == 2