mirror of
https://gitlab.com/comunic/comunicapiv3
synced 2024-11-22 21:39:21 +00:00
Implement presence mechanismes
This commit is contained in:
parent
82bb23640a
commit
2f545574fa
@ -262,3 +262,12 @@ CREATE TABLE `comunic_custom_emojis` (
|
|||||||
`shortcut` VARCHAR(45) NULL,
|
`shortcut` VARCHAR(45) NULL,
|
||||||
`path` VARCHAR(255) NULL,
|
`path` VARCHAR(255) NULL,
|
||||||
PRIMARY KEY (`id`));
|
PRIMARY KEY (`id`));
|
||||||
|
|
||||||
|
CREATE TABLE `forez_presence` (
|
||||||
|
`id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` INT NULL,
|
||||||
|
`group_id` INT NULL,
|
||||||
|
`year` INT NULL,
|
||||||
|
`month` INT NULL,
|
||||||
|
`day` INT NULL,
|
||||||
|
PRIMARY KEY (`id`));
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
-- Nothing yet
|
|
||||||
ALTER TABLE `utilisateurs`
|
ALTER TABLE `utilisateurs`
|
||||||
ADD COLUMN `is_email_public` INT NULL DEFAULT 0 AFTER `allow_notif_sound`,
|
ADD COLUMN `is_email_public` INT NULL DEFAULT 0 AFTER `allow_notif_sound`,
|
||||||
ADD COLUMN `location` VARCHAR(45) NULL AFTER `is_email_visible`;
|
ADD COLUMN `location` VARCHAR(45) NULL AFTER `is_email_visible`;
|
||||||
|
|
||||||
|
CREATE TABLE `comunic`.`forez_presence` (
|
||||||
|
`id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` INT NULL,
|
||||||
|
`group_id` INT NULL,
|
||||||
|
`year` INT NULL,
|
||||||
|
`month` INT NULL,
|
||||||
|
`day` INT NULL,
|
||||||
|
PRIMARY KEY (`id`));
|
||||||
|
@ -57,6 +57,9 @@ pub mod database_tables_names {
|
|||||||
|
|
||||||
/// Notifications table
|
/// Notifications table
|
||||||
pub const NOTIFICATIONS_TABLE: &str = "comunic_notifications";
|
pub const NOTIFICATIONS_TABLE: &str = "comunic_notifications";
|
||||||
|
|
||||||
|
/// Forez presence table
|
||||||
|
pub const FOREZ_PRESENCE_TABLE: &str = "forez_presence";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push Notifications Database prefix
|
/// Push Notifications Database prefix
|
||||||
|
@ -5,12 +5,14 @@
|
|||||||
//!
|
//!
|
||||||
//! @author Pierre Hubert
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
use crate::data::http_request_handler::HttpRequestHandler;
|
|
||||||
use crate::routes::RequestResult;
|
|
||||||
use crate::data::config::conf;
|
|
||||||
use crate::data::base_request_handler::BaseRequestHandler;
|
|
||||||
use crate::api_data::group_api::GroupApi;
|
use crate::api_data::group_api::GroupApi;
|
||||||
use crate::helpers::groups_helper;
|
use crate::data::base_request_handler::BaseRequestHandler;
|
||||||
|
use crate::data::config::conf;
|
||||||
|
use crate::data::http_request_handler::HttpRequestHandler;
|
||||||
|
use crate::data::presence::Presence;
|
||||||
|
use crate::data::user_ws_request_handler::UserWsRequestHandler;
|
||||||
|
use crate::helpers::{forez_presence_helper, groups_helper};
|
||||||
|
use crate::routes::RequestResult;
|
||||||
|
|
||||||
/// Get the list of declared Forez groups in the application
|
/// Get the list of declared Forez groups in the application
|
||||||
pub fn get_list_groups(r: &mut HttpRequestHandler) -> RequestResult {
|
pub fn get_list_groups(r: &mut HttpRequestHandler) -> RequestResult {
|
||||||
@ -22,3 +24,114 @@ pub fn get_list_groups(r: &mut HttpRequestHandler) -> RequestResult {
|
|||||||
|
|
||||||
r.set_response(list)
|
r.set_response(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set presence
|
||||||
|
///
|
||||||
|
/// Presences format: YYYY,MM,DD;YYYY,MM,DD;...
|
||||||
|
pub fn set_presence(r: &mut UserWsRequestHandler) -> RequestResult {
|
||||||
|
let group = r.post_forez_group("group")?;
|
||||||
|
let presences = r.post_string_opt("presence", 0, false)?;
|
||||||
|
|
||||||
|
let mut list = vec![];
|
||||||
|
for p in presences.split(";") {
|
||||||
|
if p == "" {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let info: Vec<&str> = p.split(",").collect();
|
||||||
|
|
||||||
|
if info.len() != 3 {
|
||||||
|
r.bad_request("Invalid presence information!".to_string())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let year = info[0].parse::<u32>()?;
|
||||||
|
let month = info[1].parse::<u16>()?;
|
||||||
|
let day = info[2].parse::<u16>()?;
|
||||||
|
|
||||||
|
if year < 2020 || year > 2100 {
|
||||||
|
r.bad_request("Invalid year specified!".to_string())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if month < 1 || month > 12 {
|
||||||
|
r.bad_request("Invalid month specified!".to_string())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if day < 1 || day > 31 {
|
||||||
|
r.bad_request("Invalid day specified!".to_string())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let presence = Presence {
|
||||||
|
id: 0,
|
||||||
|
user_id: r.user_id()?,
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
day,
|
||||||
|
};
|
||||||
|
|
||||||
|
if !list.contains(&presence) {
|
||||||
|
list.push(presence);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
forez_presence_helper::update(&group, &r.user_id()?, list)?;
|
||||||
|
|
||||||
|
r.success("Presences updated.")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the list of presences of all the members of a group
|
||||||
|
///
|
||||||
|
/// Format: USER_ID,YYYY,MM,DD
|
||||||
|
pub fn get_list<H: BaseRequestHandler>(r: &mut H) -> RequestResult {
|
||||||
|
let group = r.post_forez_group("group")?;
|
||||||
|
let list = forez_presence_helper::get_list(&group)?;
|
||||||
|
|
||||||
|
let list = list
|
||||||
|
.iter()
|
||||||
|
.map(|p| format!("{},{},{},{}", p.user_id.id(), p.year, p.month, p.day))
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
|
r.set_response(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a new day of presence
|
||||||
|
pub fn add_day<H: BaseRequestHandler>(r: &mut H) -> RequestResult {
|
||||||
|
let group = r.post_forez_group("group")?;
|
||||||
|
|
||||||
|
let mut list = forez_presence_helper::get_user_presences(&group, &r.user_id()?)?;
|
||||||
|
|
||||||
|
let presence = Presence {
|
||||||
|
id: 0,
|
||||||
|
user_id: r.user_id()?,
|
||||||
|
year: r.post_u32("year")?,
|
||||||
|
month: r.post_u16("month")?,
|
||||||
|
day: r.post_u16("day")?,
|
||||||
|
};
|
||||||
|
|
||||||
|
if !list.contains(&presence) {
|
||||||
|
list.push(presence);
|
||||||
|
}
|
||||||
|
|
||||||
|
forez_presence_helper::update(&group, &r.user_id()?, list)?;
|
||||||
|
|
||||||
|
r.success("Updated presences.")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove a day of presence
|
||||||
|
pub fn del_day<H: BaseRequestHandler>(r: &mut H) -> RequestResult {
|
||||||
|
let group = r.post_forez_group("group")?;
|
||||||
|
|
||||||
|
let mut list = forez_presence_helper::get_user_presences(&group, &r.user_id()?)?;
|
||||||
|
|
||||||
|
let presence = Presence {
|
||||||
|
id: 0,
|
||||||
|
user_id: r.user_id()?,
|
||||||
|
year: r.post_u32("year")?,
|
||||||
|
month: r.post_u16("month")?,
|
||||||
|
day: r.post_u16("day")?,
|
||||||
|
};
|
||||||
|
|
||||||
|
list.retain(|el| el != &presence);
|
||||||
|
forez_presence_helper::update(&group, &r.user_id()?, list)?;
|
||||||
|
|
||||||
|
r.success("Updated presences.")
|
||||||
|
}
|
@ -14,6 +14,7 @@ use serde::Serialize;
|
|||||||
use crate::api_data::http_error::HttpError;
|
use crate::api_data::http_error::HttpError;
|
||||||
use crate::constants::PASSWORD_MIN_LENGTH;
|
use crate::constants::PASSWORD_MIN_LENGTH;
|
||||||
use crate::data::comment::Comment;
|
use crate::data::comment::Comment;
|
||||||
|
use crate::data::config::conf;
|
||||||
use crate::data::conversation::{ConversationMember, ConvID};
|
use crate::data::conversation::{ConversationMember, ConvID};
|
||||||
use crate::data::custom_emoji::CustomEmoji;
|
use crate::data::custom_emoji::CustomEmoji;
|
||||||
use crate::data::error::{ExecError, Res, ResultBoxError};
|
use crate::data::error::{ExecError, Res, ResultBoxError};
|
||||||
@ -484,6 +485,14 @@ pub trait BaseRequestHandler {
|
|||||||
Ok(self.post_string(name)?.parse::<u64>()?)
|
Ok(self.post_string(name)?.parse::<u64>()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn post_u32(&mut self, name: &str) -> Res<u32> {
|
||||||
|
Ok(self.post_u64(name)? as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_u16(&mut self, name: &str) -> Res<u16> {
|
||||||
|
Ok(self.post_u64(name)? as u16)
|
||||||
|
}
|
||||||
|
|
||||||
fn post_positive_u64_opt(&mut self, name: &str) -> Res<Option<u64>> {
|
fn post_positive_u64_opt(&mut self, name: &str) -> Res<Option<u64>> {
|
||||||
match self.post_u64_opt(name, 0)? {
|
match self.post_u64_opt(name, 0)? {
|
||||||
0 => Ok(None),
|
0 => Ok(None),
|
||||||
@ -796,4 +805,15 @@ pub trait BaseRequestHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a membership to a Forez group
|
||||||
|
fn post_forez_group(&mut self, name: &str) -> Res<GroupID> {
|
||||||
|
let group = self.post_group_id_with_access(name, GroupAccessLevel::MEMBER_ACCESS)?;
|
||||||
|
|
||||||
|
if !conf().forez_groups.contains(&group) {
|
||||||
|
self.bad_request(format!("The group {} is not a Forez group!", group.id()))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(group)
|
||||||
|
}
|
||||||
}
|
}
|
@ -40,3 +40,4 @@ pub mod user_ws_connection;
|
|||||||
pub mod call_signal;
|
pub mod call_signal;
|
||||||
pub mod new_notifications_settings;
|
pub mod new_notifications_settings;
|
||||||
pub mod push_notification;
|
pub mod push_notification;
|
||||||
|
pub mod presence;
|
22
src/data/presence.rs
Normal file
22
src/data/presence.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//! # Presence information
|
||||||
|
//!
|
||||||
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
|
use crate::data::user::UserID;
|
||||||
|
|
||||||
|
pub struct Presence {
|
||||||
|
pub id: u64,
|
||||||
|
pub user_id: UserID,
|
||||||
|
pub year: u32,
|
||||||
|
pub month: u16,
|
||||||
|
pub day: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Presence {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.user_id == other.user_id &&
|
||||||
|
self.year == other.year &&
|
||||||
|
self.month == other.month &&
|
||||||
|
self.day == other.day
|
||||||
|
}
|
||||||
|
}
|
@ -350,6 +350,16 @@ impl<'a> RowResult<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_u16(&self, name: &str) -> ResultBoxError<u16> {
|
||||||
|
let value = self.row.get_opt(self.find_col(name)?);
|
||||||
|
|
||||||
|
match value {
|
||||||
|
None => Err(ExecError::boxed_string(
|
||||||
|
format!("Could not extract integer field {} !", name))),
|
||||||
|
Some(s) => Ok(s?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Find an integer included in the request
|
/// Find an integer included in the request
|
||||||
pub fn get_usize(&self, name: &str) -> Result<usize, Box<dyn Error>> {
|
pub fn get_usize(&self, name: &str) -> Result<usize, Box<dyn Error>> {
|
||||||
let value = self.row.get_opt(self.find_col(name)?);
|
let value = self.row.get_opt(self.find_col(name)?);
|
||||||
@ -661,6 +671,11 @@ impl InsertQuery {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_u16(mut self, key: &str, value: u16) -> InsertQuery {
|
||||||
|
self.values.insert(key.to_string(), Value::from(value));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_user_id(mut self, key: &str, value: &UserID) -> InsertQuery {
|
pub fn add_user_id(mut self, key: &str, value: &UserID) -> InsertQuery {
|
||||||
self.values.insert(key.to_string(), Value::from(value.id()));
|
self.values.insert(key.to_string(), Value::from(value.id()));
|
||||||
self
|
self
|
||||||
|
62
src/helpers/forez_presence_helper.rs
Normal file
62
src/helpers/forez_presence_helper.rs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
//! # Forez Presence helper
|
||||||
|
//!
|
||||||
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
|
use crate::constants::database_tables_names::FOREZ_PRESENCE_TABLE;
|
||||||
|
use crate::data::error::Res;
|
||||||
|
use crate::data::group_id::GroupID;
|
||||||
|
use crate::data::presence::Presence;
|
||||||
|
use crate::data::user::UserID;
|
||||||
|
use crate::helpers::database;
|
||||||
|
|
||||||
|
/// Get the list of presence contained in the database
|
||||||
|
pub fn get_list(group_id: &GroupID) -> Res<Vec<Presence>> {
|
||||||
|
database::QueryInfo::new(FOREZ_PRESENCE_TABLE)
|
||||||
|
.cond_group_id("group_id", group_id)
|
||||||
|
.exec(db_to_presence)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the list of presences of a specific user
|
||||||
|
pub fn get_user_presences(group_id: &GroupID, user_id: &UserID) -> Res<Vec<Presence>> {
|
||||||
|
database::QueryInfo::new(FOREZ_PRESENCE_TABLE)
|
||||||
|
.cond_user_id("user_id", user_id)
|
||||||
|
.cond_group_id("group_id", group_id)
|
||||||
|
.exec(db_to_presence)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the presences of a user
|
||||||
|
pub fn update(group_id: &GroupID, user_id: &UserID, list: Vec<Presence>) -> Res {
|
||||||
|
let previous_presences = get_user_presences(group_id, user_id)?;
|
||||||
|
for presence in &list {
|
||||||
|
if !previous_presences.contains(presence) {
|
||||||
|
database::InsertQuery::new(FOREZ_PRESENCE_TABLE)
|
||||||
|
.add_user_id("user_id", user_id)
|
||||||
|
.add_group_id("group_id", group_id)
|
||||||
|
.add_u32("year", presence.year)
|
||||||
|
.add_u16("month", presence.month)
|
||||||
|
.add_u16("day", presence.day)
|
||||||
|
.insert()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for prev in &previous_presences {
|
||||||
|
if !list.contains(prev) {
|
||||||
|
database::DeleteQuery::new(FOREZ_PRESENCE_TABLE)
|
||||||
|
.cond_u64("id", prev.id)
|
||||||
|
.exec()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Turn a database entry into a presence entry
|
||||||
|
fn db_to_presence(row: &database::RowResult) -> Res<Presence> {
|
||||||
|
Ok(Presence {
|
||||||
|
id: row.get_u64("id")?,
|
||||||
|
user_id: row.get_user_id("user_id")?,
|
||||||
|
year: row.get_u32("year")?,
|
||||||
|
month: row.get_u16("month")?,
|
||||||
|
day: row.get_u16("day")?,
|
||||||
|
})
|
||||||
|
}
|
@ -21,3 +21,4 @@ pub mod calls_helper;
|
|||||||
pub mod push_notifications_helper;
|
pub mod push_notifications_helper;
|
||||||
pub mod independent_push_notifications_service_helper;
|
pub mod independent_push_notifications_service_helper;
|
||||||
pub mod firebase_notifications_helper;
|
pub mod firebase_notifications_helper;
|
||||||
|
pub mod forez_presence_helper;
|
@ -2,7 +2,7 @@
|
|||||||
//!
|
//!
|
||||||
//! @author Pierre Hubert
|
//! @author Pierre Hubert
|
||||||
|
|
||||||
use crate::controllers::{calls_controller, conversations_controller, likes_controller, user_ws_actions};
|
use crate::controllers::{calls_controller, conversations_controller, forez_controller, likes_controller, user_ws_actions};
|
||||||
use crate::data::error::Res;
|
use crate::data::error::Res;
|
||||||
use crate::data::user_ws_request_handler::UserWsRequestHandler;
|
use crate::data::user_ws_request_handler::UserWsRequestHandler;
|
||||||
|
|
||||||
@ -49,6 +49,11 @@ pub fn get_user_ws_routes() -> Vec<UserWsRoute> {
|
|||||||
UserWsRoute::new("calls/mark_ready", calls_controller::mark_user_ready),
|
UserWsRoute::new("calls/mark_ready", calls_controller::mark_user_ready),
|
||||||
UserWsRoute::new("calls/request_offer", calls_controller::request_offer),
|
UserWsRoute::new("calls/request_offer", calls_controller::request_offer),
|
||||||
UserWsRoute::new("calls/stop_streaming", calls_controller::stop_streaming),
|
UserWsRoute::new("calls/stop_streaming", calls_controller::stop_streaming),
|
||||||
|
|
||||||
|
// Presence controller
|
||||||
|
UserWsRoute::new("forez_presence/list", forez_controller::get_list),
|
||||||
|
UserWsRoute::new("forez_presence/add_day", forez_controller::add_day),
|
||||||
|
UserWsRoute::new("forez_presence/del_day", forez_controller::del_day),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user