From 6dfcb3f4ae6934765c5c591b8dbce687823dea49 Mon Sep 17 00:00:00 2001 From: Yjn024 <61787533+JieningYu@users.noreply.github.com> Date: Mon, 8 Jan 2024 15:03:47 +0800 Subject: [PATCH] Add notification module --- src/lib.rs | 1 + src/main.rs | 2 +- src/notification.rs | 102 ++++++++++++++++++++++++++++++++++++++++++++ src/tests/mod.rs | 2 +- 4 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 src/notification.rs diff --git a/src/lib.rs b/src/lib.rs index 14234ab..248fc87 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ use time::Duration; pub mod config; pub mod account; +pub mod notification; pub mod post; pub mod resource; diff --git a/src/main.rs b/src/main.rs index 4d09891..eba5b96 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use dmds::{IoHandle, World}; use lettre::AsyncSmtpTransport; use sms4_backend::{account::Account, config::Config, resource, Error}; -use tokio::sync::{Mutex, RwLock}; +use tokio::sync::Mutex; macro_rules! ipc { ($c:literal) => { diff --git a/src/notification.rs b/src/notification.rs new file mode 100644 index 0000000..bdd806d --- /dev/null +++ b/src/notification.rs @@ -0,0 +1,102 @@ +use std::{ + hash::{Hash, Hasher}, + time::SystemTime, +}; + +use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; + +/// Notification sent by admins, and displayed +/// by the screens. +/// +/// # dmds Dimensions +/// +/// ```txt +/// 0 -> id +/// 1 -> start date day of the year +/// ``` +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Notification { + /// Id of the notification. + #[serde(skip)] + id: u64, + + /// Title of the notification. + /// + /// # Examples + /// + /// ```txt + /// 教务通知 + /// ``` + /// + /// ```txt + /// 教务公告 + /// ``` + pub title: String, + /// Body of the notification. + pub body: String, + + /// Start time of the notification. + time: OffsetDateTime, + /// Sender's account id of the notification. + sender: u64, +} + +impl Notification { + /// Creates a new notification. + /// + /// The **id** of the notification is generated + /// from the body, time and current time. + pub fn new(title: String, body: String, time: OffsetDateTime, sender: u64) -> Self { + let mut hasher = siphasher::sip::SipHasher24::new(); + body.hash(&mut hasher); + time.hash(&mut hasher); + SystemTime::now().hash(&mut hasher); + + Self { + id: hasher.finish(), + title, + body, + time, + sender, + } + } + + /// Returns the id of the notification. + #[inline] + pub fn id(&self) -> u64 { + self.id + } +} + +impl dmds::Data for Notification { + const DIMS: usize = 2; + const VERSION: u32 = 1; + + #[inline] + fn dim(&self, dim: usize) -> u64 { + match dim { + 0 => self.id, + 1 => self.time.date().ordinal() as u64, + _ => unreachable!(), + } + } + + fn decode(version: u32, dims: &[u64], buf: B) -> std::io::Result { + match version { + 1 => bincode::deserialize_from(buf.reader()) + .map(|mut n: Self| { + n.id = dims[0]; + n + }) + .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err)), + _ => unreachable!("unsupported data version {version}"), + } + } + + #[inline] + fn encode(&self, buf: B) -> std::io::Result<()> { + bincode::serialize_into(buf.writer(), self) + .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err)) + } +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 8084183..77921f5 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -3,7 +3,7 @@ use std::{path::PathBuf, sync::Arc}; use axum::Router; use dmds::{mem_io_handle::MemStorage, world}; use sms4_backend::config::Config; -use tokio::sync::{Mutex, RwLock}; +use tokio::sync::Mutex; use crate::Global;