SarthakSidhant commited on
Commit
217500e
Β·
verified Β·
1 Parent(s): 684c52d

Upload 4 files

Browse files
Files changed (4) hide show
  1. README.md +5 -5
  2. app.py +400 -0
  3. new +0 -0
  4. requirements.txt +9 -0
README.md CHANGED
@@ -1,10 +1,10 @@
1
  ---
2
- title: Shugma
3
- emoji: πŸ“š
4
- colorFrom: red
5
- colorTo: yellow
6
  sdk: gradio
7
- sdk_version: 5.43.1
8
  app_file: app.py
9
  pinned: false
10
  ---
 
1
  ---
2
+ title: Newnewawea
3
+ emoji: πŸš€
4
+ colorFrom: yellow
5
+ colorTo: gray
6
  sdk: gradio
7
+ sdk_version: 5.43.0
8
  app_file: app.py
9
  pinned: false
10
  ---
app.py ADDED
@@ -0,0 +1,400 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ import json
4
+ import os
5
+ from datetime import datetime
6
+ import base64
7
+ import io
8
+ from PIL import Image
9
+
10
+ # API URLs from the ECI website
11
+ CAPTCHA_API_URL = "https://gateway-voters.eci.gov.in/api/v1/captcha-service/generateCaptcha/EROLL"
12
+ SEARCH_API_URL = "https://gateway-voters.eci.gov.in/api/v1/elastic/search-by-epic-from-national-display"
13
+
14
+ # Create directory for saving responses
15
+ RESPONSES_DIR = "."
16
+ if not os.path.exists(RESPONSES_DIR):
17
+ os.makedirs(RESPONSES_DIR)
18
+
19
+ def save_json_response(json_data, epic_number, status):
20
+ """Save JSON response to a file with a timestamp."""
21
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S_%f')[:-3] # Include milliseconds
22
+ filename = f"response_{status}_{epic_number}_{timestamp}.json"
23
+ filepath = os.path.join(RESPONSES_DIR, filename)
24
+
25
+ response_data = {
26
+ "timestamp": datetime.now().isoformat(),
27
+ "epic_number": epic_number,
28
+ "status": status,
29
+ "response_data": json_data
30
+ }
31
+
32
+ try:
33
+ with open(filepath, 'w', encoding='utf-8') as f:
34
+ json.dump(response_data, f, indent=4, ensure_ascii=False)
35
+ print(f"Response saved to {filepath}")
36
+ return filepath
37
+ except Exception as e:
38
+ print(f"Error saving JSON response: {e}")
39
+ return None
40
+
41
+ def get_new_captcha():
42
+ """Fetches a new captcha and returns it as a PIL Image object with captcha ID."""
43
+ try:
44
+ response = requests.get(CAPTCHA_API_URL, timeout=15)
45
+ response.raise_for_status()
46
+ api_data = response.json()
47
+
48
+ base64_image_string = api_data.get('captcha')
49
+ captcha_id = api_data.get('id')
50
+
51
+ if base64_image_string and captcha_id:
52
+ # Decode the base64 string into bytes
53
+ image_bytes = base64.b64decode(base64_image_string)
54
+ # Create a PIL Image object from the bytes
55
+ image = Image.open(io.BytesIO(image_bytes))
56
+
57
+ status_msg = f"α¬… New captcha fetched at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
58
+ return image, captcha_id, status_msg
59
+ else:
60
+ return None, None, "Error: Invalid API response format."
61
+
62
+ except requests.exceptions.RequestException as e:
63
+ return None, None, f"Error: API request failed: {e}"
64
+ except (ValueError, Exception) as e:
65
+ return None, None, f"Error: Failed to decode data from API: {e}"
66
+
67
+ def get_captcha_api():
68
+ """API-friendly version that returns captcha as base64 for external use."""
69
+ try:
70
+ response = requests.get(CAPTCHA_API_URL, timeout=15)
71
+ response.raise_for_status()
72
+ api_data = response.json()
73
+
74
+ base64_image_string = api_data.get('captcha')
75
+ captcha_id = api_data.get('id')
76
+
77
+ if base64_image_string and captcha_id:
78
+ timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
79
+ return {
80
+ "success": True,
81
+ "captcha_id": captcha_id,
82
+ "captcha_base64": base64_image_string,
83
+ "timestamp": timestamp,
84
+ "message": f"Captcha fetched successfully at {timestamp}"
85
+ }
86
+ else:
87
+ return {
88
+ "success": False,
89
+ "error": "Invalid API response format",
90
+ "captcha_id": None,
91
+ "captcha_base64": None
92
+ }
93
+
94
+ except Exception as e:
95
+ return {
96
+ "success": False,
97
+ "error": str(e),
98
+ "captcha_id": None,
99
+ "captcha_base64": None
100
+ }
101
+
102
+ def search_epic_api(epic_number, captcha_data, captcha_id):
103
+ """API-friendly version of epic search."""
104
+ if not all([epic_number, captcha_data, captcha_id]):
105
+ return {
106
+ "success": False,
107
+ "error": "Missing required fields (epic_number, captcha_data, captcha_id)",
108
+ "data": None
109
+ }
110
+
111
+ headers = {
112
+ 'Accept': 'application/json, text/plain, */*',
113
+ 'Content-Type': 'application/json',
114
+ 'Origin': 'https://electoralsearch.eci.gov.in',
115
+ 'Referer': 'https://electoralsearch.eci.gov.in/',
116
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
117
+ }
118
+
119
+ payload = {
120
+ "isPortal": True,
121
+ "epicNumber": epic_number.strip().upper(),
122
+ "captchaId": captcha_id,
123
+ "captchaData": captcha_data.strip(),
124
+ "securityKey": "na"
125
+ }
126
+
127
+ try:
128
+ response = requests.post(SEARCH_API_URL, headers=headers, json=payload, timeout=30)
129
+ response_text = response.text.lower()
130
+
131
+ if ("invalid captcha" in response_text or
132
+ "captcha is not valid" in response_text):
133
+ return {
134
+ "success": False,
135
+ "error": "Invalid captcha",
136
+ "captcha_incorrect": True,
137
+ "data": None,
138
+ "timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
139
+ }
140
+
141
+ response.raise_for_status()
142
+
143
+ try:
144
+ result_json = response.json()
145
+ # Save successful response
146
+ saved_file = save_json_response(result_json, epic_number, "success")
147
+
148
+ return {
149
+ "success": True,
150
+ "data": result_json,
151
+ "epic_number": epic_number,
152
+ "saved_file": saved_file,
153
+ "timestamp": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
154
+ }
155
+
156
+ except json.JSONDecodeError:
157
+ save_json_response({"raw_response": response.text}, epic_number, "non_json")
158
+ return {
159
+ "success": False,
160
+ "error": "Non-JSON response received",
161
+ "raw_response": response.text,
162
+ "data": None
163
+ }
164
+
165
+ except Exception as e:
166
+ return {
167
+ "success": False,
168
+ "error": str(e),
169
+ "data": None
170
+ }
171
+
172
+ def perform_epic_search(epic_number, captcha_data, captcha_id):
173
+ """
174
+ Submits the EPIC number and captcha data. Returns the JSON response and status.
175
+ Automatically fetches a new captcha after each attempt.
176
+ """
177
+ if not all([epic_number, captcha_data, captcha_id]):
178
+ return None, "Error: Missing required fields. Please fill all fields.", gr.update(), gr.update()
179
+
180
+ headers = {
181
+ 'Accept': 'application/json, text/plain, */*',
182
+ 'Content-Type': 'application/json',
183
+ 'Origin': 'https://electoralsearch.eci.gov.in',
184
+ 'Referer': 'https://electoralsearch.eci.gov.in/',
185
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
186
+ }
187
+
188
+ payload = {
189
+ "isPortal": True,
190
+ "epicNumber": epic_number.strip().upper(),
191
+ "captchaId": captcha_id,
192
+ "captchaData": captcha_data.strip(),
193
+ "securityKey": "na"
194
+ }
195
+
196
+ search_timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
197
+
198
+ try:
199
+ response = requests.post(SEARCH_API_URL, headers=headers, json=payload, timeout=30)
200
+ response_text = response.text.lower()
201
+
202
+ # Check for invalid captcha
203
+ if ("invalid captcha" in response_text or
204
+ "captcha is not valid" in response_text or
205
+ ("captcha" in response_text and "invalid" in response_text)):
206
+
207
+ save_json_response({
208
+ "error": "Invalid captcha",
209
+ "response_text": response.text,
210
+ }, epic_number, "captcha_failed")
211
+
212
+ status = f"ᭌ Incorrect Captcha at {search_timestamp}. Fetching a new one..."
213
+ new_image, new_id, captcha_status = get_new_captcha()
214
+ combined_status = f"{status}\n{captcha_status}"
215
+
216
+ # Return no JSON, update status, and provide the new captcha image and ID
217
+ return None, combined_status, new_image, new_id
218
+
219
+ response.raise_for_status()
220
+
221
+ try:
222
+ result_json = response.json()
223
+ saved_file = save_json_response(result_json, epic_number, "success")
224
+
225
+ status = f"α¬… Search Successful at {search_timestamp}\n"
226
+ if saved_file:
227
+ status += f"Response saved to: {os.path.basename(saved_file)}\n"
228
+ status += "Fetching new captcha for the next search..."
229
+
230
+ new_image, new_id, captcha_status = get_new_captcha()
231
+ combined_status = f"{status}\n{captcha_status}"
232
+
233
+ return result_json, combined_status, new_image, new_id
234
+
235
+ except json.JSONDecodeError:
236
+ save_json_response({
237
+ "raw_response": response.text,
238
+ }, epic_number, "non_json_response")
239
+
240
+ status = f"αͺ οˆ Non-JSON response received at {search_timestamp}. See saved file for details."
241
+ new_image, new_id, captcha_status = get_new_captcha()
242
+ combined_status = f"{status}\n{captcha_status}"
243
+
244
+ return {"raw_response": response.text}, combined_status, new_image, new_id
245
+
246
+ except requests.exceptions.Timeout:
247
+ error_msg = f"៱ Request timed out at {search_timestamp}. Please try again."
248
+ save_json_response({"error": "Timeout"}, epic_number, "timeout")
249
+ return None, error_msg, gr.update(), gr.update()
250
+
251
+ except requests.exceptions.RequestException as e:
252
+ status_code = e.response.status_code if e.response else 'N/A'
253
+ error_details = f"ᭌ Request failed at {search_timestamp}\nStatus: {status_code}\nError: {e}"
254
+
255
+ save_json_response({
256
+ "error": str(e),
257
+ "status_code": status_code,
258
+ "response_text": e.response.text if e.response else ''
259
+ }, epic_number, "request_failed")
260
+
261
+ return None, error_details, gr.update(), gr.update()
262
+
263
+ def clear_inputs():
264
+ """Clear input fields"""
265
+ return "", ""
266
+
267
+ # ==============================================================================
268
+ # GRADIO INTERFACE
269
+ # ==============================================================================
270
+
271
+ with gr.Blocks(theme=gr.themes.Soft(), title="ECI Voter Search") as demo:
272
+ gr.Markdown("""
273
+ # 창 ECI Voter Search via EPIC Number
274
+
275
+ **Instructions:**
276
+ 1. A captcha will load automatically.
277
+ 2. Enter an EPIC number and the text from the captcha image.
278
+ 3. Click "Search Voter Details".
279
+ 4. Responses are automatically saved to the `eci_responses` folder.
280
+ """)
281
+
282
+ captcha_id_state = gr.State()
283
+
284
+ with gr.Row():
285
+ with gr.Column(scale=1):
286
+ gr.Markdown("### μ°½ Captcha & Search")
287
+
288
+ with gr.Group():
289
+ captcha_image = gr.Image(
290
+ label="Captcha Image",
291
+ interactive=False,
292
+ type="pil",
293
+ height=100
294
+ )
295
+
296
+ with gr.Row():
297
+ fetch_captcha_btn = gr.Button("μ°½ Refresh Captcha", size="sm")
298
+ clear_btn = gr.Button("창 Clear Inputs", size="sm")
299
+
300
+ epic_input = gr.Textbox(
301
+ label="EPIC Number",
302
+ placeholder="e.g., ABC1234567"
303
+ )
304
+
305
+ captcha_input = gr.Textbox(
306
+ label="Captcha Text",
307
+ placeholder="Enter the text from the captcha image"
308
+ )
309
+
310
+ submit_btn = gr.Button("μ°½ Search Voter Details", variant="primary", size="lg")
311
+
312
+ with gr.Column(scale=2):
313
+ gr.Markdown("### μ°½ Results & Status")
314
+
315
+ status_output = gr.Textbox(
316
+ label="Status",
317
+ interactive=False,
318
+ lines=4,
319
+ value="μ°½ Loading... Fetching initial captcha..."
320
+ )
321
+
322
+ json_output = gr.JSON(
323
+ label="Voter Details Response"
324
+ )
325
+
326
+ gr.Markdown(f"""
327
+ **μ°½ Auto-Save Location:** All responses are automatically saved in the `{os.path.abspath(RESPONSES_DIR)}` directory.
328
+ """)
329
+
330
+ # Event Handlers
331
+
332
+ # Load initial captcha when the app starts
333
+ demo.load(
334
+ fn=get_new_captcha,
335
+ inputs=None,
336
+ outputs=[captcha_image, captcha_id_state, status_output]
337
+ )
338
+
339
+ # Handler for the "Refresh Captcha" button
340
+ fetch_captcha_btn.click(
341
+ fn=get_new_captcha,
342
+ inputs=None,
343
+ outputs=[captcha_image, captcha_id_state, status_output],
344
+ api_name="get_new_captcha"
345
+ )
346
+
347
+ # Handler for the "Clear Inputs" button
348
+ clear_btn.click(
349
+ fn=clear_inputs,
350
+ inputs=None,
351
+ outputs=[epic_input, captcha_input]
352
+ )
353
+
354
+ # Handler for the main search button
355
+ submit_btn.click(
356
+ fn=perform_epic_search,
357
+ inputs=[epic_input, captcha_input, captcha_id_state],
358
+ outputs=[json_output, status_output, captcha_image, captcha_id_state],
359
+ api_name="search_epic"
360
+ )
361
+
362
+ # Allow submitting with the Enter key from the captcha input field
363
+ captcha_input.submit(
364
+ fn=perform_epic_search,
365
+ inputs=[epic_input, captcha_input, captcha_id_state],
366
+ outputs=[json_output, status_output, captcha_image, captcha_id_state]
367
+ )
368
+
369
+ # Hidden API interfaces for external access
370
+ with gr.Group(visible=False):
371
+ gr.Interface(
372
+ fn=get_captcha_api,
373
+ inputs=[],
374
+ outputs=gr.JSON(),
375
+ api_name="api_get_captcha"
376
+ )
377
+
378
+ gr.Interface(
379
+ fn=search_epic_api,
380
+ inputs=[
381
+ gr.Textbox(label="epic_number"),
382
+ gr.Textbox(label="captcha_data"),
383
+ gr.Textbox(label="captcha_id")
384
+ ],
385
+ outputs=gr.JSON(),
386
+ api_name="api_search_epic"
387
+ )
388
+
389
+ if __name__ == "__main__":
390
+ print(f"μ°½ Responses will be saved to: {os.path.abspath(RESPONSES_DIR)}")
391
+ print("Starting Gradio server...")
392
+ print("API Endpoints will be available at your server address:")
393
+ print(" - GET captcha: /api/api_get_captcha")
394
+ print(" - POST search: /api/api_search_epic")
395
+
396
+ demo.launch(
397
+ server_name="0.0.0.0",
398
+ server_port=7860,
399
+ debug=True,
400
+ )
new ADDED
File without changes
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ gradio-client
2
+ requests
3
+ Pillow
4
+ imagehash
5
+ numpy
6
+ tqdm
7
+ transformers
8
+ torch
9
+ huggingface_hub