2022-03-15 07:51:34 +00:00
"""
script for telegram bot and its functions
"""
__author__ = " Florian Kellermann, Linus Eickhoff "
__date__ = " 11.03.2022 "
2022-03-15 14:02:01 +00:00
__version__ = " 0.0.4 "
2022-03-15 07:51:34 +00:00
__license__ = " None "
# side-dependencies: none
2022-03-12 16:20:33 +00:00
# Work in Progress
2022-03-15 12:53:39 +00:00
# Api-Key: 5228016873:AAGFrh0P6brag7oD3gxXjCh5gnLLE8JMvMs /debugAPI Key: 5108535940:AAF5FpPHNV96WxGCDt8aMrGGKke1VILYib4 (https://t.me/mynewdebugbot)
2022-03-12 17:31:10 +00:00
# text bot at t.me/projektaktienbot
# API Documentation https://core.telegram.org/bots/api
# Code examples https://github.com/eternnoir/pyTelegramBotAPI#getting-started
2022-03-15 08:15:12 +00:00
2022-03-12 18:44:58 +00:00
import os
2022-03-12 17:31:10 +00:00
import telebot
2022-03-12 18:24:25 +00:00
import time
import sys
import logging
2022-03-16 16:42:46 +00:00
import json
2022-03-15 08:15:12 +00:00
2022-03-15 13:49:36 +00:00
import news . news_fetcher as news
2022-03-16 08:30:33 +00:00
import shares . share_fetcher as share_fetcher
2022-03-15 12:53:39 +00:00
2022-03-12 18:24:25 +00:00
from telebot import types
2022-03-15 12:53:39 +00:00
from dotenv import load_dotenv
2022-03-29 08:49:02 +00:00
from api_handling . api_handler import API_Handler
2022-03-28 17:39:37 +00:00
2022-03-15 12:53:39 +00:00
2022-03-29 06:49:32 +00:00
load_dotenv ( dotenv_path = ' .env ' )
2022-03-12 17:31:10 +00:00
2022-03-16 16:42:46 +00:00
bot_version = " 0.2.1 "
2022-03-13 09:49:51 +00:00
user_list = [ ]
2022-03-28 17:39:37 +00:00
#create api handler
2022-03-29 08:49:02 +00:00
api_handler = API_Handler ( " https://aktienbot.flokaiser.com/api " , str ( os . getenv ( " BOT_EMAIL " ) ) , str ( os . getenv ( " BOT_PASSWORD " ) ) )
print ( api_handler . token )
2022-03-28 17:39:37 +00:00
2022-03-13 09:49:51 +00:00
class User : # Currently saving users in this class to test functionality -> later database
2022-03-13 12:20:39 +00:00
def __init__ ( self , p_user_id , p_user_name , p_chat_id ) :
2022-03-15 14:02:01 +00:00
""" Initialize a new user
: type self :
: param self : for class
: type p_user_id : int
: param p_user_id : telegram user id
: type p_user_name : str
: param p_user_name : first name of user
: type p_chat_id : int
: param p_chat_id : telegram chat id
: raises :
: rtype :
"""
2022-03-13 09:49:51 +00:00
self . user_id = int ( p_user_id )
self . chat_id = int ( p_chat_id )
2022-03-13 12:20:39 +00:00
self . user_name = str ( p_user_name )
2022-03-13 09:49:51 +00:00
2022-03-12 18:44:58 +00:00
bot = telebot . TeleBot ( os . getenv ( ' BOT_API_KEY ' ) )
2022-03-13 09:49:51 +00:00
@bot.message_handler ( commands = [ ' start ' ] ) # /start -> saving as new user and sending welcome
def send_start ( message ) :
2022-03-15 14:02:01 +00:00
""" Description
: type message : message object bot
: param message : message that was reacted to , in this case always containing ' /start '
: raises : none
: rtype : none
"""
2022-03-13 10:34:36 +00:00
new_user = User ( int ( message . from_user . id ) , message . from_user . first_name , int ( message . chat . id ) )
2022-03-13 09:49:51 +00:00
existing_already = False
for known_user in user_list :
if known_user . user_id == new_user . user_id :
existing_already = True
if existing_already == False :
2022-03-13 10:34:36 +00:00
user_list . append ( new_user )
2022-03-13 09:49:51 +00:00
bot . reply_to ( message , " Welcome to this share bot project. Type /help to get information on what this bot can do " )
2022-03-15 12:53:39 +00:00
2022-03-13 12:35:50 +00:00
@bot.message_handler ( commands = [ ' version ' ] )
def send_version ( message ) :
2022-03-15 14:02:01 +00:00
""" Sending programm version
: type message : message object bot
: param message : message that was reacted to , in this case always containing ' /version '
: raises : none
: rtype : none
"""
2022-03-15 08:05:28 +00:00
bot . reply_to ( message , bot_version )
2022-03-12 17:31:10 +00:00
2022-03-15 12:53:39 +00:00
2022-03-13 09:49:51 +00:00
@bot.message_handler ( commands = [ ' help ' ] ) # /help -> sending all functions
2022-03-12 17:31:10 +00:00
def send_welcome ( message ) :
2022-03-15 14:02:01 +00:00
""" Send all functions
: type message : message object bot
: param message : message that was reacted to , in this case always containing ' /help '
: raises : none
: rtype : none
"""
2022-03-16 08:30:33 +00:00
bot . reply_to ( message , " /id or /auth for authentication. /update to get updates on your shares. /users to see all users. /news to get current use for your keywords. /share to get price of specific share. For further details see aktienbot.flokaiser.com " )
2022-03-15 12:53:39 +00:00
2022-03-13 10:34:36 +00:00
@bot.message_handler ( commands = [ ' users ' ] )
def send_all_users ( message ) :
2022-03-15 14:02:01 +00:00
""" Send all users, only possible for admins
: type message : message object bot
: param message : message that was reacted to , in this case always containing ' /users '
: raises : none
: rtype : none
"""
2022-03-13 10:34:36 +00:00
print ( ' Debug: users command ' )
2022-03-15 14:02:01 +00:00
user_id = int ( message . from_user . id )
# tbd check if user is admin
2022-03-13 10:34:36 +00:00
answer = ' Current number of users: ' + str ( len ( user_list ) )
bot . send_message ( chat_id = user_id , text = answer )
for known_user in user_list :
answer = str ( known_user . user_id ) + ' : ' + known_user . user_name
bot . send_message ( chat_id = user_id , text = answer )
2022-03-13 09:49:51 +00:00
2022-03-13 08:05:44 +00:00
2022-03-13 09:49:51 +00:00
@bot.message_handler ( commands = [ ' id ' , ' auth ' ] ) # /auth or /id -> Authentication with user_id over web tool
2022-03-13 08:05:44 +00:00
def send_id ( message ) :
2022-03-15 14:02:01 +00:00
""" Send user id for authentication with browser
: type message : message object bot
: param message : message that was reacted to , in this case always containing ' /id ' or ' /auth '
: raises : none
: rtype : none
"""
2022-03-13 09:49:51 +00:00
answer = ' Your ID/Authentication Code is: [ ' + str ( message . from_user . id ) + ' ]. Enter this code in the settings on aktienbot.flokaiser.com to get updates on your shares. '
2022-03-13 08:05:44 +00:00
bot . reply_to ( message , answer )
2022-03-12 17:31:10 +00:00
2022-03-13 09:49:51 +00:00
2022-03-29 06:31:58 +00:00
#function that sends telegram status(running or offline) as message from telegram bot to user
@bot.message_handler ( commands = [ ' status ' ] )
def send_status ( message ) :
""" Sends status to user
: type message : message object bot
: param message : message that was reacted to , if no other command handler gets called
: raises : none
: rtype : none
"""
bot . reply_to ( message , " bot is running " )
2022-03-16 08:30:33 +00:00
@bot.message_handler ( commands = [ ' update ' ] )
2022-03-13 09:49:51 +00:00
def send_update ( message ) :
2022-03-15 14:02:01 +00:00
""" Send update on shares
: type message : message object bot
: param message : message that was reacted to , in this case always containing ' /help '
: raises : none
: rtype : none
"""
2022-03-13 09:49:51 +00:00
user_id = int ( message . from_user . id )
2022-03-15 14:02:01 +00:00
2022-03-16 16:42:46 +00:00
#Can be deleted when getting from database
dirname = os . path . dirname ( __file__ )
json_path = os . path . join ( dirname , ' shares/shares_example.json ' )
2022-03-15 14:02:01 +00:00
2022-03-16 16:42:46 +00:00
with open ( json_path ) as json_file :
json_share_data = json . load ( json_file )
int_share_count = int ( json_share_data [ ' share_count ' ] )
2022-03-16 16:49:57 +00:00
str_username = str ( json_share_data [ ' user ' ] )
bot . send_message ( chat_id = user_id , text = f ' Hello { str_username } . Here is the update on your currently owned shares: ' )
2022-03-16 16:42:46 +00:00
for i in range ( int_share_count ) :
my_share = json_share_data [ ' shares ' ] [ i ]
my_share_symbol = str ( my_share [ ' symbol ' ] )
my_share_amount = float ( my_share [ ' amount_bought ' ] )
my_share_buy_price = float ( my_share [ ' price_bought ' ] )
my_share_course = float ( share_fetcher . get_share_price ( my_share_symbol ) )
my_update_message = f ' Symbol: { my_share_symbol } \n Price: { my_share_course } \n Bought for: { my_share_buy_price } \n \
Amount owned : { my_share_amount } \nWin / Lose : { ( my_share_amount * my_share_course ) - ( my_share_amount * my_share_buy_price ) } '
bot . send_message ( chat_id = user_id , text = my_update_message )
2022-03-16 08:30:33 +00:00
@bot.message_handler ( commands = [ ' share ' ] )
2022-03-16 16:42:46 +00:00
def send_share_update ( message ) :
2022-03-16 08:30:33 +00:00
""" Send price of a specific share
: type message : message object bot
: param message : message that was reacted to , in this case always containing ' /share '
: raises : none
: rtype : none
"""
user_id = int ( message . from_user . id )
2022-03-15 14:02:01 +00:00
2022-03-13 09:49:51 +00:00
#Get Information for user with this id
2022-03-16 08:30:33 +00:00
bot . send_message ( chat_id = user_id , text = ' Send symbol of share: ' )
2022-03-16 09:02:28 +00:00
#str_share_price = shares.wait_for_share.main_loop(bot)
bot . register_next_step_handler ( message , send_share_price )
2022-03-16 08:30:33 +00:00
2022-03-16 09:02:28 +00:00
def send_share_price ( message ) :
2022-03-16 16:42:46 +00:00
str_share_price = share_fetcher . get_share_price ( str ( message . text ) )
2022-03-16 09:02:28 +00:00
bot . reply_to ( message , str_share_price )
2022-03-13 09:49:51 +00:00
2022-03-15 14:02:01 +00:00
@bot.message_handler ( commands = [ ' news ' ] )
2022-03-15 12:53:39 +00:00
def send_news ( message ) :
2022-03-15 14:02:01 +00:00
""" Get news for keywords of user
: type message : message object bot
: param message : message that was reacted to , in this case always containing ' /news '
: raises : none
: rtype : none
"""
2022-03-15 12:53:39 +00:00
user_id = int ( message . from_user . id )
2022-03-29 08:49:02 +00:00
keywords = api_handler . get_user_keywords ( user_id )
2022-03-29 10:20:58 +00:00
keywords_search = ' OR ' . join ( keywords )
print ( keywords_search )
2022-03-29 10:28:28 +00:00
news_list = news . get_all_news_by_keyword ( keywords_search ) [ " articles " ] [ : 5 ]
2022-03-29 08:49:02 +00:00
2022-03-29 10:20:58 +00:00
if news_list :
for article in news_list :
formatted_article = news . format_article ( article )
bot . send_message ( chat_id = user_id , text = formatted_article , parse_mode = " MARKDOWN " )
else :
bot . send_message ( chat_id = user_id , text = ' No news found for your keywords. ' )
2022-03-15 12:53:39 +00:00
2022-03-28 17:39:37 +00:00
@bot.message_handler ( commands = [ ' addkeyword ' ] )
def add_keyword ( message ) :
""" Add keyword to user
: type message : message object bot
: param message : message that was reacted to , in this case always ' /addkeyword '
: raises : none
: rtype : none
"""
user_id = int ( message . from_user . id )
bot . send_message ( chat_id = user_id , text = ' Type keyword to add: ' )
bot . register_next_step_handler ( message , store_keyword )
def store_keyword ( message ) :
user_id = int ( message . from_user . id )
2022-03-29 08:49:02 +00:00
print ( str ( user_id ) )
keyword = str ( message . text ) . lower ( )
api_handler . set_keyword ( user_id , keyword )
bot . send_message ( chat_id = user_id , text = f ' Keyword " { keyword } " added. ' )
2022-03-29 10:04:49 +00:00
2022-03-29 08:49:02 +00:00
@bot.message_handler ( commands = [ ' removekeyword ' ] )
def remove_keyword ( message ) :
""" Remove keyword from user
: type message : message object bot
: param message : message that was reacted to , in this case always ' /removekeyword '
: raises : none
: rtype : none
"""
user_id = int ( message . from_user . id )
bot . send_message ( chat_id = user_id , text = ' Type keyword to remove: ' )
bot . register_next_step_handler ( message , remove_keyword_step )
def remove_keyword_step ( message ) :
user_id = int ( message . from_user . id )
keyword = str ( message . text ) . lower ( )
api_handler . delete_keyword ( user_id , keyword )
bot . send_message ( chat_id = user_id , text = f ' Keyword " { keyword } " removed. ' )
2022-03-28 17:39:37 +00:00
2022-03-29 10:04:49 +00:00
@bot.message_handler ( commands = [ ' keywords ' ] )
def send_keywords ( message ) :
""" Send keywords of user
: type message : message object bot
: param message : message that was reacted to , in this case always ' /keywords '
: raises : none
: rtype : none
"""
user_id = int ( message . from_user . id )
keywords = api_handler . get_user_keywords ( user_id )
bot . send_message ( chat_id = user_id , text = f ' Your keywords are: { keywords } ' )
2022-03-13 09:49:51 +00:00
@bot.message_handler ( func = lambda message : True ) # Returning that command is unkown for any other statement
2022-03-12 17:31:10 +00:00
def echo_all ( message ) :
2022-03-15 14:02:01 +00:00
""" Tell that command is not known if it is no known command
: type message : message object bot
: param message : message that was reacted to , if no other command handler gets called
: raises : none
: rtype : none
"""
2022-03-13 08:05:44 +00:00
answer = ' Do not know this command or text: ' + message . text
2022-03-12 18:44:58 +00:00
bot . reply_to ( message , answer )
2022-03-13 10:34:36 +00:00
2022-03-12 18:24:25 +00:00
telebot . logger . setLevel ( logging . DEBUG )
2022-03-13 09:49:51 +00:00
@bot.inline_handler ( lambda query : query . query == ' text ' ) # inline prints for debugging
2022-03-12 18:24:25 +00:00
def query_text ( inline_query ) :
2022-03-15 14:02:01 +00:00
""" Output in the console about current user actions and status of bot
: type inline_query :
: param inline_query :
: raises : none
: rtype : none
"""
2022-03-12 18:24:25 +00:00
try :
r = types . InlineQueryResultArticle ( ' 1 ' , ' Result1 ' , types . InputTextMessageContent ( ' hi ' ) )
r2 = types . InlineQueryResultArticle ( ' 2 ' , ' Result2 ' , types . InputTextMessageContent ( ' hi ' ) )
bot . answer_inline_query ( inline_query . id , [ r , r2 ] )
except Exception as e :
print ( e )
2022-03-12 18:44:58 +00:00
2022-03-12 18:24:25 +00:00
def main_loop ( ) :
2022-03-15 14:02:01 +00:00
""" Get Information about bot status every 3 seconds
: raises : none
: rtype : none
"""
2022-03-12 18:24:25 +00:00
bot . infinity_polling ( )
2022-03-12 17:31:10 +00:00
2022-03-12 18:24:25 +00:00
if __name__ == ' __main__ ' :
try :
main_loop ( )
except KeyboardInterrupt :
print ( ' \n Exiting by user request. \n ' )
2022-03-13 12:35:50 +00:00
sys . exit ( 0 )