stable/freqtrade/rpc/webhook.py

107 lines
4.2 KiB
Python
Raw Normal View History

2018-07-05 19:32:53 +00:00
"""
This module manages webhook communication
"""
import logging
import time
2020-09-28 17:39:41 +00:00
from typing import Any, Dict
2018-07-05 19:32:53 +00:00
2020-09-28 17:39:41 +00:00
from requests import RequestException, post
2018-07-05 19:32:53 +00:00
2021-06-09 17:51:44 +00:00
from freqtrade.enums import RPCMessageType
from freqtrade.rpc import RPC, RPCHandler
2018-07-05 19:32:53 +00:00
logger = logging.getLogger(__name__)
logger.debug('Included module rpc.webhook ...')
class Webhook(RPCHandler):
2018-07-05 19:32:53 +00:00
""" This class handles all webhook communication """
def __init__(self, rpc: RPC, config: Dict[str, Any]) -> None:
2018-07-05 19:32:53 +00:00
"""
Init the Webhook class, and init the super class RPCHandler
:param rpc: instance of RPC Helper class
:param config: Configuration object
2018-07-05 19:32:53 +00:00
:return: None
"""
super().__init__(rpc, config)
2018-07-05 19:32:53 +00:00
2018-07-14 11:29:34 +00:00
self._url = self._config['webhook']['url']
2021-02-26 14:46:23 +00:00
self._format = self._config['webhook'].get('format', 'form')
self._retries = self._config['webhook'].get('retries', 0)
self._retry_delay = self._config['webhook'].get('retry_delay', 0.1)
2018-07-05 19:32:53 +00:00
def cleanup(self) -> None:
"""
Cleanup pending module resources.
This will do nothing for webhooks, they will simply not be called anymore
"""
pass
def send_msg(self, msg: Dict[str, Any]) -> None:
""" Send a message to telegram channel """
try:
2022-04-04 17:05:36 +00:00
whconfig = self._config['webhook']
# DEPRECATED: Sell terminology
2021-12-29 13:24:12 +00:00
if msg['type'] in [RPCMessageType.BUY, RPCMessageType.SHORT]:
2022-04-04 17:05:36 +00:00
valuedict = whconfig.get('webhookbuy', None)
2021-12-29 13:24:12 +00:00
elif msg['type'] in [RPCMessageType.BUY_CANCEL, RPCMessageType.SHORT_CANCEL]:
2022-04-04 17:05:36 +00:00
valuedict = whconfig.get('webhookbuycancel', None)
2021-12-29 13:24:12 +00:00
elif msg['type'] in [RPCMessageType.BUY_FILL, RPCMessageType.SHORT_FILL]:
2022-04-04 17:05:36 +00:00
valuedict = whconfig.get('webhookbuyfill', None)
2022-04-04 17:10:44 +00:00
elif msg['type'] == RPCMessageType.EXIT:
2022-04-04 17:05:36 +00:00
valuedict = whconfig.get('webhookexit', whconfig.get('webhooksell', None))
2022-04-04 17:08:31 +00:00
elif msg['type'] == RPCMessageType.EXIT_FILL:
2022-04-04 17:05:36 +00:00
valuedict = whconfig.get('webhookexitfill', whconfig.get('webhookexitfill', None))
2022-04-04 17:07:20 +00:00
elif msg['type'] == RPCMessageType.EXIT_CANCEL:
2022-04-04 17:05:36 +00:00
valuedict = whconfig.get('webhookexitcancel',
whconfig.get('webhooksellcancel', None))
2021-04-20 04:41:58 +00:00
elif msg['type'] in (RPCMessageType.STATUS,
RPCMessageType.STARTUP,
RPCMessageType.WARNING):
2022-04-04 17:05:36 +00:00
valuedict = whconfig.get('webhookstatus', None)
2018-07-05 19:32:53 +00:00
else:
raise NotImplementedError('Unknown message type: {}'.format(msg['type']))
if not valuedict:
2020-09-19 18:04:12 +00:00
logger.info("Message type '%s' not configured for webhooks", msg['type'])
2018-07-05 19:32:53 +00:00
return
2018-07-12 19:54:31 +00:00
payload = {key: value.format(**msg) for (key, value) in valuedict.items()}
2018-07-05 19:32:53 +00:00
self._send_msg(payload)
except KeyError as exc:
logger.exception("Problem calling Webhook. Please check your webhook configuration. "
"Exception: %s", exc)
def _send_msg(self, payload: dict) -> None:
2018-07-14 11:29:34 +00:00
"""do the actual call to the webhook"""
2018-07-05 19:32:53 +00:00
success = False
attempts = 0
while not success and attempts <= self._retries:
if attempts:
2021-11-29 18:54:54 +00:00
if self._retry_delay:
time.sleep(self._retry_delay)
logger.info("Retrying webhook...")
attempts += 1
try:
if self._format == 'form':
response = post(self._url, data=payload)
elif self._format == 'json':
response = post(self._url, json=payload)
elif self._format == 'raw':
2021-11-29 18:54:54 +00:00
response = post(self._url, data=payload['data'],
headers={'Content-Type': 'text/plain'})
else:
raise NotImplementedError('Unknown format: {}'.format(self._format))
2021-11-29 18:54:54 +00:00
2021-11-28 23:30:41 +00:00
# Throw a RequestException if the post was not successful
response.raise_for_status()
success = True
except RequestException as exc:
logger.warning("Could not call webhook url. Exception: %s", exc)