diff --git a/bot.py b/bot.py index 1432eb1..39f3f3d 100644 --- a/bot.py +++ b/bot.py @@ -3,13 +3,20 @@ import logging import os import telegram -from functions import Symbol -from telegram.ext import CommandHandler, Filters, MessageHandler, Updater - -TELEGRAM_TOKEN = ( - "724630968:AAHL_cpMgrw-B9zSbVlVe7iTYyo0XXL8fi4" # os.environ["TELEGRAM"] +from telegram import InlineQueryResultArticle, InputTextMessageContent +from telegram.ext import ( + CommandHandler, + Filters, + InlineQueryHandler, + MessageHandler, + Updater, ) -IEX_TOKEN = "sk_9e8d93b7cac84cd4b800f34d15b72ad6" # os.environ["IEX"] + +from functions import Symbol + +TELEGRAM_TOKEN = os.environ["TELEGRAM"] + +IEX_TOKEN = os.environ["IEX"] s = Symbol(IEX_TOKEN) # Enable logging @@ -107,6 +114,34 @@ def info(bot, update): ) +def inline_query(bot, update): + """ + Handles inline query. + Does a fuzzy search on input and returns stocks that are close. + """ + matches = s.search_symbols(update.inline_query.query) + results = [] + for match in matches: + try: + price = s.price_reply([match[0]])[match[0]] + print(price) + results.append( + InlineQueryResultArticle( + match[0], + title=match[1], + input_message_content=InputTextMessageContent( + price, parse_mode=telegram.ParseMode.MARKDOWN + ), + ) + ) + except TypeError: + pass + + if len(results) == 5: + bot.answerInlineQuery(update.inline_query.id, results) + return + + def error(bot, update, error): """Log Errors caused by Updates.""" logger.warning('Update "%s" caused error "%s"', update, error) @@ -131,6 +166,9 @@ def main(): # on noncommand i.e message - echo the message on Telegram dp.add_handler(MessageHandler(Filters.text, symbol_detect)) + # Inline Bot commands + dp.add_handler(InlineQueryHandler(inline_query)) + # log all errors dp.add_error_handler(error) diff --git a/functions.py b/functions.py index 54ee25e..a5364d9 100644 --- a/functions.py +++ b/functions.py @@ -1,16 +1,45 @@ import json import os import re -from datetime import datetime +from datetime import datetime, timedelta -import requests +import pandas as pd +import requests as r +from fuzzywuzzy import fuzz class Symbol: SYMBOL_REGEX = "[$]([a-zA-Z]{1,4})" + LIST_URL = "http://oatsreportable.finra.org/OATSReportableSecurities-SOD.txt" def __init__(self, IEX_TOKEN: str): self.IEX_TOKEN = IEX_TOKEN + self.symbol_list, self.symbol_ts = self.get_symbol_list() + + def get_symbol_list(self): + raw_symbols = r.get(self.LIST_URL).text + symbols = pd.DataFrame( + [line.split("|") for line in raw_symbols.split("\n")][:-1] + ) + symbols.columns = symbols.iloc[0] + symbols = symbols.drop(symbols.index[0]) + symbols = symbols.drop(symbols.index[-1]) + symbols["Description"] = symbols["Symbol"] + ": " + symbols["Issue_Name"] + return symbols, datetime.now() + + def search_symbols(self, search: str): + if self.symbol_ts - datetime.now() > timedelta(hours=12): + self.symbol_list, self.symbol_ts = self.get_symbol_list() + + symbols = self.symbol_list + symbols["Match"] = symbols.apply( + lambda x: fuzz.partial_ratio( + search.lower(), f"{x['Symbol']} {x['Issue_Name']}".lower() + ), + axis=1, + ) + symbols.sort_values(by="Match", ascending=False, inplace=True) + return list(zip(list(symbols["Symbol"]), list(symbols["Description"]))) def find_symbols(self, text: str): """ @@ -27,11 +56,10 @@ class Symbol: for symbol in symbols: IEXurl = f"https://cloud.iexapis.com/stable/stock/{symbol}/quote?token={self.IEX_TOKEN}" - response = requests.get(IEXurl) + response = r.get(IEXurl) if response.status_code == 200: IEXData = response.json() message = 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: @@ -52,7 +80,7 @@ class Symbol: for symbol in symbols: IEXurl = f"https://cloud.iexapis.com/stable/data-points/{symbol}/NEXTDIVIDENDDATE?token={self.IEX_TOKEN}" - response = requests.get(IEXurl) + response = r.get(IEXurl) if response.status_code == 200: # extract date from json @@ -86,7 +114,7 @@ class Symbol: for symbol in symbols: IEXurl = f"https://cloud.iexapis.com/stable/stock/{symbol}/news/last/3?token={self.IEX_TOKEN}" - response = requests.get(IEXurl) + response = r.get(IEXurl) if response.status_code == 200: data = response.json() newsMessages[symbol] = f"News for **{symbol.upper()}**:\n" @@ -105,7 +133,7 @@ class Symbol: for symbol in symbols: IEXurl = f"https://cloud.iexapis.com/stable/stock/{symbol}/company?token={self.IEX_TOKEN}" - response = requests.get(IEXurl) + response = r.get(IEXurl) if response.status_code == 200: data = response.json() diff --git a/requirements.txt b/requirements.txt index 2be6790..f3830cf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,5 @@ python-telegram-bot==11.1.0 -requests==2.21.0 \ No newline at end of file +requests==2.21.0 +pandas==0.25.3 +fuzzywuzzy==0.18.0 +python-Levenshtein==0.12.0 \ No newline at end of file