TelegramAktienBot/telegram_bot/bot_updates.py

213 lines
7.2 KiB
Python
Raw Normal View History

"""
script for regularly sending updates on shares and news based on user interval
"""
__author__ = "Florian Kellermann, Linus Eickhoff"
2022-05-10 15:37:20 +00:00
__date__ = "10.05.2022"
2022-05-11 21:33:48 +00:00
__version__ = "1.0.2"
__license__ = "None"
import os
import sys
2022-05-11 21:33:48 +00:00
import time
2022-05-12 06:59:12 +00:00
from apscheduler.schedulers.background import BackgroundScheduler # scheduler for cron
2022-05-11 21:33:48 +00:00
from dotenv import load_dotenv
2022-05-11 21:33:48 +00:00
import helper_functions as hf
import news.news_fetcher as news_fetcher
import shares.share_fetcher as share_fetcher
from api_handling.api_handler import API_Handler
from bot import bot
'''
* * * * * code
weekday (0->Monday, 7->Sunday)
Month (1-12)
Day (1-31)
Hour (0-23)
Minute (0-59)
example 0 8 * * * -> daily update at 8am
'''
user_ids = []
user_crontab = []
load_dotenv(dotenv_path='.env')
2022-05-11 21:33:48 +00:00
def start_updater():
2022-04-26 05:39:06 +00:00
""" starting function for regularly sending updates
:raises: none
:rtype: none
"""
2022-05-11 21:33:48 +00:00
2022-04-26 07:02:21 +00:00
print("Bot updates started")
2022-05-11 21:33:48 +00:00
2022-05-12 16:19:42 +00:00
my_handler = API_Handler(os.getenv("API_URL"), str(os.getenv("BOT_EMAIL")), str(os.getenv("BOT_PASSWORD")))
2022-04-26 06:43:51 +00:00
2022-04-26 05:39:06 +00:00
update_crontab(my_handler)
2022-05-11 21:33:48 +00:00
2022-04-26 05:39:06 +00:00
def update_crontab(p_my_handler):
""" Updating crontab lists every hour
:type pCurrent_Time: time when starting crontab update
:param pCurrent_Time: datetime
:raises: none
:rtype: none
"""
2022-05-11 21:33:48 +00:00
global user_crontab
global user_ids
2022-05-11 07:40:08 +00:00
all_users = p_my_handler.get_all_users() # get all users so crontabs can update for everybody
2022-05-13 09:59:11 +00:00
if all_users == None:
print("No users found, trying again.")
update_crontab(p_my_handler)
return
user_ids = []
user_crontab = []
2022-05-11 21:33:48 +00:00
2022-05-13 10:28:22 +00:00
for element in all_users:
if element["cron"] != '' and element["telegram_user_id"] != '': # check if both values are existing so I have consistent data
try:
user_ids.append(int(element["telegram_user_id"]))
2022-05-04 07:58:54 +00:00
try:
2022-05-13 10:28:22 +00:00
user_crontab.append(str(element["cron"]))
except:
user_ids.pop() # if something goes wrong with cron I have to delete matching user id
except: continue
2022-05-04 07:58:54 +00:00
2022-04-26 07:02:21 +00:00
print(user_ids)
2022-05-11 21:33:48 +00:00
2022-04-21 06:23:48 +00:00
update_based_on_crontab(user_ids, user_crontab, p_my_handler)
2022-05-11 07:40:08 +00:00
update_crontab(p_my_handler) # restart the update after time sleep
2022-04-21 06:23:48 +00:00
def update_based_on_crontab(p_user_ids, p_user_crontab, p_my_handler):
""" Check all the crontab codes and add jobs to start in time
:type p_user_ids: array
:param p_user_ids: user id array of all users
:type p_user_crontab: array
:param p_user_crontab: crontabs for all users equivalent to the user array
:type p_my_handler: Api_Handler
:param p_my_handler: get database stuff
:raises: none
:rtype: none
"""
2022-05-11 07:40:08 +00:00
my_scheduler = BackgroundScheduler() # schedule sends based on cron
for i in range(len(p_user_ids)):
2022-05-11 07:40:08 +00:00
cron_split = p_user_crontab[i].split(" ") # split it up to use in scheduler
2022-04-26 07:02:21 +00:00
print(cron_split[4], cron_split[1], cron_split[0], cron_split[3], cron_split[2])
2022-05-11 21:33:48 +00:00
my_scheduler.add_job(update_for_user, 'cron', day_of_week=cron_split[4], hour=cron_split[1], minute=cron_split[0], month=cron_split[3], day=cron_split[2], args=(p_user_ids[i], p_my_handler))
my_scheduler.start()
2022-04-21 06:23:48 +00:00
2022-05-11 07:40:08 +00:00
time.sleep( 600 ) # scheduler runs in background and I wait 10mins
my_scheduler.shutdown() # after this the new crontabs will be loaded
2022-04-05 16:23:11 +00:00
def update_for_user(p_user_id, p_my_handler):
""" Pull shares and send updates for specific user id
:type p_user_id: integer
:param p_user_id: user id of user that shall receive update
:type p_my_handler: Api_Handler
:param p_my_handler: handle the api and pull from database
:raises: none
:rtype: none
"""
share_symbols = []
share_amounts = []
2022-05-11 07:40:08 +00:00
my_portfolio = p_my_handler.get_user_portfolio(p_user_id) # get all existing shares for user
2022-05-13 10:25:56 +00:00
my_portfolio = None
if my_portfolio!=None:
for element in my_portfolio:
if element["count"] != '' and element["isin"] != '':
print(element["count"], element["isin"])
share_symbols.append(element["isin"])
share_amounts.append(element["count"])
my_user = p_my_handler.get_user(p_user_id)
2022-05-13 10:25:56 +00:00
send_to_user("Hello %s this is your update for today:"%str(my_user["username"]), pUser_id=p_user_id)
2022-05-11 07:40:08 +00:00
shares = p_my_handler.get_user_shares(p_user_id) # all interest shares
2022-05-11 07:40:08 +00:00
if len(share_symbols) != 0: # iterate through all shares
for i in range(len(share_symbols)):
my_price = share_fetcher.get_share_price_no_currency(share_symbols[i])
2022-05-11 07:26:42 +00:00
my_update_message = f'{share_fetcher.get_share_information_markdown(share_symbols[i])}\ncount: {hf.make_markdown_proof(share_amounts[i])}\nTotal: {hf.make_markdown_proof(round(float(my_price) * float(share_amounts[i]), 2))} EUR'
2022-05-10 19:51:27 +00:00
bot.send_message(chat_id=p_user_id, text=my_update_message, parse_mode="MARKDOWNV2")
else:
2022-05-12 16:19:42 +00:00
send_to_user("No shares found for your account. Check " + os.getenv("WEBSITE_URL") + " to change your settings and add shares.", pUser_id=p_user_id)
2022-05-11 21:33:48 +00:00
if len(shares) != 0: # Send updates on watchlist shares if existing
send_to_user("Your watchlist shares:", pUser_id=p_user_id)
for element in shares:
2022-05-10 19:51:27 +00:00
send_to_user(share_fetcher.get_share_information_markdown(element), pUser_id=p_user_id, md_mode=True)
2022-05-11 21:33:48 +00:00
keywords = p_my_handler.get_user_keywords(p_user_id) # get keywords as array
if (keywords): # if keywords exist and array is not empty
send_to_user("If you haven't read yet: \nHere are some interesting news according to your keywords:", pUser_id=p_user_id)
for keyword in keywords:
news = news_fetcher.get_top_news_by_keyword(keyword)["articles"]
2022-05-10 16:45:51 +00:00
keyword = hf.make_markdown_proof(keyword)
if not news: # if empty news array
2022-05-11 07:26:42 +00:00
send_to_user(f"No news found for keyword _{keyword}_\.", pUser_id=p_user_id, md_mode=True)
2022-05-10 15:14:53 +00:00
elif news == None: # if news is none
2022-05-11 07:26:42 +00:00
send_to_user(f"Server error for keyword _{keyword}_\.", pUser_id=p_user_id, md_mode=True)
else:
2022-05-11 21:33:48 +00:00
news_formatted = news_fetcher.format_article(news[0]) # format for message, only use the most popular article
send_to_user(f"_keyword: {keyword}_\n\n{news_formatted}", pUser_id=p_user_id, md_mode=True) # send news with related keyword in Markdown
2022-05-11 21:33:48 +00:00
def send_to_user(pText, pUser_id, md_mode=False):
""" Send message to user
:type pText: string
:param pText: Text to send to user
:type pUser_id: int
:param pUser_id: user to send to. per default me (Florian Kellermann)
:type md_mode: boolean
:param md_mode: if true, parse_mode is markdown
:raises: none
:rtype: none
"""
if md_mode:
2022-05-10 16:45:51 +00:00
bot.send_message(chat_id=pUser_id, text=pText, parse_mode="MARKDOWNV2")
else:
bot.send_message(chat_id=pUser_id, text=pText)
if __name__ == "__main__":
try:
start_updater()
sys.exit(-1)
except KeyboardInterrupt:
print("Ending")
2022-05-11 21:33:48 +00:00
sys.exit(-1)