mirror of
https://github.com/soxoj/maigret.git
synced 2026-05-07 06:24:35 +00:00
updates to webinterface
This commit is contained in:
+2
-1
@@ -495,7 +495,8 @@ async def main():
|
|||||||
|
|
||||||
if args.web:
|
if args.web:
|
||||||
from maigret.web.app import app
|
from maigret.web.app import app
|
||||||
app.run(port=args.web) # Use the port from arguments
|
port = args.web if isinstance(args.web, int) else 5000
|
||||||
|
app.run(port=port) # Use the port from arguments
|
||||||
|
|
||||||
# Usernames initial list
|
# Usernames initial list
|
||||||
usernames = {
|
usernames = {
|
||||||
|
|||||||
+7
-20
@@ -6,6 +6,7 @@ import asyncio
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
import maigret
|
import maigret
|
||||||
|
import maigret.settings
|
||||||
from maigret.sites import MaigretDatabase
|
from maigret.sites import MaigretDatabase
|
||||||
from maigret.report import generate_report_context
|
from maigret.report import generate_report_context
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ job_results = {}
|
|||||||
MAIGRET_DB_FILE = os.path.join('maigret', 'resources', 'data.json')
|
MAIGRET_DB_FILE = os.path.join('maigret', 'resources', 'data.json')
|
||||||
COOKIES_FILE = "cookies.txt"
|
COOKIES_FILE = "cookies.txt"
|
||||||
UPLOAD_FOLDER = 'uploads'
|
UPLOAD_FOLDER = 'uploads'
|
||||||
REPORTS_FOLDER = 'reports'
|
REPORTS_FOLDER = os.path.abspath('/tmp/maigret_reports')
|
||||||
|
|
||||||
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
||||||
os.makedirs(REPORTS_FOLDER, exist_ok=True)
|
os.makedirs(REPORTS_FOLDER, exist_ok=True)
|
||||||
@@ -31,8 +32,7 @@ def setup_logger(log_level, name):
|
|||||||
return logger
|
return logger
|
||||||
|
|
||||||
async def maigret_search(username, options):
|
async def maigret_search(username, options):
|
||||||
logger = setup_logger(logging.DEBUG, 'maigret')
|
logger = setup_logger(logging.WARNING, 'maigret')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
db = MaigretDatabase().load_from_path(MAIGRET_DB_FILE)
|
db = MaigretDatabase().load_from_path(MAIGRET_DB_FILE)
|
||||||
sites = db.ranked_sites_dict(top=int(options.get('top_sites', 500)))
|
sites = db.ranked_sites_dict(top=int(options.get('top_sites', 500)))
|
||||||
@@ -45,7 +45,6 @@ async def maigret_search(username, options):
|
|||||||
id_type=options.get('id_type', 'username'),
|
id_type=options.get('id_type', 'username'),
|
||||||
cookies=COOKIES_FILE if options.get('use_cookies') else None,
|
cookies=COOKIES_FILE if options.get('use_cookies') else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
return results
|
return results
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error during search: {str(e)}")
|
logger.error(f"Error during search: {str(e)}")
|
||||||
@@ -83,7 +82,6 @@ def process_search_task(usernames, options, timestamp):
|
|||||||
for username, id_type, results in general_results:
|
for username, id_type, results in general_results:
|
||||||
report_base = os.path.join(session_folder, f"report_{username}")
|
report_base = os.path.join(session_folder, f"report_{username}")
|
||||||
|
|
||||||
# Save reports in different formats
|
|
||||||
csv_path = f"{report_base}.csv"
|
csv_path = f"{report_base}.csv"
|
||||||
json_path = f"{report_base}.json"
|
json_path = f"{report_base}.json"
|
||||||
pdf_path = f"{report_base}.pdf"
|
pdf_path = f"{report_base}.pdf"
|
||||||
@@ -96,7 +94,6 @@ def process_search_task(usernames, options, timestamp):
|
|||||||
maigret.report.save_pdf_report(pdf_path, context)
|
maigret.report.save_pdf_report(pdf_path, context)
|
||||||
maigret.report.save_html_report(html_path, context)
|
maigret.report.save_html_report(html_path, context)
|
||||||
|
|
||||||
# Extract claimed profiles
|
|
||||||
claimed_profiles = []
|
claimed_profiles = []
|
||||||
for site_name, site_data in results.items():
|
for site_name, site_data in results.items():
|
||||||
if (site_data.get('status') and
|
if (site_data.get('status') and
|
||||||
@@ -109,7 +106,6 @@ def process_search_task(usernames, options, timestamp):
|
|||||||
|
|
||||||
individual_reports.append({
|
individual_reports.append({
|
||||||
'username': username,
|
'username': username,
|
||||||
# Must create paths relative to REPORTS_FOLDER
|
|
||||||
'csv_file': os.path.join(f"search_{timestamp}", f"report_{username}.csv"),
|
'csv_file': os.path.join(f"search_{timestamp}", f"report_{username}.csv"),
|
||||||
'json_file': os.path.join(f"search_{timestamp}", f"report_{username}.json"),
|
'json_file': os.path.join(f"search_{timestamp}", f"report_{username}.json"),
|
||||||
'pdf_file': os.path.join(f"search_{timestamp}", f"report_{username}.pdf"),
|
'pdf_file': os.path.join(f"search_{timestamp}", f"report_{username}.pdf"),
|
||||||
@@ -144,7 +140,6 @@ def search():
|
|||||||
flash('At least one username is required', 'danger')
|
flash('At least one username is required', 'danger')
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
# Split usernames by common separators
|
|
||||||
usernames = [u.strip() for u in usernames_input.replace(',', ' ').split() if u.strip()]
|
usernames = [u.strip() for u in usernames_input.replace(',', ' ').split() if u.strip()]
|
||||||
|
|
||||||
# Create timestamp for this search session
|
# Create timestamp for this search session
|
||||||
@@ -152,11 +147,10 @@ def search():
|
|||||||
|
|
||||||
logging.info(f"Starting search for usernames: {usernames}")
|
logging.info(f"Starting search for usernames: {usernames}")
|
||||||
|
|
||||||
# Collect options from form
|
|
||||||
options = {
|
options = {
|
||||||
'top_sites': request.form.get('top_sites', '500'),
|
'top_sites': request.form.get('top_sites', '500'),
|
||||||
'timeout': request.form.get('timeout', '30'),
|
'timeout': request.form.get('timeout', '30'),
|
||||||
'id_type': request.form.get('id_type', 'username'),
|
'id_type': 'username', # fixed as username
|
||||||
'use_cookies': 'use_cookies' in request.form,
|
'use_cookies': 'use_cookies' in request.form,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +162,6 @@ def search():
|
|||||||
background_jobs[timestamp]['thread'].start()
|
background_jobs[timestamp]['thread'].start()
|
||||||
|
|
||||||
logging.info(f"Search job started with timestamp: {timestamp}")
|
logging.info(f"Search job started with timestamp: {timestamp}")
|
||||||
flash('Search started. Please wait while we process your request...', 'info')
|
|
||||||
|
|
||||||
# Redirect to status page
|
# Redirect to status page
|
||||||
return redirect(url_for('status', timestamp=timestamp))
|
return redirect(url_for('status', timestamp=timestamp))
|
||||||
@@ -191,35 +184,30 @@ def status(timestamp):
|
|||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
if result['status'] == 'completed':
|
if result['status'] == 'completed':
|
||||||
# Redirect to results page
|
# Redirect to results page once done
|
||||||
return redirect(url_for('results', session_id=result['session_folder']))
|
return redirect(url_for('results', session_id=result['session_folder']))
|
||||||
else:
|
else:
|
||||||
error_msg = result.get('error', 'Unknown error occurred')
|
error_msg = result.get('error', 'Unknown error occurred')
|
||||||
flash(f'Search failed: {error_msg}', 'danger')
|
flash(f'Search failed: {error_msg}', 'danger')
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
# If job is still running, show status page
|
# If job is still running, show status page with a simple spinner
|
||||||
logging.info(f"Job still running for timestamp: {timestamp}")
|
|
||||||
return render_template('status.html', timestamp=timestamp)
|
return render_template('status.html', timestamp=timestamp)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/results/<session_id>')
|
@app.route('/results/<session_id>')
|
||||||
def results(session_id):
|
def results(session_id):
|
||||||
# Validate session_id format
|
|
||||||
if not session_id.startswith('search_'):
|
if not session_id.startswith('search_'):
|
||||||
flash('Invalid results session format', 'danger')
|
flash('Invalid results session format', 'danger')
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
# Find matching result data
|
|
||||||
result_data = next(
|
result_data = next(
|
||||||
(r for r in job_results.values()
|
(r for r in job_results.values()
|
||||||
if r.get('status') == 'completed' and r['session_folder'] == session_id),
|
if r.get('status') == 'completed' and r['session_folder'] == session_id),
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
|
|
||||||
if not result_data:
|
|
||||||
flash('Results not found or search is still in progress', 'warning')
|
|
||||||
return redirect(url_for('index'))
|
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'results.html',
|
'results.html',
|
||||||
@@ -231,7 +219,6 @@ def results(session_id):
|
|||||||
|
|
||||||
@app.route('/reports/<path:filename>')
|
@app.route('/reports/<path:filename>')
|
||||||
def download_report(filename):
|
def download_report(filename):
|
||||||
"""Serve report files"""
|
|
||||||
try:
|
try:
|
||||||
file_path = os.path.join(REPORTS_FOLDER, filename)
|
file_path = os.path.join(REPORTS_FOLDER, filename)
|
||||||
return send_file(file_path)
|
return send_file(file_path)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<h1 class="mb-4">Processing Search</h1>
|
<h1 class="mb-4">Search Results</h1>
|
||||||
|
|
||||||
{% with messages = get_flashed_messages() %}
|
{% with messages = get_flashed_messages() %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
@@ -11,23 +11,46 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
<div class="text-center my-5">
|
<p>The search has completed. Below are the results:</p>
|
||||||
<div class="spinner-border text-primary" role="status">
|
|
||||||
<span class="visually-hidden">Loading...</span>
|
|
||||||
</div>
|
|
||||||
<p class="mt-3">Processing your search request. Please wait...</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
<!-- Display the combined graph if available -->
|
||||||
// Check status every 2 seconds
|
{% if graph_file %}
|
||||||
setInterval(function() {
|
<h3>Combined Graph</h3>
|
||||||
fetch(window.location.href)
|
<iframe src="{{ url_for('download_report', filename=graph_file) }}" style="width:100%; height:600px; border:none;"></iframe>
|
||||||
.then(response => {
|
{% endif %}
|
||||||
if (response.redirected) {
|
|
||||||
window.location.href = response.url;
|
<hr>
|
||||||
}
|
|
||||||
});
|
<!-- Display individual reports -->
|
||||||
}, 2000);
|
{% if individual_reports %}
|
||||||
</script>
|
<h3>Individual Reports</h3>
|
||||||
|
<ul class="list-group">
|
||||||
|
{% for report in individual_reports %}
|
||||||
|
<li class="list-group-item">
|
||||||
|
<h5>{{ report.username }}</h5>
|
||||||
|
<p>
|
||||||
|
<a href="{{ url_for('download_report', filename=report.csv_file) }}">CSV Report</a> |
|
||||||
|
<a href="{{ url_for('download_report', filename=report.json_file) }}">JSON Report</a> |
|
||||||
|
<a href="{{ url_for('download_report', filename=report.pdf_file) }}">PDF Report</a> |
|
||||||
|
<a href="{{ url_for('download_report', filename=report.html_file) }}">HTML Report</a>
|
||||||
|
</p>
|
||||||
|
{% if report.claimed_profiles %}
|
||||||
|
<strong>Claimed Profiles:</strong>
|
||||||
|
<ul>
|
||||||
|
{% for profile in report.claimed_profiles %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ profile.url }}" target="_blank">{{ profile.site_name }}</a> (Tags: {{ profile.tags|join(', ') }})
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
<p>No claimed profiles found.</p>
|
||||||
|
{% endif %}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
<p>No individual reports available.</p>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,26 +1,16 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container mt-4">
|
<div class="container mt-4 text-center">
|
||||||
<div class="card">
|
<h2>Search in progress...</h2>
|
||||||
<div class="card-body text-center">
|
<p>Your request is being processed in the background. This page will automatically redirect once the results are ready.</p>
|
||||||
<h2>Processing Search Request</h2>
|
<div class="spinner-border text-primary" role="status">
|
||||||
<div class="alert alert-info">
|
<span class="visually-hidden">Loading...</span>
|
||||||
Your search is being processed. This page will automatically redirect to the results when complete.
|
|
||||||
</div>
|
|
||||||
<div class="progress mb-3">
|
|
||||||
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 100%"></div>
|
|
||||||
</div>
|
|
||||||
<div class="spinner-border text-primary" role="status">
|
|
||||||
<span class="visually-hidden">Loading...</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Simple page refresh every 2 seconds
|
// Auto-refresh the page every 5 seconds to check completion
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, 2000);
|
}, 5000);
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user