import os import tempfile import logging import urllib.parse import requests import streamlit as st from gtts import gTTS from dotenv import load_dotenv from translatepy import Translator # -------------------- Load Environment -------------------- load_dotenv() # -------------------- Configuration -------------------- WIKIPEDIA_API_BASE_URL_PREFIX = ".wikipedia.org/w/api.php" ENGLISH_SUMMARY_SENTENCES = 5 WIKIMEDIA_HEADERS = { 'User-Agent': 'WikiHealthNavigator/1.0 (contact@example.com)' } REQUEST_TIMEOUT = 30 translator = Translator() logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # -------------------- Wikipedia Summary Fetch -------------------- @st.cache_data(ttl=3600) def fetch_wikipedia_content(query, lang="en", is_fallback=False): if not query: return None, None, lang title = query.strip() encoded_title = urllib.parse.quote(title, safe="") rest_url = f"https://{lang}.wikipedia.org/api/rest_v1/page/summary/{encoded_title}" try: resp = requests.get(rest_url, headers=WIKIMEDIA_HEADERS, timeout=REQUEST_TIMEOUT) resp.raise_for_status() j = resp.json() summary = j.get("extract") or j.get("description") full_url = j.get("content_urls", {}).get("desktop", {}).get("page") if summary: return summary, full_url, lang except Exception as e: logger.debug("REST failed: %s", e) try: api = f"https://{lang}{WIKIPEDIA_API_BASE_URL_PREFIX}" params = { "action": "query", "format": "json", "formatversion": 2, "prop": "extracts|info", "inprop": "url", "titles": title, "redirects": 1, "explaintext": True, **({"exsentences": ENGLISH_SUMMARY_SENTENCES} if lang == "en" else {}) } res = requests.get(api, params=params, headers=WIKIMEDIA_HEADERS, timeout=REQUEST_TIMEOUT) res.raise_for_status() pages = res.json().get("query", {}).get("pages", []) if pages and not pages[0].get("missing"): return pages[0].get("extract"), pages[0].get("fullurl"), lang except Exception as e: logger.debug("Query API failed: %s", e) if not is_fallback and lang != "en": return fetch_wikipedia_content(query, lang="en", is_fallback=True) return None, None, lang # -------------------- Wikipedia Image Fetch -------------------- @st.cache_data(ttl=3600) def fetch_wikipedia_images(query, lang="en", max_images=3): if not query: return [] api = f"https://{lang}.wikipedia.org/w/api.php" params = { "action": "query", "format": "json", "prop": "pageimages", "piprop": "original", "titles": query, "redirects": 1 } try: res = requests.get(api, params=params, headers=WIKIMEDIA_HEADERS, timeout=REQUEST_TIMEOUT) res.raise_for_status() pages = res.json().get("query", {}).get("pages", {}) images = [] for page in pages.values(): if "original" in page: images.append(page["original"]["source"]) return images[:max_images] except Exception as e: logger.debug("Image fetch failed: %s", e) return [] # -------------------- Narration -------------------- def narrate_text(text, lang_code): try: clean = text.strip().replace("\n", " ") if not clean: st.warning("Nothing to narrate.") return tts = gTTS(text=clean, lang=lang_code) with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as fp: tts.save(fp.name) audio_path = fp.name st.audio(audio_path, format="audio/mp3") except Exception as e: st.error(f"Narration error: {e}") # -------------------- Translation -------------------- def translate_summary(text, target_lang): try: return translator.translate(text, target_lang).result except Exception: return text # -------------------- Streamlit UI -------------------- st.set_page_config(page_title="WikiHealth Navigator", layout="centered") st.title("🩺 WikiHealth Navigator") st.markdown("Search health topics using Wikipedia (with images & audio)") languages = { "English": "en", "हिन्दी": "hi", "తెలుగు": "te", "தமிழ்": "ta" } col1, col2 = st.columns([2, 3]) with col1: selected = st.selectbox("Select Language:", list(languages.keys())) lang_code = languages[selected] with col2: query = st.text_input("Enter a health topic:") if st.button("🔍 Search") and query: with st.spinner("Searching Wikipedia..."): summary, url, actual_lang = fetch_wikipedia_content(query, lang_code) if summary: if actual_lang != lang_code: summary = translate_summary(summary, lang_code) st.subheader("📝 Summary") st.write(summary) st.subheader("🖼️ Related Images") images = fetch_wikipedia_images(query, lang_code) if images: cols = st.columns(len(images)) for col, img in zip(cols, images): col.image(img, use_container_width=True) else: st.info("No images found.") if st.button("🔊 Narrate Summary"): narrate_text(summary, lang_code) if url: st.markdown(f"[Read full article on Wikipedia]({url})") else: st.warning("No information found.")