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 # Free tier: 25,000 requests/day
GOOGLE_PAGESPEED_API_KEY=your_pagespeed_api_key_here 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) # Email Configuration (for user verification)
MAIL_SERVER=smtp.gmail.com MAIL_SERVER=smtp.gmail.com
MAIL_PORT=587 MAIL_PORT=587

View File

@ -17,6 +17,9 @@ psycopg2-binary==2.9.9
# Google Gemini AI # Google Gemini AI
google-generativeai==0.3.2 google-generativeai==0.3.2
# Google Maps/Places API
googlemaps==4.10.0
# Environment Configuration # Environment Configuration
python-dotenv==1.0.0 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 typing import Optional, Dict, List, Tuple, Any
from urllib.parse import urlparse from urllib.parse import urlparse
import time 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 import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
@ -408,9 +422,9 @@ class WebsiteAuditor:
if matches: if matches:
# Get first valid match, excluding common false positives # Get first valid match, excluding common false positives
for match in matches: 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, []) 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 # Construct full URL
if platform == 'facebook': if platform == 'facebook':
url = f'https://facebook.com/{match}' url = f'https://facebook.com/{match}'
@ -439,6 +453,207 @@ class WebsiteAuditor:
return result 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: class BraveSearcher:
"""Search for social media profiles and Google reviews using Brave Search.""" """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]: def search_google_reviews(self, company_name: str, city: str = 'Wejherowo') -> Dict[str, Any]:
""" """
Search for Google reviews via Brave. Search for Google reviews using Google Places API.
Returns dict with rating, reviews_count.
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 = { result = {
'google_rating': None, 'google_rating': None,
'google_reviews_count': None, 'google_reviews_count': None,
'opening_hours': None,
'business_status': None,
} }
try: try:
query = f'{company_name} {city} opinie google' # Use Google Places API for accurate data
# This would use Brave API or scraping google_api_key = os.getenv('GOOGLE_PLACES_API_KEY')
# For now, placeholder
pass 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: 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 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]: def _search_brave(self, query: str, platform: str) -> Optional[str]:
""" """
Perform Brave search and extract relevant URL. Perform Brave search and extract relevant URL.
@ -512,6 +853,15 @@ class SocialMediaAuditor:
self.website_auditor = WebsiteAuditor() self.website_auditor = WebsiteAuditor()
self.brave_searcher = BraveSearcher() 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, def get_companies(self, company_ids: Optional[List[int]] = None,
batch_start: Optional[int] = None, batch_start: Optional[int] = None,
batch_end: Optional[int] = None) -> List[Dict]: batch_end: Optional[int] = None) -> List[Dict]:
@ -546,6 +896,18 @@ class SocialMediaAuditor:
return [dict(row._mapping) for row in result] 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]: def audit_company(self, company: Dict) -> Dict[str, Any]:
""" """
Perform full audit for a single company. Perform full audit for a single company.
@ -589,11 +951,31 @@ class SocialMediaAuditor:
result['social_media'] = website_social result['social_media'] = website_social
# 4. Google reviews search # 4. Google reviews search - prefer Google Places API if available
try: try:
result['google_reviews'] = self.brave_searcher.search_google_reviews( if self.google_places_searcher:
company['name'], city # 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: except Exception as e:
result['errors'].append(f'Google reviews search failed: {str(e)}') result['errors'].append(f'Google reviews search failed: {str(e)}')
@ -755,6 +1137,7 @@ class SocialMediaAuditor:
def main(): def main():
parser = argparse.ArgumentParser(description='Social Media & Website Audit') 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-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('--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('--all', action='store_true', help='Audit all companies')
parser.add_argument('--dry-run', action='store_true', help='Print results without saving') parser.add_argument('--dry-run', action='store_true', help='Print results without saving')
@ -769,6 +1152,14 @@ def main():
if args.company_id: if args.company_id:
summary = auditor.run_audit(company_ids=[args.company_id], dry_run=args.dry_run) 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: elif args.batch:
start, end = map(int, args.batch.split('-')) start, end = map(int, args.batch.split('-'))
summary = auditor.run_audit(batch_start=start, batch_end=end, dry_run=args.dry_run) 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