|
from flask import Flask, request, jsonify, render_template |
|
from flask_socketio import SocketIO, emit |
|
import json |
|
import uuid |
|
import os |
|
from datetime import datetime |
|
|
|
app = Flask(__name__) |
|
app.config['SECRET_KEY'] = 'your-secret-key' |
|
socketio = SocketIO(app) |
|
|
|
|
|
jobs = [] |
|
connected_clients = {} |
|
|
|
def save_jobs(): |
|
"""Save jobs to JSON file""" |
|
try: |
|
with open('jobs.json', 'w') as f: |
|
json.dump(jobs, f) |
|
except Exception as e: |
|
print(f"Error saving jobs: {e}") |
|
|
|
def load_jobs(): |
|
"""Load jobs from JSON file""" |
|
try: |
|
if os.path.exists('jobs.json') and os.path.getsize('jobs.json') > 0: |
|
with open('jobs.json', 'r') as f: |
|
return json.load(f) |
|
except Exception as e: |
|
print(f"Error loading jobs: {e}") |
|
return [] |
|
|
|
@app.route('/') |
|
def index(): |
|
return render_template('index.html') |
|
|
|
@app.route('/submit_job', methods=['POST']) |
|
def submit_job(): |
|
youtube_url = request.form.get("youtube_url") |
|
exit_time = int(request.form.get("exit_time", 10)) |
|
mode = request.form.get("mode", "once") |
|
job_id = str(uuid.uuid4()) |
|
|
|
job = { |
|
"job_id": job_id, |
|
"youtube_url": youtube_url, |
|
"exit_time": exit_time, |
|
"mode": mode, |
|
"status": "pending" |
|
} |
|
jobs.append(job) |
|
save_jobs() |
|
|
|
return jsonify({"message": "Job submitted successfully", "job_id": job_id}) |
|
|
|
@socketio.on('client_info') |
|
def handle_client_info(data): |
|
client_id = request.sid |
|
connected_clients[client_id] = { |
|
'ip': data.get('ip', 'Unknown'), |
|
'country': data.get('country', 'Unknown'), |
|
'city': data.get('city', 'Unknown'), |
|
'connected_at': datetime.now().isoformat() |
|
} |
|
|
|
emit('client_connected', { |
|
'client_id': client_id, |
|
'ip': data.get('ip', 'Unknown'), |
|
'country': data.get('country', 'Unknown'), |
|
'city': data.get('city', 'Unknown') |
|
}, broadcast=True) |
|
|
|
@socketio.on('disconnect') |
|
def handle_disconnect(): |
|
client_id = request.sid |
|
if client_id in connected_clients: |
|
del connected_clients[client_id] |
|
emit('client_disconnected', client_id, broadcast=True) |
|
|
|
@app.route('/get_job', methods=['GET']) |
|
def get_job(): |
|
for job in jobs: |
|
if job["status"] == "pending": |
|
return jsonify(job) |
|
return jsonify({"message": "No pending jobs"}) |
|
|
|
@app.route('/update_job_status', methods=['POST']) |
|
def update_job_status(): |
|
data = request.get_json() |
|
job_id = data.get("job_id") |
|
status = data.get("status", "done") |
|
|
|
for job in jobs: |
|
if job["job_id"] == job_id: |
|
job["status"] = status |
|
break |
|
|
|
save_jobs() |
|
return jsonify({"message": f"Job {job_id} marked as {status}"}) |
|
|
|
if __name__ == "__main__": |
|
jobs = load_jobs() |
|
|
|
if not os.path.exists('templates'): |
|
os.makedirs('templates') |
|
|
|
template_path = os.path.join('templates', 'index.html') |
|
if not os.path.exists(template_path): |
|
with open(template_path, 'w') as f: |
|
f.write('''<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>YouTube Job Manager</title> |
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> |
|
<style> |
|
body { padding: 20px; } |
|
.connection-status { margin-bottom: 20px; } |
|
</style> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<div class="row"> |
|
<div class="col-md-8 offset-md-2"> |
|
<h1 class="mb-4">YouTube Job Manager</h1> |
|
|
|
<div class="card mb-4"> |
|
<div class="card-header"> |
|
<h5 class="mb-0">Connected Clients</h5> |
|
</div> |
|
<div class="card-body"> |
|
<table class="table" id="clientsTable"> |
|
<thead> |
|
<tr> |
|
<th>IP Address</th> |
|
<th>Country</th> |
|
<th>City</th> |
|
<th>Status</th> |
|
</tr> |
|
</thead> |
|
<tbody id="clientsTableBody"> |
|
</tbody> |
|
</table> |
|
</div> |
|
</div> |
|
|
|
<div class="card"> |
|
<div class="card-header"> |
|
<h5 class="mb-0">Submit New Job</h5> |
|
</div> |
|
<div class="card-body"> |
|
<form action="/submit_job" method="post" class="needs-validation" novalidate> |
|
<div class="mb-3"> |
|
<label for="youtube_url" class="form-label">YouTube URL:</label> |
|
<input type="text" class="form-control" id="youtube_url" name="youtube_url" required> |
|
</div> |
|
|
|
<div class="mb-3"> |
|
<label for="exit_time" class="form-label">Exit Time (seconds):</label> |
|
<input type="number" class="form-control" id="exit_time" name="exit_time" value="10" required> |
|
</div> |
|
|
|
<div class="mb-3"> |
|
<label for="mode" class="form-label">Mode:</label> |
|
<select class="form-select" id="mode" name="mode"> |
|
<option value="once">Once</option> |
|
<option value="again">Again</option> |
|
<option value="continuous">Continuous</option> |
|
</select> |
|
</div> |
|
|
|
<button type="submit" class="btn btn-primary">Submit Job</button> |
|
</form> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script> |
|
<script> |
|
const socket = io(); |
|
|
|
socket.on('connect', () => { |
|
console.log('Connected to server'); |
|
}); |
|
|
|
socket.on('client_connected', (data) => { |
|
const tableBody = document.getElementById('clientsTableBody'); |
|
const row = document.createElement('tr'); |
|
row.setAttribute('data-client-id', data.client_id); |
|
row.innerHTML = ` |
|
<td>${data.ip}</td> |
|
<td>${data.country}</td> |
|
<td>${data.city}</td> |
|
<td><span class="badge bg-success">Connected</span></td> |
|
`; |
|
tableBody.appendChild(row); |
|
}); |
|
|
|
socket.on('client_disconnected', (clientId) => { |
|
const row = document.querySelector(`tr[data-client-id="${clientId}"]`); |
|
if (row) { |
|
row.querySelector('.badge').className = 'badge bg-danger'; |
|
row.querySelector('.badge').textContent = 'Disconnected'; |
|
} |
|
}); |
|
</script> |
|
</body> |
|
</html> |
|
''') |
|
|
|
socketio.run(app, host="0.0.0.0", port=7860, debug=False, allow_unsafe_werkzeug=True) |
|
|
|
|