rastof9 commited on
Commit
2a9b5c4
·
1 Parent(s): d98cb87
app/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
- from flask import Flask
2
  from flask_sqlalchemy import SQLAlchemy
3
  from flask_migrate import Migrate
4
- from flask_login import LoginManager
5
  from celery import Celery
6
  from config import Config
7
  import redis
@@ -93,7 +93,7 @@ def create_app(config_class=Config):
93
  try:
94
  logger.info("Importing and registering dashboard blueprint...")
95
  from .routes.dashboard import dashboard_bp
96
- app.register_blueprint(dashboard_bp)
97
  logger.info("Dashboard blueprint registered successfully")
98
  except Exception as e:
99
  logger.error(f"Error registering dashboard blueprint: {e}")
@@ -141,7 +141,14 @@ def create_app(config_class=Config):
141
  # Add a simple route directly to the app
142
  @app.route('/')
143
  def index():
144
- return 'Application is running! Try /test for the test endpoint.'
 
 
 
 
 
 
 
145
 
146
  logger.info("Application initialization complete")
147
  return app
 
1
+ from flask import Flask, redirect, url_for
2
  from flask_sqlalchemy import SQLAlchemy
3
  from flask_migrate import Migrate
4
+ from flask_login import LoginManager, current_user
5
  from celery import Celery
6
  from config import Config
7
  import redis
 
93
  try:
94
  logger.info("Importing and registering dashboard blueprint...")
95
  from .routes.dashboard import dashboard_bp
96
+ app.register_blueprint(dashboard_bp, url_prefix='/dashboard')
97
  logger.info("Dashboard blueprint registered successfully")
98
  except Exception as e:
99
  logger.error(f"Error registering dashboard blueprint: {e}")
 
141
  # Add a simple route directly to the app
142
  @app.route('/')
143
  def index():
144
+ if current_user.is_authenticated:
145
+ try:
146
+ return redirect(url_for('dashboard.index'))
147
+ except:
148
+ # Fallback to facebook_ads if dashboard is not available
149
+ return redirect(url_for('facebook_ads.index'))
150
+ else:
151
+ return redirect(url_for('auth.login'))
152
 
153
  logger.info("Application initialization complete")
154
  return app
app/__pycache__/__init__.cpython-311.pyc CHANGED
Binary files a/app/__pycache__/__init__.cpython-311.pyc and b/app/__pycache__/__init__.cpython-311.pyc differ
 
app/__pycache__/__init__.cpython-312.pyc CHANGED
Binary files a/app/__pycache__/__init__.cpython-312.pyc and b/app/__pycache__/__init__.cpython-312.pyc differ
 
app/models/__init__.py CHANGED
@@ -5,6 +5,7 @@ from app import db
5
  from datetime import datetime
6
  from flask_login import UserMixin
7
  from werkzeug.security import generate_password_hash, check_password_hash
 
8
 
9
  class User(UserMixin, db.Model):
10
  id = db.Column(db.Integer, primary_key=True)
 
5
  from datetime import datetime
6
  from flask_login import UserMixin
7
  from werkzeug.security import generate_password_hash, check_password_hash
8
+ from .facebook_ad import FacebookAd
9
 
10
  class User(UserMixin, db.Model):
11
  id = db.Column(db.Integer, primary_key=True)
app/models/__pycache__/__init__.cpython-312.pyc CHANGED
Binary files a/app/models/__pycache__/__init__.cpython-312.pyc and b/app/models/__pycache__/__init__.cpython-312.pyc differ
 
app/models/__pycache__/facebook_ad.cpython-312.pyc CHANGED
Binary files a/app/models/__pycache__/facebook_ad.cpython-312.pyc and b/app/models/__pycache__/facebook_ad.cpython-312.pyc differ
 
app/models/facebook_ad.py CHANGED
@@ -6,6 +6,8 @@ import json
6
  class FacebookAd(db.Model):
7
  """Model for storing Facebook ads data."""
8
 
 
 
9
  id = db.Column(db.Integer, primary_key=True)
10
  ad_id = db.Column(db.String(255), index=True, unique=True)
11
  advertiser = db.Column(db.String(255), index=True)
@@ -46,8 +48,6 @@ class FacebookAd(db.Model):
46
  else:
47
  self.image_urls_json = json.dumps(value)
48
 
49
- image_urls = property(get_image_urls, set_image_urls)
50
-
51
  def get_links(self):
52
  """Get links as a list."""
53
  if not self.links_json:
@@ -64,8 +64,6 @@ class FacebookAd(db.Model):
64
  else:
65
  self.links_json = json.dumps(value)
66
 
67
- links = property(get_links, set_links)
68
-
69
  def get_metadata(self):
70
  """Get metadata as a dictionary."""
71
  if not self.metadata_json:
@@ -82,8 +80,6 @@ class FacebookAd(db.Model):
82
  else:
83
  self.metadata_json = json.dumps(value)
84
 
85
- metadata = property(get_metadata, set_metadata)
86
-
87
  def get_topics(self):
88
  """Get topics as a list."""
89
  if not self.topics_json:
@@ -100,8 +96,6 @@ class FacebookAd(db.Model):
100
  else:
101
  self.topics_json = json.dumps(value)
102
 
103
- topics = property(get_topics, set_topics)
104
-
105
  def get_entities(self):
106
  """Get entities as a list of dictionaries."""
107
  if not self.entities_json:
@@ -118,8 +112,6 @@ class FacebookAd(db.Model):
118
  else:
119
  self.entities_json = json.dumps(value)
120
 
121
- entities = property(get_entities, set_entities)
122
-
123
  @classmethod
124
  def from_scraper_data(cls, data, user_id=None):
125
  """Create a FacebookAd instance from scraper data."""
@@ -142,20 +134,6 @@ class FacebookAd(db.Model):
142
 
143
  return ad
144
 
145
- def get_image_urls_limited(self, limit=None):
146
- """Get image URLs, optionally limited to a specific number."""
147
- urls = self.get_image_urls()
148
- if limit and len(urls) > limit:
149
- return urls[:limit]
150
- return urls
151
-
152
- def get_links_limited(self, limit=None):
153
- """Get links, optionally limited to a specific number."""
154
- links = self.get_links()
155
- if limit and len(links) > limit:
156
- return links[:limit]
157
- return links
158
-
159
  def to_dict(self):
160
  """Convert the ad to a dictionary for API responses."""
161
  return {
@@ -171,4 +149,4 @@ class FacebookAd(db.Model):
171
  'topics': self.get_topics(),
172
  'created_at': self.created_at.isoformat() if self.created_at else None,
173
  'updated_at': self.updated_at.isoformat() if self.updated_at else None
174
- }
 
6
  class FacebookAd(db.Model):
7
  """Model for storing Facebook ads data."""
8
 
9
+ __tablename__ = 'facebook_ads'
10
+
11
  id = db.Column(db.Integer, primary_key=True)
12
  ad_id = db.Column(db.String(255), index=True, unique=True)
13
  advertiser = db.Column(db.String(255), index=True)
 
48
  else:
49
  self.image_urls_json = json.dumps(value)
50
 
 
 
51
  def get_links(self):
52
  """Get links as a list."""
53
  if not self.links_json:
 
64
  else:
65
  self.links_json = json.dumps(value)
66
 
 
 
67
  def get_metadata(self):
68
  """Get metadata as a dictionary."""
69
  if not self.metadata_json:
 
80
  else:
81
  self.metadata_json = json.dumps(value)
82
 
 
 
83
  def get_topics(self):
84
  """Get topics as a list."""
85
  if not self.topics_json:
 
96
  else:
97
  self.topics_json = json.dumps(value)
98
 
 
 
99
  def get_entities(self):
100
  """Get entities as a list of dictionaries."""
101
  if not self.entities_json:
 
112
  else:
113
  self.entities_json = json.dumps(value)
114
 
 
 
115
  @classmethod
116
  def from_scraper_data(cls, data, user_id=None):
117
  """Create a FacebookAd instance from scraper data."""
 
134
 
135
  return ad
136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  def to_dict(self):
138
  """Convert the ad to a dictionary for API responses."""
139
  return {
 
149
  'topics': self.get_topics(),
150
  'created_at': self.created_at.isoformat() if self.created_at else None,
151
  'updated_at': self.updated_at.isoformat() if self.updated_at else None
152
+ }
app/routes/__pycache__/dashboard.cpython-312.pyc CHANGED
Binary files a/app/routes/__pycache__/dashboard.cpython-312.pyc and b/app/routes/__pycache__/dashboard.cpython-312.pyc differ
 
app/routes/dashboard.py CHANGED
@@ -1,7 +1,6 @@
1
  from flask import Blueprint, render_template, request
2
  from flask_login import login_required
3
- from ..models import Ad
4
- from ..services.ai_processor import AIPipeline
5
 
6
  dashboard_bp = Blueprint('dashboard', __name__)
7
 
@@ -11,11 +10,16 @@ def index():
11
  page = request.args.get('page', 1, type=int)
12
  per_page = 10
13
  query = request.args.get('query', '')
14
- sentiment_filter = request.args.get('sentiment', '')
15
 
16
- ads = Ad.query.filter(
17
- Ad.content.contains(query),
18
- Ad.sentiment.contains(sentiment_filter)
19
- ).paginate(page=page, per_page=per_page)
 
 
 
20
 
21
- return render_template('dashboard.html', ads=ads, query=query, sentiment_filter=sentiment_filter)
 
 
 
 
1
  from flask import Blueprint, render_template, request
2
  from flask_login import login_required
3
+ from ..models import FacebookAd
 
4
 
5
  dashboard_bp = Blueprint('dashboard', __name__)
6
 
 
10
  page = request.args.get('page', 1, type=int)
11
  per_page = 10
12
  query = request.args.get('query', '')
 
13
 
14
+ # Use FacebookAd model with correct filter
15
+ if query:
16
+ ads = FacebookAd.query.filter(
17
+ FacebookAd.content.contains(query)
18
+ ).paginate(page=page, per_page=per_page)
19
+ else:
20
+ ads = FacebookAd.query.paginate(page=page, per_page=per_page)
21
 
22
+ return render_template('dashboard/index.html',
23
+ ads=ads,
24
+ query=query,
25
+ title="Dashboard")
app/templates/base.html CHANGED
@@ -21,11 +21,13 @@
21
  <div class="collapse navbar-collapse" id="navbarNav">
22
  <ul class="navbar-nav me-auto">
23
  {% if current_user.is_authenticated %}
 
24
  <li class="nav-item">
25
  <a class="nav-link" href="{{ url_for('google_ads.dashboard') }}">
26
  <i class="fab fa-google"></i> Google Ads
27
  </a>
28
  </li>
 
29
  <li class="nav-item">
30
  <a class="nav-link" href="{{ url_for('facebook_ads.index') }}">
31
  <i class="fab fa-facebook"></i> Facebook Ads
 
21
  <div class="collapse navbar-collapse" id="navbarNav">
22
  <ul class="navbar-nav me-auto">
23
  {% if current_user.is_authenticated %}
24
+ {# Temporarily disabled until Google Ads blueprint is fixed
25
  <li class="nav-item">
26
  <a class="nav-link" href="{{ url_for('google_ads.dashboard') }}">
27
  <i class="fab fa-google"></i> Google Ads
28
  </a>
29
  </li>
30
+ #}
31
  <li class="nav-item">
32
  <a class="nav-link" href="{{ url_for('facebook_ads.index') }}">
33
  <i class="fab fa-facebook"></i> Facebook Ads
app/templates/dashboard/index.html ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block content %}
4
+ <div class="container mt-4">
5
+ <h1>{{ title }}</h1>
6
+
7
+ <!-- Search Form -->
8
+ <form method="GET" action="{{ url_for('dashboard.index') }}" class="mb-4">
9
+ <div class="input-group">
10
+ <input type="text" class="form-control" name="query" value="{{ query }}" placeholder="Search ads...">
11
+ <button type="submit" class="btn btn-primary">Search</button>
12
+ </div>
13
+ </form>
14
+
15
+ <!-- Ads List -->
16
+ <div class="row">
17
+ {% if ads.items %}
18
+ {% for ad in ads.items %}
19
+ <div class="col-md-6 mb-4">
20
+ <div class="card">
21
+ <div class="card-body">
22
+ <h5 class="card-title">Ad #{{ ad.id }}</h5>
23
+ <p class="card-text">{{ ad.content[:200] }}...</p>
24
+ <div class="mt-2">
25
+ <a href="{{ url_for('facebook_ads.ad_detail', ad_id=ad.id) }}" class="btn btn-sm btn-primary">View Details</a>
26
+ </div>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ {% endfor %}
31
+ {% else %}
32
+ <div class="col-12">
33
+ <div class="alert alert-info">
34
+ No ads found. Try a different search query.
35
+ </div>
36
+ </div>
37
+ {% endif %}
38
+ </div>
39
+
40
+ <!-- Pagination -->
41
+ {% if ads.pages > 1 %}
42
+ <nav aria-label="Page navigation" class="mt-4">
43
+ <ul class="pagination justify-content-center">
44
+ {% if ads.has_prev %}
45
+ <li class="page-item">
46
+ <a class="page-link" href="{{ url_for('dashboard.index', page=ads.prev_num, query=query) }}">Previous</a>
47
+ </li>
48
+ {% endif %}
49
+
50
+ {% for page_num in ads.iter_pages(left_edge=2, left_current=2, right_current=3, right_edge=2) %}
51
+ {% if page_num %}
52
+ <li class="page-item {% if page_num == ads.page %}active{% endif %}">
53
+ <a class="page-link" href="{{ url_for('dashboard.index', page=page_num, query=query) }}">{{ page_num }}</a>
54
+ </li>
55
+ {% else %}
56
+ <li class="page-item disabled"><span class="page-link">...</span></li>
57
+ {% endif %}
58
+ {% endfor %}
59
+
60
+ {% if ads.has_next %}
61
+ <li class="page-item">
62
+ <a class="page-link" href="{{ url_for('dashboard.index', page=ads.next_num, query=query) }}">Next</a>
63
+ </li>
64
+ {% endif %}
65
+ </ul>
66
+ </nav>
67
+ {% endif %}
68
+ </div>
69
+ {% endblock %}
requirements.txt CHANGED
@@ -14,7 +14,7 @@ requests==2.31.0
14
  beautifulsoup4==4.12.3
15
  selenium==4.17.2
16
  transformers==4.37.2
17
- torch==2.1.2
18
  textblob==0.17.1
19
  spacy==3.7.2
20
  en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.7.1/en_core_web_sm-3.7.1-py3-none-any.whl
 
14
  beautifulsoup4==4.12.3
15
  selenium==4.17.2
16
  transformers==4.37.2
17
+ torch==2.2.2
18
  textblob==0.17.1
19
  spacy==3.7.2
20
  en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.7.1/en_core_web_sm-3.7.1-py3-none-any.whl