mirror of
https://github.com/freedit-org/freedit.git
synced 2026-04-25 03:05:37 -04:00
[wip] notifications
This commit is contained in:
@@ -15,7 +15,7 @@ use super::{
|
||||
extract_element, get_batch, get_count_by_prefix, get_ids_by_prefix, get_ids_by_tag,
|
||||
get_inn_role, get_one, get_range, get_site_config, get_uid_by_name, has_unread, incr_id,
|
||||
into_response, is_mod, ivec_to_u32,
|
||||
notification::{mark_read, NtType},
|
||||
notification::{add_notification, mark_read, NtType},
|
||||
timestamp_to_date, u32_to_ivec, u8_slice_to_u32, user_stats,
|
||||
utils::md2html,
|
||||
Claim, Comment, FormPost, Inn, PageData, ParamsPage, Post, User, ValidatedForm,
|
||||
@@ -33,7 +33,7 @@ use axum::{
|
||||
use bincode::config::standard;
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use serde::Deserialize;
|
||||
use sled::{Batch, Db, IVec};
|
||||
use sled::{Batch, Db};
|
||||
use std::{collections::BTreeSet, path::PathBuf};
|
||||
use validator::Validate;
|
||||
|
||||
@@ -1342,7 +1342,6 @@ pub(crate) async fn comment_post(
|
||||
|
||||
// extract @username or @uid notificaiton
|
||||
let notifications = extract_element(&content, 5, '@');
|
||||
let notification_tree = db.open_tree("notifications")?;
|
||||
for notification in ¬ifications {
|
||||
let (uid, username) = match notification.parse::<u32>() {
|
||||
Ok(uid) => {
|
||||
@@ -1366,18 +1365,9 @@ pub(crate) async fn comment_post(
|
||||
content = content.replace(&from, &to);
|
||||
|
||||
// notify user to be mentioned in comment
|
||||
|
||||
// prevent duplicate notifications
|
||||
if uid != post.uid {
|
||||
let nid = incr_id(&db, "notifications_count")?;
|
||||
let k = [
|
||||
&u32_to_ivec(uid),
|
||||
&u32_to_ivec(nid),
|
||||
&IVec::from(&[NtType::PostMention as u8]),
|
||||
]
|
||||
.concat();
|
||||
let v = [&pid_ivec, &u32_to_ivec(cid), &IVec::from(&[0])].concat();
|
||||
notification_tree.insert(k, v)?;
|
||||
add_notification(&db, uid, NtType::PostMention, pid, cid)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1438,15 +1428,7 @@ pub(crate) async fn comment_post(
|
||||
|
||||
// notify post author
|
||||
if post.uid != claim.uid {
|
||||
let nid = incr_id(&db, "notifications_count")?;
|
||||
let k = [
|
||||
&u32_to_ivec(post.uid),
|
||||
&u32_to_ivec(nid),
|
||||
&IVec::from(&[NtType::PostComment as u8]),
|
||||
]
|
||||
.concat();
|
||||
let v = [&pid_ivec, &u32_to_ivec(cid), &IVec::from(&[0])].concat();
|
||||
notification_tree.insert(k, v)?;
|
||||
add_notification(&db, post.uid, NtType::PostComment, pid, cid)?;
|
||||
}
|
||||
|
||||
user_stats(&db, claim.uid, "comment")?;
|
||||
|
||||
@@ -9,13 +9,13 @@ use axum::{
|
||||
};
|
||||
use bincode::config::standard;
|
||||
use serde::Deserialize;
|
||||
use sled::Db;
|
||||
use sled::{Db, IVec};
|
||||
|
||||
use crate::error::AppError;
|
||||
|
||||
use super::{
|
||||
get_ids_by_prefix, get_one, get_site_config, has_unread, into_response, u32_to_ivec,
|
||||
u8_slice_to_u32, Claim, Comment, PageData, Post, Solo, User,
|
||||
get_ids_by_prefix, get_one, get_site_config, has_unread, incr_id, into_response, u32_to_ivec,
|
||||
u8_slice_to_u32, Claim, Comment, Inn, PageData, Post, Solo, User,
|
||||
};
|
||||
|
||||
/// notification.html
|
||||
@@ -217,7 +217,43 @@ pub(crate) async fn notification(
|
||||
};
|
||||
notifications.push(notification);
|
||||
}
|
||||
_ => todo!(),
|
||||
NtType::InnNotification => {
|
||||
let role = u8_slice_to_u32(&value[0..4]);
|
||||
let iid = u8_slice_to_u32(&value[4..8]);
|
||||
let inn: Inn = get_one(&db, "inns", iid)?;
|
||||
let notification = Notification {
|
||||
nid,
|
||||
nt_type: nt_type.to_string(),
|
||||
uid: claim.uid,
|
||||
username: claim.username.clone(),
|
||||
id1: 0,
|
||||
id2: 0,
|
||||
id3: 0,
|
||||
content1: "".into(),
|
||||
content2: format!(
|
||||
"Your role in {} (id:{}) has been changed to {role}",
|
||||
inn.inn_name, iid
|
||||
),
|
||||
is_read: value[8] == 1,
|
||||
};
|
||||
notifications.push(notification);
|
||||
}
|
||||
NtType::SiteNotification => {
|
||||
let role = u8_slice_to_u32(&value[0..4]);
|
||||
let notification = Notification {
|
||||
nid,
|
||||
nt_type: nt_type.to_string(),
|
||||
uid: claim.uid,
|
||||
username: claim.username.clone(),
|
||||
id1: 0,
|
||||
id2: 0,
|
||||
id3: 0,
|
||||
content1: "".into(),
|
||||
content2: format!("Your site role has been changed to {role}"),
|
||||
is_read: value[8] == 1,
|
||||
};
|
||||
notifications.push(notification);
|
||||
}
|
||||
}
|
||||
|
||||
if n >= 30 {
|
||||
@@ -258,3 +294,23 @@ struct InnNotification {
|
||||
iid: u32,
|
||||
uid: u32,
|
||||
}
|
||||
|
||||
pub(super) fn add_notification(
|
||||
db: &Db,
|
||||
uid: u32,
|
||||
nt_type: NtType,
|
||||
id1: u32,
|
||||
id2: u32,
|
||||
) -> Result<(), AppError> {
|
||||
let nid = incr_id(db, "notifications_count")?;
|
||||
let k = [
|
||||
&u32_to_ivec(uid),
|
||||
&u32_to_ivec(nid),
|
||||
&IVec::from(&[nt_type as u8]),
|
||||
]
|
||||
.concat();
|
||||
let v = [&u32_to_ivec(id1), &u32_to_ivec(id2), &IVec::from(&[0])].concat();
|
||||
db.open_tree("notifications")?.insert(k, v)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::{
|
||||
extract_element, get_count_by_prefix, get_ids_by_prefix, get_ids_by_tag, get_one, get_range,
|
||||
get_referer, get_site_config, get_uid_by_name, has_unread, incr_id, into_response, ivec_to_u32,
|
||||
notification::{mark_read, NtType},
|
||||
notification::{add_notification, mark_read, NtType},
|
||||
timestamp_to_date, u32_to_ivec, u8_slice_to_u32, user_stats,
|
||||
utils::md2html,
|
||||
Claim, IterType, PageData, ParamsPage, Solo, User, ValidatedForm,
|
||||
@@ -16,7 +16,7 @@ use axum::{
|
||||
use bincode::config::standard;
|
||||
use chrono::Utc;
|
||||
use serde::Deserialize;
|
||||
use sled::{Db, IVec};
|
||||
use sled::Db;
|
||||
use validator::Validate;
|
||||
|
||||
/// Form data: `/solo/user/:uid` solo create.
|
||||
@@ -370,9 +370,10 @@ pub(crate) async fn solo_post(
|
||||
let mut hashtags = Vec::new();
|
||||
|
||||
let replied_uesr;
|
||||
let reply_to = if input.reply_to == 0 {
|
||||
let reply_to;
|
||||
if input.reply_to == 0 {
|
||||
replied_uesr = None;
|
||||
None
|
||||
reply_to = None;
|
||||
} else {
|
||||
let mut solo_replied: Solo = get_one(&db, "solos", input.reply_to)?;
|
||||
solo_replied.replies.push(sid);
|
||||
@@ -382,23 +383,16 @@ pub(crate) async fn solo_post(
|
||||
.insert(&u32_to_ivec(input.reply_to), solo_replied_encode)?;
|
||||
|
||||
if solo_replied.uid != uid {
|
||||
let nid = incr_id(&db, "notifications_count")?;
|
||||
let k = [
|
||||
&u32_to_ivec(solo_replied.uid),
|
||||
&u32_to_ivec(nid),
|
||||
&IVec::from(&[NtType::SoloComment as u8]),
|
||||
]
|
||||
.concat();
|
||||
let v = [
|
||||
&u32_to_ivec(input.reply_to),
|
||||
&u32_to_ivec(sid),
|
||||
&IVec::from(&[0]),
|
||||
]
|
||||
.concat();
|
||||
db.open_tree("notifications")?.insert(k, v)?;
|
||||
add_notification(
|
||||
&db,
|
||||
solo_replied.uid,
|
||||
NtType::SoloComment,
|
||||
input.reply_to,
|
||||
sid,
|
||||
)?;
|
||||
}
|
||||
|
||||
Some(input.reply_to)
|
||||
reply_to = Some(input.reply_to)
|
||||
};
|
||||
|
||||
if visibility == 0 {
|
||||
@@ -417,7 +411,6 @@ pub(crate) async fn solo_post(
|
||||
|
||||
// extract @username or @uid notificaiton
|
||||
let notifications = extract_element(&content, 5, '@');
|
||||
let notification_tree = db.open_tree("notifications")?;
|
||||
for notification in ¬ifications {
|
||||
let (uid, username) = match notification.parse::<u32>() {
|
||||
Ok(uid) => {
|
||||
@@ -442,15 +435,7 @@ pub(crate) async fn solo_post(
|
||||
|
||||
// notify user to be mentioned in comment
|
||||
if uid != claim.uid && replied_uesr != Some(uid) {
|
||||
let nid = incr_id(&db, "notifications_count")?;
|
||||
let k = [
|
||||
&u32_to_ivec(uid),
|
||||
&u32_to_ivec(nid),
|
||||
&IVec::from(&[NtType::SoloMention as u8]),
|
||||
]
|
||||
.concat();
|
||||
let v = [&sid_ivec, &u32_to_ivec(0), &IVec::from(&[0])].concat();
|
||||
notification_tree.insert(k, v)?;
|
||||
add_notification(&db, uid, NtType::SoloMention, sid, 0)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
use super::{
|
||||
generate_nanoid_expire, get_count_by_prefix, get_ids_by_prefix, get_inn_role, get_one,
|
||||
get_range, get_site_config, get_uid_by_name, incr_id, into_response, is_mod, timestamp_to_date,
|
||||
u32_to_ivec, u8_slice_to_u32, user_stats, Claim, Inn, IterType, PageData, ParamsPage,
|
||||
SiteConfig, User, ValidatedForm,
|
||||
get_range, get_site_config, get_uid_by_name, incr_id, into_response, is_mod,
|
||||
notification::{add_notification, NtType},
|
||||
timestamp_to_date, u32_to_ivec, u8_slice_to_u32, user_stats, Claim, Inn, IterType, PageData,
|
||||
ParamsPage, SiteConfig, User, ValidatedForm,
|
||||
};
|
||||
use crate::{config::CONFIG, controller::get_count, error::AppError};
|
||||
use ::rand::{thread_rng, Rng};
|
||||
@@ -360,15 +361,15 @@ pub(crate) async fn role_post(
|
||||
|
||||
let inn_users_k = [&u32_to_ivec(id), &u32_to_ivec(uid)].concat();
|
||||
|
||||
// protect super
|
||||
if let Some(user_inn_role) = get_inn_role(&db, id, uid)? {
|
||||
if user_inn_role > inn_role {
|
||||
return Err(AppError::Unauthorized);
|
||||
}
|
||||
let old_inn_role = get_inn_role(&db, id, uid)?.unwrap_or_default();
|
||||
|
||||
if user_inn_role == 1 && form.role != "Pending" {
|
||||
db.open_tree("inn_apply")?.remove(&inn_users_k)?;
|
||||
}
|
||||
// protect super
|
||||
if old_inn_role > inn_role {
|
||||
return Err(AppError::Unauthorized);
|
||||
}
|
||||
|
||||
if old_inn_role == 1 && form.role != "Pending" {
|
||||
db.open_tree("inn_apply")?.remove(&inn_users_k)?;
|
||||
}
|
||||
|
||||
let inn_role: u8 = match form.role.as_str() {
|
||||
@@ -391,20 +392,24 @@ pub(crate) async fn role_post(
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
db.open_tree("inn_users")?
|
||||
.insert(&inn_users_k, &[inn_role])?;
|
||||
if old_inn_role != inn_role {
|
||||
db.open_tree("inn_users")?
|
||||
.insert(&inn_users_k, &[inn_role])?;
|
||||
|
||||
let user_inns_k = [&u32_to_ivec(uid), &u32_to_ivec(id)].concat();
|
||||
if inn_role >= 3 {
|
||||
db.open_tree("user_inns")?.insert(&user_inns_k, &[])?;
|
||||
} else {
|
||||
db.open_tree("user_inns")?.remove(&user_inns_k)?;
|
||||
}
|
||||
let user_inns_k = [&u32_to_ivec(uid), &u32_to_ivec(id)].concat();
|
||||
if inn_role >= 3 {
|
||||
db.open_tree("user_inns")?.insert(&user_inns_k, &[])?;
|
||||
} else {
|
||||
db.open_tree("user_inns")?.remove(&user_inns_k)?;
|
||||
}
|
||||
|
||||
if inn_role >= 8 {
|
||||
db.open_tree("mod_inns")?.insert(&user_inns_k, &[])?;
|
||||
} else {
|
||||
db.open_tree("mod_inns")?.remove(&user_inns_k)?;
|
||||
if inn_role >= 8 {
|
||||
db.open_tree("mod_inns")?.insert(&user_inns_k, &[])?;
|
||||
} else {
|
||||
db.open_tree("mod_inns")?.remove(&user_inns_k)?;
|
||||
}
|
||||
|
||||
add_notification(&db, uid, NtType::InnNotification, inn_role as u32, id)?;
|
||||
}
|
||||
|
||||
target = format!("/user/list?filter=inn&id={id}");
|
||||
@@ -415,18 +420,24 @@ pub(crate) async fn role_post(
|
||||
}
|
||||
|
||||
let mut user: User = get_one(&db, "users", uid)?;
|
||||
user.role = match form.role.as_str() {
|
||||
let role = match form.role.as_str() {
|
||||
"Admin" => 255,
|
||||
"Senior" => 100,
|
||||
"Standard" => 10,
|
||||
"Banned" => 0,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let user_encode = bincode::encode_to_vec(&user, standard())?;
|
||||
db.open_tree("users")?
|
||||
.insert(&u32_to_ivec(uid), user_encode)?;
|
||||
|
||||
Claim::update_role(&db, uid)?;
|
||||
if user.role != role {
|
||||
user.role = role;
|
||||
let user_encode = bincode::encode_to_vec(&user, standard())?;
|
||||
db.open_tree("users")?
|
||||
.insert(&u32_to_ivec(uid), user_encode)?;
|
||||
|
||||
Claim::update_role(&db, uid)?;
|
||||
|
||||
add_notification(&db, uid, NtType::SiteNotification, role as u32, 0)?;
|
||||
}
|
||||
target = "/user/list".to_string();
|
||||
}
|
||||
Ordering::Less => unreachable!(),
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
{% if !nt.is_read %}
|
||||
<a href="/notification?nid={{nt.nid}}&op_type=mark"><span class="tag is-info" title="Mark as read">✔️</span></a>
|
||||
{% endif %}
|
||||
<a href="/notification?iid={{nt.nid}}&op_type=delete"><span class="tag is-danger" title="Delete notification">❌</span></a>
|
||||
<a href="/notification?nid={{nt.nid}}&op_type=delete"><span class="tag is-danger" title="Delete notification">❌</span></a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
Reference in New Issue
Block a user