2024-01-25 14:24:09 +00:00
|
|
|
use crate::{community::BanFromCommunity, context::LemmyContext, post::DeletePost};
|
2023-07-19 13:49:41 +00:00
|
|
|
use activitypub_federation::config::Data;
|
|
|
|
use futures::future::BoxFuture;
|
2023-08-01 13:53:36 +00:00
|
|
|
use lemmy_db_schema::{
|
2023-08-02 16:52:41 +00:00
|
|
|
newtypes::{CommunityId, DbUrl, PersonId},
|
|
|
|
source::{
|
|
|
|
comment::Comment,
|
|
|
|
community::Community,
|
|
|
|
person::Person,
|
|
|
|
post::Post,
|
|
|
|
private_message::PrivateMessage,
|
|
|
|
},
|
2023-08-01 13:53:36 +00:00
|
|
|
};
|
2023-08-02 16:52:41 +00:00
|
|
|
use lemmy_db_views::structs::PrivateMessageView;
|
2023-09-20 14:18:31 +00:00
|
|
|
use lemmy_utils::error::LemmyResult;
|
2023-09-18 14:25:35 +00:00
|
|
|
use once_cell::sync::{Lazy, OnceCell};
|
|
|
|
use tokio::{
|
|
|
|
sync::{
|
|
|
|
mpsc,
|
|
|
|
mpsc::{UnboundedReceiver, UnboundedSender, WeakUnboundedSender},
|
|
|
|
Mutex,
|
|
|
|
},
|
|
|
|
task::JoinHandle,
|
|
|
|
};
|
2023-08-02 16:52:41 +00:00
|
|
|
use url::Url;
|
2023-07-19 13:49:41 +00:00
|
|
|
|
|
|
|
type MatchOutgoingActivitiesBoxed =
|
|
|
|
Box<for<'a> fn(SendActivityData, &'a Data<LemmyContext>) -> BoxFuture<'a, LemmyResult<()>>>;
|
|
|
|
|
2023-09-20 14:18:31 +00:00
|
|
|
/// This static is necessary so that the api_common crates don't need to depend on lemmy_apub
|
2023-07-19 13:49:41 +00:00
|
|
|
pub static MATCH_OUTGOING_ACTIVITIES: OnceCell<MatchOutgoingActivitiesBoxed> = OnceCell::new();
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum SendActivityData {
|
|
|
|
CreatePost(Post),
|
2023-08-01 13:53:36 +00:00
|
|
|
UpdatePost(Post),
|
2023-08-02 16:52:41 +00:00
|
|
|
DeletePost(Post, Person, DeletePost),
|
2024-01-25 14:24:09 +00:00
|
|
|
RemovePost {
|
|
|
|
post: Post,
|
|
|
|
moderator: Person,
|
|
|
|
reason: Option<String>,
|
|
|
|
removed: bool,
|
|
|
|
},
|
2023-08-02 16:52:41 +00:00
|
|
|
LockPost(Post, Person, bool),
|
|
|
|
FeaturePost(Post, Person, bool),
|
2023-07-28 14:39:38 +00:00
|
|
|
CreateComment(Comment),
|
2023-08-02 16:52:41 +00:00
|
|
|
UpdateComment(Comment),
|
2023-08-01 13:53:36 +00:00
|
|
|
DeleteComment(Comment, Person, Community),
|
2024-01-25 14:24:09 +00:00
|
|
|
RemoveComment {
|
|
|
|
comment: Comment,
|
|
|
|
moderator: Person,
|
|
|
|
community: Community,
|
|
|
|
reason: Option<String>,
|
|
|
|
},
|
|
|
|
LikePostOrComment {
|
|
|
|
object_id: DbUrl,
|
|
|
|
actor: Person,
|
|
|
|
community: Community,
|
|
|
|
score: i16,
|
|
|
|
},
|
2023-08-02 09:32:16 +00:00
|
|
|
FollowCommunity(Community, Person, bool),
|
2023-08-02 16:52:41 +00:00
|
|
|
UpdateCommunity(Person, Community),
|
|
|
|
DeleteCommunity(Person, Community, bool),
|
2024-01-25 14:24:09 +00:00
|
|
|
RemoveCommunity {
|
|
|
|
moderator: Person,
|
|
|
|
community: Community,
|
|
|
|
reason: Option<String>,
|
|
|
|
removed: bool,
|
|
|
|
},
|
|
|
|
AddModToCommunity {
|
|
|
|
moderator: Person,
|
|
|
|
community_id: CommunityId,
|
|
|
|
target: PersonId,
|
|
|
|
added: bool,
|
|
|
|
},
|
|
|
|
BanFromCommunity {
|
|
|
|
moderator: Person,
|
|
|
|
community_id: CommunityId,
|
|
|
|
target: Person,
|
|
|
|
data: BanFromCommunity,
|
|
|
|
},
|
|
|
|
BanFromSite {
|
|
|
|
moderator: Person,
|
|
|
|
banned_user: Person,
|
|
|
|
reason: Option<String>,
|
|
|
|
remove_data: Option<bool>,
|
|
|
|
ban: bool,
|
|
|
|
expires: Option<i64>,
|
|
|
|
},
|
2023-08-02 16:52:41 +00:00
|
|
|
CreatePrivateMessage(PrivateMessageView),
|
|
|
|
UpdatePrivateMessage(PrivateMessageView),
|
|
|
|
DeletePrivateMessage(Person, PrivateMessage, bool),
|
2023-08-28 10:23:45 +00:00
|
|
|
DeleteUser(Person, bool),
|
2024-01-25 14:24:09 +00:00
|
|
|
CreateReport {
|
|
|
|
object_id: Url,
|
|
|
|
actor: Person,
|
|
|
|
community: Community,
|
|
|
|
reason: String,
|
|
|
|
},
|
2023-07-19 13:49:41 +00:00
|
|
|
}
|
|
|
|
|
2023-09-18 14:25:35 +00:00
|
|
|
// TODO: instead of static, move this into LemmyContext. make sure that stopping the process with
|
|
|
|
// ctrl+c still works.
|
|
|
|
static ACTIVITY_CHANNEL: Lazy<ActivityChannel> = Lazy::new(|| {
|
|
|
|
let (sender, receiver) = mpsc::unbounded_channel();
|
|
|
|
let weak_sender = sender.downgrade();
|
|
|
|
ActivityChannel {
|
|
|
|
weak_sender,
|
|
|
|
receiver: Mutex::new(receiver),
|
|
|
|
keepalive_sender: Mutex::new(Some(sender)),
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
pub struct ActivityChannel {
|
|
|
|
weak_sender: WeakUnboundedSender<SendActivityData>,
|
|
|
|
receiver: Mutex<UnboundedReceiver<SendActivityData>>,
|
|
|
|
keepalive_sender: Mutex<Option<UnboundedSender<SendActivityData>>>,
|
|
|
|
}
|
2023-07-19 13:49:41 +00:00
|
|
|
|
|
|
|
impl ActivityChannel {
|
2023-09-18 14:25:35 +00:00
|
|
|
pub async fn retrieve_activity() -> Option<SendActivityData> {
|
|
|
|
let mut lock = ACTIVITY_CHANNEL.receiver.lock().await;
|
|
|
|
lock.recv().await
|
|
|
|
}
|
|
|
|
|
2023-07-19 13:49:41 +00:00
|
|
|
pub async fn submit_activity(
|
|
|
|
data: SendActivityData,
|
2023-09-20 14:18:31 +00:00
|
|
|
_context: &Data<LemmyContext>,
|
2023-07-19 13:49:41 +00:00
|
|
|
) -> LemmyResult<()> {
|
2023-09-18 14:25:35 +00:00
|
|
|
// could do `ACTIVITY_CHANNEL.keepalive_sender.lock()` instead and get rid of weak_sender,
|
|
|
|
// not sure which way is more efficient
|
2023-09-20 14:18:31 +00:00
|
|
|
if let Some(sender) = ACTIVITY_CHANNEL.weak_sender.upgrade() {
|
2023-09-18 14:25:35 +00:00
|
|
|
sender.send(data)?;
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-12-18 18:17:10 +00:00
|
|
|
pub async fn close(outgoing_activities_task: JoinHandle<()>) -> LemmyResult<()> {
|
2023-09-18 14:25:35 +00:00
|
|
|
ACTIVITY_CHANNEL.keepalive_sender.lock().await.take();
|
2023-12-18 18:17:10 +00:00
|
|
|
outgoing_activities_task.await?;
|
2023-09-18 14:25:35 +00:00
|
|
|
Ok(())
|
2023-07-19 13:49:41 +00:00
|
|
|
}
|
|
|
|
}
|