diff --git a/credentials.py b/credentials.py deleted file mode 100644 index e339fc2..0000000 --- a/credentials.py +++ /dev/null @@ -1,4 +0,0 @@ -secrets = { - 'TOKEN': "https://discordapp.com/developers/applications/ > BOTNAME > Bot > 'copy token'", - 'BRAVOS_API': 'https://bravos.co/a/data' -} diff --git a/stockBot.py b/stockBot.py index 02cf2a1..90fa66e 100644 --- a/stockBot.py +++ b/stockBot.py @@ -1,107 +1,47 @@ # Work with Python 3.6 -import json -from discord.ext import commands import discord import re import urllib.request -import credentials +import json +import tickerInfo as ti -# Make sure to update credentials.py with your secrets -TOKEN = credentials.secrets['TOKEN'] -BRAVOS_API = credentials.secrets['BRAVOS_API'] -BOT_PREFIX = ("?", "!") +TOKEN = "Discord Token" +TICKER_REGEX = "[$]([a-zA-Z]{1,4})" -client = commands.Bot(command_prefix=BOT_PREFIX) - - -@client.event # Make bot say when its ready -async def on_ready(): - print('Bot is Ready!!!') +client = discord.Client() @client.event async def on_message(message): + """ + This runs every time a message is detected. + """ - if message.author == client.user: # Prevent bot from reacting to its own messages + # Check that message wasnt the bot. + if message.author == client.user: return - # define information about the message - author = message.author - content = message.content.lower() - channel = message.channel + 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 - try: - # regex to find tickers in messages, looks for up to 4 word characters following a dollar sign and captures the 4 word characters - tickers = re.findall('[$](\w{1,4})', content) + # print(message.author.id) - # get ticker information from bravos api, turns tickers into comma separated list so that only one api call is needed per message - url = 'https://data.bravos.co/v1/quote?symbols=' + ",".join(tickers) + \ - '&apikey=' + BRAVOS_API + '&format=json' - - # load json data from url as an object - with urllib.request.urlopen(url) as url: - data = json.loads(url.read().decode()) - - for ticker in tickers: # iterate through the tickers and print relevant info one message at a time - try: # checks if data is a valid ticker, if it is not tells the user - - # Get Stock ticker name from Data Object - nameTicker = data[ticker.upper()]['name'] - # Get Stock Ticker price from Object - priceTicker = data[ticker.upper()]['price'] - - # Checks if !news is called, and prints news embed if it is - if content.startswith('!news'): - - embed = displayembed(ticker, nameTicker, priceTicker) - await client.send_message(channel, embed=embed) - else: # If news embed isnt called, print normal stock price - await client.send_message(channel, 'The current stock price of ' + nameTicker + ' is $**' + str(priceTicker) + '**') - - except KeyError: # If searching for the ticker in loaded data fails, then Bravos didnt provide it, so tell the user. - await client.send_message(channel, ticker.upper() + ' does not exist.') - pass - except: - pass + # if message.content.startswith("!hello"): + # print(dir(message.author)) + # msg = "Hello {0.author.mention}".format(message) + # await client.send_message(message.channel, msg) -# Prints an embed full of news about listed stock -def displayembed(ticker, nameTicker, priceTicker): +@client.event +async def on_ready(): + print("Logged in as") + print(client.user.name) + print(client.user.id) + print("------") - embed = discord.Embed( - title='News for ' + nameTicker, - description='The current stock price of ' + - nameTicker + ' is $**' + str(priceTicker) + '**', - color=0x50bdfe - ) - ''' - Get ticker logo from Motley Fool, then get then print the following sources: - Bravos, Seeking Alpha, MSN Money, Yahoo Finance, Wall Street Journal, The Street. - ''' - embed.set_thumbnail( - url='https://g.foolcdn.com/art/companylogos/mark/' + ticker + '.png') - embed.add_field(name='Bravos', - value='https://bravos.co/' + ticker, inline=False) - embed.add_field(name='Seeking Alpha', - value='https://seekingalpha.com/symbol/' + ticker, inline=False) - embed.add_field( - name='MSN Money', value='https://www.msn.com/en-us/money/stockdetails?symbol=' + ticker, inline=False) - embed.add_field(name='Yahoo Finance', - value='https://finance.yahoo.com/quote/' + ticker, inline=False) - embed.add_field(name='Wall Street Journal', - value='https://quotes.wsj.com/' + ticker, inline=False) - embed.add_field( - name='The Street', value='https://www.thestreet.com/quote/' + ticker + '.html', inline=False) - embed.add_field( - name='Zacks', value='https://www.zacks.com/stock/quote/' + ticker, inline=False) - return embed - - -async def list_servers(): - await client.wait_until_ready() - while not client.is_closed: - print("Current servers:") - for server in client.servers: - print(server.name) client.run(TOKEN) diff --git a/tickerInfo.py b/tickerInfo.py new file mode 100644 index 0000000..a3d13ca --- /dev/null +++ b/tickerInfo.py @@ -0,0 +1,105 @@ +import urllib.request +import json +from datetime import datetime +import time + + +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()) + + for ticker in tickers: + ticker = ticker.upper() + + # 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") + else: + stockData[ticker] = 0 + return stockData + + +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