diff --git a/Dockerfile b/Dockerfile index 4c95c94..cee81ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ -FROM python:3.6-slim +FROM python:3.7-slim COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt COPY . . -CMD [ "python", "./stockBot.py" ] \ No newline at end of file +CMD [ "python", "./bot.py" ] diff --git a/bot.py b/bot.py index 90fa66e..277b56c 100644 --- a/bot.py +++ b/bot.py @@ -1,47 +1,35 @@ -# Work with Python 3.6 import discord -import re -import urllib.request -import json -import tickerInfo as ti - -TOKEN = "Discord Token" -TICKER_REGEX = "[$]([a-zA-Z]{1,4})" +from functions import * client = discord.Client() @client.event -async def on_message(message): - """ - This runs every time a message is detected. - """ - - # Check that message wasnt the bot. - if message.author == client.user: - return - - tickers = re.findall(TICKER_REGEX, message.content) - if tickers is not []: - print(tickers) - await client.send_typing(message.channel) - await client.send_message(message.channel, ti.tickerMessage(tickers)) - return - - # print(message.author.id) - - # if message.content.startswith("!hello"): - # print(dir(message.author)) - # msg = "Hello {0.author.mention}".format(message) - # await client.send_message(message.channel, msg) +async def on_ready(): + print("We have logged in as {0.user}".format(client)) @client.event -async def on_ready(): - print("Logged in as") - print(client.user.name) - print(client.user.id) - print("------") +async def on_message(message): + if message.author == client.user: + return + + # Check for dividend command + if message.content.startswith("/dividend"): + replies = tickerDividend(getTickers(message.content)) + if replies: + for tick, reply in replies.items(): + await message.channel.send(reply) + else: + await message.channel.send("No tickers found.") + # If no commands, check for any tickers. + else: + replies = tickerDataReply(getTickers(message.content)) + if replies: + for symbol, reply in replies.items(): + await message.channel.send(reply) + else: + return -client.run(TOKEN) +client.run(os.environ["DISCORD"]) diff --git a/functions.py b/functions.py index a3d13ca..7df7498 100644 --- a/functions.py +++ b/functions.py @@ -1,105 +1,80 @@ -import urllib.request import json -from datetime import datetime +import os +import re import time +import urllib.request +from datetime import datetime + +IEX_TOKEN = os.environ["IEX"] -def tickerQuote(tickers): - """Gathers information from IEX api on stock""" - stockData = {} - IEXURL = ( - "https://api.iextrading.com/1.0/stock/market/batch?symbols=" - + ",".join(tickers) - + "&types=quote" - ) - print("Gathering Quote from " + IEXURL) - with urllib.request.urlopen(IEXURL) as url: - IEXData = json.loads(url.read().decode()) +def getTickers(text: str): + """ + Takes a blob of text and returns any stock tickers found. + """ + + TICKER_REGEX = "[$]([a-zA-Z]{1,4})" + + return list(set(re.findall(TICKER_REGEX, text))) + + +def tickerDataReply(tickers: list): + """ + Takes a list of tickers and returns a list of strings with information about the ticker. + """ + tickerReplies = {} + for ticker in tickers: + IEXURL = ( + f"https://cloud.iexapis.com/stable/stock/{ticker}/quote?token={IEX_TOKEN}" + ) + try: + with urllib.request.urlopen(IEXURL) as url: + IEXData = json.loads(url.read().decode()) + + reply = f"The current stock price of {IEXData['companyName']} is $**{IEXData['latestPrice']}**" + + # Determine wording of change text + change = round(IEXData["changePercent"] * 100, 2) + if change > 0: + reply += f", the stock is currently **up {change}%**" + elif change < 0: + reply += f", the stock is currently **down {change}%**" + else: + reply += ", the stock hasn't shown any movement today." + except: + reply = f"The ticker: {ticker} was not found." + + tickerReplies[ticker] = reply + + return tickerReplies + + +def tickerDividend(tickers: list): + messages = {} for ticker in tickers: - ticker = ticker.upper() + IEXurl = f"https://cloud.iexapis.com/stable/stock/{ticker}/dividends/next?token={IEX_TOKEN}" + with urllib.request.urlopen(IEXurl) as url: + data = json.loads(url.read().decode()) + if data: + # Pattern IEX uses for dividend date. + pattern = "%Y-%m-%d" - # Makes sure ticker exists before populating a dictionary - if ticker in IEXData: - stockData[ticker] = 1 - stockData[ticker + "Name"] = IEXData[ticker]["quote"]["companyName"] - stockData[ticker + "Price"] = IEXData[ticker]["quote"]["latestPrice"] - stockData[ticker + "Change"] = round( - (IEXData[ticker]["quote"]["changePercent"] * 100), 2 - ) - stockData[ticker + "Image"] = stockLogo(ticker) - print(ticker + " Quote Gathered") + # Convert divDate to seconds, and subtract it from current time. + dividendSeconds = datetime.strptime( + data["paymentDate"], pattern + ).timestamp() + difference = dividendSeconds - int(time.time()) + + # Calculate (d)ays, (h)ours, (m)inutes, and (s)econds + d, h = divmod(difference, 86400) + h, m = divmod(h, 3600) + m, s = divmod(m, 60) + + messages[ + ticker + ] = f"{data['description']}\n\nThe dividend is in: {d:.0f} Days {h:.0f} Hours {m:.0f} Minutes {s:.0f} Seconds." else: - stockData[ticker] = 0 - return stockData + messages[ticker] = f"{ticker} either doesn't exist or pays no dividend." - -def stockNews(ticker): - """Makes a bunch of strings that are links to news websites for an input ticker""" - print("Gather News on " + ticker) - - newsLink = f"https://api.iextrading.com/1.0/stock/{ticker}/news/last/5" - print(newsLink) - with urllib.request.urlopen(newsLink) as url: - data = json.loads(url.read().decode()) - - news = {"link": [], "title": []} - for i in range(len(data)): - news["link"].append(data[i]["url"]) - news["title"].append(data[i]["headline"]) - return news - - -def stockLogo(ticker): - """returns a png of an input ticker""" - logoURL = f"https://g.foolcdn.com/art/companylogos/mark/{ticker}.png" - return logoURL - - -def stockInfo(ticker): - infoURL = f"https://api.iextrading.com/1.0/stock/{ticker}/stats" - - with urllib.request.urlopen(infoURL) as url: - data = json.loads(url.read().decode()) - - info = {} - - info["companyName"] = data["companyName"] - info["marketCap"] = data["marketcap"] - info["yearHigh"] = data["week52high"] - info["yearLow"] = data["week52low"] - info["divRate"] = data["dividendRate"] - info["divYield"] = data["dividendYield"] - info["divDate"] = data["exDividendDate"] - - return info - - -def stockDividend(ticker): - data = stockInfo(ticker) - print(data["divDate"]) - if data["divDate"] == 0: - return "{} has no dividend.".format(data["companyName"]) - - line1 = "{} current dividend yield is: {:.3f}%, or ${:.3f} per share.".format( - data["companyName"], data["divRate"], data["divYield"] - ) - - divDate = data["divDate"] - - # Pattern IEX uses for dividend date. - pattern = "%Y-%m-%d %H:%M:%S.%f" - - # Convert divDate to seconds, and subtract it from current time. - divSeconds = datetime.strptime(divDate, pattern).timestamp() - difference = divSeconds - int(time.time()) - - # Calculate (d)ays, (h)ours, (m)inutes, and (s)econds - d, h = divmod(difference, 86400) - h, m = divmod(h, 3600) - m, s = divmod(m, 60) - - countdownMessage = f"\n\nThe dividend is in: {d:.0f} Days {h:.0f} Hours {m:.0f} Minutes {s:.0f} Seconds." - - message = line1 + countdownMessage - return message + return messages diff --git a/requirements.txt b/requirements.txt index 0fe1883..359a951 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1 @@ -discord.py==0.16.12 -discord==0.0.2 +discord.py==1.2.1 \ No newline at end of file