Skip to content

Commit a229e3c

Browse files
author
Aarushi Keshari
committed
fix: resolve upstream sync conflicts and transition avatar raw emojis to fontawesome structural icons
2 parents eb71c08 + 17cbe72 commit a229e3c

40 files changed

Lines changed: 4620 additions & 1204 deletions

‎.DS_Store‎

8 KB
Binary file not shown.

‎.github/workflows/ci.yml‎

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: CI – Run Tests
2+
3+
on:
4+
push:
5+
branches: ["main", "master"]
6+
pull_request:
7+
branches: ["main", "master"]
8+
9+
jobs:
10+
test:
11+
name: pytest
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- uses: actions/setup-python@v5
18+
with:
19+
python-version: "3.11"
20+
cache: "pip"
21+
22+
- name: Install dependencies
23+
run: |
24+
pip install --upgrade pip
25+
pip install -r backend/requirements.txt
26+
pip install pytest pytest-cov
27+
pip install flask-wtf bleach Pillow beautifulsoup4 "pydantic[email]" pytest pytest-cov
28+
29+
- name: Run pytest
30+
env:
31+
GOOGLE_BOOKS_API_KEY: "ci-fake-key"
32+
OPENAI_API_KEY: "ci-fake-key"
33+
GROQ_API_KEY: "ci-fake-key"
34+
GEMINI_API_KEY: "ci-fake-key"
35+
FLASK_ENV: testing
36+
PYTHONPATH: ".:backend"
37+
run: |
38+
python -m pytest tests/ \
39+
--ignore=tests/test_llm.py \
40+
--ignore=tests/test_mood_improvements.py \
41+
--ignore=tests/test_mood_cache_db.py \
42+
--ignore=tests/test_category_cache.py \
43+
--ignore=tests/test_env_validation.py \
44+
--ignore=tests/test_purchase_links.py \
45+
-v --tb=short --cov=backend
46+
47+
- name: Install dependencies
48+
run: |
49+
pip install --upgrade pip
50+
pip install torch --index-url https://download.pytorch.org/whl/cpu
51+
pip install -r backend/requirements.txt
52+
pip install flask-wtf bleach Pillow pytest pytest-cov
53+
54+
- name: Install dependencies
55+
run: |
56+
pip install --upgrade pip
57+
pip install torch --index-url https://download.pytorch.org/whl/cpu
58+
pip install -r backend/requirements.txt
59+
pip install flask-wtf bleach Pillow beautifulsoup4 pytest pytest-cov

‎.gitignore‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ mood_analysis/mood_cache.json
66
*.cache
77

88
# Environment variables
9-
.env
10-
.env.local
11-
.env.production
12-
.env.development
9+
/.env
10+
/.env.local
11+
/.env.production
12+
/.env.development
1313

1414
# Sensitive local files
1515
*.token
@@ -32,3 +32,4 @@ instance/
3232
*.db
3333
# Virtual Environment
3434
venv/
35+
.venv/

‎backend/app.py‎

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from flask_wtf.csrf import CSRFProtect, generate_csrf, CSRFError
1515
from sqlalchemy.exc import SQLAlchemyError
1616
from dotenv import load_dotenv
17-
from backend.spine_generator import create_spine
17+
from spine_generator import create_spine
1818
import os
1919
import requests
2020
import secrets
@@ -25,8 +25,8 @@
2525
import sys
2626
import os
2727
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
28-
from sanitizer import sanitize_payload
29-
from reader_identity.routes import reader_identity_bp
28+
from backend.sanitizer import sanitize_payload
29+
from backend.reader_identity.routes import reader_identity_bp
3030

3131
# Load environment variables from config directory based on APP_ENV
3232
env = os.getenv('APP_ENV', 'development')
@@ -2405,20 +2405,9 @@ def delete_price_alert(alert_id):
24052405
with app.app_context():
24062406
db.create_all()
24072407

2408-
@app.route('/api/books', methods=['GET'])
2409-
def get_books():
2410-
query = request.args.get('q')
2411-
max_results = request.args.get('maxResults', 10)
2412-
2413-
API_KEY = os.getenv("GOOGLE_BOOKS_API_KEY")
2414-
url = f"https://www.googleapis.com/books/v1/volumes?q={query}&maxResults={max_results}&key={API_KEY}"
2415-
2416-
try:
2417-
response = requests.get(url)
2418-
data = response.json()
2419-
return jsonify(data)
2420-
except Exception as e:
2421-
return jsonify({"error": "Failed to fetch books"}), 500
2408+
# NOTE: Book search is performed directly from the frontend using the Google Books API.
2409+
# The old backend proxy endpoint /api/books has been removed to avoid unnecessary
2410+
# load on the backend server.
24222411

24232412
if __name__ == '__main__':
24242413
server_config = app_config.server

‎backend/config.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,9 @@ def from_env(cls) -> 'GoogleOAuthConfig':
166166
redirect_uri=os.getenv('GOOGLE_OAUTH_REDIRECT_URI'),
167167
frontend_redirect_url=os.getenv('FRONTEND_URL', 'http://127.0.0.1:5500/frontend/pages/library.html'),
168168
scope=os.getenv('GOOGLE_OAUTH_SCOPE', 'openid email profile')
169-
169+
)
170+
171+
@dataclass
170172
class EmailConfig:
171173
"""Email service configuration (e.g., SendGrid, Mailgun)."""
172174
api_key: Optional[str]
Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
"""
22
Handles unsupervised reader clustering.
33
"""
4-
from sklearn.feature_extraction.text import TfidfVectorizer
5-
from sklearn.cluster import KMeans
64
"""
75
Uses TF-IDF and KMeans clustering for grouping readers.
86
"""
@@ -11,29 +9,39 @@
119
class ClusterEngine:
1210

1311
def __init__(self):
14-
15-
self.vectorizer = TfidfVectorizer(
16-
stop_words="english"
17-
)
12+
self.vectorizer = None
1813

1914
def cluster_reviews(self, reviews):
20-
21-
vectors = self.vectorizer.fit_transform(
22-
reviews
23-
)
24-
25-
cluster_count = min(
26-
len(reviews),
27-
4
28-
)
29-
30-
model = KMeans(
31-
n_clusters=cluster_count,
32-
random_state=42
33-
)
34-
35-
clusters = model.fit_predict(
36-
vectors
37-
)
38-
39-
return clusters.tolist()
15+
if not reviews:
16+
return [-1]
17+
18+
try:
19+
from sklearn.cluster import KMeans
20+
if self.vectorizer is None:
21+
from sklearn.feature_extraction.text import TfidfVectorizer
22+
self.vectorizer = TfidfVectorizer(
23+
stop_words="english"
24+
)
25+
vectors = self.vectorizer.fit_transform(
26+
reviews
27+
)
28+
29+
cluster_count = min(
30+
len(reviews),
31+
4
32+
)
33+
if cluster_count == 0:
34+
return [-1]
35+
36+
model = KMeans(
37+
n_clusters=cluster_count,
38+
random_state=42
39+
)
40+
41+
clusters = model.fit_predict(
42+
vectors
43+
)
44+
45+
return clusters.tolist()
46+
except Exception:
47+
return [-1]

‎backend/reader_identity/embedding_engine.py‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
"""
22
Handles semantic similarity using sentence embeddings.
33
"""
4-
from sentence_transformers import SentenceTransformer
5-
from sklearn.metrics.pairwise import cosine_similarity
64

75
"""
86
Generates embeddings and compares semantic similarity.
@@ -12,16 +10,18 @@
1210
class EmbeddingEngine:
1311

1412
def __init__(self):
15-
16-
self.model = SentenceTransformer(
17-
"all-MiniLM-L6-v2"
18-
)
13+
self.model = None
1914

2015
def get_embedding(self, text):
21-
16+
if self.model is None:
17+
from sentence_transformers import SentenceTransformer
18+
self.model = SentenceTransformer(
19+
"all-MiniLM-L6-v2"
20+
)
2221
return self.model.encode([text])
2322

2423
def compare_texts(self, text1, text2):
24+
from sklearn.metrics.pairwise import cosine_similarity
2525

2626
embedding1 = self.get_embedding(text1)
2727

‎backend/reader_identity/routes.py‎

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,50 +14,9 @@
1414
"/api/v1/reader-archetype",
1515
methods=["POST"]
1616
)
17-
1817
def reader_archetype():
19-
2018
try:
21-
2219
data = request.get_json()
23-
24-
if not data:
25-
26-
return jsonify({
27-
"success": False,
28-
"error": "Missing JSON body"
29-
}), 400
30-
31-
genres = data.get("genres", [])
32-
33-
reviews = data.get("reviews", [])
34-
35-
if not reviews:
36-
37-
return jsonify({
38-
"success": False,
39-
"error": "Reviews are required"
40-
}), 400
41-
42-
result = generator.generate_profile(
43-
genres,
44-
reviews
45-
)
46-
47-
return jsonify(result)
48-
49-
except Exception as e:
50-
51-
return jsonify({
52-
"success": False,
53-
"error": str(e)
54-
}), 500
55-
def reader_archetype():
56-
57-
try:
58-
59-
data = request.get_json()
60-
6120
if not data:
6221
return jsonify({
6322
"success": False,
@@ -83,11 +42,9 @@ def reader_archetype():
8342
genres,
8443
reviews
8544
)
86-
8745
return jsonify(result), 200
8846

8947
except Exception as e:
90-
9148
return jsonify({
9249
"success": False,
9350
"error": str(e)

‎backend/reader_identity/sentiment_engine.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
Handles sentiment analysis for reader reviews.
33
"""
44

5-
from textblob import TextBlob
6-
75
"""
86
Performs sentiment-based emotional profiling.
97
"""
108

119
class SentimentEngine:
1210

1311
def analyze_reviews(self, reviews):
12+
from textblob import TextBlob
1413

1514
combined_text = " ".join(reviews)
1615

41.1 KB
Loading

0 commit comments

Comments
 (0)