mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
feat(api): add moderation events and visibility actions (#3219)
This commit is contained in:
@@ -4,14 +4,19 @@ const USER_FLAG_BUG_HUNTER: i64 = 1 << 3;
|
||||
const USER_FLAG_FRIENDLY_BOT: i64 = 1 << 4;
|
||||
const USER_FLAG_FRIENDLY_BOT_MANUAL_APPROVAL: i64 = 1 << 5;
|
||||
const USER_FLAG_SPAMMER: i64 = 1 << 6;
|
||||
pub const USER_FLAG_PROFILE_HIDDEN: i64 = 1 << 7;
|
||||
const USER_FLAG_DELETED: i64 = 1 << 34;
|
||||
const USER_FLAG_DISABLED: i64 = 1 << 38;
|
||||
pub const USER_FLAG_STAFF_HIDDEN: i64 = 1 << 57;
|
||||
const PUBLIC_USER_FLAGS: i64 = USER_FLAG_STAFF
|
||||
| USER_FLAG_PARTNER
|
||||
| USER_FLAG_BUG_HUNTER
|
||||
| USER_FLAG_FRIENDLY_BOT
|
||||
| USER_FLAG_FRIENDLY_BOT_MANUAL_APPROVAL
|
||||
| USER_FLAG_SPAMMER;
|
||||
| USER_FLAG_SPAMMER
|
||||
| USER_FLAG_PROFILE_HIDDEN;
|
||||
const PUBLIC_USER_FLAGS_WITHOUT_STAFF: i64 = PUBLIC_USER_FLAGS & !USER_FLAG_STAFF;
|
||||
const NON_ENFORCEMENT_DELETION_REASONS: [i32; 3] = [1, 2, 19];
|
||||
|
||||
pub fn visible_user_flags(flags: i64) -> i32 {
|
||||
let visible_flags = if (flags & USER_FLAG_STAFF_HIDDEN) != 0 {
|
||||
@@ -21,3 +26,79 @@ pub fn visible_user_flags(flags: i64) -> i32 {
|
||||
};
|
||||
(flags & visible_flags) as i32
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub struct AccountStanding {
|
||||
pub flags: i64,
|
||||
pub temp_banned_until_ms: Option<i64>,
|
||||
pub pending_deletion_at_ms: Option<i64>,
|
||||
pub deletion_reason_code: Option<i32>,
|
||||
}
|
||||
|
||||
impl AccountStanding {
|
||||
pub fn deleted_for_display(&self) -> bool {
|
||||
self.flags & USER_FLAG_DELETED != 0 && self.pending_deletion_at_ms.is_none()
|
||||
}
|
||||
|
||||
pub fn profile_hidden(&self, now_ms: i64) -> bool {
|
||||
let banned = self.flags & USER_FLAG_DISABLED != 0
|
||||
&& self
|
||||
.temp_banned_until_ms
|
||||
.is_some_and(|until| until > now_ms);
|
||||
let deleting = self.pending_deletion_at_ms.is_some()
|
||||
&& self
|
||||
.deletion_reason_code
|
||||
.is_some_and(|code| !NON_ENFORCEMENT_DELETION_REASONS.contains(&code));
|
||||
!self.deleted_for_display()
|
||||
&& (self.flags & (USER_FLAG_PROFILE_HIDDEN | USER_FLAG_SPAMMER) != 0
|
||||
|| banned
|
||||
|| deleting)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const NOW: i64 = 1_790_000_000_000;
|
||||
|
||||
fn standing(flags: i64) -> AccountStanding {
|
||||
AccountStanding {
|
||||
flags,
|
||||
..AccountStanding::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_hidden_follows_enforcement_state() {
|
||||
assert!(!standing(0).profile_hidden(NOW));
|
||||
assert!(standing(USER_FLAG_PROFILE_HIDDEN).profile_hidden(NOW));
|
||||
assert!(standing(USER_FLAG_SPAMMER).profile_hidden(NOW));
|
||||
assert!(!standing(USER_FLAG_DISABLED).profile_hidden(NOW));
|
||||
let banned = AccountStanding {
|
||||
temp_banned_until_ms: Some(NOW + 1),
|
||||
..standing(USER_FLAG_DISABLED)
|
||||
};
|
||||
assert!(banned.profile_hidden(NOW));
|
||||
assert!(!banned.profile_hidden(NOW + 1));
|
||||
let deleting = |code| AccountStanding {
|
||||
pending_deletion_at_ms: Some(NOW),
|
||||
deletion_reason_code: Some(code),
|
||||
..standing(USER_FLAG_DELETED)
|
||||
};
|
||||
assert!(deleting(3).profile_hidden(NOW));
|
||||
assert!(deleting(20).profile_hidden(NOW));
|
||||
for code in NON_ENFORCEMENT_DELETION_REASONS {
|
||||
assert!(!deleting(code).profile_hidden(NOW), "{code}");
|
||||
}
|
||||
assert!(!standing(USER_FLAG_DELETED | USER_FLAG_SPAMMER).profile_hidden(NOW));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_hidden_bit_is_public() {
|
||||
assert_eq!(
|
||||
visible_user_flags(USER_FLAG_PROFILE_HIDDEN | USER_FLAG_DISABLED),
|
||||
USER_FLAG_PROFILE_HIDDEN as i32
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user