Reformatting

This commit is contained in:
Administrator 2022-05-11 23:33:48 +02:00
parent 24eb954856
commit 397dd23b8d
21 changed files with 424 additions and 439 deletions

View File

@ -3,6 +3,7 @@
Aktienbot API Aktienbot API
## Development ## Development
1. Create virtual environment `python -m venv venv env/Scripts/activate` 1. Create virtual environment `python -m venv venv env/Scripts/activate`
2. Install requirements `pip install -r api/requirements.txt` 2. Install requirements `pip install -r api/requirements.txt`
3. Set environment variables (see list below) 3. Set environment variables (see list below)
@ -10,8 +11,8 @@ Aktienbot API
2. Or set variables using `export` or `set` commands. (Windows `set`, Linux `export`) 2. Or set variables using `export` or `set` commands. (Windows `set`, Linux `export`)
4. Run api `python api/app.py` 4. Run api `python api/app.py`
## Testing ## Testing
1. Create virtual environment `python -m venv venv env/Scripts/activate` 1. Create virtual environment `python -m venv venv env/Scripts/activate`
2. Install requirements `pip install -r api/requirements.txt` 2. Install requirements `pip install -r api/requirements.txt`
3. Set environment variables (see list below) 3. Set environment variables (see list below)
@ -21,6 +22,7 @@ Aktienbot API
5. Run tests: `python -m pytest -v --cov-report term-missing --cov=app` 5. Run tests: `python -m pytest -v --cov-report term-missing --cov=app`
## Environment variables ## Environment variables
``` ```
# Flask secret key # Flask secret key
SECRET_KEY= SECRET_KEY=
@ -34,6 +36,7 @@ Aktienbot API
``` ```
## Docker ## Docker
``` ```
docker run -d \ docker run -d \
--name aktienbot_api \ --name aktienbot_api \
@ -48,4 +51,5 @@ docker run -d \
--restart unless-stopped \ --restart unless-stopped \
registry.flokaiser.com/aktienbot/api:latest registry.flokaiser.com/aktienbot/api:latest
``` ```
or load environment variables from file by using `--env-file <filename>` or load environment variables from file by using `--env-file <filename>`

View File

@ -4,21 +4,19 @@ __credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin P
__license__ = "GPL 3.0" __license__ = "GPL 3.0"
__version__ = "1.0.0" __version__ = "1.0.0"
from flask import current_app
from apiflask import APIFlask from apiflask import APIFlask
from dotenv import load_dotenv
from flask_cors import CORS
from app.blueprints.keyword import keyword_blueprint from app.blueprints.keyword import keyword_blueprint
from app.blueprints.portfolio import portfolio_blueprint from app.blueprints.portfolio import portfolio_blueprint
from app.blueprints.shares import shares_blueprint
from app.blueprints.share_price import share_price_blueprint from app.blueprints.share_price import share_price_blueprint
from app.blueprints.transactions import transaction_blueprint from app.blueprints.shares import shares_blueprint
from app.blueprints.telegram import telegram_blueprint from app.blueprints.telegram import telegram_blueprint
from app.blueprints.transactions import transaction_blueprint
from app.blueprints.user import users_blueprint from app.blueprints.user import users_blueprint
from app.helper_functions import hash_password from app.helper_functions import hash_password
from app.models import * from app.models import *
from dotenv import load_dotenv
from flask import current_app
from flask_cors import CORS
def create_app(config_filename=None): def create_app(config_filename=None):

View File

@ -4,10 +4,9 @@ __credits__ = ["Florian Kaiser", "Florian Kellermann", "Linus Eickhof", "Kevin P
__license__ = "GPL 3.0" __license__ = "GPL 3.0"
__version__ = "1.0.0" __version__ = "1.0.0"
from flask import current_app
import jwt import jwt
from apiflask import HTTPTokenAuth from apiflask import HTTPTokenAuth
from flask import current_app
auth = HTTPTokenAuth() auth = HTTPTokenAuth()

View File

@ -7,12 +7,11 @@ __version__ = "1.0.0"
import os import os
from apiflask import APIBlueprint, abort from apiflask import APIBlueprint, abort
from app.auth import auth
from app.db import database as db from app.db import database as db
from app.helper_functions import make_response, get_email_or_abort_401 from app.helper_functions import make_response, get_email_or_abort_401
from app.auth import auth
from app.schema import KeywordResponseSchema, KeywordSchema, DeleteSuccessfulSchema
from app.models import Keyword from app.models import Keyword
from app.schema import KeywordResponseSchema, KeywordSchema, DeleteSuccessfulSchema
keyword_blueprint = APIBlueprint('keyword', __name__, url_prefix='/api') keyword_blueprint = APIBlueprint('keyword', __name__, url_prefix='/api')
__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))

View File

@ -6,9 +6,8 @@ __version__ = "1.0.0"
import pytest import pytest
from app import create_app, db from app import create_app, db
from app.models import User, Transaction, Keyword, Share
from app.helper_functions import hash_password from app.helper_functions import hash_password
from app.models import User, Transaction, Keyword, Share
@pytest.fixture(scope='module') @pytest.fixture(scope='module')

View File

@ -8,6 +8,7 @@ __version__ = "1.0.0"
This file (test_keyword.py) contains the functional tests for the `keyword` blueprint. This file (test_keyword.py) contains the functional tests for the `keyword` blueprint.
""" """
import json import json
from tests.functional.helper_functions import get_token from tests.functional.helper_functions import get_token

View File

@ -8,6 +8,7 @@ __version__ = "1.0.0"
This file (test_portfolio.py) contains the functional tests for the `portfolio` blueprint. This file (test_portfolio.py) contains the functional tests for the `portfolio` blueprint.
""" """
import json import json
from tests.functional.helper_functions import get_token from tests.functional.helper_functions import get_token

View File

@ -8,6 +8,7 @@ __version__ = "1.0.0"
This file (test_share.py) contains the functional tests for the `share` blueprint. This file (test_share.py) contains the functional tests for the `share` blueprint.
""" """
import json import json
from tests.functional.helper_functions import get_token from tests.functional.helper_functions import get_token

View File

@ -8,6 +8,7 @@ __version__ = "1.0.0"
This file (test_telegram.py) contains the functional tests for the `telegram` blueprint. This file (test_telegram.py) contains the functional tests for the `telegram` blueprint.
""" """
import json import json
from tests.functional.helper_functions import get_token from tests.functional.helper_functions import get_token

View File

@ -8,6 +8,7 @@ __version__ = "1.0.0"
This file (test_transaction.py) contains the functional tests for the `transaction` blueprint. This file (test_transaction.py) contains the functional tests for the `transaction` blueprint.
""" """
import json import json
from tests.functional.helper_functions import get_token from tests.functional.helper_functions import get_token

View File

@ -3,6 +3,7 @@
Aktienbot telegram bot Aktienbot telegram bot
## Development ## Development
1. Create virtual environment `python -m venv venv` 1. Create virtual environment `python -m venv venv`
2. Launch venv: `.\venv\Scripts\activate` 2. Launch venv: `.\venv\Scripts\activate`
3. Install requirements `pip install -r telegram_bot/requirements.txt` 3. Install requirements `pip install -r telegram_bot/requirements.txt`
@ -12,6 +13,7 @@ Aktienbot telegram bot
5. Run api `python telegram_bot/bot.py` 5. Run api `python telegram_bot/bot.py`
## Environment variables ## Environment variables
``` ```
# Telegram bot api key # Telegram bot api key
BOT_API_KEY= BOT_API_KEY=
@ -21,6 +23,7 @@ Aktienbot telegram bot
``` ```
## Docker ## Docker
``` ```
docker run -d \ docker run -d \
--name aktienbot_bot \ --name aktienbot_bot \
@ -31,4 +34,5 @@ docker run -d \
--restart unless-stopped \ --restart unless-stopped \
registry.flokaiser.com/aktienbot/bot:latest registry.flokaiser.com/aktienbot/bot:latest
``` ```
or load environment variables from file by using `--env-file <filename>` or load environment variables from file by using `--env-file <filename>`

View File

@ -6,17 +6,19 @@ __date__ = "10.05.2022"
__version__ = "1.0.2" __version__ = "1.0.2"
__license__ = "None" __license__ = "None"
#side-dependencies: none # side-dependencies: none
#Work in Progress # Work in Progress
import sys
import os import os
import sys
import requests as r import requests as r
from croniter import croniter # used for checking cron formatting from croniter import croniter # used for checking cron formatting
from dotenv import load_dotenv from dotenv import load_dotenv
load_dotenv() # loads environment vars load_dotenv() # loads environment vars
# note: for more information about the api visit swagger documentation on https://gruppe1.testsites.info/api/docs#/ # note: for more information about the api visit swagger documentation on https://gruppe1.testsites.info/api/docs#/
class API_Handler: class API_Handler:
@ -43,7 +45,6 @@ class API_Handler:
set_admin(email, is_admin): sets the admin status of the user with the given email set_admin(email, is_admin): sets the admin status of the user with the given email
""" """
def __init__(self, db_adress, email, password): def __init__(self, db_adress, email, password):
"""initializes the API_Handler class """initializes the API_Handler class
@ -63,7 +64,6 @@ class API_Handler:
print("Error: " + str(p.status_code) + " invalid credentials") print("Error: " + str(p.status_code) + " invalid credentials")
self.token = None self.token = None
def reauthorize(self, email, password): # can be used if token expired def reauthorize(self, email, password): # can be used if token expired
"""set new credentials """set new credentials
@ -87,7 +87,6 @@ class API_Handler:
self.token = None self.token = None
return None return None
def get_user(self, user_id, max_retries=10): # max retries are used recursively if the request fails def get_user(self, user_id, max_retries=10): # max retries are used recursively if the request fails
"""gets the shares of the user """gets the shares of the user
@ -107,12 +106,11 @@ class API_Handler:
with r.Session() as s: with r.Session() as s:
headers = {'Authorization': 'Bearer ' + self.token + ":" + str(user_id)} # authorization is bot_token:user_id (user_id is the id of the user you want to get data from) headers = {'Authorization': 'Bearer ' + self.token + ":" + str(user_id)} # authorization is bot_token:user_id (user_id is the id of the user you want to get data from)
req = s.get(self.db_adress + "/user", headers=headers) req = s.get(self.db_adress + "/user", headers=headers)
if(req.status_code == 200): if (req.status_code == 200):
return req.json()["data"] return req.json()["data"]
else: else:
return self.get_user(user_id, max_retries-1) # if request fails try again recursively return self.get_user(user_id, max_retries - 1) # if request fails try again recursively
def get_all_users(self, max_retries=10): def get_all_users(self, max_retries=10):
"""gets all users """gets all users
@ -132,12 +130,11 @@ class API_Handler:
with r.Session() as s: with r.Session() as s:
headers = {'Authorization': 'Bearer ' + self.token} headers = {'Authorization': 'Bearer ' + self.token}
req = s.get(self.db_adress + "/users", headers=headers) req = s.get(self.db_adress + "/users", headers=headers)
if(req.status_code == 200): if (req.status_code == 200):
return req.json()["data"] return req.json()["data"]
else: else:
return self.get_all_users(max_retries-1) return self.get_all_users(max_retries - 1)
def get_user_keywords(self, user_id, max_retries=10): def get_user_keywords(self, user_id, max_retries=10):
"""gets the keywords of the user """gets the keywords of the user
@ -159,7 +156,7 @@ class API_Handler:
with r.Session() as s: with r.Session() as s:
headers = {'Authorization': 'Bearer ' + self.token + ":" + str(user_id)} headers = {'Authorization': 'Bearer ' + self.token + ":" + str(user_id)}
req = s.get(self.db_adress + "/keywords", headers=headers) req = s.get(self.db_adress + "/keywords", headers=headers)
if(req.status_code == 200): if (req.status_code == 200):
keywords_json = req.json()["data"] keywords_json = req.json()["data"]
for keyword in keywords_json: # keywords_json is a list of dictionaries for keyword in keywords_json: # keywords_json is a list of dictionaries
keywords.append(keyword["keyword"]) keywords.append(keyword["keyword"])
@ -167,9 +164,7 @@ class API_Handler:
return keywords # will be empty if no keywords are set return keywords # will be empty if no keywords are set
else: else:
return self.get_user_keywords(user_id, max_retries-1) return self.get_user_keywords(user_id, max_retries - 1)
def set_keyword(self, user_id, keyword): def set_keyword(self, user_id, keyword):
"""sets the keyword of the user """sets the keyword of the user
@ -190,7 +185,6 @@ class API_Handler:
return req.status_code return req.status_code
def delete_keyword(self, user_id, keyword): def delete_keyword(self, user_id, keyword):
"""deletes the keyword of the user """deletes the keyword of the user
@ -210,7 +204,6 @@ class API_Handler:
return req.status_code return req.status_code
def get_user_shares(self, user_id, max_retries=10): def get_user_shares(self, user_id, max_retries=10):
"""gets the shares of the user """gets the shares of the user
@ -230,7 +223,7 @@ class API_Handler:
with r.Session() as s: with r.Session() as s:
headers = {'Authorization': 'Bearer ' + self.token + ":" + str(user_id)} headers = {'Authorization': 'Bearer ' + self.token + ":" + str(user_id)}
req = s.get(self.db_adress + "/shares", headers=headers) req = s.get(self.db_adress + "/shares", headers=headers)
if(req.status_code == 200): if (req.status_code == 200):
shares_json = req.json()["data"] shares_json = req.json()["data"]
shares = [] shares = []
for share in shares_json: for share in shares_json:
@ -239,8 +232,7 @@ class API_Handler:
return shares return shares
else: else:
return self.get_user_shares(user_id, max_retries-1) return self.get_user_shares(user_id, max_retries - 1)
def set_share(self, user_id, isin, comment): def set_share(self, user_id, isin, comment):
"""sets the share of the user """sets the share of the user
@ -258,10 +250,10 @@ class API_Handler:
""" """
with r.Session() as s: with r.Session() as s:
headers = {'Authorization': 'Bearer ' + self.token + ":" + str(user_id)} headers = {'Authorization': 'Bearer ' + self.token + ":" + str(user_id)}
req = s.post(self.db_adress + "/share", json={"comment": comment, "isin": isin}, headers=headers) # set share by setting comment and isin, comment can be the real name of the share e.g. "Apple Inc." req = s.post(self.db_adress + "/share", json={"comment": comment, "isin": isin},
headers=headers) # set share by setting comment and isin, comment can be the real name of the share e.g. "Apple Inc."
return req.status_code return req.status_code
def delete_share(self, user_id, isin): def delete_share(self, user_id, isin):
"""deletes the share of the user """deletes the share of the user
@ -280,7 +272,6 @@ class API_Handler:
req = s.delete(self.db_adress + "/share", json={"isin": str(isin)}, headers=headers) # to delete a share only the isin is needed because it is unique, shares are not transactions! req = s.delete(self.db_adress + "/share", json={"isin": str(isin)}, headers=headers) # to delete a share only the isin is needed because it is unique, shares are not transactions!
return req.status_code return req.status_code
def get_user_transactions(self, user_id, max_retries=10): def get_user_transactions(self, user_id, max_retries=10):
"""gets the transactions of the user """gets the transactions of the user
@ -305,8 +296,7 @@ class API_Handler:
transactions_dict = req.json()["data"] transactions_dict = req.json()["data"]
return transactions_dict return transactions_dict
else: else:
return self.get_user_transactions(user_id, max_retries-1) return self.get_user_transactions(user_id, max_retries - 1)
def set_transaction(self, user_id, comment, isin, count, price, time): def set_transaction(self, user_id, comment, isin, count, price, time):
"""sets the transaction of the user """sets the transaction of the user
@ -328,11 +318,11 @@ class API_Handler:
with r.Session() as s: with r.Session() as s:
time = time[:-3] + "Z" # remove last character and add Z to make it a valid date for db time = time[:-3] + "Z" # remove last character and add Z to make it a valid date for db
headers = {'Authorization': 'Bearer ' + self.token + ":" + str(user_id)} headers = {'Authorization': 'Bearer ' + self.token + ":" + str(user_id)}
transaction = {"comment": str(comment), "count": float(count), "isin": str(isin), "price": float(price), "time": str(time)} # set transaction as JSON with all the attributes needed according to Swagger docs transaction = {"comment": str(comment), "count": float(count), "isin": str(isin), "price": float(price),
"time": str(time)} # set transaction as JSON with all the attributes needed according to Swagger docs
req = s.post(self.db_adress + "/transaction", json=transaction, headers=headers) req = s.post(self.db_adress + "/transaction", json=transaction, headers=headers)
return req.status_code return req.status_code
def get_user_portfolio(self, user_id, max_retries=10): def get_user_portfolio(self, user_id, max_retries=10):
"""gets the portfolio of the user """gets the portfolio of the user
@ -356,7 +346,7 @@ class API_Handler:
portfolio_dict = req.json()["data"] # get the data of the JSON portfolio_dict = req.json()["data"] # get the data of the JSON
return portfolio_dict return portfolio_dict
else: else:
return self.get_user_portfolio(user_id, max_retries-1) return self.get_user_portfolio(user_id, max_retries - 1)
def set_cron_interval(self, user_id, cron_interval): def set_cron_interval(self, user_id, cron_interval):
"""sets the cron interval of the user """sets the cron interval of the user
@ -380,7 +370,6 @@ class API_Handler:
req = s.put(self.db_adress + "/user/setCron", json={"cron": str(cron_interval)}, headers=headers) # put not post (see swagger docs) req = s.put(self.db_adress + "/user/setCron", json={"cron": str(cron_interval)}, headers=headers) # put not post (see swagger docs)
return req.status_code return req.status_code
def set_admin(self, email, is_admin): def set_admin(self, email, is_admin):
"""sets the admin of the user """sets the admin of the user
@ -396,7 +385,7 @@ class API_Handler:
""" """
with r.Session() as s: with r.Session() as s:
headers = {'Authorization': 'Bearer ' + self.token} # only bot token is needed, user is chosen by email headers = {'Authorization': 'Bearer ' + self.token} # only bot token is needed, user is chosen by email
req = s.put(self.db_adress + "/user/setAdmin", json={"admin": is_admin,"email": str(email)}, headers=headers) req = s.put(self.db_adress + "/user/setAdmin", json={"admin": is_admin, "email": str(email)}, headers=headers)
return req.status_code return req.status_code
@ -405,11 +394,11 @@ if __name__ == "__main__": # editable, just for basic on the go testing of new f
print("This is a module for the telegram bot. It is not intended to be run directly.") print("This is a module for the telegram bot. It is not intended to be run directly.")
handler = API_Handler("https://gruppe1.testsites.info/api", str(os.getenv("BOT_EMAIL")), str(os.getenv("BOT_PASSWORD"))) # get creds from env handler = API_Handler("https://gruppe1.testsites.info/api", str(os.getenv("BOT_EMAIL")), str(os.getenv("BOT_PASSWORD"))) # get creds from env
print(handler.token) print(handler.token)
keywords = handler.get_user_keywords(user_id = 1709356058) #user_id here is currently mine (Linus) keywords = handler.get_user_keywords(user_id=1709356058) # user_id here is currently mine (Linus)
print(keywords) print(keywords)
shares = handler.get_user_portfolio(user_id = 1709356058) shares = handler.get_user_portfolio(user_id=1709356058)
print("set cron with status: "+ str(handler.set_cron_interval(user_id = 1709356058, cron_interval = "0 0 * * *"))) print("set cron with status: " + str(handler.set_cron_interval(user_id=1709356058, cron_interval="0 0 * * *")))
user = handler.get_user(user_id = 1709356058) user = handler.get_user(user_id=1709356058)
print(user) print(user)
all_users = handler.get_all_users() all_users = handler.get_all_users()
admin_status = handler.set_admin("test@test.com", "true") admin_status = handler.set_admin("test@test.com", "true")

View File

@ -1,4 +1,3 @@
""" """
script for telegram bot and its functions script for telegram bot and its functions
""" """
@ -14,37 +13,34 @@ __license__ = "None"
# API Documentation https://core.telegram.org/bots/api # API Documentation https://core.telegram.org/bots/api
# Code examples https://github.com/eternnoir/pyTelegramBotAPI#getting-started # Code examples https://github.com/eternnoir/pyTelegramBotAPI#getting-started
import datetime as dt
import logging
import os import os
import re
import sys
import telebot import telebot
import sys from dotenv import load_dotenv
import logging from telebot import types
import re
import helper_functions as hf
import news.news_fetcher as news import news.news_fetcher as news
import shares.share_fetcher as share_fetcher import shares.share_fetcher as share_fetcher
import helper_functions as hf
import datetime as dt
from telebot import types
from dotenv import load_dotenv
from api_handling.api_handler import API_Handler from api_handling.api_handler import API_Handler
load_dotenv(dotenv_path='.env') # load environment variables load_dotenv(dotenv_path='.env') # load environment variables
bot_version = "2.0.1" # version of bot bot_version = "2.0.1" # version of bot
#create api handler # create api handler
api_handler = API_Handler("https://gruppe1.testsites.info/api", str(os.getenv("BOT_EMAIL")), str(os.getenv("BOT_PASSWORD"))) # get creds from env vars. api_handler = API_Handler("https://gruppe1.testsites.info/api", str(os.getenv("BOT_EMAIL")), str(os.getenv("BOT_PASSWORD"))) # get creds from env vars.
print("Webserver Token: " + str(api_handler.token)) print("Webserver Token: " + str(api_handler.token))
bot = telebot.TeleBot(os.getenv('BOT_API_KEY')) bot = telebot.TeleBot(os.getenv('BOT_API_KEY'))
@bot.message_handler(commands=['start', 'Start']) @bot.message_handler(commands=['start', 'Start'])
def send_start(message): def send_start(message):
""" Sending welcome message to new user """ Sending welcome message to new user
:type message: message object bot :type message: message object bot
:param message: message that was reacted to, in this case always containing '/start' :param message: message that was reacted to, in this case always containing '/start'
@ -61,7 +57,6 @@ def send_start(message):
@bot.message_handler(commands=['version', 'Version']) @bot.message_handler(commands=['version', 'Version'])
def send_version(message): def send_version(message):
""" Sending programm version """ Sending programm version
:type message: message object bot :type message: message object bot
:param message: message that was reacted to, in this case always containing '/version' :param message: message that was reacted to, in this case always containing '/version'
@ -75,7 +70,6 @@ def send_version(message):
@bot.message_handler(commands=['help', 'Help']) # /help -> sending all functions @bot.message_handler(commands=['help', 'Help']) # /help -> sending all functions
def send_help(message): def send_help(message):
""" Send all functions """ Send all functions
:type message: message object bot :type message: message object bot
:param message: message that was reacted to, in this case always containing '/help' :param message: message that was reacted to, in this case always containing '/help'
@ -84,12 +78,12 @@ def send_help(message):
:rtype: none :rtype: none
""" """
bot.reply_to(message, "/id or /auth get your user id\n/update get updates on your shares.\n/shares get update on interesting shares\n/setAdmin set admin rights of user (ADMIN)\n/users see all users. (ADMIN)\n/me get my user info\n/news get top article for each keyword.\n/allnews get all news (last 7 days)\n/keywords get all your keywords\n/addkeyword add a keyword\n/removekeyword remove a keyword\n/transactions get all transactions\n/newtransaction create new transaction\n/share get price of specific share\n/portfolio see own portfolio\n/removeshare removes share from portfolio\n/interval get update interval\n/setinterval set update interval\n For further details see https://gruppe1.testsites.info") bot.reply_to(message,
"/id or /auth get your user id\n/update get updates on your shares.\n/shares get update on interesting shares\n/setAdmin set admin rights of user (ADMIN)\n/users see all users. (ADMIN)\n/me get my user info\n/news get top article for each keyword.\n/allnews get all news (last 7 days)\n/keywords get all your keywords\n/addkeyword add a keyword\n/removekeyword remove a keyword\n/transactions get all transactions\n/newtransaction create new transaction\n/share get price of specific share\n/portfolio see own portfolio\n/removeshare removes share from portfolio\n/interval get update interval\n/setinterval set update interval\n For further details see https://gruppe1.testsites.info")
@bot.message_handler(commands=['users', 'Users']) # /users -> sending all users @bot.message_handler(commands=['users', 'Users']) # /users -> sending all users
def send_all_users(message): def send_all_users(message):
""" Send all users, only possible for admins """ Send all users, only possible for admins
:type message: message object bot :type message: message object bot
:param message: message that was reacted to, in this case always containing '/users' :param message: message that was reacted to, in this case always containing '/users'
@ -101,7 +95,7 @@ def send_all_users(message):
user_id = int(message.from_user.id) user_id = int(message.from_user.id)
user_data = api_handler.get_user(user_id) user_data = api_handler.get_user(user_id)
if(user_data["admin"] == False): # check if user has admin rights if (user_data["admin"] == False): # check if user has admin rights
bot.reply_to(message, "You have to be an admin to use this command") bot.reply_to(message, "You have to be an admin to use this command")
return return
@ -110,7 +104,6 @@ def send_all_users(message):
bot.send_message(chat_id=user_id, text="There are " + str(user_count) + " users in the database:") bot.send_message(chat_id=user_id, text="There are " + str(user_count) + " users in the database:")
for user in user_list: for user in user_list:
username = user['username'] username = user['username']
email = user['email'] email = user['email']
id = user['telegram_user_id'] id = user['telegram_user_id']
@ -122,7 +115,6 @@ def send_all_users(message):
@bot.message_handler(commands=['setAdmin', 'SetAdmin', 'setadmin', 'Setadmin']) # set admin rights to user TBD: not working!! @bot.message_handler(commands=['setAdmin', 'SetAdmin', 'setadmin', 'Setadmin']) # set admin rights to user TBD: not working!!
def set_admin(message): def set_admin(message):
""" Set admin rights to user """ Set admin rights to user
:type message: message object bot :type message: message object bot
:param message: message that was reacted to, in this case always containing '/setAdmin' :param message: message that was reacted to, in this case always containing '/setAdmin'
@ -134,13 +126,14 @@ def set_admin(message):
user_id = int(message.from_user.id) user_id = int(message.from_user.id)
user_data = api_handler.get_user(user_id) user_data = api_handler.get_user(user_id)
if(user_data["admin"] == False): # check if user has admin rights if (user_data["admin"] == False): # check if user has admin rights
bot.reply_to(message, "You have to be an admin to use this command") bot.reply_to(message, "You have to be an admin to use this command")
return return
bot.send_message(chat_id=user_id, text='send email and true if this account should have admin rights, else false\n in format: <email>,<is_admin>') # request email and admin rights to change to bot.send_message(chat_id=user_id, text='send email and true if this account should have admin rights, else false\n in format: <email>,<is_admin>') # request email and admin rights to change to
bot.register_next_step_handler(message, set_admin_step) bot.register_next_step_handler(message, set_admin_step)
def set_admin_step(message): def set_admin_step(message):
str_message = str(message.text) str_message = str(message.text)
args_message = str_message.split(',') # split message into email and admin rights args_message = str_message.split(',') # split message into email and admin rights
@ -158,7 +151,7 @@ def set_admin_step(message):
status = api_handler.set_admin(email, is_admin) # set admin in db status = api_handler.set_admin(email, is_admin) # set admin in db
if(status == 200): if (status == 200):
bot.reply_to(message, "Admin rights set") bot.reply_to(message, "Admin rights set")
else: else:
@ -190,7 +183,6 @@ def send_user(message):
@bot.message_handler(commands=['id', 'auth', 'Id', 'Auth']) # /auth or /id -> Authentication with user_id over web tool @bot.message_handler(commands=['id', 'auth', 'Id', 'Auth']) # /auth or /id -> Authentication with user_id over web tool
def send_id(message): def send_id(message):
""" Send user id for authentication with browser """ Send user id for authentication with browser
:type message: message object bot :type message: message object bot
:param message: message that was reacted to, in this case always containing '/id' or '/auth' :param message: message that was reacted to, in this case always containing '/id' or '/auth'
@ -203,10 +195,9 @@ def send_id(message):
bot.reply_to(message, answer) bot.reply_to(message, answer)
#function that can be used to ensure that the bot is online and running # function that can be used to ensure that the bot is online and running
@bot.message_handler(commands=['status', 'Status']) @bot.message_handler(commands=['status', 'Status'])
def send_status(message): def send_status(message):
""" Sends status to user """ Sends status to user
:type message: message object bot :type message: message object bot
:param message: message that was reacted to, if no other command handler gets called :param message: message that was reacted to, if no other command handler gets called
@ -220,7 +211,6 @@ def send_status(message):
@bot.message_handler(commands=['update', 'Update']) # /update -> update shares @bot.message_handler(commands=['update', 'Update']) # /update -> update shares
def update_for_user(message): def update_for_user(message):
p_user_id = int(message.from_user.id) p_user_id = int(message.from_user.id)
p_my_handler = api_handler p_my_handler = api_handler
@ -230,13 +220,13 @@ def update_for_user(message):
my_portfolio = p_my_handler.get_user_portfolio(p_user_id) my_portfolio = p_my_handler.get_user_portfolio(p_user_id)
for element in my_portfolio: for element in my_portfolio:
if element["count"] != '' and element["isin"]!= '': if element["count"] != '' and element["isin"] != '':
print(element["count"], element["isin"]) print(element["count"], element["isin"])
share_symbols.append(element["isin"]) share_symbols.append(element["isin"])
share_amounts.append(element["count"]) share_amounts.append(element["count"])
my_user = p_my_handler.get_user(p_user_id) my_user = p_my_handler.get_user(p_user_id)
send_to_user("Hello %s this is your share update:"%str(my_user["username"]), pUser_id=p_user_id) send_to_user("Hello %s this is your share update:" % str(my_user["username"]), pUser_id=p_user_id)
if len(share_symbols) != 0: if len(share_symbols) != 0:
for i in range(len(share_symbols)): for i in range(len(share_symbols)):
@ -248,7 +238,6 @@ def update_for_user(message):
def send_to_user(pText, pUser_id): def send_to_user(pText, pUser_id):
""" Send message to user """ Send message to user
:type pText: string :type pText: string
:param pText: Text to send to user :param pText: Text to send to user
@ -265,7 +254,6 @@ def send_to_user(pText, pUser_id):
@bot.message_handler(commands=['share', 'Share']) # /share -> get share price @bot.message_handler(commands=['share', 'Share']) # /share -> get share price
def send_share_update(message): def send_share_update(message):
""" Send price of a specific share """ Send price of a specific share
:type message: message object bot :type message: message object bot
:param message: message that was reacted to, in this case always containing '/share' :param message: message that was reacted to, in this case always containing '/share'
@ -279,6 +267,7 @@ def send_share_update(message):
bot.send_message(chat_id=user_id, text='Send Symbol/ISIN of share or name of company:') bot.send_message(chat_id=user_id, text='Send Symbol/ISIN of share or name of company:')
bot.register_next_step_handler(message, send_share_price) bot.register_next_step_handler(message, send_share_price)
def send_share_price(message): def send_share_price(message):
str_share_price = share_fetcher.get_share_information_markdown(str(message.text)) str_share_price = share_fetcher.get_share_information_markdown(str(message.text))
bot.reply_to(message, str_share_price, parse_mode="MARKDOWNV2") bot.reply_to(message, str_share_price, parse_mode="MARKDOWNV2")
@ -286,7 +275,6 @@ def send_share_price(message):
@bot.message_handler(commands=['allnews', 'Allnews']) # /allnews -> get all news @bot.message_handler(commands=['allnews', 'Allnews']) # /allnews -> get all news
def send_all_news(message): def send_all_news(message):
""" Get news for keywords of user """ Get news for keywords of user
:type message: message object bot :type message: message object bot
:param message: message that was reacted to, in this case always containing '/allnews' :param message: message that was reacted to, in this case always containing '/allnews'
@ -373,6 +361,7 @@ def add_keyword(message):
bot.send_message(chat_id=user_id, text='Type keyword to add:') bot.send_message(chat_id=user_id, text='Type keyword to add:')
bot.register_next_step_handler(message, store_keyword) # wait for user to send keyword, then call store_keyword function bot.register_next_step_handler(message, store_keyword) # wait for user to send keyword, then call store_keyword function
def store_keyword(message): def store_keyword(message):
user_id = int(message.from_user.id) user_id = int(message.from_user.id)
keyword = str(message.text).lower() # lower to ensure Bitcoin and bitcoin is not stored as individual keywords keyword = str(message.text).lower() # lower to ensure Bitcoin and bitcoin is not stored as individual keywords
@ -397,6 +386,7 @@ def remove_keyword(message):
bot.send_message(chat_id=user_id, text='Type keyword to remove:') bot.send_message(chat_id=user_id, text='Type keyword to remove:')
bot.register_next_step_handler(message, remove_keyword_step) # wait for user to send keyword to remove, then call remove_keyword_step function bot.register_next_step_handler(message, remove_keyword_step) # wait for user to send keyword to remove, then call remove_keyword_step function
def remove_keyword_step(message): def remove_keyword_step(message):
user_id = int(message.from_user.id) user_id = int(message.from_user.id)
keyword = str(message.text).lower() keyword = str(message.text).lower()
@ -492,7 +482,7 @@ def remove_share_step(message):
bot.send_message(chat_id=user_id, text=f'Failed deleting share "{isin}". (statuscode {status})\nMake sure that the share is in your portfolio and written exactly like there.') bot.send_message(chat_id=user_id, text=f'Failed deleting share "{isin}". (statuscode {status})\nMake sure that the share is in your portfolio and written exactly like there.')
@bot.message_handler(commands=['newtransaction', 'Newtransaction']) #tbd not working rn may be deleted in future @bot.message_handler(commands=['newtransaction', 'Newtransaction']) # tbd not working rn may be deleted in future
def set_new_transaction(message): def set_new_transaction(message):
""" Set new transaction for user """ Set new transaction for user
:type message: message object bot :type message: message object bot
@ -503,7 +493,8 @@ def set_new_transaction(message):
:rtype: none :rtype: none
""" """
user_id = int(message.from_user.id) user_id = int(message.from_user.id)
bot.send_message(chat_id=user_id, text='Type "<name of stock>,<isin/name/symbol>,<amount>,<price_per_stock_usd>" (time of transaction will be set to now, negative amount is selling, positive is buying):') bot.send_message(chat_id=user_id,
text='Type "<name of stock>,<isin/name/symbol>,<amount>,<price_per_stock_usd>" (time of transaction will be set to now, negative amount is selling, positive is buying):')
bot.register_next_step_handler(message, set_new_transaction_step) bot.register_next_step_handler(message, set_new_transaction_step)
@ -609,7 +600,6 @@ def send_shares(message):
bot.send_message(chat_id=user_id, text=share_fetcher.get_share_information_markdown(element), parse_mode="MARKDOWNV2") bot.send_message(chat_id=user_id, text=share_fetcher.get_share_information_markdown(element), parse_mode="MARKDOWNV2")
@bot.message_handler(commands=['setinterval', 'Setinterval']) @bot.message_handler(commands=['setinterval', 'Setinterval'])
def set_new_interval(message): def set_new_interval(message):
""" Set new interval for user """ Set new interval for user
@ -624,8 +614,8 @@ def set_new_interval(message):
bot.send_message(chat_id=user_id, text='Type interval in cron format:\n(https://crontab.guru/)') bot.send_message(chat_id=user_id, text='Type interval in cron format:\n(https://crontab.guru/)')
bot.register_next_step_handler(message, set_new_interval_step) # executes function when user sends message bot.register_next_step_handler(message, set_new_interval_step) # executes function when user sends message
def set_new_interval_step(message):
def set_new_interval_step(message):
user_id = int(message.from_user.id) user_id = int(message.from_user.id)
interval = str(message.text) interval = str(message.text)
status = api_handler.set_cron_interval(user_id, interval) # send cron to db status = api_handler.set_cron_interval(user_id, interval) # send cron to db
@ -643,7 +633,6 @@ def set_new_interval_step(message):
@bot.message_handler(func=lambda message: True) # Returning that command is unknown for any other statement @bot.message_handler(func=lambda message: True) # Returning that command is unknown for any other statement
def echo_all(message): def echo_all(message):
""" Tell that command is not known if it is no known command """ Tell that command is not known if it is no known command
:type message: message object bot :type message: message object bot
:param message: message that was reacted to, if no other command handler gets called :param message: message that was reacted to, if no other command handler gets called
@ -661,7 +650,6 @@ telebot.logger.setLevel(logging.DEBUG)
@bot.inline_handler(lambda query: query.query == 'text') # inline prints for debugging @bot.inline_handler(lambda query: query.query == 'text') # inline prints for debugging
def query_text(inline_query): def query_text(inline_query):
""" Output in the console about current user actions and status of bot """ Output in the console about current user actions and status of bot
:type inline_query: :type inline_query:
:param inline_query: :param inline_query:
@ -679,7 +667,6 @@ def query_text(inline_query):
def main_loop(): def main_loop():
""" Start bot """ Start bot
:raises: none :raises: none
@ -687,6 +674,7 @@ def main_loop():
""" """
bot.infinity_polling() bot.infinity_polling()
if __name__ == '__main__': if __name__ == '__main__':
try: try:
main_loop() main_loop()

View File

@ -6,17 +6,18 @@ __date__ = "10.05.2022"
__version__ = "1.0.2" __version__ = "1.0.2"
__license__ = "None" __license__ = "None"
from dotenv import load_dotenv
import news.news_fetcher as news_fetcher
import time
import os import os
from bot import bot
import sys import sys
from apscheduler.schedulers.background import BackgroundScheduler import time
from api_handling.api_handler import API_Handler
import shares.share_fetcher as share_fetcher
import helper_functions as hf
from apscheduler.schedulers.background import BackgroundScheduler
from dotenv import load_dotenv
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 * * * * * code
@ -35,6 +36,7 @@ user_crontab = []
load_dotenv(dotenv_path='.env') load_dotenv(dotenv_path='.env')
def start_updater(): def start_updater():
""" starting function for regularly sending updates """ starting function for regularly sending updates
:raises: none :raises: none
@ -46,7 +48,6 @@ def start_updater():
my_handler = API_Handler("https://gruppe1.testsites.info/api", str(os.getenv("BOT_EMAIL")), str(os.getenv("BOT_PASSWORD"))) my_handler = API_Handler("https://gruppe1.testsites.info/api", str(os.getenv("BOT_EMAIL")), str(os.getenv("BOT_PASSWORD")))
update_crontab(my_handler) update_crontab(my_handler)
@ -76,8 +77,8 @@ def update_crontab(p_my_handler):
user_crontab.append(str(element["cron"])) user_crontab.append(str(element["cron"]))
except: except:
user_ids.pop() user_ids.pop()
except: continue except:
continue
print(user_ids) print(user_ids)
@ -87,7 +88,6 @@ def update_crontab(p_my_handler):
def update_based_on_crontab(p_user_ids, p_user_crontab, p_my_handler): 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 """ Check all the crontab codes and add jobs to start in time
:type p_user_ids: array :type p_user_ids: array
:param p_user_ids: user id array of all users :param p_user_ids: user id array of all users
@ -108,15 +108,15 @@ def update_based_on_crontab(p_user_ids, p_user_crontab, p_my_handler):
for i in range(len(p_user_ids)): for i in range(len(p_user_ids)):
cron_split = p_user_crontab[i].split(" ") cron_split = p_user_crontab[i].split(" ")
print(cron_split[4], cron_split[1], cron_split[0], cron_split[3], cron_split[2]) print(cron_split[4], cron_split[1], cron_split[0], cron_split[3], cron_split[2])
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.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() my_scheduler.start()
time.sleep( 600 ) time.sleep(600)
my_scheduler.shutdown() my_scheduler.shutdown()
def update_for_user(p_user_id, p_my_handler):
def update_for_user(p_user_id, p_my_handler):
""" Pull shares and send updates for specific user id """ Pull shares and send updates for specific user id
:type p_user_id: integer :type p_user_id: integer
:param p_user_id: user id of user that shall receive update :param p_user_id: user id of user that shall receive update
@ -135,13 +135,13 @@ def update_for_user(p_user_id, p_my_handler):
my_portfolio = p_my_handler.get_user_portfolio(p_user_id) my_portfolio = p_my_handler.get_user_portfolio(p_user_id)
for element in my_portfolio: for element in my_portfolio:
if element["count"] != '' and element["isin"]!= '': if element["count"] != '' and element["isin"] != '':
print(element["count"], element["isin"]) print(element["count"], element["isin"])
share_symbols.append(element["isin"]) share_symbols.append(element["isin"])
share_amounts.append(element["count"]) share_amounts.append(element["count"])
my_user = p_my_handler.get_user(p_user_id) my_user = p_my_handler.get_user(p_user_id)
send_to_user("Hello %s this is your share update for today:"%str(my_user["username"]), pUser_id=p_user_id) send_to_user("Hello %s this is your share update for today:" % str(my_user["username"]), pUser_id=p_user_id)
shares = p_my_handler.get_user_shares(p_user_id) shares = p_my_handler.get_user_shares(p_user_id)
@ -153,16 +153,14 @@ def update_for_user(p_user_id, p_my_handler):
else: else:
send_to_user("No shares found for your account. Check https://gruppe1.testsites.info to change your settings and add shares.", pUser_id=p_user_id) send_to_user("No shares found for your account. Check https://gruppe1.testsites.info to change your settings and add shares.", pUser_id=p_user_id)
if len(shares) != 0: # Send updates on watchlist shares if existing
if len(shares)!=0: # Send updates on watchlist shares if existing
send_to_user("Your watchlist shares:", pUser_id=p_user_id) send_to_user("Your watchlist shares:", pUser_id=p_user_id)
for element in shares: for element in shares:
send_to_user(share_fetcher.get_share_information_markdown(element), pUser_id=p_user_id, md_mode=True) send_to_user(share_fetcher.get_share_information_markdown(element), pUser_id=p_user_id, md_mode=True)
keywords = p_my_handler.get_user_keywords(p_user_id) # get keywords as array keywords = p_my_handler.get_user_keywords(p_user_id) # get keywords as array
if(keywords): # if keywords exist and array is not empty 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) 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: for keyword in keywords:
news = news_fetcher.get_top_news_by_keyword(keyword)["articles"] news = news_fetcher.get_top_news_by_keyword(keyword)["articles"]
@ -178,9 +176,7 @@ def update_for_user(p_user_id, p_my_handler):
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 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
def send_to_user(pText, pUser_id, md_mode=False):
def send_to_user(pText, pUser_id , md_mode = False):
""" Send message to user """ Send message to user
:type pText: string :type pText: string
:param pText: Text to send to user :param pText: Text to send to user
@ -201,7 +197,6 @@ def send_to_user(pText, pUser_id , md_mode = False):
bot.send_message(chat_id=pUser_id, text=pText) bot.send_message(chat_id=pUser_id, text=pText)
if __name__ == "__main__": if __name__ == "__main__":
try: try:
start_updater() start_updater()

View File

@ -6,6 +6,7 @@ __date__ = "10.05.2022"
__version__ = "1.0.0" __version__ = "1.0.0"
__license__ = "None" __license__ = "None"
def contains_markdownv1_symbols(text): def contains_markdownv1_symbols(text):
""" checks if text contains markdown symbols """ checks if text contains markdown symbols
:type text: string :type text: string
@ -57,7 +58,6 @@ def make_markdown_proof(text): # used to avoid errors related to markdown parsem
text = text.replace("$", "\\$") text = text.replace("$", "\\$")
text = text.replace("%", "\\%") text = text.replace("%", "\\%")
return text return text

View File

@ -6,14 +6,13 @@ __date__ = "26.04.2022"
__version__ = "1.0.0" __version__ = "1.0.0"
__license__ = "None" __license__ = "None"
import sys
import os import os
import requests import sys
import helper_functions as hf import helper_functions as hf
import requests
from newsapi import NewsApiClient
from dotenv import load_dotenv from dotenv import load_dotenv
from newsapi import NewsApiClient
load_dotenv() # loads environment vars load_dotenv() # loads environment vars
@ -29,7 +28,8 @@ try:
except KeyError: except KeyError:
print("Error: Could not get sources, may be blocked because of too many requests (free newsapi is limited to 100 reqs per day)") print("Error: Could not get sources, may be blocked because of too many requests (free newsapi is limited to 100 reqs per day)")
str_sources = str("Reuters, bbc, cnn, fox-news, google-news, hacker-news, nytimes, the-huffington-post, the-new-york-times, business-insider, bbc-news, cbc-news, ESPN, fox-sports, google-news-uk, independent, the-wall-street-journal, the-washington-times, time, usa-today") str_sources = str(
"Reuters, bbc, cnn, fox-news, google-news, hacker-news, nytimes, the-huffington-post, the-new-york-times, business-insider, bbc-news, cbc-news, ESPN, fox-sports, google-news-uk, independent, the-wall-street-journal, the-washington-times, time, usa-today")
def get_all_news_by_keyword(keyword, from_date="2000-01-01"): def get_all_news_by_keyword(keyword, from_date="2000-01-01"):
@ -42,7 +42,7 @@ def get_all_news_by_keyword(keyword, from_date="2000-01-01"):
JSON/dict: dict containing articles JSON/dict: dict containing articles
""" """
top_headlines = newsapi.get_everything(q=keyword, sources=str_sources, language='en', from_param=from_date) # keywords can be combined with OR (e.g. keyword = "bitcoin OR ethereum") top_headlines = newsapi.get_everything(q=keyword, sources=str_sources, language='en', from_param=from_date) # keywords can be combined with OR (e.g. keyword = "bitcoin OR ethereum")
if(top_headlines["status"] == "ok"): if (top_headlines["status"] == "ok"):
return top_headlines return top_headlines
else: else:
return None return None
@ -57,7 +57,7 @@ def get_top_news_by_keyword(keyword):
JSON/dict: dict containing articles JSON/dict: dict containing articles
""" """
top_headlines = newsapi.get_top_headlines(q=keyword, sources=str_sources, language='en') # get top headlines, measured by popularity from NewsApi top_headlines = newsapi.get_top_headlines(q=keyword, sources=str_sources, language='en') # get top headlines, measured by popularity from NewsApi
if(top_headlines["status"] == "ok"): if (top_headlines["status"] == "ok"):
return top_headlines return top_headlines
else: else:
return None return None

View File

@ -6,10 +6,11 @@ __date__ = "10.05.2022"
__version__ = "1.0.1" __version__ = "1.0.1"
__license__ = "None" __license__ = "None"
import helper_functions as hf
import investpy import investpy
import pandas import pandas
from currency_converter import CurrencyConverter from currency_converter import CurrencyConverter
import helper_functions as hf
def get_share_price(str_search_for): def get_share_price(str_search_for):
"""get stock price per share for company name or isin or symbol """get stock price per share for company name or isin or symbol
@ -30,7 +31,7 @@ def get_share_price(str_search_for):
stock_price = round(float(stock_price), 2) stock_price = round(float(stock_price), 2)
str_return =str(stock_price) + " " + str(currency) str_return = str(stock_price) + " " + str(currency)
return str_return return str_return
@ -50,13 +51,14 @@ def get_share_price(str_search_for):
stock_price = round(float(stock_price), 2) stock_price = round(float(stock_price), 2)
str_return =str(stock_price) + " EUR" str_return = str(stock_price) + " EUR"
return str_return return str_return
except RuntimeError: except RuntimeError:
return "None" return "None"
def get_share_price_no_currency(str_search_for): def get_share_price_no_currency(str_search_for):
"""get stock price per share for company name or isin or symbol no currency """get stock price per share for company name or isin or symbol no currency
Args: Args:
@ -67,7 +69,6 @@ def get_share_price_no_currency(str_search_for):
search_result = investpy.search_quotes(text=str_search_for, products=['stocks'], search_result = investpy.search_quotes(text=str_search_for, products=['stocks'],
countries=['germany'], n_results=1) countries=['germany'], n_results=1)
recent_data = pandas.DataFrame(search_result.retrieve_recent_data()) recent_data = pandas.DataFrame(search_result.retrieve_recent_data())
stock_price = recent_data.iloc[-1]["Close"] stock_price = recent_data.iloc[-1]["Close"]
@ -91,10 +92,11 @@ def get_share_price_no_currency(str_search_for):
stock_price = round(float(stock_price), 2) stock_price = round(float(stock_price), 2)
str_return =str(stock_price) str_return = str(stock_price)
return str_return return str_return
def get_share_information(str_search_for): def get_share_information(str_search_for):
search_result = investpy.search_quotes(text=str_search_for, products=['stocks'], search_result = investpy.search_quotes(text=str_search_for, products=['stocks'],
countries=['germany'], n_results=1) countries=['germany'], n_results=1)
@ -103,6 +105,7 @@ def get_share_information(str_search_for):
return str_return return str_return
def get_share_information_markdown(str_search_for): def get_share_information_markdown(str_search_for):
search_result = investpy.search_quotes(text=str_search_for, products=['stocks'], search_result = investpy.search_quotes(text=str_search_for, products=['stocks'],
countries=['germany'], n_results=1) countries=['germany'], n_results=1)
@ -110,12 +113,14 @@ def get_share_information_markdown(str_search_for):
str_return = f'*{hf.make_markdown_proof(search_result.name)}*\n_{hf.make_markdown_proof(search_result.symbol)}_\nworth: {hf.make_markdown_proof(get_share_price(str_search_for))}' str_return = f'*{hf.make_markdown_proof(search_result.name)}*\n_{hf.make_markdown_proof(search_result.symbol)}_\nworth: {hf.make_markdown_proof(get_share_price(str_search_for))}'
return str_return return str_return
def get_share_information_simple(str_search_for): def get_share_information_simple(str_search_for):
search_result = investpy.search_quotes(text=str_search_for, products=['stocks'], search_result = investpy.search_quotes(text=str_search_for, products=['stocks'],
countries=['germany'], n_results=1) countries=['germany'], n_results=1)
str_return = search_result.name + "\n" +search_result.symbol + "\nworth: " + get_share_price(str_search_for) str_return = search_result.name + "\n" + search_result.symbol + "\nworth: " + get_share_price(str_search_for)
return str_return return str_return
if __name__ == "__main__": if __name__ == "__main__":
print("None") print("None")