fix: no more id collisions
This commit is contained in:
parent
71d017693c
commit
0b3573a513
11 changed files with 151 additions and 120 deletions
|
@ -234,7 +234,7 @@ and show_community and community.id != config.town_square or question %}
|
|||
{% else %}
|
||||
<details>
|
||||
<summary
|
||||
class="card flex gap-2 items-center secondary red w-full"
|
||||
class="card flex gap-2 items-center tertiary red w-full"
|
||||
>
|
||||
{{ icon "triangle-alert" }}
|
||||
<b>{{ post.context.content_warning }}</b>
|
||||
|
|
|
@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
|
|||
use totp_rs::TOTP;
|
||||
use tetratto_shared::{
|
||||
hash::{hash_salted, salt},
|
||||
snow::AlmostSnowflake,
|
||||
snow::Snowflake,
|
||||
unix_epoch_timestamp,
|
||||
};
|
||||
|
||||
|
@ -227,10 +227,7 @@ impl User {
|
|||
let password = hash_salted(password, salt.clone());
|
||||
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
username,
|
||||
password,
|
||||
|
@ -408,10 +405,7 @@ impl Notification {
|
|||
/// Returns a new [`Notification`].
|
||||
pub fn new(title: String, content: String, owner: usize) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
title,
|
||||
content,
|
||||
|
@ -434,10 +428,7 @@ impl UserFollow {
|
|||
/// Create a new [`UserFollow`].
|
||||
pub fn new(initiator: usize, receiver: usize) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
initiator,
|
||||
receiver,
|
||||
|
@ -465,10 +456,7 @@ impl UserBlock {
|
|||
/// Create a new [`UserBlock`].
|
||||
pub fn new(initiator: usize, receiver: usize) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
initiator,
|
||||
receiver,
|
||||
|
@ -488,10 +476,7 @@ impl IpBlock {
|
|||
/// Create a new [`IpBlock`].
|
||||
pub fn new(initiator: usize, receiver: String) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
initiator,
|
||||
receiver,
|
||||
|
@ -532,10 +517,7 @@ impl UserWarning {
|
|||
/// Create a new [`UserWarning`].
|
||||
pub fn new(user: usize, moderator: usize, content: String) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
receiver: user,
|
||||
moderator,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use serde::{Serialize, Deserialize};
|
||||
use tetratto_shared::{snow::AlmostSnowflake, unix_epoch_timestamp};
|
||||
use tetratto_shared::{snow::Snowflake, unix_epoch_timestamp};
|
||||
|
||||
use super::communities_permissions::CommunityPermission;
|
||||
|
||||
|
@ -30,10 +30,7 @@ impl Channel {
|
|||
/// Create a new [`Channel`].
|
||||
pub fn new(community: usize, owner: usize, position: usize, title: String) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
community,
|
||||
owner,
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
|
@ -84,10 +81,7 @@ impl Message {
|
|||
let now = unix_epoch_timestamp() as usize;
|
||||
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
channel,
|
||||
owner,
|
||||
created: now,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use tetratto_shared::{snow::AlmostSnowflake, unix_epoch_timestamp};
|
||||
use tetratto_shared::{snow::Snowflake, unix_epoch_timestamp};
|
||||
use super::communities_permissions::CommunityPermission;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
|
@ -30,10 +30,7 @@ impl Community {
|
|||
/// Create a new [`Community`].
|
||||
pub fn new(title: String, owner: usize) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
title: title.clone(),
|
||||
context: CommunityContext {
|
||||
|
@ -145,10 +142,7 @@ impl CommunityMembership {
|
|||
/// Create a new [`CommunityMembership`].
|
||||
pub fn new(owner: usize, community: usize, role: CommunityPermission) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
owner,
|
||||
community,
|
||||
|
@ -250,10 +244,7 @@ impl Post {
|
|||
owner: usize,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
content,
|
||||
owner,
|
||||
|
@ -328,10 +319,7 @@ impl Question {
|
|||
ip: String,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
owner,
|
||||
receiver,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use tetratto_shared::{snow::AlmostSnowflake, unix_epoch_timestamp};
|
||||
use tetratto_shared::{snow::Snowflake, unix_epoch_timestamp};
|
||||
|
||||
use super::reactions::AssetType;
|
||||
|
||||
|
@ -15,10 +15,7 @@ impl AuditLogEntry {
|
|||
/// Create a new [`AuditLogEntry`].
|
||||
pub fn new(moderator: usize, content: String) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
moderator,
|
||||
content,
|
||||
|
@ -40,10 +37,7 @@ impl Report {
|
|||
/// Create a new [`Report`].
|
||||
pub fn new(owner: usize, content: String, asset: usize, asset_type: AssetType) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
owner,
|
||||
content,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use tetratto_shared::{snow::AlmostSnowflake, unix_epoch_timestamp};
|
||||
use tetratto_shared::{snow::Snowflake, unix_epoch_timestamp};
|
||||
|
||||
/// All of the items which support reactions.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
@ -28,10 +28,7 @@ impl Reaction {
|
|||
/// Create a new [`Reaction`].
|
||||
pub fn new(owner: usize, asset: usize, asset_type: AssetType, is_like: bool) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
owner,
|
||||
asset,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use serde::{Serialize, Deserialize};
|
||||
use tetratto_shared::{snow::AlmostSnowflake, unix_epoch_timestamp};
|
||||
use tetratto_shared::{snow::Snowflake, unix_epoch_timestamp};
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum ActionType {
|
||||
|
@ -32,10 +32,7 @@ impl ActionRequest {
|
|||
/// Create a new [`ActionRequest`].
|
||||
pub fn new(owner: usize, action_type: ActionType, linked_asset: usize) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
owner,
|
||||
action_type,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use serde::{Serialize, Deserialize};
|
||||
use tetratto_shared::{snow::AlmostSnowflake, unix_epoch_timestamp};
|
||||
use tetratto_shared::{snow::Snowflake, unix_epoch_timestamp};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum MediaType {
|
||||
|
@ -27,10 +27,7 @@ impl MediaUpload {
|
|||
/// Create a new [`MediaUpload`].
|
||||
pub fn new(what: MediaType, owner: usize) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
owner,
|
||||
what,
|
||||
|
@ -61,10 +58,7 @@ impl CustomEmoji {
|
|||
is_animated: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: AlmostSnowflake::new(1234567890)
|
||||
.to_string()
|
||||
.parse::<usize>()
|
||||
.unwrap(),
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
owner,
|
||||
community,
|
||||
|
|
|
@ -11,8 +11,8 @@ ammonia = "4.1.0"
|
|||
chrono = "0.4.41"
|
||||
comrak = "0.38.0"
|
||||
hex_fmt = "0.3.0"
|
||||
num-bigint = "0.4.6"
|
||||
rand = "0.9.1"
|
||||
serde = "1.0.219"
|
||||
sha2 = "0.10.8"
|
||||
snowflaked = "1.0.3"
|
||||
uuid = { version = "1.16.0", features = ["v4"] }
|
||||
|
|
|
@ -1,51 +1,29 @@
|
|||
//! Almost Snowflake
|
||||
//!
|
||||
//! Random IDs which include timestamp information (like Twitter Snowflakes)
|
||||
//!
|
||||
//! IDs are generated with 41 bits of an epoch timestamp, 10 bits of a machine/server ID, and 12 bits of randomly generated numbers.
|
||||
//!
|
||||
//! ```
|
||||
//! tttttttttttttttttttttttttttttttttttttttttiiiiiiiiiirrrrrrrrrrrr...
|
||||
//! Timestamp ID Seed
|
||||
//! ```
|
||||
use crate::epoch_timestamp;
|
||||
use std::time::{UNIX_EPOCH, Duration};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use snowflaked::{Builder, Generator};
|
||||
|
||||
use num_bigint::BigInt;
|
||||
use rand::Rng;
|
||||
|
||||
static SEED_LEN: usize = 12;
|
||||
// static ID_LEN: usize = 10;
|
||||
pub const EPOCH_2024: u64 = 1704067200000;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct AlmostSnowflake(String);
|
||||
pub struct Snowflake(String);
|
||||
|
||||
pub fn bigint(input: usize) -> BigInt {
|
||||
BigInt::from(input)
|
||||
}
|
||||
impl Snowflake {
|
||||
pub fn builder() -> Builder {
|
||||
Builder::new().epoch(UNIX_EPOCH + Duration::from_millis(EPOCH_2024))
|
||||
}
|
||||
|
||||
impl AlmostSnowflake {
|
||||
/// Create a new [`AlmostSnowflake`]
|
||||
pub fn new(server_id: usize) -> Self {
|
||||
// generate random bytes
|
||||
let mut bytes = String::new();
|
||||
|
||||
let mut rng = rand::rng();
|
||||
for _ in 1..=SEED_LEN {
|
||||
bytes.push_str(&rng.random_range(0..10).to_string())
|
||||
}
|
||||
|
||||
// build id
|
||||
let mut id = bigint(epoch_timestamp(2024) as usize) << 22_u128;
|
||||
id |= bigint((server_id % 1024) << 12);
|
||||
id |= bigint((bytes.parse::<usize>().unwrap() + 1) % 4096);
|
||||
|
||||
// return
|
||||
Self(id.to_string())
|
||||
pub fn new() -> Self {
|
||||
Self(
|
||||
Self::builder()
|
||||
.build::<Generator>()
|
||||
.generate::<u64>()
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for AlmostSnowflake {
|
||||
impl std::fmt::Display for Snowflake {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue