wuhp commited on
Commit
0237ea8
·
verified ·
1 Parent(s): 2a1f984

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +124 -0
app.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import requests
4
+ import json
5
+
6
+ # ---------- Helpers ----------
7
+
8
+ def load_csv(file):
9
+ df = pd.read_csv(file.name)
10
+ required = {"TYPE1", "TYPE2", "URL"}
11
+ if not required.issubset(df.columns):
12
+ raise ValueError("CSV must contain TYPE1, TYPE2, URL columns")
13
+ return df
14
+
15
+ def get_type1_list(df):
16
+ return sorted(df["TYPE1"].unique().tolist())
17
+
18
+ def get_type2_list(df, type1):
19
+ return sorted(df[df["TYPE1"] == type1]["TYPE2"].unique().tolist())
20
+
21
+ def get_matching_rows(df, type1, type2):
22
+ return df[(df["TYPE1"] == type1) & (df["TYPE2"] == type2)]
23
+
24
+ def preview_rows(rows):
25
+ if rows.empty:
26
+ return "No matching reports found."
27
+ return rows[["TYPE1", "TYPE2", "URL"]].to_string(index=False)
28
+
29
+ def send_request(url, headers_json):
30
+ try:
31
+ headers = json.loads(headers_json) if headers_json else {}
32
+ except json.JSONDecodeError:
33
+ return "Invalid headers JSON"
34
+
35
+ headers.setdefault("User-Agent", "Mozilla/5.0")
36
+ headers.setdefault("Accept", "application/json")
37
+
38
+ try:
39
+ r = requests.get(url, headers=headers, timeout=15)
40
+ except Exception as e:
41
+ return f"Request failed: {e}"
42
+
43
+ try:
44
+ return json.dumps(r.json(), indent=2)
45
+ except ValueError:
46
+ return r.text
47
+
48
+ # ---------- UI ----------
49
+
50
+ with gr.Blocks(title="TikTok Report Research Tool") as app:
51
+ gr.Markdown("""
52
+ ## TikTok Report Research Tool
53
+ **Educational / analysis use only**
54
+
55
+ **Flow**
56
+ 1. Upload CSV
57
+ 2. Pick TYPE1 (profile / video / comments)
58
+ 3. Pick TYPE2 (category)
59
+ 4. Preview all matching reports
60
+ 5. Send **one** report only
61
+ """)
62
+
63
+ csv_file = gr.File(label="Upload CSV")
64
+ df_state = gr.State()
65
+ rows_state = gr.State()
66
+
67
+ type1 = gr.Dropdown(label="Report Target (TYPE1)")
68
+ type2 = gr.Dropdown(label="Report Category (TYPE2)")
69
+ report_select = gr.Dropdown(label="Report Selection")
70
+
71
+ preview = gr.Textbox(label="Preview (auto-updated)", lines=10)
72
+
73
+ headers = gr.Textbox(
74
+ label="Request Headers (JSON)",
75
+ lines=4,
76
+ placeholder='{"User-Agent":"...","Referer":"https://www.tiktok.com/"}'
77
+ )
78
+
79
+ output = gr.Textbox(label="Response", lines=10)
80
+
81
+ # ---------- Events ----------
82
+
83
+ def on_csv_upload(file):
84
+ df = load_csv(file)
85
+ return df, gr.Dropdown.update(choices=get_type1_list(df))
86
+
87
+ csv_file.upload(on_csv_upload, csv_file, [df_state, type1])
88
+
89
+ type1.change(
90
+ lambda df, t1: gr.Dropdown.update(choices=get_type2_list(df, t1)),
91
+ [df_state, type1],
92
+ type2
93
+ )
94
+
95
+ def on_type2_change(df, t1, t2):
96
+ rows = get_matching_rows(df, t1, t2)
97
+ options = ["ALL (preview only)"] + [str(i) for i in rows.index.tolist()]
98
+ return (
99
+ gr.Dropdown.update(choices=options),
100
+ rows,
101
+ preview_rows(rows)
102
+ )
103
+
104
+ type2.change(
105
+ on_type2_change,
106
+ [df_state, type1, type2],
107
+ [report_select, rows_state, preview]
108
+ )
109
+
110
+ def on_send(selection, rows, headers_json):
111
+ if selection == "ALL (preview only)":
112
+ return "ALL is preview-only.\nPlease select a single report to send."
113
+
114
+ row = rows.loc[int(selection)]
115
+ return send_request(row.URL, headers_json)
116
+
117
+ send = gr.Button("Send Single Report")
118
+ send.click(
119
+ on_send,
120
+ [report_select, rows_state, headers],
121
+ output
122
+ )
123
+
124
+ app.launch()