Feed polling
This commit is contained in:
parent
f8b81d8382
commit
5c103507c1
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2432,6 +2432,7 @@ dependencies = [
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"ubyte",
|
||||
"uuid",
|
||||
"version_check",
|
||||
"yansi",
|
||||
]
|
||||
@ -2513,6 +2514,7 @@ dependencies = [
|
||||
"time",
|
||||
"tokio",
|
||||
"uncased",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -7,7 +7,7 @@ edition = "2021"
|
||||
argon2 = "0.5.3"
|
||||
atom_syndication = "0.12.6"
|
||||
chrono = { version = "0.4.34", features = ["serde"] }
|
||||
rocket = { version = "0.5.1", features = ["json", "secrets"] }
|
||||
rocket = { version = "0.5.1", features = ["json", "secrets", "uuid"] }
|
||||
rocket_db_pools = { version = "0.2.0", features = ["sqlx_sqlite"] }
|
||||
rocket_dyn_templates = { version = "0.2.0", features = ["tera"] }
|
||||
rss = "2.0.11"
|
||||
|
31
src/feed_utils.rs
Normal file
31
src/feed_utils.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use feed_rs;
|
||||
use url::Url;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FeedError;
|
||||
|
||||
pub async fn fetch_feed(url: &Url) -> Result<feed_rs::model::Feed, FeedError> {
|
||||
// Fetch the feed content
|
||||
let response = reqwest::get(url.as_ref()).await.map_err(|e| {
|
||||
eprintln!("Failed to fetch feed: {}", e);
|
||||
FeedError
|
||||
})?;
|
||||
|
||||
let content = response.text().await.map_err(|e| {
|
||||
eprintln!("Failed to read response body: {}", e);
|
||||
FeedError
|
||||
})?;
|
||||
|
||||
// Parse the feed
|
||||
let feed_data = feed_rs::parser::parse(content.as_bytes()).map_err(|e| {
|
||||
eprintln!("Failed to parse feed content: {}", e);
|
||||
FeedError
|
||||
})?;
|
||||
|
||||
println!("Fetched feed: {}", url.as_ref());
|
||||
for item in &feed_data.entries {
|
||||
println!("{:?}", item);
|
||||
}
|
||||
|
||||
Ok(feed_data)
|
||||
}
|
31
src/feeds.rs
31
src/feeds.rs
@ -5,6 +5,7 @@ use sqlx::types::JsonValue;
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::feed_utils::fetch_feed;
|
||||
use crate::user::AuthenticatedUser;
|
||||
use crate::Db;
|
||||
|
||||
@ -43,36 +44,6 @@ pub struct NewFeed {
|
||||
pub categorization: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FeedError;
|
||||
|
||||
async fn fetch_feed(url: &Url) -> Result<feed_rs::model::Feed, FeedError> {
|
||||
// Fetch the feed content
|
||||
let response = reqwest::get(url.as_ref()).await.map_err(|e| {
|
||||
eprintln!("Failed to fetch feed: {}", e);
|
||||
FeedError
|
||||
})?;
|
||||
|
||||
let content = response.text().await.map_err(|e| {
|
||||
eprintln!("Failed to read response body: {}", e);
|
||||
FeedError
|
||||
})?;
|
||||
|
||||
// Parse the feed
|
||||
let feed_data = feed_rs::parser::parse(content.as_bytes()).map_err(|e| {
|
||||
eprintln!("Failed to parse feed content: {}", e);
|
||||
FeedError
|
||||
})?;
|
||||
|
||||
println!("Fetched feed: {}", url.as_ref());
|
||||
for item in &feed_data.entries {
|
||||
println!("{:?}", item);
|
||||
|
||||
}
|
||||
|
||||
Ok(feed_data)
|
||||
}
|
||||
|
||||
#[post("/feeds", data = "<new_feed>")]
|
||||
pub async fn create_feed(
|
||||
mut db: Connection<Db>,
|
||||
|
@ -1,7 +1,9 @@
|
||||
#[macro_use]
|
||||
extern crate rocket;
|
||||
|
||||
mod feed_utils;
|
||||
mod feeds;
|
||||
mod poll;
|
||||
mod user;
|
||||
|
||||
use rocket::fs::FileServer;
|
||||
@ -64,6 +66,7 @@ fn rocket() -> _ {
|
||||
feeds::get_feed,
|
||||
feeds::list_feeds,
|
||||
feeds::delete_feed,
|
||||
poll::poll_feed,
|
||||
],
|
||||
)
|
||||
.mount("/static", FileServer::from("static"))
|
||||
|
35
src/poll.rs
Normal file
35
src/poll.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use crate::{feed_utils::fetch_feed, Db};
|
||||
use rocket::http::Status;
|
||||
use rocket::serde::uuid::Uuid;
|
||||
use rocket::serde::{json::Json, Serialize};
|
||||
use rocket_db_pools::Connection;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct FeedPollResponse {
|
||||
count: usize,
|
||||
}
|
||||
|
||||
#[post("/poll/<feed_id>")]
|
||||
pub async fn poll_feed(
|
||||
mut db: Connection<Db>,
|
||||
feed_id: Uuid,
|
||||
) -> Result<Json<FeedPollResponse>, Status> {
|
||||
let feed_id = feed_id.to_string();
|
||||
// Get the feed URL from the database
|
||||
let feed_url = sqlx::query!("SELECT url FROM feeds WHERE feed_id = ?", feed_id)
|
||||
.fetch_optional(&mut **db)
|
||||
.await
|
||||
.map_err(|_| Status::InternalServerError)?
|
||||
.ok_or(Status::NotFound)?
|
||||
.url;
|
||||
|
||||
// Parse the URL
|
||||
let url = url::Url::parse(&feed_url).map_err(|_| Status::InternalServerError)?;
|
||||
|
||||
let feed_data = fetch_feed(&url).await.map_err(|_| Status::BadGateway)?;
|
||||
|
||||
Ok(Json(FeedPollResponse {
|
||||
count: feed_data.entries.len(),
|
||||
}))
|
||||
}
|
@ -33,9 +33,20 @@ function renderFeedItem(feed) {
|
||||
const name = document.createElement('span');
|
||||
name.className = 'feed-name';
|
||||
name.textContent = feed.name;
|
||||
name.onclick = () => {
|
||||
// TODO: Handle feed click
|
||||
console.log('Feed clicked:', feed);
|
||||
name.onclick = async () => {
|
||||
try {
|
||||
const response = await fetch(`/poll/${feed.feed_id}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
console.log('Feed poll response:', data);
|
||||
} else {
|
||||
console.error('Failed to poll feed:', response.status);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error polling feed:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const menuButton = document.createElement('button');
|
||||
|
Loading…
Reference in New Issue
Block a user