Merge pull request #7549 from froggleston/discord_sendmsg
Add support for dp.send_msg() to webhooks
This commit is contained in:
commit
28f0a35e73
@ -215,16 +215,18 @@ Mandatory parameters are marked as **Required**, which means that they are requi
|
||||
| `telegram.balance_dust_level` | Dust-level (in stake currency) - currencies with a balance below this will not be shown by `/balance`. <br> **Datatype:** float
|
||||
| `telegram.reload` | Allow "reload" buttons on telegram messages. <br>*Defaults to `True`.<br> **Datatype:** boolean
|
||||
| `telegram.notification_settings.*` | Detailed notification settings. Refer to the [telegram documentation](telegram-usage.md) for details.<br> **Datatype:** dictionary
|
||||
| `telegram.allow_custom_messages` | Enable the sending of Telegram messages from strategies via the dataprovider.send_msg() function. <br> **Datatype:** Boolean
|
||||
| | **Webhook**
|
||||
| `webhook.enabled` | Enable usage of Webhook notifications <br> **Datatype:** Boolean
|
||||
| `webhook.url` | URL for the webhook. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.webhookentry` | Payload to send on entry. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.webhookentrycancel` | Payload to send on entry order cancel. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.webhookentryfill` | Payload to send on entry order filled. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.webhookexit` | Payload to send on exit. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.webhookexitcancel` | Payload to send on exit order cancel. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.webhookexitfill` | Payload to send on exit order filled. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.webhookstatus` | Payload to send on status calls. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.entry` | Payload to send on entry. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.entry_cancel` | Payload to send on entry order cancel. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.entry_fill` | Payload to send on entry order filled. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.exit` | Payload to send on exit. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.exit_cancel` | Payload to send on exit order cancel. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.exit_fill` | Payload to send on exit order filled. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.status` | Payload to send on status calls. Only required if `webhook.enabled` is `true`. See the [webhook documentation](webhook-config.md) for more details. <br> **Datatype:** String
|
||||
| `webhook.allow_custom_messages` | Enable the sending of Webhook messages from strategies via the dataprovider.send_msg() function. <br> **Datatype:** Boolean
|
||||
| | **Rest API / FreqUI / Producer-Consumer**
|
||||
| `api_server.enabled` | Enable usage of API Server. See the [API Server documentation](rest-api.md) for more details. <br> **Datatype:** Boolean
|
||||
| `api_server.listen_ip_address` | Bind IP address. See the [API Server documentation](rest-api.md) for more details. <br> **Datatype:** IPv4
|
||||
|
@ -66,11 +66,11 @@ We will keep a compatibility layer for 1-2 versions (so both `buy_tag` and `ente
|
||||
|
||||
#### Naming changes
|
||||
|
||||
Webhook terminology changed from "sell" to "exit", and from "buy" to "entry".
|
||||
Webhook terminology changed from "sell" to "exit", and from "buy" to "entry", removing "webhook" in the process.
|
||||
|
||||
* `webhookbuy` -> `webhookentry`
|
||||
* `webhookbuyfill` -> `webhookentryfill`
|
||||
* `webhookbuycancel` -> `webhookentrycancel`
|
||||
* `webhooksell` -> `webhookexit`
|
||||
* `webhooksellfill` -> `webhookexitfill`
|
||||
* `webhooksellcancel` -> `webhookexitcancel`
|
||||
* `webhookbuy`, `webhookentry` -> `entry`
|
||||
* `webhookbuyfill`, `webhookentryfill` -> `entry_fill`
|
||||
* `webhookbuycancel`, `webhookentrycancel` -> `entry_cancel`
|
||||
* `webhooksell`, `webhookexit` -> `exit`
|
||||
* `webhooksellfill`, `webhookexitfill` -> `exit_fill`
|
||||
* `webhooksellcancel`, `webhookexitcancel` -> `exit_cancel`
|
||||
|
@ -50,12 +50,12 @@ Note : `forcesell`, `forcebuy`, `emergencysell` are changed to `force_exit`, `fo
|
||||
* `force_sell` -> `force_exit`
|
||||
* `emergency_sell` -> `emergency_exit`
|
||||
* Webhook terminology changed from "sell" to "exit", and from "buy" to entry
|
||||
* `webhookbuy` -> `webhookentry`
|
||||
* `webhookbuyfill` -> `webhookentryfill`
|
||||
* `webhookbuycancel` -> `webhookentrycancel`
|
||||
* `webhooksell` -> `webhookexit`
|
||||
* `webhooksellfill` -> `webhookexitfill`
|
||||
* `webhooksellcancel` -> `webhookexitcancel`
|
||||
* `webhookbuy` -> `entry`
|
||||
* `webhookbuyfill` -> `entry_fill`
|
||||
* `webhookbuycancel` -> `entry_cancel`
|
||||
* `webhooksell` -> `exit`
|
||||
* `webhooksellfill` -> `exit_fill`
|
||||
* `webhooksellcancel` -> `exit_cancel`
|
||||
* Telegram notification settings
|
||||
* `buy` -> `entry`
|
||||
* `buy_fill` -> `entry_fill`
|
||||
|
@ -77,6 +77,7 @@ Example configuration showing the different settings:
|
||||
"enabled": true,
|
||||
"token": "your_telegram_token",
|
||||
"chat_id": "your_telegram_chat_id",
|
||||
"allow_custom_messages": true,
|
||||
"notification_settings": {
|
||||
"status": "silent",
|
||||
"warning": "on",
|
||||
@ -115,6 +116,7 @@ Example configuration showing the different settings:
|
||||
`show_candle` - show candle values as part of entry/exit messages. Only possible values are `"ohlc"` or `"off"`.
|
||||
|
||||
`balance_dust_level` will define what the `/balance` command takes as "dust" - Currencies with a balance below this will be shown.
|
||||
`allow_custom_messages` completely disable strategy messages.
|
||||
`reload` allows you to disable reload-buttons on selected messages.
|
||||
|
||||
## Create a custom keyboard (command shortcut buttons)
|
||||
|
@ -10,37 +10,37 @@ Sample configuration (tested using IFTTT).
|
||||
"webhook": {
|
||||
"enabled": true,
|
||||
"url": "https://maker.ifttt.com/trigger/<YOUREVENT>/with/key/<YOURKEY>/",
|
||||
"webhookentry": {
|
||||
"entry": {
|
||||
"value1": "Buying {pair}",
|
||||
"value2": "limit {limit:8f}",
|
||||
"value3": "{stake_amount:8f} {stake_currency}"
|
||||
},
|
||||
"webhookentrycancel": {
|
||||
"entry_cancel": {
|
||||
"value1": "Cancelling Open Buy Order for {pair}",
|
||||
"value2": "limit {limit:8f}",
|
||||
"value3": "{stake_amount:8f} {stake_currency}"
|
||||
},
|
||||
"webhookentryfill": {
|
||||
"entry_fill": {
|
||||
"value1": "Buy Order for {pair} filled",
|
||||
"value2": "at {open_rate:8f}",
|
||||
"value3": ""
|
||||
},
|
||||
"webhookexit": {
|
||||
"exit": {
|
||||
"value1": "Exiting {pair}",
|
||||
"value2": "limit {limit:8f}",
|
||||
"value3": "profit: {profit_amount:8f} {stake_currency} ({profit_ratio})"
|
||||
},
|
||||
"webhookexitcancel": {
|
||||
"exit_cancel": {
|
||||
"value1": "Cancelling Open Exit Order for {pair}",
|
||||
"value2": "limit {limit:8f}",
|
||||
"value3": "profit: {profit_amount:8f} {stake_currency} ({profit_ratio})"
|
||||
},
|
||||
"webhookexitfill": {
|
||||
"exit_fill": {
|
||||
"value1": "Exit Order for {pair} filled",
|
||||
"value2": "at {close_rate:8f}.",
|
||||
"value3": ""
|
||||
},
|
||||
"webhookstatus": {
|
||||
"status": {
|
||||
"value1": "Status: {status}",
|
||||
"value2": "",
|
||||
"value3": ""
|
||||
@ -57,7 +57,7 @@ You can set the POST body format to Form-Encoded (default), JSON-Encoded, or raw
|
||||
"enabled": true,
|
||||
"url": "https://<YOURSUBDOMAIN>.cloud.mattermost.com/hooks/<YOURHOOK>",
|
||||
"format": "json",
|
||||
"webhookstatus": {
|
||||
"status": {
|
||||
"text": "Status: {status}"
|
||||
}
|
||||
},
|
||||
@ -88,17 +88,30 @@ Optional parameters are available to enable automatic retries for webhook messag
|
||||
"url": "https://<YOURHOOKURL>",
|
||||
"retries": 3,
|
||||
"retry_delay": 0.2,
|
||||
"webhookstatus": {
|
||||
"status": {
|
||||
"status": "Status: {status}"
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
Custom messages can be sent to Webhook endpoints via the `self.dp.send_msg()` function from within the strategy. To enable this, set the `allow_custom_messages` option to `true`:
|
||||
|
||||
```json
|
||||
"webhook": {
|
||||
"enabled": true,
|
||||
"url": "https://<YOURHOOKURL>",
|
||||
"allow_custom_messages": true,
|
||||
"strategy_msg": {
|
||||
"status": "StrategyMessage: {msg}"
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
Different payloads can be configured for different events. Not all fields are necessary, but you should configure at least one of the dicts, otherwise the webhook will never be called.
|
||||
|
||||
### Webhookentry
|
||||
### Entry
|
||||
|
||||
The fields in `webhook.webhookentry` are filled when the bot executes a long/short. Parameters are filled using string.format.
|
||||
The fields in `webhook.entry` are filled when the bot executes a long/short. Parameters are filled using string.format.
|
||||
Possible parameters are:
|
||||
|
||||
* `trade_id`
|
||||
@ -118,9 +131,9 @@ Possible parameters are:
|
||||
* `current_rate`
|
||||
* `enter_tag`
|
||||
|
||||
### Webhookentrycancel
|
||||
### Entry cancel
|
||||
|
||||
The fields in `webhook.webhookentrycancel` are filled when the bot cancels a long/short order. Parameters are filled using string.format.
|
||||
The fields in `webhook.entry_cancel` are filled when the bot cancels a long/short order. Parameters are filled using string.format.
|
||||
Possible parameters are:
|
||||
|
||||
* `trade_id`
|
||||
@ -139,9 +152,9 @@ Possible parameters are:
|
||||
* `current_rate`
|
||||
* `enter_tag`
|
||||
|
||||
### Webhookentryfill
|
||||
### Entry fill
|
||||
|
||||
The fields in `webhook.webhookentryfill` are filled when the bot filled a long/short order. Parameters are filled using string.format.
|
||||
The fields in `webhook.entry_fill` are filled when the bot filled a long/short order. Parameters are filled using string.format.
|
||||
Possible parameters are:
|
||||
|
||||
* `trade_id`
|
||||
@ -160,9 +173,9 @@ Possible parameters are:
|
||||
* `current_rate`
|
||||
* `enter_tag`
|
||||
|
||||
### Webhookexit
|
||||
### Exit
|
||||
|
||||
The fields in `webhook.webhookexit` are filled when the bot exits a trade. Parameters are filled using string.format.
|
||||
The fields in `webhook.exit` are filled when the bot exits a trade. Parameters are filled using string.format.
|
||||
Possible parameters are:
|
||||
|
||||
* `trade_id`
|
||||
@ -184,9 +197,9 @@ Possible parameters are:
|
||||
* `open_date`
|
||||
* `close_date`
|
||||
|
||||
### Webhookexitfill
|
||||
### Exit fill
|
||||
|
||||
The fields in `webhook.webhookexitfill` are filled when the bot fills a exit order (closes a Trade). Parameters are filled using string.format.
|
||||
The fields in `webhook.exit_fill` are filled when the bot fills a exit order (closes a Trade). Parameters are filled using string.format.
|
||||
Possible parameters are:
|
||||
|
||||
* `trade_id`
|
||||
@ -209,9 +222,9 @@ Possible parameters are:
|
||||
* `open_date`
|
||||
* `close_date`
|
||||
|
||||
### Webhookexitcancel
|
||||
### Exit cancel
|
||||
|
||||
The fields in `webhook.webhookexitcancel` are filled when the bot cancels a exit order. Parameters are filled using string.format.
|
||||
The fields in `webhook.exit_cancel` are filled when the bot cancels a exit order. Parameters are filled using string.format.
|
||||
Possible parameters are:
|
||||
|
||||
* `trade_id`
|
||||
@ -234,9 +247,9 @@ Possible parameters are:
|
||||
* `open_date`
|
||||
* `close_date`
|
||||
|
||||
### Webhookstatus
|
||||
### Status
|
||||
|
||||
The fields in `webhook.webhookstatus` are used for regular status messages (Started / Stopped / ...). Parameters are filled using string.format.
|
||||
The fields in `webhook.status` are used for regular status messages (Started / Stopped / ...). Parameters are filled using string.format.
|
||||
|
||||
The only possible value here is `{status}`.
|
||||
|
||||
@ -280,7 +293,6 @@ You can configure this as follows:
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
The above represents the default (`exit_fill` and `entry_fill` are optional and will default to the above configuration) - modifications are obviously possible.
|
||||
|
||||
Available fields correspond to the fields for webhooks and are documented in the corresponding webhook sections.
|
||||
@ -288,3 +300,13 @@ Available fields correspond to the fields for webhooks and are documented in the
|
||||
The notifications will look as follows by default.
|
||||
|
||||
![discord-notification](assets/discord_notification.png)
|
||||
|
||||
Custom messages can be sent from a strategy to Discord endpoints via the dataprovider.send_msg() function. To enable this, set the `allow_custom_messages` option to `true`:
|
||||
|
||||
```json
|
||||
"discord": {
|
||||
"enabled": true,
|
||||
"webhook_url": "https://discord.com/api/webhooks/<Your webhook URL ...>",
|
||||
"allow_custom_messages": true,
|
||||
},
|
||||
```
|
||||
|
@ -5,7 +5,7 @@ bot constants
|
||||
"""
|
||||
from typing import Any, Dict, List, Literal, Tuple
|
||||
|
||||
from freqtrade.enums import CandleType
|
||||
from freqtrade.enums import CandleType, RPCMessageType
|
||||
|
||||
|
||||
DEFAULT_CONFIG = 'config.json'
|
||||
@ -282,6 +282,7 @@ CONF_SCHEMA = {
|
||||
'enabled': {'type': 'boolean'},
|
||||
'token': {'type': 'string'},
|
||||
'chat_id': {'type': 'string'},
|
||||
'allow_custom_messages': {'type': 'boolean', 'default': True},
|
||||
'balance_dust_level': {'type': 'number', 'minimum': 0.0},
|
||||
'notification_settings': {
|
||||
'type': 'object',
|
||||
@ -344,6 +345,8 @@ CONF_SCHEMA = {
|
||||
'format': {'type': 'string', 'enum': WEBHOOK_FORMAT_OPTIONS, 'default': 'form'},
|
||||
'retries': {'type': 'integer', 'minimum': 0},
|
||||
'retry_delay': {'type': 'number', 'minimum': 0},
|
||||
**dict([(x, {'type': 'object'}) for x in RPCMessageType]),
|
||||
# Below -> Deprecated
|
||||
'webhookentry': {'type': 'object'},
|
||||
'webhookentrycancel': {'type': 'object'},
|
||||
'webhookentryfill': {'type': 'object'},
|
||||
|
@ -11,13 +11,12 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class Discord(Webhook):
|
||||
def __init__(self, rpc: 'RPC', config: Config):
|
||||
# super().__init__(rpc, config)
|
||||
self._config = config
|
||||
self.rpc = rpc
|
||||
self.config = config
|
||||
self.strategy = config.get('strategy', '')
|
||||
self.timeframe = config.get('timeframe', '')
|
||||
|
||||
self._url = self.config['discord']['webhook_url']
|
||||
self._url = config['discord']['webhook_url']
|
||||
self._format = 'json'
|
||||
self._retries = 1
|
||||
self._retry_delay = 0.1
|
||||
@ -31,19 +30,21 @@ class Discord(Webhook):
|
||||
|
||||
def send_msg(self, msg) -> None:
|
||||
|
||||
if msg['type'].value in self.config['discord']:
|
||||
if msg['type'].value in self._config['discord']:
|
||||
logger.info(f"Sending discord message: {msg}")
|
||||
|
||||
msg['strategy'] = self.strategy
|
||||
msg['timeframe'] = self.timeframe
|
||||
fields = self.config['discord'].get(msg['type'].value)
|
||||
fields = self._config['discord'].get(msg['type'].value)
|
||||
color = 0x0000FF
|
||||
if msg['type'] in (RPCMessageType.EXIT, RPCMessageType.EXIT_FILL):
|
||||
profit_ratio = msg.get('profit_ratio')
|
||||
color = (0x00FF00 if profit_ratio > 0 else 0xFF0000)
|
||||
|
||||
title = msg['type'].value
|
||||
if 'pair' in msg:
|
||||
title = f"Trade: {msg['pair']} {msg['type'].value}"
|
||||
embeds = [{
|
||||
'title': f"Trade: {msg['pair']} {msg['type'].value}",
|
||||
'title': title,
|
||||
'color': color,
|
||||
'fields': [],
|
||||
|
||||
@ -51,7 +52,7 @@ class Discord(Webhook):
|
||||
for f in fields:
|
||||
for k, v in f.items():
|
||||
v = v.format(**msg)
|
||||
embeds[0]['fields'].append( # type: ignore
|
||||
embeds[0]['fields'].append(
|
||||
{'name': k, 'value': v, 'inline': True})
|
||||
|
||||
# Send the message to discord channel
|
||||
|
@ -88,7 +88,10 @@ class RPCManager:
|
||||
"""
|
||||
while queue:
|
||||
msg = queue.popleft()
|
||||
self.send_msg({
|
||||
logger.info('Sending rpc strategy_msg: %s', msg)
|
||||
for mod in self.registered_modules:
|
||||
if mod._config.get(mod.name, {}).get('allow_custom_messages', False):
|
||||
mod.send_msg({
|
||||
'type': RPCMessageType.STRATEGY_MSG,
|
||||
'msg': msg,
|
||||
})
|
||||
|
@ -3,7 +3,7 @@ This module manages webhook communication
|
||||
"""
|
||||
import logging
|
||||
import time
|
||||
from typing import Any, Dict
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from requests import RequestException, post
|
||||
|
||||
@ -41,10 +41,9 @@ class Webhook(RPCHandler):
|
||||
"""
|
||||
pass
|
||||
|
||||
def send_msg(self, msg: Dict[str, Any]) -> None:
|
||||
""" Send a message to telegram channel """
|
||||
try:
|
||||
def _get_value_dict(self, msg: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||
whconfig = self._config['webhook']
|
||||
# Deprecated 2022.10 - only keep generic method.
|
||||
if msg['type'] in [RPCMessageType.ENTRY]:
|
||||
valuedict = whconfig.get('webhookentry')
|
||||
elif msg['type'] in [RPCMessageType.ENTRY_CANCEL]:
|
||||
@ -61,6 +60,9 @@ class Webhook(RPCHandler):
|
||||
RPCMessageType.STARTUP,
|
||||
RPCMessageType.WARNING):
|
||||
valuedict = whconfig.get('webhookstatus')
|
||||
elif msg['type'].value in whconfig:
|
||||
# Allow all types ...
|
||||
valuedict = whconfig.get(msg['type'].value)
|
||||
elif msg['type'] in (
|
||||
RPCMessageType.PROTECTION_TRIGGER,
|
||||
RPCMessageType.PROTECTION_TRIGGER_GLOBAL,
|
||||
@ -68,9 +70,15 @@ class Webhook(RPCHandler):
|
||||
RPCMessageType.ANALYZED_DF,
|
||||
RPCMessageType.STRATEGY_MSG):
|
||||
# Don't fail for non-implemented types
|
||||
return
|
||||
else:
|
||||
raise NotImplementedError('Unknown message type: {}'.format(msg['type']))
|
||||
return None
|
||||
return valuedict
|
||||
|
||||
def send_msg(self, msg: Dict[str, Any]) -> None:
|
||||
""" Send a message to telegram channel """
|
||||
try:
|
||||
|
||||
valuedict = self._get_value_dict(msg)
|
||||
|
||||
if not valuedict:
|
||||
logger.info("Message type '%s' not configured for webhooks", msg['type'])
|
||||
return
|
||||
|
@ -99,6 +99,7 @@ def test_send_msg_telegram_error(mocker, default_conf, caplog) -> None:
|
||||
|
||||
def test_process_msg_queue(mocker, default_conf, caplog) -> None:
|
||||
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg')
|
||||
default_conf['telegram']['allow_custom_messages'] = True
|
||||
mocker.patch('freqtrade.rpc.telegram.Telegram._init')
|
||||
|
||||
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
|
||||
@ -108,8 +109,8 @@ def test_process_msg_queue(mocker, default_conf, caplog) -> None:
|
||||
queue.append('Test message 2')
|
||||
rpc_manager.process_msg_queue(queue)
|
||||
|
||||
assert log_has("Sending rpc message: {'type': strategy_msg, 'msg': 'Test message'}", caplog)
|
||||
assert log_has("Sending rpc message: {'type': strategy_msg, 'msg': 'Test message 2'}", caplog)
|
||||
assert log_has("Sending rpc strategy_msg: Test message", caplog)
|
||||
assert log_has("Sending rpc strategy_msg: Test message 2", caplog)
|
||||
assert telegram_mock.call_count == 2
|
||||
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
from datetime import datetime, timedelta
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
from requests import RequestException
|
||||
|
||||
from freqtrade.enums import ExitType, RPCMessageType
|
||||
@ -337,34 +336,18 @@ def test_exception_send_msg(default_conf, mocker, caplog):
|
||||
caplog)
|
||||
|
||||
default_conf["webhook"] = get_webhook_dict()
|
||||
default_conf["webhook"]["webhookentry"]["value1"] = "{DEADBEEF:8f}"
|
||||
default_conf["webhook"]["strategy_msg"] = {"value1": "{DEADBEEF:8f}"}
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
|
||||
webhook = Webhook(RPC(get_patched_freqtradebot(mocker, default_conf)), default_conf)
|
||||
msg = {
|
||||
'type': RPCMessageType.ENTRY,
|
||||
'exchange': 'Binance',
|
||||
'pair': 'ETH/BTC',
|
||||
'limit': 0.005,
|
||||
'order_type': 'limit',
|
||||
'stake_amount': 0.8,
|
||||
'stake_amount_fiat': 500,
|
||||
'stake_currency': 'BTC',
|
||||
'fiat_currency': 'EUR'
|
||||
'type': RPCMessageType.STRATEGY_MSG,
|
||||
'msg': 'hello world',
|
||||
}
|
||||
webhook.send_msg(msg)
|
||||
assert log_has("Problem calling Webhook. Please check your webhook configuration. "
|
||||
"Exception: 'DEADBEEF'", caplog)
|
||||
|
||||
msg_mock = MagicMock()
|
||||
mocker.patch("freqtrade.rpc.webhook.Webhook._send_msg", msg_mock)
|
||||
msg = {
|
||||
'type': 'DEADBEEF',
|
||||
'status': 'whatever'
|
||||
}
|
||||
with pytest.raises(NotImplementedError):
|
||||
webhook.send_msg(msg)
|
||||
|
||||
# Test no failure for not implemented but known messagetypes
|
||||
for e in RPCMessageType:
|
||||
msg = {
|
||||
|
Loading…
Reference in New Issue
Block a user