diff --git a/src/activitypub/inbox.rs b/src/activitypub/inbox.rs index 612aa6b..20982b3 100644 --- a/src/activitypub/inbox.rs +++ b/src/activitypub/inbox.rs @@ -1,20 +1,45 @@ -use axum::{extract::State, http::StatusCode, Json}; -use sea_orm::{EntityTrait, QueryOrder, QuerySelect}; +use axum::{extract::{Query, State}, http::StatusCode}; +use sea_orm::{ColumnTrait, Condition, EntityTrait, QueryFilter, QueryOrder, QuerySelect}; -use crate::{model, server::Context}; +use crate::{activitystream::{object::collection::{page::CollectionPageMut, CollectionMut, CollectionType}, BaseMut, Node}, model, server::Context, url}; -use super::JsonLD; +use super::{activity::ap_activity, jsonld::LD, JsonLD, Pagination, PUBLIC_TARGET}; -pub async fn get(State(ctx) : State, Json(_object): Json) -> Result, StatusCode> { - match model::activity::Entity::find() - .order_by(model::activity::Column::Published, sea_orm::Order::Desc) - .limit(20) - .all(ctx.db()) - .await - { - Ok(x) => todo!(), - Err(_e) => Err(StatusCode::INTERNAL_SERVER_ERROR), +pub async fn get(State(ctx) : State, Query(page): Query) -> Result, StatusCode> { + let limit = page.batch.unwrap_or(20).min(100); + let offset = page.offset.unwrap_or(0); + if let Some(true) = page.page { + match model::addressing::Entity::find() + .filter(Condition::all().add(model::addressing::Column::Actor.eq(PUBLIC_TARGET))) + .order_by(model::addressing::Column::Published, sea_orm::Order::Desc) + .find_also_related(model::activity::Entity) // TODO join also with objects + .limit(limit) + .offset(offset) + .all(ctx.db()) + .await + { + Ok(x) => Ok(JsonLD(serde_json::Value::new_object() + .set_id(Some(&url!(ctx, "/inbox"))) + .set_collection_type(Some(CollectionType::OrderedCollection)) + .set_part_of(Node::link(url!(ctx, "/inbox"))) + .set_next(Node::link(url!(ctx, "/inbox?page=true&offset={}", offset+limit))) + .set_ordered_items(Node::array( + x.into_iter() + .filter_map(|(_, a)| Some(ap_activity(a?))) + .collect() + )) + .ld_context() + )), + Err(_e) => Err(StatusCode::INTERNAL_SERVER_ERROR), + } + } else { + Ok(JsonLD(serde_json::Value::new_object() + .set_id(Some(&url!(ctx, "/inbox"))) + .set_collection_type(Some(CollectionType::OrderedCollection)) + .set_first(Node::link(url!(ctx, "/inbox?page=true"))) + .ld_context() + )) } } diff --git a/src/model/addressing.rs b/src/model/addressing.rs index 4eae990..8dea7d5 100644 --- a/src/model/addressing.rs +++ b/src/model/addressing.rs @@ -8,6 +8,7 @@ pub struct Model { pub actor: String, pub activity: String, pub object: Option, + pub published: ChronoDateTimeUtc, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/src/router.rs b/src/router.rs index b1e041d..7835e68 100644 --- a/src/router.rs +++ b/src/router.rs @@ -8,8 +8,10 @@ pub async fn serve(db: DatabaseConnection, domain: String) { // core server inbox/outbox, maybe for feeds? TODO do we need these? .route("/", get(ap::view)) // TODO shared inboxes and instance stream will come later, just use users *boxes for now - // .route("/inbox", post(ap::inbox)) - // .route("/outbox", get(ap::outbox)) + .route("/inbox", get(ap::inbox::get)) + // .route("/inbox", post(ap::inbox::post)) + // .route("/outbox", get(ap::outbox::get)) + // .route("/outbox", get(ap::outbox::post)) // .well-known and discovery .route("/.well-known/webfinger", get(ap::well_known::webfinger)) .route("/.well-known/host-meta", get(ap::well_known::host_meta)) @@ -26,8 +28,8 @@ pub async fn serve(db: DatabaseConnection, domain: String) { .route("/objects/:id", get(ap::object::view)) .with_state(crate::server::Context::new(db, domain)); - // run our app with hyper, listening globally on port 3000 - let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); + // run our app with hyper, listening locally on port 3000 + let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap(); axum::serve(listener, app) .await diff --git a/src/server.rs b/src/server.rs index 7574cf0..0623ace 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,8 +1,6 @@ use std::sync::Arc; -use axum::{routing::{get, post}, Router}; use sea_orm::DatabaseConnection; -use crate::activitypub as ap; #[derive(Clone)] pub struct Context(Arc);