From ee9054c1150208300327bdd21442519c8c4496fd Mon Sep 17 00:00:00 2001 From: MuslemRahimi Date: Mon, 3 Feb 2025 11:06:34 +0100 Subject: [PATCH] update price alert --- app/cron_price_alert.py | 168 ++++++++++++++-------------------------- app/test.py | 8 +- 2 files changed, 62 insertions(+), 114 deletions(-) diff --git a/app/cron_price_alert.py b/app/cron_price_alert.py index d37d89c..595ace1 100755 --- a/app/cron_price_alert.py +++ b/app/cron_price_alert.py @@ -13,142 +13,88 @@ import pytz import pandas as pd import numpy as np - -import smtplib -from email.mime.multipart import MIMEMultipart -from email.mime.text import MIMEText -import boto3 -from botocore.exceptions import NoCredentialsError -from bs4 import BeautifulSoup +import requests from dotenv import load_dotenv import os load_dotenv() api_key = os.getenv('FMP_API_KEY') +stocknear_api_key = os.getenv('STOCKNEAR_API_KEY') + pb_admin_email = os.getenv('POCKETBASE_ADMIN_EMAIL') pb_password = os.getenv('POCKETBASE_PASSWORD') -aws_access_key_id = os.getenv('AWS_ACCESS_KEY_ID') -aws_secret_access_key = os.getenv('AWS_SECRET_ACCESS_KEY') berlin_tz = pytz.timezone('Europe/Berlin') pb = PocketBase('http://127.0.0.1:8090') admin_data = pb.collection('_superusers').auth_with_password(pb_admin_email, pb_password) +# Define the URL and the API key +origin = "https://stocknear.com" #"http://localhost:5173" +url = f"{origin}/api/sendPushSubscription" -#Send price alert via email -def send_email(recipient, symbol, asset_type, current_price,target_price, condition): - # Replace the placeholders with your AWS SES credentials - region_name = 'eu-north-1' #email-smtp.eu-north-1.amazonaws.com - - # Replace the placeholders with your sender email and password - sender_email = 'mrahimi@stocknear.com' - - to_email = recipient # user email address - subject = f'Price Alert triggered for ${symbol}' - - # Read the index.html file - with open('html_template/price_alert.html', 'r') as file: - html_content = file.read() - - # Parse the HTML content - soup = BeautifulSoup(html_content, 'html.parser') - - # Extract the body element - html_body = str(soup.body) - # Get the current date - current_date = datetime.now() - # Define the format string - date_format = "%A - %B %d, %Y" - # Format the date - formatted_date = current_date.strftime(date_format) +headers = {"Content-Type": "application/json"} - if asset_type == 'stock': - asset_type = 'stocks' - elif asset_type == 'etf': - asset_type = 'etf' - elif asset_type == 'crypto': - asset_type = 'crypto' +async def push_notification(symbol, user_id): + data = { + "title": f"Price Alert for {symbol} got triggered", + "body": "", + "url": f"{origin}/notifications", + "userId": user_id, + "key": stocknear_api_key, + } - html_body = html_body.replace('currentDate', formatted_date) - html_body = html_body.replace('addingSentence', f'The price of ${current_price} is at/{condition} your target price of ${target_price}') - html_body = html_body.replace('symbol', symbol) - html_body = html_body.replace('asset-link', f'{asset_type}/{symbol}') - - # Create a MIMEMultipart object - message = MIMEMultipart('alternative') - message['Subject'] = subject - message['From'] = sender_email - message['To'] = to_email - - #Preheader text - preheader = MIMEText("This is a price alert notification.", 'plain') - - message.attach(MIMEText(html_body, 'html')) - - # Use Amazon SES to send the email - ses_client = boto3.client( - 'ses', - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - region_name=region_name - ) - - try: - # Send the email - response = ses_client.send_raw_email( - Source=message['From'], - Destinations=[message['To']], - RawMessage={'Data': message.as_string()}, - ) - print("Email sent successfully!") - except NoCredentialsError: - print("AWS credentials not available") - except Exception as e: - print(f"Error sending email: {e}") + response = requests.post(url, headers=headers, data=json.dumps(data)) async def run(): result = pb.collection("priceAlert").get_full_list(query_params={"filter": 'triggered=false'}) if len(result) != 0: for item in result: - symbol = item.symbol - with open(f"json/quote/{symbol}.json", 'r') as file: - data = ujson.load(file) - current_price = round(data['price'],2) - target_price = round(item.target_price,2) - if (item.condition == 'below') and target_price >= current_price: - #print('below true', symbol, target_price) - pb.collection("priceAlert").update(item.id, {"triggered": True}) + try: + symbol = item.symbol + with open(f"json/quote/{symbol}.json", 'r') as file: + data = ujson.load(file) + current_price = round(data['price'],2) + target_price = round(item.target_price,2) + if (item.condition == 'below') and target_price >= current_price: + #print('below true', symbol, target_price) + pb.collection("priceAlert").update(item.id, {"triggered": True}) + + newNotification = { + 'opUser': item.user, + 'user': '9ncz4wunmhk0k52', #stocknear bot id + 'notifyType': 'priceAlert', + 'priceAlert': item.id, + 'liveResults': {'symbol': symbol, 'assetType': item.asset_type, 'condition': item.condition, 'targetPrice': target_price, 'currentPrice': current_price}, + } + + notify_item = pb.collection('notifications').create(newNotification) + + await push_notification(symbol, item.user) + pb.collection('notifications').update(notify_item.id, {"sent": True}) + + elif (item.condition == 'above') and target_price <= current_price: + #print('above true', symbol, target_price) + pb.collection("priceAlert").update(item.id, {"triggered": True}) + + newNotification = { + 'opUser': item.user, + 'user': '9ncz4wunmhk0k52', #stocknear bot id + 'notifyType': 'priceAlert', + 'priceAlert': item.id, + 'liveResults': {'symbol': symbol, 'assetType': item.asset_type, 'condition': item.condition, 'targetPrice': target_price, 'currentPrice': current_price}, + } + + notify_item = pb.collection('notifications').create(newNotification) + await push_notification(symbol, item.user) + pb.collection('notifications').update(notify_item.id, {"sent": True}) + + except Exception as e: + print(e) - newNotification = { - 'opUser': item.user, - 'user': '9ncz4wunmhk0k52', #stocknear bot id - 'notifyType': 'priceAlert', - 'priceAlert': item.id, - 'liveResults': {'symbol': symbol, 'assetType': item.asset_type, 'condition': item.condition, 'targetPrice': target_price, 'currentPrice': current_price}, - } - pb.collection('notifications').create(newNotification) - #send alert via email - #recipient = (pb.collection('users').get_one(item.user)).email - #send_email(recipient, symbol, item.asset_type, current_price, target_price, item.condition) - elif (item.condition == 'above') and target_price <= current_price: - #print('above true', symbol, target_price) - pb.collection("priceAlert").update(item.id, {"triggered": True}) - - newNotification = { - 'opUser': item.user, - 'user': '9ncz4wunmhk0k52', #stocknear bot id - 'notifyType': 'priceAlert', - 'priceAlert': item.id, - 'liveResults': {'symbol': symbol, 'assetType': item.asset_type, 'condition': item.condition, 'targetPrice': target_price, 'currentPrice': current_price}, - } - pb.collection('notifications').create(newNotification) - #send alert via email - #recipient = (pb.collection('users').get_one(item.user)).email - #send_email(recipient, symbol, item.asset_type, current_price, target_price, item.condition) try: asyncio.run(run()) except Exception as e: diff --git a/app/test.py b/app/test.py index d64d516..eaa9997 100644 --- a/app/test.py +++ b/app/test.py @@ -7,12 +7,14 @@ api_key = os.getenv('STOCKNEAR_API_KEY') # Define the URL and the API key -url = 'https://stocknear.com/api/sendPushSubscription' +origin = "https://stocknear.com" +url = f"{origin}/api/sendPushSubscription" # Define the data payload for the notification data = { - "title": "Price Alert", - "body": "bus bauen", + "title": "Hast du nix besseres zu tun am Sonntag", + "body": "Du Opfer", + "url": f"{origin}/stocks/nvda", "key": api_key, }