Upload 5 files
Browse files- .env.example +0 -4
- README.md +135 -139
- app.py +34 -33
- officers.csv +6 -0
- test_network.py +12 -0
.env.example
CHANGED
|
@@ -8,7 +8,3 @@ NVIDIA_API_KEY=your_nvidia_api_key
|
|
| 8 |
|
| 9 |
# MongoDB
|
| 10 |
MONGODB_URI=mongodb+srv://username:password@cluster0.sxci1.mongodb.net/?retryWrites=true&w=majority
|
| 11 |
-
|
| 12 |
-
# Telegram API
|
| 13 |
-
TELEGRAM_BOT_TOKEN=your_bot_token_here
|
| 14 |
-
TELEGRAM_GROUP_ID=your_group_chat_id_here
|
|
|
|
| 8 |
|
| 9 |
# MongoDB
|
| 10 |
MONGODB_URI=mongodb+srv://username:password@cluster0.sxci1.mongodb.net/?retryWrites=true&w=majority
|
|
|
|
|
|
|
|
|
|
|
|
README.md
CHANGED
|
@@ -1,139 +1,135 @@
|
|
| 1 |
-
---
|
| 2 |
-
title: ALDDS
|
| 3 |
-
emoji: ๐ป
|
| 4 |
-
colorFrom: purple
|
| 5 |
-
colorTo: red
|
| 6 |
-
sdk: gradio
|
| 7 |
-
sdk_version: 6.14.0
|
| 8 |
-
python_version: '3.13'
|
| 9 |
-
app_file: app.py
|
| 10 |
-
pinned: false
|
| 11 |
-
---
|
| 12 |
-
|
| 13 |
-
# โ๏ธ Automated Legal Document Digitization System (ALDDS)
|
| 14 |
-
|
| 15 |
-

|
| 16 |
-

|
| 17 |
-

|
| 18 |
-

|
| 19 |
-
|
| 20 |
-
Upload a photo of a legal document (bailable warrant, summon, etc.) and seamlessly convert it into structured JSON data. ALDDS handles the OCR, AI parsing, secure storage, and live dispatcher notifications in a single streamlined pipeline.
|
| 21 |
-
|
| 22 |
-
## ๐ Pipeline & Architecture
|
| 23 |
-
|
| 24 |
-
```text
|
| 25 |
-
Image Upload โ Cloudinary Hosting โ Tesseract OCR โ NVIDIA LLMs โ MongoDB โ
|
| 26 |
-
```
|
| 27 |
-
|
| 28 |
-
1. **OCR Extraction**: Uses Tesseract to extract raw text from image uploads.
|
| 29 |
-
2. **AI Parsing**: Leverages advanced NVIDIA models (`qwen/qwen3-coder-480b-a35b-instruct`, Llama 3) to parse the unstructured OCR text into a strict 10-field JSON schema.
|
| 30 |
-
3. **Secure Storage**: Automatically commits the digital record to a MongoDB database.
|
| 31 |
-
4. **Live Dashboard**: A real-time, searchable Police Dashboard built directly into the UI.
|
| 32 |
-
5. **Instant Notifications**: Dispatchers can
|
| 33 |
-
|
| 34 |
-
---
|
| 35 |
-
|
| 36 |
-
## ๐ Features
|
| 37 |
-
|
| 38 |
-
- **Multi-Model Fallback**: The app cycles through a priority list of NVIDIA LLMs ensuring maximum uptime and reliability during the parsing phase.
|
| 39 |
-
- **๐ฎ Live Police Dashboard**: A dedicated tab for station dispatchers to monitor incoming warrants. Includes a real-time MongoDB search filter (by Case No, IO Name, Station, etc.).
|
| 40 |
-
- **
|
| 41 |
-
|
| 42 |
-
---
|
| 43 |
-
|
| 44 |
-
## ๐ Environment Setup
|
| 45 |
-
|
| 46 |
-
To run ALDDS locally or in the cloud, you need the following API keys configured in a `.env` file (or as Secrets on Hugging Face).
|
| 47 |
-
|
| 48 |
-
```env
|
| 49 |
-
# Cloudinary (Image Hosting)
|
| 50 |
-
CLOUDINARY_CLOUD_NAME=your_cloud_name
|
| 51 |
-
CLOUDINARY_API_KEY=your_api_key
|
| 52 |
-
CLOUDINARY_API_SECRET=your_api_secret
|
| 53 |
-
|
| 54 |
-
# NVIDIA API (LLM Parsing)
|
| 55 |
-
NVIDIA_API_KEY=your_nvidia_api_key
|
| 56 |
-
|
| 57 |
-
# MongoDB (Database)
|
| 58 |
-
MONGODB_URI=mongodb+srv://username:password@cluster0.../?retryWrites=true&w=majority
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
|
| 65 |
-
|
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
#
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
If
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
|
| 126 |
-
|
|
| 127 |
-
| `
|
| 128 |
-
| `
|
| 129 |
-
| `
|
| 130 |
-
| `
|
| 131 |
-
| `
|
| 132 |
-
| `
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
| `Hearing_Date` | Scheduled hearing or appearance date (DD-MM-YYYY) |
|
| 137 |
-
|
| 138 |
-
---
|
| 139 |
-
*Built to streamline station workflows, eliminate manual data entry, and instantly notify field officers.*
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: ALDDS
|
| 3 |
+
emoji: ๐ป
|
| 4 |
+
colorFrom: purple
|
| 5 |
+
colorTo: red
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: 6.14.0
|
| 8 |
+
python_version: '3.13'
|
| 9 |
+
app_file: app.py
|
| 10 |
+
pinned: false
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
# โ๏ธ Automated Legal Document Digitization System (ALDDS)
|
| 14 |
+
|
| 15 |
+

|
| 16 |
+

|
| 17 |
+

|
| 18 |
+

|
| 19 |
+
|
| 20 |
+
Upload a photo of a legal document (bailable warrant, summon, etc.) and seamlessly convert it into structured JSON data. ALDDS handles the OCR, AI parsing, secure storage, and live dispatcher notifications in a single streamlined pipeline.
|
| 21 |
+
|
| 22 |
+
## ๐ Pipeline & Architecture
|
| 23 |
+
|
| 24 |
+
```text
|
| 25 |
+
Image Upload โ Cloudinary Hosting โ Tesseract OCR โ NVIDIA LLMs โ MongoDB โ WhatsApp Alert
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
1. **OCR Extraction**: Uses Tesseract to extract raw text from image uploads.
|
| 29 |
+
2. **AI Parsing**: Leverages advanced NVIDIA models (`qwen/qwen3-coder-480b-a35b-instruct`, Llama 3) to parse the unstructured OCR text into a strict 10-field JSON schema.
|
| 30 |
+
3. **Secure Storage**: Automatically commits the digital record to a MongoDB database.
|
| 31 |
+
4. **Live Dashboard**: A real-time, searchable Police Dashboard built directly into the UI.
|
| 32 |
+
5. **Instant Notifications**: Dispatchers can notify Investigating Officers (IOs) instantly via zero-cost WhatsApp `wa.me` links populated from an internal CSV database.
|
| 33 |
+
|
| 34 |
+
---
|
| 35 |
+
|
| 36 |
+
## ๐ Features
|
| 37 |
+
|
| 38 |
+
- **Multi-Model Fallback**: The app cycles through a priority list of NVIDIA LLMs ensuring maximum uptime and reliability during the parsing phase.
|
| 39 |
+
- **๐ฎ Live Police Dashboard**: A dedicated tab for station dispatchers to monitor incoming warrants. Includes a real-time MongoDB search filter (by Case No, IO Name, Station, etc.).
|
| 40 |
+
- **๐ฌ WhatsApp Integration**: Zero-API-cost notifications. Selecting an officer from the dropdown dynamically pulls their phone number from `officers.csv` and opens a pre-filled WhatsApp window for the dispatcher to send manually.
|
| 41 |
+
|
| 42 |
+
---
|
| 43 |
+
|
| 44 |
+
## ๐ Environment Setup
|
| 45 |
+
|
| 46 |
+
To run ALDDS locally or in the cloud, you need the following API keys configured in a `.env` file (or as Secrets on Hugging Face).
|
| 47 |
+
|
| 48 |
+
```env
|
| 49 |
+
# Cloudinary (Image Hosting)
|
| 50 |
+
CLOUDINARY_CLOUD_NAME=your_cloud_name
|
| 51 |
+
CLOUDINARY_API_KEY=your_api_key
|
| 52 |
+
CLOUDINARY_API_SECRET=your_api_secret
|
| 53 |
+
|
| 54 |
+
# NVIDIA API (LLM Parsing)
|
| 55 |
+
NVIDIA_API_KEY=your_nvidia_api_key
|
| 56 |
+
|
| 57 |
+
# MongoDB (Database)
|
| 58 |
+
MONGODB_URI=mongodb+srv://username:password@cluster0.../?retryWrites=true&w=majority
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
| Variable | Where to get it |
|
| 62 |
+
|---|---|
|
| 63 |
+
| `CLOUDINARY_*` | [Cloudinary Console](https://console.cloudinary.com/) โ Dashboard |
|
| 64 |
+
| `NVIDIA_API_KEY` | [NVIDIA Build](https://build.nvidia.com/) โ API Catalog โ Get API Key |
|
| 65 |
+
| `MONGODB_URI` | [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) โ Database โ Connect |
|
| 66 |
+
|
| 67 |
+
---
|
| 68 |
+
|
| 69 |
+
## ๐ป Local Installation Guide
|
| 70 |
+
|
| 71 |
+
### 1. Install Tesseract OCR (System Binary)
|
| 72 |
+
Python's `pytesseract` requires the underlying Tesseract engine to be installed on your OS.
|
| 73 |
+
|
| 74 |
+
**Windows**
|
| 75 |
+
1. Download installer from: https://github.com/UB-Mannheim/tesseract/wiki
|
| 76 |
+
2. Run installer (default path: `C:\Program Files\Tesseract-OCR\`)
|
| 77 |
+
3. The app is hardcoded to look for this path on Windows.
|
| 78 |
+
|
| 79 |
+
**Linux (Debian/Ubuntu)**
|
| 80 |
+
```bash
|
| 81 |
+
sudo apt-get update
|
| 82 |
+
sudo apt-get install tesseract-ocr
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
**macOS**
|
| 86 |
+
```bash
|
| 87 |
+
brew install tesseract
|
| 88 |
+
```
|
| 89 |
+
|
| 90 |
+
### 2. Run the App
|
| 91 |
+
```bash
|
| 92 |
+
# Clone repository
|
| 93 |
+
git clone https://huggingface.co/spaces/LovnishVerma/ALDDS
|
| 94 |
+
cd ALDDS
|
| 95 |
+
|
| 96 |
+
# Install Dependencies
|
| 97 |
+
pip install -r requirements.txt
|
| 98 |
+
|
| 99 |
+
# Run the Server
|
| 100 |
+
python app.py
|
| 101 |
+
```
|
| 102 |
+
The interface will launch at **http://127.0.0.1:7860**.
|
| 103 |
+
|
| 104 |
+
---
|
| 105 |
+
|
| 106 |
+
## โ๏ธ Hugging Face Spaces Deployment
|
| 107 |
+
|
| 108 |
+
If you are deploying ALDDS to Hugging Face Spaces, follow these critical steps:
|
| 109 |
+
|
| 110 |
+
1. **Set Up Secrets**: Go to your Space **Settings** -> **Variables and secrets**. Add all variables from your `.env` file as **Secrets**.
|
| 111 |
+
2. **System Dependencies**: Hugging Face runs Debian Linux. The repository includes a `packages.txt` file telling Hugging Face to install `tesseract-ocr` and `libtesseract-dev` during the Docker build.
|
| 112 |
+
3. **CRLF Warning**: Ensure that `packages.txt` is saved with Unix (`LF`) line endings. If it has Windows (`CRLF`) line endings, the Hugging Face Docker build will fail with a `Package not found` error.
|
| 113 |
+
4. **Restart**: Always click **Restart Space** after adding or modifying Secrets so the new environment variables are loaded into the container.
|
| 114 |
+
|
| 115 |
+
---
|
| 116 |
+
|
| 117 |
+
## ๐ Extracted JSON Schema
|
| 118 |
+
|
| 119 |
+
The LLM is strictly prompted to extract the following fields. If a field cannot be found, it defaults to `null`.
|
| 120 |
+
|
| 121 |
+
| JSON Key | Description |
|
| 122 |
+
|---|---|
|
| 123 |
+
| `Case_FIR_Number` | FIR or court case reference number |
|
| 124 |
+
| `Act_and_Sections` | Applicable IPC/CRPC legal acts and sections |
|
| 125 |
+
| `Type_of_Document` | Warrant, summon, notice, etc. |
|
| 126 |
+
| `Target_Police_Station` | Police station the document is addressed to |
|
| 127 |
+
| `IO_Name_and_Belt_No` | Investigating Officer's name and belt number |
|
| 128 |
+
| `IO_Mobile_Number` | IO's contact number |
|
| 129 |
+
| `Person_Name_To_Serve` | Name of the person to be served/arrested |
|
| 130 |
+
| `Person_Address` | Address of the target person |
|
| 131 |
+
| `Court_Name` | Issuing court name |
|
| 132 |
+
| `Hearing_Date` | Scheduled hearing or appearance date (DD-MM-YYYY) |
|
| 133 |
+
|
| 134 |
+
---
|
| 135 |
+
*Built to streamline station workflows, eliminate manual data entry, and instantly notify field officers.*
|
|
|
|
|
|
|
|
|
|
|
|
app.py
CHANGED
|
@@ -14,6 +14,7 @@ import re
|
|
| 14 |
import json
|
| 15 |
import concurrent.futures
|
| 16 |
import requests
|
|
|
|
| 17 |
|
| 18 |
import gradio as gr
|
| 19 |
import cloudinary
|
|
@@ -65,6 +66,15 @@ if mongo_uri:
|
|
| 65 |
print(f"โ MongoDB connection failed: {exc}")
|
| 66 |
collection = None
|
| 67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 70 |
# B. Core Processing Logic
|
|
@@ -608,13 +618,17 @@ with gr.Blocks(
|
|
| 608 |
raw_ocr_out = gr.Textbox(label="๐ Raw OCR Text", lines=8, interactive=False)
|
| 609 |
json_out = gr.JSON(label="๐ Extracted Structured Data (JSON)")
|
| 610 |
|
| 611 |
-
gr.Markdown("### ๐จ Notify Investigating Officer")
|
| 612 |
with gr.Row():
|
| 613 |
-
|
| 614 |
-
|
| 615 |
-
|
|
|
|
| 616 |
|
| 617 |
-
|
|
|
|
|
|
|
|
|
|
| 618 |
|
| 619 |
def _make_status_html(icon, message, color):
|
| 620 |
return (
|
|
@@ -662,45 +676,32 @@ with gr.Blocks(
|
|
| 662 |
outputs=[status_out, cloudinary_url_out, cloudinary_link_html, raw_ocr_out, json_out],
|
| 663 |
)
|
| 664 |
|
| 665 |
-
|
| 666 |
-
|
| 667 |
-
if (!
|
| 668 |
if (!url) return "โ No document uploaded yet.";
|
| 669 |
-
if (!bot_token) return "โ Bot token not configured in .env";
|
| 670 |
|
| 671 |
let case_no = data && data["Case_FIR_Number"] ? data["Case_FIR_Number"] : "Unknown Case";
|
| 672 |
let court = data && data["Court_Name"] ? data["Court_Name"] : "Unknown Court";
|
| 673 |
|
| 674 |
let text = `๐จ *New Warrant Uploaded*\\n*Case:* ${case_no}\\n*Court:* ${court}\\n*Document:* ${url}`;
|
| 675 |
-
let
|
| 676 |
|
| 677 |
-
|
| 678 |
-
|
| 679 |
-
|
| 680 |
-
|
| 681 |
-
|
| 682 |
-
|
| 683 |
-
|
| 684 |
-
parse_mode: "Markdown"
|
| 685 |
-
})
|
| 686 |
-
});
|
| 687 |
-
let out = await res.json();
|
| 688 |
-
if (out.ok) {
|
| 689 |
-
return `โ
Alert sent successfully to ${chat_id}!`;
|
| 690 |
-
} else {
|
| 691 |
-
return `โ Failed: ${out.description}`;
|
| 692 |
-
}
|
| 693 |
-
} catch (e) {
|
| 694 |
-
return `โ Error connecting to Telegram: ${e.message}`;
|
| 695 |
-
}
|
| 696 |
}
|
| 697 |
"""
|
| 698 |
|
| 699 |
-
|
| 700 |
fn=None,
|
| 701 |
-
inputs=[
|
| 702 |
-
outputs=[
|
| 703 |
-
js=
|
| 704 |
)
|
| 705 |
|
| 706 |
with gr.Tab("๐ฎ Live Police Dashboard"):
|
|
|
|
| 14 |
import json
|
| 15 |
import concurrent.futures
|
| 16 |
import requests
|
| 17 |
+
import csv
|
| 18 |
|
| 19 |
import gradio as gr
|
| 20 |
import cloudinary
|
|
|
|
| 66 |
print(f"โ MongoDB connection failed: {exc}")
|
| 67 |
collection = None
|
| 68 |
|
| 69 |
+
# Load Officers Database
|
| 70 |
+
officers_db = {}
|
| 71 |
+
try:
|
| 72 |
+
with open("officers.csv", "r", encoding="utf-8") as f:
|
| 73 |
+
reader = csv.DictReader(f)
|
| 74 |
+
for row in reader:
|
| 75 |
+
officers_db[row["Officer_Name"]] = row["Phone_Number"]
|
| 76 |
+
except Exception as e:
|
| 77 |
+
print(f"โ ๏ธ Could not load officers.csv: {e}")
|
| 78 |
|
| 79 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 80 |
# B. Core Processing Logic
|
|
|
|
| 618 |
raw_ocr_out = gr.Textbox(label="๐ Raw OCR Text", lines=8, interactive=False)
|
| 619 |
json_out = gr.JSON(label="๐ Extracted Structured Data (JSON)")
|
| 620 |
|
| 621 |
+
gr.Markdown("### ๐จ Notify Investigating Officer (WhatsApp)")
|
| 622 |
with gr.Row():
|
| 623 |
+
io_dropdown = gr.Dropdown(label="Select Officer (from CSV)", choices=list(officers_db.keys()), scale=2)
|
| 624 |
+
manual_phone_in = gr.Textbox(label="WhatsApp Mobile No.", placeholder="e.g. 919876543210", scale=2)
|
| 625 |
+
send_wa_btn = gr.Button("๐ฌ Send via WhatsApp", variant="secondary", scale=1)
|
| 626 |
+
wa_status_out = gr.HTML()
|
| 627 |
|
| 628 |
+
# Auto-fill phone when IO selected
|
| 629 |
+
def update_phone(officer_name):
|
| 630 |
+
return officers_db.get(officer_name, "")
|
| 631 |
+
io_dropdown.change(fn=update_phone, inputs=[io_dropdown], outputs=[manual_phone_in])
|
| 632 |
|
| 633 |
def _make_status_html(icon, message, color):
|
| 634 |
return (
|
|
|
|
| 676 |
outputs=[status_out, cloudinary_url_out, cloudinary_link_html, raw_ocr_out, json_out],
|
| 677 |
)
|
| 678 |
|
| 679 |
+
js_code_wa = """
|
| 680 |
+
(phone, url, data) => {
|
| 681 |
+
if (!phone) return "โ Please enter a WhatsApp number.";
|
| 682 |
if (!url) return "โ No document uploaded yet.";
|
|
|
|
| 683 |
|
| 684 |
let case_no = data && data["Case_FIR_Number"] ? data["Case_FIR_Number"] : "Unknown Case";
|
| 685 |
let court = data && data["Court_Name"] ? data["Court_Name"] : "Unknown Court";
|
| 686 |
|
| 687 |
let text = `๐จ *New Warrant Uploaded*\\n*Case:* ${case_no}\\n*Court:* ${court}\\n*Document:* ${url}`;
|
| 688 |
+
let encoded_text = encodeURIComponent(text);
|
| 689 |
|
| 690 |
+
let clean_phone = phone.replace(/[^0-9]/g, '');
|
| 691 |
+
if (!clean_phone) return "โ Invalid phone number.";
|
| 692 |
+
|
| 693 |
+
let wa_url = `https://wa.me/${clean_phone}?text=${encoded_text}`;
|
| 694 |
+
window.open(wa_url, '_blank');
|
| 695 |
+
|
| 696 |
+
return `โ
WhatsApp opened for ${phone}! Click Send in WhatsApp.`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 697 |
}
|
| 698 |
"""
|
| 699 |
|
| 700 |
+
send_wa_btn.click(
|
| 701 |
fn=None,
|
| 702 |
+
inputs=[manual_phone_in, cloudinary_url_out, json_out],
|
| 703 |
+
outputs=[wa_status_out],
|
| 704 |
+
js=js_code_wa
|
| 705 |
)
|
| 706 |
|
| 707 |
with gr.Tab("๐ฎ Live Police Dashboard"):
|
officers.csv
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Officer_Name,Phone_Number
|
| 2 |
+
Insp. Lovnish Verma (101),+918894869371
|
| 3 |
+
SI Amit Singh (102),+919876543211
|
| 4 |
+
ASI Vikram Sharma (103),+919876543212
|
| 5 |
+
HC Ramesh Chand (104),+919876543213
|
| 6 |
+
SI Vikas Kumar (105),+919876543214
|
test_network.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import requests
|
| 2 |
+
|
| 3 |
+
try:
|
| 4 |
+
print("Testing basic internet access...")
|
| 5 |
+
google_check = requests.get("https://www.google.com", timeout=10)
|
| 6 |
+
print(f"Google status: {google_check.status_code}")
|
| 7 |
+
|
| 8 |
+
print("Testing Telegram endpoint access...")
|
| 9 |
+
telegram_check = requests.get("https://api.telegram.org", timeout=10)
|
| 10 |
+
print(f"Telegram status: {telegram_check.status_code}")
|
| 11 |
+
except Exception as e:
|
| 12 |
+
print(f"โ Network blocked: {e}")
|