Add full application source

This commit is contained in:
Dr Jones
2026-05-22 12:47:24 -07:00
parent 53138fdd1e
commit c958a06b96
37 changed files with 6642 additions and 0 deletions

0
src/utils/__init__.py Normal file
View File

59
src/utils/file_io.py Normal file
View File

@@ -0,0 +1,59 @@
"""
File I/O utilities for reading/writing password lists and proxy lists.
"""
from pathlib import Path
from typing import List, Optional
from config import PASSWORDS_FILE, PROXIES_FILE, VALID_PROXIES_FILE
def save_passwords(passwords: List[str], filepath: Optional[Path] = None, append: bool = True):
"""Save password list to file. Appends by default."""
path = filepath or PASSWORDS_FILE
mode = "a" if append else "w"
with open(path, mode, encoding="utf-8") as f:
for pwd in passwords:
f.write(pwd + "\n")
def load_passwords(filepath: Optional[Path] = None) -> List[str]:
"""Load passwords from file, stripping whitespace and removing empties."""
path = filepath or PASSWORDS_FILE
if not path.exists():
return []
with open(path, "r", encoding="utf-8") as f:
return [line.strip() for line in f if line.strip()]
def save_proxies(proxies: List[str], filepath: Optional[Path] = None):
"""Save proxy list to file."""
path = filepath or PROXIES_FILE
with open(path, "w", encoding="utf-8") as f:
for proxy in proxies:
f.write(proxy + "\n")
def load_proxies(filepath: Optional[Path] = None) -> List[str]:
"""Load proxies from file."""
path = filepath or PROXIES_FILE
if not path.exists():
return []
with open(path, "r", encoding="utf-8") as f:
return [line.strip() for line in f if line.strip()]
def save_valid_proxies(proxies: List[str]):
"""Save validated proxies to their dedicated file."""
save_proxies(proxies, VALID_PROXIES_FILE)
def load_valid_proxies() -> List[str]:
"""Load validated proxies."""
return load_proxies(VALID_PROXIES_FILE)
def count_lines(filepath: Path) -> int:
"""Count non-empty lines in a file."""
if not filepath.exists():
return 0
with open(filepath, "r", encoding="utf-8") as f:
return sum(1 for line in f if line.strip())

116
src/utils/logger.py Normal file
View File

@@ -0,0 +1,116 @@
"""
Structured logging for the Facebook Recovery System.
Provides both file logging and in-memory log capture for the GUI.
"""
import csv
import logging
import threading
from datetime import datetime
from pathlib import Path
from typing import Optional
from config import ATTEMPT_LOG_FILE
class AttemptLogger:
"""Logs each login attempt to CSV and maintains an in-memory buffer for the GUI."""
def __init__(self, log_path: Optional[Path] = None):
self.log_path = log_path or ATTEMPT_LOG_FILE
self.buffer = [] # In-memory list of log entries for GUI display
self._lock = threading.Lock()
self._init_csv()
def _init_csv(self):
"""Create CSV with headers if it doesn't exist."""
if not self.log_path.exists():
self.log_path.parent.mkdir(parents=True, exist_ok=True)
with open(self.log_path, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow([
"timestamp", "password", "proxy_ip", "proxy_port",
"proxy_protocol", "status_code", "result", "response_time_ms",
"message",
])
def log_attempt(
self,
password: str,
proxy_ip: str,
proxy_port: int,
proxy_protocol: str,
status_code: int,
result: str,
response_time_ms: float,
message: str = "",
):
"""Log a single attempt."""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
entry = {
"timestamp": timestamp,
"password": password,
"proxy_ip": proxy_ip,
"proxy_port": proxy_port,
"proxy_protocol": proxy_protocol,
"status_code": status_code,
"result": result,
"response_time_ms": f"{response_time_ms:.1f}",
"message": message,
}
with self._lock:
# Write to CSV
with open(self.log_path, "a", newline="") as f:
writer = csv.DictWriter(f, fieldnames=entry.keys())
writer.writerow(entry)
# Keep in memory buffer (limit to last 10000 for performance)
self.buffer.append(entry)
if len(self.buffer) > 10000:
self.buffer = self.buffer[-5000:]
def get_recent(self, count: int = 100) -> list:
"""Get the most recent log entries."""
with self._lock:
return self.buffer[-count:]
def get_stats(self) -> dict:
"""Get aggregate statistics from the log."""
with self._lock:
total = len(self.buffer)
successes = sum(1 for e in self.buffer if e["result"] == "SUCCESS")
failures = total - successes
return {
"total": total,
"successes": successes,
"failures": failures,
}
class FileLogger:
"""General purpose file logger for system events."""
def __init__(self, name: str = "facebook_recovery"):
self.logger = logging.getLogger(name)
self.logger.setLevel(logging.DEBUG)
# Guard against adding duplicate handlers when re-instantiated
if not self.logger.handlers:
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
formatter = logging.Formatter(
"[%(asctime)s] %(levelname)s: %(message)s",
datefmt="%H:%M:%S"
)
ch.setFormatter(formatter)
self.logger.addHandler(ch)
def info(self, msg: str):
self.logger.info(msg)
def debug(self, msg: str):
self.logger.debug(msg)
def warning(self, msg: str):
self.logger.warning(msg)
def error(self, msg: str):
self.logger.error(msg)