1
0
Fork 0
mirror of https://github.com/Nutomic/ibis.git synced 2025-02-11 02:04:52 +00:00

instance view with articles (not working)

This commit is contained in:
Felix Ableitner 2025-01-24 12:48:08 +01:00
parent 9677a316f1
commit 18514e082c
6 changed files with 67 additions and 30 deletions

View file

@ -7,15 +7,11 @@ use crate::{
},
common::{
instance::{
DbInstance,
FollowInstanceParams,
GetInstanceParams,
InstanceView,
DbInstance, FollowInstanceParams, GetInstanceParams, InstanceView, InstanceView2,
UpdateInstanceParams,
},
user::LocalUserView,
ResolveObjectParams,
SuccessResponse,
ResolveObjectParams, SuccessResponse,
},
};
use activitypub_federation::{config::Data, fetch::object_id::ObjectId};
@ -27,7 +23,7 @@ use axum_macros::debug_handler;
pub(in crate::backend::api) async fn get_instance(
context: Data<IbisContext>,
Form(params): Form<GetInstanceParams>,
) -> MyResult<Json<InstanceView>> {
) -> MyResult<Json<InstanceView2>> {
let local_instance = DbInstance::read_view(params.id, &context)?;
Ok(Json(local_instance))
}
@ -75,7 +71,7 @@ pub(super) async fn resolve_instance(
#[debug_handler]
pub(in crate::backend::api) async fn list_instances(
context: Data<IbisContext>,
) -> MyResult<Json<Vec<DbInstance>>> {
) -> MyResult<Json<Vec<InstanceView>>> {
let instances = DbInstance::list(&context)?;
Ok(Json(instances))
}

View file

@ -5,14 +5,14 @@ use crate::{
IbisContext,
},
federation::objects::{
articles_collection::DbArticleCollection,
instance_collection::DbInstanceCollection,
articles_collection::DbArticleCollection, instance_collection::DbInstanceCollection,
},
utils::error::MyResult,
},
common::{
instance::{DbInstance, InstanceView},
newtypes::{CommentId, InstanceId},
article::DbArticle,
instance::{DbInstance, InstanceView, InstanceView2},
newtypes::{ArticleId, CommentId, InstanceId},
user::DbPerson,
},
};
@ -22,17 +22,19 @@ use activitypub_federation::{
};
use chrono::{DateTime, Utc};
use diesel::{
associations::HasTable,
define_sql_function,
deserialize::{self, FromSql},
insert_into,
update,
AsChangeset,
ExpressionMethods,
Insertable,
JoinOnDsl,
QueryDsl,
RunQueryDsl,
pg::{Pg, PgValue},
sql_types::Record,
update, AsChangeset, ExpressionMethods, Insertable, JoinOnDsl, NullableExpressionMethods,
QueryDsl, RunQueryDsl,
};
use std::{fmt::Debug, ops::DerefMut};
use super::array_agg;
#[derive(Debug, Clone, Insertable, AsChangeset)]
#[diesel(table_name = instance, check_for_backend(diesel::pg::Pg))]
pub struct DbInstanceForm {
@ -100,14 +102,14 @@ impl DbInstance {
pub fn read_view(
id: Option<InstanceId>,
context: &Data<IbisContext>,
) -> MyResult<InstanceView> {
) -> MyResult<InstanceView2> {
let instance = match id {
Some(id) => DbInstance::read(id, context),
None => DbInstance::read_local(context),
}?;
let followers = DbInstance::read_followers(instance.id, context)?;
Ok(InstanceView {
Ok(InstanceView2 {
instance,
followers,
})
@ -147,9 +149,28 @@ impl DbInstance {
.get_results(conn.deref_mut())?)
}
pub fn list(context: &Data<IbisContext>) -> MyResult<Vec<DbInstance>> {
pub fn list(context: &Data<IbisContext>) -> MyResult<Vec<InstanceView>> {
let mut conn = context.db_pool.get()?;
Ok(instance::table.get_results(conn.deref_mut())?)
// select instance, array_agg(article) from instance left join article on instance.id=article.instance_id group by instance.id;
let res: Vec<_> = instance::table
.left_join(article::table.on(instance::id.eq(article::instance_id)))
.select((
instance::all_columns,
//array_agg(article::all_columns)
diesel::dsl::sql::<diesel::sql_types::Array<article::SqlType>>(
"array_agg(article.*)",
),
))
.group_by(instance::id)
// TODO: throws invalid trait bound
.get_results::<(DbInstance, Vec<DbArticle>)>(conn.deref_mut())?;
Ok(res
.into_iter()
.map(|x| InstanceView {
instance: x.0,
articles: x.1,
})
.collect())
}
/// Read the instance where an article is hosted, based on a comment id.
@ -167,3 +188,16 @@ impl DbInstance {
.get_result(conn.deref_mut())?)
}
}
define_sql_function!(fn array_agg<T: diesel::sql_types::SingleValue>(expr: T) -> Array<T>);
// https://github.com/diesel-rs/diesel/discussions/3826
impl FromSql<diesel::sql_types::Record<article::SqlType>, Pg> for DbArticle {
fn from_sql(value: PgValue<'_>) -> deserialize::Result<Self> {
//let mut bytes = value.as_bytes();
//let res: (i32,) = FromSql::<Record<article::SqlType>, Pg>::from_sql(value)?;
//Ok(Label1 { id: res.0 })
todo!()
}
}

View file

@ -4,9 +4,7 @@ use crate::backend::{
};
use diesel::{
r2d2::{ConnectionManager, Pool},
PgConnection,
QueryDsl,
RunQueryDsl,
PgConnection, QueryDsl, RunQueryDsl,
};
use std::ops::DerefMut;

View file

@ -52,6 +52,7 @@ impl Collection for DbInstanceCollection {
let instances = future::try_join_all(
instances
.into_iter()
.map(|i| i.instance)
.filter(|i| !i.local)
.map(|i| i.into_json(context))
.collect::<Vec<_>>(),

View file

@ -1,4 +1,5 @@
use super::{
article::DbArticle,
newtypes::InstanceId,
user::{DbPerson, LocalUserView},
};
@ -9,8 +10,7 @@ use url::Url;
#[cfg(feature = "ssr")]
use {
crate::backend::{
database::schema::instance,
federation::objects::articles_collection::DbArticleCollection,
database::schema::instance, federation::objects::articles_collection::DbArticleCollection,
federation::objects::instance_collection::DbInstanceCollection,
},
activitypub_federation::fetch::{collection_id::CollectionId, object_id::ObjectId},
@ -55,6 +55,14 @@ impl DbInstance {
#[cfg_attr(feature = "ssr", derive(Queryable))]
#[cfg_attr(feature = "ssr", diesel(table_name = article, check_for_backend(diesel::pg::Pg)))]
pub struct InstanceView {
pub instance: DbInstance,
pub articles: Vec<DbArticle>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[cfg_attr(feature = "ssr", derive(Queryable))]
#[cfg_attr(feature = "ssr", diesel(table_name = article, check_for_backend(diesel::pg::Pg)))]
pub struct InstanceView2 {
pub instance: DbInstance,
pub followers: Vec<DbPerson>,
}

View file

@ -4,7 +4,7 @@ use crate::common::{
instance::{
DbInstance,
FollowInstanceParams,
InstanceView,
InstanceView2,
SiteView,
UpdateInstanceParams,
},
@ -17,7 +17,7 @@ use leptos::prelude::ServerFnError;
use url::Url;
impl ApiClient {
pub async fn get_local_instance(&self) -> Option<InstanceView> {
pub async fn get_local_instance(&self) -> Option<InstanceView2> {
self.get("/api/v1/instance", None::<i32>).await
}