Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -1,4 +1,95 @@
|
|
1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
import os, re, json, sqlite3, logging
|
3 |
|
4 |
app = Flask(__name__)
|
@@ -463,6 +554,7 @@ body{margin:0;font-family:Nunito,sans-serif;background:#f6f8fb;}
|
|
463 |
.form-group{margin-bottom:15px;}
|
464 |
.form-group label{display:block;margin-bottom:5px;font-weight:600;}
|
465 |
.form-control{width:100%;padding:8px;border:1px solid #ddd;border-radius:4px;box-sizing:border-box;}
|
|
|
466 |
.btn{padding:8px 15px;border:none;border-radius:4px;cursor:pointer;font-weight:600;}
|
467 |
.btn-primary{background:#4a6dd8;color:white;}
|
468 |
.btn-danger{background:#e53e3e;color:white;}
|
@@ -727,11 +819,23 @@ function loadManage() {
|
|
727 |
<div class="manage-panel">
|
728 |
<h2>Add New URL</h2>
|
729 |
<div class="form-group">
|
730 |
-
<label for="new-url">URL</label>
|
731 |
<input type="text" id="new-url" class="form-control" placeholder="https://example.com">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
732 |
</div>
|
733 |
-
<button onclick="addUrl()" class="btn btn-primary">Add URL</button>
|
734 |
<div id="add-status" class="status"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
735 |
|
736 |
<h2>Manage Saved URLs</h2>
|
737 |
<div id="url-list" class="url-list">Loading...</div>
|
|
|
1 |
+
function addBatchUrls() {
|
2 |
+
const textarea = document.getElementById('batch-urls');
|
3 |
+
const text = textarea.value.trim();
|
4 |
+
|
5 |
+
if (!text) {
|
6 |
+
showStatus('add-status', 'Please enter at least one URL', false);
|
7 |
+
return;
|
8 |
+
}
|
9 |
+
|
10 |
+
// Split by newlines and filter out empty lines
|
11 |
+
let urls = text.split(/\r?\n/).filter(url => url.trim() !== '');
|
12 |
+
|
13 |
+
// Limit to 100 URLs
|
14 |
+
if (urls.length > 100) {
|
15 |
+
showStatus('add-status', 'Too many URLs. Limited to 100 at once.', false);
|
16 |
+
urls = urls.slice(0, 100);
|
17 |
+
}
|
18 |
+
|
19 |
+
if (urls.length === 0) {
|
20 |
+
showStatus('add-status', 'No valid URLs found', false);
|
21 |
+
return;
|
22 |
+
}
|
23 |
+
|
24 |
+
// Show progress bar
|
25 |
+
const progressBar = document.getElementById('progress-bar');
|
26 |
+
const progressFill = document.getElementById('progress-fill');
|
27 |
+
const progressText = document.getElementById('progress-text');
|
28 |
+
progressBar.style.display = 'block';
|
29 |
+
progressFill.style.width = '0%';
|
30 |
+
progressText.textContent = '0%';
|
31 |
+
|
32 |
+
// Add URLs one by one
|
33 |
+
let processed = 0;
|
34 |
+
let succeeded = 0;
|
35 |
+
|
36 |
+
function updateProgress() {
|
37 |
+
const percentage = Math.round((processed / urls.length) * 100);
|
38 |
+
progressFill.style.width = percentage + '%';
|
39 |
+
progressText.textContent = `${processed}/${urls.length} (${percentage}%)`;
|
40 |
+
}
|
41 |
+
|
42 |
+
function addNextUrl(index) {
|
43 |
+
if (index >= urls.length) {
|
44 |
+
// All done
|
45 |
+
setTimeout(() => {
|
46 |
+
progressBar.style.display = 'none';
|
47 |
+
textarea.value = '';
|
48 |
+
showStatus('add-status', `Added ${succeeded} of ${urls.length} URLs successfully`, true);
|
49 |
+
|
50 |
+
// Reload URL list and favorites
|
51 |
+
loadUrlList();
|
52 |
+
if (active === 'Favorites') {
|
53 |
+
loadFavorites(currentPage);
|
54 |
+
}
|
55 |
+
}, 500);
|
56 |
+
return;
|
57 |
+
}
|
58 |
+
|
59 |
+
const url = urls[index].trim();
|
60 |
+
if (!url) {
|
61 |
+
// Skip empty URLs
|
62 |
+
processed++;
|
63 |
+
updateProgress();
|
64 |
+
addNextUrl(index + 1);
|
65 |
+
return;
|
66 |
+
}
|
67 |
+
|
68 |
+
const formData = new FormData();
|
69 |
+
formData.append('url', url);
|
70 |
+
|
71 |
+
makeRequest('/api/url/add', 'POST', formData, function(data) {
|
72 |
+
processed++;
|
73 |
+
|
74 |
+
if (data.success) {
|
75 |
+
succeeded++;
|
76 |
+
|
77 |
+
// Update localStorage
|
78 |
+
const localUrls = loadFromLocalStorage() || [];
|
79 |
+
if (!localUrls.includes(url)) {
|
80 |
+
localUrls.unshift(url);
|
81 |
+
saveToLocalStorage(localUrls);
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
updateProgress();
|
86 |
+
addNextUrl(index + 1);
|
87 |
+
});
|
88 |
+
}
|
89 |
+
|
90 |
+
// Start adding URLs
|
91 |
+
addNextUrl(0);
|
92 |
+
}from flask import Flask, render_template, request, jsonify
|
93 |
import os, re, json, sqlite3, logging
|
94 |
|
95 |
app = Flask(__name__)
|
|
|
554 |
.form-group{margin-bottom:15px;}
|
555 |
.form-group label{display:block;margin-bottom:5px;font-weight:600;}
|
556 |
.form-control{width:100%;padding:8px;border:1px solid #ddd;border-radius:4px;box-sizing:border-box;}
|
557 |
+
textarea.form-control{min-height:100px;font-family:monospace;resize:vertical;}
|
558 |
.btn{padding:8px 15px;border:none;border-radius:4px;cursor:pointer;font-weight:600;}
|
559 |
.btn-primary{background:#4a6dd8;color:white;}
|
560 |
.btn-danger{background:#e53e3e;color:white;}
|
|
|
819 |
<div class="manage-panel">
|
820 |
<h2>Add New URL</h2>
|
821 |
<div class="form-group">
|
822 |
+
<label for="new-url">Single URL</label>
|
823 |
<input type="text" id="new-url" class="form-control" placeholder="https://example.com">
|
824 |
+
<button onclick="addUrl()" class="btn btn-primary" style="margin-top:10px">Add URL</button>
|
825 |
+
</div>
|
826 |
+
|
827 |
+
<div class="form-group" style="margin-top:20px">
|
828 |
+
<label for="batch-urls">Multiple URLs (up to 100 URLs, one per line)</label>
|
829 |
+
<textarea id="batch-urls" class="form-control" rows="8" placeholder="https://example1.com https://example2.com https://example3.com"></textarea>
|
830 |
+
<button onclick="addBatchUrls()" class="btn btn-primary" style="margin-top:10px">Add All URLs</button>
|
831 |
</div>
|
|
|
832 |
<div id="add-status" class="status"></div>
|
833 |
+
<div id="progress-bar" style="display:none; margin:15px 0;">
|
834 |
+
<div style="height:20px; background-color:#f0f0f0; border-radius:4px; overflow:hidden;">
|
835 |
+
<div id="progress-fill" style="height:100%; width:0%; background-color:#4a6dd8; transition:width 0.3s;"></div>
|
836 |
+
</div>
|
837 |
+
<div id="progress-text" style="text-align:center; margin-top:5px; font-size:14px;">0%</div>
|
838 |
+
</div>
|
839 |
|
840 |
<h2>Manage Saved URLs</h2>
|
841 |
<div id="url-list" class="url-list">Loading...</div>
|