mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-26 11:21:02 +00:00
Merge branch 'main' into fix_deleted_post_search_results
This commit is contained in:
commit
b9d36aa64e
16 changed files with 181 additions and 52 deletions
22
crates/apub/assets/nodebb/objects/group.json
Normal file
22
crates/apub/assets/nodebb/objects/group.json
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
"id": "https://community.nodebb.org/category/31",
|
||||||
|
"url": "https://community.nodebb.org/category/31/threadiverse-working-group",
|
||||||
|
"inbox": "https://community.nodebb.org/category/31/inbox",
|
||||||
|
"outbox": "https://community.nodebb.org/category/31/outbox",
|
||||||
|
"sharedInbox": "https://community.nodebb.org/inbox",
|
||||||
|
"type": "Group",
|
||||||
|
"name": "Threadiverse Working Group",
|
||||||
|
"preferredUsername": "swicg-threadiverse-wg",
|
||||||
|
"summary": "Discussion and announcements related to the SWICG Threadiverse task force",
|
||||||
|
"icon": {
|
||||||
|
"type": "Image",
|
||||||
|
"mediaType": "image/png",
|
||||||
|
"url": "https://community.nodebb.org/assets/uploads/system/site-logo.png"
|
||||||
|
},
|
||||||
|
"publicKey": {
|
||||||
|
"id": "https://community.nodebb.org/category/31#key",
|
||||||
|
"owner": "https://community.nodebb.org/category/31",
|
||||||
|
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0/Or3Ox2/jbhBZzF8W0Y\nWuS/4lgm5O5rxQk2nDRBXU/qNaZnMPkW2FxFPuPetndUVKSD2+vWF3SUlFyZ/vhT\nITzLkbRSILMiZCUg+0mvqi6va1WMBglMe5jLkc7wdfgNsosqBzKMdyMxqDZr++mJ\n8DjuqzWHENcjWcbMfSfAa9nkZHBIQUsHGGIwxEbKNlPqF0JIB66py7xmXbboDxpD\nPVF3EMkgZNnbmDGtlkZCKbztradyNRVl/u6KJpV3fbi+m/8CZ+POc4I5sKCQY1Hr\ndslHlm6tCkJQxIIKQtz0ZJ5yCUYmk48C2gFCndfJtYoEy9iR62xSemky6y04gWVc\naQIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
38
crates/apub/assets/nodebb/objects/page.json
Normal file
38
crates/apub/assets/nodebb/objects/page.json
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
"id": "https://community.nodebb.org/topic/17908",
|
||||||
|
"type": "Page",
|
||||||
|
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||||
|
"cc": ["https://community.nodebb.org/uid/2/followers"],
|
||||||
|
"inReplyTo": null,
|
||||||
|
"published": "2024-03-19T20:25:39.462Z",
|
||||||
|
"url": "https://community.nodebb.org/topic/17908/threadiverse-working-group",
|
||||||
|
"attributedTo": "https://community.nodebb.org/uid/2",
|
||||||
|
"audience": "https://community.nodebb.org/category/31/threadiverse-working-group",
|
||||||
|
"sensitive": false,
|
||||||
|
"summary": null,
|
||||||
|
"name": "Threadiverse Working Group",
|
||||||
|
"content": "<p dir=\"auto\">NodeBB is at this year's FediForum, and one of the breakout sessions centred around <strong>the Theadiverse</strong>, the subset of ActivityPub-enabled applications built around a topic-centric model of content representation.</p>\n<p dir=\"auto\">Some of the topic touched upon included:</p>\n<ul>\n<li>Aligning on a standard representation for collections of Notes</li>\n<li>FEP-1b12 — Group federation and implementation thereof by Lemmy, et al.</li>\n<li>Offering a comparatively more feature-rich experience vis-a-vis restrictions re: microblogging</li>\n<li>Going forward: collaborating on building compatible threadiverse implementations</li>\n</ul>\n<p dir=\"auto\">The main action item involved <strong>the genesis of an informal working group for the threadiverse</strong>, in order to align our disparate implementations toward a common path.</p>\n<p dir=\"auto\">We intend to meet monthly at first, with the first meeting likely sometime early-to-mid April.</p>\n<p dir=\"auto\">The topic of the first WG call is: <strong>Representation of the higherlevel collection of Notes (posts, etc.) — Article vs. Page, etc?</strong></p>\n<p dir=\"auto\">Interested?</p>\n<ul>\n<li>Publicly reply to this post (NodeBB does not support non-public posts at this time) if you'd like to join the list</li>\n<li>If you prefer to remain private, please email <a href=\"mailto:julian@nodebb.org\" rel=\"nofollow ugc\">julian@nodebb.org</a></li>\n</ul>\n<hr />\n<p dir=\"auto\">As an aside, I'd love to try something new and attempt tokeep as much of this as I can on the social web. Can you do me a favour and boost this to your followers?</p>\n",
|
||||||
|
"source": {
|
||||||
|
"content": "NodeBB is at this year's FediForum, and one of the breakout sessions centred around **the Theadiverse**, the subset of ActivityPub-enabled applications built around a topic-centric model of content representation.\n\nSome of the topic touched upon included:\n\n* Aligning on a standard representation for collections of Notes\n* FEP-1b12 — Group federation and implementation thereof by Lemmy, et al.\n* Offering a comparatively more feature-rich experience vis-a-vis restrictions re: microblogging\n* Going forward: collaborating on building compatible threadiverse implementations\n\nThe main action item involved **the genesis of an informal working group for the threadiverse**, in order to align our disparate implementations toward a common path.\n\nWe intend to meet monthly at first, with the first meeting likely sometime early-to-mid April.\n\nThe topic of the first WG call is: **Representation of the higher level collection of Notes (posts, etc.) — Article vs. Page, etc?**\n\nInterested?\n\n* Publicly reply to this post (NodeBB does not support non-public postsat this time) if you'd like to join the list\n* If you prefer to remain private, please email julian@nodebb.org\n\n----\n\nAs an aside, I'd love to try something new and attempt to keep as much of this as I can on the social web. Can you do me a favour and boost this to your followers?",
|
||||||
|
"mediaType": "text/markdown"
|
||||||
|
},
|
||||||
|
"tag": [
|
||||||
|
{
|
||||||
|
"type": "Hashtag",
|
||||||
|
"href": "https://community.nodebb.org/tags/fediforum",
|
||||||
|
"name": "#fediforum"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Hashtag",
|
||||||
|
"href": "https://community.nodebb.org/tags/activitypub",
|
||||||
|
"name": "#activitypub"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Hashtag",
|
||||||
|
"href": "https://community.nodebb.org/tags/threadiverse",
|
||||||
|
"name": "#threadiverse"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attachment": []
|
||||||
|
}
|
29
crates/apub/assets/nodebb/objects/person.json
Normal file
29
crates/apub/assets/nodebb/objects/person.json
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
"id": "https://community.nodebb.org/uid/2",
|
||||||
|
"url": "https://community.nodebb.org/user/julian",
|
||||||
|
"followers": "https://community.nodebb.org/uid/2/followers",
|
||||||
|
"following": "https://community.nodebb.org/uid/2/following",
|
||||||
|
"inbox": "https://community.nodebb.org/uid/2/inbox",
|
||||||
|
"outbox": "https://community.nodebb.org/uid/2/outbox",
|
||||||
|
"sharedInbox": "https://community.nodebb.org/inbox",
|
||||||
|
"type": "Person",
|
||||||
|
"name": "julian",
|
||||||
|
"preferredUsername": "julian",
|
||||||
|
"summary": "Hi! I'm Julian, one of the co-founders of NodeBB, the forum software you are using right now.\r\n\r\nI started this company with two colleagues, Baris and Andrew, in 2013, and have been doing the startup thing since (although I think at some point along the way we stopped being a startup and just became a boring ol' small business).\r\n\r\nIn my free time I rock climb, cycle, and lift weights. I live just outside Toronto, Canada, with my wife and three children.",
|
||||||
|
"icon": {
|
||||||
|
"type": "Image",
|
||||||
|
"mediaType": "image/jpeg",
|
||||||
|
"url": "https://community.nodebb.org/assets/uploads/profile/uid-2/2-profileavatar-1701457270279.jpeg"
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"type": "Image",
|
||||||
|
"mediaType": "image/jpeg",
|
||||||
|
"url": "https://community.nodebb.org/assets/uploads/profile/uid-2/2-profilecover-1649468285913.jpeg"
|
||||||
|
},
|
||||||
|
"publicKey": {
|
||||||
|
"id": "https://community.nodebb.org/uid/2#key",
|
||||||
|
"owner": "https://community.nodebb.org/uid/2",
|
||||||
|
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzEr0sFdATahQzprS4EOT\nZq+KMc6UTbt2GDP20OrQi/P5AXAbMaQiRCRdGWhYGjnH0jicn5NnozNxRo+HchJT\nV6NOHxpsxqPCoaLeoBkhfhbSCLr2Gzil6mmfqf9TjnI7A7ZTtCc0G+n0ztyL9HwL\nkEAI178l2gckk4XKKYnEd+dyiIevExrq/ROLgwW1o428FZvlF5amKxhpVUEygRU8\nCd1hqWYs+xYDOJURCP5qEx/MmRPpV/yGMTMyF+/gcQc0TUZnhWAM2E4M+aq3aKh6\nJP/vsry+5YZPUaPWfopbT5Ijyt6ZSElp6Avkg56eTz0a5SRcjCVS6IFVPwiLlzOe\nYwIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||||
|
}
|
||||||
|
}
|
|
@ -94,7 +94,12 @@ impl AnnounceActivity {
|
||||||
actor: community.id().into(),
|
actor: community.id().into(),
|
||||||
to: vec![public()],
|
to: vec![public()],
|
||||||
object: IdOrNestedObject::NestedObject(object),
|
object: IdOrNestedObject::NestedObject(object),
|
||||||
cc: vec![community.followers_url.clone().into()],
|
cc: community
|
||||||
|
.followers_url
|
||||||
|
.clone()
|
||||||
|
.map(Into::into)
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
kind: AnnounceType::Announce,
|
kind: AnnounceType::Announce,
|
||||||
id,
|
id,
|
||||||
})
|
})
|
||||||
|
|
|
@ -105,7 +105,7 @@ impl ActivityHandler for UpdateCommunity {
|
||||||
last_refreshed_at: Some(naive_now()),
|
last_refreshed_at: Some(naive_now()),
|
||||||
icon: Some(self.object.icon.map(|i| i.url.into())),
|
icon: Some(self.object.icon.map(|i| i.url.into())),
|
||||||
banner: Some(self.object.image.map(|i| i.url.into())),
|
banner: Some(self.object.image.map(|i| i.url.into())),
|
||||||
followers_url: Some(self.object.followers.into()),
|
followers_url: self.object.followers.map(Into::into),
|
||||||
inbox_url: Some(self.object.inbox.into()),
|
inbox_url: Some(self.object.inbox.into()),
|
||||||
shared_inbox_url: Some(self.object.endpoints.map(|e| e.shared_inbox.into())),
|
shared_inbox_url: Some(self.object.endpoints.map(|e| e.shared_inbox.into())),
|
||||||
moderators_url: self.object.attributed_to.map(Into::into),
|
moderators_url: self.object.attributed_to.map(Into::into),
|
||||||
|
|
|
@ -66,7 +66,6 @@ impl CreateOrUpdatePage {
|
||||||
kind: CreateOrUpdateType,
|
kind: CreateOrUpdateType,
|
||||||
context: Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
) -> LemmyResult<()> {
|
) -> LemmyResult<()> {
|
||||||
let post = ApubPost(post);
|
|
||||||
let community_id = post.community_id;
|
let community_id = post.community_id;
|
||||||
let person: ApubPerson = Person::read(&mut context.pool(), person_id)
|
let person: ApubPerson = Person::read(&mut context.pool(), person_id)
|
||||||
.await?
|
.await?
|
||||||
|
@ -78,7 +77,7 @@ impl CreateOrUpdatePage {
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let create_or_update =
|
let create_or_update =
|
||||||
CreateOrUpdatePage::new(post, &person, &community, kind, &context).await?;
|
CreateOrUpdatePage::new(post.into(), &person, &community, kind, &context).await?;
|
||||||
let is_mod_action = create_or_update.object.is_mod_action(&context).await?;
|
let is_mod_action = create_or_update.object.is_mod_action(&context).await?;
|
||||||
let activity = AnnouncableActivities::CreateOrUpdatePost(create_or_update);
|
let activity = AnnouncableActivities::CreateOrUpdatePost(create_or_update);
|
||||||
send_activity_in_community(
|
send_activity_in_community(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activity_lists::AnnouncableActivities,
|
activity_lists::AnnouncableActivities,
|
||||||
objects::{community::ApubCommunity, post::ApubPost},
|
objects::community::ApubCommunity,
|
||||||
protocol::{
|
protocol::{
|
||||||
activities::{
|
activities::{
|
||||||
community::announce::AnnounceActivity,
|
community::announce::AnnounceActivity,
|
||||||
|
@ -18,11 +18,8 @@ use activitypub_federation::{
|
||||||
};
|
};
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
use lemmy_api_common::{context::LemmyContext, utils::generate_outbox_url};
|
use lemmy_api_common::{context::LemmyContext, utils::generate_outbox_url};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{utils::FETCH_LIMIT_MAX, SortType};
|
||||||
source::{person::Person, post::Post},
|
use lemmy_db_views::{post_view::PostQuery, structs::SiteView};
|
||||||
traits::Crud,
|
|
||||||
utils::FETCH_LIMIT_MAX,
|
|
||||||
};
|
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
error::{LemmyError, LemmyResult},
|
error::{LemmyError, LemmyResult},
|
||||||
LemmyErrorType,
|
LemmyErrorType,
|
||||||
|
@ -41,19 +38,30 @@ impl Collection for ApubCommunityOutbox {
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
async fn read_local(owner: &Self::Owner, data: &Data<Self::DataType>) -> LemmyResult<Self::Kind> {
|
async fn read_local(owner: &Self::Owner, data: &Data<Self::DataType>) -> LemmyResult<Self::Kind> {
|
||||||
let post_list: Vec<ApubPost> = Post::list_for_community(&mut data.pool(), owner.id)
|
let site = SiteView::read_local(&mut data.pool())
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.ok_or(LemmyErrorType::LocalSiteNotSetup)?
|
||||||
.map(Into::into)
|
.site;
|
||||||
.collect();
|
|
||||||
|
let post_views = PostQuery {
|
||||||
|
community_id: Some(owner.id),
|
||||||
|
sort: Some(SortType::New),
|
||||||
|
limit: Some(FETCH_LIMIT_MAX),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.list(&site, &mut data.pool())
|
||||||
|
.await?;
|
||||||
|
|
||||||
let mut ordered_items = vec![];
|
let mut ordered_items = vec![];
|
||||||
for post in post_list {
|
for post_view in post_views {
|
||||||
let person = Person::read(&mut data.pool(), post.creator_id)
|
let create = CreateOrUpdatePage::new(
|
||||||
.await?
|
post_view.post.into(),
|
||||||
.ok_or(LemmyErrorType::CouldntFindPerson)?
|
&post_view.creator.into(),
|
||||||
.into();
|
owner,
|
||||||
let create =
|
CreateOrUpdateType::Create,
|
||||||
CreateOrUpdatePage::new(post, &person, owner, CreateOrUpdateType::Create, data).await?;
|
data,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
let announcable = AnnouncableActivities::CreateOrUpdatePost(create);
|
let announcable = AnnouncableActivities::CreateOrUpdatePost(create);
|
||||||
let announce = AnnounceActivity::new(announcable.try_into()?, owner, data)?;
|
let announce = AnnounceActivity::new(announcable.try_into()?, owner, data)?;
|
||||||
ordered_items.push(announce);
|
ordered_items.push(announce);
|
||||||
|
|
|
@ -128,7 +128,14 @@ pub(crate) mod tests {
|
||||||
use crate::protocol::objects::{group::Group, tombstone::Tombstone};
|
use crate::protocol::objects::{group::Group, tombstone::Tombstone};
|
||||||
use actix_web::body::to_bytes;
|
use actix_web::body::to_bytes;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{community::CommunityInsertForm, instance::Instance},
|
newtypes::InstanceId,
|
||||||
|
source::{
|
||||||
|
community::CommunityInsertForm,
|
||||||
|
instance::Instance,
|
||||||
|
local_site::{LocalSite, LocalSiteInsertForm},
|
||||||
|
local_site_rate_limit::{LocalSiteRateLimit, LocalSiteRateLimitInsertForm},
|
||||||
|
site::{Site, SiteInsertForm},
|
||||||
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
CommunityVisibility,
|
CommunityVisibility,
|
||||||
};
|
};
|
||||||
|
@ -142,6 +149,8 @@ pub(crate) mod tests {
|
||||||
) -> LemmyResult<(Instance, Community)> {
|
) -> LemmyResult<(Instance, Community)> {
|
||||||
let instance =
|
let instance =
|
||||||
Instance::read_or_create(&mut context.pool(), "my_domain.tld".to_string()).await?;
|
Instance::read_or_create(&mut context.pool(), "my_domain.tld".to_string()).await?;
|
||||||
|
create_local_site(context, instance.id).await?;
|
||||||
|
|
||||||
let community_form = CommunityInsertForm::builder()
|
let community_form = CommunityInsertForm::builder()
|
||||||
.name("testcom6".to_string())
|
.name("testcom6".to_string())
|
||||||
.title("nada".to_owned())
|
.title("nada".to_owned())
|
||||||
|
@ -154,6 +163,28 @@ pub(crate) mod tests {
|
||||||
Ok((instance, community))
|
Ok((instance, community))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Necessary for the community outbox fetching
|
||||||
|
async fn create_local_site(
|
||||||
|
context: &Data<LemmyContext>,
|
||||||
|
instance_id: InstanceId,
|
||||||
|
) -> LemmyResult<()> {
|
||||||
|
// Create a local site, since this is necessary for community fetching.
|
||||||
|
let site_form = SiteInsertForm::builder()
|
||||||
|
.name("test site".to_string())
|
||||||
|
.instance_id(instance_id)
|
||||||
|
.build();
|
||||||
|
let site = Site::create(&mut context.pool(), &site_form).await?;
|
||||||
|
|
||||||
|
let local_site_form = LocalSiteInsertForm::builder().site_id(site.id).build();
|
||||||
|
let local_site = LocalSite::create(&mut context.pool(), &local_site_form).await?;
|
||||||
|
let local_site_rate_limit_form = LocalSiteRateLimitInsertForm::builder()
|
||||||
|
.local_site_id(local_site.id)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
LocalSiteRateLimit::create(&mut context.pool(), &local_site_rate_limit_form).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn decode_response<T: DeserializeOwned>(res: HttpResponse) -> LemmyResult<T> {
|
async fn decode_response<T: DeserializeOwned>(res: HttpResponse) -> LemmyResult<T> {
|
||||||
let body = to_bytes(res.into_body()).await.unwrap();
|
let body = to_bytes(res.into_body()).await.unwrap();
|
||||||
let body = std::str::from_utf8(&body)?;
|
let body = std::str::from_utf8(&body)?;
|
||||||
|
@ -164,6 +195,7 @@ pub(crate) mod tests {
|
||||||
#[serial]
|
#[serial]
|
||||||
async fn test_get_community() -> LemmyResult<()> {
|
async fn test_get_community() -> LemmyResult<()> {
|
||||||
let context = LemmyContext::init_test_context().await;
|
let context = LemmyContext::init_test_context().await;
|
||||||
|
let (instance, community) = init(false, CommunityVisibility::Public, &context).await?;
|
||||||
|
|
||||||
// fetch invalid community
|
// fetch invalid community
|
||||||
let query = CommunityQuery {
|
let query = CommunityQuery {
|
||||||
|
@ -172,8 +204,6 @@ pub(crate) mod tests {
|
||||||
let res = get_apub_community_http(query.into(), context.reset_request_count()).await;
|
let res = get_apub_community_http(query.into(), context.reset_request_count()).await;
|
||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
|
|
||||||
let (instance, community) = init(false, CommunityVisibility::Public, &context).await?;
|
|
||||||
|
|
||||||
// fetch valid community
|
// fetch valid community
|
||||||
let query = CommunityQuery {
|
let query = CommunityQuery {
|
||||||
community_name: community.name.clone(),
|
community_name: community.name.clone(),
|
||||||
|
|
|
@ -113,7 +113,7 @@ impl Object for ApubCommunity {
|
||||||
featured: Some(generate_featured_url(&self.actor_id)?.into()),
|
featured: Some(generate_featured_url(&self.actor_id)?.into()),
|
||||||
inbox: self.inbox_url.clone().into(),
|
inbox: self.inbox_url.clone().into(),
|
||||||
outbox: generate_outbox_url(&self.actor_id)?.into(),
|
outbox: generate_outbox_url(&self.actor_id)?.into(),
|
||||||
followers: self.followers_url.clone().into(),
|
followers: self.followers_url.clone().map(Into::into),
|
||||||
endpoints: self.shared_inbox_url.clone().map(|s| Endpoints {
|
endpoints: self.shared_inbox_url.clone().map(|s| Endpoints {
|
||||||
shared_inbox: s.into(),
|
shared_inbox: s.into(),
|
||||||
}),
|
}),
|
||||||
|
@ -164,7 +164,7 @@ impl Object for ApubCommunity {
|
||||||
last_refreshed_at: Some(naive_now()),
|
last_refreshed_at: Some(naive_now()),
|
||||||
icon,
|
icon,
|
||||||
banner,
|
banner,
|
||||||
followers_url: Some(group.followers.clone().into()),
|
followers_url: group.followers.clone().map(Into::into),
|
||||||
inbox_url: Some(group.inbox.into()),
|
inbox_url: Some(group.inbox.into()),
|
||||||
shared_inbox_url: group.endpoints.map(|e| e.shared_inbox.into()),
|
shared_inbox_url: group.endpoints.map(|e| e.shared_inbox.into()),
|
||||||
moderators_url: group.attributed_to.clone().map(Into::into),
|
moderators_url: group.attributed_to.clone().map(Into::into),
|
||||||
|
@ -187,11 +187,9 @@ impl Object for ApubCommunity {
|
||||||
let context_ = context.reset_request_count();
|
let context_ = context.reset_request_count();
|
||||||
spawn_try_task(async move {
|
spawn_try_task(async move {
|
||||||
group.outbox.dereference(&community_, &context_).await.ok();
|
group.outbox.dereference(&community_, &context_).await.ok();
|
||||||
group
|
if let Some(followers) = group.followers {
|
||||||
.followers
|
followers.dereference(&community_, &context_).await.ok();
|
||||||
.dereference(&community_, &context_)
|
}
|
||||||
.await
|
|
||||||
.ok();
|
|
||||||
if let Some(featured) = group.featured {
|
if let Some(featured) = group.featured {
|
||||||
featured.dereference(&community_, &context_).await.ok();
|
featured.dereference(&community_, &context_).await.ok();
|
||||||
}
|
}
|
||||||
|
@ -275,7 +273,9 @@ pub(crate) mod tests {
|
||||||
// change these links so they dont fetch over the network
|
// change these links so they dont fetch over the network
|
||||||
json.attributed_to = None;
|
json.attributed_to = None;
|
||||||
json.outbox = CollectionId::parse("https://enterprise.lemmy.ml/c/tenforward/not_outbox")?;
|
json.outbox = CollectionId::parse("https://enterprise.lemmy.ml/c/tenforward/not_outbox")?;
|
||||||
json.followers = CollectionId::parse("https://enterprise.lemmy.ml/c/tenforward/not_followers")?;
|
json.followers = Some(CollectionId::parse(
|
||||||
|
"https://enterprise.lemmy.ml/c/tenforward/not_followers",
|
||||||
|
)?);
|
||||||
|
|
||||||
let url = Url::parse("https://enterprise.lemmy.ml/c/tenforward")?;
|
let url = Url::parse("https://enterprise.lemmy.ml/c/tenforward")?;
|
||||||
ApubCommunity::verify(&json, &url, &context2).await?;
|
ApubCommunity::verify(&json, &url, &context2).await?;
|
||||||
|
|
|
@ -45,7 +45,7 @@ pub struct Group {
|
||||||
/// username, set at account creation and usually fixed after that
|
/// username, set at account creation and usually fixed after that
|
||||||
pub(crate) preferred_username: String,
|
pub(crate) preferred_username: String,
|
||||||
pub(crate) inbox: Url,
|
pub(crate) inbox: Url,
|
||||||
pub(crate) followers: CollectionId<ApubCommunityFollower>,
|
pub(crate) followers: Option<CollectionId<ApubCommunityFollower>>,
|
||||||
pub(crate) public_key: PublicKey,
|
pub(crate) public_key: PublicKey,
|
||||||
|
|
||||||
/// title
|
/// title
|
||||||
|
|
|
@ -190,4 +190,12 @@ mod tests {
|
||||||
test_json::<Person>("assets/mobilizon/objects/person.json")?;
|
test_json::<Person>("assets/mobilizon/objects/person.json")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_object_nodebb() -> LemmyResult<()> {
|
||||||
|
test_json::<Group>("assets/nodebb/objects/group.json")?;
|
||||||
|
test_json::<Page>("assets/nodebb/objects/page.json")?;
|
||||||
|
test_json::<Person>("assets/nodebb/objects/person.json")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,22 +84,6 @@ impl Post {
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_for_community(
|
|
||||||
pool: &mut DbPool<'_>,
|
|
||||||
the_community_id: CommunityId,
|
|
||||||
) -> Result<Vec<Self>, Error> {
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
post::table
|
|
||||||
.filter(post::community_id.eq(the_community_id))
|
|
||||||
.filter(post::deleted.eq(false))
|
|
||||||
.filter(post::removed.eq(false))
|
|
||||||
.then_order_by(post::featured_community.desc())
|
|
||||||
.then_order_by(post::published.desc())
|
|
||||||
.limit(FETCH_LIMIT_MAX)
|
|
||||||
.load::<Self>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn list_featured_for_community(
|
pub async fn list_featured_for_community(
|
||||||
pool: &mut DbPool<'_>,
|
pool: &mut DbPool<'_>,
|
||||||
the_community_id: CommunityId,
|
the_community_id: CommunityId,
|
||||||
|
|
|
@ -178,7 +178,7 @@ diesel::table! {
|
||||||
icon -> Nullable<Text>,
|
icon -> Nullable<Text>,
|
||||||
banner -> Nullable<Text>,
|
banner -> Nullable<Text>,
|
||||||
#[max_length = 255]
|
#[max_length = 255]
|
||||||
followers_url -> Varchar,
|
followers_url -> Nullable<Varchar>,
|
||||||
#[max_length = 255]
|
#[max_length = 255]
|
||||||
inbox_url -> Varchar,
|
inbox_url -> Varchar,
|
||||||
#[max_length = 255]
|
#[max_length = 255]
|
||||||
|
|
|
@ -49,8 +49,8 @@ pub struct Community {
|
||||||
/// A URL for a banner.
|
/// A URL for a banner.
|
||||||
pub banner: Option<DbUrl>,
|
pub banner: Option<DbUrl>,
|
||||||
#[cfg_attr(feature = "full", ts(skip))]
|
#[cfg_attr(feature = "full", ts(skip))]
|
||||||
#[serde(skip, default = "placeholder_apub_url")]
|
#[serde(skip)]
|
||||||
pub followers_url: DbUrl,
|
pub followers_url: Option<DbUrl>,
|
||||||
#[cfg_attr(feature = "full", ts(skip))]
|
#[cfg_attr(feature = "full", ts(skip))]
|
||||||
#[serde(skip, default = "placeholder_apub_url")]
|
#[serde(skip, default = "placeholder_apub_url")]
|
||||||
pub inbox_url: DbUrl,
|
pub inbox_url: DbUrl,
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE community
|
||||||
|
ALTER COLUMN followers_url SET NOT NULL;
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE community
|
||||||
|
ALTER COLUMN followers_url DROP NOT NULL;
|
||||||
|
|
Loading…
Reference in a new issue