Rss feed
This commit is contained in:
@@ -19,6 +19,7 @@ serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
easy-nostr = { path = "./easy-nostr" }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
feed-rs = "2.3.1"
|
||||
|
||||
# FIX: default-features entfernt und rustls-tls hinzugefügt
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
|
||||
|
||||
@@ -11,6 +11,8 @@ pub fn run() {
|
||||
home::fetch_nostr_posts,
|
||||
news::save_openrouter_key,
|
||||
news::fetch_ai_news,
|
||||
news::fetch_rss_news,
|
||||
news::save_rss_url,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
||||
@@ -5,6 +5,7 @@ use tauri::State;
|
||||
#[derive(Default)]
|
||||
pub struct NewsState {
|
||||
pub openrouter_key: Mutex<String>,
|
||||
pub rss_url: Mutex<String>, // Neu: Speicher für die RSS-URL
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
@@ -15,26 +16,29 @@ pub struct NewsArticle {
|
||||
pub created_at: u64,
|
||||
}
|
||||
|
||||
// Bestehender Command für den API Key
|
||||
#[tauri::command]
|
||||
pub async fn save_openrouter_key(key: String, state: State<'_, NewsState>) -> Result<(), String> {
|
||||
let mut lock = state
|
||||
.openrouter_key
|
||||
.lock()
|
||||
.map_err(|_| "Lock failed".to_string())?;
|
||||
let mut lock = state.openrouter_key.lock().map_err(|_| "Lock failed")?;
|
||||
*lock = key.trim().to_string();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// NEU: Command zum Speichern der RSS URL
|
||||
#[tauri::command]
|
||||
pub async fn save_rss_url(url: String, state: State<'_, NewsState>) -> Result<(), String> {
|
||||
let mut lock = state.rss_url.lock().map_err(|_| "Lock failed")?;
|
||||
*lock = url.trim().to_string();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn fetch_ai_news(state: State<'_, NewsState>) -> Result<Vec<NewsArticle>, String> {
|
||||
let key = {
|
||||
let lock = state
|
||||
.openrouter_key
|
||||
.lock()
|
||||
.map_err(|_| "Lock failed".to_string())?;
|
||||
lock.clone()
|
||||
};
|
||||
|
||||
let key = state
|
||||
.openrouter_key
|
||||
.lock()
|
||||
.map_err(|_| "Lock failed")?
|
||||
.clone();
|
||||
if key.is_empty() {
|
||||
return Err("API Key fehlt.".to_string());
|
||||
}
|
||||
@@ -51,21 +55,15 @@ pub async fn fetch_ai_news(state: State<'_, NewsState>) -> Result<Vec<NewsArticl
|
||||
let response = client
|
||||
.post("https://openrouter.ai/api/v1/chat/completions")
|
||||
.header("Authorization", format!("Bearer {}", key))
|
||||
.header("HTTP-Referer", "http://localhost:1420")
|
||||
.json(&body)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
return Err(format!("API Fehler: {}", response.status()));
|
||||
}
|
||||
|
||||
let json_res: serde_json::Value = response.json().await.map_err(|e| e.to_string())?;
|
||||
|
||||
let content = json_res["choices"][0]["message"]["content"]
|
||||
.as_str()
|
||||
.ok_or_else(|| "Kein Content im JSON".to_string())?
|
||||
.unwrap_or("Fehler")
|
||||
.to_string();
|
||||
|
||||
Ok(vec![NewsArticle {
|
||||
@@ -74,3 +72,46 @@ pub async fn fetch_ai_news(state: State<'_, NewsState>) -> Result<Vec<NewsArticl
|
||||
created_at: 0,
|
||||
}])
|
||||
}
|
||||
|
||||
// VERBESSERT: Lädt nun den echten Feed von der gespeicherten URL
|
||||
#[tauri::command]
|
||||
pub async fn fetch_rss_news(state: State<'_, NewsState>) -> Result<Vec<NewsArticle>, String> {
|
||||
let url = state.rss_url.lock().map_err(|_| "Lock failed")?.clone();
|
||||
|
||||
if url.is_empty() {
|
||||
return Err("RSS URL fehlt. Bitte in den Einstellungen eintragen.".to_string());
|
||||
}
|
||||
|
||||
let response = reqwest::get(&url)
|
||||
.await
|
||||
.map_err(|e| e.to_string())?
|
||||
.bytes()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let feed = feed_rs::parser::parse(&response[..]).map_err(|e| e.to_string())?;
|
||||
|
||||
let articles = feed
|
||||
.entries
|
||||
.into_iter()
|
||||
.take(5)
|
||||
.map(|entry| NewsArticle {
|
||||
content: format!(
|
||||
"### {}\n\n{}",
|
||||
entry.title.map(|t| t.content).unwrap_or_default(),
|
||||
entry
|
||||
.summary
|
||||
.map(|s| s.content)
|
||||
.unwrap_or_else(|| "Kein Inhalt".to_string())
|
||||
),
|
||||
author: feed
|
||||
.title
|
||||
.as_ref()
|
||||
.map(|t| t.content.clone())
|
||||
.unwrap_or_else(|| "RSS".into()),
|
||||
created_at: entry.updated.map(|d| d.timestamp() as u64).unwrap_or(0),
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(articles)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user