Spaces:
Sleeping
Sleeping
Upload 7 files
Browse files
app.py
CHANGED
|
@@ -144,21 +144,34 @@ Today's date: {datetime.utcnow().strftime('%Y-%m-%d')}
|
|
| 144 |
# ---------------------------------------------------------------------------
|
| 145 |
|
| 146 |
RSS_SOURCE_OPTIONS = [
|
| 147 |
-
|
| 148 |
-
("
|
| 149 |
-
("
|
| 150 |
-
("
|
| 151 |
-
("
|
| 152 |
-
("
|
| 153 |
-
("
|
| 154 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
]
|
| 156 |
|
| 157 |
EXAMPLE_QUERIES = [
|
| 158 |
-
["Sudan", ["bbc_world", "al_jazeera", "middle_east_eye"], 14],
|
| 159 |
-
["Myanmar", ["bbc_world", "crisis_group", "radio_free_asia"], 21],
|
| 160 |
-
["Ukraine", ["bbc_world", "npr_world", "sky_news"], 7],
|
| 161 |
-
["Haiti", ["bbc_world", "al_jazeera", "
|
| 162 |
]
|
| 163 |
|
| 164 |
CSS = """
|
|
@@ -191,9 +204,12 @@ with gr.Blocks(title="OSINT Threat Analyst", css=CSS, theme=gr.themes.Soft()) as
|
|
| 191 |
max_lines=1,
|
| 192 |
)
|
| 193 |
|
|
|
|
|
|
|
|
|
|
| 194 |
rss_sources = gr.CheckboxGroup(
|
| 195 |
choices=RSS_SOURCE_OPTIONS,
|
| 196 |
-
value=[
|
| 197 |
label="RSS News Sources",
|
| 198 |
)
|
| 199 |
|
|
@@ -254,6 +270,20 @@ with gr.Blocks(title="OSINT Threat Analyst", css=CSS, theme=gr.themes.Soft()) as
|
|
| 254 |
label="Example Queries",
|
| 255 |
)
|
| 256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
analyze_btn.click(
|
| 258 |
fn=run_analysis,
|
| 259 |
inputs=[country_input, rss_sources, days_back],
|
|
|
|
| 144 |
# ---------------------------------------------------------------------------
|
| 145 |
|
| 146 |
RSS_SOURCE_OPTIONS = [
|
| 147 |
+
# General world news
|
| 148 |
+
("BBC World", "bbc_world"),
|
| 149 |
+
("Al Jazeera", "al_jazeera"),
|
| 150 |
+
("France 24", "france24"),
|
| 151 |
+
("NPR World", "npr_world"),
|
| 152 |
+
("Sky News", "sky_news"),
|
| 153 |
+
("UN News", "un_news"),
|
| 154 |
+
# Regional / specialist
|
| 155 |
+
("Middle East Eye", "middle_east_eye"),
|
| 156 |
+
("Radio Free Asia", "radio_free_asia"),
|
| 157 |
+
# OSINT / investigative
|
| 158 |
+
("Bellingcat", "bellingcat"),
|
| 159 |
+
("The Intercept", "the_intercept"),
|
| 160 |
+
("OCCRP", "occrp"),
|
| 161 |
+
# Policy / security analysis
|
| 162 |
+
("Crisis Group", "crisis_group"),
|
| 163 |
+
("War on the Rocks", "war_on_rocks"),
|
| 164 |
+
("Just Security", "just_security"),
|
| 165 |
+
# Human rights
|
| 166 |
+
("Human Rights Watch", "hrw"),
|
| 167 |
+
("Amnesty Intl", "amnesty"),
|
| 168 |
]
|
| 169 |
|
| 170 |
EXAMPLE_QUERIES = [
|
| 171 |
+
["Sudan", ["bbc_world", "al_jazeera", "middle_east_eye", "hrw"], 14],
|
| 172 |
+
["Myanmar", ["bbc_world", "crisis_group", "radio_free_asia", "hrw"], 21],
|
| 173 |
+
["Ukraine", ["bbc_world", "npr_world", "sky_news", "war_on_rocks"], 7],
|
| 174 |
+
["Haiti", ["bbc_world", "al_jazeera", "un_news", "amnesty"], 14],
|
| 175 |
]
|
| 176 |
|
| 177 |
CSS = """
|
|
|
|
| 204 |
max_lines=1,
|
| 205 |
)
|
| 206 |
|
| 207 |
+
with gr.Row():
|
| 208 |
+
select_all_btn = gr.Button("Deselect All", size="sm", scale=1)
|
| 209 |
+
|
| 210 |
rss_sources = gr.CheckboxGroup(
|
| 211 |
choices=RSS_SOURCE_OPTIONS,
|
| 212 |
+
value=[v for _, v in RSS_SOURCE_OPTIONS], # all selected by default
|
| 213 |
label="RSS News Sources",
|
| 214 |
)
|
| 215 |
|
|
|
|
| 270 |
label="Example Queries",
|
| 271 |
)
|
| 272 |
|
| 273 |
+
_ALL_SOURCE_KEYS = [v for _, v in RSS_SOURCE_OPTIONS]
|
| 274 |
+
|
| 275 |
+
def toggle_sources(current_values):
|
| 276 |
+
"""Select all if any are unchecked; deselect all if all are checked."""
|
| 277 |
+
if len(current_values) == len(_ALL_SOURCE_KEYS):
|
| 278 |
+
return gr.update(value=[]), gr.update(value="Select All")
|
| 279 |
+
return gr.update(value=_ALL_SOURCE_KEYS), gr.update(value="Deselect All")
|
| 280 |
+
|
| 281 |
+
select_all_btn.click(
|
| 282 |
+
fn=toggle_sources,
|
| 283 |
+
inputs=[rss_sources],
|
| 284 |
+
outputs=[rss_sources, select_all_btn],
|
| 285 |
+
)
|
| 286 |
+
|
| 287 |
analyze_btn.click(
|
| 288 |
fn=run_analysis,
|
| 289 |
inputs=[country_input, rss_sources, days_back],
|
tools.py
CHANGED
|
@@ -177,14 +177,32 @@ def fetch_acled_events(country: str, days_back: int = 14, limit: int = 25) -> st
|
|
| 177 |
|
| 178 |
RSS_FEED_REGISTRY = {
|
| 179 |
# Verified working as of 2026-05
|
|
|
|
|
|
|
| 180 |
"bbc_world": "https://feeds.bbci.co.uk/news/world/rss.xml",
|
| 181 |
"al_jazeera": "https://www.aljazeera.com/xml/rss/all.xml",
|
| 182 |
-
"
|
| 183 |
-
"crisis_group": "https://www.crisisgroup.org/rss.xml",
|
| 184 |
"npr_world": "https://feeds.npr.org/1004/rss.xml",
|
| 185 |
-
"middle_east_eye": "https://www.middleeasteye.net/rss",
|
| 186 |
"sky_news": "https://feeds.skynews.com/feeds/rss/world.xml",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
"radio_free_asia": "https://www.rfa.org/english/rss2.xml",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
}
|
| 189 |
|
| 190 |
SCAN_LIMIT = 50
|
|
|
|
| 177 |
|
| 178 |
RSS_FEED_REGISTRY = {
|
| 179 |
# Verified working as of 2026-05
|
| 180 |
+
|
| 181 |
+
# --- General world news ---
|
| 182 |
"bbc_world": "https://feeds.bbci.co.uk/news/world/rss.xml",
|
| 183 |
"al_jazeera": "https://www.aljazeera.com/xml/rss/all.xml",
|
| 184 |
+
"france24": "https://www.france24.com/en/rss",
|
|
|
|
| 185 |
"npr_world": "https://feeds.npr.org/1004/rss.xml",
|
|
|
|
| 186 |
"sky_news": "https://feeds.skynews.com/feeds/rss/world.xml",
|
| 187 |
+
"un_news": "https://news.un.org/feed/subscribe/en/news/all/rss.xml",
|
| 188 |
+
|
| 189 |
+
# --- Regional / specialist ---
|
| 190 |
+
"middle_east_eye": "https://www.middleeasteye.net/rss",
|
| 191 |
"radio_free_asia": "https://www.rfa.org/english/rss2.xml",
|
| 192 |
+
|
| 193 |
+
# --- OSINT / investigative ---
|
| 194 |
+
"bellingcat": "https://www.bellingcat.com/feed/",
|
| 195 |
+
"the_intercept": "https://theintercept.com/feed/?rss",
|
| 196 |
+
"occrp": "https://www.occrp.org/en/component/rssfeed/index.xml",
|
| 197 |
+
|
| 198 |
+
# --- Policy / security analysis ---
|
| 199 |
+
"crisis_group": "https://www.crisisgroup.org/rss.xml",
|
| 200 |
+
"war_on_rocks": "https://warontherocks.com/feed/",
|
| 201 |
+
"just_security": "https://www.justsecurity.org/feed/",
|
| 202 |
+
|
| 203 |
+
# --- Human rights ---
|
| 204 |
+
"hrw": "https://www.hrw.org/rss.xml",
|
| 205 |
+
"amnesty": "https://www.amnesty.org/en/feed/",
|
| 206 |
}
|
| 207 |
|
| 208 |
SCAN_LIMIT = 50
|