Compare commits

...

11 Commits

Author SHA1 Message Date
115c1c1193 auto-claude: subtask-4-3 - Verify database has Google data for INPI company
BLOCKED: Cannot verify - dependencies not met:
- Local SQLite database empty (no tables initialized)
- Google Places API not enabled for current API key
- Previous subtask (4-2) was blocked, no audit ran

Documented blockers and options to unblock in build-progress.txt.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:52:14 +01:00
06c22539d7 auto-claude: subtask-4-2 - Add --company-slug support and dotenv loading
- Add --company-slug argument to social_media_audit.py for easier testing
- Add get_company_id_by_slug() method to SocialMediaAuditor class
- Add python-dotenv support to load .env file from project root
- Create verify_google_places.py script for direct API testing

Note: Full verification blocked - current API key (PageSpeed) doesn't have
Places API enabled. Requires enabling Places API in Google Cloud Console
for project NORDABIZNES (gen-lang-client-0540794446).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:49:59 +01:00
3d69d53550 auto-claude: subtask-3-4 - Run all tests and verify they pass
Fixed bug in social media exclusion logic that was too aggressive.
The substring check `any(ex in match.lower() for ex in excludes)`
was incorrectly excluding valid usernames containing exclusion
strings (e.g., 'testcompany' was excluded because it contained 'p').

Changed to exact match only to properly handle Instagram post URLs
(`instagram.com/p/...`) without false positives on valid usernames.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:41:54 +01:00
9cd5066afe auto-claude: subtask-3-3 - Add test_search_google_reviews_error for API error
Added test for search_google_reviews method to handle API errors gracefully.
The test mocks GooglePlacesSearcher to simulate a RequestException during
get_place_details and verifies that the method returns None values instead
of crashing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:39:11 +01:00
ee6bc656ef auto-claude: subtask-3-2 - Add test_search_google_reviews for successful API response
Added test_search_google_reviews test in TestBraveSearcherGoogleReviews class
that verifies successful Google reviews retrieval via Google Places API:
- Mocks complete place lookup with realistic place_id
- Mocks full place details response including rating, reviews count,
  opening hours, and business status
- Verifies all expected fields are correctly returned
- Validates correct API calls are made with expected parameters

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:37:27 +01:00
c057794c64 auto-claude: subtask-3-1 - Create test file for social_media_audit with Google Places tests
Add comprehensive unit tests for social_media_audit.py:
- WebsiteAuditor tests: SSL checks, hosting detection, HTML parsing, social media extraction
- GooglePlacesSearcher tests: find_place, get_place_details, API error handling
- BraveSearcher tests: Google reviews search, fallback mechanisms
- SocialMediaAuditor tests: company auditing, result saving, integration tests
- Pattern tests: hosting providers, social media URL patterns, exclusion rules

Tests follow the same structure and patterns as test_seo_audit.py.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:35:27 +01:00
3bdbde1621 auto-claude: subtask-2-3 - Update SocialMediaAuditor to use GooglePlacesSearcher
- Add google_places_searcher attribute to SocialMediaAuditor
- Initialize GooglePlacesSearcher if GOOGLE_PLACES_API_KEY env var is set
- Update audit_company() to use Places API directly when available
- Fallback to Brave Search when API key not configured
- Log which data source is being used for reviews

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:31:22 +01:00
b389287697 auto-claude: subtask-2-2 - Replace placeholder search_google_reviews() method
Implemented actual Google reviews data collection in BraveSearcher class:
- Uses GooglePlacesSearcher to find company and get place details
- Returns google_rating, google_reviews_count, opening_hours, business_status
- Falls back to Brave Search API parsing when Google API key not available
- Added _search_brave_for_reviews() helper for fallback implementation
- Proper error handling and logging throughout

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:29:50 +01:00
4110ef63b5 auto-claude: subtask-2-1 - Add GooglePlacesSearcher class to social_media_audit.py
Implements GooglePlacesSearcher class with:
- find_place() method: searches for business by name and city
  using Google Places findplacefromtext API
- get_place_details() method: retrieves rating, review count,
  opening hours, business status, phone, and website

Features:
- Uses GOOGLE_PLACES_API_KEY environment variable
- Comprehensive error handling (timeout, request errors)
- Polish language locale support
- Follows existing BraveSearcher class pattern

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 20:27:49 +01:00
1426a73e0d auto-claude: subtask-1-2 - Document GOOGLE_PLACES_API_KEY in .env.example 2026-01-08 20:24:37 +01:00
c8d9d295af auto-claude: subtask-1-1 - Add googlemaps package to requirements.txt 2026-01-08 20:23:55 +01:00
6 changed files with 1764 additions and 13 deletions

25
.auto-claude-status Normal file
View File

@ -0,0 +1,25 @@
{
"active": true,
"spec": "007-https-nordabiznes-pl-audit-gbp-inpi-dane-nie-sa-w-",
"state": "building",
"subtasks": {
"completed": 12,
"total": 14,
"in_progress": 1,
"failed": 0
},
"phase": {
"current": "DEV Verification",
"id": null,
"total": 4
},
"workers": {
"active": 0,
"max": 1
},
"session": {
"number": 13,
"started_at": "2026-01-08T20:23:31.762031"
},
"last_update": "2026-01-08T20:50:25.874452"
}

View File

@ -20,6 +20,12 @@ GOOGLE_GEMINI_API_KEY=your_gemini_api_key_here
# Free tier: 25,000 requests/day
GOOGLE_PAGESPEED_API_KEY=your_pagespeed_api_key_here
# Google Places API (for GBP audits - Google Business Profile)
# Get your API key from: https://console.cloud.google.com/apis/credentials
# Enable "Places API" in Google Cloud Console
# Free tier: $200/month credit (covers ~10,000 requests)
GOOGLE_PLACES_API_KEY=your_places_api_key_here
# Email Configuration (for user verification)
MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587

View File

@ -17,6 +17,9 @@ psycopg2-binary==2.9.9
# Google Gemini AI
google-generativeai==0.3.2
# Google Maps/Places API
googlemaps==4.10.0
# Environment Configuration
python-dotenv==1.0.0

View File

@ -33,6 +33,20 @@ from datetime import datetime, timedelta
from typing import Optional, Dict, List, Tuple, Any
from urllib.parse import urlparse
import time
from pathlib import Path
# Load .env file from project root
try:
from dotenv import load_dotenv
# Find .env file relative to this script
script_dir = Path(__file__).resolve().parent
project_root = script_dir.parent
env_path = project_root / '.env'
if env_path.exists():
load_dotenv(env_path)
logging.info(f"Loaded .env from {env_path}")
except ImportError:
pass # python-dotenv not installed, rely on system environment
import requests
from bs4 import BeautifulSoup
@ -408,9 +422,9 @@ class WebsiteAuditor:
if matches:
# Get first valid match, excluding common false positives
for match in matches:
# Check against exclusion list
# Check against exclusion list (exact match only to avoid false positives)
excludes = SOCIAL_MEDIA_EXCLUDE.get(platform, [])
if match.lower() not in excludes and not any(ex in match.lower() for ex in excludes):
if match.lower() not in excludes:
# Construct full URL
if platform == 'facebook':
url = f'https://facebook.com/{match}'
@ -439,6 +453,207 @@ class WebsiteAuditor:
return result
class GooglePlacesSearcher:
"""Search for Google Business profiles using Google Places API."""
# Google Places API configuration
FIND_PLACE_URL = 'https://maps.googleapis.com/maps/api/place/findplacefromtext/json'
PLACE_DETAILS_URL = 'https://maps.googleapis.com/maps/api/place/details/json'
def __init__(self, api_key: Optional[str] = None):
"""
Initialize GooglePlacesSearcher.
Args:
api_key: Google Places API key. Falls back to GOOGLE_PLACES_API_KEY env var.
"""
self.api_key = api_key or os.getenv('GOOGLE_PLACES_API_KEY')
self.session = requests.Session()
self.session.headers.update({'User-Agent': USER_AGENT})
def find_place(self, company_name: str, city: str = 'Wejherowo') -> Optional[str]:
"""
Find a place by company name and city.
Uses Google Places findplacefromtext API to search for a business
and returns the place_id if found.
Args:
company_name: Name of the company to search for.
city: City to narrow down the search (default: Wejherowo).
Returns:
place_id string if found, None otherwise.
"""
if not self.api_key:
logger.warning('Google Places API key not configured')
return None
try:
# Construct search query with company name and city
search_query = f'{company_name} {city}'
params = {
'input': search_query,
'inputtype': 'textquery',
'fields': 'place_id,name,formatted_address',
'language': 'pl',
'key': self.api_key,
}
response = self.session.get(
self.FIND_PLACE_URL,
params=params,
timeout=REQUEST_TIMEOUT
)
response.raise_for_status()
data = response.json()
if data.get('status') == 'OK' and data.get('candidates'):
candidate = data['candidates'][0]
place_id = candidate.get('place_id')
logger.info(
f"Found place for '{company_name}': {candidate.get('name')} "
f"at {candidate.get('formatted_address')}"
)
return place_id
elif data.get('status') == 'ZERO_RESULTS':
logger.info(f"No Google Business Profile found for '{company_name}' in {city}")
return None
else:
logger.warning(
f"Google Places API returned status: {data.get('status')} "
f"for '{company_name}'"
)
return None
except requests.exceptions.Timeout:
logger.error(f"Timeout searching for '{company_name}' on Google Places")
return None
except requests.exceptions.RequestException as e:
logger.error(f"Request error searching for '{company_name}': {e}")
return None
except Exception as e:
logger.error(f"Error finding place for '{company_name}': {e}")
return None
def get_place_details(self, place_id: str) -> Dict[str, Any]:
"""
Get detailed information about a place.
Retrieves rating, review count, opening hours, and other business details
from Google Places API.
Args:
place_id: Google Place ID returned from find_place().
Returns:
Dict containing:
- google_rating: Decimal rating (1.0-5.0) or None
- google_reviews_count: Integer review count or None
- opening_hours: Dict with weekday_text and open_now, or None
- business_status: String like 'OPERATIONAL', 'CLOSED_TEMPORARILY', etc.
- formatted_phone: Phone number or None
- website: Website URL or None
"""
result = {
'google_rating': None,
'google_reviews_count': None,
'opening_hours': None,
'business_status': None,
'formatted_phone': None,
'website': None,
}
if not self.api_key:
logger.warning('Google Places API key not configured')
return result
if not place_id:
return result
try:
# Request fields we need for the audit
fields = [
'rating',
'user_ratings_total',
'opening_hours',
'business_status',
'formatted_phone_number',
'website',
'name',
]
params = {
'place_id': place_id,
'fields': ','.join(fields),
'language': 'pl',
'key': self.api_key,
}
response = self.session.get(
self.PLACE_DETAILS_URL,
params=params,
timeout=REQUEST_TIMEOUT
)
response.raise_for_status()
data = response.json()
if data.get('status') == 'OK' and data.get('result'):
place = data['result']
# Extract rating
if 'rating' in place:
result['google_rating'] = round(float(place['rating']), 1)
# Extract review count
if 'user_ratings_total' in place:
result['google_reviews_count'] = int(place['user_ratings_total'])
# Extract opening hours
if 'opening_hours' in place:
hours = place['opening_hours']
result['opening_hours'] = {
'weekday_text': hours.get('weekday_text', []),
'open_now': hours.get('open_now'),
'periods': hours.get('periods', []),
}
# Extract business status
if 'business_status' in place:
result['business_status'] = place['business_status']
# Extract phone
if 'formatted_phone_number' in place:
result['formatted_phone'] = place['formatted_phone_number']
# Extract website
if 'website' in place:
result['website'] = place['website']
logger.info(
f"Retrieved details for {place.get('name')}: "
f"rating={result['google_rating']}, "
f"reviews={result['google_reviews_count']}"
)
else:
logger.warning(
f"Google Places API returned status: {data.get('status')} "
f"for place_id: {place_id}"
)
except requests.exceptions.Timeout:
logger.error(f"Timeout getting details for place_id: {place_id}")
except requests.exceptions.RequestException as e:
logger.error(f"Request error getting place details: {e}")
except Exception as e:
logger.error(f"Error getting place details for {place_id}: {e}")
return result
class BraveSearcher:
"""Search for social media profiles and Google reviews using Brave Search."""
@ -475,24 +690,150 @@ class BraveSearcher:
def search_google_reviews(self, company_name: str, city: str = 'Wejherowo') -> Dict[str, Any]:
"""
Search for Google reviews via Brave.
Returns dict with rating, reviews_count.
Search for Google reviews using Google Places API.
This method uses the GooglePlacesSearcher to find the company on Google
and retrieve its rating and review count.
Args:
company_name: Name of the company to search for.
city: City to narrow down the search (default: Wejherowo).
Returns:
Dict containing:
- google_rating: Decimal rating (1.0-5.0) or None
- google_reviews_count: Integer review count or None
- opening_hours: Dict with weekday_text and open_now, or None
- business_status: String like 'OPERATIONAL', 'CLOSED_TEMPORARILY', etc.
"""
result = {
'google_rating': None,
'google_reviews_count': None,
'opening_hours': None,
'business_status': None,
}
try:
query = f'{company_name} {city} opinie google'
# This would use Brave API or scraping
# For now, placeholder
pass
# Use Google Places API for accurate data
google_api_key = os.getenv('GOOGLE_PLACES_API_KEY')
if google_api_key:
# Use GooglePlacesSearcher for accurate data retrieval
places_searcher = GooglePlacesSearcher(api_key=google_api_key)
# Step 1: Find the place by company name and city
place_id = places_searcher.find_place(company_name, city)
if place_id:
# Step 2: Get detailed information including reviews
details = places_searcher.get_place_details(place_id)
result['google_rating'] = details.get('google_rating')
result['google_reviews_count'] = details.get('google_reviews_count')
result['opening_hours'] = details.get('opening_hours')
result['business_status'] = details.get('business_status')
logger.info(
f"Google reviews for '{company_name}': "
f"rating={result['google_rating']}, "
f"reviews={result['google_reviews_count']}, "
f"status={result['business_status']}"
)
else:
logger.info(f"No Google Business Profile found for '{company_name}' in {city}")
else:
# Fallback: Try Brave Search API if available
if self.api_key:
brave_result = self._search_brave_for_reviews(company_name, city)
if brave_result:
result.update(brave_result)
else:
logger.warning(
'Neither GOOGLE_PLACES_API_KEY nor BRAVE_API_KEY configured. '
'Cannot retrieve Google reviews data.'
)
except Exception as e:
logger.warning(f'Google reviews search failed: {e}')
logger.warning(f'Google reviews search failed for {company_name}: {e}')
return result
def _search_brave_for_reviews(self, company_name: str, city: str) -> Optional[Dict[str, Any]]:
"""
Fallback method to search for Google reviews via Brave Search API.
This parses search results to extract rating and review count from
Google Business snippets in search results.
Args:
company_name: Name of the company.
city: City for location context.
Returns:
Dict with google_rating and google_reviews_count, or None if not found.
"""
if not self.api_key:
return None
try:
query = f'{company_name} {city} opinie google'
# Brave Web Search API endpoint
url = 'https://api.search.brave.com/res/v1/web/search'
headers = {
'Accept': 'application/json',
'Accept-Encoding': 'gzip',
'X-Subscription-Token': self.api_key,
}
params = {
'q': query,
'count': 10,
'country': 'pl',
'search_lang': 'pl',
'ui_lang': 'pl-PL',
}
response = self.session.get(url, headers=headers, params=params, timeout=REQUEST_TIMEOUT)
response.raise_for_status()
data = response.json()
# Parse search results for rating/review patterns
# Google snippets often contain patterns like "4,5 (123 opinii)" or "Rating: 4.5 · 123 reviews"
for result in data.get('web', {}).get('results', []):
snippet = result.get('description', '') + ' ' + result.get('title', '')
# Pattern for Polish Google reviews: "4,5 (123 opinii)" or "4.5 · 123 reviews"
rating_patterns = [
r'(\d+[,\.]\d)\s*[·\(]\s*(\d+)\s*(?:opinii|recenzji|reviews)',
r'ocena[:\s]+(\d+[,\.]\d).*?(\d+)\s*(?:opinii|recenzji)',
r'rating[:\s]+(\d+[,\.]\d).*?(\d+)\s*(?:reviews|opinii)',
]
for pattern in rating_patterns:
match = re.search(pattern, snippet, re.IGNORECASE)
if match:
rating_str = match.group(1).replace(',', '.')
reviews_str = match.group(2)
return {
'google_rating': round(float(rating_str), 1),
'google_reviews_count': int(reviews_str),
}
logger.info(f"No Google reviews data found in Brave results for '{company_name}'")
return None
except requests.exceptions.Timeout:
logger.warning(f"Timeout searching Brave for '{company_name}' reviews")
return None
except requests.exceptions.RequestException as e:
logger.warning(f"Brave API request failed for '{company_name}': {e}")
return None
except Exception as e:
logger.warning(f"Error parsing Brave results for '{company_name}': {e}")
return None
def _search_brave(self, query: str, platform: str) -> Optional[str]:
"""
Perform Brave search and extract relevant URL.
@ -512,6 +853,15 @@ class SocialMediaAuditor:
self.website_auditor = WebsiteAuditor()
self.brave_searcher = BraveSearcher()
# Initialize Google Places searcher if API key is available
google_places_api_key = os.getenv('GOOGLE_PLACES_API_KEY')
if google_places_api_key:
self.google_places_searcher = GooglePlacesSearcher(api_key=google_places_api_key)
logger.info('Google Places API key found - using Places API for reviews')
else:
self.google_places_searcher = None
logger.info('GOOGLE_PLACES_API_KEY not set - falling back to Brave Search for reviews')
def get_companies(self, company_ids: Optional[List[int]] = None,
batch_start: Optional[int] = None,
batch_end: Optional[int] = None) -> List[Dict]:
@ -546,6 +896,18 @@ class SocialMediaAuditor:
return [dict(row._mapping) for row in result]
def get_company_id_by_slug(self, slug: str) -> Optional[int]:
"""Get company ID by slug."""
with self.Session() as session:
query = text("""
SELECT id FROM companies WHERE slug = :slug
""")
result = session.execute(query, {'slug': slug})
row = result.fetchone()
if row:
return row[0]
return None
def audit_company(self, company: Dict) -> Dict[str, Any]:
"""
Perform full audit for a single company.
@ -589,11 +951,31 @@ class SocialMediaAuditor:
result['social_media'] = website_social
# 4. Google reviews search
# 4. Google reviews search - prefer Google Places API if available
try:
result['google_reviews'] = self.brave_searcher.search_google_reviews(
company['name'], city
)
if self.google_places_searcher:
# Use Google Places API directly for accurate data
place_id = self.google_places_searcher.find_place(company['name'], city)
if place_id:
details = self.google_places_searcher.get_place_details(place_id)
result['google_reviews'] = {
'google_rating': details.get('google_rating'),
'google_reviews_count': details.get('google_reviews_count'),
'opening_hours': details.get('opening_hours'),
'business_status': details.get('business_status'),
}
else:
result['google_reviews'] = {
'google_rating': None,
'google_reviews_count': None,
'opening_hours': None,
'business_status': None,
}
else:
# Fallback to Brave Search
result['google_reviews'] = self.brave_searcher.search_google_reviews(
company['name'], city
)
except Exception as e:
result['errors'].append(f'Google reviews search failed: {str(e)}')
@ -755,6 +1137,7 @@ class SocialMediaAuditor:
def main():
parser = argparse.ArgumentParser(description='Social Media & Website Audit')
parser.add_argument('--company-id', type=int, help='Audit single company by ID')
parser.add_argument('--company-slug', type=str, help='Audit single company by slug')
parser.add_argument('--batch', type=str, help='Audit batch of companies (e.g., 1-10)')
parser.add_argument('--all', action='store_true', help='Audit all companies')
parser.add_argument('--dry-run', action='store_true', help='Print results without saving')
@ -769,6 +1152,14 @@ def main():
if args.company_id:
summary = auditor.run_audit(company_ids=[args.company_id], dry_run=args.dry_run)
elif args.company_slug:
# Look up company ID by slug
company_id = auditor.get_company_id_by_slug(args.company_slug)
if company_id:
summary = auditor.run_audit(company_ids=[company_id], dry_run=args.dry_run)
else:
print(f"Error: Company with slug '{args.company_slug}' not found")
sys.exit(1)
elif args.batch:
start, end = map(int, args.batch.split('-'))
summary = auditor.run_audit(batch_start=start, batch_end=end, dry_run=args.dry_run)

View File

@ -0,0 +1,120 @@
#!/usr/bin/env python3
"""
Verify Google Places API integration for social_media_audit.py.
This script tests the GooglePlacesSearcher class directly without
requiring database access.
"""
import os
import sys
from pathlib import Path
# Add user site-packages to path
sys.path.insert(0, '/Users/maciejpi/Library/Python/3.9/lib/python/site-packages')
# Load .env file from project root
try:
from dotenv import load_dotenv
script_dir = Path(__file__).resolve().parent
project_root = script_dir.parent
env_path = project_root / '.env'
if env_path.exists():
load_dotenv(env_path)
print(f"Loaded .env from {env_path}")
except ImportError:
print("python-dotenv not installed, using system environment")
# Import GooglePlacesSearcher from social_media_audit
from social_media_audit import GooglePlacesSearcher, BraveSearcher
def main():
api_key = os.getenv('GOOGLE_PLACES_API_KEY')
print(f"\nGoogle Places API Key: {'*' * 10 + api_key[-8:] if api_key else 'NOT SET'}")
if not api_key or api_key == 'your_places_api_key_here':
print("ERROR: GOOGLE_PLACES_API_KEY not configured in .env")
sys.exit(1)
# Test GooglePlacesSearcher directly
print("\n" + "=" * 60)
print("Testing GooglePlacesSearcher for INPI company")
print("=" * 60)
searcher = GooglePlacesSearcher(api_key=api_key)
# Step 1: Find place
print("\n1. Finding place for 'INPI' in Wejherowo...")
place_id = searcher.find_place('INPI', 'Wejherowo')
if not place_id:
print(" ERROR: Could not find INPI on Google Places")
print(" This could mean:")
print(" - The company doesn't have a Google Business Profile")
print(" - The API key doesn't have Places API enabled")
print(" - The search query needs adjustment")
sys.exit(1)
print(f" Found place_id: {place_id}")
# Step 2: Get place details
print("\n2. Getting place details...")
details = searcher.get_place_details(place_id)
print(f"\n Results:")
print(f" - google_rating: {details.get('google_rating')}")
print(f" - google_reviews_count: {details.get('google_reviews_count')}")
print(f" - business_status: {details.get('business_status')}")
print(f" - opening_hours: {'Yes' if details.get('opening_hours') else 'Not available'}")
if details.get('opening_hours'):
hours = details.get('opening_hours', {})
if hours.get('weekday_text'):
print(" - Hours:")
for day in hours['weekday_text']:
print(f" {day}")
# Step 3: Test via BraveSearcher.search_google_reviews
print("\n" + "=" * 60)
print("Testing BraveSearcher.search_google_reviews()")
print("=" * 60)
brave = BraveSearcher()
result = brave.search_google_reviews('INPI', 'Wejherowo')
print(f"\n Results:")
print(f" - google_rating: {result.get('google_rating')}")
print(f" - google_reviews_count: {result.get('google_reviews_count')}")
print(f" - business_status: {result.get('business_status')}")
print(f" - opening_hours: {'Yes' if result.get('opening_hours') else 'Not available'}")
# Verify expected data
print("\n" + "=" * 60)
print("VERIFICATION SUMMARY")
print("=" * 60)
success = True
if result.get('google_rating') is not None:
print(f"[PASS] google_rating present: {result['google_rating']}")
else:
print("[FAIL] google_rating is None")
success = False
if result.get('google_reviews_count') is not None:
print(f"[PASS] google_reviews_count present: {result['google_reviews_count']}")
else:
print("[FAIL] google_reviews_count is None")
success = False
if success:
print("\n[SUCCESS] Google Places API integration is working!")
print("The social_media_audit.py can now collect Google reviews data.")
else:
print("\n[WARNING] Some data was not retrieved.")
print("Check if the business has a Google Business Profile with reviews.")
return 0 if success else 1
if __name__ == '__main__':
sys.exit(main())

File diff suppressed because it is too large Load Diff