Merge remote-tracking branch 'yerba/main' into main
This commit is contained in:
commit
76193d37da
11 changed files with 207 additions and 129 deletions
|
@ -8,7 +8,10 @@ import {
|
||||||
createCommunity,
|
createCommunity,
|
||||||
deleteCommunity,
|
deleteCommunity,
|
||||||
removeCommunity,
|
removeCommunity,
|
||||||
|
getCommunity,
|
||||||
|
followCommunity,
|
||||||
delay,
|
delay,
|
||||||
|
longDelay,
|
||||||
} from './shared';
|
} from './shared';
|
||||||
import {
|
import {
|
||||||
Community,
|
Community,
|
||||||
|
@ -55,6 +58,21 @@ test('Create community', async () => {
|
||||||
test('Delete community', async () => {
|
test('Delete community', async () => {
|
||||||
let communityRes = await createCommunity(beta);
|
let communityRes = await createCommunity(beta);
|
||||||
await delay();
|
await delay();
|
||||||
|
|
||||||
|
// Cache the community on Alpha
|
||||||
|
let searchShort = `!${communityRes.community.name}@lemmy-beta:8551`;
|
||||||
|
let search = await searchForCommunity(alpha, searchShort);
|
||||||
|
let communityOnAlpha = search.communities[0];
|
||||||
|
assertCommunityFederation(communityOnAlpha, communityRes.community);
|
||||||
|
await delay();
|
||||||
|
|
||||||
|
// Follow the community from alpha
|
||||||
|
let follow = await followCommunity(alpha, true, communityOnAlpha.id);
|
||||||
|
|
||||||
|
// Make sure the follow response went through
|
||||||
|
expect(follow.community.local).toBe(false);
|
||||||
|
await delay();
|
||||||
|
|
||||||
let deleteCommunityRes = await deleteCommunity(
|
let deleteCommunityRes = await deleteCommunity(
|
||||||
beta,
|
beta,
|
||||||
true,
|
true,
|
||||||
|
@ -64,11 +82,9 @@ test('Delete community', async () => {
|
||||||
await delay();
|
await delay();
|
||||||
|
|
||||||
// Make sure it got deleted on A
|
// Make sure it got deleted on A
|
||||||
let search = await searchForBetaCommunity(alpha);
|
let communityOnAlphaDeleted = await getCommunity(alpha, communityOnAlpha.id);
|
||||||
let communityA = search.communities[0];
|
expect(communityOnAlphaDeleted.community.deleted).toBe(true);
|
||||||
// TODO this fails currently, because no updates are pushed
|
await delay();
|
||||||
// expect(communityA.deleted).toBe(true);
|
|
||||||
// assertCommunityFederation(communityA, communityRes.community);
|
|
||||||
|
|
||||||
// Undelete
|
// Undelete
|
||||||
let undeleteCommunityRes = await deleteCommunity(
|
let undeleteCommunityRes = await deleteCommunity(
|
||||||
|
@ -80,29 +96,39 @@ test('Delete community', async () => {
|
||||||
await delay();
|
await delay();
|
||||||
|
|
||||||
// Make sure it got undeleted on A
|
// Make sure it got undeleted on A
|
||||||
let search2 = await searchForBetaCommunity(alpha);
|
let communityOnAlphaUnDeleted = await getCommunity(alpha, communityOnAlpha.id);
|
||||||
let communityA2 = search2.communities[0];
|
expect(communityOnAlphaUnDeleted.community.deleted).toBe(false);
|
||||||
// TODO this fails currently, because no updates are pushed
|
|
||||||
// expect(communityA2.deleted).toBe(false);
|
|
||||||
// assertCommunityFederation(communityA2, undeleteCommunityRes.community);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Remove community', async () => {
|
test('Remove community', async () => {
|
||||||
let communityRes = await createCommunity(beta);
|
let communityRes = await createCommunity(beta);
|
||||||
await delay();
|
await delay();
|
||||||
|
|
||||||
|
// Cache the community on Alpha
|
||||||
|
let searchShort = `!${communityRes.community.name}@lemmy-beta:8551`;
|
||||||
|
let search = await searchForCommunity(alpha, searchShort);
|
||||||
|
let communityOnAlpha = search.communities[0];
|
||||||
|
assertCommunityFederation(communityOnAlpha, communityRes.community);
|
||||||
|
await delay();
|
||||||
|
|
||||||
|
// Follow the community from alpha
|
||||||
|
let follow = await followCommunity(alpha, true, communityOnAlpha.id);
|
||||||
|
|
||||||
|
// Make sure the follow response went through
|
||||||
|
expect(follow.community.local).toBe(false);
|
||||||
|
await delay();
|
||||||
|
|
||||||
let removeCommunityRes = await removeCommunity(
|
let removeCommunityRes = await removeCommunity(
|
||||||
beta,
|
beta,
|
||||||
true,
|
true,
|
||||||
communityRes.community.id
|
communityRes.community.id
|
||||||
);
|
);
|
||||||
expect(removeCommunityRes.community.removed).toBe(true);
|
expect(removeCommunityRes.community.removed).toBe(true);
|
||||||
|
await delay();
|
||||||
|
|
||||||
// Make sure it got removed on A
|
// Make sure it got Removed on A
|
||||||
let search = await searchForBetaCommunity(alpha);
|
let communityOnAlphaRemoved = await getCommunity(alpha, communityOnAlpha.id);
|
||||||
let communityA = search.communities[0];
|
expect(communityOnAlphaRemoved.community.removed).toBe(true);
|
||||||
// TODO this fails currently, because no updates are pushed
|
|
||||||
// expect(communityA.removed).toBe(true);
|
|
||||||
// assertCommunityFederation(communityA, communityRes.community);
|
|
||||||
await delay();
|
await delay();
|
||||||
|
|
||||||
// unremove
|
// unremove
|
||||||
|
@ -114,15 +140,18 @@ test('Remove community', async () => {
|
||||||
expect(unremoveCommunityRes.community.removed).toBe(false);
|
expect(unremoveCommunityRes.community.removed).toBe(false);
|
||||||
await delay();
|
await delay();
|
||||||
|
|
||||||
// Make sure it got unremoved on A
|
// Make sure it got undeleted on A
|
||||||
let search2 = await searchForBetaCommunity(alpha);
|
let communityOnAlphaUnRemoved = await getCommunity(alpha, communityOnAlpha.id);
|
||||||
let communityA2 = search2.communities[0];
|
expect(communityOnAlphaUnRemoved.community.removed).toBe(false);
|
||||||
// TODO this fails currently, because no updates are pushed
|
|
||||||
// expect(communityA2.removed).toBe(false);
|
|
||||||
// assertCommunityFederation(communityA2, unremoveCommunityRes.community);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Search for beta community', async () => {
|
test('Search for beta community', async () => {
|
||||||
let search = await searchForBetaCommunity(alpha);
|
let communityRes = await createCommunity(beta);
|
||||||
expect(search.communities[0].name).toBe('main');
|
expect(communityRes.community.name).toBeDefined();
|
||||||
|
await delay();
|
||||||
|
|
||||||
|
let searchShort = `!${communityRes.community.name}@lemmy-beta:8551`;
|
||||||
|
let search = await searchForCommunity(alpha, searchShort);
|
||||||
|
let communityOnAlpha = search.communities[0];
|
||||||
|
assertCommunityFederation(communityOnAlpha, communityRes.community);
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
RemoveCommentForm,
|
RemoveCommentForm,
|
||||||
SearchForm,
|
SearchForm,
|
||||||
CommentResponse,
|
CommentResponse,
|
||||||
|
GetCommunityForm,
|
||||||
CommunityForm,
|
CommunityForm,
|
||||||
DeleteCommunityForm,
|
DeleteCommunityForm,
|
||||||
RemoveCommunityForm,
|
RemoveCommunityForm,
|
||||||
|
@ -402,6 +403,16 @@ export async function createCommunity(
|
||||||
return api.client.createCommunity(form);
|
return api.client.createCommunity(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getCommunity(
|
||||||
|
api: API,
|
||||||
|
id: number,
|
||||||
|
): Promise<CommunityResponse> {
|
||||||
|
let form: GetCommunityForm = {
|
||||||
|
id,
|
||||||
|
};
|
||||||
|
return api.client.getCommunity(form);
|
||||||
|
}
|
||||||
|
|
||||||
export async function deleteCommunity(
|
export async function deleteCommunity(
|
||||||
api: API,
|
api: API,
|
||||||
deleted: boolean,
|
deleted: boolean,
|
||||||
|
|
|
@ -8,4 +8,14 @@ for Item in alpha beta gamma delta epsilon ; do
|
||||||
sudo chown -R 991:991 volumes/pictrs_$Item
|
sudo chown -R 991:991 volumes/pictrs_$Item
|
||||||
done
|
done
|
||||||
|
|
||||||
sudo docker-compose up
|
sudo docker-compose up -d
|
||||||
|
|
||||||
|
echo "Waiting for Lemmy to start..."
|
||||||
|
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8541/api/v1/site')" != "200" ]]; do sleep 1; done
|
||||||
|
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8551/api/v1/site')" != "200" ]]; do sleep 1; done
|
||||||
|
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8561/api/v1/site')" != "200" ]]; do sleep 1; done
|
||||||
|
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8571/api/v1/site')" != "200" ]]; do sleep 1; done
|
||||||
|
while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8581/api/v1/site')" != "200" ]]; do sleep 1; done
|
||||||
|
echo "All instances started."
|
||||||
|
|
||||||
|
sudo docker-compose logs -f
|
||||||
|
|
|
@ -559,6 +559,56 @@ Sent to: User
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `object` | yes | Any `Create`, `Update`, `Like`, `Dislike`, `Delete` `Remove` or `Undo` activity as described above |
|
| `object` | yes | Any `Create`, `Update`, `Like`, `Dislike`, `Delete` `Remove` or `Undo` activity as described above |
|
||||||
|
|
||||||
|
### Remove or Delete Community
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
"id": "http://ds9.lemmy.ml/activities/remove/e4ca7688-af9d-48b7-864f-765e7f9f3591",
|
||||||
|
"type": "Remove",
|
||||||
|
"actor": "http://ds9.lemmy.ml/c/some_community",
|
||||||
|
"cc": [
|
||||||
|
"http://ds9.lemmy.ml/c/some_community/followers"
|
||||||
|
],
|
||||||
|
"to": "https://www.w3.org/ns/activitystreams#Public",
|
||||||
|
"object": "http://ds9.lemmy.ml/c/some_community"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Field Name | Mandatory | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `type` | yes | Either `Remove` or `Delete` |
|
||||||
|
|
||||||
|
### Restore Removed or Deleted Community
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
"id": "http://ds9.lemmy.ml/activities/like/0703668c-8b09-4a85-aa7a-f93621936901",
|
||||||
|
"type": "Undo",
|
||||||
|
"actor": "http://ds9.lemmy.ml/c/some_community",
|
||||||
|
"to": "https://www.w3.org/ns/activitystreams#Public",
|
||||||
|
"cc": [
|
||||||
|
"http://ds9.lemmy.ml/c/testcom/followers"
|
||||||
|
],
|
||||||
|
"object": {
|
||||||
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
"id": "http://ds9.lemmy.ml/activities/remove/1062b5e0-07e8-44fc-868c-854209935bdd",
|
||||||
|
"type": "Remove",
|
||||||
|
"actor": "http://ds9.lemmy.ml/c/some_community",
|
||||||
|
"object": "http://ds9.lemmy.ml/c/testcom",
|
||||||
|
"to": "https://www.w3.org/ns/activitystreams#Public",
|
||||||
|
"cc": [
|
||||||
|
"http://ds9.lemmy.ml/c/testcom/followers"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
| Field Name | Mandatory | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `object.type` | yes | Either `Remove` or `Delete` |
|
||||||
|
|
||||||
### Create or Update Private message
|
### Create or Update Private message
|
||||||
|
|
||||||
Creates a new private message between two users.
|
Creates a new private message between two users.
|
||||||
|
|
|
@ -327,9 +327,9 @@ impl Perform for DeleteCommunity {
|
||||||
|
|
||||||
// Send apub messages
|
// Send apub messages
|
||||||
if deleted {
|
if deleted {
|
||||||
updated_community.send_delete(&user, context).await?;
|
updated_community.send_delete(context).await?;
|
||||||
} else {
|
} else {
|
||||||
updated_community.send_undo_delete(&user, context).await?;
|
updated_community.send_undo_delete(context).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let edit_id = data.edit_id;
|
let edit_id = data.edit_id;
|
||||||
|
@ -395,9 +395,9 @@ impl Perform for RemoveCommunity {
|
||||||
|
|
||||||
// Apub messages
|
// Apub messages
|
||||||
if removed {
|
if removed {
|
||||||
updated_community.send_remove(&user, context).await?;
|
updated_community.send_remove(context).await?;
|
||||||
} else {
|
} else {
|
||||||
updated_community.send_undo_remove(&user, context).await?;
|
updated_community.send_undo_remove(context).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let edit_id = data.edit_id;
|
let edit_id = data.edit_id;
|
||||||
|
|
|
@ -38,7 +38,7 @@ use lemmy_db::{
|
||||||
ListingType,
|
ListingType,
|
||||||
SortType,
|
SortType,
|
||||||
};
|
};
|
||||||
use lemmy_structs::{blocking, user::*};
|
use lemmy_structs::{blocking, send_email_to_user, user::*};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
apub::{generate_actor_keypair, make_apub_endpoint, EndpointType},
|
apub::{generate_actor_keypair, make_apub_endpoint, EndpointType},
|
||||||
email::send_email,
|
email::send_email,
|
||||||
|
@ -61,7 +61,6 @@ use lemmy_websocket::{
|
||||||
LemmyContext,
|
LemmyContext,
|
||||||
UserOperation,
|
UserOperation,
|
||||||
};
|
};
|
||||||
use log::error;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
|
@ -1041,23 +1040,12 @@ impl Perform for CreatePrivateMessage {
|
||||||
let recipient_user =
|
let recipient_user =
|
||||||
blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
|
blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
|
||||||
if recipient_user.send_notifications_to_email {
|
if recipient_user.send_notifications_to_email {
|
||||||
if let Some(email) = recipient_user.email {
|
send_email_to_user(
|
||||||
let subject = &format!(
|
recipient_user,
|
||||||
"{} - Private Message from {}",
|
"Private Message from",
|
||||||
Settings::get().hostname,
|
"Private Message",
|
||||||
user.name,
|
|
||||||
);
|
|
||||||
let html = &format!(
|
|
||||||
"<h1>Private Message</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
|
||||||
user.name,
|
|
||||||
&content_slurs_removed,
|
&content_slurs_removed,
|
||||||
Settings::get().get_protocol_and_hostname()
|
|
||||||
);
|
);
|
||||||
match send_email(subject, &email, &recipient_user.name, html) {
|
|
||||||
Ok(_o) => _o,
|
|
||||||
Err(e) => error!("{}", e),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let message = blocking(context.pool(), move |conn| {
|
let message = blocking(context.pool(), move |conn| {
|
||||||
|
|
|
@ -4,7 +4,6 @@ use crate::{
|
||||||
check_is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
fetcher::get_or_fetch_and_upsert_user,
|
fetcher::get_or_fetch_and_upsert_user,
|
||||||
ActorType,
|
ActorType,
|
||||||
ToApub,
|
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::{
|
activity::{
|
||||||
|
@ -23,7 +22,7 @@ use activitystreams::{
|
||||||
};
|
};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lemmy_db::{community::Community, community_view::CommunityFollowerView, user::User_, DbPool};
|
use lemmy_db::{community::Community, community_view::CommunityFollowerView, DbPool};
|
||||||
use lemmy_structs::blocking;
|
use lemmy_structs::blocking;
|
||||||
use lemmy_utils::{location_info, settings::Settings, LemmyError};
|
use lemmy_utils::{location_info, settings::Settings, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -85,10 +84,8 @@ impl ActorType for Community {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the creator of a community deletes the community, send this to all followers.
|
/// If the creator of a community deletes the community, send this to all followers.
|
||||||
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_delete(&self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let group = self.to_apub(context.pool()).await?;
|
let mut delete = Delete::new(self.actor_id()?, self.actor_id()?);
|
||||||
|
|
||||||
let mut delete = Delete::new(creator.actor_id.to_owned(), group.into_any_base()?);
|
|
||||||
delete
|
delete
|
||||||
.set_context(activitystreams::context())
|
.set_context(activitystreams::context())
|
||||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
.set_id(generate_activity_id(DeleteType::Delete)?)
|
||||||
|
@ -100,21 +97,15 @@ impl ActorType for Community {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the creator of a community reverts the deletion of a community, send this to all followers.
|
/// If the creator of a community reverts the deletion of a community, send this to all followers.
|
||||||
async fn send_undo_delete(
|
async fn send_undo_delete(&self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
&self,
|
let mut delete = Delete::new(self.actor_id()?, self.actor_id()?);
|
||||||
creator: &User_,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
let group = self.to_apub(context.pool()).await?;
|
|
||||||
|
|
||||||
let mut delete = Delete::new(creator.actor_id.to_owned(), group.into_any_base()?);
|
|
||||||
delete
|
delete
|
||||||
.set_context(activitystreams::context())
|
.set_context(activitystreams::context())
|
||||||
.set_id(generate_activity_id(DeleteType::Delete)?)
|
.set_id(generate_activity_id(DeleteType::Delete)?)
|
||||||
.set_to(public())
|
.set_to(public())
|
||||||
.set_many_ccs(vec![self.get_followers_url()?]);
|
.set_many_ccs(vec![self.get_followers_url()?]);
|
||||||
|
|
||||||
let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?);
|
let mut undo = Undo::new(self.actor_id()?, delete.into_any_base()?);
|
||||||
undo
|
undo
|
||||||
.set_context(activitystreams::context())
|
.set_context(activitystreams::context())
|
||||||
.set_id(generate_activity_id(UndoType::Undo)?)
|
.set_id(generate_activity_id(UndoType::Undo)?)
|
||||||
|
@ -126,8 +117,8 @@ impl ActorType for Community {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If an admin removes a community, send this to all followers.
|
/// If an admin removes a community, send this to all followers.
|
||||||
async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let mut remove = Remove::new(mod_.actor_id.to_owned(), self.actor_id()?);
|
let mut remove = Remove::new(self.actor_id()?, self.actor_id()?);
|
||||||
remove
|
remove
|
||||||
.set_context(activitystreams::context())
|
.set_context(activitystreams::context())
|
||||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
.set_id(generate_activity_id(RemoveType::Remove)?)
|
||||||
|
@ -139,8 +130,8 @@ impl ActorType for Community {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If an admin reverts the removal of a community, send this to all followers.
|
/// If an admin reverts the removal of a community, send this to all followers.
|
||||||
async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_undo_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let mut remove = Remove::new(mod_.actor_id.to_owned(), self.actor_id()?);
|
let mut remove = Remove::new(self.actor_id()?, self.actor_id()?);
|
||||||
remove
|
remove
|
||||||
.set_context(activitystreams::context())
|
.set_context(activitystreams::context())
|
||||||
.set_id(generate_activity_id(RemoveType::Remove)?)
|
.set_id(generate_activity_id(RemoveType::Remove)?)
|
||||||
|
@ -148,7 +139,7 @@ impl ActorType for Community {
|
||||||
.set_many_ccs(vec![self.get_followers_url()?]);
|
.set_many_ccs(vec![self.get_followers_url()?]);
|
||||||
|
|
||||||
// Undo that fake activity
|
// Undo that fake activity
|
||||||
let mut undo = Undo::new(mod_.actor_id.to_owned(), remove.into_any_base()?);
|
let mut undo = Undo::new(self.actor_id()?, remove.into_any_base()?);
|
||||||
undo
|
undo
|
||||||
.set_context(activitystreams::context())
|
.set_context(activitystreams::context())
|
||||||
.set_id(generate_activity_id(LikeType::Like)?)
|
.set_id(generate_activity_id(LikeType::Like)?)
|
||||||
|
|
|
@ -94,27 +94,19 @@ impl ActorType for User_ {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_delete(&self, _creator: &User_, _context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_delete(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_undo_delete(
|
async fn send_undo_delete(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
&self,
|
|
||||||
_creator: &User_,
|
|
||||||
_context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_remove(&self, _creator: &User_, _context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_remove(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_undo_remove(
|
async fn send_undo_remove(&self, _context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
&self,
|
|
||||||
_creator: &User_,
|
|
||||||
_context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -251,10 +251,14 @@ pub(crate) async fn get_or_fetch_and_upsert_user(
|
||||||
Ok(u) if !u.local && should_refetch_actor(u.last_refreshed_at) => {
|
Ok(u) if !u.local && should_refetch_actor(u.last_refreshed_at) => {
|
||||||
debug!("Fetching and updating from remote user: {}", apub_id);
|
debug!("Fetching and updating from remote user: {}", apub_id);
|
||||||
let person =
|
let person =
|
||||||
fetch_remote_object::<PersonExt>(context.client(), apub_id, recursion_counter).await?;
|
fetch_remote_object::<PersonExt>(context.client(), apub_id, recursion_counter).await;
|
||||||
|
// If fetching failed, return the existing data.
|
||||||
|
if person.is_err() {
|
||||||
|
return Ok(u);
|
||||||
|
}
|
||||||
|
|
||||||
let mut uf = UserForm::from_apub(
|
let mut uf = UserForm::from_apub(
|
||||||
&person,
|
&person?,
|
||||||
context,
|
context,
|
||||||
Some(apub_id.to_owned()),
|
Some(apub_id.to_owned()),
|
||||||
recursion_counter,
|
recursion_counter,
|
||||||
|
@ -320,7 +324,7 @@ pub(crate) async fn get_or_fetch_and_upsert_community(
|
||||||
match community {
|
match community {
|
||||||
Ok(c) if !c.local && should_refetch_actor(c.last_refreshed_at) => {
|
Ok(c) if !c.local && should_refetch_actor(c.last_refreshed_at) => {
|
||||||
debug!("Fetching and updating from remote community: {}", apub_id);
|
debug!("Fetching and updating from remote community: {}", apub_id);
|
||||||
fetch_remote_community(apub_id, context, Some(c.id), recursion_counter).await
|
fetch_remote_community(apub_id, context, Some(c), recursion_counter).await
|
||||||
}
|
}
|
||||||
Ok(c) => Ok(c),
|
Ok(c) => Ok(c),
|
||||||
Err(NotFound {}) => {
|
Err(NotFound {}) => {
|
||||||
|
@ -331,17 +335,24 @@ pub(crate) async fn get_or_fetch_and_upsert_community(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Request a community by apub ID from a remote instance, including moderators. If `community_id`,
|
/// Request a community by apub ID from a remote instance, including moderators. If `old_community`,
|
||||||
/// is set, this is an update for a community which is already known locally. If not, we don't know
|
/// is set, this is an update for a community which is already known locally. If not, we don't know
|
||||||
/// the community yet and also pull the outbox, to get some initial posts.
|
/// the community yet and also pull the outbox, to get some initial posts.
|
||||||
async fn fetch_remote_community(
|
async fn fetch_remote_community(
|
||||||
apub_id: &Url,
|
apub_id: &Url,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
community_id: Option<i32>,
|
old_community: Option<Community>,
|
||||||
recursion_counter: &mut i32,
|
recursion_counter: &mut i32,
|
||||||
) -> Result<Community, LemmyError> {
|
) -> Result<Community, LemmyError> {
|
||||||
let group = fetch_remote_object::<GroupExt>(context.client(), apub_id, recursion_counter).await?;
|
let group = fetch_remote_object::<GroupExt>(context.client(), apub_id, recursion_counter).await;
|
||||||
|
// If fetching failed, return the existing data.
|
||||||
|
if let Some(ref c) = old_community {
|
||||||
|
if group.is_err() {
|
||||||
|
return Ok(c.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let group = group?;
|
||||||
let cf =
|
let cf =
|
||||||
CommunityForm::from_apub(&group, context, Some(apub_id.to_owned()), recursion_counter).await?;
|
CommunityForm::from_apub(&group, context, Some(apub_id.to_owned()), recursion_counter).await?;
|
||||||
let community = blocking(context.pool(), move |conn| Community::upsert(conn, &cf)).await??;
|
let community = blocking(context.pool(), move |conn| Community::upsert(conn, &cf)).await??;
|
||||||
|
@ -364,7 +375,7 @@ async fn fetch_remote_community(
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: need to make this work to update mods of existing communities
|
// TODO: need to make this work to update mods of existing communities
|
||||||
if community_id.is_none() {
|
if old_community.is_none() {
|
||||||
let community_id = community.id;
|
let community_id = community.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
for mod_ in creator_and_moderators {
|
for mod_ in creator_and_moderators {
|
||||||
|
|
|
@ -189,15 +189,11 @@ pub trait ActorType {
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError>;
|
) -> Result<(), LemmyError>;
|
||||||
|
|
||||||
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
|
async fn send_delete(&self, context: &LemmyContext) -> Result<(), LemmyError>;
|
||||||
async fn send_undo_delete(
|
async fn send_undo_delete(&self, context: &LemmyContext) -> Result<(), LemmyError>;
|
||||||
&self,
|
|
||||||
creator: &User_,
|
|
||||||
context: &LemmyContext,
|
|
||||||
) -> Result<(), LemmyError>;
|
|
||||||
|
|
||||||
async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
|
async fn send_remove(&self, context: &LemmyContext) -> Result<(), LemmyError>;
|
||||||
async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
|
async fn send_undo_remove(&self, context: &LemmyContext) -> Result<(), LemmyError>;
|
||||||
|
|
||||||
async fn send_announce(
|
async fn send_announce(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -77,7 +77,6 @@ fn do_send_local_notifs(
|
||||||
do_send_email: bool,
|
do_send_email: bool,
|
||||||
) -> Vec<i32> {
|
) -> Vec<i32> {
|
||||||
let mut recipient_ids = Vec::new();
|
let mut recipient_ids = Vec::new();
|
||||||
let hostname = &Settings::get().get_protocol_and_hostname();
|
|
||||||
|
|
||||||
// Send the local mentions
|
// Send the local mentions
|
||||||
for mention in mentions
|
for mention in mentions
|
||||||
|
@ -106,17 +105,12 @@ fn do_send_local_notifs(
|
||||||
|
|
||||||
// Send an email to those users that have notifications on
|
// Send an email to those users that have notifications on
|
||||||
if do_send_email && mention_user.send_notifications_to_email {
|
if do_send_email && mention_user.send_notifications_to_email {
|
||||||
if let Some(mention_email) = mention_user.email {
|
send_email_to_user(
|
||||||
let subject = &format!("{} - Mentioned by {}", Settings::get().hostname, user.name,);
|
mention_user,
|
||||||
let html = &format!(
|
"Mentioned by",
|
||||||
"<h1>User Mention</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
"User Mention",
|
||||||
user.name, comment.content, hostname
|
&comment.content,
|
||||||
);
|
)
|
||||||
match send_email(subject, &mention_email, &mention_user.name, html) {
|
|
||||||
Ok(_o) => _o,
|
|
||||||
Err(e) => error!("{}", e),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,17 +124,7 @@ fn do_send_local_notifs(
|
||||||
recipient_ids.push(parent_user.id);
|
recipient_ids.push(parent_user.id);
|
||||||
|
|
||||||
if do_send_email && parent_user.send_notifications_to_email {
|
if do_send_email && parent_user.send_notifications_to_email {
|
||||||
if let Some(comment_reply_email) = parent_user.email {
|
send_email_to_user(parent_user, "Reply from", "Comment Reply", &comment.content)
|
||||||
let subject = &format!("{} - Reply from {}", Settings::get().hostname, user.name,);
|
|
||||||
let html = &format!(
|
|
||||||
"<h1>Comment Reply</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
|
||||||
user.name, comment.content, hostname
|
|
||||||
);
|
|
||||||
match send_email(subject, &comment_reply_email, &parent_user.name, html) {
|
|
||||||
Ok(_o) => _o,
|
|
||||||
Err(e) => error!("{}", e),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,17 +137,7 @@ fn do_send_local_notifs(
|
||||||
recipient_ids.push(parent_user.id);
|
recipient_ids.push(parent_user.id);
|
||||||
|
|
||||||
if do_send_email && parent_user.send_notifications_to_email {
|
if do_send_email && parent_user.send_notifications_to_email {
|
||||||
if let Some(post_reply_email) = parent_user.email {
|
send_email_to_user(parent_user, "Reply from", "Post Reply", &comment.content)
|
||||||
let subject = &format!("{} - Reply from {}", Settings::get().hostname, user.name,);
|
|
||||||
let html = &format!(
|
|
||||||
"<h1>Post Reply</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
|
||||||
user.name, comment.content, hostname
|
|
||||||
);
|
|
||||||
match send_email(subject, &post_reply_email, &parent_user.name, html) {
|
|
||||||
Ok(_o) => _o,
|
|
||||||
Err(e) => error!("{}", e),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,3 +145,29 @@ fn do_send_local_notifs(
|
||||||
};
|
};
|
||||||
recipient_ids
|
recipient_ids
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn send_email_to_user(user: User_, subject_text: &str, body_text: &str, comment_content: &str) {
|
||||||
|
if user.banned {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(user_email) = user.email {
|
||||||
|
let subject = &format!(
|
||||||
|
"{} - {} {}",
|
||||||
|
subject_text,
|
||||||
|
Settings::get().hostname,
|
||||||
|
user.name,
|
||||||
|
);
|
||||||
|
let html = &format!(
|
||||||
|
"<h1>{}</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
||||||
|
body_text,
|
||||||
|
user.name,
|
||||||
|
comment_content,
|
||||||
|
Settings::get().get_protocol_and_hostname()
|
||||||
|
);
|
||||||
|
match send_email(subject, &user_email, &user.name, html) {
|
||||||
|
Ok(_o) => _o,
|
||||||
|
Err(e) => error!("{}", e),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue