"url",
]
-[[package]]
-name = "actix"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f728064aca1c318585bf4bb04ffcfac9e75e508ab4e8b1bd9ba5dfe04e2cbed5"
-dependencies = [
- "actix-rt",
- "actix_derive",
- "bitflags",
- "bytes",
- "crossbeam-channel",
- "futures-core",
- "futures-sink",
- "futures-task",
- "futures-util",
- "log",
- "once_cell",
- "parking_lot 0.12.1",
- "pin-project-lite",
- "smallvec",
- "tokio",
- "tokio-util 0.7.4",
-]
-
[[package]]
name = "actix-codec"
version = "0.5.0"
"syn 1.0.103",
]
-[[package]]
-name = "actix_derive"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d44b8fee1ced9671ba043476deddef739dd0959bf77030b26b738cc591737a7"
-dependencies = [
- "proc-macro2 1.0.47",
- "quote 1.0.21",
- "syn 1.0.103",
-]
-
[[package]]
name = "addr2line"
version = "0.19.0"
"base64",
"bcrypt",
"captcha",
- "chrono",
"lemmy_api_common",
"lemmy_db_schema",
"lemmy_db_views",
name = "lemmy_api_common"
version = "0.17.1"
dependencies = [
- "actix",
"actix-rt",
+ "actix-web",
"anyhow",
"chrono",
"encoding",
"lemmy_db_views_moderator",
"lemmy_utils",
"percent-encoding",
- "rand 0.8.5",
"regex",
"reqwest",
"reqwest-middleware",
"rosetta-i18n",
"serde",
- "serde_json",
"serde_with",
- "strum",
- "strum_macros",
"tracing",
"ts-rs",
"url",
version = "0.17.1"
dependencies = [
"activitypub_federation",
- "actix",
"actix-rt",
"actix-web",
"anyhow",
version = "0.17.1"
dependencies = [
"activitypub_federation",
- "actix",
"actix-cors",
"actix-web",
"clokwerk",
rand = "0.8.5"
opentelemetry = { version = "0.17.0", features = ["rt-tokio"] }
tracing-opentelemetry = { version = "0.17.2" }
-actix = "0.13"
ts-rs = { version = "6.2", features = ["serde-compat", "format", "chrono-impl"] }
[dependencies]
clokwerk = { workspace = true }
doku = { workspace = true }
serde_json = { workspace = true }
-actix = { workspace = true }
tracing-opentelemetry = { workspace = true, optional = true }
opentelemetry = { workspace = true, optional = true }
console-subscriber = { version = "0.1.8", optional = true }
lemmy_db_views_actor = { workspace = true, features = ["full"] }
lemmy_api_common = { workspace = true, features = ["full"] }
bcrypt = { workspace = true }
-chrono = { workspace = true }
serde = { workspace = true }
actix-web = { workspace = true }
base64 = { workspace = true }
traits::Crud,
};
use lemmy_db_views::structs::CommentView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for DistinguishComment {
type Response = CommentResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<CommentResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommentResponse, LemmyError> {
let data: &DistinguishComment = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_comment_response,
comment::{CommentResponse, CreateCommentLike},
context::LemmyContext,
utils::{check_community_ban, check_downvotes_enabled, local_user_view_from_jwt},
- websocket::UserOperation,
};
use lemmy_db_schema::{
newtypes::LocalUserId,
traits::Likeable,
};
use lemmy_db_views::structs::{CommentView, LocalUserView};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for CreateCommentLike {
type Response = CommentResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<CommentResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommentResponse, LemmyError> {
let data: &CreateCommentLike = self;
let local_site = LocalSite::read(context.pool()).await?;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
.map_err(|e| LemmyError::from_error_message(e, "couldnt_like_comment"))?;
}
- context
- .send_comment_ws_message(
- &UserOperation::CreateCommentLike,
- data.comment_id,
- websocket_id,
- None,
- Some(local_user_view.person.id),
- recipient_ids,
- )
- .await
+ build_comment_response(
+ context,
+ comment_id,
+ Some(local_user_view),
+ None,
+ recipient_ids,
+ )
+ .await
}
}
traits::Saveable,
};
use lemmy_db_views::structs::CommentView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for SaveComment {
type Response = CommentResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<CommentResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommentResponse, LemmyError> {
let data: &SaveComment = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
comment::{CommentReportResponse, CreateCommentReport},
context::LemmyContext,
utils::{check_community_ban, local_user_view_from_jwt, send_new_report_email_to_admins},
- websocket::UserOperation,
};
use lemmy_db_schema::{
source::{
traits::Reportable,
};
use lemmy_db_views::structs::{CommentReportView, CommentView};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
/// Creates a comment report and notifies the moderators of the community
#[async_trait::async_trait(?Send)]
impl Perform for CreateCommentReport {
type Response = CommentReportResponse;
- #[tracing::instrument(skip(context, websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
) -> Result<CommentReportResponse, LemmyError> {
let data: &CreateCommentReport = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
.await?;
}
- let res = CommentReportResponse {
+ Ok(CommentReportResponse {
comment_report_view,
- };
-
- context.send_mod_ws_message(
- &UserOperation::CreateCommentReport,
- &res,
- comment_view.community.id,
- websocket_id,
- )?;
-
- Ok(res)
+ })
}
}
utils::local_user_view_from_jwt,
};
use lemmy_db_views::comment_report_view::CommentReportQuery;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
/// Lists comment reports for a community if an id is supplied
/// or returns all comment reports for communities a user moderates
impl Perform for ListCommentReports {
type Response = ListCommentReportsResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<ListCommentReportsResponse, LemmyError> {
let data: &ListCommentReports = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
.list()
.await?;
- let res = ListCommentReportsResponse { comment_reports };
-
- Ok(res)
+ Ok(ListCommentReportsResponse { comment_reports })
}
}
comment::{CommentReportResponse, ResolveCommentReport},
context::LemmyContext,
utils::{is_mod_or_admin, local_user_view_from_jwt},
- websocket::UserOperation,
};
use lemmy_db_schema::{source::comment_report::CommentReport, traits::Reportable};
use lemmy_db_views::structs::CommentReportView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
/// Resolves or unresolves a comment report and notifies the moderators of the community
#[async_trait::async_trait(?Send)]
impl Perform for ResolveCommentReport {
type Response = CommentReportResponse;
- #[tracing::instrument(skip(context, websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
) -> Result<CommentReportResponse, LemmyError> {
let data: &ResolveCommentReport = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let report_id = data.report_id;
let comment_report_view = CommentReportView::read(context.pool(), report_id, person_id).await?;
- let res = CommentReportResponse {
+ Ok(CommentReportResponse {
comment_report_view,
- };
-
- context.send_mod_ws_message(
- &UserOperation::ResolveCommentReport,
- &res,
- report.community.id,
- websocket_id,
- )?;
-
- Ok(res)
+ })
}
}
community::{AddModToCommunity, AddModToCommunityResponse},
context::LemmyContext,
utils::{is_mod_or_admin, local_user_view_from_jwt},
- websocket::UserOperation,
};
use lemmy_db_schema::{
source::{
traits::{Crud, Joinable},
};
use lemmy_db_views_actor::structs::CommunityModeratorView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for AddModToCommunity {
type Response = AddModToCommunityResponse;
- #[tracing::instrument(skip(context, websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
) -> Result<AddModToCommunityResponse, LemmyError> {
let data: &AddModToCommunity = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let community_id = data.community_id;
let moderators = CommunityModeratorView::for_community(context.pool(), community_id).await?;
- let res = AddModToCommunityResponse { moderators };
- context.send_mod_ws_message(
- &UserOperation::AddModToCommunity,
- &res,
- community_id,
- websocket_id,
- )?;
-
- Ok(res)
+ Ok(AddModToCommunityResponse { moderators })
}
}
community::{BanFromCommunity, BanFromCommunityResponse},
context::LemmyContext,
utils::{is_mod_or_admin, local_user_view_from_jwt, remove_user_data_in_community},
- websocket::{
- handlers::messages::SendCommunityRoomMessage,
- serialize_websocket_message,
- UserOperation,
- },
};
use lemmy_db_schema::{
source::{
use lemmy_utils::{
error::LemmyError,
utils::{time::naive_from_unix, validation::is_valid_body_field},
- ConnectionId,
};
#[async_trait::async_trait(?Send)]
impl Perform for BanFromCommunity {
type Response = BanFromCommunityResponse;
- #[tracing::instrument(skip(context, websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
) -> Result<BanFromCommunityResponse, LemmyError> {
let data: &BanFromCommunity = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let person_id = data.person_id;
let person_view = PersonView::read(context.pool(), person_id).await?;
- let res = BanFromCommunityResponse {
+ Ok(BanFromCommunityResponse {
person_view,
banned: data.ban,
- };
-
- // A custom ban message
- let message = serialize_websocket_message(&UserOperation::BanFromCommunity, &res)?;
- context.chat_server().do_send(SendCommunityRoomMessage {
- community_id,
- message,
- websocket_id,
- });
-
- Ok(res)
+ })
}
}
traits::{Blockable, Followable},
};
use lemmy_db_views_actor::structs::CommunityView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for BlockCommunity {
type Response = BlockCommunityResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<BlockCommunityResponse, LemmyError> {
let data: &BlockCommunity = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
traits::{Crud, Followable},
};
use lemmy_db_views_actor::structs::CommunityView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for FollowCommunity {
type Response = CommunityResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<CommunityResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommunityResponse, LemmyError> {
let data: &FollowCommunity = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_community_response,
community::{CommunityResponse, HideCommunity},
context::LemmyContext,
utils::{is_admin, local_user_view_from_jwt},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::{
},
traits::Crud,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for HideCommunity {
type Response = CommunityResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<CommunityResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommunityResponse, LemmyError> {
let data: &HideCommunity = self;
// Verify its a admin (only admin can hide or unhide it)
ModHideCommunity::create(context.pool(), &mod_hide_community_form).await?;
- context
- .send_community_ws_message(
- &UserOperationCrud::EditCommunity,
- data.community_id,
- websocket_id,
- None,
- )
- .await
+ build_community_response(context, local_user_view, community_id).await
}
}
traits::{Crud, Joinable},
};
use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
-use lemmy_utils::{error::LemmyError, location_info, ConnectionId};
+use lemmy_utils::{error::LemmyError, location_info};
// TODO: we dont do anything for federation here, it should be updated the next time the community
// gets fetched. i hope we can get rid of the community creator role soon.
impl Perform for TransferCommunity {
type Response = GetCommunityResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<GetCommunityResponse, LemmyError> {
let data: &TransferCommunity = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
community_view,
site: None,
moderators,
- online: 0,
discussion_languages: vec![],
})
}
use actix_web::web::Data;
-use captcha::Captcha;
use lemmy_api_common::{context::LemmyContext, utils::local_site_to_slur_regex};
use lemmy_db_schema::source::local_site::LocalSite;
-use lemmy_utils::{error::LemmyError, utils::slurs::check_slurs, ConnectionId};
+use lemmy_utils::{error::LemmyError, utils::slurs::check_slurs};
mod comment;
mod comment_report;
mod private_message;
mod private_message_report;
mod site;
-mod websocket;
#[async_trait::async_trait(?Send)]
pub trait Perform {
type Response: serde::ser::Serialize + Send;
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError>;
-}
-
-/// Converts the captcha to a base64 encoded wav audio file
-pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> String {
- let letters = captcha.as_wav();
-
- let mut concat_letters: Vec<u8> = Vec::new();
-
- for letter in letters {
- let bytes = letter.unwrap_or_default();
- concat_letters.extend(bytes);
- }
-
- // Convert to base64
- base64::encode(concat_letters)
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError>;
}
/// Check size of report and remove whitespace
context::LemmyContext,
person::{AddAdmin, AddAdminResponse},
utils::{is_admin, local_user_view_from_jwt},
- websocket::UserOperation,
};
use lemmy_db_schema::{
source::{
traits::Crud,
};
use lemmy_db_views_actor::structs::PersonView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for AddAdmin {
type Response = AddAdminResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<AddAdminResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<AddAdminResponse, LemmyError> {
let data: &AddAdmin = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let admins = PersonView::admins(context.pool()).await?;
- let res = AddAdminResponse { admins };
-
- context.send_all_ws_message(&UserOperation::AddAdmin, &res, websocket_id)?;
-
- Ok(res)
+ Ok(AddAdminResponse { admins })
}
}
context::LemmyContext,
person::{BanPerson, BanPersonResponse},
utils::{is_admin, local_user_view_from_jwt, remove_user_data},
- websocket::UserOperation,
};
use lemmy_db_schema::{
source::{
use lemmy_utils::{
error::LemmyError,
utils::{time::naive_from_unix, validation::is_valid_body_field},
- ConnectionId,
};
#[async_trait::async_trait(?Send)]
impl Perform for BanPerson {
type Response = BanPersonResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<BanPersonResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<BanPersonResponse, LemmyError> {
let data: &BanPerson = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let person_id = data.person_id;
let person_view = PersonView::read(context.pool(), person_id).await?;
- let res = BanPersonResponse {
+ Ok(BanPersonResponse {
person_view,
banned: data.ban,
- };
-
- context.send_all_ws_message(&UserOperation::BanPerson, &res, websocket_id)?;
-
- Ok(res)
+ })
}
}
traits::Blockable,
};
use lemmy_db_views_actor::structs::PersonView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for BlockPerson {
type Response = BlockPersonResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<BlockPersonResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<BlockPersonResponse, LemmyError> {
let data: &BlockPerson = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
.map_err(|e| LemmyError::from_error_message(e, "person_block_already_exists"))?;
}
- let res = BlockPersonResponse {
+ Ok(BlockPersonResponse {
person_view: target_person_view,
blocked: data.block,
- };
-
- Ok(res)
+ })
}
}
utils::{local_user_view_from_jwt, password_length_check},
};
use lemmy_db_schema::source::local_user::LocalUser;
-use lemmy_utils::{claims::Claims, error::LemmyError, ConnectionId};
+use lemmy_utils::{claims::Claims, error::LemmyError};
#[async_trait::async_trait(?Send)]
impl Perform for ChangePassword {
type Response = LoginResponse;
- #[tracing::instrument(skip(self, context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<LoginResponse, LemmyError> {
+ #[tracing::instrument(skip(self, context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<LoginResponse, LemmyError> {
let data: &ChangePassword = self;
let local_user_view = local_user_view_from_jwt(data.auth.as_ref(), context).await?;
RegistrationMode,
};
use lemmy_db_views::structs::SiteView;
-use lemmy_utils::{claims::Claims, error::LemmyError, ConnectionId};
+use lemmy_utils::{claims::Claims, error::LemmyError};
#[async_trait::async_trait(?Send)]
impl Perform for PasswordChangeAfterReset {
type Response = LoginResponse;
- #[tracing::instrument(skip(self, context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<LoginResponse, LemmyError> {
+ #[tracing::instrument(skip(self, context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<LoginResponse, LemmyError> {
let data: &PasswordChangeAfterReset = self;
// Fetch the user_id from the token
+++ /dev/null
-use crate::{captcha_as_wav_base64, Perform};
-use actix_web::web::Data;
-use captcha::{gen, Difficulty};
-use chrono::Duration;
-use lemmy_api_common::{
- context::LemmyContext,
- person::{CaptchaResponse, GetCaptcha, GetCaptchaResponse},
- websocket::{handlers::captcha::AddCaptcha, structs::CaptchaItem},
-};
-use lemmy_db_schema::{source::local_site::LocalSite, utils::naive_now};
-use lemmy_utils::{error::LemmyError, ConnectionId};
-
-#[async_trait::async_trait(?Send)]
-impl Perform for GetCaptcha {
- type Response = GetCaptchaResponse;
-
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
- let local_site = LocalSite::read(context.pool()).await?;
-
- if !local_site.captcha_enabled {
- return Ok(GetCaptchaResponse { ok: None });
- }
-
- let captcha = gen(match local_site.captcha_difficulty.as_str() {
- "easy" => Difficulty::Easy,
- "hard" => Difficulty::Hard,
- _ => Difficulty::Medium,
- });
-
- let answer = captcha.chars_as_string();
-
- let png = captcha.as_base64().expect("failed to generate captcha");
-
- let uuid = uuid::Uuid::new_v4().to_string();
-
- let wav = captcha_as_wav_base64(&captcha);
-
- let captcha_item = CaptchaItem {
- answer,
- uuid: uuid.clone(),
- expires: naive_now() + Duration::minutes(10), // expires in 10 minutes
- };
-
- // Stores the captcha item on the queue
- context.chat_server().do_send(AddCaptcha {
- captcha: captcha_item,
- });
-
- Ok(GetCaptchaResponse {
- ok: Some(CaptchaResponse { png, wav, uuid }),
- })
- }
-}
utils::{is_admin, local_user_view_from_jwt},
};
use lemmy_db_views_actor::structs::PersonView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetBannedPersons {
type Response = BannedPersonsResponse;
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let data: &GetBannedPersons = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let banned = PersonView::banned(context.pool()).await?;
- let res = Self::Response { banned };
-
- Ok(res)
+ Ok(Self::Response { banned })
}
}
utils::{check_registration_application, check_user_valid},
};
use lemmy_db_views::structs::{LocalUserView, SiteView};
-use lemmy_utils::{
- claims::Claims,
- error::LemmyError,
- utils::validation::check_totp_2fa_valid,
- ConnectionId,
-};
+use lemmy_utils::{claims::Claims, error::LemmyError, utils::validation::check_totp_2fa_valid};
#[async_trait::async_trait(?Send)]
impl Perform for Login {
type Response = LoginResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<LoginResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<LoginResponse, LemmyError> {
let data: &Login = self;
let site_view = SiteView::read_local(context.pool()).await?;
mod block;
mod change_password;
mod change_password_after_reset;
-mod get_captcha;
mod list_banned;
mod login;
mod notifications;
utils::local_user_view_from_jwt,
};
use lemmy_db_views_actor::person_mention_view::PersonMentionQuery;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetPersonMentions {
type Response = GetPersonMentionsResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<GetPersonMentionsResponse, LemmyError> {
let data: &GetPersonMentions = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
utils::local_user_view_from_jwt,
};
use lemmy_db_views_actor::comment_reply_view::CommentReplyQuery;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetReplies {
type Response = GetRepliesResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<GetRepliesResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetRepliesResponse, LemmyError> {
let data: &GetReplies = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
person_mention::PersonMention,
private_message::PrivateMessage,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for MarkAllAsRead {
type Response = GetRepliesResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<GetRepliesResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetRepliesResponse, LemmyError> {
let data: &MarkAllAsRead = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let person_id = local_user_view.person.id;
traits::Crud,
};
use lemmy_db_views_actor::structs::PersonMentionView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for MarkPersonMentionAsRead {
type Response = PersonMentionResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<PersonMentionResponse, LemmyError> {
let data: &MarkPersonMentionAsRead = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
traits::Crud,
};
use lemmy_db_views_actor::structs::CommentReplyView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for MarkCommentReplyAsRead {
type Response = CommentReplyResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<CommentReplyResponse, LemmyError> {
let data = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
};
use lemmy_db_views::structs::PrivateMessageView;
use lemmy_db_views_actor::structs::{CommentReplyView, PersonMentionView};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetUnreadCount {
type Response = GetUnreadCountResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let data = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let private_messages =
PrivateMessageView::get_unread_messages(context.pool(), person_id).await?;
- let res = Self::Response {
+ Ok(Self::Response {
replies,
mentions,
private_messages,
- };
-
- Ok(res)
+ })
}
}
utils::local_user_view_from_jwt,
};
use lemmy_db_views::structs::{CommentReportView, PostReportView, PrivateMessageReportView};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetReportCount {
type Response = GetReportCountResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<GetReportCountResponse, LemmyError> {
let data: &GetReportCount = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
None
};
- let res = GetReportCountResponse {
+ Ok(GetReportCountResponse {
community_id,
comment_reports,
post_reports,
private_message_reports,
- };
-
- Ok(res)
+ })
}
}
utils::send_password_reset_email,
};
use lemmy_db_views::structs::LocalUserView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for PasswordReset {
type Response = PasswordResetResponse;
- #[tracing::instrument(skip(self, context, _websocket_id))]
+ #[tracing::instrument(skip(self, context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<PasswordResetResponse, LemmyError> {
let data: &PasswordReset = self;
is_valid_display_name,
is_valid_matrix_id,
},
- ConnectionId,
};
#[async_trait::async_trait(?Send)]
impl Perform for SaveUserSettings {
type Response = LoginResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<LoginResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<LoginResponse, LemmyError> {
let data: &SaveUserSettings = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let site_view = SiteView::read_local(context.pool()).await?;
impl Perform for VerifyEmail {
type Response = VerifyEmailResponse;
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<usize>,
- ) -> Result<Self::Response, LemmyError> {
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let token = self.token.clone();
let verification = EmailVerification::read_for_token(context.pool(), &token)
.await
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_post_response,
context::LemmyContext,
post::{FeaturePost, PostResponse},
utils::{
is_mod_or_admin,
local_user_view_from_jwt,
},
- websocket::UserOperation,
};
use lemmy_db_schema::{
source::{
traits::Crud,
PostFeatureType,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for FeaturePost {
type Response = PostResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<PostResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> {
let data: &FeaturePost = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
ModFeaturePost::create(context.pool(), &form).await?;
- context
- .send_post_ws_message(
- &UserOperation::FeaturePost,
- data.post_id,
- websocket_id,
- Some(local_user_view.person.id),
- )
- .await
+ build_post_response(
+ context,
+ orig_post.community_id,
+ local_user_view.person.id,
+ post_id,
+ )
+ .await
}
}
post::{GetSiteMetadata, GetSiteMetadataResponse},
request::fetch_site_metadata,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetSiteMetadata {
type Response = GetSiteMetadataResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<GetSiteMetadataResponse, LemmyError> {
let data: &Self = self;
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_post_response,
context::LemmyContext,
post::{CreatePostLike, PostResponse},
utils::{
local_user_view_from_jwt,
mark_post_as_read,
},
- websocket::UserOperation,
};
use lemmy_db_schema::{
source::{
},
traits::{Crud, Likeable},
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for CreatePostLike {
type Response = PostResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<PostResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> {
let data: &CreatePostLike = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let local_site = LocalSite::read(context.pool()).await?;
// Mark the post as read
mark_post_as_read(person_id, post_id, context.pool()).await?;
- context
- .send_post_ws_message(
- &UserOperation::CreatePostLike,
- data.post_id,
- websocket_id,
- Some(local_user_view.person.id),
- )
- .await
+ build_post_response(
+ context,
+ post.community_id,
+ local_user_view.person.id,
+ post_id,
+ )
+ .await
}
}
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_post_response,
context::LemmyContext,
post::{LockPost, PostResponse},
utils::{
is_mod_or_admin,
local_user_view_from_jwt,
},
- websocket::UserOperation,
};
use lemmy_db_schema::{
source::{
},
traits::Crud,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for LockPost {
type Response = PostResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<PostResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> {
let data: &LockPost = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
};
ModLockPost::create(context.pool(), &form).await?;
- context
- .send_post_ws_message(
- &UserOperation::LockPost,
- data.post_id,
- websocket_id,
- Some(local_user_view.person.id),
- )
- .await
+ build_post_response(
+ context,
+ orig_post.community_id,
+ local_user_view.person.id,
+ post_id,
+ )
+ .await
}
}
utils::{local_user_view_from_jwt, mark_post_as_read, mark_post_as_unread},
};
use lemmy_db_views::structs::PostView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for MarkPostAsRead {
type Response = PostResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let data = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
// Fetch it
let post_view = PostView::read(context.pool(), post_id, Some(person_id), None).await?;
- let res = Self::Response { post_view };
-
- Ok(res)
+ Ok(Self::Response { post_view })
}
}
traits::Saveable,
};
use lemmy_db_views::structs::PostView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for SavePost {
type Response = PostResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<PostResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> {
let data: &SavePost = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
context::LemmyContext,
post::{CreatePostReport, PostReportResponse},
utils::{check_community_ban, local_user_view_from_jwt, send_new_report_email_to_admins},
- websocket::UserOperation,
};
use lemmy_db_schema::{
source::{
traits::Reportable,
};
use lemmy_db_views::structs::{PostReportView, PostView};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
/// Creates a post report and notifies the moderators of the community
#[async_trait::async_trait(?Send)]
impl Perform for CreatePostReport {
type Response = PostReportResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<PostReportResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostReportResponse, LemmyError> {
let data: &CreatePostReport = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let local_site = LocalSite::read(context.pool()).await?;
.await?;
}
- let res = PostReportResponse { post_report_view };
-
- context.send_mod_ws_message(
- &UserOperation::CreatePostReport,
- &res,
- post_view.community.id,
- websocket_id,
- )?;
-
- Ok(res)
+ Ok(PostReportResponse { post_report_view })
}
}
utils::local_user_view_from_jwt,
};
use lemmy_db_views::post_report_view::PostReportQuery;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
/// Lists post reports for a community if an id is supplied
/// or returns all post reports for communities a user moderates
impl Perform for ListPostReports {
type Response = ListPostReportsResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<ListPostReportsResponse, LemmyError> {
let data: &ListPostReports = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
.list()
.await?;
- let res = ListPostReportsResponse { post_reports };
-
- Ok(res)
+ Ok(ListPostReportsResponse { post_reports })
}
}
context::LemmyContext,
post::{PostReportResponse, ResolvePostReport},
utils::{is_mod_or_admin, local_user_view_from_jwt},
- websocket::UserOperation,
};
use lemmy_db_schema::{source::post_report::PostReport, traits::Reportable};
use lemmy_db_views::structs::PostReportView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
/// Resolves or unresolves a post report and notifies the moderators of the community
#[async_trait::async_trait(?Send)]
impl Perform for ResolvePostReport {
type Response = PostReportResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<PostReportResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostReportResponse, LemmyError> {
let data: &ResolvePostReport = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let post_report_view = PostReportView::read(context.pool(), report_id, person_id).await?;
- let res = PostReportResponse { post_report_view };
-
- context.send_mod_ws_message(
- &UserOperation::ResolvePostReport,
- &res,
- report.community.id,
- websocket_id,
- )?;
-
- Ok(res)
+ Ok(PostReportResponse { post_report_view })
}
}
context::LemmyContext,
private_message::{MarkPrivateMessageAsRead, PrivateMessageResponse},
utils::local_user_view_from_jwt,
- websocket::UserOperation,
};
use lemmy_db_schema::{
source::private_message::{PrivateMessage, PrivateMessageUpdateForm},
traits::Crud,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_db_views::structs::PrivateMessageView;
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for MarkPrivateMessageAsRead {
type Response = PrivateMessageResponse;
- #[tracing::instrument(skip(context, websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
) -> Result<PrivateMessageResponse, LemmyError> {
let data: &MarkPrivateMessageAsRead = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_private_message"))?;
- // No need to send an apub update
- context
- .send_pm_ws_message(
- &UserOperation::MarkPrivateMessageAsRead,
- data.private_message_id,
- websocket_id,
- )
- .await
+ let view = PrivateMessageView::read(context.pool(), private_message_id).await?;
+ Ok(PrivateMessageResponse {
+ private_message_view: view,
+ })
}
}
context::LemmyContext,
private_message::{CreatePrivateMessageReport, PrivateMessageReportResponse},
utils::{local_user_view_from_jwt, send_new_report_email_to_admins},
- websocket::UserOperation,
};
use lemmy_db_schema::{
- newtypes::CommunityId,
source::{
local_site::LocalSite,
private_message::PrivateMessage,
traits::{Crud, Reportable},
};
use lemmy_db_views::structs::PrivateMessageReportView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for CreatePrivateMessageReport {
type Response = PrivateMessageReportResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let local_user_view = local_user_view_from_jwt(&self.auth, context).await?;
let local_site = LocalSite::read(context.pool()).await?;
.await?;
}
- let res = PrivateMessageReportResponse {
- private_message_report_view,
- };
-
- context.send_mod_ws_message(
- &UserOperation::CreatePrivateMessageReport,
- &res,
- CommunityId(0),
- websocket_id,
- )?;
-
// TODO: consider federating this
- Ok(res)
+ Ok(PrivateMessageReportResponse {
+ private_message_report_view,
+ })
}
}
utils::{is_admin, local_user_view_from_jwt},
};
use lemmy_db_views::private_message_report_view::PrivateMessageReportQuery;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for ListPrivateMessageReports {
type Response = ListPrivateMessageReportsResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let local_user_view = local_user_view_from_jwt(&self.auth, context).await?;
is_admin(&local_user_view)?;
.list()
.await?;
- let res = ListPrivateMessageReportsResponse {
+ Ok(ListPrivateMessageReportsResponse {
private_message_reports,
- };
-
- Ok(res)
+ })
}
}
context::LemmyContext,
private_message::{PrivateMessageReportResponse, ResolvePrivateMessageReport},
utils::{is_admin, local_user_view_from_jwt},
- websocket::UserOperation,
-};
-use lemmy_db_schema::{
- newtypes::CommunityId,
- source::private_message_report::PrivateMessageReport,
- traits::Reportable,
};
+use lemmy_db_schema::{source::private_message_report::PrivateMessageReport, traits::Reportable};
use lemmy_db_views::structs::PrivateMessageReportView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for ResolvePrivateMessageReport {
type Response = PrivateMessageReportResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let local_user_view = local_user_view_from_jwt(&self.auth, context).await?;
is_admin(&local_user_view)?;
let private_message_report_view =
PrivateMessageReportView::read(context.pool(), report_id).await?;
- let res = PrivateMessageReportResponse {
+ Ok(PrivateMessageReportResponse {
private_message_report_view,
- };
-
- context.send_mod_ws_message(
- &UserOperation::ResolvePrivateMessageReport,
- &res,
- CommunityId(0),
- websocket_id,
- )?;
-
- Ok(res)
+ })
}
}
utils::build_federated_instances,
};
use lemmy_db_views::structs::SiteView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetFederatedInstances {
type Response = GetFederatedInstancesResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let site_view = SiteView::read_local(context.pool()).await?;
let federated_instances =
build_federated_instances(&site_view.local_site, context.pool()).await?;
};
use lemmy_db_views::structs::{CustomEmojiView, SiteView};
use lemmy_db_views_actor::structs::PersonView;
-use lemmy_utils::{error::LemmyError, version, ConnectionId};
+use lemmy_utils::{error::LemmyError, version};
#[async_trait::async_trait(?Send)]
impl Perform for LeaveAdmin {
type Response = GetSiteResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<GetSiteResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetSiteResponse, LemmyError> {
let data: &LeaveAdmin = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
Ok(GetSiteResponse {
site_view,
admins,
- online: 0,
version: version::VERSION.to_string(),
my_user: None,
all_languages,
ModTransferCommunityView,
ModlogListParams,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
use ModlogActionType::*;
#[async_trait::async_trait(?Send)]
impl Perform for GetModlog {
type Response = GetModlogResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<GetModlogResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetModlogResponse, LemmyError> {
let data: &GetModlog = self;
let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), context).await;
},
traits::Crud,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for PurgeComment {
type Response = PurgeItemResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let data: &Self = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
},
traits::Crud,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for PurgeCommunity {
type Response = PurgeItemResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let data: &Self = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
},
traits::Crud,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for PurgePerson {
type Response = PurgeItemResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let data: &Self = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
},
traits::Crud,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for PurgePost {
type Response = PurgeItemResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let data: &Self = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
utils::diesel_option_overwrite,
};
use lemmy_db_views::structs::{LocalUserView, RegistrationApplicationView};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for ApproveRegistrationApplication {
type Response = RegistrationApplicationResponse;
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let data = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
};
use lemmy_db_schema::source::local_site::LocalSite;
use lemmy_db_views::registration_application_view::RegistrationApplicationQuery;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
/// Lists registration applications, filterable by undenied only.
#[async_trait::async_trait(?Send)]
impl Perform for ListRegistrationApplications {
type Response = ListRegistrationApplicationsResponse;
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let data = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let local_site = LocalSite::read(context.pool()).await?;
.list()
.await?;
- let res = Self::Response {
+ Ok(Self::Response {
registration_applications,
- };
-
- Ok(res)
+ })
}
}
};
use lemmy_db_schema::source::local_site::LocalSite;
use lemmy_db_views::structs::RegistrationApplicationView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl Perform for GetUnreadRegistrationApplicationCount {
type Response = GetUnreadRegistrationApplicationCountResponse;
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let data = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let local_site = LocalSite::read(context.pool()).await?;
+++ /dev/null
-use crate::Perform;
-use actix_web::web::Data;
-use lemmy_api_common::{
- context::LemmyContext,
- utils::local_user_view_from_jwt,
- websocket::{
- handlers::join_rooms::{JoinCommunityRoom, JoinModRoom, JoinPostRoom, JoinUserRoom},
- structs::{
- CommunityJoin,
- CommunityJoinResponse,
- ModJoin,
- ModJoinResponse,
- PostJoin,
- PostJoinResponse,
- UserJoin,
- UserJoinResponse,
- },
- },
-};
-use lemmy_utils::{error::LemmyError, ConnectionId};
-
-#[async_trait::async_trait(?Send)]
-impl Perform for UserJoin {
- type Response = UserJoinResponse;
-
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<UserJoinResponse, LemmyError> {
- let data: &UserJoin = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
-
- if let Some(id) = websocket_id {
- context.chat_server().do_send(JoinUserRoom {
- user_id: local_user_view.local_user.id,
- id,
- });
- }
-
- Ok(UserJoinResponse { joined: true })
- }
-}
-
-#[async_trait::async_trait(?Send)]
-impl Perform for CommunityJoin {
- type Response = CommunityJoinResponse;
-
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<CommunityJoinResponse, LemmyError> {
- let data: &CommunityJoin = self;
-
- if let Some(id) = websocket_id {
- context.chat_server().do_send(JoinCommunityRoom {
- community_id: data.community_id,
- id,
- });
- }
-
- Ok(CommunityJoinResponse { joined: true })
- }
-}
-
-#[async_trait::async_trait(?Send)]
-impl Perform for ModJoin {
- type Response = ModJoinResponse;
-
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<ModJoinResponse, LemmyError> {
- let data: &ModJoin = self;
-
- if let Some(id) = websocket_id {
- context.chat_server().do_send(JoinModRoom {
- community_id: data.community_id,
- id,
- });
- }
-
- Ok(ModJoinResponse { joined: true })
- }
-}
-
-#[async_trait::async_trait(?Send)]
-impl Perform for PostJoin {
- type Response = PostJoinResponse;
-
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<PostJoinResponse, LemmyError> {
- let data: &PostJoin = self;
-
- if let Some(id) = websocket_id {
- context.chat_server().do_send(JoinPostRoom {
- post_id: data.post_id,
- id,
- });
- }
-
- Ok(PostJoinResponse { joined: true })
- }
-}
percent-encoding = { workspace = true, optional = true }
webpage = { version = "1.4.0", default-features = false, features = ["serde"], optional = true }
encoding = { version = "0.2.33", optional = true }
-rand = { workspace = true }
-serde_json = { workspace = true }
anyhow = { workspace = true }
-strum = { workspace = true }
-strum_macros = { workspace = true }
-actix = { workspace = true }
futures = { workspace = true }
uuid = { workspace = true }
actix-rt = { workspace = true }
reqwest = { workspace = true }
ts-rs = { workspace = true, optional = true }
+actix-web = { workspace = true }
--- /dev/null
+use crate::{
+ comment::CommentResponse,
+ community::CommunityResponse,
+ context::LemmyContext,
+ post::PostResponse,
+ utils::{check_person_block, get_interface_language, is_mod_or_admin, send_email_to_user},
+};
+use actix_web::web::Data;
+use lemmy_db_schema::{
+ newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId},
+ source::{
+ actor_language::CommunityLanguage,
+ comment::Comment,
+ comment_reply::{CommentReply, CommentReplyInsertForm},
+ person::Person,
+ person_mention::{PersonMention, PersonMentionInsertForm},
+ post::Post,
+ },
+ traits::Crud,
+};
+use lemmy_db_views::structs::{CommentView, LocalUserView, PostView};
+use lemmy_db_views_actor::structs::CommunityView;
+use lemmy_utils::{error::LemmyError, utils::mention::MentionData};
+
+pub async fn build_comment_response(
+ context: &Data<LemmyContext>,
+ comment_id: CommentId,
+ local_user_view: Option<LocalUserView>,
+ form_id: Option<String>,
+ recipient_ids: Vec<LocalUserId>,
+) -> Result<CommentResponse, LemmyError> {
+ let person_id = local_user_view.map(|l| l.person.id);
+ let comment_view = CommentView::read(context.pool(), comment_id, person_id).await?;
+ Ok(CommentResponse {
+ comment_view,
+ recipient_ids,
+ form_id,
+ })
+}
+
+pub async fn build_community_response(
+ context: &Data<LemmyContext>,
+ local_user_view: LocalUserView,
+ community_id: CommunityId,
+) -> Result<CommunityResponse, LemmyError> {
+ let is_mod_or_admin = is_mod_or_admin(context.pool(), local_user_view.person.id, community_id)
+ .await
+ .is_ok();
+ let person_id = local_user_view.person.id;
+ let community_view = CommunityView::read(
+ context.pool(),
+ community_id,
+ Some(person_id),
+ Some(is_mod_or_admin),
+ )
+ .await?;
+ let discussion_languages = CommunityLanguage::read(context.pool(), community_id).await?;
+
+ Ok(CommunityResponse {
+ community_view,
+ discussion_languages,
+ })
+}
+
+pub async fn build_post_response(
+ context: &Data<LemmyContext>,
+ community_id: CommunityId,
+ person_id: PersonId,
+ post_id: PostId,
+) -> Result<PostResponse, LemmyError> {
+ let is_mod_or_admin = is_mod_or_admin(context.pool(), person_id, community_id)
+ .await
+ .is_ok();
+ let post_view = PostView::read(
+ context.pool(),
+ post_id,
+ Some(person_id),
+ Some(is_mod_or_admin),
+ )
+ .await?;
+ Ok(PostResponse { post_view })
+}
+
+// TODO: this function is a mess and should be split up to handle email seperately
+#[tracing::instrument(skip_all)]
+pub async fn send_local_notifs(
+ mentions: Vec<MentionData>,
+ comment: &Comment,
+ person: &Person,
+ post: &Post,
+ do_send_email: bool,
+ context: &LemmyContext,
+) -> Result<Vec<LocalUserId>, LemmyError> {
+ let mut recipient_ids = Vec::new();
+ let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
+
+ // Send the local mentions
+ for mention in mentions
+ .iter()
+ .filter(|m| m.is_local(&context.settings().hostname) && m.name.ne(&person.name))
+ .collect::<Vec<&MentionData>>()
+ {
+ let mention_name = mention.name.clone();
+ let user_view = LocalUserView::read_from_name(context.pool(), &mention_name).await;
+ if let Ok(mention_user_view) = user_view {
+ // TODO
+ // At some point, make it so you can't tag the parent creator either
+ // This can cause two notifications, one for reply and the other for mention
+ recipient_ids.push(mention_user_view.local_user.id);
+
+ let user_mention_form = PersonMentionInsertForm {
+ recipient_id: mention_user_view.person.id,
+ comment_id: comment.id,
+ read: None,
+ };
+
+ // Allow this to fail softly, since comment edits might re-update or replace it
+ // Let the uniqueness handle this fail
+ PersonMention::create(context.pool(), &user_mention_form)
+ .await
+ .ok();
+
+ // Send an email to those local users that have notifications on
+ if do_send_email {
+ let lang = get_interface_language(&mention_user_view);
+ send_email_to_user(
+ &mention_user_view,
+ &lang.notification_mentioned_by_subject(&person.name),
+ &lang.notification_mentioned_by_body(&comment.content, &inbox_link, &person.name),
+ context.settings(),
+ )
+ }
+ }
+ }
+
+ // Send comment_reply to the parent commenter / poster
+ if let Some(parent_comment_id) = comment.parent_comment_id() {
+ let parent_comment = Comment::read(context.pool(), parent_comment_id).await?;
+
+ // Get the parent commenter local_user
+ let parent_creator_id = parent_comment.creator_id;
+
+ // Only add to recipients if that person isn't blocked
+ let creator_blocked = check_person_block(person.id, parent_creator_id, context.pool())
+ .await
+ .is_err();
+
+ // Don't send a notif to yourself
+ if parent_comment.creator_id != person.id && !creator_blocked {
+ let user_view = LocalUserView::read_person(context.pool(), parent_creator_id).await;
+ if let Ok(parent_user_view) = user_view {
+ recipient_ids.push(parent_user_view.local_user.id);
+
+ let comment_reply_form = CommentReplyInsertForm {
+ recipient_id: parent_user_view.person.id,
+ comment_id: comment.id,
+ read: None,
+ };
+
+ // Allow this to fail softly, since comment edits might re-update or replace it
+ // Let the uniqueness handle this fail
+ CommentReply::create(context.pool(), &comment_reply_form)
+ .await
+ .ok();
+
+ if do_send_email {
+ let lang = get_interface_language(&parent_user_view);
+ send_email_to_user(
+ &parent_user_view,
+ &lang.notification_comment_reply_subject(&person.name),
+ &lang.notification_comment_reply_body(&comment.content, &inbox_link, &person.name),
+ context.settings(),
+ )
+ }
+ }
+ }
+ } else {
+ // If there's no parent, its the post creator
+ // Only add to recipients if that person isn't blocked
+ let creator_blocked = check_person_block(person.id, post.creator_id, context.pool())
+ .await
+ .is_err();
+
+ if post.creator_id != person.id && !creator_blocked {
+ let creator_id = post.creator_id;
+ let parent_user = LocalUserView::read_person(context.pool(), creator_id).await;
+ if let Ok(parent_user_view) = parent_user {
+ recipient_ids.push(parent_user_view.local_user.id);
+
+ let comment_reply_form = CommentReplyInsertForm {
+ recipient_id: parent_user_view.person.id,
+ comment_id: comment.id,
+ read: None,
+ };
+
+ // Allow this to fail softly, since comment edits might re-update or replace it
+ // Let the uniqueness handle this fail
+ CommentReply::create(context.pool(), &comment_reply_form)
+ .await
+ .ok();
+
+ if do_send_email {
+ let lang = get_interface_language(&parent_user_view);
+ send_email_to_user(
+ &parent_user_view,
+ &lang.notification_post_reply_subject(&person.name),
+ &lang.notification_post_reply_body(&comment.content, &inbox_link, &person.name),
+ context.settings(),
+ )
+ }
+ }
+ }
+ }
+
+ Ok(recipient_ids)
+}
pub community_view: CommunityView,
pub site: Option<Site>,
pub moderators: Vec<CommunityModeratorView>,
- pub online: usize,
pub discussion_languages: Vec<LanguageId>,
}
-use crate::websocket::chat_server::ChatServer;
-use actix::Addr;
use lemmy_db_schema::{source::secret::Secret, utils::DbPool};
use lemmy_utils::{
rate_limit::RateLimitCell,
#[derive(Clone)]
pub struct LemmyContext {
pool: DbPool,
- chat_server: Addr<ChatServer>,
client: Arc<ClientWithMiddleware>,
secret: Arc<Secret>,
rate_limit_cell: RateLimitCell,
impl LemmyContext {
pub fn create(
pool: DbPool,
- chat_server: Addr<ChatServer>,
client: ClientWithMiddleware,
secret: Secret,
rate_limit_cell: RateLimitCell,
) -> LemmyContext {
LemmyContext {
pool,
- chat_server,
client: Arc::new(client),
secret: Arc::new(secret),
rate_limit_cell,
pub fn pool(&self) -> &DbPool {
&self.pool
}
- pub fn chat_server(&self) -> &Addr<ChatServer> {
- &self.chat_server
- }
pub fn client(&self) -> &ClientWithMiddleware {
&self.client
}
+#[cfg(feature = "full")]
+pub mod build_response;
pub mod comment;
pub mod community;
#[cfg(feature = "full")]
pub mod site;
#[cfg(feature = "full")]
pub mod utils;
-#[cfg(feature = "full")]
-pub mod websocket;
-#[macro_use]
-extern crate strum_macros;
pub extern crate lemmy_db_schema;
pub extern crate lemmy_db_views;
pub extern crate lemmy_db_views_actor;
pub moderators: Vec<CommunityModeratorView>,
/// A list of cross-posts, or other times / communities this link has been posted to.
pub cross_posts: Vec<PostView>,
- pub online: usize,
}
#[skip_serializing_none]
pub struct GetSiteResponse {
pub site_view: SiteView,
pub admins: Vec<PersonView>,
- pub online: usize,
pub version: String,
pub my_user: Option<MyUserInfo>,
pub all_languages: Vec<Language>,
+++ /dev/null
-use crate::websocket::{
- handlers::{SessionInfo, WsMessage},
- structs::CaptchaItem,
-};
-use actix::{Actor, Context};
-use lemmy_db_schema::newtypes::{CommunityId, LocalUserId, PostId};
-use lemmy_utils::ConnectionId;
-use rand::{rngs::StdRng, SeedableRng};
-use std::collections::{HashMap, HashSet};
-
-pub struct ChatServer {
- /// A map from generated random ID to session addr
- pub sessions: HashMap<ConnectionId, SessionInfo>,
-
- /// A map from post_id to set of connectionIDs
- pub post_rooms: HashMap<PostId, HashSet<ConnectionId>>,
-
- /// A map from community to set of connectionIDs
- pub community_rooms: HashMap<CommunityId, HashSet<ConnectionId>>,
-
- pub mod_rooms: HashMap<CommunityId, HashSet<ConnectionId>>,
-
- /// A map from user id to its connection ID for joined users. Remember a user can have multiple
- /// sessions (IE clients)
- pub(super) user_rooms: HashMap<LocalUserId, HashSet<ConnectionId>>,
-
- pub(super) rng: StdRng,
-
- /// A list of the current captchas
- pub(super) captchas: Vec<CaptchaItem>,
-}
-
-/// `ChatServer` is an actor. It maintains list of connection client session.
-/// And manages available rooms. Peers send messages to other peers in same
-/// room through `ChatServer`.
-impl ChatServer {
- pub fn new() -> ChatServer {
- ChatServer {
- sessions: Default::default(),
- post_rooms: Default::default(),
- community_rooms: Default::default(),
- mod_rooms: Default::default(),
- user_rooms: Default::default(),
- rng: StdRng::from_entropy(),
- captchas: vec![],
- }
- }
-
- pub fn send_message(
- &self,
- connections: &HashSet<ConnectionId>,
- message: &str,
- exclude_connection: Option<ConnectionId>,
- ) {
- for id in connections
- .iter()
- .filter(|c| Some(*c) != exclude_connection.as_ref())
- {
- if let Some(session) = self.sessions.get(id) {
- session.addr.do_send(WsMessage(message.to_owned()));
- }
- }
- }
-}
-
-impl Default for ChatServer {
- fn default() -> Self {
- Self::new()
- }
-}
-
-/// Make actor from `ChatServer`
-impl Actor for ChatServer {
- /// We are going to use simple Context, we just need ability to communicate
- /// with other actors.
- type Context = Context<Self>;
-}
+++ /dev/null
-use crate::websocket::{chat_server::ChatServer, structs::CaptchaItem};
-use actix::{Context, Handler, Message};
-use lemmy_db_schema::utils::naive_now;
-
-/// Adding a Captcha
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct AddCaptcha {
- pub captcha: CaptchaItem,
-}
-
-impl Handler<AddCaptcha> for ChatServer {
- type Result = ();
-
- fn handle(&mut self, msg: AddCaptcha, _: &mut Context<Self>) -> Self::Result {
- self.captchas.push(msg.captcha);
- }
-}
-
-/// Checking a Captcha
-#[derive(Message)]
-#[rtype(bool)]
-pub struct CheckCaptcha {
- pub uuid: String,
- pub answer: String,
-}
-
-impl Handler<CheckCaptcha> for ChatServer {
- type Result = bool;
-
- fn handle(&mut self, msg: CheckCaptcha, _: &mut Context<Self>) -> Self::Result {
- // Remove all the ones that are past the expire time
- self.captchas.retain(|x| x.expires.gt(&naive_now()));
-
- let check = self
- .captchas
- .iter()
- .any(|r| r.uuid == msg.uuid && r.answer.to_lowercase() == msg.answer.to_lowercase());
-
- // Remove this uuid so it can't be re-checked (Checks only work once)
- self.captchas.retain(|x| x.uuid != msg.uuid);
-
- check
- }
-}
+++ /dev/null
-use crate::websocket::{
- chat_server::ChatServer,
- handlers::{SessionInfo, WsMessage},
-};
-use actix::{Context, Handler, Message, Recipient};
-use lemmy_utils::ConnectionId;
-use rand::Rng;
-
-/// New chat session is created
-#[derive(Message)]
-#[rtype(ConnectionId)]
-pub struct Connect {
- pub addr: Recipient<WsMessage>,
-}
-
-/// Handler for Connect message.
-///
-/// Register new session and assign unique id to this session
-impl Handler<Connect> for ChatServer {
- type Result = ConnectionId;
-
- fn handle(&mut self, msg: Connect, _: &mut Context<Self>) -> Self::Result {
- // register session with random id
- let id = self.rng.gen::<usize>();
- let session = SessionInfo { addr: msg.addr };
- self.sessions.insert(id, session);
-
- // send id back
- id
- }
-}
-
-/// Session is disconnected
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct Disconnect {
- pub id: ConnectionId,
-}
-
-/// Handler for Disconnect message.
-impl Handler<Disconnect> for ChatServer {
- type Result = ();
-
- fn handle(&mut self, msg: Disconnect, _: &mut Context<Self>) -> Self::Result {
- // remove address
- if self.sessions.remove(&msg.id).is_some() {
- // remove session from all rooms
- for sessions in self.user_rooms.values_mut() {
- sessions.remove(&msg.id);
- }
- for sessions in self.post_rooms.values_mut() {
- sessions.remove(&msg.id);
- }
- for sessions in self.community_rooms.values_mut() {
- sessions.remove(&msg.id);
- }
- for sessions in self.mod_rooms.values_mut() {
- sessions.remove(&msg.id);
- }
- }
- }
-}
+++ /dev/null
-use crate::websocket::chat_server::ChatServer;
-use actix::{Context, Handler, Message};
-use lemmy_db_schema::newtypes::{CommunityId, LocalUserId, PostId};
-use lemmy_utils::ConnectionId;
-use std::collections::HashSet;
-
-/// Joining a Post room
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct JoinPostRoom {
- pub post_id: PostId,
- pub id: ConnectionId,
-}
-
-impl Handler<JoinPostRoom> for ChatServer {
- type Result = ();
-
- fn handle(&mut self, msg: JoinPostRoom, _: &mut Context<Self>) -> Self::Result {
- // remove session from all rooms
- for sessions in self.post_rooms.values_mut() {
- sessions.remove(&msg.id);
- }
-
- // Also leave all communities
- // This avoids double messages
- // TODO found a bug, whereby community messages like
- // delete and remove aren't sent, because
- // you left the community room
- for sessions in self.community_rooms.values_mut() {
- sessions.remove(&msg.id);
- }
-
- self
- .post_rooms
- .entry(msg.post_id)
- .or_insert_with(HashSet::new)
- .insert(msg.id);
- }
-}
-
-/// Joining a Community Room
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct JoinCommunityRoom {
- pub community_id: CommunityId,
- pub id: ConnectionId,
-}
-
-impl Handler<JoinCommunityRoom> for ChatServer {
- type Result = ();
-
- fn handle(&mut self, msg: JoinCommunityRoom, _: &mut Context<Self>) -> Self::Result {
- // remove session from all rooms
- for sessions in self.community_rooms.values_mut() {
- sessions.remove(&msg.id);
- }
-
- // Also leave all post rooms
- // This avoids double messages
- for sessions in self.post_rooms.values_mut() {
- sessions.remove(&msg.id);
- }
-
- self
- .community_rooms
- .entry(msg.community_id)
- .or_insert_with(HashSet::new)
- .insert(msg.id);
- }
-}
-
-/// Joining a Mod room
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct JoinModRoom {
- pub community_id: CommunityId,
- pub id: ConnectionId,
-}
-
-impl Handler<JoinModRoom> for ChatServer {
- type Result = ();
-
- fn handle(&mut self, msg: JoinModRoom, _: &mut Context<Self>) -> Self::Result {
- // remove session from all rooms
- for sessions in self.mod_rooms.values_mut() {
- sessions.remove(&msg.id);
- }
-
- self
- .mod_rooms
- .entry(msg.community_id)
- .or_insert_with(HashSet::new)
- .insert(msg.id);
- }
-}
-
-/// Joining a User room
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct JoinUserRoom {
- pub user_id: LocalUserId,
- pub id: ConnectionId,
-}
-
-impl Handler<JoinUserRoom> for ChatServer {
- type Result = ();
-
- fn handle(&mut self, msg: JoinUserRoom, _: &mut Context<Self>) -> Self::Result {
- // remove session from all rooms
- for sessions in self.user_rooms.values_mut() {
- sessions.remove(&msg.id);
- }
-
- self
- .user_rooms
- .entry(msg.user_id)
- .or_insert_with(HashSet::new)
- .insert(msg.id);
- }
-}
+++ /dev/null
-use crate::websocket::chat_server::ChatServer;
-use actix::{Context, Handler, Message};
-use lemmy_db_schema::newtypes::{CommunityId, LocalUserId, PostId};
-use lemmy_utils::ConnectionId;
-use std::collections::HashSet;
-
-/// Sending a post room message
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct SendPostRoomMessage {
- pub post_id: PostId,
- pub message: String,
- pub websocket_id: Option<ConnectionId>,
-}
-
-impl Handler<SendPostRoomMessage> for ChatServer {
- type Result = ();
-
- fn handle(&mut self, msg: SendPostRoomMessage, _: &mut Context<Self>) -> Self::Result {
- let room_connections = self.post_rooms.get(&msg.post_id);
- if let Some(connections) = room_connections {
- self.send_message(connections, &msg.message, msg.websocket_id);
- }
- }
-}
-
-/// Sending a community room message
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct SendCommunityRoomMessage {
- pub community_id: CommunityId,
- pub message: String,
- pub websocket_id: Option<ConnectionId>,
-}
-
-impl Handler<SendCommunityRoomMessage> for ChatServer {
- type Result = ();
-
- fn handle(&mut self, msg: SendCommunityRoomMessage, _: &mut Context<Self>) -> Self::Result {
- let room_connections = self.community_rooms.get(&msg.community_id);
- if let Some(connections) = room_connections {
- self.send_message(connections, &msg.message, msg.websocket_id);
- }
- }
-}
-
-/// Sending a mod room message
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct SendModRoomMessage {
- pub community_id: CommunityId,
- pub message: String,
- pub websocket_id: Option<ConnectionId>,
-}
-
-impl Handler<SendModRoomMessage> for ChatServer {
- type Result = ();
-
- fn handle(&mut self, msg: SendModRoomMessage, _: &mut Context<Self>) -> Self::Result {
- let room_connections = self.community_rooms.get(&msg.community_id);
- if let Some(connections) = room_connections {
- self.send_message(connections, &msg.message, msg.websocket_id);
- }
- }
-}
-
-/// Sending a user room message
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct SendUserRoomMessage {
- pub recipient_id: LocalUserId,
- pub message: String,
- pub websocket_id: Option<ConnectionId>,
-}
-
-impl Handler<SendUserRoomMessage> for ChatServer {
- type Result = ();
-
- fn handle(&mut self, msg: SendUserRoomMessage, _: &mut Context<Self>) -> Self::Result {
- let room_connections = self.user_rooms.get(&msg.recipient_id);
- if let Some(connections) = room_connections {
- self.send_message(connections, &msg.message, msg.websocket_id);
- }
- }
-}
-
-/// Sending a message to every session
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct SendAllMessage {
- pub message: String,
- pub websocket_id: Option<ConnectionId>,
-}
-
-impl Handler<SendAllMessage> for ChatServer {
- type Result = ();
-
- fn handle(&mut self, msg: SendAllMessage, _: &mut Context<Self>) -> Self::Result {
- let connections: HashSet<ConnectionId> = self.sessions.keys().cloned().collect();
- self.send_message(&connections, &msg.message, msg.websocket_id);
- }
-}
-
-///// Send websocket message in all sessions which joined a specific room.
-/////
-///// `message` - The json message body to send
-///// `room` - Connection IDs which should receive the message
-///// `exclude_connection` - Dont send to user who initiated the api call, as that
-///// would result in duplicate notification
-//async fn send_message_in_room(
-// &self,
-// message: &str,
-// room: Option<HashSet<ConnectionId>>,
-// exclude_connection: Option<ConnectionId>,
-//) -> Result<(), LemmyError> {
-// let mut session = self.inner()?.sessions.clone();
-// if let Some(room) = room {
-// // Note, this will ignore any errors, such as closed connections
-// join_all(
-// room
-// .into_iter()
-// .filter(|c| Some(c) != exclude_connection.as_ref())
-// .filter_map(|c| session.remove(&c))
-// .map(|mut s: Session| async move { s.text(message).await }),
-// )
-// .await;
-// }
-// Ok(())
-//}
-//}
+++ /dev/null
-use actix::{Message, Recipient};
-
-pub mod captcha;
-pub mod connect;
-pub mod join_rooms;
-pub mod messages;
-pub mod online_users;
-
-/// A string message sent to a websocket session
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct WsMessage(pub String);
-
-// TODO move this?
-pub struct SessionInfo {
- pub addr: Recipient<WsMessage>,
- // pub ip: IpAddr
-}
+++ /dev/null
-use crate::websocket::chat_server::ChatServer;
-use actix::{Context, Handler, Message};
-use lemmy_db_schema::newtypes::{CommunityId, PostId};
-
-/// Getting the number of online connections
-#[derive(Message)]
-#[rtype(usize)]
-pub struct GetUsersOnline;
-
-/// Handler for Disconnect message.
-impl Handler<GetUsersOnline> for ChatServer {
- type Result = usize;
-
- fn handle(&mut self, _msg: GetUsersOnline, _: &mut Context<Self>) -> Self::Result {
- self.sessions.len()
- }
-}
-
-/// Getting the number of post users online
-#[derive(Message)]
-#[rtype(usize)]
-pub struct GetPostUsersOnline {
- pub post_id: PostId,
-}
-
-/// Handler for Disconnect message.
-impl Handler<GetPostUsersOnline> for ChatServer {
- type Result = usize;
-
- fn handle(&mut self, msg: GetPostUsersOnline, _: &mut Context<Self>) -> Self::Result {
- self
- .post_rooms
- .get(&msg.post_id)
- .map_or(1, std::collections::HashSet::len)
- }
-}
-
-/// Getting the number of post users online
-#[derive(Message)]
-#[rtype(usize)]
-pub struct GetCommunityUsersOnline {
- pub community_id: CommunityId,
-}
-
-/// Handler for Disconnect message.
-impl Handler<GetCommunityUsersOnline> for ChatServer {
- type Result = usize;
-
- fn handle(&mut self, msg: GetCommunityUsersOnline, _: &mut Context<Self>) -> Self::Result {
- self
- .community_rooms
- .get(&msg.community_id)
- .map_or(1, std::collections::HashSet::len)
- }
-}
+++ /dev/null
-use actix::{Message, Recipient};
-use lemmy_utils::error::LemmyError;
-use serde::Serialize;
-
-pub mod chat_server;
-pub mod handlers;
-pub mod send;
-pub mod structs;
-
-/// A string message sent to a websocket session
-#[derive(Message)]
-#[rtype(result = "()")]
-pub struct WsMessage(pub String);
-
-pub struct SessionInfo {
- pub addr: Recipient<WsMessage>,
-}
-
-#[derive(Serialize)]
-struct WebsocketResponse<T> {
- op: String,
- data: T,
-}
-
-pub fn serialize_websocket_message<Response, OP>(
- op: &OP,
- data: &Response,
-) -> Result<String, LemmyError>
-where
- Response: Serialize,
- OP: ToString,
-{
- let response = WebsocketResponse {
- op: op.to_string(),
- data,
- };
- Ok(serde_json::to_string(&response)?)
-}
-
-#[derive(EnumString, Display, Debug, Clone)]
-pub enum UserOperation {
- Login,
- GetCaptcha,
- SaveComment,
- CreateCommentLike,
- DistinguishComment,
- CreateCommentReport,
- ResolveCommentReport,
- ListCommentReports,
- CreatePostLike,
- LockPost,
- FeaturePost,
- MarkPostAsRead,
- SavePost,
- CreatePostReport,
- ResolvePostReport,
- ListPostReports,
- GetReportCount,
- GetUnreadCount,
- VerifyEmail,
- FollowCommunity,
- GetReplies,
- GetPersonMentions,
- MarkPersonMentionAsRead,
- MarkCommentReplyAsRead,
- GetModlog,
- BanFromCommunity,
- AddModToCommunity,
- AddAdmin,
- GetUnreadRegistrationApplicationCount,
- ListRegistrationApplications,
- ApproveRegistrationApplication,
- BanPerson,
- GetBannedPersons,
- MarkAllAsRead,
- SaveUserSettings,
- TransferCommunity,
- LeaveAdmin,
- PasswordReset,
- PasswordChange,
- MarkPrivateMessageAsRead,
- CreatePrivateMessageReport,
- ResolvePrivateMessageReport,
- ListPrivateMessageReports,
- UserJoin,
- PostJoin,
- CommunityJoin,
- ModJoin,
- ChangePassword,
- GetSiteMetadata,
- BlockCommunity,
- BlockPerson,
- PurgePerson,
- PurgeCommunity,
- PurgePost,
- PurgeComment,
- GetFederatedInstances,
-}
-
-#[derive(EnumString, Display, Debug, Clone)]
-pub enum UserOperationCrud {
- // Site
- CreateSite,
- GetSite,
- EditSite,
- // Community
- CreateCommunity,
- ListCommunities,
- EditCommunity,
- DeleteCommunity,
- RemoveCommunity,
- // Post
- CreatePost,
- GetPost,
- EditPost,
- DeletePost,
- RemovePost,
- // Comment
- CreateComment,
- GetComment,
- EditComment,
- DeleteComment,
- RemoveComment,
- // User
- Register,
- DeleteAccount,
- // Private Message
- CreatePrivateMessage,
- GetPrivateMessages,
- EditPrivateMessage,
- DeletePrivateMessage,
- //Emojis
- CreateCustomEmoji,
- EditCustomEmoji,
- DeleteCustomEmoji,
-}
-
-#[derive(EnumString, Display, Debug, Clone)]
-pub enum UserOperationApub {
- GetPosts,
- GetCommunity,
- GetComments,
- GetPersonDetails,
- Search,
- ResolveObject,
-}
+++ /dev/null
-use super::{
- handlers::messages::{
- SendAllMessage,
- SendCommunityRoomMessage,
- SendModRoomMessage,
- SendPostRoomMessage,
- SendUserRoomMessage,
- },
- serialize_websocket_message,
-};
-use crate::{
- comment::CommentResponse,
- community::CommunityResponse,
- context::LemmyContext,
- post::PostResponse,
- private_message::PrivateMessageResponse,
- utils::{check_person_block, get_interface_language, send_email_to_user},
-};
-use lemmy_db_schema::{
- newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId, PrivateMessageId},
- source::{
- actor_language::CommunityLanguage,
- comment::Comment,
- comment_reply::{CommentReply, CommentReplyInsertForm},
- person::Person,
- person_mention::{PersonMention, PersonMentionInsertForm},
- post::Post,
- },
- traits::Crud,
- SubscribedType,
-};
-use lemmy_db_views::structs::{CommentView, LocalUserView, PostView, PrivateMessageView};
-use lemmy_db_views_actor::structs::CommunityView;
-use lemmy_utils::{error::LemmyError, utils::mention::MentionData, ConnectionId};
-use serde::Serialize;
-
-impl LemmyContext {
- #[tracing::instrument(skip_all)]
- pub async fn send_post_ws_message<OP>(
- &self,
- op: &OP,
- post_id: PostId,
- websocket_id: Option<ConnectionId>,
- person_id: Option<PersonId>,
- ) -> Result<PostResponse, LemmyError>
- where
- OP: ToString,
- {
- let post_view = PostView::read(self.pool(), post_id, person_id, Some(true)).await?;
-
- let res = PostResponse { post_view };
-
- // Send it to the post room
- // Don't send my data with it
- let mut post_sent = res.clone();
- post_sent.post_view.my_vote = None;
- let message = serialize_websocket_message(op, &post_sent)?;
-
- self.chat_server().do_send(SendPostRoomMessage {
- post_id,
- message: message.clone(),
- websocket_id,
- });
-
- // Send it to /c/all and that community
- self.chat_server().do_send(SendCommunityRoomMessage {
- community_id: CommunityId(0),
- message: message.clone(),
- websocket_id,
- });
-
- self.chat_server().do_send(SendCommunityRoomMessage {
- community_id: post_sent.post_view.community.id,
- message,
- websocket_id,
- });
-
- Ok(res)
- }
-
- // TODO: in many call sites in apub crate, we are setting an empty vec for recipient_ids,
- // we should get the actual recipient actors from somewhere
- #[tracing::instrument(skip_all)]
- pub async fn send_comment_ws_message_simple<OP>(
- &self,
- op: &OP,
- comment_id: CommentId,
- ) -> Result<CommentResponse, LemmyError>
- where
- OP: ToString,
- {
- self
- .send_comment_ws_message(op, comment_id, None, None, None, vec![])
- .await
- }
-
- #[tracing::instrument(skip_all)]
- pub async fn send_comment_ws_message<OP>(
- &self,
- op: &OP,
- comment_id: CommentId,
- websocket_id: Option<ConnectionId>,
- form_id: Option<String>,
- person_id: Option<PersonId>,
- recipient_ids: Vec<LocalUserId>,
- ) -> Result<CommentResponse, LemmyError>
- where
- OP: ToString,
- {
- let view = CommentView::read(self.pool(), comment_id, person_id).await?;
-
- let mut res = CommentResponse {
- comment_view: view,
- recipient_ids,
- form_id,
- };
-
- // Strip out my specific user info
- let mut sent_recipient_comment = res.clone();
- sent_recipient_comment.form_id = None;
- sent_recipient_comment.comment_view.my_vote = None;
- let recipient_message = serialize_websocket_message(op, &sent_recipient_comment)?;
-
- // Send it to the recipient(s) including the mentioned users
- for recipient_id in &sent_recipient_comment.recipient_ids {
- self.chat_server().do_send(SendUserRoomMessage {
- recipient_id: *recipient_id,
- message: recipient_message.clone(),
- websocket_id,
- });
- }
-
- // Remove the recipients here to separate mentions / user messages from post or community comments
- let mut sent_post_comment = sent_recipient_comment;
- sent_post_comment.recipient_ids = Vec::new();
- let post_message = serialize_websocket_message(op, &sent_post_comment)?;
-
- // Send it to the post room
- self.chat_server().do_send(SendPostRoomMessage {
- post_id: sent_post_comment.comment_view.post.id,
- message: post_message.clone(),
- websocket_id,
- });
-
- // Send it to the community too
- self.chat_server().do_send(SendCommunityRoomMessage {
- community_id: sent_post_comment.comment_view.community.id,
- message: post_message,
- websocket_id,
- });
- // TODO should I send it to all? Seems excessive
- // self
- // .send_community_room_message(
- // user_operation,
- // &comment_post_sent,
- // CommunityId(0),
- // websocket_id,
- // )
- // .await?;
-
- // No need to return recipients
- res.recipient_ids = Vec::new();
-
- Ok(res)
- }
-
- #[tracing::instrument(skip_all)]
- pub async fn send_community_ws_message<OP>(
- &self,
- op: &OP,
- community_id: CommunityId,
- websocket_id: Option<ConnectionId>,
- person_id: Option<PersonId>,
- ) -> Result<CommunityResponse, LemmyError>
- where
- OP: ToString,
- {
- let community_view =
- CommunityView::read(self.pool(), community_id, person_id, Some(true)).await?;
- let discussion_languages = CommunityLanguage::read(self.pool(), community_id).await?;
-
- let mut res = CommunityResponse {
- community_view,
- discussion_languages,
- };
-
- // Strip out the person id and subscribed when sending to others
- res.community_view.subscribed = SubscribedType::NotSubscribed;
- let message = serialize_websocket_message(op, &res)?;
-
- self.chat_server().do_send(SendCommunityRoomMessage {
- community_id: res.community_view.community.id,
- message,
- websocket_id,
- });
-
- Ok(res)
- }
-
- #[tracing::instrument(skip_all)]
- pub async fn send_pm_ws_message<OP>(
- &self,
- op: &OP,
- private_message_id: PrivateMessageId,
- websocket_id: Option<ConnectionId>,
- ) -> Result<PrivateMessageResponse, LemmyError>
- where
- OP: ToString,
- {
- let view = PrivateMessageView::read(self.pool(), private_message_id).await?;
-
- let res = PrivateMessageResponse {
- private_message_view: view,
- };
-
- // Send notifications to the local recipient, if one exists
- if res.private_message_view.recipient.local {
- let recipient_id = res.private_message_view.recipient.id;
- let local_recipient = LocalUserView::read_person(self.pool(), recipient_id).await?;
-
- let message = serialize_websocket_message(op, &res)?;
-
- self.chat_server().do_send(SendUserRoomMessage {
- recipient_id: local_recipient.local_user.id,
- message,
- websocket_id,
- });
- }
-
- Ok(res)
- }
-
- #[tracing::instrument(skip_all)]
- pub async fn send_local_notifs(
- &self,
- mentions: Vec<MentionData>,
- comment: &Comment,
- person: &Person,
- post: &Post,
- do_send_email: bool,
- ) -> Result<Vec<LocalUserId>, LemmyError> {
- let mut recipient_ids = Vec::new();
- let inbox_link = format!("{}/inbox", self.settings().get_protocol_and_hostname());
-
- // Send the local mentions
- for mention in mentions
- .iter()
- .filter(|m| m.is_local(&self.settings().hostname) && m.name.ne(&person.name))
- .collect::<Vec<&MentionData>>()
- {
- let mention_name = mention.name.clone();
- let user_view = LocalUserView::read_from_name(self.pool(), &mention_name).await;
- if let Ok(mention_user_view) = user_view {
- // TODO
- // At some point, make it so you can't tag the parent creator either
- // This can cause two notifications, one for reply and the other for mention
- recipient_ids.push(mention_user_view.local_user.id);
-
- let user_mention_form = PersonMentionInsertForm {
- recipient_id: mention_user_view.person.id,
- comment_id: comment.id,
- read: None,
- };
-
- // Allow this to fail softly, since comment edits might re-update or replace it
- // Let the uniqueness handle this fail
- PersonMention::create(self.pool(), &user_mention_form)
- .await
- .ok();
-
- // Send an email to those local users that have notifications on
- if do_send_email {
- let lang = get_interface_language(&mention_user_view);
- send_email_to_user(
- &mention_user_view,
- &lang.notification_mentioned_by_subject(&person.name),
- &lang.notification_mentioned_by_body(&comment.content, &inbox_link, &person.name),
- self.settings(),
- )
- }
- }
- }
-
- // Send comment_reply to the parent commenter / poster
- if let Some(parent_comment_id) = comment.parent_comment_id() {
- let parent_comment = Comment::read(self.pool(), parent_comment_id).await?;
-
- // Get the parent commenter local_user
- let parent_creator_id = parent_comment.creator_id;
-
- // Only add to recipients if that person isn't blocked
- let creator_blocked = check_person_block(person.id, parent_creator_id, self.pool())
- .await
- .is_err();
-
- // Don't send a notif to yourself
- if parent_comment.creator_id != person.id && !creator_blocked {
- let user_view = LocalUserView::read_person(self.pool(), parent_creator_id).await;
- if let Ok(parent_user_view) = user_view {
- recipient_ids.push(parent_user_view.local_user.id);
-
- let comment_reply_form = CommentReplyInsertForm {
- recipient_id: parent_user_view.person.id,
- comment_id: comment.id,
- read: None,
- };
-
- // Allow this to fail softly, since comment edits might re-update or replace it
- // Let the uniqueness handle this fail
- CommentReply::create(self.pool(), &comment_reply_form)
- .await
- .ok();
-
- if do_send_email {
- let lang = get_interface_language(&parent_user_view);
- send_email_to_user(
- &parent_user_view,
- &lang.notification_comment_reply_subject(&person.name),
- &lang.notification_comment_reply_body(&comment.content, &inbox_link, &person.name),
- self.settings(),
- )
- }
- }
- }
- } else {
- // If there's no parent, its the post creator
- // Only add to recipients if that person isn't blocked
- let creator_blocked = check_person_block(person.id, post.creator_id, self.pool())
- .await
- .is_err();
-
- if post.creator_id != person.id && !creator_blocked {
- let creator_id = post.creator_id;
- let parent_user = LocalUserView::read_person(self.pool(), creator_id).await;
- if let Ok(parent_user_view) = parent_user {
- recipient_ids.push(parent_user_view.local_user.id);
-
- let comment_reply_form = CommentReplyInsertForm {
- recipient_id: parent_user_view.person.id,
- comment_id: comment.id,
- read: None,
- };
-
- // Allow this to fail softly, since comment edits might re-update or replace it
- // Let the uniqueness handle this fail
- CommentReply::create(self.pool(), &comment_reply_form)
- .await
- .ok();
-
- if do_send_email {
- let lang = get_interface_language(&parent_user_view);
- send_email_to_user(
- &parent_user_view,
- &lang.notification_post_reply_subject(&person.name),
- &lang.notification_post_reply_body(&comment.content, &inbox_link, &person.name),
- self.settings(),
- )
- }
- }
- }
- }
-
- Ok(recipient_ids)
- }
-
- #[tracing::instrument(skip_all)]
- pub fn send_all_ws_message<Data, OP>(
- &self,
- op: &OP,
- data: Data,
- websocket_id: Option<ConnectionId>,
- ) -> Result<(), LemmyError>
- where
- Data: Serialize,
- OP: ToString,
- {
- let message = serialize_websocket_message(op, &data)?;
- self.chat_server().do_send(SendAllMessage {
- message,
- websocket_id,
- });
- Ok(())
- }
-
- #[tracing::instrument(skip_all)]
- pub fn send_mod_ws_message<Data, OP>(
- &self,
- op: &OP,
- data: Data,
- community_id: CommunityId,
- websocket_id: Option<ConnectionId>,
- ) -> Result<(), LemmyError>
- where
- Data: Serialize,
- OP: ToString,
- {
- let message = serialize_websocket_message(op, &data)?;
- self.chat_server().do_send(SendModRoomMessage {
- community_id,
- message,
- websocket_id,
- });
- Ok(())
- }
-}
+++ /dev/null
-use crate::sensitive::Sensitive;
-use lemmy_db_schema::newtypes::{CommunityId, PostId};
-use serde::{Deserialize, Serialize};
-#[cfg(feature = "full")]
-use ts_rs::TS;
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-#[cfg_attr(feature = "full", derive(TS))]
-#[cfg_attr(feature = "full", ts(export))]
-/// Join a user room.
-pub struct UserJoin {
- pub auth: Sensitive<String>,
-}
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-#[cfg_attr(feature = "full", derive(TS))]
-#[cfg_attr(feature = "full", ts(export))]
-/// The join response.
-pub struct UserJoinResponse {
- pub joined: bool,
-}
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-#[cfg_attr(feature = "full", derive(TS))]
-#[cfg_attr(feature = "full", ts(export))]
-/// Join a community room.
-pub struct CommunityJoin {
- pub community_id: CommunityId,
-}
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-#[cfg_attr(feature = "full", derive(TS))]
-#[cfg_attr(feature = "full", ts(export))]
-/// The join response.
-pub struct CommunityJoinResponse {
- pub joined: bool,
-}
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-#[cfg_attr(feature = "full", derive(TS))]
-#[cfg_attr(feature = "full", ts(export))]
-/// Join a mod room.
-pub struct ModJoin {
- pub community_id: CommunityId,
-}
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-#[cfg_attr(feature = "full", derive(TS))]
-#[cfg_attr(feature = "full", ts(export))]
-/// The join response.
-pub struct ModJoinResponse {
- pub joined: bool,
-}
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-#[cfg_attr(feature = "full", derive(TS))]
-#[cfg_attr(feature = "full", ts(export))]
-/// Join a post room.
-pub struct PostJoin {
- pub post_id: PostId,
-}
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-#[cfg_attr(feature = "full", derive(TS))]
-#[cfg_attr(feature = "full", ts(export))]
-/// The join response.
-pub struct PostJoinResponse {
- pub joined: bool,
-}
-
-#[derive(Debug)]
-pub struct CaptchaItem {
- pub uuid: String,
- pub answer: String,
- pub expires: chrono::NaiveDateTime,
-}
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::{build_comment_response, send_local_notifs},
comment::{CommentResponse, CreateComment},
context::LemmyContext,
utils::{
local_user_view_from_jwt,
EndpointType,
},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::{
slurs::remove_slurs,
validation::is_valid_body_field,
},
- ConnectionId,
};
#[async_trait::async_trait(?Send)]
impl PerformCrud for CreateComment {
type Response = CommentResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<CommentResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommentResponse, LemmyError> {
let data: &CreateComment = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let local_site = LocalSite::read(context.pool()).await?;
.map_err(|e| LemmyError::from_error_message(e, "couldnt_create_comment"))?;
// Scan the comment for user mentions, add those rows
- let post_id = post.id;
let mentions = scrape_text_for_mentions(&content_slurs_removed);
- let recipient_ids = context
- .send_local_notifs(
- mentions,
- &updated_comment,
- &local_user_view.person,
- &post,
- true,
- )
- .await?;
+ let recipient_ids = send_local_notifs(
+ mentions,
+ &updated_comment,
+ &local_user_view.person,
+ &post,
+ true,
+ context,
+ )
+ .await?;
// You like your own comment by default
let like_form = CommentLikeForm {
comment_id: inserted_comment.id,
- post_id,
+ post_id: post.id,
person_id: local_user_view.person.id,
score: 1,
};
}
}
- context
- .send_comment_ws_message(
- &UserOperationCrud::CreateComment,
- inserted_comment.id,
- websocket_id,
- data.form_id.clone(),
- Some(local_user_view.person.id),
- recipient_ids,
- )
- .await
+ build_comment_response(
+ context,
+ inserted_comment.id,
+ Some(local_user_view),
+ self.form_id.clone(),
+ recipient_ids,
+ )
+ .await
}
}
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::{build_comment_response, send_local_notifs},
comment::{CommentResponse, DeleteComment},
context::LemmyContext,
utils::{check_community_ban, local_user_view_from_jwt},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::{
traits::Crud,
};
use lemmy_db_views::structs::CommentView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for DeleteComment {
type Response = CommentResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<CommentResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommentResponse, LemmyError> {
let data: &DeleteComment = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let post_id = updated_comment.post_id;
let post = Post::read(context.pool(), post_id).await?;
- let recipient_ids = context
- .send_local_notifs(
- vec![],
- &updated_comment,
- &local_user_view.person,
- &post,
- false,
- )
- .await?;
-
- let res = context
- .send_comment_ws_message(
- &UserOperationCrud::DeleteComment,
- data.comment_id,
- websocket_id,
- None,
- Some(local_user_view.person.id),
- recipient_ids,
- )
- .await?;
+ let recipient_ids = send_local_notifs(
+ vec![],
+ &updated_comment,
+ &local_user_view.person,
+ &post,
+ false,
+ context,
+ )
+ .await?;
- Ok(res)
+ build_comment_response(
+ context,
+ updated_comment.id,
+ Some(local_user_view),
+ None,
+ recipient_ids,
+ )
+ .await
}
}
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_comment_response,
comment::{CommentResponse, GetComment},
context::LemmyContext,
utils::{check_private_instance, local_user_view_from_jwt_opt},
};
use lemmy_db_schema::source::local_site::LocalSite;
-use lemmy_db_views::structs::CommentView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for GetComment {
type Response = CommentResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let data = self;
let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), context).await;
let local_site = LocalSite::read(context.pool()).await?;
check_private_instance(&local_user_view, &local_site)?;
- let person_id = local_user_view.map(|u| u.person.id);
- let id = data.id;
- let comment_view = CommentView::read(context.pool(), id, person_id)
- .await
- .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_comment"))?;
-
- Ok(Self::Response {
- comment_view,
- form_id: None,
- recipient_ids: Vec::new(),
- })
+ build_comment_response(context, data.id, local_user_view, None, vec![]).await
}
}
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::{build_comment_response, send_local_notifs},
comment::{CommentResponse, RemoveComment},
context::LemmyContext,
utils::{check_community_ban, is_mod_or_admin, local_user_view_from_jwt},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::{
traits::Crud,
};
use lemmy_db_views::structs::CommentView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for RemoveComment {
type Response = CommentResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<CommentResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommentResponse, LemmyError> {
let data: &RemoveComment = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let post_id = updated_comment.post_id;
let post = Post::read(context.pool(), post_id).await?;
- let recipient_ids = context
- .send_local_notifs(
- vec![],
- &updated_comment,
- &local_user_view.person.clone(),
- &post,
- false,
- )
- .await?;
-
- let res = context
- .send_comment_ws_message(
- &UserOperationCrud::RemoveComment,
- data.comment_id,
- websocket_id,
- None, // TODO maybe this might clear other forms
- Some(local_user_view.person.id),
- recipient_ids,
- )
- .await?;
+ let recipient_ids = send_local_notifs(
+ vec![],
+ &updated_comment,
+ &local_user_view.person.clone(),
+ &post,
+ false,
+ context,
+ )
+ .await?;
- Ok(res)
+ build_comment_response(
+ context,
+ updated_comment.id,
+ Some(local_user_view),
+ None,
+ recipient_ids,
+ )
+ .await
}
}
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::{build_comment_response, send_local_notifs},
comment::{CommentResponse, EditComment},
context::LemmyContext,
utils::{check_community_ban, local_site_to_slur_regex, local_user_view_from_jwt},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::{
slurs::remove_slurs,
validation::is_valid_body_field,
},
- ConnectionId,
};
#[async_trait::async_trait(?Send)]
impl PerformCrud for EditComment {
type Response = CommentResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<CommentResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommentResponse, LemmyError> {
let data: &EditComment = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let local_site = LocalSite::read(context.pool()).await?;
// Do the mentions / recipients
let updated_comment_content = updated_comment.content.clone();
let mentions = scrape_text_for_mentions(&updated_comment_content);
- let recipient_ids = context
- .send_local_notifs(
- mentions,
- &updated_comment,
- &local_user_view.person,
- &orig_comment.post,
- false,
- )
- .await?;
+ let recipient_ids = send_local_notifs(
+ mentions,
+ &updated_comment,
+ &local_user_view.person,
+ &orig_comment.post,
+ false,
+ context,
+ )
+ .await?;
- context
- .send_comment_ws_message(
- &UserOperationCrud::EditComment,
- data.comment_id,
- websocket_id,
- data.form_id.clone(),
- None,
- recipient_ids,
- )
- .await
+ build_comment_response(
+ context,
+ updated_comment.id,
+ Some(local_user_view),
+ self.form_id.clone(),
+ recipient_ids,
+ )
+ .await
}
}
use activitypub_federation::http_signatures::generate_actor_keypair;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_community_response,
community::{CommunityResponse, CreateCommunity},
context::LemmyContext,
utils::{
utils::diesel_option_overwrite_to_url_create,
};
use lemmy_db_views::structs::SiteView;
-use lemmy_db_views_actor::structs::CommunityView;
use lemmy_utils::{
error::LemmyError,
utils::{
slurs::{check_slurs, check_slurs_opt},
validation::{is_valid_actor_name, is_valid_body_field},
},
- ConnectionId,
};
#[async_trait::async_trait(?Send)]
impl PerformCrud for CreateCommunity {
type Response = CommunityResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<CommunityResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommunityResponse, LemmyError> {
let data: &CreateCommunity = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let site_view = SiteView::read_local(context.pool()).await?;
CommunityLanguage::update(context.pool(), languages, community_id).await?;
}
- let person_id = local_user_view.person.id;
- let community_view =
- CommunityView::read(context.pool(), inserted_community.id, Some(person_id), None).await?;
- let discussion_languages =
- CommunityLanguage::read(context.pool(), inserted_community.id).await?;
-
- Ok(CommunityResponse {
- community_view,
- discussion_languages,
- })
+ build_community_response(context, local_user_view, community_id).await
}
}
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_community_response,
community::{CommunityResponse, DeleteCommunity},
context::LemmyContext,
utils::{is_top_mod, local_user_view_from_jwt},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::community::{Community, CommunityUpdateForm},
traits::Crud,
};
use lemmy_db_views_actor::structs::CommunityModeratorView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for DeleteCommunity {
type Response = CommunityResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<CommunityResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommunityResponse, LemmyError> {
let data: &DeleteCommunity = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_community"))?;
- let res = context
- .send_community_ws_message(
- &UserOperationCrud::DeleteCommunity,
- data.community_id,
- websocket_id,
- Some(local_user_view.person.id),
- )
- .await?;
-
- Ok(res)
+ build_community_response(context, local_user_view, community_id).await
}
}
};
use lemmy_db_schema::source::local_site::LocalSite;
use lemmy_db_views_actor::community_view::CommunityQuery;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for ListCommunities {
type Response = ListCommunitiesResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<ListCommunitiesResponse, LemmyError> {
let data: &ListCommunities = self;
let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), context).await;
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_community_response,
community::{CommunityResponse, RemoveCommunity},
context::LemmyContext,
utils::{is_admin, local_user_view_from_jwt},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::{
},
traits::Crud,
};
-use lemmy_utils::{error::LemmyError, utils::time::naive_from_unix, ConnectionId};
+use lemmy_utils::{error::LemmyError, utils::time::naive_from_unix};
#[async_trait::async_trait(?Send)]
impl PerformCrud for RemoveCommunity {
type Response = CommunityResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<CommunityResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommunityResponse, LemmyError> {
let data: &RemoveCommunity = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
};
ModRemoveCommunity::create(context.pool(), &form).await?;
- let res = context
- .send_community_ws_message(
- &UserOperationCrud::RemoveCommunity,
- data.community_id,
- websocket_id,
- Some(local_user_view.person.id),
- )
- .await?;
-
- Ok(res)
+ build_community_response(context, local_user_view, community_id).await
}
}
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_community_response,
community::{CommunityResponse, EditCommunity},
context::LemmyContext,
utils::{local_site_to_slur_regex, local_user_view_from_jwt},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
newtypes::PersonId,
use lemmy_utils::{
error::LemmyError,
utils::{slurs::check_slurs_opt, validation::is_valid_body_field},
- ConnectionId,
};
#[async_trait::async_trait(?Send)]
impl PerformCrud for EditCommunity {
type Response = CommunityResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<CommunityResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommunityResponse, LemmyError> {
let data: &EditCommunity = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let local_site = LocalSite::read(context.pool()).await?;
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_community"))?;
- context
- .send_community_ws_message(
- &UserOperationCrud::EditCommunity,
- data.community_id,
- websocket_id,
- None,
- )
- .await
+ build_community_response(context, local_user_view, community_id).await
}
}
local_site::LocalSite,
};
use lemmy_db_views::structs::CustomEmojiView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for CreateCustomEmoji {
type Response = CustomEmojiResponse;
- #[tracing::instrument(skip(self, context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<CustomEmojiResponse, LemmyError> {
+ #[tracing::instrument(skip(self, context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CustomEmojiResponse, LemmyError> {
let data: &CreateCustomEmoji = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
utils::{is_admin, local_user_view_from_jwt},
};
use lemmy_db_schema::source::custom_emoji::CustomEmoji;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for DeleteCustomEmoji {
type Response = DeleteCustomEmojiResponse;
- #[tracing::instrument(skip(self, context, _websocket_id))]
+ #[tracing::instrument(skip(self, context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<DeleteCustomEmojiResponse, LemmyError> {
let data: &DeleteCustomEmoji = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
local_site::LocalSite,
};
use lemmy_db_views::structs::CustomEmojiView;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for EditCustomEmoji {
type Response = CustomEmojiResponse;
- #[tracing::instrument(skip(self, context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<CustomEmojiResponse, LemmyError> {
+ #[tracing::instrument(skip(self, context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<CustomEmojiResponse, LemmyError> {
let data: &EditCustomEmoji = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
use actix_web::web::Data;
use lemmy_api_common::context::LemmyContext;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
mod comment;
mod community;
pub trait PerformCrud {
type Response: serde::ser::Serialize + Send;
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError>;
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError>;
}
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_post_response,
context::LemmyContext,
post::{CreatePost, PostResponse},
request::fetch_site_data,
mark_post_as_read,
EndpointType,
},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
impls::actor_language::default_post_language,
slurs::{check_slurs, check_slurs_opt},
validation::{clean_url_params, is_valid_body_field, is_valid_post_title},
},
- ConnectionId,
};
use tracing::{warn, Instrument};
use url::Url;
impl PerformCrud for CreatePost {
type Response = PostResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<PostResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> {
let data: &CreatePost = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let local_site = LocalSite::read(context.pool()).await?;
}
}
- context
- .send_post_ws_message(
- &UserOperationCrud::CreatePost,
- inserted_post.id,
- websocket_id,
- Some(local_user_view.person.id),
- )
- .await
+ build_post_response(context, community_id, person_id, post_id).await
}
}
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_post_response,
context::LemmyContext,
post::{DeletePost, PostResponse},
utils::{check_community_ban, check_community_deleted_or_removed, local_user_view_from_jwt},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::post::{Post, PostUpdateForm},
traits::Crud,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for DeletePost {
type Response = PostResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<PostResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> {
let data: &DeletePost = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
)
.await?;
- let res = context
- .send_post_ws_message(
- &UserOperationCrud::DeletePost,
- data.post_id,
- websocket_id,
- Some(local_user_view.person.id),
- )
- .await?;
-
- Ok(res)
+ build_post_response(
+ context,
+ orig_post.community_id,
+ local_user_view.person.id,
+ post_id,
+ )
+ .await
}
}
local_user_view_from_jwt_opt,
mark_post_as_read,
},
- websocket::handlers::online_users::GetPostUsersOnline,
};
use lemmy_db_schema::{
aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm},
};
use lemmy_db_views::{post_view::PostQuery, structs::PostView};
use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for GetPost {
type Response = GetPostResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<GetPostResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetPostResponse, LemmyError> {
let data: &GetPost = self;
let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), context).await;
let local_site = LocalSite::read(context.pool()).await?;
Vec::new()
};
- let online = context
- .chat_server()
- .send(GetPostUsersOnline { post_id })
- .await?;
-
// Return the jwt
Ok(GetPostResponse {
post_view,
community_view,
moderators,
- online,
cross_posts,
})
}
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_post_response,
context::LemmyContext,
post::{PostResponse, RemovePost},
utils::{check_community_ban, is_mod_or_admin, local_user_view_from_jwt},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::{
},
traits::Crud,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for RemovePost {
type Response = PostResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<PostResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> {
let data: &RemovePost = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
};
ModRemovePost::create(context.pool(), &form).await?;
- let res = context
- .send_post_ws_message(
- &UserOperationCrud::RemovePost,
- data.post_id,
- websocket_id,
- Some(local_user_view.person.id),
- )
- .await?;
-
- Ok(res)
+ build_post_response(
+ context,
+ orig_post.community_id,
+ local_user_view.person.id,
+ post_id,
+ )
+ .await
}
}
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
+ build_response::build_post_response,
context::LemmyContext,
post::{EditPost, PostResponse},
request::fetch_site_data,
utils::{check_community_ban, local_site_to_slur_regex, local_user_view_from_jwt},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::{
slurs::check_slurs_opt,
validation::{clean_url_params, is_valid_body_field, is_valid_post_title},
},
- ConnectionId,
};
#[async_trait::async_trait(?Send)]
impl PerformCrud for EditPost {
type Response = PostResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<PostResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> {
let data: &EditPost = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let local_site = LocalSite::read(context.pool()).await?;
return Err(LemmyError::from_error_message(e, err_type));
}
- context
- .send_post_ws_message(
- &UserOperationCrud::EditPost,
- data.post_id,
- websocket_id,
- Some(local_user_view.person.id),
- )
- .await
+ build_post_response(
+ context,
+ orig_post.community_id,
+ local_user_view.person.id,
+ post_id,
+ )
+ .await
}
}
send_email_to_user,
EndpointType,
},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::{
},
traits::Crud,
};
-use lemmy_db_views::structs::LocalUserView;
+use lemmy_db_views::structs::{LocalUserView, PrivateMessageView};
use lemmy_utils::{
error::LemmyError,
utils::{slurs::remove_slurs, validation::is_valid_body_field},
- ConnectionId,
};
#[async_trait::async_trait(?Send)]
impl PerformCrud for CreatePrivateMessage {
type Response = PrivateMessageResponse;
- #[tracing::instrument(skip(self, context, websocket_id))]
+ #[tracing::instrument(skip(self, context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
) -> Result<PrivateMessageResponse, LemmyError> {
let data: &CreatePrivateMessage = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_create_private_message"))?;
- let res = context
- .send_pm_ws_message(
- &UserOperationCrud::CreatePrivateMessage,
- inserted_private_message.id,
- websocket_id,
- )
- .await?;
+ let view = PrivateMessageView::read(context.pool(), inserted_private_message.id).await?;
// Send email to the local recipient, if one exists
- if res.private_message_view.recipient.local {
+ if view.recipient.local {
let recipient_id = data.recipient_id;
let local_recipient = LocalUserView::read_person(context.pool(), recipient_id).await?;
let lang = get_interface_language(&local_recipient);
);
}
- Ok(res)
+ Ok(PrivateMessageResponse {
+ private_message_view: view,
+ })
}
}
context::LemmyContext,
private_message::{DeletePrivateMessage, PrivateMessageResponse},
utils::local_user_view_from_jwt,
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::private_message::{PrivateMessage, PrivateMessageUpdateForm},
traits::Crud,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_db_views::structs::PrivateMessageView;
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for DeletePrivateMessage {
type Response = PrivateMessageResponse;
- #[tracing::instrument(skip(self, context, websocket_id))]
+ #[tracing::instrument(skip(self, context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
) -> Result<PrivateMessageResponse, LemmyError> {
let data: &DeletePrivateMessage = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_private_message"))?;
- context
- .send_pm_ws_message(
- &UserOperationCrud::DeletePrivateMessage,
- data.private_message_id,
- websocket_id,
- )
- .await
+ let view = PrivateMessageView::read(context.pool(), private_message_id).await?;
+ Ok(PrivateMessageResponse {
+ private_message_view: view,
+ })
}
}
utils::local_user_view_from_jwt,
};
use lemmy_db_views::private_message_view::PrivateMessageQuery;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for GetPrivateMessages {
type Response = PrivateMessagesResponse;
- #[tracing::instrument(skip(self, context, _websocket_id))]
+ #[tracing::instrument(skip(self, context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<PrivateMessagesResponse, LemmyError> {
let data: &GetPrivateMessages = self;
let local_user_view = local_user_view_from_jwt(data.auth.as_ref(), context).await?;
context::LemmyContext,
private_message::{EditPrivateMessage, PrivateMessageResponse},
utils::{local_site_to_slur_regex, local_user_view_from_jwt},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::{
traits::Crud,
utils::naive_now,
};
+use lemmy_db_views::structs::PrivateMessageView;
use lemmy_utils::{
error::LemmyError,
utils::{slurs::remove_slurs, validation::is_valid_body_field},
- ConnectionId,
};
#[async_trait::async_trait(?Send)]
impl PerformCrud for EditPrivateMessage {
type Response = PrivateMessageResponse;
- #[tracing::instrument(skip(self, context, websocket_id))]
+ #[tracing::instrument(skip(self, context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
) -> Result<PrivateMessageResponse, LemmyError> {
let data: &EditPrivateMessage = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_private_message"))?;
- context
- .send_pm_ws_message(
- &UserOperationCrud::EditPrivateMessage,
- data.private_message_id,
- websocket_id,
- )
- .await
+ let view = PrivateMessageView::read(context.pool(), private_message_id).await?;
+
+ Ok(PrivateMessageResponse {
+ private_message_view: view,
+ })
}
}
slurs::{check_slurs, check_slurs_opt},
validation::is_valid_body_field,
},
- ConnectionId,
};
use url::Url;
impl PerformCrud for CreateSite {
type Response = SiteResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<SiteResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<SiteResponse, LemmyError> {
let data: &CreateSite = self;
let local_site = LocalSite::read(context.pool()).await?;
sensitive::Sensitive,
site::{GetSite, GetSiteResponse, MyUserInfo},
utils::{check_user_valid, check_validator_time},
- websocket::handlers::online_users::GetUsersOnline,
};
use lemmy_db_schema::{
newtypes::LocalUserId,
PersonBlockView,
PersonView,
};
-use lemmy_utils::{claims::Claims, error::LemmyError, version, ConnectionId};
+use lemmy_utils::{claims::Claims, error::LemmyError, version};
#[async_trait::async_trait(?Send)]
impl PerformCrud for GetSite {
type Response = GetSiteResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<GetSiteResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetSiteResponse, LemmyError> {
let data: &GetSite = self;
let site_view = SiteView::read_local(context.pool()).await?;
let admins = PersonView::admins(context.pool()).await?;
- let online = context.chat_server().send(GetUsersOnline).await?;
-
// Build the local user
let my_user = if let Some(local_user_view) =
local_user_settings_view_from_jwt_opt(data.auth.as_ref(), context).await
Ok(GetSiteResponse {
site_view,
admins,
- online,
version: version::VERSION.to_string(),
my_user,
all_languages,
local_user_view_from_jwt,
site_description_length_check,
},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::{
use lemmy_utils::{
error::LemmyError,
utils::{slurs::check_slurs_opt, validation::is_valid_body_field},
- ConnectionId,
};
#[async_trait::async_trait(?Send)]
impl PerformCrud for EditSite {
type Response = SiteResponse;
- #[tracing::instrument(skip(context, websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<SiteResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<SiteResponse, LemmyError> {
let data: &EditSite = self;
let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
let site_view = SiteView::read_local(context.pool()).await?;
taglines,
};
- context.send_all_ws_message(&UserOperationCrud::EditSite, &res, websocket_id)?;
-
Ok(res)
}
}
send_verification_email,
EndpointType,
},
- websocket::handlers::captcha::CheckCaptcha,
};
use lemmy_db_schema::{
aggregates::structs::PersonAggregates,
slurs::{check_slurs, check_slurs_opt},
validation::is_valid_actor_name,
},
- ConnectionId,
};
#[async_trait::async_trait(?Send)]
impl PerformCrud for Register {
type Response = LoginResponse;
- #[tracing::instrument(skip(self, context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<LoginResponse, LemmyError> {
+ #[tracing::instrument(skip(self, context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<LoginResponse, LemmyError> {
let data: &Register = self;
let site_view = SiteView::read_local(context.pool()).await?;
return Err(LemmyError::from_message("passwords_dont_match"));
}
- // If the site is set up, check the captcha
- if local_site.site_setup && local_site.captcha_enabled {
- let check = context
- .chat_server()
- .send(CheckCaptcha {
- uuid: data.captcha_uuid.clone().unwrap_or_default(),
- answer: data.captcha_answer.clone().unwrap_or_default(),
- })
- .await?;
- if !check {
- return Err(LemmyError::from_message("captcha_incorrect"));
- }
- }
-
let slur_regex = local_site_to_slur_regex(&local_site);
check_slurs(&data.username, &slur_regex)?;
check_slurs_opt(&data.answer, &slur_regex)?;
person::{DeleteAccount, DeleteAccountResponse},
utils::local_user_view_from_jwt,
};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait(?Send)]
impl PerformCrud for DeleteAccount {
type Response = DeleteAccountResponse;
- #[tracing::instrument(skip(self, context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError> {
+ #[tracing::instrument(skip(self, context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
let data = self;
let local_user_view = local_user_view_from_jwt(data.auth.as_ref(), context).await?;
serde = { workspace = true }
actix-web = { workspace = true }
actix-rt = { workspace = true }
-actix = { workspace = true }
tracing = { workspace = true }
strum_macros = { workspace = true }
url = { workspace = true }
{
"@context": [
"https://www.w3.org/ns/activitystreams",
- "https://w3id.org/security/v1",
{
- "vcard": "http://www.w3.org/2006/vcard/ns#",
- "dfrn": "http://purl.org/macgirvin/dfrn/1.0/",
- "diaspora": "https://diasporafoundation.org/ns/",
- "litepub": "http://litepub.social/ns#",
- "toot": "http://joinmastodon.org/ns#",
- "schema": "http://schema.org#",
- "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+ "ostatus": "http://ostatus.org#",
+ "atomUri": "ostatus:atomUri",
+ "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
+ "conversation": "ostatus:conversation",
"sensitive": "as:sensitive",
- "Hashtag": "as:Hashtag",
- "directMessage": "litepub:directMessage",
- "discoverable": "toot:discoverable",
- "PropertyValue": "schema:PropertyValue",
- "value": "schema:value"
+ "toot": "http://joinmastodon.org/ns#",
+ "votersCount": "toot:votersCount"
}
],
- "id": "https://pirati.ca/objects/ec054ce7-8062-3c1b-016c-910426317080/Create",
+ "id": "https://masto.qa.urbanwildlife.biz/users/mastodon/statuses/110435994705014161/activity",
"type": "Create",
- "actor": "https://pirati.ca/profile/heluecht",
- "published": "2022-03-24T07:17:21Z",
- "instrument": {
- "type": "Service",
- "name": "Friendica 'Siberian Iris' 2022.05-dev-1452",
- "url": "https://pirati.ca"
- },
- "to": ["https://ds9.lemmy.ml/c/testcom"],
+ "actor": "https://masto.qa.urbanwildlife.biz/users/mastodon",
+ "published": "2023-05-26T16:45:48Z",
+ "to": ["https://www.w3.org/ns/activitystreams#Public"],
"cc": [
- "https://www.w3.org/ns/activitystreams#Public",
- "https://ds9.lemmy.ml/c/testcom/followers"
+ "https://masto.qa.urbanwildlife.biz/users/mastodon/followers",
+ "https://lemmy.qa.urbanwildlife.biz/c/lemmy_community",
+ "https://lemmy.qa.urbanwildlife.biz/c/lemmy_community/followers"
],
"object": {
- "id": "https://pirati.ca/objects/ec054ce7-8062-3c1b-016c-910426317080",
- "type": "Page",
- "summary": "",
+ "id": "https://masto.qa.urbanwildlife.biz/users/mastodon/statuses/110435994705014161",
+ "type": "Note",
+ "summary": null,
"inReplyTo": null,
- "diaspora:guid": "ec054ce7-8062-3c1b-016c-910426317080",
- "published": "2022-03-24T07:17:21Z",
- "url": "https://www.nasaspaceflight.com/2022/03/us-eva-80/",
- "attributedTo": "https://pirati.ca/profile/heluecht",
+ "published": "2023-05-26T16:45:48Z",
+ "url": "https://masto.qa.urbanwildlife.biz/@mastodon/110435994705014161",
+ "attributedTo": "https://masto.qa.urbanwildlife.biz/users/mastodon",
+ "to": ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc": [
+ "https://masto.qa.urbanwildlife.biz/users/mastodon/followers",
+ "https://lemmy.qa.urbanwildlife.biz/c/lemmy_community",
+ "https://lemmy.qa.urbanwildlife.biz/c/lemmy_community/followers"
+ ],
"sensitive": false,
- "context": "https://pirati.ca/objects/ec054ce7-8062-3c1b-016c-910426317080#context",
- "name": "ISS astronauts perform final spacewalk of Expedition 66",
- "content": "Expedition 66 astronauts Raja Chari and Matthias Maurer ventured outside the International Space Station on Wednesday, performing a spacewalk to carry out repairs and upgrades on the space station.",
+ "atomUri": "https://masto.qa.urbanwildlife.biz/users/mastodon/statuses/110435994705014161",
+ "inReplyToAtomUri": null,
+ "conversation": "tag:masto.qa.urbanwildlife.biz,2023-05-26:objectId=61:objectType=Conversation",
+ "content": "<p>Test post to community</p><p><span class=\"h-card\"><a href=\"https://lemmy.qa.urbanwildlife.biz/c/lemmy_community\" class=\"u-url mention\">@<span>lemmy_community</span></a></span></p>",
"contentMap": {
- "de": "<bdi>!<a href=\"https://ds9.lemmy.ml/c/testcom\" class=\"userinfo mention\" title=\"testcom\">testcom</a></bdi> Expedition 66 astronauts Raja Chari and Matthias Maurer ventured outside the International Space Station on Wednesday, performing a spacewalk to carry out repairs and upgrades on the space station.<br><a href=\"https://www.nasaspaceflight.com/2022/03/us-eva-80/\" target=\"_blank\" rel=\"noopener noreferrer\">ISS astronauts perform final spacewalk of Expedition 66</a>"
- },
- "source": {
- "content": "![url=https://ds9.lemmy.ml/c/testcom]testcom[/url] Expedition 66 astronauts Raja Chari and Matthias Maurer ventured outside the International Space Station on Wednesday, performing a spacewalk to carry out repairs and upgrades on the space station.\n[attachment type='link' url='https://www.nasaspaceflight.com/2022/03/us-eva-80/' title='ISS astronauts perform final spacewalk of Expedition 66' publisher_name='NASASpaceFlight.com' publisher_url='https://www.nasaspaceflight.com/' publisher_img='https://www.nasaspaceflight.com/wp-content/uploads/2017/12/logo.svg' author_name='Justin Davenport' author_url='https://www.nasaspaceflight.com/author/justin/' author_img='https://secure.gravatar.com/avatar/5dc0dc04b38dbb016bf6f15552555883?s=96&d=mm&r=g' image='https://www.nasaspaceflight.com/wp-content/uploads/2022/03/51941297402_fa7a00c1ee_o-scaled.jpg']Expedition 66 astronauts Raja Chari and Matthias Maurer ventured outside the International Space Station on…[/attachment]",
- "mediaType": "text/bbcode"
+ "fr": "<p>Test post to community</p><p><span class=\"h-card\"><a href=\"https://lemmy.qa.urbanwildlife.biz/c/lemmy_community\" class=\"u-url mention\">@<span>lemmy_community</span></a></span></p>"
},
"attachment": [],
"tag": [
{
"type": "Mention",
- "href": "https://ds9.lemmy.ml/c/testcom",
- "name": "@testcom@ds9.lemmy.ml"
+ "href": "https://lemmy.qa.urbanwildlife.biz/c/lemmy_community",
+ "name": "@lemmy_community@lemmy.qa.urbanwildlife.biz"
}
],
- "to": ["https://ds9.lemmy.ml/c/testcom"],
- "cc": [
- "https://www.w3.org/ns/activitystreams#Public",
- "https://ds9.lemmy.ml/c/testcom/followers"
- ]
- },
- "signature": {
- "type": "RsaSignature2017",
- "nonce": "e68dbf66bac13fd0811863c32bbc59ab56dc0ced4a7f0df06a49b015dd142e29",
- "creator": "https://pirati.ca/profile/heluecht#main-key",
- "created": "2022-03-24T07:18:24Z",
- "signatureValue": "T+TZbRA0DhaCG3bRRPXQmxE2bsdIk8j/cueqsXTKCOSbrWvels2B9cg3twAYIfEmtyZ/f6iKz67MnMzAc4wDS5Gm5lJ/bVoweG3+OVtgfpzYUwR85az6qEX7NS0yLNdciqpZnh5J46F8lk+SKuLGEvlGuHVAd5yYXJoSJc0slM3rVvPv1s8toLHsJzM9H9aITLfZdEo99DmGgcAcSm1lrpFlXXMc+nWGAABpvK4eTrhj1auWOs6qb4q9GUyjfg2OdYrEq+vj4tir8uP/2azJHUea2JwIYbu0Cqt13OAPWC4Znz9MZdI6NQcQvipwFRq1tvfjsonzWIkBotDK9seBxTyj1kJfDd9hcPFXQdaNI549U4JJMxenKH5Yj5tj5Df0lg2hiFOCZ5fka5qmVpqDdPni4fnkCICzKpdJwUpwDaJlwbK8tnMlS5stQv+5+fX3O7sTy2z5PiFFYR/DdHHrMAz4eEoYe9AfrUGB5XzSyHRq0YThDMW4expIGm9KZxhfYgnKPVSqmmZLDKMYD69zwV7IMGfj+W9KqbnhrW+v1JQmWSziYmz4g+ESmo+F72kaVqu1UxIi0qToOA/QDp/HOZSM+YJUCQoCL41faO5+7MNrISL8TIjAa8Y5lXrx5oAKEXEx0biqBaxinOdzuqDl8dvyVtPa/DMez8enTbcGzdQ="
+ "replies": {
+ "id": "https://masto.qa.urbanwildlife.biz/users/mastodon/statuses/110435994705014161/replies",
+ "type": "Collection",
+ "first": {
+ "type": "CollectionPage",
+ "next": "https://masto.qa.urbanwildlife.biz/users/mastodon/statuses/110435994705014161/replies?only_other_accounts=true&page=true",
+ "partOf": "https://masto.qa.urbanwildlife.biz/users/mastodon/statuses/110435994705014161/replies",
+ "items": []
+ }
+ }
}
}
"@id": "toot:featured",
"@type": "@id"
},
+ "featuredTags": {
+ "@id": "toot:featuredTags",
+ "@type": "@id"
+ },
"alsoKnownAs": {
"@id": "as:alsoKnownAs",
"@type": "@id"
"schema": "http://schema.org#",
"PropertyValue": "schema:PropertyValue",
"value": "schema:value",
- "IdentityProof": "toot:IdentityProof",
"discoverable": "toot:discoverable",
"Device": "toot:Device",
"Ed25519Signature": "toot:Ed25519Signature",
"messageFranking": "toot:messageFranking",
"messageType": "toot:messageType",
"cipherText": "toot:cipherText",
- "Hashtag": "as:Hashtag",
+ "suspended": "toot:suspended",
"focalPoint": {
"@container": "@list",
"@id": "toot:focalPoint"
}
}
],
- "id": "https://mastodon.madrid/users/felix",
+ "id": "https://masto.qa.urbanwildlife.biz/users/mastodon",
"type": "Person",
- "following": "https://mastodon.madrid/users/felix/following",
- "followers": "https://mastodon.madrid/users/felix/followers",
- "inbox": "https://mastodon.madrid/users/felix/inbox",
- "outbox": "https://mastodon.madrid/users/felix/outbox",
- "featured": "https://mastodon.madrid/users/felix/collections/featured",
- "preferredUsername": "felix",
- "name": "",
- "summary": "<p><a href=\"https://mastodon.madrid/tags/Lemmy\" class=\"mention hashtag\" rel=\"tag\">#<span>Lemmy</span></a> Maintainer</p>",
- "url": "https://mastodon.madrid/@felix",
+ "following": "https://masto.qa.urbanwildlife.biz/users/mastodon/following",
+ "followers": "https://masto.qa.urbanwildlife.biz/users/mastodon/followers",
+ "inbox": "https://masto.qa.urbanwildlife.biz/users/mastodon/inbox",
+ "outbox": "https://masto.qa.urbanwildlife.biz/users/mastodon/outbox",
+ "featured": "https://masto.qa.urbanwildlife.biz/users/mastodon/collections/featured",
+ "featuredTags": "https://masto.qa.urbanwildlife.biz/users/mastodon/collections/tags",
+ "preferredUsername": "mastodon",
+ "name": "Mastodon",
+ "summary": "",
+ "url": "https://masto.qa.urbanwildlife.biz/@mastodon",
"manuallyApprovesFollowers": false,
"discoverable": false,
- "devices": "https://mastodon.madrid/users/felix/collections/devices",
+ "published": "2022-10-03T00:00:00Z",
+ "devices": "https://masto.qa.urbanwildlife.biz/users/mastodon/collections/devices",
"publicKey": {
- "id": "https://mastodon.madrid/users/felix#main-key",
- "owner": "https://mastodon.madrid/users/felix",
- "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzc+evQS6XHTUdniPmFfH\n0U6aa4NaGSTQY4fmJna9w9Sr/8nNN4XWbGJLD4kawPxAXMbK63RMkkxvaHI9w+Oe\nd6oIJH2Z5qH4s2eX8f610SGDvyEZltLAY8TkMhNEp+3bOCKf1zG/uCsE7uC6Mjal\nd6KYyqoom5TwO2UWH5r6l3vyLFvnXWX2zOgSWJwLNLxMWkkd9AqM7k9+pgmeaNWD\n6JvG7Na5ywsR4CZrE5PjgtiC9LWP/H3Elgb2nIzye5HUEJuK2h1+eNFP3HSK5CF3\ncrg4DsZ1n5X3fQVm5YmFUYtEMLZL5S18dFsp6uwE0TmVOODJdnJ6+cgu0/8t2ROR\nJQIDAQAB\n-----END PUBLIC KEY-----\n"
+ "id": "https://masto.qa.urbanwildlife.biz/users/mastodon#main-key",
+ "owner": "https://masto.qa.urbanwildlife.biz/users/mastodon",
+ "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBdE55VmV9gTrhJmRF1K\neX7xTRo17JGQ7d1/KJWsQ1zH62GGeG/E+BG3h/BRtfgI7Z9jwfNEyx8g/Ue8rSeZ\n3M7yc09/Z90uwGVY24hxwAJyzWIN2cv5ayhdtk268byT6NX98a9PQcHlx5i6Bhef\nMlpY73I5gxYlofvwJTHq/VupXVw9K76KId2AgR2z8tLiXPc8TED56HulDWdMlWn3\n9B4mWNYmzMBF7lOl58Ws6bFsiv8GnI3uEywzUGhXqz4242FGveHdAGBaCpUYrm8W\nmT8PArqv3B4fCD1ghakSmxRr3y9clwhkC+kB/aoT6z313uZYbQuvZF1bfbh6EZWm\nIQIDAQAB\n-----END PUBLIC KEY-----\n"
},
- "tag": [
- {
- "type": "Hashtag",
- "href": "https://mastodon.madrid/explore/lemmy",
- "name": "#lemmy"
- }
- ],
+ "tag": [],
"attachment": [],
"endpoints": {
- "sharedInbox": "https://mastodon.madrid/inbox"
+ "sharedInbox": "https://masto.qa.urbanwildlife.biz/inbox"
},
"icon": {
"type": "Image",
- "mediaType": "image/jpeg",
- "url": "https://mastodon.madrid/system/accounts/avatars/000/087/969/original/ffdd1c832b453bc9.jpg?1598972149"
+ "mediaType": "image/png",
+ "url": "https://masto.qa.urbanwildlife.biz/system/accounts/avatars/109/105/103/301/739/269/original/2cf61ff96e94cb1d.png"
}
}
context::LemmyContext,
post::{CreatePostReport, PostReportResponse},
utils::local_user_view_from_jwt,
- websocket::UserOperation,
};
use lemmy_db_schema::{
source::{
},
traits::Reportable,
};
-use lemmy_db_views::structs::{CommentReportView, PostReportView};
use lemmy_utils::error::LemmyError;
use url::Url;
reason: self.summary,
original_post_body: post.body.clone(),
};
-
- let report = PostReport::report(context.pool(), &report_form).await?;
-
- let post_report_view = PostReportView::read(context.pool(), report.id, actor.id).await?;
-
- context.send_mod_ws_message(
- &UserOperation::CreateCommentReport,
- &PostReportResponse { post_report_view },
- post.community_id,
- None,
- )?;
+ PostReport::report(context.pool(), &report_form).await?;
}
PostOrComment::Comment(comment) => {
let report_form = CommentReportForm {
original_comment_text: comment.content.clone(),
reason: self.summary,
};
-
- let report = CommentReport::report(context.pool(), &report_form).await?;
-
- let comment_report_view =
- CommentReportView::read(context.pool(), report.id, actor.id).await?;
- let community_id = comment_report_view.community.id;
-
- context.send_mod_ws_message(
- &UserOperation::CreateCommentReport,
- &CommentReportResponse {
- comment_report_view,
- },
- community_id,
- None,
- )?;
+ CommentReport::report(context.pool(), &report_form).await?;
}
};
Ok(())
community::{CommunityResponse, EditCommunity, HideCommunity},
context::LemmyContext,
utils::local_user_view_from_jwt,
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{source::community::Community, traits::Crud};
use lemmy_utils::error::LemmyError;
let community_update_form = self.object.into_update_form();
- let updated_community =
- Community::update(context.pool(), community.id, &community_update_form).await?;
-
- context
- .send_community_ws_message(
- &UserOperationCrud::EditCommunity,
- updated_community.id,
- None,
- None,
- )
- .await?;
+ Community::update(context.pool(), community.id, &community_update_form).await?;
Ok(())
}
}
activities::{
check_community_deleted_or_removed,
community::send_activity_in_community,
- create_or_update::get_comment_notif_recipients,
generate_activity_id,
verify_is_public,
verify_person_in_community,
traits::{ActivityHandler, Actor, Object},
};
use lemmy_api_common::{
+ build_response::send_local_notifs,
comment::{CommentResponse, CreateComment, EditComment},
context::LemmyContext,
utils::{check_post_deleted_or_removed, is_mod_or_admin},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
newtypes::PersonId,
},
traits::{Crud, Likeable},
};
-use lemmy_utils::error::LemmyError;
+use lemmy_utils::{error::LemmyError, utils::mention::scrape_text_for_mentions};
use url::Url;
#[async_trait::async_trait]
CommentLike::like(context.pool(), &like_form).await?;
let do_send_email = self.kind == CreateOrUpdateType::Create;
- let recipients =
- get_comment_notif_recipients(&self.actor, &comment, do_send_email, context).await?;
- let notif_type = match self.kind {
- CreateOrUpdateType::Create => UserOperationCrud::CreateComment,
- CreateOrUpdateType::Update => UserOperationCrud::EditComment,
- };
- context
- .send_comment_ws_message(¬if_type, comment.id, None, None, None, recipients)
- .await?;
+ let post_id = comment.post_id;
+ let post = Post::read(context.pool(), post_id).await?;
+ let actor = self.actor.dereference(context).await?;
+
+ // Note:
+ // Although mentions could be gotten from the post tags (they are included there), or the ccs,
+ // Its much easier to scrape them from the comment body, since the API has to do that
+ // anyway.
+ // TODO: for compatibility with other projects, it would be much better to read this from cc or tags
+ let mentions = scrape_text_for_mentions(&comment.content);
+ send_local_notifs(mentions, &comment.0, &actor, &post, do_send_email, context).await?;
Ok(())
}
}
-use crate::objects::person::ApubPerson;
-use activitypub_federation::{config::Data, fetch::object_id::ObjectId};
-use lemmy_api_common::context::LemmyContext;
-use lemmy_db_schema::{
- newtypes::LocalUserId,
- source::{comment::Comment, post::Post},
- traits::Crud,
-};
-use lemmy_utils::{error::LemmyError, utils::mention::scrape_text_for_mentions};
-
pub mod comment;
pub mod post;
pub mod private_message;
-
-#[tracing::instrument(skip_all)]
-async fn get_comment_notif_recipients(
- actor: &ObjectId<ApubPerson>,
- comment: &Comment,
- do_send_email: bool,
- context: &Data<LemmyContext>,
-) -> Result<Vec<LocalUserId>, LemmyError> {
- let post_id = comment.post_id;
- let post = Post::read(context.pool(), post_id).await?;
- let actor = actor.dereference(context).await?;
-
- // Note:
- // Although mentions could be gotten from the post tags (they are included there), or the ccs,
- // Its much easier to scrape them from the comment body, since the API has to do that
- // anyway.
- // TODO: for compatibility with other projects, it would be much better to read this from cc or tags
- let mentions = scrape_text_for_mentions(&comment.content);
- context
- .send_local_notifs(mentions, comment, &actor, &post, do_send_email)
- .await
-}
use lemmy_api_common::{
context::LemmyContext,
post::{CreatePost, EditPost, PostResponse},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
newtypes::PersonId,
score: 1,
};
PostLike::like(context.pool(), &like_form).await?;
-
- let notif_type = match self.kind {
- CreateOrUpdateType::Create => UserOperationCrud::CreatePost,
- CreateOrUpdateType::Update => UserOperationCrud::EditPost,
- };
- context
- .send_post_ws_message(¬if_type, post.id, None, None)
- .await?;
Ok(())
}
}
use lemmy_api_common::{
context::LemmyContext,
private_message::{CreatePrivateMessage, EditPrivateMessage, PrivateMessageResponse},
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
newtypes::PersonId,
#[tracing::instrument(skip_all)]
async fn receive(self, context: &Data<Self::DataType>) -> Result<(), LemmyError> {
insert_activity(&self.id, &self, false, true, context).await?;
- let private_message = ApubPrivateMessage::from_json(self.object, context).await?;
-
- let notif_type = match self.kind {
- CreateOrUpdateType::Create => UserOperationCrud::CreatePrivateMessage,
- CreateOrUpdateType::Update => UserOperationCrud::EditPrivateMessage,
- };
- context
- .send_pm_ws_message(¬if_type, private_message.id, None)
- .await?;
-
+ ApubPrivateMessage::from_json(self.object, context).await?;
Ok(())
}
}
protocol::{activities::deletion::delete::Delete, IdOrNestedObject},
};
use activitypub_federation::{config::Data, kinds::activity::DeleteType, traits::ActivityHandler};
-use lemmy_api_common::{context::LemmyContext, websocket::UserOperationCrud};
+use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::{
source::{
comment::{Comment, CommentUpdateForm},
reason: Option<String>,
context: &Data<LemmyContext>,
) -> Result<(), LemmyError> {
- use UserOperationCrud::*;
match DeletableObjects::read_from_db(object, context).await? {
DeletableObjects::Community(community) => {
if community.local {
expires: None,
};
ModRemoveCommunity::create(context.pool(), &form).await?;
- let deleted_community = Community::update(
+ Community::update(
context.pool(),
community.id,
&CommunityUpdateForm::builder().removed(Some(true)).build(),
)
.await?;
-
- context
- .send_community_ws_message(&RemoveCommunity, deleted_community.id, None, None)
- .await?;
}
DeletableObjects::Post(post) => {
let form = ModRemovePostForm {
reason,
};
ModRemovePost::create(context.pool(), &form).await?;
- let removed_post = Post::update(
+ Post::update(
context.pool(),
post.id,
&PostUpdateForm::builder().removed(Some(true)).build(),
)
.await?;
-
- context
- .send_post_ws_message(&RemovePost, removed_post.id, None, None)
- .await?;
}
DeletableObjects::Comment(comment) => {
let form = ModRemoveCommentForm {
reason,
};
ModRemoveComment::create(context.pool(), &form).await?;
- let removed_comment = Comment::update(
+ Comment::update(
context.pool(),
comment.id,
&CommentUpdateForm::builder().removed(Some(true)).build(),
)
.await?;
-
- context
- .send_comment_ws_message_simple(&RemoveComment, removed_comment.id)
- .await?;
}
DeletableObjects::PrivateMessage(_) => unimplemented!(),
}
post::{DeletePost, PostResponse, RemovePost},
private_message::{DeletePrivateMessage, PrivateMessageResponse},
utils::local_user_view_from_jwt,
- websocket::UserOperationCrud,
};
use lemmy_db_schema::{
source::{
send_apub_delete_in_community(mod_, c, object, None, true, context).await?;
}
- let community = Community::update(
+ Community::update(
context.pool(),
community.id,
&CommunityUpdateForm::builder()
.build(),
)
.await?;
- context
- .send_community_ws_message(
- &UserOperationCrud::DeleteCommunity,
- community.id,
- None,
- None,
- )
- .await?;
}
DeletableObjects::Post(post) => {
if deleted != post.deleted {
- let deleted_post = Post::update(
+ Post::update(
context.pool(),
post.id,
&PostUpdateForm::builder().deleted(Some(deleted)).build(),
)
.await?;
- context
- .send_post_ws_message(&UserOperationCrud::DeletePost, deleted_post.id, None, None)
- .await?;
}
}
DeletableObjects::Comment(comment) => {
if deleted != comment.deleted {
- let deleted_comment = Comment::update(
+ Comment::update(
context.pool(),
comment.id,
&CommentUpdateForm::builder().deleted(Some(deleted)).build(),
)
.await?;
- context
- .send_comment_ws_message_simple(&UserOperationCrud::DeleteComment, deleted_comment.id)
- .await?;
}
}
DeletableObjects::PrivateMessage(pm) => {
- let deleted_private_message = PrivateMessage::update(
+ PrivateMessage::update(
context.pool(),
pm.id,
&PrivateMessageUpdateForm::builder()
.build(),
)
.await?;
-
- context
- .send_pm_ws_message(
- &UserOperationCrud::DeletePrivateMessage,
- deleted_private_message.id,
- None,
- )
- .await?;
}
}
Ok(())
protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
};
use activitypub_federation::{config::Data, kinds::activity::UndoType, traits::ActivityHandler};
-use lemmy_api_common::{context::LemmyContext, websocket::UserOperationCrud};
+use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::{
source::{
comment::{Comment, CommentUpdateForm},
object: &Url,
context: &Data<LemmyContext>,
) -> Result<(), LemmyError> {
- use UserOperationCrud::*;
match DeletableObjects::read_from_db(object, context).await? {
DeletableObjects::Community(community) => {
if community.local {
expires: None,
};
ModRemoveCommunity::create(context.pool(), &form).await?;
- let deleted_community = Community::update(
+ Community::update(
context.pool(),
community.id,
&CommunityUpdateForm::builder().removed(Some(false)).build(),
)
.await?;
- context
- .send_community_ws_message(&EditCommunity, deleted_community.id, None, None)
- .await?;
}
DeletableObjects::Post(post) => {
let form = ModRemovePostForm {
reason: None,
};
ModRemovePost::create(context.pool(), &form).await?;
- let removed_post = Post::update(
+ Post::update(
context.pool(),
post.id,
&PostUpdateForm::builder().removed(Some(false)).build(),
)
.await?;
- context
- .send_post_ws_message(&EditPost, removed_post.id, None, None)
- .await?;
}
DeletableObjects::Comment(comment) => {
let form = ModRemoveCommentForm {
reason: None,
};
ModRemoveComment::create(context.pool(), &form).await?;
- let removed_comment = Comment::update(
+ Comment::update(
context.pool(),
comment.id,
&CommentUpdateForm::builder().removed(Some(false)).build(),
)
.await?;
- context
- .send_comment_ws_message_simple(&EditComment, removed_comment.id)
- .await?;
}
DeletableObjects::PrivateMessage(_) => unimplemented!(),
}
protocol::verification::verify_urls_match,
traits::{ActivityHandler, Actor},
};
-use lemmy_api_common::{
- community::CommunityResponse,
- context::LemmyContext,
- websocket::{
- handlers::messages::SendUserRoomMessage,
- serialize_websocket_message,
- UserOperation,
- },
-};
-use lemmy_db_schema::{
- source::{actor_language::CommunityLanguage, community::CommunityFollower},
- traits::Followable,
-};
-use lemmy_db_views::structs::LocalUserView;
-use lemmy_db_views_actor::structs::CommunityView;
+use lemmy_api_common::context::LemmyContext;
+use lemmy_db_schema::{source::community::CommunityFollower, traits::Followable};
use lemmy_utils::error::LemmyError;
use url::Url;
let person_id = person.id;
CommunityFollower::follow_accepted(context.pool(), community_id, person_id).await?;
- // Send the Subscribed message over websocket
- // Re-read the community_view to get the new SubscribedType
- let community_view =
- CommunityView::read(context.pool(), community_id, Some(person_id), None).await?;
-
- // Get the local_user_id
- let local_recipient_id = LocalUserView::read_person(context.pool(), person_id)
- .await?
- .local_user
- .id;
- let discussion_languages = CommunityLanguage::read(context.pool(), community_id).await?;
-
- let res = CommunityResponse {
- community_view,
- discussion_languages,
- };
-
- let message = serialize_websocket_message(&UserOperation::FollowCommunity, &res)?;
-
- context.chat_server().do_send(SendUserRoomMessage {
- recipient_id: local_recipient_id,
- message,
- websocket_id: None,
- });
-
Ok(())
}
}
SearchResponse,
SiteResponse,
},
- websocket::structs::{
- CommunityJoin,
- CommunityJoinResponse,
- ModJoin,
- ModJoinResponse,
- PostJoin,
- PostJoinResponse,
- UserJoin,
- UserJoinResponse,
- },
};
impl SendActivity for Register {
type Response = LoginResponse;
}
-impl SendActivity for UserJoin {
- type Response = UserJoinResponse;
-}
-
-impl SendActivity for PostJoin {
- type Response = PostJoinResponse;
-}
-
-impl SendActivity for CommunityJoin {
- type Response = CommunityJoinResponse;
-}
-
-impl SendActivity for ModJoin {
- type Response = ModJoinResponse;
-}
-
impl SendActivity for SaveUserSettings {
type Response = LoginResponse;
}
post::{CreatePostLike, PostResponse},
sensitive::Sensitive,
utils::local_user_view_from_jwt,
- websocket::UserOperation,
};
use lemmy_db_schema::{
newtypes::CommunityId,
let person_id = actor.id;
CommentLike::remove(context.pool(), person_id, comment_id).await?;
CommentLike::like(context.pool(), &like_form).await?;
-
- context
- .send_comment_ws_message_simple(&UserOperation::CreateCommentLike, comment_id)
- .await?;
Ok(())
}
let person_id = actor.id;
PostLike::remove(context.pool(), person_id, post_id).await?;
PostLike::like(context.pool(), &like_form).await?;
-
- context
- .send_post_ws_message(&UserOperation::CreatePostLike, post.id, None, None)
- .await?;
Ok(())
}
let comment_id = comment.id;
let person_id = actor.id;
CommentLike::remove(context.pool(), person_id, comment_id).await?;
-
- context
- .send_comment_ws_message_simple(&UserOperation::CreateCommentLike, comment_id)
- .await?;
Ok(())
}
let post_id = post.id;
let person_id = actor.id;
PostLike::remove(context.pool(), person_id, post_id).await?;
-
- context
- .send_post_ws_message(&UserOperation::CreatePostLike, post_id, None, None)
- .await?;
Ok(())
}
traits::Crud,
};
use lemmy_db_views::comment_view::CommentQuery;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait]
impl PerformApub for GetComments {
type Response = GetCommentsResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<GetCommentsResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetCommentsResponse, LemmyError> {
let data: &GetComments = self;
let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), context).await;
let local_site = LocalSite::read(context.pool()).await?;
};
use lemmy_db_schema::source::{community::Community, local_site::LocalSite};
use lemmy_db_views::post_view::PostQuery;
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait]
impl PerformApub for GetPosts {
type Response = GetPostsResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<GetPostsResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<GetPostsResponse, LemmyError> {
let data: &GetPosts = self;
let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), context).await;
let local_site = LocalSite::read(context.pool()).await?;
use activitypub_federation::config::Data;
use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::{newtypes::CommunityId, source::local_site::LocalSite, ListingType};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
mod list_comments;
mod list_posts;
pub trait PerformApub {
type Response: serde::ser::Serialize + Send;
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<Self::Response, LemmyError>;
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError>;
}
/// Returns default listing type, depending if the query is for frontpage or community.
community::{GetCommunity, GetCommunityResponse},
context::LemmyContext,
utils::{check_private_instance, is_mod_or_admin_opt, local_user_view_from_jwt_opt},
- websocket::handlers::online_users::GetCommunityUsersOnline,
};
use lemmy_db_schema::source::{
actor_language::CommunityLanguage,
site::Site,
};
use lemmy_db_views_actor::structs::{CommunityModeratorView, CommunityView};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait]
impl PerformApub for GetCommunity {
type Response = GetCommunityResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<GetCommunityResponse, LemmyError> {
let data: &GetCommunity = self;
let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), context).await;
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
- let online = context
- .chat_server()
- .send(GetCommunityUsersOnline { community_id })
- .await?;
-
let site_id =
Site::instance_actor_id_from_url(community_view.community.actor_id.clone().into());
let mut site = Site::read_from_apub_id(context.pool(), &site_id.into()).await?;
community_view,
site,
moderators,
- online,
discussion_languages,
};
};
use lemmy_db_views::{comment_view::CommentQuery, post_view::PostQuery};
use lemmy_db_views_actor::structs::{CommunityModeratorView, PersonView};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait]
impl PerformApub for GetPersonDetails {
type Response = GetPersonDetailsResponse;
- #[tracing::instrument(skip(self, context, _websocket_id))]
+ #[tracing::instrument(skip(self, context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<GetPersonDetailsResponse, LemmyError> {
let data: &GetPersonDetails = self;
use lemmy_db_schema::{newtypes::PersonId, source::local_site::LocalSite, utils::DbPool};
use lemmy_db_views::structs::{CommentView, PostView};
use lemmy_db_views_actor::structs::{CommunityView, PersonView};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait]
impl PerformApub for ResolveObject {
type Response = ResolveObjectResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
+ #[tracing::instrument(skip(context))]
async fn perform(
&self,
context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
) -> Result<ResolveObjectResponse, LemmyError> {
let local_user_view = local_user_view_from_jwt(&self.auth, context).await?;
let local_site = LocalSite::read(context.pool()).await?;
};
use lemmy_db_views::{comment_view::CommentQuery, post_view::PostQuery};
use lemmy_db_views_actor::{community_view::CommunityQuery, person_view::PersonQuery};
-use lemmy_utils::{error::LemmyError, ConnectionId};
+use lemmy_utils::error::LemmyError;
#[async_trait::async_trait]
impl PerformApub for Search {
type Response = SearchResponse;
- #[tracing::instrument(skip(context, _websocket_id))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- _websocket_id: Option<ConnectionId>,
- ) -> Result<SearchResponse, LemmyError> {
+ #[tracing::instrument(skip(context))]
+ async fn perform(&self, context: &Data<LemmyContext>) -> Result<SearchResponse, LemmyError> {
let data: &Search = self;
let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), context).await;
#[cfg(test)]
pub(crate) mod tests {
use activitypub_federation::config::{Data, FederationConfig};
- use actix::Actor;
use anyhow::anyhow;
- use lemmy_api_common::{
- context::LemmyContext,
- request::build_user_agent,
- websocket::chat_server::ChatServer,
- };
+ use lemmy_api_common::{context::LemmyContext, request::build_user_agent};
use lemmy_db_schema::{source::secret::Secret, utils::build_db_pool_for_tests};
use lemmy_utils::{
rate_limit::{RateLimitCell, RateLimitConfig},
let rate_limit_config = RateLimitConfig::builder().build();
let rate_limit_cell = RateLimitCell::new(rate_limit_config).await;
- let chat_server = ChatServer::default().start();
- let context = LemmyContext::create(pool, chat_server, client, secret, rate_limit_cell.clone());
+ let context = LemmyContext::create(pool, client, secret, rate_limit_cell.clone());
let config = FederationConfig::builder()
.domain("example.com")
.app_data(context)
ChangePassword,
DeleteAccount,
GetBannedPersons,
- GetCaptcha,
GetPersonDetails,
GetPersonMentions,
GetReplies,
ResolveObject,
Search,
},
- websocket::structs::{CommunityJoin, ModJoin, PostJoin, UserJoin},
};
use lemmy_api_crud::PerformCrud;
use lemmy_apub::{api::PerformApub, SendActivity};
)
.route("/transfer", web::post().to(route_post::<TransferCommunity>))
.route("/ban_user", web::post().to(route_post::<BanFromCommunity>))
- .route("/mod", web::post().to(route_post::<AddModToCommunity>))
- .route("/join", web::post().to(route_post::<CommunityJoin>))
- .route("/mod/join", web::post().to(route_post::<ModJoin>)),
+ .route("/mod", web::post().to(route_post::<AddModToCommunity>)),
)
.service(
web::scope("/federated_instances")
.route("/list", web::get().to(route_get_apub::<GetPosts>))
.route("/like", web::post().to(route_post::<CreatePostLike>))
.route("/save", web::put().to(route_post::<SavePost>))
- .route("/join", web::post().to(route_post::<PostJoin>))
.route("/report", web::post().to(route_post::<CreatePostReport>))
.route(
"/report/resolve",
.wrap(rate_limit.register())
.route(web::post().to(route_post_crud::<Register>)),
)
- .service(
- // Handle captcha separately
- web::resource("/user/get_captcha")
- .wrap(rate_limit.post())
- .route(web::get().to(route_get::<GetCaptcha>)),
- )
// User actions
.service(
web::scope("/user")
web::post().to(route_post::<MarkPersonMentionAsRead>),
)
.route("/replies", web::get().to(route_get::<GetReplies>))
- .route("/join", web::post().to(route_post::<UserJoin>))
// Admin action. I don't like that it's in /user
.route("/ban", web::post().to(route_post::<BanPerson>))
.route("/banned", web::get().to(route_get::<GetBannedPersons>))
+ Send
+ 'static,
{
- let res = data.perform(&context, None).await?;
+ let res = data.perform(&context).await?;
SendActivity::send_activity(&data, &res, &apub_data).await?;
Ok(HttpResponse::Ok().json(res))
}
+ Send
+ 'static,
{
- let res = data.perform(&context, None).await?;
+ let res = data.perform(&context).await?;
SendActivity::send_activity(&data.0, &res, &context).await?;
Ok(HttpResponse::Ok().json(res))
}
+ Send
+ 'static,
{
- let res = data.perform(&context, None).await?;
+ let res = data.perform(&context).await?;
SendActivity::send_activity(&data, &res, &apub_data).await?;
Ok(HttpResponse::Ok().json(res))
}
use crate::{code_migrations::run_advanced_migrations, root_span_builder::QuieterRootSpanBuilder};
use activitypub_federation::config::{FederationConfig, FederationMiddleware};
-use actix::Actor;
use actix_cors::Cors;
use actix_web::{middleware, web::Data, App, HttpServer, Result};
use doku::json::{AutoComments, CommentsStyle, Formatting, ObjectsStyle};
check_private_instance_and_federation_enabled,
local_site_rate_limit_to_rate_limit_config,
},
- websocket::chat_server::ChatServer,
};
use lemmy_apub::{VerifyUrlData, FEDERATION_HTTP_FETCH_LIMIT};
use lemmy_db_schema::{
scheduled_tasks::setup(db_url, user_agent).expect("Couldn't set up scheduled_tasks");
});
- let chat_server = ChatServer::default().start();
-
// Create Http server with websocket support
let settings_bind = settings.clone();
HttpServer::new(move || {
let context = LemmyContext::create(
pool.clone(),
- chat_server.clone(),
client.clone(),
secret.clone(),
rate_limit_cell.clone(),