mirror of
https://gitlab.com/simple-stock-bots/simple-discord-stock-bot.git
synced 2025-06-16 15:17:29 +00:00
updated to meet telegram features
This commit is contained in:
parent
e658bc3af6
commit
ca33627af0
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,3 @@
|
|||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
__pycache__/functions.cpython-38.pyc
|
__pycache__
|
||||||
.devcontainer
|
.devcontainer
|
@ -6,7 +6,7 @@ import re
|
|||||||
import requests as r
|
import requests as r
|
||||||
|
|
||||||
|
|
||||||
class T_info:
|
class D_info:
|
||||||
license = re.sub(
|
license = re.sub(
|
||||||
r"\b\n",
|
r"\b\n",
|
||||||
" ",
|
" ",
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
FROM python:3.8-buster
|
FROM python:3.9-buster
|
||||||
|
|
||||||
COPY requirements.txt ./
|
COPY requirements.txt ./
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
# COPY . .
|
COPY . .
|
||||||
|
|
||||||
# CMD [ "python", "./bot.py" ]
|
CMD [ "python", "./bot.py" ]
|
||||||
|
165
bot.py
165
bot.py
@ -1,22 +1,29 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
import html
|
||||||
import io
|
import io
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import traceback
|
||||||
|
from logging import critical, debug, error, info, warning
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
import mplfinance as mpf
|
import mplfinance as mpf
|
||||||
|
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
|
|
||||||
from functions import Symbol
|
from symbol_router import Router
|
||||||
|
from D_info import D_info
|
||||||
|
|
||||||
DISCORD_TOKEN = "NjAxNjYwNzM1ODQzNDY3Mjg0.XTFiOQ.DMEKIug2mhX1WGGVSD1bYuYXVro"
|
|
||||||
|
|
||||||
try:
|
DISCORD_TOKEN = os.environ["DISCORD"]
|
||||||
IEX_TOKEN = os.environ["IEX"]
|
|
||||||
except KeyError:
|
s = Router()
|
||||||
IEX_TOKEN = ""
|
d = D_info()
|
||||||
print("Starting without an IEX Token will not allow you to get market data!")
|
|
||||||
s = Symbol(IEX_TOKEN)
|
|
||||||
|
|
||||||
|
|
||||||
client = discord.Client()
|
client = discord.Client()
|
||||||
@ -24,7 +31,7 @@ client = discord.Client()
|
|||||||
|
|
||||||
bot = commands.Bot(
|
bot = commands.Bot(
|
||||||
command_prefix="/",
|
command_prefix="/",
|
||||||
description=s.help_text,
|
description=d.help_text,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -38,16 +45,12 @@ async def on_ready():
|
|||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def status(ctx):
|
async def status(ctx: commands):
|
||||||
"""Debug command for diagnosing if the bot is experiencing any issues."""
|
"""Debug command for diagnosing if the bot is experiencing any issues."""
|
||||||
message = ""
|
message = ""
|
||||||
try:
|
try:
|
||||||
message = "Contact MisterBiggs#0465 if you need help.\n"
|
message = "Contact MisterBiggs#0465 if you need help.\n"
|
||||||
# IEX Status
|
message += s.status("") + "\n"
|
||||||
message += s.iex_status() + "\n"
|
|
||||||
|
|
||||||
# Message Status
|
|
||||||
message += s.message_status()
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
message += (
|
message += (
|
||||||
f"*\n\nERROR ENCOUNTERED:*\n{ex}\n\n"
|
f"*\n\nERROR ENCOUNTERED:*\n{ex}\n\n"
|
||||||
@ -57,59 +60,59 @@ async def status(ctx):
|
|||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def license(ctx):
|
async def license(ctx: commands):
|
||||||
"""Returns the bots license agreement."""
|
"""Returns the bots license agreement."""
|
||||||
await ctx.send(s.license)
|
await ctx.send(d.license)
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def donate(ctx):
|
async def donate(ctx: commands):
|
||||||
"""Details on how to support the development and hosting of the bot."""
|
"""Details on how to support the development and hosting of the bot."""
|
||||||
await ctx.send(s.donate_text)
|
await ctx.send(d.donate_text)
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def stat(ctx, *, sym: str):
|
async def stat(ctx: commands, *, sym: str):
|
||||||
"""Get statistics on a list of stock symbols."""
|
"""Get statistics on a list of stock symbols."""
|
||||||
symbols = s.find_symbols(sym)
|
symbols = s.find_symbols(sym)
|
||||||
|
|
||||||
if symbols:
|
if symbols:
|
||||||
for reply in s.stat_reply(symbols).items():
|
for reply in s.stat_reply(symbols):
|
||||||
await ctx.send(reply[1])
|
await ctx.send(reply)
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def dividend(ctx, *, sym: str):
|
async def dividend(ctx: commands, *, sym: str):
|
||||||
"""Get dividend information on a stock symbol."""
|
"""Get dividend information on a stock symbol."""
|
||||||
symbols = s.find_symbols(sym)
|
symbols = s.find_symbols(sym)
|
||||||
|
|
||||||
if symbols:
|
if symbols:
|
||||||
for symbol in symbols:
|
for reply in s.dividend_reply(symbols):
|
||||||
await ctx.send(s.dividend_reply(symbol))
|
await ctx.send(reply)
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def news(ctx, *, sym: str):
|
async def news(ctx: commands, *, sym: str):
|
||||||
"""Get recent english news on a stock symbol."""
|
"""Get recent english news on a stock symbol."""
|
||||||
symbols = s.find_symbols(sym)
|
symbols = s.find_symbols(sym)
|
||||||
|
|
||||||
if symbols:
|
if symbols:
|
||||||
for reply in s.news_reply(symbols).items():
|
for reply in s.news_reply(symbols):
|
||||||
await ctx.send(reply[1])
|
await ctx.send(reply)
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def info(ctx, *, sym: str):
|
async def info(ctx: commands, *, sym: str):
|
||||||
"""Get information of a stock ticker."""
|
"""Get information of a stock ticker."""
|
||||||
symbols = s.find_symbols(sym)
|
symbols = s.find_symbols(sym)
|
||||||
|
|
||||||
if symbols:
|
if symbols:
|
||||||
for reply in s.info_reply(symbols).items():
|
for reply in s.info_reply(symbols):
|
||||||
await ctx.send(reply[1])
|
await ctx.send(reply[0:1900])
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def search(ctx, *, query: str):
|
async def search(ctx: commands, *, query: str):
|
||||||
"""Search for a stock symbol using either symbol of company name."""
|
"""Search for a stock symbol using either symbol of company name."""
|
||||||
results = s.search_symbols(query)
|
results = s.search_symbols(query)
|
||||||
if results:
|
if results:
|
||||||
@ -120,90 +123,110 @@ async def search(ctx, *, query: str):
|
|||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def crypto(ctx, symbol: str):
|
async def crypto(ctx: commands, symbol: str):
|
||||||
"""Get the price of a cryptocurrency using in USD."""
|
"""Get the price of a cryptocurrency using in USD."""
|
||||||
reply = s.crypto_reply(symbol)
|
await ctx.send(
|
||||||
if reply:
|
"Crypto now has native support. Any crypto can be called using two dollar signs: `$$eth` `$$btc` `$$doge`"
|
||||||
await ctx.send(reply)
|
)
|
||||||
else:
|
|
||||||
await ctx.send("Crypto Symbol could not be found.")
|
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def intra(ctx, sym: str):
|
async def intra(ctx: commands, sym: str):
|
||||||
"""Get a chart for the stocks movement since market open."""
|
"""Get a chart for the stocks movement since market open."""
|
||||||
with ctx.channel.typing():
|
symbols = s.find_symbols(sym)
|
||||||
|
|
||||||
symbol = s.find_symbols(sym)[0]
|
if len(symbols):
|
||||||
|
symbol = symbols[0]
|
||||||
|
else:
|
||||||
|
await ctx.send("No symbols or coins found.")
|
||||||
|
return
|
||||||
|
|
||||||
df = s.intra_reply(symbol)
|
df = s.intra_reply(symbol)
|
||||||
if df.empty:
|
if df.empty:
|
||||||
await ctx.send("Invalid symbol please see `/help` for usage details.")
|
await ctx.send("Invalid symbol please see `/help` for usage details.")
|
||||||
return
|
return
|
||||||
|
with ctx.channel.typing():
|
||||||
|
|
||||||
buf = io.BytesIO()
|
buf = io.BytesIO()
|
||||||
mpf.plot(
|
mpf.plot(
|
||||||
df,
|
df,
|
||||||
type="renko",
|
type="renko",
|
||||||
title=f"\n${symbol.upper()}",
|
title=f"\n{symbol.name}",
|
||||||
volume=True,
|
volume="volume" in df.keys(),
|
||||||
style="yahoo",
|
style="yahoo",
|
||||||
mav=20,
|
|
||||||
savefig=dict(fname=buf, dpi=400, bbox_inches="tight"),
|
savefig=dict(fname=buf, dpi=400, bbox_inches="tight"),
|
||||||
)
|
)
|
||||||
|
|
||||||
buf.seek(0)
|
buf.seek(0)
|
||||||
|
|
||||||
caption = (
|
# Get price so theres no request lag after the image is sent
|
||||||
f"\nIntraday chart for ${symbol.upper()} from {df.first_valid_index().strftime('%I:%M')} to"
|
price_reply = s.price_reply([symbol])[0]
|
||||||
+ f" {df.last_valid_index().strftime('%I:%M')} ET on"
|
|
||||||
+ f" {datetime.date.today().strftime('%d, %b %Y')}"
|
|
||||||
)
|
|
||||||
|
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
content=caption,
|
|
||||||
file=discord.File(
|
file=discord.File(
|
||||||
buf,
|
buf,
|
||||||
filename=f"{symbol.upper()}:{datetime.date.today().strftime('%d%b%Y')}.png",
|
filename=f"{symbol.name}:intra{datetime.date.today().strftime('%S%M%d%b%Y')}.png",
|
||||||
),
|
),
|
||||||
|
content=f"\nIntraday chart for {symbol.name} from {df.first_valid_index().strftime('%d %b at %H:%M')} to"
|
||||||
|
+ f" {df.last_valid_index().strftime('%d %b at %H:%M')}",
|
||||||
)
|
)
|
||||||
await ctx.send(f"{s.price_reply([symbol])[symbol]}")
|
await ctx.send(price_reply)
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def chart(ctx, sym: str):
|
async def chart(ctx: commands, sym: str):
|
||||||
"""Get a chart for the stocks movement for the past month."""
|
"""returns a chart of the past month of data for a symbol"""
|
||||||
with ctx.channel.typing():
|
|
||||||
|
|
||||||
symbol = s.find_symbols(sym)[0]
|
symbols = s.find_symbols(sym)
|
||||||
|
|
||||||
df = s.intra_reply(symbol)
|
if len(symbols):
|
||||||
|
symbol = symbols[0]
|
||||||
|
else:
|
||||||
|
await ctx.send("No symbols or coins found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
df = s.chart_reply(symbol)
|
||||||
if df.empty:
|
if df.empty:
|
||||||
await ctx.send("Invalid symbol please see `/help` for usage details.")
|
await ctx.send("Invalid symbol please see `/help` for usage details.")
|
||||||
return
|
return
|
||||||
|
with ctx.channel.typing():
|
||||||
|
|
||||||
buf = io.BytesIO()
|
buf = io.BytesIO()
|
||||||
mpf.plot(
|
mpf.plot(
|
||||||
df,
|
df,
|
||||||
type="candle",
|
type="candle",
|
||||||
title=f"\n${symbol.upper()}",
|
title=f"\n{symbol.name}",
|
||||||
volume=True,
|
volume="volume" in df.keys(),
|
||||||
style="yahoo",
|
style="yahoo",
|
||||||
savefig=dict(fname=buf, dpi=400, bbox_inches="tight"),
|
savefig=dict(fname=buf, dpi=400, bbox_inches="tight"),
|
||||||
)
|
)
|
||||||
buf.seek(0)
|
buf.seek(0)
|
||||||
|
|
||||||
caption = (
|
# Get price so theres no request lag after the image is sent
|
||||||
f"\n1 Month chart for ${symbol.upper()} from {df.first_valid_index().strftime('%d, %b %Y')}"
|
price_reply = s.price_reply([symbol])[0]
|
||||||
+ f" to {df.last_valid_index().strftime('%d, %b %Y')}"
|
|
||||||
)
|
|
||||||
|
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
content=caption,
|
|
||||||
file=discord.File(
|
file=discord.File(
|
||||||
buf,
|
buf,
|
||||||
filename=f"{symbol.upper()}:{datetime.date.today().strftime('1M%d%b%Y')}.png",
|
filename=f"{symbol.name}:1M{datetime.date.today().strftime('%d%b%Y')}.png",
|
||||||
),
|
),
|
||||||
|
content=f"\n1 Month chart for {symbol.name} from {df.first_valid_index().strftime('%d, %b %Y')}"
|
||||||
|
+ f" to {df.last_valid_index().strftime('%d, %b %Y')}",
|
||||||
)
|
)
|
||||||
await ctx.send(f"{s.price_reply([symbol])[symbol]}")
|
await ctx.send(price_reply)
|
||||||
|
|
||||||
|
|
||||||
|
@bot.command()
|
||||||
|
async def cap(ctx: commands, sym: str):
|
||||||
|
symbols = s.find_symbols(sym)
|
||||||
|
if symbols:
|
||||||
|
with ctx.channel.typing():
|
||||||
|
for reply in s.cap_reply(symbols):
|
||||||
|
await ctx.send(reply)
|
||||||
|
|
||||||
|
|
||||||
|
@bot.command()
|
||||||
|
async def trending(ctx: commands):
|
||||||
|
with ctx.channel.typing():
|
||||||
|
await ctx.send(s.trending())
|
||||||
|
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
@ -211,7 +234,7 @@ async def on_message(message):
|
|||||||
|
|
||||||
if message.author.id == bot.user.id:
|
if message.author.id == bot.user.id:
|
||||||
return
|
return
|
||||||
|
if message.content:
|
||||||
if message.content[0] == "/":
|
if message.content[0] == "/":
|
||||||
await bot.process_commands(message)
|
await bot.process_commands(message)
|
||||||
return
|
return
|
||||||
@ -220,8 +243,8 @@ async def on_message(message):
|
|||||||
symbols = s.find_symbols(message.content)
|
symbols = s.find_symbols(message.content)
|
||||||
|
|
||||||
if symbols:
|
if symbols:
|
||||||
for reply in s.price_reply(symbols).items():
|
for reply in s.price_reply(symbols):
|
||||||
await message.channel.send(reply[1])
|
await message.channel.send(reply)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user