Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -6,6 +6,7 @@ import json
|
|
| 6 |
import random
|
| 7 |
from urllib.parse import urlparse, parse_qs
|
| 8 |
from threading import Event
|
|
|
|
| 9 |
|
| 10 |
class ReportSender:
|
| 11 |
def __init__(self):
|
|
@@ -30,7 +31,6 @@ class ReportSender:
|
|
| 30 |
self.is_running = True
|
| 31 |
|
| 32 |
master_urls = [u.strip() for u in master_url_batch.split('\n') if u.strip()]
|
| 33 |
-
|
| 34 |
num_urls = len(master_urls)
|
| 35 |
|
| 36 |
if not master_urls:
|
|
@@ -38,18 +38,42 @@ class ReportSender:
|
|
| 38 |
yield " Error: No valid URLs found in the Report URL Batch input. Ensure each URL starts with 'http' or 'https'.", False, "Stopped"
|
| 39 |
return
|
| 40 |
|
| 41 |
-
|
|
|
|
|
|
|
| 42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
headers = {
|
| 44 |
"User-Agent": USER_AGENT,
|
| 45 |
"Referer": "https://www.tiktok.com/",
|
| 46 |
"Cookie": cookie_header,
|
| 47 |
"Accept-Encoding": "gzip, deflate, br, zstd",
|
|
|
|
| 48 |
}
|
| 49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
log_history = f" Starting batch loop for {num_urls} report types...\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
yield log_history, self.is_running, "Running"
|
| 52 |
total_requests_sent = 0
|
|
|
|
| 53 |
while not self.stop_event.is_set():
|
| 54 |
for i, final_url in enumerate(master_urls):
|
| 55 |
if self.stop_event.is_set():
|
|
@@ -57,8 +81,8 @@ class ReportSender:
|
|
| 57 |
|
| 58 |
delay = random.uniform(1, 3)
|
| 59 |
time.sleep(delay)
|
| 60 |
-
|
| 61 |
-
|
| 62 |
try:
|
| 63 |
query_params = parse_qs(urlparse(final_url).query)
|
| 64 |
reason_code = query_params.get('reason', ['UNKNOWN'])[0]
|
|
@@ -71,17 +95,23 @@ class ReportSender:
|
|
| 71 |
response = requests.get(final_url, headers=headers, timeout=10)
|
| 72 |
timestamp = time.strftime("%H:%M:%S")
|
| 73 |
total_requests_sent += 1
|
|
|
|
|
|
|
| 74 |
is_empty_success = response.status_code == 200 and not response.text.strip()
|
| 75 |
is_json_success = False
|
|
|
|
|
|
|
|
|
|
| 76 |
if not is_empty_success:
|
| 77 |
try:
|
| 78 |
parsed = response.json()
|
| 79 |
-
|
| 80 |
-
is_json_success = True
|
| 81 |
status_code_msg = parsed.get('status_message', 'No Message')
|
| 82 |
-
|
|
|
|
|
|
|
| 83 |
except:
|
| 84 |
-
status_code_msg = "Non-JSON"
|
| 85 |
status_code_val = response.status_code
|
| 86 |
|
| 87 |
is_success = is_empty_success or is_json_success
|
|
@@ -92,9 +122,9 @@ class ReportSender:
|
|
| 92 |
else:
|
| 93 |
status_icon = "⚠️"
|
| 94 |
if not is_empty_success and not is_json_success:
|
| 95 |
-
status_msg = f"
|
| 96 |
else:
|
| 97 |
-
status_msg = f"
|
| 98 |
|
| 99 |
log_entry = (
|
| 100 |
f"[{timestamp}] {status_icon} REQ ({total_requests_sent}): {report_name}\n"
|
|
@@ -148,7 +178,7 @@ with gr.Blocks() as app:
|
|
| 148 |
gr.Markdown("### 2. Report URLs Batch")
|
| 149 |
master_url_batch_input = gr.Textbox(
|
| 150 |
label="Master Signed Report URLs (One full URL per line)",
|
| 151 |
-
placeholder="Paste ONE OR MORE FULLY SIGNED & WORKING report URLs here.
|
| 152 |
lines=5,
|
| 153 |
max_lines=10
|
| 154 |
)
|
|
|
|
| 6 |
import random
|
| 7 |
from urllib.parse import urlparse, parse_qs
|
| 8 |
from threading import Event
|
| 9 |
+
from http.cookies import SimpleCookie
|
| 10 |
|
| 11 |
class ReportSender:
|
| 12 |
def __init__(self):
|
|
|
|
| 31 |
self.is_running = True
|
| 32 |
|
| 33 |
master_urls = [u.strip() for u in master_url_batch.split('\n') if u.strip()]
|
|
|
|
| 34 |
num_urls = len(master_urls)
|
| 35 |
|
| 36 |
if not master_urls:
|
|
|
|
| 38 |
yield " Error: No valid URLs found in the Report URL Batch input. Ensure each URL starts with 'http' or 'https'.", False, "Stopped"
|
| 39 |
return
|
| 40 |
|
| 41 |
+
# FIXED: Updated User-Agent to a current, real version (Chrome 131)
|
| 42 |
+
# Using a fake future version like 143 can trigger bot detection.
|
| 43 |
+
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
|
| 44 |
|
| 45 |
+
# FIXED: Logic to extract csrf token from the cookie string
|
| 46 |
+
csrf_token = ""
|
| 47 |
+
try:
|
| 48 |
+
cookie_parser = SimpleCookie()
|
| 49 |
+
cookie_parser.load(cookie_header)
|
| 50 |
+
if 'tt_csrf_token' in cookie_parser:
|
| 51 |
+
csrf_token = cookie_parser['tt_csrf_token'].value
|
| 52 |
+
except Exception as e:
|
| 53 |
+
print(f"Error parsing cookie for CSRF: {e}")
|
| 54 |
+
|
| 55 |
headers = {
|
| 56 |
"User-Agent": USER_AGENT,
|
| 57 |
"Referer": "https://www.tiktok.com/",
|
| 58 |
"Cookie": cookie_header,
|
| 59 |
"Accept-Encoding": "gzip, deflate, br, zstd",
|
| 60 |
+
"Accept-Language": "en-US,en;q=0.9",
|
| 61 |
}
|
| 62 |
|
| 63 |
+
# FIXED: Add the CSRF header if found. This is critical for different accounts.
|
| 64 |
+
if csrf_token:
|
| 65 |
+
headers["tt-csrf-token"] = csrf_token
|
| 66 |
+
headers["x-secsdk-csrf-token"] = csrf_token
|
| 67 |
+
|
| 68 |
log_history = f" Starting batch loop for {num_urls} report types...\n"
|
| 69 |
+
if csrf_token:
|
| 70 |
+
log_history += " ℹ️ CSRF Token detected and applied to headers.\n"
|
| 71 |
+
else:
|
| 72 |
+
log_history += " ⚠️ WARNING: Could not find 'tt_csrf_token' in cookie. Requests may fail.\n"
|
| 73 |
+
|
| 74 |
yield log_history, self.is_running, "Running"
|
| 75 |
total_requests_sent = 0
|
| 76 |
+
|
| 77 |
while not self.stop_event.is_set():
|
| 78 |
for i, final_url in enumerate(master_urls):
|
| 79 |
if self.stop_event.is_set():
|
|
|
|
| 81 |
|
| 82 |
delay = random.uniform(1, 3)
|
| 83 |
time.sleep(delay)
|
| 84 |
+
|
| 85 |
+
# Setup Log names
|
| 86 |
try:
|
| 87 |
query_params = parse_qs(urlparse(final_url).query)
|
| 88 |
reason_code = query_params.get('reason', ['UNKNOWN'])[0]
|
|
|
|
| 95 |
response = requests.get(final_url, headers=headers, timeout=10)
|
| 96 |
timestamp = time.strftime("%H:%M:%S")
|
| 97 |
total_requests_sent += 1
|
| 98 |
+
|
| 99 |
+
# Logic to determine success
|
| 100 |
is_empty_success = response.status_code == 200 and not response.text.strip()
|
| 101 |
is_json_success = False
|
| 102 |
+
status_code_msg = "No Message"
|
| 103 |
+
status_code_val = "???"
|
| 104 |
+
|
| 105 |
if not is_empty_success:
|
| 106 |
try:
|
| 107 |
parsed = response.json()
|
| 108 |
+
status_code_val = parsed.get('status_code', -1)
|
|
|
|
| 109 |
status_code_msg = parsed.get('status_message', 'No Message')
|
| 110 |
+
|
| 111 |
+
if status_code_val == 0:
|
| 112 |
+
is_json_success = True
|
| 113 |
except:
|
| 114 |
+
status_code_msg = "Non-JSON Response"
|
| 115 |
status_code_val = response.status_code
|
| 116 |
|
| 117 |
is_success = is_empty_success or is_json_success
|
|
|
|
| 122 |
else:
|
| 123 |
status_icon = "⚠️"
|
| 124 |
if not is_empty_success and not is_json_success:
|
| 125 |
+
status_msg = f"Failed ({response.status_code}): Code: {status_code_val} | Msg: {status_code_msg}"
|
| 126 |
else:
|
| 127 |
+
status_msg = f"Failed ({response.status_code}): Unexpected Error"
|
| 128 |
|
| 129 |
log_entry = (
|
| 130 |
f"[{timestamp}] {status_icon} REQ ({total_requests_sent}): {report_name}\n"
|
|
|
|
| 178 |
gr.Markdown("### 2. Report URLs Batch")
|
| 179 |
master_url_batch_input = gr.Textbox(
|
| 180 |
label="Master Signed Report URLs (One full URL per line)",
|
| 181 |
+
placeholder="Paste ONE OR MORE FULLY SIGNED & WORKING report URLs here.",
|
| 182 |
lines=5,
|
| 183 |
max_lines=10
|
| 184 |
)
|