kopia lustrzana https://github.com/fabston/TradingView-Webhook-Bot
Beautified code
rodzic
e55d973f5b
commit
dca330cde5
|
@ -5,18 +5,18 @@ labels: bug
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Describe the bug:**
|
## Describe the bug
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
**Steps to reproduce:**
|
### Steps to reproduce
|
||||||
Steps to reproduce the behavior.
|
Steps to reproduce the behavior.
|
||||||
|
|
||||||
**Expected behavior:**
|
### Expected behavior
|
||||||
A clear and concise description of what you expected to happen.
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
**Environment:**
|
### Environment
|
||||||
- OS: [e.g. Arch Linux]
|
- OS: [e.g. Arch Linux]
|
||||||
- Other details that you think may affect.
|
- Other details that you think may affect.
|
||||||
|
|
||||||
**Additional context:**
|
### Additional context
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
|
|
|
@ -5,14 +5,11 @@ labels: enhancement
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe:**
|
## Summary
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
Brief explanation of the feature.
|
||||||
|
|
||||||
**Describe the solution you'd like:**
|
### Basic example
|
||||||
A clear and concise description of what you want to happen.
|
Include a basic example or links here.
|
||||||
|
|
||||||
**Describe alternatives you've considered:**
|
### Motivation
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
Why are we doing this? What use cases does it support? What is the expected outcome?
|
||||||
|
|
||||||
**Additional context:**
|
|
||||||
Add any other context about the feature request here.
|
|
||||||
|
|
|
@ -10,13 +10,13 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v1
|
- uses: actions/stale@v3
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
stale-issue-message: 'It looks like this has been idle a while, so I am marking it as stale. Remove the label or comment if this issue should remain open.'
|
stale-issue-message: 'It looks like this has been idle a while, so I am marking it as stale. Remove the label or comment if this issue should remain open.'
|
||||||
stale-pr-message: 'It looks like this PR has been idle a while, so I am marking it as stale. Remove the label or comment if this is still being worked on.'
|
stale-pr-message: 'It looks like this PR has been idle a while, so I am marking it as stale. Remove the label or comment if this is still being worked on.'
|
||||||
stale-issue-label: 'no-activity'
|
stale-issue-label: 'no-activity'
|
||||||
stale-pr-label: 'no-activity'
|
stale-pr-label: 'no-activity'
|
||||||
exempt-pr-labels: 'help wanted'
|
exempt-pr-labels: 'help wanted,enhancement'
|
||||||
days-before-stale: 30
|
days-before-stale: 30
|
||||||
days-before-close: 5
|
days-before-close: 5
|
|
@ -45,7 +45,7 @@ Find out more at [WebhookAlerts.com](https://webhookalerts.com). Got a question?
|
||||||
- Dynamically send alerts to different Telegram and/or Discord channels
|
- Dynamically send alerts to different Telegram and/or Discord channels
|
||||||
- TradingView `{{close}}`, `{{exchange}}` etc. variables support. Read more [here](https://www.tradingview.com/blog/en/introducing-variables-in-alerts-14880/)
|
- TradingView `{{close}}`, `{{exchange}}` etc. variables support. Read more [here](https://www.tradingview.com/blog/en/introducing-variables-in-alerts-14880/)
|
||||||
|
|
||||||
> 💡 Got a feature idea? Open an [issue](https://github.com/fabston/TradingView-Webhook-Bot/issues/new?assignees=&labels=&template=feature-request---.md) and I might implement it.
|
> 💡 Got a feature idea? Open an [issue](https://github.com/fabston/TradingView-Webhook-Bot/issues/new?assignees=&labels=enhancement&template=feature-request---.md) and I might implement it.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
> ⚠️ Best to run the bot on a VPS. I can recommend <a href="https://fabston.dev/hetzner" title="Get €20 in cloud credits">Hetzner</a>'s CX11 VPS for 2.89€/month.
|
> ⚠️ Best to run the bot on a VPS. I can recommend <a href="https://fabston.dev/hetzner" title="Get €20 in cloud credits">Hetzner</a>'s CX11 VPS for 2.89€/month.
|
||||||
|
|
BIN
assets/bmac.png
BIN
assets/bmac.png
Plik binarny nie jest wyświetlany.
Przed Szerokość: | Wysokość: | Rozmiar: 262 KiB Po Szerokość: | Wysokość: | Rozmiar: 12 KiB |
30
config.py
30
config.py
|
@ -9,35 +9,37 @@
|
||||||
# "key":"9T2q394M92", "telegram":"-1001298977502", "discord":"789842349670960670/BFeBBrCt-w2Z9RJ2wlH6TWUjM5bJuC29aJaJ5OQv9sE6zCKY_AlOxxFwRURkgEl852s3", "msg":"Long #{{ticker}} at `{{close}}`"
|
# "key":"9T2q394M92", "telegram":"-1001298977502", "discord":"789842349670960670/BFeBBrCt-w2Z9RJ2wlH6TWUjM5bJuC29aJaJ5OQv9sE6zCKY_AlOxxFwRURkgEl852s3", "msg":"Long #{{ticker}} at `{{close}}`"
|
||||||
# }
|
# }
|
||||||
|
|
||||||
sec_key = '' # Can be anything. Has to match with "key" in your TradingView alert message
|
sec_key = (
|
||||||
|
"" # Can be anything. Has to match with "key" in your TradingView alert message
|
||||||
|
)
|
||||||
|
|
||||||
# Telegram Settings
|
# Telegram Settings
|
||||||
send_telegram_alerts = False
|
send_telegram_alerts = False
|
||||||
tg_token = '' # Bot token. Get it from @Botfather
|
tg_token = "" # Bot token. Get it from @Botfather
|
||||||
channel = 0 # Channel ID (ex. -1001487568087)
|
channel = 0 # Channel ID (ex. -1001487568087)
|
||||||
|
|
||||||
# Discord Settings
|
# Discord Settings
|
||||||
send_discord_alerts = False
|
send_discord_alerts = False
|
||||||
discord_webhook = '' # Discord Webhook URL (https://support.discordapp.com/hc/de/articles/228383668-Webhooks-verwenden)
|
discord_webhook = "" # Discord Webhook URL (https://support.discordapp.com/hc/de/articles/228383668-Webhooks-verwenden)
|
||||||
|
|
||||||
# Slack Settings
|
# Slack Settings
|
||||||
send_slack_alerts = False
|
send_slack_alerts = False
|
||||||
slack_webhook = '' # Slack Webhook URL (https://api.slack.com/messaging/webhooks)
|
slack_webhook = "" # Slack Webhook URL (https://api.slack.com/messaging/webhooks)
|
||||||
|
|
||||||
# Twitter Settings
|
# Twitter Settings
|
||||||
send_twitter_alerts = False
|
send_twitter_alerts = False
|
||||||
tw_ckey = ''
|
tw_ckey = ""
|
||||||
tw_csecret = ''
|
tw_csecret = ""
|
||||||
tw_atoken = ''
|
tw_atoken = ""
|
||||||
tw_asecret = ''
|
tw_asecret = ""
|
||||||
|
|
||||||
# Email Settings
|
# Email Settings
|
||||||
send_email_alerts = False
|
send_email_alerts = False
|
||||||
email_sender = '' # Your email address
|
email_sender = "" # Your email address
|
||||||
email_receivers = ['', ''] # Receivers, can be multiple
|
email_receivers = ["", ""] # Receivers, can be multiple
|
||||||
email_subject = 'Trade Alert!'
|
email_subject = "Trade Alert!"
|
||||||
|
|
||||||
email_port = 465 # SMTP SSL Port (ex. 465)
|
email_port = 465 # SMTP SSL Port (ex. 465)
|
||||||
email_host = '' # SMTP host (ex. smtp.gmail.com)
|
email_host = "" # SMTP host (ex. smtp.gmail.com)
|
||||||
email_user = '' # SMTP Login credentials
|
email_user = "" # SMTP Login credentials
|
||||||
email_password = '' # SMTP Login credentials
|
email_password = "" # SMTP Login credentials
|
||||||
|
|
93
handler.py
93
handler.py
|
@ -4,72 +4,97 @@
|
||||||
# File Name : handler.py #
|
# File Name : handler.py #
|
||||||
# ----------------------------------------------- #
|
# ----------------------------------------------- #
|
||||||
|
|
||||||
import config
|
import smtplib
|
||||||
from telegram import Bot
|
import ssl
|
||||||
from discord_webhook import DiscordWebhook, DiscordEmbed
|
|
||||||
from slack_webhook import Slack
|
|
||||||
import tweepy
|
|
||||||
import smtplib, ssl
|
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
|
|
||||||
|
import tweepy
|
||||||
|
from discord_webhook import DiscordEmbed, DiscordWebhook
|
||||||
|
from slack_webhook import Slack
|
||||||
|
from telegram import Bot
|
||||||
|
|
||||||
|
import config
|
||||||
|
|
||||||
|
|
||||||
def send_alert(data):
|
def send_alert(data):
|
||||||
if config.send_telegram_alerts:
|
if config.send_telegram_alerts:
|
||||||
tg_bot = Bot(token=config.tg_token)
|
tg_bot = Bot(token=config.tg_token)
|
||||||
try:
|
try:
|
||||||
tg_bot.sendMessage(data['telegram'],
|
tg_bot.sendMessage(
|
||||||
data['msg'].encode('latin-1', 'backslashreplace').decode('unicode_escape'),
|
data["telegram"],
|
||||||
parse_mode='MARKDOWN')
|
data["msg"]
|
||||||
|
.encode("latin-1", "backslashreplace")
|
||||||
|
.decode("unicode_escape"),
|
||||||
|
parse_mode="MARKDOWN",
|
||||||
|
)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
tg_bot.sendMessage(config.channel,
|
tg_bot.sendMessage(
|
||||||
data['msg'].encode('latin-1', 'backslashreplace').decode('unicode_escape'),
|
config.channel,
|
||||||
parse_mode='MARKDOWN')
|
data["msg"]
|
||||||
|
.encode("latin-1", "backslashreplace")
|
||||||
|
.decode("unicode_escape"),
|
||||||
|
parse_mode="MARKDOWN",
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('[X] Telegram Error:\n>', e)
|
print("[X] Telegram Error:\n>", e)
|
||||||
|
|
||||||
if config.send_discord_alerts:
|
if config.send_discord_alerts:
|
||||||
try:
|
try:
|
||||||
webhook = DiscordWebhook(url="https://discord.com/api/webhooks/" + data['discord'])
|
webhook = DiscordWebhook(
|
||||||
embed = DiscordEmbed(title=data['msg'])
|
url="https://discord.com/api/webhooks/" + data["discord"]
|
||||||
|
)
|
||||||
|
embed = DiscordEmbed(title=data["msg"])
|
||||||
webhook.add_embed(embed)
|
webhook.add_embed(embed)
|
||||||
response = webhook.execute()
|
webhook.execute()
|
||||||
except KeyError:
|
except KeyError:
|
||||||
webhook = DiscordWebhook(url="https://discord.com/api/webhooks/" + config.discord_webhook)
|
webhook = DiscordWebhook(
|
||||||
embed = DiscordEmbed(title=data['msg'])
|
url="https://discord.com/api/webhooks/" + config.discord_webhook
|
||||||
|
)
|
||||||
|
embed = DiscordEmbed(title=data["msg"])
|
||||||
webhook.add_embed(embed)
|
webhook.add_embed(embed)
|
||||||
response = webhook.execute()
|
webhook.execute()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('[X] Discord Error:\n>', e)
|
print("[X] Discord Error:\n>", e)
|
||||||
|
|
||||||
if config.send_slack_alerts:
|
if config.send_slack_alerts:
|
||||||
try:
|
try:
|
||||||
slack = Slack(url='https://hooks.slack.com/services/' + data['slack'])
|
slack = Slack(url="https://hooks.slack.com/services/" + data["slack"])
|
||||||
slack.post(text=data['msg'])
|
slack.post(text=data["msg"])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
slack = Slack(url='https://hooks.slack.com/services/' + config.slack_webhook)
|
slack = Slack(
|
||||||
slack.post(text=data['msg'])
|
url="https://hooks.slack.com/services/" + config.slack_webhook
|
||||||
|
)
|
||||||
|
slack.post(text=data["msg"])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('[X] Slack Error:\n>', e)
|
print("[X] Slack Error:\n>", e)
|
||||||
|
|
||||||
if config.send_twitter_alerts:
|
if config.send_twitter_alerts:
|
||||||
tw_auth = tweepy.OAuthHandler(config.tw_ckey, config.tw_csecret)
|
tw_auth = tweepy.OAuthHandler(config.tw_ckey, config.tw_csecret)
|
||||||
tw_auth.set_access_token(config.tw_atoken, config.tw_asecret)
|
tw_auth.set_access_token(config.tw_atoken, config.tw_asecret)
|
||||||
tw_api = tweepy.API(tw_auth)
|
tw_api = tweepy.API(tw_auth)
|
||||||
try:
|
try:
|
||||||
tw_api.update_status(status=data['msg'].replace('*', '').replace('_', '').replace('`', ''))
|
tw_api.update_status(
|
||||||
|
status=data["msg"].replace("*", "").replace("_", "").replace("`", "")
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('[X] Twitter Error:\n>', e)
|
print("[X] Twitter Error:\n>", e)
|
||||||
|
|
||||||
if config.send_email_alerts:
|
if config.send_email_alerts:
|
||||||
try:
|
try:
|
||||||
email_msg = MIMEText(data['msg'].replace('*', '').replace('_', '').replace('`', ''))
|
email_msg = MIMEText(
|
||||||
email_msg['Subject'] = config.email_subject
|
data["msg"].replace("*", "").replace("_", "").replace("`", "")
|
||||||
email_msg['From'] = config.email_sender
|
)
|
||||||
email_msg['To'] = config.email_sender
|
email_msg["Subject"] = config.email_subject
|
||||||
|
email_msg["From"] = config.email_sender
|
||||||
|
email_msg["To"] = config.email_sender
|
||||||
context = ssl.create_default_context()
|
context = ssl.create_default_context()
|
||||||
with smtplib.SMTP_SSL(config.email_host, config.email_port, context=context) as server:
|
with smtplib.SMTP_SSL(
|
||||||
|
config.email_host, config.email_port, context=context
|
||||||
|
) as server:
|
||||||
server.login(config.email_user, config.email_password)
|
server.login(config.email_user, config.email_password)
|
||||||
server.sendmail(config.email_sender, config.email_receivers, email_msg.as_string())
|
server.sendmail(
|
||||||
|
config.email_sender, config.email_receivers, email_msg.as_string()
|
||||||
|
)
|
||||||
server.quit()
|
server.quit()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('[X] Email Error:\n>', e)
|
print("[X] Email Error:\n>", e)
|
||||||
|
|
30
main.py
30
main.py
|
@ -4,10 +4,12 @@
|
||||||
# File Name : main.py #
|
# File Name : main.py #
|
||||||
# ----------------------------------------------- #
|
# ----------------------------------------------- #
|
||||||
|
|
||||||
import config
|
|
||||||
import time
|
|
||||||
from flask import Flask, request
|
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
|
from flask import Flask, request
|
||||||
|
|
||||||
|
import config
|
||||||
from handler import *
|
from handler import *
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
@ -18,27 +20,27 @@ def get_timestamp():
|
||||||
return timestamp
|
return timestamp
|
||||||
|
|
||||||
|
|
||||||
@app.route('/webhook', methods=['POST'])
|
@app.route("/webhook", methods=["POST"])
|
||||||
def webhook():
|
def webhook():
|
||||||
try:
|
try:
|
||||||
if request.method == 'POST':
|
if request.method == "POST":
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
key = data['key']
|
key = data["key"]
|
||||||
if key == config.sec_key:
|
if key == config.sec_key:
|
||||||
print(get_timestamp(), 'Alert Received & Sent!')
|
print(get_timestamp(), "Alert Received & Sent!")
|
||||||
send_alert(data)
|
send_alert(data)
|
||||||
return 'Sent alert', 200
|
return "Sent alert", 200
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print('[X]', get_timestamp(), 'Alert Received & Refused! (Wrong Key)')
|
print("[X]", get_timestamp(), "Alert Received & Refused! (Wrong Key)")
|
||||||
return 'Refused alert', 400
|
return "Refused alert", 400
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('[X]', get_timestamp(), 'Error:\n>', e)
|
print("[X]", get_timestamp(), "Error:\n>", e)
|
||||||
return 'Error', 400
|
return "Error", 400
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
from waitress import serve
|
from waitress import serve
|
||||||
|
|
||||||
serve(app, host='0.0.0.0', port=80)
|
serve(app, host="0.0.0.0", port=80)
|
||||||
|
|
|
@ -1,6 +1,36 @@
|
||||||
flask
|
appdirs==1.4.4
|
||||||
waitress
|
APScheduler==3.6.3
|
||||||
python-telegram-bot
|
black==21.5b1
|
||||||
discord-webhook
|
cachetools==4.2.2
|
||||||
slack-webhook
|
certifi==2021.5.30
|
||||||
tweepy
|
chardet==4.0.0
|
||||||
|
click==8.0.1
|
||||||
|
discord-webhook==0.14.0
|
||||||
|
flake8==3.9.2
|
||||||
|
Flask==2.0.1
|
||||||
|
idna==2.10
|
||||||
|
isort==5.8.0
|
||||||
|
itsdangerous==2.0.1
|
||||||
|
Jinja2==3.0.1
|
||||||
|
MarkupSafe==2.0.1
|
||||||
|
mccabe==0.6.1
|
||||||
|
mypy-extensions==0.4.3
|
||||||
|
oauthlib==3.1.1
|
||||||
|
pathspec==0.8.1
|
||||||
|
pycodestyle==2.7.0
|
||||||
|
pyflakes==2.3.1
|
||||||
|
PySocks==1.7.1
|
||||||
|
python-telegram-bot==13.6
|
||||||
|
pytz==2021.1
|
||||||
|
regex==2021.4.4
|
||||||
|
requests==2.25.1
|
||||||
|
requests-oauthlib==1.3.0
|
||||||
|
six==1.16.0
|
||||||
|
slack-webhook==1.0.6
|
||||||
|
toml==0.10.2
|
||||||
|
tornado==6.1
|
||||||
|
tweepy==3.10.0
|
||||||
|
tzlocal==2.1
|
||||||
|
urllib3==1.26.5
|
||||||
|
waitress==2.0.0
|
||||||
|
Werkzeug==2.0.1
|
||||||
|
|
Ładowanie…
Reference in New Issue