import gradio as gr
import requests
from datetime import datetime
import json
import re
# Emergency contacts specific to Chittagong and Bangladesh
EMERGENCY_DB = {
"BD": {
"police": "999",
"women_helpline": "109",
"ambulance": "199",
"fire": "16163",
"crisis_center": "10921",
"legal_aid": "16430",
"chittagong_police": "031-619101"
}
}
CHITTAGONG_SAFE_AREAS = {
"safe": ["Agrabad", "GEC Circle", "Nasirabad", "Panchlaish", "CDA Avenue"],
"moderate": ["New Market", "Chawkbazar", "Sadarghat", "Reazuddin Bazar"],
"caution_night": ["Halishahar", "Bahaddarhat", "Katalganj"]
}
SYSTEM_PROMPT = """You are SafeHer AI, a comprehensive women's safety assistant for Chittagong, Bangladesh with real-time capabilities.
CAPABILITIES:
1. REAL-TIME ROUTE SAFETY: Analyze routes in Chittagong using live data, traffic, and time-based safety
2. LEGAL GUIDANCE: Provide Bangladesh harassment laws, women's rights, legal procedures
3. MENTAL HEALTH SUPPORT: Offer emotional support, coping strategies, trauma response
4. EMERGENCY PROTOCOLS: Guide through SOS situations with step-by-step actions
5. AREA INTELLIGENCE: Real-time safety info for Chittagong neighborhoods
CHITTAGONG-SPECIFIC KNOWLEDGE:
- Know major areas: Agrabad, Khulshi, GEC, Panchlaish, New Market, CDA, Halishahar
- Time-sensitive advice based on Chittagong conditions
- Local emergency contacts and support centers
BANGLADESH LAWS YOU MUST KNOW:
- Domestic Violence (Prevention and Protection) Act 2010
- Women and Children Repression Prevention Act 2000
- Sexual Harassment at Workplace (Prevention) Act 2009
- Dowry Prohibition Act 1980
Be empowering, precise, culturally sensitive, and action-oriented. Always cite sources when using real-time data.
Emergency: Police 999, Women Helpline 109, Chittagong Police 031-619101"""
def search_web(query):
"""Search web for real-time information"""
try:
response = requests.get(
"https://api.duckduckgo.com/",
params={"q": query, "format": "json"},
timeout=10
)
if response.status_code == 200:
data = response.json()
return data.get("AbstractText", "") or data.get("Answer", "")
return None
except Exception as e:
print(f"Search error: {e}")
return None
def get_location_coords(location):
"""Get coordinates for a location using Nominatim with Chittagong context"""
try:
# Add Chittagong context if not already present
search_location = location
if "chittagong" not in location.lower() and "chattogram" not in location.lower():
search_location = f"{location}, Chittagong, Bangladesh"
print(f"DEBUG: Searching for coordinates of: {search_location}")
response = requests.get(
"https://nominatim.openstreetmap.org/search",
params={
"q": search_location,
"format": "json",
"limit": 1,
"countrycodes": "bd"
},
headers={"User-Agent": "SafeHer-App-Chittagong/1.0"},
timeout=15
)
print(f"DEBUG: Geocoding response status: {response.status_code}")
if response.status_code == 200 and response.json():
data = response.json()[0]
lat, lon = float(data["lat"]), float(data["lon"])
print(f"DEBUG: Found coordinates - Lat: {lat}, Lon: {lon}")
return lat, lon
else:
print(f"DEBUG: No results found for {search_location}")
return None
except Exception as e:
print(f"DEBUG: Geocoding error: {e}")
return None
def assess_area_safety(area_name, current_hour):
"""Assess safety of Chittagong area based on time and known data"""
safety_tips = []
# Check against known safe/unsafe areas
for safe_area in CHITTAGONG_SAFE_AREAS["safe"]:
if safe_area.lower() in area_name.lower():
safety_tips.append(f"β {safe_area} is generally safe")
for caution_area in CHITTAGONG_SAFE_AREAS["caution_night"]:
if caution_area.lower() in area_name.lower():
if current_hour >= 20 or current_hour <= 6:
safety_tips.append(f"β οΈ {caution_area} - Extra caution at night. Travel with companions if possible")
else:
safety_tips.append(f"β {caution_area} - Generally safe during daytime")
# Time-based general advice
if current_hour >= 22 or current_hour <= 5:
safety_tips.append("π¨ Very late/early hours - Avoid travel if possible")
elif current_hour >= 20 or current_hour <= 6:
safety_tips.append("β οΈ Night time - Use well-lit main roads, inform someone")
elif current_hour >= 18:
safety_tips.append("β οΈ Evening - Stay on busy streets, finish travel before 9 PM")
else:
safety_tips.append("β Daytime - Generally safer, but stay alert")
return " | ".join(safety_tips) if safety_tips else "βΉοΈ Stay alert and aware of surroundings"
def create_interactive_map(start_loc, end_loc, route_info=""):
"""Create interactive Leaflet map with route for Chittagong"""
print(f"DEBUG: Creating map for {start_loc} to {end_loc}")
start_coords = get_location_coords(start_loc)
end_coords = get_location_coords(end_loc)
if not start_coords or not end_coords:
error_msg = ""
if not start_coords:
error_msg += f"β Could not find: {start_loc} "
if not end_coords:
error_msg += f"β Could not find: {end_loc} "
return f"""
"""
print(f"DEBUG: Successfully got coordinates for both locations")
center_lat = (start_coords[0] + end_coords[0]) / 2
center_lon = (start_coords[1] + end_coords[1]) / 2
current_hour = datetime.now().hour
safety_color = "#dc3545" if (current_hour >= 22 or current_hour <= 6) else "#ffc107" if current_hour >= 18 else "#28a745"
# Get safety assessment
route_safety = assess_area_safety(f"{start_loc} {end_loc}", current_hour)
html = f"""
πΊοΈ Route Map: {start_loc} β {end_loc}
π Location: Chittagong, Bangladesh
π Current Time: {datetime.now().strftime('%I:%M %p, %B %d, %Y')}
π‘οΈ Safety Status:
{'π¨ High Alert - Night' if current_hour >= 22 or current_hour <= 6
else 'β οΈ Evening Caution' if current_hour >= 18
else 'β Daytime Safe'}
π‘ Route Safety: {route_safety}
"""
return html
def call_groq(messages, api_key):
"""Call Groq API with error handling"""
try:
response = requests.post(
"https://api.groq.com/openai/v1/chat/completions",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
},
json={
"model": "llama-3.3-70b-versatile",
"messages": messages,
"temperature": 0.7,
"max_tokens": 2000
},
timeout=30
)
if response.status_code == 200:
return response.json()["choices"][0]["message"]["content"]
else:
return f"β API Error {response.status_code}: {response.text[:200]}"
except requests.exceptions.Timeout:
return "β Request timeout. Please try again."
except Exception as e:
return f"β Error: {str(e)}"
def enhanced_chat(message, history, api_key):
"""Enhanced chat with web search and context awareness"""
if not api_key or api_key.strip() == "":
return history + [[message, "β οΈ **API Key Required**\n\nPlease enter your Groq API key above to use SafeHer AI.\n\nπ Get a FREE key at: https://console.groq.com\n\n(Takes 1 minute to sign up!)"]], None
# Detect query type and search web if needed
web_context = ""
keywords = message.lower()
# Search for legal, harassment, crime, or safety info
if any(word in keywords for word in ["law", "legal", "harassment", "rights", "violence", "rape", "assault", "crime", "report"]):
search_query = f"Bangladesh women harassment law rights legal procedures"
web_result = search_web(search_query)
if web_result:
web_context += f"\n[LEGAL INFO: {web_result[:400]}]"
# Search for current safety/crime data for Chittagong
if any(word in keywords for word in ["safe", "safety", "crime", "dangerous", "area", "chittagong", "route"]):
search_query = f"Chittagong Bangladesh safety crime current news"
web_result = search_web(search_query)
if web_result:
web_context += f"\n[SAFETY DATA: {web_result[:400]}]"
# Search for mental health resources
if any(word in keywords for word in ["trauma", "anxiety", "depression", "mental", "stress", "help", "support", "scared", "afraid"]):
search_query = f"Bangladesh women mental health support trauma counseling"
web_result = search_web(search_query)
if web_result:
web_context += f"\n[MENTAL HEALTH: {web_result[:400]}]"
current_hour = datetime.now().hour
context = f"\n[CONTEXT: Time={datetime.now().strftime('%Y-%m-%d %I:%M %p')}, TimeOfDay={'NIGHT' if current_hour >= 20 or current_hour <= 6 else 'EVENING' if current_hour >= 17 else 'DAY'}, Location=Chittagong]{web_context}"
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
# Include conversation history (last 5 exchanges)
for user_msg, bot_msg in history[-5:]:
if user_msg and bot_msg:
messages.append({"role": "user", "content": user_msg})
messages.append({"role": "assistant", "content": bot_msg})
messages.append({"role": "user", "content": message + context})
response = call_groq(messages, api_key.strip())
# Extract locations for map - IMPROVED DETECTION
map_html = None
# More comprehensive route patterns
route_patterns = [
r'(?:from|start|starting|leave|depart)\s+([a-zA-Z\s,]+?)\s+(?:to|destination|ending|till|reach|arrive)\s+([a-zA-Z\s,]+?)(?:\.|$|,|\?|now|right)',
r'(?:route|way|path|travel|go|going)\s+(?:from\s+)?([a-zA-Z\s,]+?)\s+to\s+([a-zA-Z\s,]+?)(?:\.|$|,|\?|now|right)',
r'([a-zA-Z\s,]+?)\s+(?:to|till)\s+([a-zA-Z\s,]+?)\s+(?:route|safe|safety|now|right)',
r'safe.*?(?:from\s+)?([a-zA-Z\s,]+?)\s+(?:to|till)\s+([a-zA-Z\s,]+)',
]
for pattern in route_patterns:
route_match = re.search(pattern, message.lower())
if route_match:
start_loc = route_match.group(1).strip()
end_loc = route_match.group(2).strip()
# Clean up locations
start_loc = re.sub(r'\s+', ' ', start_loc)
end_loc = re.sub(r'\s+', ' ', end_loc)
print(f"DEBUG: Detected route - Start: {start_loc}, End: {end_loc}")
map_html = create_interactive_map(start_loc, end_loc, response[:300])
break
# If no route detected but keywords suggest mapping
if not map_html and any(word in keywords for word in ["route", "map", "from", "to", "safe way"]):
# Try to extract any two location-like words
locations = re.findall(r'\b([A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)\b', message)
if len(locations) >= 2:
print(f"DEBUG: Fallback detection - Locations: {locations}")
map_html = create_interactive_map(locations[0], locations[1], response[:300])
return history + [[message, response]], map_html
def show_legal_info():
return """# π Bangladesh Women's Legal Rights & Harassment Laws
## **Key Laws Protecting Women:**
### 1. **Sexual Harassment at Workplace (Prevention) Act 2009**
- **Definition:** Unwanted sexual advances, requests for sexual favors, verbal or physical conduct of sexual nature
- **Workplace Coverage:** All organizations must have complaint committees
- **Penalties:** Up to 5 years imprisonment and/or fine up to BDT 50,000
- **Protection:** Cannot dismiss complainant during investigation
### 2. **Women and Children Repression Prevention Act 2000 (Amended 2003)**
- **Covers:** Rape, gang rape, sexual assault, acid attacks, kidnapping, dowry-related violence
- **Severe Penalties:** Death penalty or life imprisonment for heinous offenses
- **Fast-Track Courts:** Designated courts for speedy justice
- **Protection:** Identity protection for victims
### 3. **Domestic Violence (Prevention and Protection) Act 2010**
- **Types of Abuse Covered:** Physical, psychological, sexual, economic abuse
- **Remedies Available:**
- Protection orders (restraining orders)
- Residence orders (right to stay in home)
- Monetary relief (compensation)
- Custody orders for children
- **Filing:** Can file with police or directly with magistrate
### 4. **Dowry Prohibition Act 1980**
- **Prohibition:** Giving, taking, or demanding dowry is illegal
- **Punishment:** Up to 5 years imprisonment + fine up to BDT 1,00,000
- **Protection:** Dowry-related violence covered under special laws
---
## **How to Report Harassment/Violence:**
### **IMMEDIATE ACTION:**
1. **Call Emergency Numbers:**
- Police: **999**
- Women & Children Helpline: **109**
- Chittagong Police Control: **031-619101**
2. **Preserve Evidence:**
- Screenshots of messages/emails
- Photos/videos (if safe to take)
- Witness contact information
- Medical records if injured
3. **Don't:**
- Wash or change clothes (if physical assault)
- Delete digital evidence
- Go alone to meet harasser
### **FILING COMPLAINT:**
**Option 1: Police Station (FIR - First Information Report)**
- Go to nearest police station
- **Your Right:** Police MUST register your FIR
- Get FIR copy immediately
- If police refuse, contact superintendent or DIG
**Option 2: Magistrate Court**
- Can file directly for domestic violence
- Magistrate can issue protection order immediately
**Option 3: Workplace Committee**
- For workplace harassment
- Committee must investigate within 60 days
- Appeal to appeals committee if needed
### **MEDICAL EXAMINATION:**
- **One-Stop Crisis Centers (OCC):** Available at medical college hospitals
- Chittagong Medical College Hospital OCC
- Provides medical + legal + psychological support
- Free and confidential
- Medical certificate is crucial legal evidence
---
## **Support Organizations in Chittagong:**
### **Legal Aid:**
- **National Legal Aid Services:** Call **16430**
- **Bangladesh Mahila Parishad (Women's Council)**
- **Bangladesh National Women Lawyers Association (BNWLA)**
- **Ain o Salish Kendra (ASK)**
- **BLAST (Bangladesh Legal Aid and Services Trust)**
### **Crisis Support:**
- **Women & Children Crisis Center:** **10921**
- **One-Stop Crisis Center (OCC):** Chittagong Medical College
- **BRAC Support Centers**
---
## **YOUR LEGAL RIGHTS:**
β **Right to file FIR** without harassment or dismissal
β **Right to free legal aid** (if financially unable)
β **Right to protection and privacy** (identity protection in court)
β **Right to compensation** for damages
β **Right to appeal** if dissatisfied with verdict
β **Right to witness protection** if threatened
β **Right to speedy trial** (fast-track courts available)
---
## **Important Legal Facts:**
- **Time Limit:** File as soon as possible. Some offenses have time limits.
- **No Compromise:** Serious offenses (rape, acid attack) are non-compoundable (cannot be settled out of court)
- **Burden of Proof:** In rape cases, accused must prove consent (shifted burden)
- **Privacy:** Court proceedings can be held in-camera (private)
- **Free Services:** Legal aid and medical examination are free for victims
---
## **What to Expect in Legal Process:**
1. **FIR Registration** (Day 1)
2. **Medical Examination** (Within 24 hours)
3. **Investigation** (Police collect evidence, interview witnesses)
4. **Charge Sheet** (Police submit to court)
5. **Trial** (Evidence presented, witnesses examined)
6. **Verdict** (Judge's decision)
7. **Appeal** (If needed, to High Court)
**Timeline:** Fast-track courts aim to complete trial within 6 months-1 year
---
## **EMERGENCY CONTACTS:**
- **Police Emergency:** **999**
- **Women Helpline:** **109**
- **Legal Aid:** **16430**
- **Crisis Center:** **10921**
- **Ambulance:** **199**
- **Chittagong Police:** **031-619101**
---
βοΈ **Remember:**
- **The law is on your side**
- **You have done nothing wrong**
- **You deserve justice and support**
- **Many organizations are ready to help you**
π For more information, visit Bangladesh Legal Aid and Services Trust (BLAST) website or contact local women's organizations."""
def show_sos_protocol():
current_hour = datetime.now().hour
current_time = datetime.now().strftime('%I:%M %p')
# Determine alert level
if current_hour >= 22 or current_hour <= 5:
alert = "π΄ VERY HIGH RISK"
alert_color = "#dc3545"
time_advice = "Extremely dangerous hours. Avoid travel. Call 999 immediately if threatened."
elif current_hour >= 20 or current_hour <= 6:
alert = "π HIGH RISK"
alert_color = "#fd7e14"
time_advice = "Night time - high caution needed. Stay on main roads, inform family."
elif current_hour >= 18:
alert = "π‘ MODERATE RISK"
alert_color = "#ffc107"
time_advice = "Evening time - stay in well-lit areas, complete travel before 9 PM."
else:
alert = "π’ LOWER RISK"
alert_color = "#28a745"
time_advice = "Daytime - generally safer but remain alert and aware."
return f"""# π¨ SOS EMERGENCY PROTOCOL
β οΈ Please enter both starting location and destination
"
return create_interactive_map(start, end)
map_btn.click(show_route_map, [start_input, end_input], route_map)
# Chat functionality with proper message handling
def chat_wrapper(message, history, api_key):
if not history:
history = []
# Convert messages format to tuples for processing
history_tuples = [(msg["content"], resp["content"]) for msg, resp in zip(history[::2], history[1::2])] if history else []
# Get response
updated_history, map_html = enhanced_chat(message, history_tuples, api_key)
# Convert back to messages format
messages = []
for user_msg, bot_msg in updated_history:
messages.append({"role": "user", "content": user_msg})
messages.append({"role": "assistant", "content": bot_msg})
return messages, map_html, ""
msg.submit(chat_wrapper, [msg, chatbot, api_key], [chatbot, map_display, msg])
send.click(chat_wrapper, [msg, chatbot, api_key], [chatbot, map_display, msg])
gr.Markdown("""
---
### π SafeHer AI Features:
β **Live Route Safety Mapping** with OpenStreetMap
β **Real-Time Safety Intelligence** based on time and location
β **Complete Legal Information** about Bangladesh laws
β **Mental Health Support** and trauma care resources
β **Emergency SOS Protocols** with step-by-step guidance
β **Chittagong-Specific** safety information and contacts
### π Emergency Contacts (Save These Numbers):
| Service | Number | When to Call |
|---------|---------|--------------|
| **Police Emergency** | **999** | Any danger, crime, harassment |
| **Women Helpline** | **109** | Women-specific issues, support |
| **Legal Aid** | **16430** | Free legal help |
| **Crisis Center** | **10921** | Trauma, mental health crisis |
| **Ambulance** | **199** | Medical emergency |
| **Chittagong Police** | **031-619101** | Local police control room |
### π Privacy & Safety:
- Your conversations are private
- No data is stored permanently
- For real emergencies, always call 999 first
- This AI provides guidance, not replacement for professional help
---
**Made with π for the safety and wellbeing of women in Chittagong**
*Stay safe. Stay strong. You are never alone.*
""")
if __name__ == "__main__":
app.launch(
server_name="0.0.0.0",
server_port=7860,
share=False
)