From 7108a479b5e7815baa61f6ed76dc4a24b5af15d1 Mon Sep 17 00:00:00 2001 From: Animesh Das <100115113+Animesh-Das245@users.noreply.github.com> Date: Mon, 30 Oct 2023 18:25:16 +0530 Subject: [PATCH 1/5] Create NotificationPreferenceForm.js --- frontend/src/NotificationPreferenceForm.js | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 frontend/src/NotificationPreferenceForm.js diff --git a/frontend/src/NotificationPreferenceForm.js b/frontend/src/NotificationPreferenceForm.js new file mode 100644 index 0000000..6a6f116 --- /dev/null +++ b/frontend/src/NotificationPreferenceForm.js @@ -0,0 +1,53 @@ +// src/NotificationPreferenceForm.js + +import React, { useState } from "react"; + +function NotificationPreferenceForm() { + const [email, setEmail] = useState(''); + const [productId, setProductId] = useState(''); + const [originalPrice, setOriginalPrice] = useState(''); + + const handleSubmit = async (e) => { + e.preventDefault(); + const data = { + email, + product_id: productId, + original_price: originalPrice, + }; + + const response = await fetch('http://localhost:5000/set-notification-preference', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data) + }); + + if (response.ok) { + const result = await response.json(); + alert(result.message); + } else { + alert('Failed to set notification preference. Please try again.'); + } + }; + + return ( +
+ + + + +
+ ); +} + +export default NotificationPreferenceForm; From 9863be0f15a181421e8f63abe9fac5df7b198dd0 Mon Sep 17 00:00:00 2001 From: Animesh Das <100115113+Animesh-Das245@users.noreply.github.com> Date: Mon, 30 Oct 2023 18:29:19 +0530 Subject: [PATCH 2/5] Update App.js --- frontend/src/App.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/App.js b/frontend/src/App.js index 2b50294..b8558e2 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -3,6 +3,7 @@ import SearchTextList from "./components/SearchTextList"; import PriceHistoryTable from "./components/PriceHistoryTable"; import axios from "axios"; import TrackedProductList from "./components/TrackedProductList"; +import NotificationPreferenceForm from "./NotificationPreferenceForm"; const URL = "http://localhost:5000"; @@ -83,6 +84,7 @@ function App() { onSearchTextClick={handleSearchTextClick} /> + {showPriceHistory && ( Date: Mon, 30 Oct 2023 18:38:17 +0530 Subject: [PATCH 3/5] Update app.py --- Backend/app.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Backend/app.py b/Backend/app.py index 49c9f57..660a810 100644 --- a/Backend/app.py +++ b/Backend/app.py @@ -39,6 +39,15 @@ class TrackedProducts(db.Model): def __init__(self, name, tracked=True): self.name = name self.tracked = tracked + +class NotificationPreference(db.Model): + id = db.Column(db.Integer, primary_key=True) + email = db.Column(db.String(255), nullable=False) + product_id = db.Column(db.Integer, db.ForeignKey('tracked_products.id'), nullable=False) + original_price = db.Column(db.Float, nullable=False) + product = db.relationship('TrackedProducts', back_populates='notification_preferences') + +TrackedProducts.notification_preferences = db.relationship('NotificationPreference', back_populates='product') @app.route('/results', methods=['POST']) @@ -192,6 +201,26 @@ def update_tracked_products(): "products": product_names} return jsonify(response), 200 +@app.route('/set-notification-preference', methods=['POST']) +def set_notification_preference(): + email = request.json.get('email') + product_id = request.json.get('product_id') + original_price = request.json.get('original_price') + + new_preference = NotificationPreference(email=email, product_id=product_id, original_price=original_price) + db.session.add(new_preference) + db.session.commit() + + return jsonify({'message': 'Notification preference set successfully'}), 200 + + +from apscheduler.schedulers.background import BackgroundScheduler +from notifications import check_notifications + +scheduler = BackgroundScheduler() +scheduler.add_job(func=check_notifications, trigger="interval", minutes=60) +scheduler.start() + if __name__ == '__main__': with app.app_context(): From a47f8996faac54d639b5dec6f5d6ff2630300951 Mon Sep 17 00:00:00 2001 From: Animesh Das <100115113+Animesh-Das245@users.noreply.github.com> Date: Mon, 30 Oct 2023 18:39:08 +0530 Subject: [PATCH 4/5] Create notifications.py --- Backend/notifications.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Backend/notifications.py diff --git a/Backend/notifications.py b/Backend/notifications.py new file mode 100644 index 0000000..a37489d --- /dev/null +++ b/Backend/notifications.py @@ -0,0 +1,35 @@ +import smtplib +from email.mime.text import MIMEText +from app import db, NotificationPreference, TrackedProducts + +def check_notifications(): + notification_preferences = NotificationPreference.query.all() + + for preference in notification_preferences: + latest_price = TrackedProducts.query.filter_by(id=preference.product_id).first().price + percent_drop = ((preference.original_price - latest_price) / preference.original_price) * 100 + + if percent_drop >= 30: + send_notification(preference.email, preference.product, latest_price, percent_drop) + +def send_notification(email, product, price, percent_drop): + smtp_server = 'smtp.example.com' + smtp_port = 587 + smtp_username = 'your_username' + smtp_password = 'your_password' + + subject = f'Price Drop Alert for {product.name}' + body = f'The price for {product.name} has dropped by {percent_drop}% to {price}!' + msg = MIMEText(body) + msg['Subject'] = subject + msg['From'] = 'notifications@example.com' + msg['To'] = email + + try: + with smtplib.SMTP(smtp_server, smtp_port) as server: + server.starttls() + server.login(smtp_username, smtp_password) + server.send_message(msg) + print(f'Notification sent to {email}') + except Exception as e: + print(f'Failed to send notification: {e}') From e965a2a6a990959ac141b3751ceb55d1eb9fb99e Mon Sep 17 00:00:00 2001 From: Animesh Das <100115113+Animesh-Das245@users.noreply.github.com> Date: Mon, 30 Oct 2023 18:57:46 +0530 Subject: [PATCH 5/5] Update README.md --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index f77ff69..b68b53e 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,33 @@ Fill in your [Bright Data Scraping Browser](https://brightdata.com/products/scra To automate the collection of prices from this software simply run the `scheduler/main.py` file at your desired increment while the python flask backend is running. +## New Feature: Price Drop Notifications + +We have introduced a new feature to notify users when the price of a tracked product drops by 30% or more. Users can easily set their notification preferences by providing their email address and selecting the product they are interested in. + +### Setup + +1. **SMTP Relay Service**: + - We've implemented an email notification system using an SMTP relay service. + - You will need to create an account with an SMTP relay service of your choice (e.g., SendGrid, Mailgun, etc.). + - Update the `SMTP_SERVER`, `SMTP_PORT`, `SMTP_USER`, and `SMTP_PASSWORD` environment variables in your backend configuration with the credentials provided by your SMTP relay service. + +2. **Backend Configuration**: + - In the `app.py` file in the backend folder, ensure that the `/set-notification-preference` and `/check-price-drop` routes are correctly set up. + +3. **Frontend Integration**: + - Include the `NotificationPreferenceForm` component in your frontend application where users can enter their email address and set their notification preference for specific products. + +### Usage + +- Users can navigate to the Notification Preference section on the UI. +- Enter their email address, select a product, and specify the original price. +- Once the preference is set, the system will monitor the price of the specified product. +- When a price drop of 30% or more is detected, an email notification will be sent to the user informing them of the price drop. + +This feature enhances the user experience by providing timely notifications on price drops for products they are interested in. + + ### Windows I have created a simple `.bat` script called `run.bat` that you can schedule to execute using the Windows Task Scheduler that will automatically run the backend api and send the appropriate request to it.