fix: add use tor option

This commit is contained in:
2025-09-13 13:26:39 +02:00
parent fd6a7006b0
commit c1c3e5ca53
6 changed files with 181 additions and 18 deletions

View File

@@ -11,3 +11,11 @@ HEADLESS=false
# Use mock data generation instead of denuncias.yml file (true/false)
# Set to true to generate realistic test data automatically
USE_MOCK_DATA=false
# Use Tor proxy for anonymity (true/false)
# When enabled, routes all browser traffic through Tor
USE_TOR=false
# Tor proxy address (SOCKS5)
# Default Tor proxy address, change if using custom Tor configuration
TOR_PROXY=socks5://127.0.0.1:9050

View File

@@ -15,8 +15,16 @@ docker run -e USE_MOCK_DATA=true jorgeteixe/laliga-denuncias:latest
**¿Por qué?** Este comando genera y envía denuncias falsas automáticamente al sitio oficial de LaLiga. Solo debe usarse en entornos de desarrollo con URLs de prueba.
### 🛑 NO uses VPN
Si vas a hacer denuncias reales, NO uses VPN. LaLiga necesita verificar que eres un denunciante local y serio.
### 🔐 Anonimato con Tor (Opcional)
El sistema incluye soporte para proxy Tor para mayor privacidad. Para habilitarlo:
```bash
# En tu archivo .env
USE_TOR=true
TOR_PROXY=socks5://127.0.0.1:9050
```
**Nota**: Asegurate de tener Tor ejecutandose en tu sistema antes de habilitar esta opcion.
---
@@ -84,6 +92,12 @@ HEADLESS=false
# SIEMPRE false para denuncias reales
USE_MOCK_DATA=false
# Usar proxy Tor para anonimato (opcional)
USE_TOR=false
# Direccion del proxy Tor (SOCKS5)
TOR_PROXY=socks5://127.0.0.1:9050
```
## 🔧 Como Ejecutar

18
docker-compose.local.yml Normal file
View File

@@ -0,0 +1,18 @@
services:
tor-proxy:
image: dperson/torproxy
container_name: tor-sidecar
restart: unless-stopped
laliga-denuncias:
build:
context: .
dockerfile: Dockerfile
container_name: laliga-denuncias
network_mode: "service:tor-proxy"
volumes:
- ./images:/app/images
environment:
- USE_MOCK_DATA=true
- USE_TOR=true
restart: always

18
docker-compose.yml Normal file
View File

@@ -0,0 +1,18 @@
services:
tor-proxy:
image: dperson/torproxy
container_name: tor-sidecar
restart: unless-stopped
laliga-denuncias:
image: jorgeteixe/laliga-denuncias:latest
container_name: laliga-denuncias
network_mode: "service:tor-proxy"
volumes:
- ./images:/app/images
environment:
- USE_MOCK_DATA=true
- USE_TOR=true
restart: always

134
main.py
View File

@@ -3,6 +3,8 @@ import yaml
import random
import glob
import logging
import requests
import time
from dotenv import load_dotenv
from playwright.sync_api import sync_playwright
from faker import Faker
@@ -22,13 +24,63 @@ def setup_logging():
logger = setup_logging()
def wait_for_tor_connection(proxy_server):
"""Wait for Tor connection to be established using Playwright"""
logger.info("Waiting for Tor connection to be established...")
while True:
try:
# Use Playwright to check Tor status through the proxy
with sync_playwright() as p:
browser = p.chromium.launch(
headless=True,
proxy={
"server": proxy_server
}
)
context = browser.new_context()
page = context.new_page()
try:
response = page.goto('https://check.torproject.org/api/ip', timeout=10000)
if response and response.status == 200:
content = page.content()
# Extract JSON from the page content
import re
json_match = re.search(r'\{.*\}', content)
if json_match:
import json
data = json.loads(json_match.group())
if data.get("IsTor") is True:
logger.info(f"Tor connection established! IP: {data.get('IP', 'Unknown')}")
browser.close()
return
else:
logger.info(f"Not using Tor yet. Current IP: {data.get('IP', 'Unknown')}")
else:
logger.warning("Could not parse Tor check response")
else:
logger.warning(f"Tor check failed with status: {response.status if response else 'No response'}")
except Exception as e:
logger.warning(f"Error during Tor check: {e}")
finally:
browser.close()
except Exception as e:
logger.warning(f"Error checking Tor status: {e}")
logger.info("Waiting 10 seconds before next Tor check...")
time.sleep(10)
def close_cookie_consent(page):
try:
logger.info("Waiting for cookie consent dialog to appear...")
reject_button = page.locator("#onetrust-reject-all-handler")
# Wait longer for the cookie banner to appear after page load
reject_button.wait_for(state="visible", timeout=15000)
reject_button.wait_for(state="visible", timeout=30000)
reject_button.click()
logger.info("Cookie consent dialog closed")
@@ -373,9 +425,11 @@ def submit_form(page):
success_heading = page.locator("h2:has-text('FORMULARIO ENVIADO CORRECTAMENTE')")
success_heading.wait_for(state="visible", timeout=10000)
logger.info("Form submitted successfully")
return True
except Exception as e:
logger.error(f"Error submitting form: {e}")
return False
def return_to_form(page):
@@ -409,13 +463,27 @@ def main():
headless = os.getenv("HEADLESS", "true").lower() == "true"
use_mock_data = os.getenv("USE_MOCK_DATA", "false").lower() == "true"
use_tor = os.getenv("USE_TOR", "false").lower() == "true"
proxy_address = os.getenv("TOR_PROXY", "socks5://127.0.0.1:9050")
logger.info(f"Opening browser to: {url}")
logger.info(f"Headless mode: {headless}")
logger.info(f"Use mock data: {use_mock_data}")
logger.info(f"Use Tor: {use_tor}")
if use_tor:
logger.info(f"Tor proxy: {proxy_address}")
# Wait for Tor connection if enabled
if use_tor:
wait_for_tor_connection(proxy_address)
with sync_playwright() as p:
browser = p.chromium.launch(headless=headless)
# Configure browser with or without proxy
browser_options = {"headless": headless}
if use_tor:
browser_options["proxy"] = {"server": proxy_address}
browser = p.chromium.launch(**browser_options)
page = browser.new_page()
page.goto(url)
@@ -425,6 +493,8 @@ def main():
if use_mock_data:
# Continuous mock data mode - generate and submit until stopped
submission_count = 0
failure_count = 0
max_failures = 3
logger.info("Starting continuous mock data mode - will run until stopped")
while True:
@@ -436,31 +506,65 @@ def main():
logger.info(f"Submitting for: {form_data['nombre_local']}")
fill_form(page, form_data)
submit_form(page)
return_to_form(page)
success = submit_form(page)
# Wait between submissions
wait_time = random.randint(3, 8) # Random delay 3-8 seconds
logger.info(f"Waiting {wait_time} seconds before next submission...")
page.wait_for_timeout(wait_time * 1000)
if success:
failure_count = 0 # Reset failure counter on success
return_to_form(page)
# Wait between submissions
wait_time = random.randint(3, 5) # Random delay 3-5 seconds
logger.info(f"Waiting {wait_time} seconds before next submission...")
page.wait_for_timeout(wait_time * 1000)
else:
failure_count += 1
logger.warning(f"Submission failed. Failure count: {failure_count}/{max_failures}")
if failure_count >= max_failures:
logger.error(f"Reached maximum failures ({max_failures}). Exiting application.")
break
# Wait a bit before retrying
logger.info("Waiting 5 seconds before next attempt...")
page.wait_for_timeout(5000)
else:
# YAML file mode - process all submissions once
form_data_list = load_form_data()
failure_count = 0
max_failures = 3
successful_submissions = 0
for i, form_data in enumerate(form_data_list, 1):
logger.info(f"--- Processing submission {i}/{len(form_data_list)} ---")
logger.info(f"Submitting for: {form_data['nombre_local']}")
fill_form(page, form_data)
submit_form(page)
success = submit_form(page)
# Return to form for next submission (except on last one)
if i < len(form_data_list):
return_to_form(page)
logger.info("Waiting 2 seconds before next submission...")
page.wait_for_timeout(2000)
if success:
failure_count = 0 # Reset failure counter on success
successful_submissions += 1
# Return to form for next submission (except on last one)
if i < len(form_data_list):
return_to_form(page)
logger.info("Waiting 2 seconds before next submission...")
page.wait_for_timeout(2000)
else:
failure_count += 1
logger.warning(f"Submission failed. Failure count: {failure_count}/{max_failures}")
if failure_count >= max_failures:
logger.error(f"Reached maximum failures ({max_failures}). Exiting application.")
break
# Return to form to retry or continue
if i < len(form_data_list):
return_to_form(page)
logger.info("Waiting 5 seconds before next attempt...")
page.wait_for_timeout(5000)
logger.info(f"Completed {len(form_data_list)} form submissions successfully")
logger.info(f"Completed {successful_submissions}/{len(form_data_list)} form submissions successfully")
if not headless:
input("Press Enter to close the browser...")

View File

@@ -1,6 +1,6 @@
[project]
name = "l4l1g4-d3nunc145"
version = "0.1.1"
version = "0.1.2"
description = "Automated LaLiga piracy reporting tool for legitimate complaints. Spanish form automation with Docker support."
readme = "README.md"
requires-python = ">=3.13"
@@ -9,4 +9,5 @@ dependencies = [
"playwright>=1.55.0",
"python-dotenv>=1.1.1",
"pyyaml>=6.0.2",
"requests>=2.31.0",
]