Bot features #7
12
.drone.yml
12
.drone.yml
@ -25,6 +25,10 @@ steps:
|
|||||||
repo:
|
repo:
|
||||||
from_secret: repo_webservice
|
from_secret: repo_webservice
|
||||||
dockerfile: webservice/Dockerfile
|
dockerfile: webservice/Dockerfile
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
include:
|
||||||
|
- main
|
||||||
|
|
||||||
- name: publish_bot
|
- name: publish_bot
|
||||||
image: plugins/docker
|
image: plugins/docker
|
||||||
@ -38,6 +42,10 @@ steps:
|
|||||||
repo:
|
repo:
|
||||||
from_secret: repo_bot
|
from_secret: repo_bot
|
||||||
dockerfile: telegram_bot/Dockerfile
|
dockerfile: telegram_bot/Dockerfile
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
include:
|
||||||
|
- main
|
||||||
|
|
||||||
- name: deploy
|
- name: deploy
|
||||||
image: appleboy/drone-ssh
|
image: appleboy/drone-ssh
|
||||||
@ -58,3 +66,7 @@ steps:
|
|||||||
PLUGIN_PASSWORD:
|
PLUGIN_PASSWORD:
|
||||||
from_secret: ssh_password
|
from_secret: ssh_password
|
||||||
PLUGIN_SCRIPT: /opt/docker/TelegramAktienBot/deploy.sh
|
PLUGIN_SCRIPT: /opt/docker/TelegramAktienBot/deploy.sh
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
include:
|
||||||
|
- main
|
||||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,6 +1,8 @@
|
|||||||
.idea/*
|
.idea/*
|
||||||
.env
|
.env
|
||||||
|
.env.example
|
||||||
env
|
env
|
||||||
__pycache__/*
|
Lib
|
||||||
telegram_bot/__pycache__/*
|
Include
|
||||||
telegram_bot/news/__pycache__/*
|
*/*/__pycache__/*
|
||||||
|
*/__pycache__/*
|
@ -19,6 +19,8 @@ WebEngineering2 Projekt: Aktien und News Bot für Telegram
|
|||||||
- Datenbank -> database/*
|
- Datenbank -> database/*
|
||||||
|
|
||||||
## Local setup for telegram bot
|
## Local setup for telegram bot
|
||||||
1. create .env and set API keys etc. (use .env.example as a layout)
|
0. optional: build virtual env by ``python -m venv venv``
|
||||||
2. install required libs via ``pip install -r ./telegram_bot/requirements.txt``
|
``env/Scripts/activate``
|
||||||
3. run bot.py via ``python ./telegram_bot/bot.py``
|
2. create .env and set API keys etc. (use .env.example as a layout)
|
||||||
|
3. install required libs via ``pip install -r ./telegram_bot/requirements.txt``
|
||||||
|
4. run bot.py via ``python ./telegram_bot/bot.py``
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
FROM python:3.10-alpine
|
FROM python:3.10-slim
|
||||||
|
|
||||||
WORKDIR /srv/flask_app
|
WORKDIR /srv/flask_app
|
||||||
RUN apk add build-base jpeg-dev zlib-dev musl-dev linux-headers g++
|
|
||||||
|
|
||||||
COPY telegram_bot/requirements.txt /srv/flask_app/
|
COPY telegram_bot/requirements.txt /srv/flask_app/
|
||||||
|
|
||||||
|
7
telegram_bot/api_handler.py
Normal file
7
telegram_bot/api_handler.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
"""
|
||||||
|
script for communicating with webservice to get data from database
|
||||||
|
"""
|
||||||
|
__author__ = "Florian Kellermann, Linus Eickhoff"
|
||||||
|
__date__ = "16.03.2022"
|
||||||
|
__version__ = "0.0.1"
|
||||||
|
__license__ = "None"
|
@ -20,17 +20,22 @@ import telebot
|
|||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
import logging
|
import logging
|
||||||
|
import json
|
||||||
|
|
||||||
import news.news_fetcher as news
|
import news.news_fetcher as news
|
||||||
|
<<<<<<< HEAD
|
||||||
import share_fetcher
|
import share_fetcher
|
||||||
|
=======
|
||||||
|
import shares.share_fetcher as share_fetcher
|
||||||
|
>>>>>>> 2961bbb4294b603c694edd0bf0ec74661641b833
|
||||||
|
|
||||||
from telebot import types
|
from telebot import types
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from telegram_bot.share_fetcher import Share_Handler
|
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
bot_version = "0.1.1"
|
bot_version = "0.2.1"
|
||||||
user_list = []
|
user_list = []
|
||||||
|
|
||||||
class User: # Currently saving users in this class to test functionality -> later database
|
class User: # Currently saving users in this class to test functionality -> later database
|
||||||
@ -107,7 +112,7 @@ def send_welcome(message):
|
|||||||
|
|
||||||
:rtype: none
|
:rtype: none
|
||||||
"""
|
"""
|
||||||
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. For further details see aktienbot.flokaiser.com")
|
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")
|
||||||
|
|
||||||
|
|
||||||
@bot.message_handler(commands=['users'])
|
@bot.message_handler(commands=['users'])
|
||||||
@ -148,7 +153,7 @@ def send_id(message):
|
|||||||
bot.reply_to(message, answer)
|
bot.reply_to(message, answer)
|
||||||
|
|
||||||
|
|
||||||
@bot.message_handler(commands=['update']) # /update -> send static update via user_id to this user, later fetch from database
|
@bot.message_handler(commands=['update'])
|
||||||
def send_update(message):
|
def send_update(message):
|
||||||
|
|
||||||
""" Send update on shares
|
""" Send update on shares
|
||||||
@ -161,11 +166,52 @@ def send_update(message):
|
|||||||
"""
|
"""
|
||||||
user_id = int(message.from_user.id)
|
user_id = int(message.from_user.id)
|
||||||
|
|
||||||
share_fetcher = Share_Handler()
|
#Can be deleted when getting from database
|
||||||
|
dirname = os.path.dirname(__file__)
|
||||||
|
json_path = os.path.join(dirname, 'shares/shares_example.json')
|
||||||
|
|
||||||
|
with open(json_path) as json_file:
|
||||||
|
json_share_data = json.load(json_file)
|
||||||
|
int_share_count = int(json_share_data['share_count'])
|
||||||
|
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:')
|
||||||
|
|
||||||
|
|
||||||
|
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}\nPrice: {my_share_course}\nBought 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)
|
||||||
|
|
||||||
|
|
||||||
|
@bot.message_handler(commands=['share'])
|
||||||
|
def send_share_update(message):
|
||||||
|
|
||||||
|
""" 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)
|
||||||
|
|
||||||
#Get Information for user with this id
|
#Get Information for user with this id
|
||||||
#call Share_Handler
|
bot.send_message(chat_id=user_id, text='Send symbol of share:')
|
||||||
bot.send_message(chat_id=user_id, text='This is your update')
|
#str_share_price = shares.wait_for_share.main_loop(bot)
|
||||||
|
bot.register_next_step_handler(message, send_share_price)
|
||||||
|
|
||||||
|
def send_share_price(message):
|
||||||
|
str_share_price = share_fetcher.get_share_price(str(message.text))
|
||||||
|
bot.reply_to(message, str_share_price)
|
||||||
|
|
||||||
|
|
||||||
@bot.message_handler(commands=['news'])
|
@bot.message_handler(commands=['news'])
|
||||||
@ -180,7 +226,7 @@ def send_news(message):
|
|||||||
:rtype: none
|
:rtype: none
|
||||||
"""
|
"""
|
||||||
|
|
||||||
keyword = "business"
|
keyword = "bitcoin"
|
||||||
user_id = int(message.from_user.id)
|
user_id = int(message.from_user.id)
|
||||||
#Get Information for user with this id
|
#Get Information for user with this id
|
||||||
|
|
||||||
|
@ -9,8 +9,7 @@ __license__ = "None"
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
import requests
|
||||||
import pandas as pd
|
|
||||||
|
|
||||||
from newsapi import NewsApiClient
|
from newsapi import NewsApiClient
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
@ -18,11 +17,12 @@ from dotenv import load_dotenv
|
|||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
# Init
|
# Init
|
||||||
newsapi = NewsApiClient(api_key=os.getenv('NEWS_API_KEY'))
|
api_key = os.getenv('NEWS_API_KEY')
|
||||||
|
newsapi = NewsApiClient(api_key=api_key)
|
||||||
|
source_json = requests.get(f"https://newsapi.org/v2/top-headlines/sources?apiKey={api_key}&language=en").json()
|
||||||
# /v2/top-headlines/sources
|
sources = source_json["sources"]
|
||||||
sources = newsapi.get_sources()
|
str_sources = ",".join([source["id"] for source in sources])
|
||||||
|
|
||||||
|
|
||||||
def get_top_news_by_keyword(keyword):
|
def get_top_news_by_keyword(keyword):
|
||||||
"""get top news to keyword
|
"""get top news to keyword
|
||||||
@ -32,7 +32,7 @@ def get_top_news_by_keyword(keyword):
|
|||||||
Returns:
|
Returns:
|
||||||
JSON/dict: dict containing articles
|
JSON/dict: dict containing articles
|
||||||
"""
|
"""
|
||||||
top_headlines = newsapi.get_top_headlines(q=keyword, sources='bbc-news,the-verge,cnn', language='en')
|
top_headlines = newsapi.get_top_headlines(q=keyword, sources=str_sources, language='en')
|
||||||
return top_headlines
|
return top_headlines
|
||||||
|
|
||||||
def format_article(article):
|
def format_article(article):
|
||||||
@ -55,6 +55,6 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
print("fetching top news by keyword business...")
|
print("fetching top news by keyword business...")
|
||||||
|
|
||||||
articles = get_top_news_by_keyword("business")
|
articles = get_top_news_by_keyword("bitcoin")
|
||||||
formatted_article = format_article(articles["articles"][0])
|
formatted_article = format_article(articles["articles"][0])
|
||||||
print(formatted_article)
|
print(formatted_article)
|
@ -1,8 +1,6 @@
|
|||||||
pyTelegramBotAPI~=4.4.0
|
pyTelegramBotAPI~=4.4.0
|
||||||
beautifulsoup4==4.10.0
|
Markdown~=3.3.6
|
||||||
Markdown==3.3.6
|
yfinance~=0.1.70
|
||||||
Pillow==9.0.1
|
newsapi-python~=0.2.6
|
||||||
yfinance==0.1.70
|
|
||||||
newsapi-python
|
|
||||||
pandas~=1.4.1
|
|
||||||
python-dotenv~=0.19.2
|
python-dotenv~=0.19.2
|
||||||
|
requests~=2.27.1
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
"""
|
|
||||||
script for share fetching (by symbols (e.g. AAPL, TSLA etc.))
|
|
||||||
"""
|
|
||||||
__author__ = "Florian Kellermann, Linus Eickhoff"
|
|
||||||
__date__ = "15.03.2022"
|
|
||||||
__version__ = "0.0.2"
|
|
||||||
__license__ = "None"
|
|
||||||
|
|
||||||
import yfinance
|
|
||||||
|
|
||||||
# S3W03GQH43I8O6IG
|
|
||||||
|
|
||||||
class Share_Handler:
|
|
||||||
def __init__(self):
|
|
||||||
return
|
|
||||||
|
|
||||||
def all_share_prices_for_user(self, int_user_id):
|
|
||||||
|
|
||||||
""" Get all share prices for a certain user with his id
|
|
||||||
:type int_user_id: integer
|
|
||||||
:param int_user_id: user_id to get all share prices for
|
|
||||||
|
|
||||||
:raises: none
|
|
||||||
|
|
||||||
:rtype: ###tbd### (maybe dictonary)
|
|
||||||
"""
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def get_share_price(self, str_symbol):
|
|
||||||
|
|
||||||
""" get current share price for a certain symbol
|
|
||||||
:type str_symbol: string
|
|
||||||
:param str_symbol: share symbol to get price for
|
|
||||||
|
|
||||||
:raises:
|
|
||||||
|
|
||||||
:rtype:
|
|
||||||
"""
|
|
||||||
|
|
||||||
my_share_info = yfinance.Ticker(str_symbol)
|
|
||||||
my_share_data = my_share_info.info
|
|
||||||
my_return_string = f'{my_share_data["regularMarketPrice"]} {my_share_data["currency"]}'
|
|
||||||
return my_return_string
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
""" test object and get share price
|
|
||||||
:raises: none
|
|
||||||
|
|
||||||
:rtype: none
|
|
||||||
"""
|
|
||||||
|
|
||||||
new_handler = Share_Handler()
|
|
||||||
print(new_handler.get_share_price("TL0.DE"))
|
|
27
telegram_bot/shares/share_fetcher.py
Normal file
27
telegram_bot/shares/share_fetcher.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
"""
|
||||||
|
script for share fetching (by symbols (e.g. AAPL, TSLA etc.))
|
||||||
|
"""
|
||||||
|
__author__ = "Florian Kellermann, Linus Eickhoff"
|
||||||
|
__date__ = "15.03.2022"
|
||||||
|
__version__ = "0.0.2"
|
||||||
|
__license__ = "None"
|
||||||
|
|
||||||
|
import yfinance
|
||||||
|
import json
|
||||||
|
|
||||||
|
def get_share_price(str_symbol):
|
||||||
|
|
||||||
|
""" get current share price for a certain symbol
|
||||||
|
:type str_symbol: string
|
||||||
|
:param str_symbol: share symbol to get price for
|
||||||
|
|
||||||
|
:raises:
|
||||||
|
|
||||||
|
:rtype:
|
||||||
|
"""
|
||||||
|
|
||||||
|
my_share_info = yfinance.Ticker(str_symbol)
|
||||||
|
my_share_data = my_share_info.info
|
||||||
|
#my_return_string = f'{my_share_data["regularMarketPrice"]} {my_share_data["currency"]}'
|
||||||
|
my_return_string = f'{my_share_data["regularMarketPrice"]}'
|
||||||
|
return my_return_string
|
16
telegram_bot/shares/shares_example.json
Normal file
16
telegram_bot/shares/shares_example.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"user": "FloKell",
|
||||||
|
"share_count": 2,
|
||||||
|
"shares": [
|
||||||
|
{
|
||||||
|
"symbol": "APC.DE",
|
||||||
|
"price_bought": "50.06",
|
||||||
|
"amount_bought": "5.1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"symbol": "TL0.DE",
|
||||||
|
"price_bought": "450.06",
|
||||||
|
"amount_bought": "5.13"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user