Added importer actor, file upload still not working
This commit is contained in:
@@ -202,7 +202,6 @@ pub async fn stream(
|
||||
Ok(CrawlSchedulerHandleMessage::FeedCrawler(FeedCrawlerHandleMessage::Entry(Ok(_)))) => {
|
||||
Ok(Event::default().data(
|
||||
html! {
|
||||
turbo-stream action="remove" target="feed-stream" {}
|
||||
turbo-stream action="replace" target=(feed_id) {
|
||||
template {
|
||||
li id=(feed_id) { "fetched entry" }
|
||||
@@ -216,7 +215,6 @@ pub async fn stream(
|
||||
error,
|
||||
)))) => Ok(Event::default().data(
|
||||
html! {
|
||||
turbo-stream action="remove" target="feed-stream" {}
|
||||
turbo-stream action="replace" target=(feed_id) {
|
||||
template {
|
||||
li id=(feed_id) { span class="error" { (error) } }
|
||||
|
||||
@@ -31,16 +31,19 @@ pub async fn get(State(pool): State<PgPool>, layout: Layout) -> Result<Response>
|
||||
}
|
||||
div class="add-feed" {
|
||||
h3 { "Add Feed" }
|
||||
form action="/feed" method="post" class="add-feed-form" {
|
||||
form action="/feed" method="post" class="feed-form" {
|
||||
div class="form-grid" {
|
||||
label for="url" { "URL (required): " }
|
||||
label for="url" { "URL: " }
|
||||
input type="text" id="url" name="url" placeholder="https://example.com/feed.xml" required="true";
|
||||
label for="title" { "Title: " }
|
||||
input type="text" id="title" name="title" placeholder="Feed title";
|
||||
label { "Description: " }
|
||||
textarea id="description" name="description" placeholder="Feed description" {}
|
||||
button type="submit" { "Add Feed" }
|
||||
}
|
||||
}
|
||||
form action="/import/opml" method="post" enctype="mulipart/form-data" class="feed-form" {
|
||||
div class="form-grid" {
|
||||
label for="opml" { "OPML: " }
|
||||
input type="file" id="opml" name="opml" required="true" accept="text/x-opml,application/xml,text/xml";
|
||||
button type="submit" { "Import Feeds" }
|
||||
}
|
||||
button type="submit" { "Add Feed" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
134
src/handlers/import.rs
Normal file
134
src/handlers/import.rs
Normal file
@@ -0,0 +1,134 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use axum::extract::{Multipart, Path, State};
|
||||
use axum::http::StatusCode;
|
||||
use axum::response::sse::{Event, KeepAlive};
|
||||
use axum::response::{IntoResponse, Response, Sse};
|
||||
use maud::html;
|
||||
use tokio_stream::wrappers::BroadcastStream;
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
use crate::actors::crawl_scheduler::CrawlSchedulerHandleMessage;
|
||||
use crate::actors::feed_crawler::FeedCrawlerHandleMessage;
|
||||
use crate::actors::importer::{ImporterHandle, ImporterHandleMessage};
|
||||
use crate::error::{Error, Result};
|
||||
use crate::partials::feed_link::feed_link;
|
||||
use crate::state::Imports;
|
||||
use crate::turbo_stream::TurboStream;
|
||||
use crate::uuid::Base62Uuid;
|
||||
|
||||
pub async fn opml(
|
||||
State(imports): State<Imports>,
|
||||
State(importer): State<ImporterHandle>,
|
||||
mut multipart: Multipart,
|
||||
) -> Result<Response> {
|
||||
dbg!("opml handler");
|
||||
if let Some(field) = multipart.next_field().await.map_err(|err| { dbg!(&err); err })? {
|
||||
let import_id = Base62Uuid::new();
|
||||
dbg!(&import_id);
|
||||
let file_name = field.file_name().map(|s| s.to_string());
|
||||
dbg!(&file_name);
|
||||
let bytes = field.bytes().await?;
|
||||
dbg!(&bytes.len());
|
||||
let receiver = importer.import(import_id, file_name, bytes).await;
|
||||
{
|
||||
let mut imports = imports.lock().await;
|
||||
imports.insert(import_id.as_uuid(), receiver);
|
||||
}
|
||||
|
||||
let import_html_id = format!("import-{}", import_id);
|
||||
let import_stream = format!("/import/{}/stream", import_id);
|
||||
return Ok((
|
||||
StatusCode::CREATED,
|
||||
TurboStream(
|
||||
html! {
|
||||
turbo-stream-source src=(import_stream) id="import-stream" {}
|
||||
turbo-stream action="append" target="feeds" {
|
||||
template {
|
||||
li id=(import_html_id) { "Importing..." }
|
||||
}
|
||||
}
|
||||
turbo-stream action="remove" target="no-feeds";
|
||||
}
|
||||
.into_string(),
|
||||
),
|
||||
)
|
||||
.into_response());
|
||||
}
|
||||
dbg!("no file");
|
||||
Err(Error::NoFile)
|
||||
}
|
||||
|
||||
pub async fn stream(
|
||||
Path(id): Path<Base62Uuid>,
|
||||
State(imports): State<Imports>,
|
||||
) -> Result<impl IntoResponse> {
|
||||
let receiver = {
|
||||
let mut imports = imports.lock().await;
|
||||
imports.remove(&id.as_uuid())
|
||||
}
|
||||
.ok_or_else(|| Error::NotFound("import stream", id.as_uuid()))?;
|
||||
|
||||
let stream = BroadcastStream::new(receiver);
|
||||
let import_html_id = format!("import-{}", id);
|
||||
let stream = stream.map(move |msg| match msg {
|
||||
Ok(ImporterHandleMessage::Import(Ok(_))) => Ok::<Event, String>(
|
||||
Event::default().data(
|
||||
html! {
|
||||
turbo-stream action="remove" target="import-stream" {}
|
||||
turbo-stream action="replace" target=(import_html_id) {
|
||||
template {
|
||||
li id=(import_html_id) { "Done importing" }
|
||||
}
|
||||
}
|
||||
}
|
||||
.into_string(),
|
||||
),
|
||||
),
|
||||
Ok(ImporterHandleMessage::CrawlScheduler(CrawlSchedulerHandleMessage::FeedCrawler(
|
||||
FeedCrawlerHandleMessage::Feed(Ok(feed)),
|
||||
))) => Ok::<Event, String>(
|
||||
Event::default().data(
|
||||
html! {
|
||||
turbo-stream action="prepend" target="feeds" {
|
||||
template {
|
||||
li id=(format!("feed-{}", feed.feed_id)) { (feed_link(&feed, false)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
.into_string(),
|
||||
),
|
||||
),
|
||||
Ok(ImporterHandleMessage::CrawlScheduler(CrawlSchedulerHandleMessage::FeedCrawler(
|
||||
FeedCrawlerHandleMessage::Feed(Err(error)),
|
||||
))) => Ok::<Event, String>(
|
||||
Event::default().data(
|
||||
html! {
|
||||
turbo-stream action="prepend" target="feeds" {
|
||||
template {
|
||||
li { span class="error" { (error) } }
|
||||
}
|
||||
}
|
||||
}
|
||||
.into_string(),
|
||||
),
|
||||
),
|
||||
Ok(ImporterHandleMessage::Import(Err(error))) => Ok(Event::default().data(
|
||||
html! {
|
||||
turbo-stream action="remove" target="import-stream" {}
|
||||
turbo-stream action="replace" target=(import_html_id) {
|
||||
template {
|
||||
li id=(import_html_id) { span class="error" { (error) } }
|
||||
}
|
||||
}
|
||||
}
|
||||
.into_string(),
|
||||
)),
|
||||
_ => Ok(Event::default()),
|
||||
});
|
||||
Ok(Sse::new(stream).keep_alive(
|
||||
KeepAlive::new()
|
||||
.interval(Duration::from_secs(15))
|
||||
.text("keep-alive-text"),
|
||||
))
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
pub mod api;
|
||||
pub mod entry;
|
||||
pub mod home;
|
||||
pub mod import;
|
||||
pub mod feed;
|
||||
pub mod feeds;
|
||||
pub mod log;
|
||||
|
||||
Reference in New Issue
Block a user