feat: get comment & send post
This commit is contained in:
65
src/api/comment.rs
Normal file
65
src/api/comment.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
use crate::api::{APIError, CurrentUser, PolicyError::*, API};
|
||||
use crate::models::*;
|
||||
use chrono::NaiveDateTime;
|
||||
use rocket::serde::{
|
||||
json::{json, Value},
|
||||
Serialize,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct CommentOutput {
|
||||
cid: i32,
|
||||
text: String,
|
||||
can_del: bool,
|
||||
name_id: i32,
|
||||
create_time: NaiveDateTime,
|
||||
// for old version frontend
|
||||
timestamp: i64,
|
||||
}
|
||||
|
||||
pub fn c2output(p: &Post, cs: &Vec<Comment>, user: &CurrentUser) -> Vec<CommentOutput> {
|
||||
let mut hash2id = HashMap::<&String, i32>::from([(&p.author_hash, 0)]);
|
||||
cs.iter()
|
||||
.filter_map(|c| {
|
||||
let name_id: i32 = match hash2id.get(&c.author_hash) {
|
||||
Some(id) => *id,
|
||||
None => {
|
||||
let x = hash2id.len().try_into().unwrap();
|
||||
hash2id.insert(&c.author_hash, x);
|
||||
x
|
||||
}
|
||||
};
|
||||
if c.is_deleted {
|
||||
None
|
||||
} else {
|
||||
Some(CommentOutput {
|
||||
cid: c.id,
|
||||
text: c.content.to_string(),
|
||||
can_del: user.is_admin || c.author_hash == user.namehash,
|
||||
name_id: name_id,
|
||||
create_time: c.create_time,
|
||||
timestamp: c.create_time.timestamp(),
|
||||
})
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[get("/getcomment?<pid>")]
|
||||
pub fn get_comment(pid: i32, user: CurrentUser) -> API<Value> {
|
||||
let conn = establish_connection();
|
||||
let p = Post::get(&conn, pid).map_err(APIError::from_db)?;
|
||||
if p.is_deleted {
|
||||
return Err(APIError::PcError(IsDeleted));
|
||||
}
|
||||
let cs = p.get_comments(&conn).map_err(APIError::from_db)?;
|
||||
Ok(json!({
|
||||
"code": 0,
|
||||
"data": c2output(&p, &cs, &user),
|
||||
"n_likes": p.n_likes,
|
||||
// for old version frontend
|
||||
"likenum": p.n_likes,
|
||||
}))
|
||||
}
|
||||
@@ -103,5 +103,6 @@ macro_rules! look {
|
||||
|
||||
pub type API<T> = Result<T, APIError>;
|
||||
|
||||
pub mod comment;
|
||||
pub mod post;
|
||||
pub mod systemlog;
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
use crate::api::comment::{c2output, CommentOutput};
|
||||
use crate::api::{APIError, CurrentUser, PolicyError::*, API};
|
||||
use crate::models::*;
|
||||
use chrono::NaiveDateTime;
|
||||
use diesel::SqliteConnection;
|
||||
use rocket::form::Form;
|
||||
use rocket::serde::{
|
||||
json::{json, Json, Value},
|
||||
Deserialize, Serialize,
|
||||
json::{json, Value},
|
||||
Serialize,
|
||||
};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
#[derive(FromForm)]
|
||||
pub struct PostInput<'r> {
|
||||
content: &'r str,
|
||||
#[field(validate = len(1..4097))]
|
||||
text: &'r str,
|
||||
#[field(validate = len(0..33))]
|
||||
cw: &'r str,
|
||||
allow_search: Option<i8>,
|
||||
use_title: Option<i8>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct PostOutput {
|
||||
id: i32,
|
||||
content: String,
|
||||
cw: String,
|
||||
pid: i32,
|
||||
text: String,
|
||||
cw: Option<String>,
|
||||
author_title: String,
|
||||
n_likes: i32,
|
||||
n_comments: i32,
|
||||
@@ -26,15 +32,23 @@ pub struct PostOutput {
|
||||
last_comment_time: NaiveDateTime,
|
||||
allow_search: bool,
|
||||
is_reported: Option<bool>,
|
||||
comments: Vec<CommentOutput>,
|
||||
can_del: bool,
|
||||
// for old version frontend
|
||||
timestamp: NaiveDateTime,
|
||||
timestamp: i64,
|
||||
custom_title: Option<String>,
|
||||
}
|
||||
|
||||
fn p2output(p: &Post, user: &CurrentUser) -> PostOutput {
|
||||
fn p2output(p: &Post, user: &CurrentUser, conn: &SqliteConnection) -> PostOutput {
|
||||
PostOutput {
|
||||
id: p.id,
|
||||
content: p.content.to_string(),
|
||||
cw: p.cw.to_string(),
|
||||
pid: p.id,
|
||||
text: p.content.to_string(),
|
||||
|
||||
cw: if p.cw.len() > 0 {
|
||||
Some(p.cw.to_string())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
author_title: p.author_title.to_string(),
|
||||
n_likes: p.n_likes,
|
||||
n_comments: p.n_comments,
|
||||
@@ -46,12 +60,24 @@ fn p2output(p: &Post, user: &CurrentUser) -> PostOutput {
|
||||
} else {
|
||||
None
|
||||
},
|
||||
comments: if p.n_comments > 50 {
|
||||
vec![]
|
||||
} else {
|
||||
// 单个洞还有查询评论的接口,这里挂了不用报错
|
||||
c2output(p, &p.get_comments(conn).unwrap_or(vec![]), user)
|
||||
},
|
||||
can_del: user.is_admin || p.author_hash == user.namehash,
|
||||
// for old version frontend
|
||||
timestamp: p.create_time,
|
||||
timestamp: p.create_time.timestamp(),
|
||||
custom_title: if p.author_title.len() > 0 {
|
||||
Some(p.author_title.to_string())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/post/<pid>")]
|
||||
#[get("/getone?<pid>")]
|
||||
pub fn get_one(pid: i32, user: CurrentUser) -> API<Value> {
|
||||
let conn = establish_connection();
|
||||
let p = Post::get(&conn, pid).map_err(APIError::from_db)?;
|
||||
@@ -64,7 +90,7 @@ pub fn get_one(pid: i32, user: CurrentUser) -> API<Value> {
|
||||
}
|
||||
}
|
||||
Ok(json!({
|
||||
"data": p2output(&p, &user),
|
||||
"data": p2output(&p, &user, &conn),
|
||||
"code": 0,
|
||||
}))
|
||||
}
|
||||
@@ -77,7 +103,7 @@ pub fn get_list(p: Option<u32>, order_mode: u8, user: CurrentUser) -> API<Value>
|
||||
.map_err(APIError::from_db)?;
|
||||
let ps_data = ps
|
||||
.iter()
|
||||
.map(|p| p2output(p, &user))
|
||||
.map(|p| p2output(p, &user, &conn))
|
||||
.collect::<Vec<PostOutput>>();
|
||||
Ok(json!({
|
||||
"data": ps_data,
|
||||
@@ -86,16 +112,18 @@ pub fn get_list(p: Option<u32>, order_mode: u8, user: CurrentUser) -> API<Value>
|
||||
}))
|
||||
}
|
||||
|
||||
#[post("/dopost", format = "json", data = "<poi>")]
|
||||
pub fn publish_post(poi: Json<PostInput>, user: CurrentUser) -> API<Value> {
|
||||
#[post("/dopost", data = "<poi>")]
|
||||
pub fn publish_post(poi: Form<PostInput>, user: CurrentUser) -> API<Value> {
|
||||
let conn = establish_connection();
|
||||
dbg!(poi.use_title, poi.allow_search);
|
||||
let r = Post::create(
|
||||
&conn,
|
||||
NewPost {
|
||||
content: &poi.content,
|
||||
content: &poi.text,
|
||||
cw: &poi.cw,
|
||||
author_hash: &user.namehash,
|
||||
author_title: "",
|
||||
allow_search: poi.allow_search.is_some(),
|
||||
},
|
||||
)
|
||||
.map_err(APIError::from_db)?;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::api::{CurrentUser, API};
|
||||
use crate::random_hasher::RandomHasher;
|
||||
use chrono::SubsecRound;
|
||||
use rocket::serde::json::{json, Value};
|
||||
use rocket::State;
|
||||
|
||||
@@ -9,7 +8,8 @@ pub fn get_systemlog(user: CurrentUser, rh: &State<RandomHasher>) -> API<Value>
|
||||
Ok(json!({
|
||||
"tmp_token": rh.get_tmp_token(),
|
||||
"salt": look!(rh.salt),
|
||||
"start_time": rh.start_time.round_subsecs(0),
|
||||
"start_time": rh.start_time.timestamp(),
|
||||
"custom_title": user.custom_title,
|
||||
"data": [],
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ fn rocket() -> _ {
|
||||
.mount(
|
||||
"/_api/v1",
|
||||
routes![
|
||||
api::comment::get_comment,
|
||||
api::post::get_list,
|
||||
api::post::get_one,
|
||||
api::post::publish_post,
|
||||
|
||||
@@ -40,6 +40,7 @@ pub struct NewPost<'a> {
|
||||
pub cw: &'a str,
|
||||
pub author_hash: &'a str,
|
||||
pub author_title: &'a str,
|
||||
pub allow_search: bool,
|
||||
// TODO: tags
|
||||
}
|
||||
|
||||
@@ -75,6 +76,12 @@ impl Post {
|
||||
.load(conn)
|
||||
}
|
||||
|
||||
pub fn get_comments(&self, conn: &SqliteConnection) -> MR<Vec<Comment>> {
|
||||
comments::table
|
||||
.filter(comments::post_id.eq(self.id))
|
||||
.load(conn)
|
||||
}
|
||||
|
||||
pub fn create(conn: &SqliteConnection, new_post: NewPost) -> MR<usize> {
|
||||
// TODO: tags
|
||||
insert_into(posts::table).values(&new_post).execute(conn)
|
||||
@@ -94,3 +101,16 @@ impl User {
|
||||
users::table.filter(users::token.eq(token)).first(conn).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Queryable, Debug)]
|
||||
pub struct Comment {
|
||||
pub id: i32,
|
||||
pub author_hash: String,
|
||||
pub author_title: String,
|
||||
pub content: String,
|
||||
pub create_time: NaiveDateTime,
|
||||
pub is_deleted: bool,
|
||||
pub post_id: i32,
|
||||
}
|
||||
|
||||
impl Comment {}
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
table! {
|
||||
comments (id) {
|
||||
id -> Integer,
|
||||
author_hash -> Text,
|
||||
author_title -> Text,
|
||||
content -> Text,
|
||||
create_time -> Timestamp,
|
||||
is_deleted -> Bool,
|
||||
post_id -> Integer,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
posts (id) {
|
||||
id -> Integer,
|
||||
@@ -26,6 +38,7 @@ table! {
|
||||
}
|
||||
|
||||
allow_tables_to_appear_in_same_query!(
|
||||
comments,
|
||||
posts,
|
||||
users,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user