Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animesh das245 patch 2 #11

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions Backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'])
Expand Down Expand Up @@ -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():
Expand Down
35 changes: 35 additions & 0 deletions Backend/notifications.py
Original file line number Diff line number Diff line change
@@ -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'] = '[email protected]'
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}')
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
2 changes: 2 additions & 0 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -83,6 +84,7 @@ function App() {
onSearchTextClick={handleSearchTextClick}
/>
<TrackedProductList />
<NotificationPreferenceForm />
{showPriceHistory && (
<PriceHistoryTable
priceHistory={priceHistory}
Expand Down
53 changes: 53 additions & 0 deletions frontend/src/NotificationPreferenceForm.js
Original file line number Diff line number Diff line change
@@ -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 (
<form onSubmit={handleSubmit}>
<label>
Email:
<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required />
</label>
<label>
Product ID:
<input type="number" value={productId} onChange={(e) => setProductId(e.target.value)} required />
</label>
<label>
Original Price:
<input type="number" value={originalPrice} onChange={(e) => setOriginalPrice(e.target.value)} required />
</label>
<button type="submit">Set Notification Preference</button>
</form>
);
}

export default NotificationPreferenceForm;