Added comment delete, remove, read.
This commit is contained in:
parent
ca7d2feedb
commit
fd96dfdb5e
20 changed files with 626 additions and 279 deletions
96
docs/src/contributing_websocket_http_api.md
vendored
96
docs/src/contributing_websocket_http_api.md
vendored
|
@ -1448,7 +1448,6 @@ Mods and admins can remove and lock a post, creators can delete it.
|
||||||
data: {
|
data: {
|
||||||
content: String,
|
content: String,
|
||||||
parent_id: Option<i32>,
|
parent_id: Option<i32>,
|
||||||
edit_id: Option<i32>,
|
|
||||||
post_id: i32,
|
post_id: i32,
|
||||||
auth: String
|
auth: String
|
||||||
}
|
}
|
||||||
|
@ -1470,7 +1469,7 @@ Mods and admins can remove and lock a post, creators can delete it.
|
||||||
|
|
||||||
#### Edit Comment
|
#### Edit Comment
|
||||||
|
|
||||||
Mods and admins can remove a comment, creators can delete it.
|
Only the creator can edit the comment.
|
||||||
|
|
||||||
##### Request
|
##### Request
|
||||||
```rust
|
```rust
|
||||||
|
@ -1478,15 +1477,8 @@ Mods and admins can remove a comment, creators can delete it.
|
||||||
op: "EditComment",
|
op: "EditComment",
|
||||||
data: {
|
data: {
|
||||||
content: String,
|
content: String,
|
||||||
parent_id: Option<i32>,
|
|
||||||
edit_id: i32,
|
edit_id: i32,
|
||||||
creator_id: i32,
|
auth: String,
|
||||||
post_id: i32,
|
|
||||||
removed: Option<bool>,
|
|
||||||
deleted: Option<bool>,
|
|
||||||
reason: Option<String>,
|
|
||||||
read: Option<bool>,
|
|
||||||
auth: String
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -1503,6 +1495,89 @@ Mods and admins can remove a comment, creators can delete it.
|
||||||
|
|
||||||
`PUT /comment`
|
`PUT /comment`
|
||||||
|
|
||||||
|
#### Delete Comment
|
||||||
|
|
||||||
|
Only the creator can delete the comment.
|
||||||
|
|
||||||
|
##### Request
|
||||||
|
```rust
|
||||||
|
{
|
||||||
|
op: "DeleteComment",
|
||||||
|
data: {
|
||||||
|
edit_id: i32,
|
||||||
|
deleted: bool,
|
||||||
|
auth: String,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
##### Response
|
||||||
|
```rust
|
||||||
|
{
|
||||||
|
op: "DeleteComment",
|
||||||
|
data: {
|
||||||
|
comment: CommentView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
##### HTTP
|
||||||
|
|
||||||
|
`POST /comment/delete`
|
||||||
|
|
||||||
|
|
||||||
|
#### Remove Comment
|
||||||
|
|
||||||
|
Only a mod or admin can remove the comment.
|
||||||
|
|
||||||
|
##### Request
|
||||||
|
```rust
|
||||||
|
{
|
||||||
|
op: "RemoveComment",
|
||||||
|
data: {
|
||||||
|
edit_id: i32,
|
||||||
|
removed: bool,
|
||||||
|
reason: Option<String>,
|
||||||
|
auth: String,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
##### Response
|
||||||
|
```rust
|
||||||
|
{
|
||||||
|
op: "RemoveComment",
|
||||||
|
data: {
|
||||||
|
comment: CommentView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
##### HTTP
|
||||||
|
|
||||||
|
`POST /comment/remove`
|
||||||
|
|
||||||
|
#### Mark Comment as Read
|
||||||
|
##### Request
|
||||||
|
```rust
|
||||||
|
{
|
||||||
|
op: "MarkCommentAsRead",
|
||||||
|
data: {
|
||||||
|
edit_id: i32,
|
||||||
|
read: bool,
|
||||||
|
auth: String,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
##### Response
|
||||||
|
```rust
|
||||||
|
{
|
||||||
|
op: "MarkCommentAsRead",
|
||||||
|
data: {
|
||||||
|
comment: CommentView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
##### HTTP
|
||||||
|
|
||||||
|
`POST /comment/mark_as_read`
|
||||||
|
|
||||||
#### Save Comment
|
#### Save Comment
|
||||||
##### Request
|
##### Request
|
||||||
```rust
|
```rust
|
||||||
|
@ -1538,7 +1613,6 @@ Mods and admins can remove a comment, creators can delete it.
|
||||||
op: "CreateCommentLike",
|
op: "CreateCommentLike",
|
||||||
data: {
|
data: {
|
||||||
comment_id: i32,
|
comment_id: i32,
|
||||||
post_id: i32,
|
|
||||||
score: i16,
|
score: i16,
|
||||||
auth: String
|
auth: String
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,14 +97,6 @@ impl Comment {
|
||||||
comment.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
comment.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mark_as_read(conn: &PgConnection, comment_id: i32) -> Result<Self, Error> {
|
|
||||||
use crate::schema::comment::dsl::*;
|
|
||||||
|
|
||||||
diesel::update(comment.find(comment_id))
|
|
||||||
.set(read.eq(true))
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn permadelete(conn: &PgConnection, comment_id: i32) -> Result<Self, Error> {
|
pub fn permadelete(conn: &PgConnection, comment_id: i32) -> Result<Self, Error> {
|
||||||
use crate::schema::comment::dsl::*;
|
use crate::schema::comment::dsl::*;
|
||||||
|
|
||||||
|
@ -116,6 +108,46 @@ impl Comment {
|
||||||
))
|
))
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_deleted(
|
||||||
|
conn: &PgConnection,
|
||||||
|
comment_id: i32,
|
||||||
|
new_deleted: bool,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
use crate::schema::comment::dsl::*;
|
||||||
|
diesel::update(comment.find(comment_id))
|
||||||
|
.set(deleted.eq(new_deleted))
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_removed(
|
||||||
|
conn: &PgConnection,
|
||||||
|
comment_id: i32,
|
||||||
|
new_removed: bool,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
use crate::schema::comment::dsl::*;
|
||||||
|
diesel::update(comment.find(comment_id))
|
||||||
|
.set(removed.eq(new_removed))
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_read(conn: &PgConnection, comment_id: i32, new_read: bool) -> Result<Self, Error> {
|
||||||
|
use crate::schema::comment::dsl::*;
|
||||||
|
diesel::update(comment.find(comment_id))
|
||||||
|
.set(read.eq(new_read))
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_content(
|
||||||
|
conn: &PgConnection,
|
||||||
|
comment_id: i32,
|
||||||
|
new_content: &str,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
use crate::schema::comment::dsl::*;
|
||||||
|
diesel::update(comment.find(comment_id))
|
||||||
|
.set((content.eq(new_content), updated.eq(naive_now())))
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug, Clone)]
|
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug, Clone)]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
|
naive_now,
|
||||||
schema::{community, community_follower, community_moderator, community_user_ban},
|
schema::{community, community_follower, community_moderator, community_user_ban},
|
||||||
Bannable,
|
Bannable,
|
||||||
Crud,
|
Crud,
|
||||||
|
@ -29,7 +30,6 @@ pub struct Community {
|
||||||
pub last_refreshed_at: chrono::NaiveDateTime,
|
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO add better delete, remove, lock actions here.
|
|
||||||
#[derive(Insertable, AsChangeset, Clone, Serialize, Deserialize, Debug)]
|
#[derive(Insertable, AsChangeset, Clone, Serialize, Deserialize, Debug)]
|
||||||
#[table_name = "community"]
|
#[table_name = "community"]
|
||||||
pub struct CommunityForm {
|
pub struct CommunityForm {
|
||||||
|
@ -129,9 +129,24 @@ impl Community {
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
use crate::schema::community::dsl::*;
|
use crate::schema::community::dsl::*;
|
||||||
diesel::update(community.find(community_id))
|
diesel::update(community.find(community_id))
|
||||||
.set(creator_id.eq(new_creator_id))
|
.set((creator_id.eq(new_creator_id), updated.eq(naive_now())))
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn community_mods_and_admins(
|
||||||
|
conn: &PgConnection,
|
||||||
|
community_id: i32,
|
||||||
|
) -> Result<Vec<i32>, Error> {
|
||||||
|
use crate::{community_view::CommunityModeratorView, user_view::UserView};
|
||||||
|
let mut mods_and_admins: Vec<i32> = Vec::new();
|
||||||
|
mods_and_admins.append(
|
||||||
|
&mut CommunityModeratorView::for_community(conn, community_id)
|
||||||
|
.map(|v| v.into_iter().map(|m| m.user_id).collect())?,
|
||||||
|
);
|
||||||
|
mods_and_admins
|
||||||
|
.append(&mut UserView::admins(conn).map(|v| v.into_iter().map(|a| a.id).collect())?);
|
||||||
|
Ok(mods_and_admins)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
|
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{schema::private_message, Crud};
|
use crate::{naive_now, schema::private_message, Crud};
|
||||||
use diesel::{dsl::*, result::Error, *};
|
use diesel::{dsl::*, result::Error, *};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ impl PrivateMessage {
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
use crate::schema::private_message::dsl::*;
|
use crate::schema::private_message::dsl::*;
|
||||||
diesel::update(private_message.find(private_message_id))
|
diesel::update(private_message.find(private_message_id))
|
||||||
.set(content.eq(new_content))
|
.set((content.eq(new_content), updated.eq(naive_now())))
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,14 +13,13 @@ use crate::{
|
||||||
use lemmy_db::{
|
use lemmy_db::{
|
||||||
comment::*,
|
comment::*,
|
||||||
comment_view::*,
|
comment_view::*,
|
||||||
|
community::Community,
|
||||||
community_view::*,
|
community_view::*,
|
||||||
moderator::*,
|
moderator::*,
|
||||||
naive_now,
|
|
||||||
post::*,
|
post::*,
|
||||||
site_view::*,
|
site_view::*,
|
||||||
user::*,
|
user::*,
|
||||||
user_mention::*,
|
user_mention::*,
|
||||||
user_view::*,
|
|
||||||
Crud,
|
Crud,
|
||||||
Likeable,
|
Likeable,
|
||||||
ListingType,
|
ListingType,
|
||||||
|
@ -44,7 +43,6 @@ use std::str::FromStr;
|
||||||
pub struct CreateComment {
|
pub struct CreateComment {
|
||||||
content: String,
|
content: String,
|
||||||
parent_id: Option<i32>,
|
parent_id: Option<i32>,
|
||||||
edit_id: Option<i32>, // TODO this isn't used
|
|
||||||
pub post_id: i32,
|
pub post_id: i32,
|
||||||
auth: String,
|
auth: String,
|
||||||
}
|
}
|
||||||
|
@ -52,14 +50,29 @@ pub struct CreateComment {
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct EditComment {
|
pub struct EditComment {
|
||||||
content: String,
|
content: String,
|
||||||
parent_id: Option<i32>, // TODO why are the parent_id, creator_id, post_id, etc fields required? They aren't going to change
|
|
||||||
edit_id: i32,
|
edit_id: i32,
|
||||||
creator_id: i32,
|
auth: String,
|
||||||
pub post_id: i32,
|
}
|
||||||
removed: Option<bool>,
|
|
||||||
deleted: Option<bool>,
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct DeleteComment {
|
||||||
|
edit_id: i32,
|
||||||
|
deleted: bool,
|
||||||
|
auth: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct RemoveComment {
|
||||||
|
edit_id: i32,
|
||||||
|
removed: bool,
|
||||||
reason: Option<String>,
|
reason: Option<String>,
|
||||||
read: Option<bool>,
|
auth: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct MarkCommentAsRead {
|
||||||
|
edit_id: i32,
|
||||||
|
read: bool,
|
||||||
auth: String,
|
auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +92,6 @@ pub struct CommentResponse {
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct CreateCommentLike {
|
pub struct CreateCommentLike {
|
||||||
comment_id: i32,
|
comment_id: i32,
|
||||||
pub post_id: i32,
|
|
||||||
score: i16,
|
score: i16,
|
||||||
auth: String,
|
auth: String,
|
||||||
}
|
}
|
||||||
|
@ -150,6 +162,7 @@ impl Perform for Oper<CreateComment> {
|
||||||
return Err(APIError::err("site_ban").into());
|
return Err(APIError::err("site_ban").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the comment
|
||||||
let comment_form2 = comment_form.clone();
|
let comment_form2 = comment_form.clone();
|
||||||
let inserted_comment =
|
let inserted_comment =
|
||||||
match blocking(pool, move |conn| Comment::create(&conn, &comment_form2)).await? {
|
match blocking(pool, move |conn| Comment::create(&conn, &comment_form2)).await? {
|
||||||
|
@ -157,6 +170,7 @@ impl Perform for Oper<CreateComment> {
|
||||||
Err(_e) => return Err(APIError::err("couldnt_create_comment").into()),
|
Err(_e) => return Err(APIError::err("couldnt_create_comment").into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Necessary to update the ap_id
|
||||||
let inserted_comment_id = inserted_comment.id;
|
let inserted_comment_id = inserted_comment.id;
|
||||||
let updated_comment: Comment = match blocking(pool, move |conn| {
|
let updated_comment: Comment = match blocking(pool, move |conn| {
|
||||||
let apub_id =
|
let apub_id =
|
||||||
|
@ -175,8 +189,15 @@ impl Perform for Oper<CreateComment> {
|
||||||
|
|
||||||
// Scan the comment for user mentions, add those rows
|
// Scan the comment for user mentions, add those rows
|
||||||
let mentions = scrape_text_for_mentions(&comment_form.content);
|
let mentions = scrape_text_for_mentions(&comment_form.content);
|
||||||
let recipient_ids =
|
let recipient_ids = send_local_notifs(
|
||||||
send_local_notifs(mentions, updated_comment.clone(), user.clone(), post, pool).await?;
|
mentions,
|
||||||
|
updated_comment.clone(),
|
||||||
|
user.clone(),
|
||||||
|
post,
|
||||||
|
pool,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// You like your own comment by default
|
// You like your own comment by default
|
||||||
let like_form = CommentLikeForm {
|
let like_form = CommentLikeForm {
|
||||||
|
@ -237,122 +258,34 @@ impl Perform for Oper<EditComment> {
|
||||||
|
|
||||||
let user_id = claims.id;
|
let user_id = claims.id;
|
||||||
|
|
||||||
let user = blocking(pool, move |conn| User_::read(&conn, user_id)).await??;
|
|
||||||
|
|
||||||
let edit_id = data.edit_id;
|
let edit_id = data.edit_id;
|
||||||
let orig_comment =
|
let orig_comment =
|
||||||
blocking(pool, move |conn| CommentView::read(&conn, edit_id, None)).await??;
|
blocking(pool, move |conn| CommentView::read(&conn, edit_id, None)).await??;
|
||||||
|
|
||||||
let mut editors: Vec<i32> = vec![orig_comment.creator_id];
|
// Check for a site ban
|
||||||
let mut moderators: Vec<i32> = vec![];
|
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
|
||||||
|
if user.banned {
|
||||||
let community_id = orig_comment.community_id;
|
return Err(APIError::err("site_ban").into());
|
||||||
moderators.append(
|
|
||||||
&mut blocking(pool, move |conn| {
|
|
||||||
CommunityModeratorView::for_community(&conn, community_id)
|
|
||||||
.map(|v| v.into_iter().map(|m| m.user_id).collect())
|
|
||||||
})
|
|
||||||
.await??,
|
|
||||||
);
|
|
||||||
moderators.append(
|
|
||||||
&mut blocking(pool, move |conn| {
|
|
||||||
UserView::admins(conn).map(|v| v.into_iter().map(|a| a.id).collect())
|
|
||||||
})
|
|
||||||
.await??,
|
|
||||||
);
|
|
||||||
|
|
||||||
editors.extend(&moderators);
|
|
||||||
// You are allowed to mark the comment as read even if you're banned.
|
|
||||||
if data.read.is_none() {
|
|
||||||
// Verify its the creator or a mod, or an admin
|
|
||||||
|
|
||||||
if !editors.contains(&user_id) {
|
|
||||||
return Err(APIError::err("no_comment_edit_allowed").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for a community ban
|
|
||||||
let community_id = orig_comment.community_id;
|
|
||||||
let is_banned =
|
|
||||||
move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
|
|
||||||
if blocking(pool, is_banned).await? {
|
|
||||||
return Err(APIError::err("community_ban").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for a site ban
|
|
||||||
if user.banned {
|
|
||||||
return Err(APIError::err("site_ban").into());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// check that user can mark as read
|
|
||||||
let parent_id = orig_comment.parent_id;
|
|
||||||
match parent_id {
|
|
||||||
Some(pid) => {
|
|
||||||
let parent_comment =
|
|
||||||
blocking(pool, move |conn| CommentView::read(&conn, pid, None)).await??;
|
|
||||||
if user_id != parent_comment.creator_id {
|
|
||||||
return Err(APIError::err("no_comment_edit_allowed").into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
let parent_post_id = orig_comment.post_id;
|
|
||||||
let parent_post = blocking(pool, move |conn| Post::read(conn, parent_post_id)).await??;
|
|
||||||
if user_id != parent_post.creator_id {
|
|
||||||
return Err(APIError::err("no_comment_edit_allowed").into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for a community ban
|
||||||
|
let community_id = orig_comment.community_id;
|
||||||
|
let is_banned =
|
||||||
|
move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
|
||||||
|
if blocking(pool, is_banned).await? {
|
||||||
|
return Err(APIError::err("community_ban").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that only the creator can edit
|
||||||
|
if user_id != orig_comment.creator_id {
|
||||||
|
return Err(APIError::err("no_comment_edit_allowed").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the update
|
||||||
let content_slurs_removed = remove_slurs(&data.content.to_owned());
|
let content_slurs_removed = remove_slurs(&data.content.to_owned());
|
||||||
|
|
||||||
let edit_id = data.edit_id;
|
let edit_id = data.edit_id;
|
||||||
let read_comment = blocking(pool, move |conn| Comment::read(conn, edit_id)).await??;
|
|
||||||
|
|
||||||
let comment_form = {
|
|
||||||
if data.read.is_none() {
|
|
||||||
// the ban etc checks should been made and have passed
|
|
||||||
// the comment can be properly edited
|
|
||||||
let post_removed = if moderators.contains(&user_id) {
|
|
||||||
data.removed
|
|
||||||
} else {
|
|
||||||
Some(read_comment.removed)
|
|
||||||
};
|
|
||||||
|
|
||||||
CommentForm {
|
|
||||||
content: content_slurs_removed,
|
|
||||||
parent_id: read_comment.parent_id,
|
|
||||||
post_id: read_comment.post_id,
|
|
||||||
creator_id: read_comment.creator_id,
|
|
||||||
removed: post_removed.to_owned(),
|
|
||||||
deleted: data.deleted.to_owned(),
|
|
||||||
read: Some(read_comment.read),
|
|
||||||
published: None,
|
|
||||||
updated: Some(naive_now()),
|
|
||||||
ap_id: read_comment.ap_id,
|
|
||||||
local: read_comment.local,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// the only field that can be updated it the read field
|
|
||||||
CommentForm {
|
|
||||||
content: read_comment.content,
|
|
||||||
parent_id: read_comment.parent_id,
|
|
||||||
post_id: read_comment.post_id,
|
|
||||||
creator_id: read_comment.creator_id,
|
|
||||||
removed: Some(read_comment.removed).to_owned(),
|
|
||||||
deleted: Some(read_comment.deleted).to_owned(),
|
|
||||||
read: data.read.to_owned(),
|
|
||||||
published: None,
|
|
||||||
updated: orig_comment.updated,
|
|
||||||
ap_id: read_comment.ap_id,
|
|
||||||
local: read_comment.local,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let edit_id = data.edit_id;
|
|
||||||
let comment_form2 = comment_form.clone();
|
|
||||||
let updated_comment = match blocking(pool, move |conn| {
|
let updated_comment = match blocking(pool, move |conn| {
|
||||||
Comment::update(conn, edit_id, &comment_form2)
|
Comment::update_content(conn, edit_id, &content_slurs_removed)
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
|
@ -360,54 +293,19 @@ impl Perform for Oper<EditComment> {
|
||||||
Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
|
Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if data.read.is_none() {
|
// Send the apub update
|
||||||
if let Some(deleted) = data.deleted.to_owned() {
|
updated_comment
|
||||||
if deleted {
|
.send_update(&user, &self.client, pool)
|
||||||
updated_comment
|
.await?;
|
||||||
.send_delete(&user, &self.client, pool)
|
|
||||||
.await?;
|
|
||||||
} else {
|
|
||||||
updated_comment
|
|
||||||
.send_undo_delete(&user, &self.client, pool)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
} else if let Some(removed) = data.removed.to_owned() {
|
|
||||||
if moderators.contains(&user_id) {
|
|
||||||
if removed {
|
|
||||||
updated_comment
|
|
||||||
.send_remove(&user, &self.client, pool)
|
|
||||||
.await?;
|
|
||||||
} else {
|
|
||||||
updated_comment
|
|
||||||
.send_undo_remove(&user, &self.client, pool)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
updated_comment
|
|
||||||
.send_update(&user, &self.client, pool)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mod tables
|
// Do the mentions / recipients
|
||||||
if moderators.contains(&user_id) {
|
let post_id = orig_comment.post_id;
|
||||||
if let Some(removed) = data.removed.to_owned() {
|
|
||||||
let form = ModRemoveCommentForm {
|
|
||||||
mod_user_id: user_id,
|
|
||||||
comment_id: data.edit_id,
|
|
||||||
removed: Some(removed),
|
|
||||||
reason: data.reason.to_owned(),
|
|
||||||
};
|
|
||||||
blocking(pool, move |conn| ModRemoveComment::create(conn, &form)).await??;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let post_id = data.post_id;
|
|
||||||
let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
let mentions = scrape_text_for_mentions(&comment_form.content);
|
let updated_comment_content = updated_comment.content.to_owned();
|
||||||
let recipient_ids = send_local_notifs(mentions, updated_comment, user, post, pool).await?;
|
let mentions = scrape_text_for_mentions(&updated_comment_content);
|
||||||
|
let recipient_ids =
|
||||||
|
send_local_notifs(mentions, updated_comment, user, post, pool, false).await?;
|
||||||
|
|
||||||
let edit_id = data.edit_id;
|
let edit_id = data.edit_id;
|
||||||
let comment_view = blocking(pool, move |conn| {
|
let comment_view = blocking(pool, move |conn| {
|
||||||
|
@ -436,6 +334,294 @@ impl Perform for Oper<EditComment> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl Perform for Oper<DeleteComment> {
|
||||||
|
type Response = CommentResponse;
|
||||||
|
|
||||||
|
async fn perform(
|
||||||
|
&self,
|
||||||
|
pool: &DbPool,
|
||||||
|
websocket_info: Option<WebsocketInfo>,
|
||||||
|
) -> Result<CommentResponse, LemmyError> {
|
||||||
|
let data: &DeleteComment = &self.data;
|
||||||
|
|
||||||
|
let claims = match Claims::decode(&data.auth) {
|
||||||
|
Ok(claims) => claims.claims,
|
||||||
|
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let user_id = claims.id;
|
||||||
|
|
||||||
|
let edit_id = data.edit_id;
|
||||||
|
let orig_comment =
|
||||||
|
blocking(pool, move |conn| CommentView::read(&conn, edit_id, None)).await??;
|
||||||
|
|
||||||
|
// Check for a site ban
|
||||||
|
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
|
||||||
|
if user.banned {
|
||||||
|
return Err(APIError::err("site_ban").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a community ban
|
||||||
|
let community_id = orig_comment.community_id;
|
||||||
|
let is_banned =
|
||||||
|
move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
|
||||||
|
if blocking(pool, is_banned).await? {
|
||||||
|
return Err(APIError::err("community_ban").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that only the creator can delete
|
||||||
|
if user_id != orig_comment.creator_id {
|
||||||
|
return Err(APIError::err("no_comment_edit_allowed").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the delete
|
||||||
|
let deleted = data.deleted;
|
||||||
|
let updated_comment = match blocking(pool, move |conn| {
|
||||||
|
Comment::update_deleted(conn, edit_id, deleted)
|
||||||
|
})
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
Ok(comment) => comment,
|
||||||
|
Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send the apub message
|
||||||
|
if deleted {
|
||||||
|
updated_comment
|
||||||
|
.send_delete(&user, &self.client, pool)
|
||||||
|
.await?;
|
||||||
|
} else {
|
||||||
|
updated_comment
|
||||||
|
.send_undo_delete(&user, &self.client, pool)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refetch it
|
||||||
|
let edit_id = data.edit_id;
|
||||||
|
let comment_view = blocking(pool, move |conn| {
|
||||||
|
CommentView::read(conn, edit_id, Some(user_id))
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
// Build the recipients
|
||||||
|
let post_id = comment_view.post_id;
|
||||||
|
let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
let mentions = vec![];
|
||||||
|
let recipient_ids =
|
||||||
|
send_local_notifs(mentions, updated_comment, user, post, pool, false).await?;
|
||||||
|
|
||||||
|
let mut res = CommentResponse {
|
||||||
|
comment: comment_view,
|
||||||
|
recipient_ids,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(ws) = websocket_info {
|
||||||
|
ws.chatserver.do_send(SendComment {
|
||||||
|
op: UserOperation::DeleteComment,
|
||||||
|
comment: res.clone(),
|
||||||
|
my_id: ws.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
// strip out the recipient_ids, so that
|
||||||
|
// users don't get double notifs
|
||||||
|
res.recipient_ids = Vec::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl Perform for Oper<RemoveComment> {
|
||||||
|
type Response = CommentResponse;
|
||||||
|
|
||||||
|
async fn perform(
|
||||||
|
&self,
|
||||||
|
pool: &DbPool,
|
||||||
|
websocket_info: Option<WebsocketInfo>,
|
||||||
|
) -> Result<CommentResponse, LemmyError> {
|
||||||
|
let data: &RemoveComment = &self.data;
|
||||||
|
|
||||||
|
let claims = match Claims::decode(&data.auth) {
|
||||||
|
Ok(claims) => claims.claims,
|
||||||
|
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let user_id = claims.id;
|
||||||
|
|
||||||
|
let edit_id = data.edit_id;
|
||||||
|
let orig_comment =
|
||||||
|
blocking(pool, move |conn| CommentView::read(&conn, edit_id, None)).await??;
|
||||||
|
|
||||||
|
// Check for a site ban
|
||||||
|
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
|
||||||
|
if user.banned {
|
||||||
|
return Err(APIError::err("site_ban").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a community ban
|
||||||
|
let community_id = orig_comment.community_id;
|
||||||
|
let is_banned =
|
||||||
|
move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
|
||||||
|
if blocking(pool, is_banned).await? {
|
||||||
|
return Err(APIError::err("community_ban").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that only a mod or admin can remove
|
||||||
|
let mods_and_admins = blocking(pool, move |conn| {
|
||||||
|
Community::community_mods_and_admins(conn, community_id)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
if !mods_and_admins.contains(&user_id) {
|
||||||
|
return Err(APIError::err("not_an_admin").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the remove
|
||||||
|
let removed = data.removed;
|
||||||
|
let updated_comment = match blocking(pool, move |conn| {
|
||||||
|
Comment::update_removed(conn, edit_id, removed)
|
||||||
|
})
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
Ok(comment) => comment,
|
||||||
|
Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mod tables
|
||||||
|
let form = ModRemoveCommentForm {
|
||||||
|
mod_user_id: user_id,
|
||||||
|
comment_id: data.edit_id,
|
||||||
|
removed: Some(removed),
|
||||||
|
reason: data.reason.to_owned(),
|
||||||
|
};
|
||||||
|
blocking(pool, move |conn| ModRemoveComment::create(conn, &form)).await??;
|
||||||
|
|
||||||
|
// Send the apub message
|
||||||
|
if removed {
|
||||||
|
updated_comment
|
||||||
|
.send_remove(&user, &self.client, pool)
|
||||||
|
.await?;
|
||||||
|
} else {
|
||||||
|
updated_comment
|
||||||
|
.send_undo_remove(&user, &self.client, pool)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refetch it
|
||||||
|
let edit_id = data.edit_id;
|
||||||
|
let comment_view = blocking(pool, move |conn| {
|
||||||
|
CommentView::read(conn, edit_id, Some(user_id))
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
// Build the recipients
|
||||||
|
let post_id = comment_view.post_id;
|
||||||
|
let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
let mentions = vec![];
|
||||||
|
let recipient_ids =
|
||||||
|
send_local_notifs(mentions, updated_comment, user, post, pool, false).await?;
|
||||||
|
|
||||||
|
let mut res = CommentResponse {
|
||||||
|
comment: comment_view,
|
||||||
|
recipient_ids,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(ws) = websocket_info {
|
||||||
|
ws.chatserver.do_send(SendComment {
|
||||||
|
op: UserOperation::RemoveComment,
|
||||||
|
comment: res.clone(),
|
||||||
|
my_id: ws.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
// strip out the recipient_ids, so that
|
||||||
|
// users don't get double notifs
|
||||||
|
res.recipient_ids = Vec::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl Perform for Oper<MarkCommentAsRead> {
|
||||||
|
type Response = CommentResponse;
|
||||||
|
|
||||||
|
async fn perform(
|
||||||
|
&self,
|
||||||
|
pool: &DbPool,
|
||||||
|
_websocket_info: Option<WebsocketInfo>,
|
||||||
|
) -> Result<CommentResponse, LemmyError> {
|
||||||
|
let data: &MarkCommentAsRead = &self.data;
|
||||||
|
|
||||||
|
let claims = match Claims::decode(&data.auth) {
|
||||||
|
Ok(claims) => claims.claims,
|
||||||
|
Err(_e) => return Err(APIError::err("not_logged_in").into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let user_id = claims.id;
|
||||||
|
|
||||||
|
let edit_id = data.edit_id;
|
||||||
|
let orig_comment =
|
||||||
|
blocking(pool, move |conn| CommentView::read(&conn, edit_id, None)).await??;
|
||||||
|
|
||||||
|
// Check for a site ban
|
||||||
|
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
|
||||||
|
if user.banned {
|
||||||
|
return Err(APIError::err("site_ban").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a community ban
|
||||||
|
let community_id = orig_comment.community_id;
|
||||||
|
let is_banned =
|
||||||
|
move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
|
||||||
|
if blocking(pool, is_banned).await? {
|
||||||
|
return Err(APIError::err("community_ban").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that only the recipient can mark as read
|
||||||
|
// Needs to fetch the parent comment / post to get the recipient
|
||||||
|
let parent_id = orig_comment.parent_id;
|
||||||
|
match parent_id {
|
||||||
|
Some(pid) => {
|
||||||
|
let parent_comment =
|
||||||
|
blocking(pool, move |conn| CommentView::read(&conn, pid, None)).await??;
|
||||||
|
if user_id != parent_comment.creator_id {
|
||||||
|
return Err(APIError::err("no_comment_edit_allowed").into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let parent_post_id = orig_comment.post_id;
|
||||||
|
let parent_post = blocking(pool, move |conn| Post::read(conn, parent_post_id)).await??;
|
||||||
|
if user_id != parent_post.creator_id {
|
||||||
|
return Err(APIError::err("no_comment_edit_allowed").into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the mark as read
|
||||||
|
let read = data.read;
|
||||||
|
match blocking(pool, move |conn| Comment::update_read(conn, edit_id, read)).await? {
|
||||||
|
Ok(comment) => comment,
|
||||||
|
Err(_e) => return Err(APIError::err("couldnt_update_comment").into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Refetch it
|
||||||
|
let edit_id = data.edit_id;
|
||||||
|
let comment_view = blocking(pool, move |conn| {
|
||||||
|
CommentView::read(conn, edit_id, Some(user_id))
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
|
||||||
|
let res = CommentResponse {
|
||||||
|
comment: comment_view,
|
||||||
|
recipient_ids: Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl Perform for Oper<SaveComment> {
|
impl Perform for Oper<SaveComment> {
|
||||||
type Response = CommentResponse;
|
type Response = CommentResponse;
|
||||||
|
@ -512,8 +698,12 @@ impl Perform for Oper<CreateCommentLike> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let comment_id = data.comment_id;
|
||||||
|
let orig_comment =
|
||||||
|
blocking(pool, move |conn| CommentView::read(&conn, comment_id, None)).await??;
|
||||||
|
|
||||||
// Check for a community ban
|
// Check for a community ban
|
||||||
let post_id = data.post_id;
|
let post_id = orig_comment.post_id;
|
||||||
let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
|
||||||
let community_id = post.community_id;
|
let community_id = post.community_id;
|
||||||
let is_banned =
|
let is_banned =
|
||||||
|
@ -550,7 +740,7 @@ impl Perform for Oper<CreateCommentLike> {
|
||||||
|
|
||||||
let like_form = CommentLikeForm {
|
let like_form = CommentLikeForm {
|
||||||
comment_id: data.comment_id,
|
comment_id: data.comment_id,
|
||||||
post_id: data.post_id,
|
post_id,
|
||||||
user_id,
|
user_id,
|
||||||
score: data.score,
|
score: data.score,
|
||||||
};
|
};
|
||||||
|
@ -675,9 +865,10 @@ pub async fn send_local_notifs(
|
||||||
user: User_,
|
user: User_,
|
||||||
post: Post,
|
post: Post,
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
|
do_send_email: bool,
|
||||||
) -> Result<Vec<i32>, LemmyError> {
|
) -> Result<Vec<i32>, LemmyError> {
|
||||||
let ids = blocking(pool, move |conn| {
|
let ids = blocking(pool, move |conn| {
|
||||||
do_send_local_notifs(conn, &mentions, &comment, &user, &post)
|
do_send_local_notifs(conn, &mentions, &comment, &user, &post, do_send_email)
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -690,6 +881,7 @@ fn do_send_local_notifs(
|
||||||
comment: &Comment,
|
comment: &Comment,
|
||||||
user: &User_,
|
user: &User_,
|
||||||
post: &Post,
|
post: &Post,
|
||||||
|
do_send_email: bool,
|
||||||
) -> Vec<i32> {
|
) -> Vec<i32> {
|
||||||
let mut recipient_ids = Vec::new();
|
let mut recipient_ids = Vec::new();
|
||||||
let hostname = &format!("https://{}", Settings::get().hostname);
|
let hostname = &format!("https://{}", Settings::get().hostname);
|
||||||
|
@ -720,7 +912,7 @@ fn do_send_local_notifs(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Send an email to those users that have notifications on
|
// Send an email to those users that have notifications on
|
||||||
if mention_user.send_notifications_to_email {
|
if do_send_email && mention_user.send_notifications_to_email {
|
||||||
if let Some(mention_email) = mention_user.email {
|
if let Some(mention_email) = mention_user.email {
|
||||||
let subject = &format!("{} - Mentioned by {}", Settings::get().hostname, user.name,);
|
let subject = &format!("{} - Mentioned by {}", Settings::get().hostname, user.name,);
|
||||||
let html = &format!(
|
let html = &format!(
|
||||||
|
@ -744,7 +936,7 @@ fn do_send_local_notifs(
|
||||||
if let Ok(parent_user) = User_::read(&conn, parent_comment.creator_id) {
|
if let Ok(parent_user) = User_::read(&conn, parent_comment.creator_id) {
|
||||||
recipient_ids.push(parent_user.id);
|
recipient_ids.push(parent_user.id);
|
||||||
|
|
||||||
if parent_user.send_notifications_to_email {
|
if do_send_email && parent_user.send_notifications_to_email {
|
||||||
if let Some(comment_reply_email) = parent_user.email {
|
if let Some(comment_reply_email) = parent_user.email {
|
||||||
let subject = &format!("{} - Reply from {}", Settings::get().hostname, user.name,);
|
let subject = &format!("{} - Reply from {}", Settings::get().hostname, user.name,);
|
||||||
let html = &format!(
|
let html = &format!(
|
||||||
|
@ -767,7 +959,7 @@ fn do_send_local_notifs(
|
||||||
if let Ok(parent_user) = User_::read(&conn, post.creator_id) {
|
if let Ok(parent_user) = User_::read(&conn, post.creator_id) {
|
||||||
recipient_ids.push(parent_user.id);
|
recipient_ids.push(parent_user.id);
|
||||||
|
|
||||||
if parent_user.send_notifications_to_email {
|
if do_send_email && parent_user.send_notifications_to_email {
|
||||||
if let Some(post_reply_email) = parent_user.email {
|
if let Some(post_reply_email) = parent_user.email {
|
||||||
let subject = &format!("{} - Reply from {}", Settings::get().hostname, user.name,);
|
let subject = &format!("{} - Reply from {}", Settings::get().hostname, user.name,);
|
||||||
let html = &format!(
|
let html = &format!(
|
||||||
|
|
|
@ -10,7 +10,6 @@ use crate::{
|
||||||
},
|
},
|
||||||
DbPool,
|
DbPool,
|
||||||
};
|
};
|
||||||
use diesel::PgConnection;
|
|
||||||
use lemmy_db::{naive_now, Bannable, Crud, Followable, Joinable, SortType};
|
use lemmy_db::{naive_now, Bannable, Crud, Followable, Joinable, SortType};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
generate_actor_keypair,
|
generate_actor_keypair,
|
||||||
|
@ -1078,16 +1077,3 @@ impl Perform for Oper<TransferCommunity> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn community_mods_and_admins(
|
|
||||||
conn: &PgConnection,
|
|
||||||
community_id: i32,
|
|
||||||
) -> Result<Vec<i32>, LemmyError> {
|
|
||||||
let mut editors: Vec<i32> = Vec::new();
|
|
||||||
editors.append(
|
|
||||||
&mut CommunityModeratorView::for_community(conn, community_id)
|
|
||||||
.map(|v| v.into_iter().map(|m| m.user_id).collect())?,
|
|
||||||
);
|
|
||||||
editors.append(&mut UserView::admins(conn).map(|v| v.into_iter().map(|a| a.id).collect())?);
|
|
||||||
Ok(editors)
|
|
||||||
}
|
|
||||||
|
|
|
@ -936,9 +936,11 @@ impl Perform for Oper<MarkAllAsRead> {
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
// TODO: this should probably be a bulk operation
|
// TODO: this should probably be a bulk operation
|
||||||
|
// Not easy to do as a bulk operation,
|
||||||
|
// because recipient_id isn't in the comment table
|
||||||
for reply in &replies {
|
for reply in &replies {
|
||||||
let reply_id = reply.id;
|
let reply_id = reply.id;
|
||||||
let mark_as_read = move |conn: &'_ _| Comment::mark_as_read(conn, reply_id);
|
let mark_as_read = move |conn: &'_ _| Comment::update_read(conn, reply_id, true);
|
||||||
if blocking(pool, mark_as_read).await?.is_err() {
|
if blocking(pool, mark_as_read).await?.is_err() {
|
||||||
return Err(APIError::err("couldnt_update_comment").into());
|
return Err(APIError::err("couldnt_update_comment").into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -393,7 +393,7 @@ async fn receive_create_comment(
|
||||||
// anyway.
|
// anyway.
|
||||||
let mentions = scrape_text_for_mentions(&inserted_comment.content);
|
let mentions = scrape_text_for_mentions(&inserted_comment.content);
|
||||||
let recipient_ids =
|
let recipient_ids =
|
||||||
send_local_notifs(mentions, inserted_comment.clone(), user, post, pool).await?;
|
send_local_notifs(mentions, inserted_comment.clone(), user, post, pool, true).await?;
|
||||||
|
|
||||||
// Refetch the view
|
// Refetch the view
|
||||||
let comment_view = blocking(pool, move |conn| {
|
let comment_view = blocking(pool, move |conn| {
|
||||||
|
@ -558,7 +558,7 @@ async fn receive_update_comment(
|
||||||
let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
let mentions = scrape_text_for_mentions(&updated_comment.content);
|
let mentions = scrape_text_for_mentions(&updated_comment.content);
|
||||||
let recipient_ids = send_local_notifs(mentions, updated_comment, user, post, pool).await?;
|
let recipient_ids = send_local_notifs(mentions, updated_comment, user, post, pool, false).await?;
|
||||||
|
|
||||||
// Refetch the view
|
// Refetch the view
|
||||||
let comment_view =
|
let comment_view =
|
||||||
|
|
|
@ -83,6 +83,12 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
|
||||||
.wrap(rate_limit.message())
|
.wrap(rate_limit.message())
|
||||||
.route("", web::post().to(route_post::<CreateComment>))
|
.route("", web::post().to(route_post::<CreateComment>))
|
||||||
.route("", web::put().to(route_post::<EditComment>))
|
.route("", web::put().to(route_post::<EditComment>))
|
||||||
|
.route("/delete", web::post().to(route_post::<DeleteComment>))
|
||||||
|
.route("/remove", web::post().to(route_post::<RemoveComment>))
|
||||||
|
.route(
|
||||||
|
"/mark_as_read",
|
||||||
|
web::post().to(route_post::<MarkCommentAsRead>),
|
||||||
|
)
|
||||||
.route("/like", web::post().to(route_post::<CreateCommentLike>))
|
.route("/like", web::post().to(route_post::<CreateCommentLike>))
|
||||||
.route("/save", web::put().to(route_post::<SaveComment>)),
|
.route("/save", web::put().to(route_post::<SaveComment>)),
|
||||||
)
|
)
|
||||||
|
|
|
@ -28,6 +28,9 @@ pub enum UserOperation {
|
||||||
GetCommunity,
|
GetCommunity,
|
||||||
CreateComment,
|
CreateComment,
|
||||||
EditComment,
|
EditComment,
|
||||||
|
DeleteComment,
|
||||||
|
RemoveComment,
|
||||||
|
MarkCommentAsRead,
|
||||||
SaveComment,
|
SaveComment,
|
||||||
CreateCommentLike,
|
CreateCommentLike,
|
||||||
GetPosts,
|
GetPosts,
|
||||||
|
|
|
@ -506,6 +506,9 @@ impl ChatServer {
|
||||||
// Comment ops
|
// Comment ops
|
||||||
UserOperation::CreateComment => do_user_operation::<CreateComment>(args).await,
|
UserOperation::CreateComment => do_user_operation::<CreateComment>(args).await,
|
||||||
UserOperation::EditComment => do_user_operation::<EditComment>(args).await,
|
UserOperation::EditComment => do_user_operation::<EditComment>(args).await,
|
||||||
|
UserOperation::DeleteComment => do_user_operation::<DeleteComment>(args).await,
|
||||||
|
UserOperation::RemoveComment => do_user_operation::<RemoveComment>(args).await,
|
||||||
|
UserOperation::MarkCommentAsRead => do_user_operation::<MarkCommentAsRead>(args).await,
|
||||||
UserOperation::SaveComment => do_user_operation::<SaveComment>(args).await,
|
UserOperation::SaveComment => do_user_operation::<SaveComment>(args).await,
|
||||||
UserOperation::GetComments => do_user_operation::<GetComments>(args).await,
|
UserOperation::GetComments => do_user_operation::<GetComments>(args).await,
|
||||||
UserOperation::CreateCommentLike => do_user_operation::<CreateCommentLike>(args).await,
|
UserOperation::CreateCommentLike => do_user_operation::<CreateCommentLike>(args).await,
|
||||||
|
|
39
ui/src/api_tests/api.spec.ts
vendored
39
ui/src/api_tests/api.spec.ts
vendored
|
@ -11,6 +11,8 @@ import {
|
||||||
GetFollowedCommunitiesResponse,
|
GetFollowedCommunitiesResponse,
|
||||||
GetPostResponse,
|
GetPostResponse,
|
||||||
CommentForm,
|
CommentForm,
|
||||||
|
DeleteCommentForm,
|
||||||
|
RemoveCommentForm,
|
||||||
CommentResponse,
|
CommentResponse,
|
||||||
CommunityForm,
|
CommunityForm,
|
||||||
DeleteCommunityForm,
|
DeleteCommunityForm,
|
||||||
|
@ -383,7 +385,6 @@ describe('main', () => {
|
||||||
let unlikeCommentForm: CommentLikeForm = {
|
let unlikeCommentForm: CommentLikeForm = {
|
||||||
comment_id: createResponse.comment.id,
|
comment_id: createResponse.comment.id,
|
||||||
score: 0,
|
score: 0,
|
||||||
post_id: 2,
|
|
||||||
auth: lemmyAlphaAuth,
|
auth: lemmyAlphaAuth,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -621,19 +622,16 @@ describe('main', () => {
|
||||||
expect(createCommentRes.comment.content).toBe(commentContent);
|
expect(createCommentRes.comment.content).toBe(commentContent);
|
||||||
|
|
||||||
// lemmy_beta deletes the comment
|
// lemmy_beta deletes the comment
|
||||||
let deleteCommentForm: CommentForm = {
|
let deleteCommentForm: DeleteCommentForm = {
|
||||||
content: commentContent,
|
|
||||||
edit_id: createCommentRes.comment.id,
|
edit_id: createCommentRes.comment.id,
|
||||||
post_id: createPostRes.post.id,
|
|
||||||
deleted: true,
|
deleted: true,
|
||||||
auth: lemmyBetaAuth,
|
auth: lemmyBetaAuth,
|
||||||
creator_id: createCommentRes.comment.creator_id,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let deleteCommentRes: CommentResponse = await fetch(
|
let deleteCommentRes: CommentResponse = await fetch(
|
||||||
`${lemmyBetaApiUrl}/comment`,
|
`${lemmyBetaApiUrl}/comment/delete`,
|
||||||
{
|
{
|
||||||
method: 'PUT',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
|
@ -650,19 +648,16 @@ describe('main', () => {
|
||||||
expect(getPostRes.comments[0].deleted).toBe(true);
|
expect(getPostRes.comments[0].deleted).toBe(true);
|
||||||
|
|
||||||
// lemmy_beta undeletes the comment
|
// lemmy_beta undeletes the comment
|
||||||
let undeleteCommentForm: CommentForm = {
|
let undeleteCommentForm: DeleteCommentForm = {
|
||||||
content: commentContent,
|
|
||||||
edit_id: createCommentRes.comment.id,
|
edit_id: createCommentRes.comment.id,
|
||||||
post_id: createPostRes.post.id,
|
|
||||||
deleted: false,
|
deleted: false,
|
||||||
auth: lemmyBetaAuth,
|
auth: lemmyBetaAuth,
|
||||||
creator_id: createCommentRes.comment.creator_id,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let undeleteCommentRes: CommentResponse = await fetch(
|
let undeleteCommentRes: CommentResponse = await fetch(
|
||||||
`${lemmyBetaApiUrl}/comment`,
|
`${lemmyBetaApiUrl}/comment/delete`,
|
||||||
{
|
{
|
||||||
method: 'PUT',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
|
@ -889,19 +884,16 @@ describe('main', () => {
|
||||||
expect(createCommentRes.comment.content).toBe(commentContent);
|
expect(createCommentRes.comment.content).toBe(commentContent);
|
||||||
|
|
||||||
// lemmy_beta removes the comment
|
// lemmy_beta removes the comment
|
||||||
let removeCommentForm: CommentForm = {
|
let removeCommentForm: RemoveCommentForm = {
|
||||||
content: commentContent,
|
|
||||||
edit_id: createCommentRes.comment.id,
|
edit_id: createCommentRes.comment.id,
|
||||||
post_id: createPostRes.post.id,
|
|
||||||
removed: true,
|
removed: true,
|
||||||
auth: lemmyBetaAuth,
|
auth: lemmyBetaAuth,
|
||||||
creator_id: createCommentRes.comment.creator_id,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let removeCommentRes: CommentResponse = await fetch(
|
let removeCommentRes: CommentResponse = await fetch(
|
||||||
`${lemmyBetaApiUrl}/comment`,
|
`${lemmyBetaApiUrl}/comment/remove`,
|
||||||
{
|
{
|
||||||
method: 'PUT',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
|
@ -918,19 +910,16 @@ describe('main', () => {
|
||||||
expect(getPostRes.comments[0].removed).toBe(true);
|
expect(getPostRes.comments[0].removed).toBe(true);
|
||||||
|
|
||||||
// lemmy_beta undeletes the comment
|
// lemmy_beta undeletes the comment
|
||||||
let unremoveCommentForm: CommentForm = {
|
let unremoveCommentForm: RemoveCommentForm = {
|
||||||
content: commentContent,
|
|
||||||
edit_id: createCommentRes.comment.id,
|
edit_id: createCommentRes.comment.id,
|
||||||
post_id: createPostRes.post.id,
|
|
||||||
removed: false,
|
removed: false,
|
||||||
auth: lemmyBetaAuth,
|
auth: lemmyBetaAuth,
|
||||||
creator_id: createCommentRes.comment.creator_id,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let unremoveCommentRes: CommentResponse = await fetch(
|
let unremoveCommentRes: CommentResponse = await fetch(
|
||||||
`${lemmyBetaApiUrl}/comment`,
|
`${lemmyBetaApiUrl}/comment/remove`,
|
||||||
{
|
{
|
||||||
method: 'PUT',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
|
|
30
ui/src/components/comment-node.tsx
vendored
30
ui/src/components/comment-node.tsx
vendored
|
@ -3,7 +3,9 @@ import { Link } from 'inferno-router';
|
||||||
import {
|
import {
|
||||||
CommentNode as CommentNodeI,
|
CommentNode as CommentNodeI,
|
||||||
CommentLikeForm,
|
CommentLikeForm,
|
||||||
CommentForm as CommentFormI,
|
DeleteCommentForm,
|
||||||
|
RemoveCommentForm,
|
||||||
|
MarkCommentAsReadForm,
|
||||||
MarkUserMentionAsReadForm,
|
MarkUserMentionAsReadForm,
|
||||||
SaveCommentForm,
|
SaveCommentForm,
|
||||||
BanFromCommunityForm,
|
BanFromCommunityForm,
|
||||||
|
@ -848,16 +850,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDeleteClick(i: CommentNode) {
|
handleDeleteClick(i: CommentNode) {
|
||||||
let deleteForm: CommentFormI = {
|
let deleteForm: DeleteCommentForm = {
|
||||||
content: i.props.node.comment.content,
|
|
||||||
edit_id: i.props.node.comment.id,
|
edit_id: i.props.node.comment.id,
|
||||||
creator_id: i.props.node.comment.creator_id,
|
|
||||||
post_id: i.props.node.comment.post_id,
|
|
||||||
parent_id: i.props.node.comment.parent_id,
|
|
||||||
deleted: !i.props.node.comment.deleted,
|
deleted: !i.props.node.comment.deleted,
|
||||||
auth: null,
|
auth: null,
|
||||||
};
|
};
|
||||||
WebSocketService.Instance.editComment(deleteForm);
|
WebSocketService.Instance.deleteComment(deleteForm);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSaveCommentClick(i: CommentNode) {
|
handleSaveCommentClick(i: CommentNode) {
|
||||||
|
@ -901,7 +899,6 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
|
|
||||||
let form: CommentLikeForm = {
|
let form: CommentLikeForm = {
|
||||||
comment_id: i.comment.id,
|
comment_id: i.comment.id,
|
||||||
post_id: i.comment.post_id,
|
|
||||||
score: this.state.my_vote,
|
score: this.state.my_vote,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -929,7 +926,6 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
|
|
||||||
let form: CommentLikeForm = {
|
let form: CommentLikeForm = {
|
||||||
comment_id: i.comment.id,
|
comment_id: i.comment.id,
|
||||||
post_id: i.comment.post_id,
|
|
||||||
score: this.state.my_vote,
|
score: this.state.my_vote,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -950,17 +946,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
|
|
||||||
handleModRemoveSubmit(i: CommentNode) {
|
handleModRemoveSubmit(i: CommentNode) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let form: CommentFormI = {
|
let form: RemoveCommentForm = {
|
||||||
content: i.props.node.comment.content,
|
|
||||||
edit_id: i.props.node.comment.id,
|
edit_id: i.props.node.comment.id,
|
||||||
creator_id: i.props.node.comment.creator_id,
|
|
||||||
post_id: i.props.node.comment.post_id,
|
|
||||||
parent_id: i.props.node.comment.parent_id,
|
|
||||||
removed: !i.props.node.comment.removed,
|
removed: !i.props.node.comment.removed,
|
||||||
reason: i.state.removeReason,
|
reason: i.state.removeReason,
|
||||||
auth: null,
|
auth: null,
|
||||||
};
|
};
|
||||||
WebSocketService.Instance.editComment(form);
|
WebSocketService.Instance.removeComment(form);
|
||||||
|
|
||||||
i.state.showRemoveDialog = false;
|
i.state.showRemoveDialog = false;
|
||||||
i.setState(i.state);
|
i.setState(i.state);
|
||||||
|
@ -975,16 +967,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
};
|
};
|
||||||
WebSocketService.Instance.markUserMentionAsRead(form);
|
WebSocketService.Instance.markUserMentionAsRead(form);
|
||||||
} else {
|
} else {
|
||||||
let form: CommentFormI = {
|
let form: MarkCommentAsReadForm = {
|
||||||
content: i.props.node.comment.content,
|
|
||||||
edit_id: i.props.node.comment.id,
|
edit_id: i.props.node.comment.id,
|
||||||
creator_id: i.props.node.comment.creator_id,
|
|
||||||
post_id: i.props.node.comment.post_id,
|
|
||||||
parent_id: i.props.node.comment.parent_id,
|
|
||||||
read: !i.props.node.comment.read,
|
read: !i.props.node.comment.read,
|
||||||
auth: null,
|
auth: null,
|
||||||
};
|
};
|
||||||
WebSocketService.Instance.editComment(form);
|
WebSocketService.Instance.markCommentAsRead(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
i.state.readLoading = true;
|
i.state.readLoading = true;
|
||||||
|
|
6
ui/src/components/community.tsx
vendored
6
ui/src/components/community.tsx
vendored
|
@ -409,7 +409,11 @@ export class Community extends Component<any, State> {
|
||||||
this.state.comments = data.comments;
|
this.state.comments = data.comments;
|
||||||
this.state.loading = false;
|
this.state.loading = false;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (res.op == UserOperation.EditComment) {
|
} else if (
|
||||||
|
res.op == UserOperation.EditComment ||
|
||||||
|
res.op == UserOperation.DeleteComment ||
|
||||||
|
res.op == UserOperation.RemoveComment
|
||||||
|
) {
|
||||||
let data = res.data as CommentResponse;
|
let data = res.data as CommentResponse;
|
||||||
editCommentRes(data, this.state.comments);
|
editCommentRes(data, this.state.comments);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
|
9
ui/src/components/inbox.tsx
vendored
9
ui/src/components/inbox.tsx
vendored
|
@ -484,9 +484,16 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (res.op == UserOperation.MarkAllAsRead) {
|
} else if (res.op == UserOperation.MarkAllAsRead) {
|
||||||
// Moved to be instant
|
// Moved to be instant
|
||||||
} else if (res.op == UserOperation.EditComment) {
|
} else if (
|
||||||
|
res.op == UserOperation.EditComment ||
|
||||||
|
res.op == UserOperation.DeleteComment ||
|
||||||
|
res.op == UserOperation.RemoveComment
|
||||||
|
) {
|
||||||
let data = res.data as CommentResponse;
|
let data = res.data as CommentResponse;
|
||||||
editCommentRes(data, this.state.replies);
|
editCommentRes(data, this.state.replies);
|
||||||
|
this.setState(this.state);
|
||||||
|
} else if (res.op == UserOperation.MarkCommentAsRead) {
|
||||||
|
let data = res.data as CommentResponse;
|
||||||
|
|
||||||
// If youre in the unread view, just remove it from the list
|
// If youre in the unread view, just remove it from the list
|
||||||
if (this.state.unreadOrAll == UnreadOrAll.Unread && data.comment.read) {
|
if (this.state.unreadOrAll == UnreadOrAll.Unread && data.comment.read) {
|
||||||
|
|
6
ui/src/components/main.tsx
vendored
6
ui/src/components/main.tsx
vendored
|
@ -701,7 +701,11 @@ export class Main extends Component<any, MainState> {
|
||||||
this.state.comments = data.comments;
|
this.state.comments = data.comments;
|
||||||
this.state.loading = false;
|
this.state.loading = false;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
} else if (res.op == UserOperation.EditComment) {
|
} else if (
|
||||||
|
res.op == UserOperation.EditComment ||
|
||||||
|
res.op == UserOperation.DeleteComment ||
|
||||||
|
res.op == UserOperation.RemoveComment
|
||||||
|
) {
|
||||||
let data = res.data as CommentResponse;
|
let data = res.data as CommentResponse;
|
||||||
editCommentRes(data, this.state.comments);
|
editCommentRes(data, this.state.comments);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
|
16
ui/src/components/post.tsx
vendored
16
ui/src/components/post.tsx
vendored
|
@ -8,7 +8,7 @@ import {
|
||||||
GetPostResponse,
|
GetPostResponse,
|
||||||
PostResponse,
|
PostResponse,
|
||||||
Comment,
|
Comment,
|
||||||
CommentForm as CommentFormI,
|
MarkCommentAsReadForm,
|
||||||
CommentResponse,
|
CommentResponse,
|
||||||
CommentSortType,
|
CommentSortType,
|
||||||
CommentViewType,
|
CommentViewType,
|
||||||
|
@ -167,16 +167,12 @@ export class Post extends Component<any, PostState> {
|
||||||
UserService.Instance.user &&
|
UserService.Instance.user &&
|
||||||
UserService.Instance.user.id == parent_user_id
|
UserService.Instance.user.id == parent_user_id
|
||||||
) {
|
) {
|
||||||
let form: CommentFormI = {
|
let form: MarkCommentAsReadForm = {
|
||||||
content: found.content,
|
|
||||||
edit_id: found.id,
|
edit_id: found.id,
|
||||||
creator_id: found.creator_id,
|
|
||||||
post_id: found.post_id,
|
|
||||||
parent_id: found.parent_id,
|
|
||||||
read: true,
|
read: true,
|
||||||
auth: null,
|
auth: null,
|
||||||
};
|
};
|
||||||
WebSocketService.Instance.editComment(form);
|
WebSocketService.Instance.markCommentAsRead(form);
|
||||||
UserService.Instance.user.unreadCount--;
|
UserService.Instance.user.unreadCount--;
|
||||||
UserService.Instance.sub.next({
|
UserService.Instance.sub.next({
|
||||||
user: UserService.Instance.user,
|
user: UserService.Instance.user,
|
||||||
|
@ -435,7 +431,11 @@ export class Post extends Component<any, PostState> {
|
||||||
this.state.comments.unshift(data.comment);
|
this.state.comments.unshift(data.comment);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
}
|
}
|
||||||
} else if (res.op == UserOperation.EditComment) {
|
} else if (
|
||||||
|
res.op == UserOperation.EditComment ||
|
||||||
|
res.op == UserOperation.DeleteComment ||
|
||||||
|
res.op == UserOperation.RemoveComment
|
||||||
|
) {
|
||||||
let data = res.data as CommentResponse;
|
let data = res.data as CommentResponse;
|
||||||
editCommentRes(data, this.state.comments);
|
editCommentRes(data, this.state.comments);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
|
6
ui/src/components/user-details.tsx
vendored
6
ui/src/components/user-details.tsx
vendored
|
@ -257,7 +257,11 @@ export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
|
||||||
this.setState({
|
this.setState({
|
||||||
comments: this.state.comments,
|
comments: this.state.comments,
|
||||||
});
|
});
|
||||||
} else if (res.op == UserOperation.EditComment) {
|
} else if (
|
||||||
|
res.op == UserOperation.EditComment ||
|
||||||
|
res.op == UserOperation.DeleteComment ||
|
||||||
|
res.op == UserOperation.RemoveComment
|
||||||
|
) {
|
||||||
const data = res.data as CommentResponse;
|
const data = res.data as CommentResponse;
|
||||||
editCommentRes(data, this.state.comments);
|
editCommentRes(data, this.state.comments);
|
||||||
this.setState({
|
this.setState({
|
||||||
|
|
30
ui/src/interfaces.ts
vendored
30
ui/src/interfaces.ts
vendored
|
@ -9,6 +9,9 @@ export enum UserOperation {
|
||||||
GetCommunity,
|
GetCommunity,
|
||||||
CreateComment,
|
CreateComment,
|
||||||
EditComment,
|
EditComment,
|
||||||
|
DeleteComment,
|
||||||
|
RemoveComment,
|
||||||
|
MarkCommentAsRead,
|
||||||
SaveComment,
|
SaveComment,
|
||||||
CreateCommentLike,
|
CreateCommentLike,
|
||||||
GetPosts,
|
GetPosts,
|
||||||
|
@ -679,14 +682,29 @@ export interface PostResponse {
|
||||||
|
|
||||||
export interface CommentForm {
|
export interface CommentForm {
|
||||||
content: string;
|
content: string;
|
||||||
post_id: number;
|
post_id?: number;
|
||||||
parent_id?: number;
|
parent_id?: number;
|
||||||
edit_id?: number;
|
edit_id?: number;
|
||||||
creator_id?: number;
|
creator_id?: number;
|
||||||
removed?: boolean;
|
auth: string;
|
||||||
deleted?: boolean;
|
}
|
||||||
|
|
||||||
|
export interface DeleteCommentForm {
|
||||||
|
edit_id: number;
|
||||||
|
deleted: boolean;
|
||||||
|
auth: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RemoveCommentForm {
|
||||||
|
edit_id: number;
|
||||||
|
removed: boolean;
|
||||||
reason?: string;
|
reason?: string;
|
||||||
read?: boolean;
|
auth: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MarkCommentAsReadForm {
|
||||||
|
edit_id: number;
|
||||||
|
read: boolean;
|
||||||
auth: string;
|
auth: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,7 +721,6 @@ export interface CommentResponse {
|
||||||
|
|
||||||
export interface CommentLikeForm {
|
export interface CommentLikeForm {
|
||||||
comment_id: number;
|
comment_id: number;
|
||||||
post_id: number;
|
|
||||||
score: number;
|
score: number;
|
||||||
auth?: string;
|
auth?: string;
|
||||||
}
|
}
|
||||||
|
@ -901,6 +918,9 @@ export type MessageType =
|
||||||
| GetPostsForm
|
| GetPostsForm
|
||||||
| GetCommunityForm
|
| GetCommunityForm
|
||||||
| CommentForm
|
| CommentForm
|
||||||
|
| DeleteCommentForm
|
||||||
|
| RemoveCommentForm
|
||||||
|
| MarkCommentAsReadForm
|
||||||
| CommentLikeForm
|
| CommentLikeForm
|
||||||
| SaveCommentForm
|
| SaveCommentForm
|
||||||
| CreatePostLikeForm
|
| CreatePostLikeForm
|
||||||
|
|
30
ui/src/services/WebSocketService.ts
vendored
30
ui/src/services/WebSocketService.ts
vendored
|
@ -9,6 +9,9 @@ import {
|
||||||
PostForm,
|
PostForm,
|
||||||
SavePostForm,
|
SavePostForm,
|
||||||
CommentForm,
|
CommentForm,
|
||||||
|
DeleteCommentForm,
|
||||||
|
RemoveCommentForm,
|
||||||
|
MarkCommentAsReadForm,
|
||||||
SaveCommentForm,
|
SaveCommentForm,
|
||||||
CommentLikeForm,
|
CommentLikeForm,
|
||||||
GetPostForm,
|
GetPostForm,
|
||||||
|
@ -165,14 +168,29 @@ export class WebSocketService {
|
||||||
this.ws.send(this.wsSendWrapper(UserOperation.GetCommunity, form));
|
this.ws.send(this.wsSendWrapper(UserOperation.GetCommunity, form));
|
||||||
}
|
}
|
||||||
|
|
||||||
public createComment(commentForm: CommentForm) {
|
public createComment(form: CommentForm) {
|
||||||
this.setAuth(commentForm);
|
this.setAuth(form);
|
||||||
this.ws.send(this.wsSendWrapper(UserOperation.CreateComment, commentForm));
|
this.ws.send(this.wsSendWrapper(UserOperation.CreateComment, form));
|
||||||
}
|
}
|
||||||
|
|
||||||
public editComment(commentForm: CommentForm) {
|
public editComment(form: CommentForm) {
|
||||||
this.setAuth(commentForm);
|
this.setAuth(form);
|
||||||
this.ws.send(this.wsSendWrapper(UserOperation.EditComment, commentForm));
|
this.ws.send(this.wsSendWrapper(UserOperation.EditComment, form));
|
||||||
|
}
|
||||||
|
|
||||||
|
public deleteComment(form: DeleteCommentForm) {
|
||||||
|
this.setAuth(form);
|
||||||
|
this.ws.send(this.wsSendWrapper(UserOperation.DeleteComment, form));
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeComment(form: RemoveCommentForm) {
|
||||||
|
this.setAuth(form);
|
||||||
|
this.ws.send(this.wsSendWrapper(UserOperation.RemoveComment, form));
|
||||||
|
}
|
||||||
|
|
||||||
|
public markCommentAsRead(form: MarkCommentAsReadForm) {
|
||||||
|
this.setAuth(form);
|
||||||
|
this.ws.send(this.wsSendWrapper(UserOperation.MarkCommentAsRead, form));
|
||||||
}
|
}
|
||||||
|
|
||||||
public likeComment(form: CommentLikeForm) {
|
public likeComment(form: CommentLikeForm) {
|
||||||
|
|
Loading…
Reference in a new issue