33use crate :: deserialize:: {
44 DeserializeBoolLenient , DeserializeNumberLenient , DeserializeValueLenient ,
55} ;
6+ use derivative:: Derivative ;
67use serde:: { Deserialize , Serialize } ;
78use serde_with:: { serde_as, skip_serializing_none} ;
89
10+ const IGNORE_ATTRIBUTES : [ & str ; 6 ] = [ "isDefault" , "id" , "active" , "user_id" , "config" , "name" ] ;
11+
912/// Represents a notification service in Uptime Kuma.
1013#[ skip_serializing_none]
1114#[ serde_as]
12- #[ derive( Clone , Default , Debug , PartialEq , Serialize , Deserialize , Eq ) ]
15+ #[ derive( Clone , Default , Debug , Serialize , Derivative , Deserialize , Eq ) ]
16+ #[ derivative( PartialEq ) ]
1317pub struct Notification {
1418 /// The unique identifier for the notification service.
1519 #[ serde( rename = "id" ) ]
@@ -26,7 +30,7 @@ pub struct Notification {
2630 pub active : Option < bool > ,
2731
2832 /// The user identifier associated with the notification service.
29- #[ serde( rename = "userId " ) ]
33+ #[ serde( rename = "user_id " ) ]
3034 #[ serde( alias = "user_id" ) ]
3135 pub user_id : Option < i32 > ,
3236
@@ -39,8 +43,36 @@ pub struct Notification {
3943 /// Additional service specific configuration in JSON format.
4044 #[ serde( rename = "config" ) ]
4145 #[ serde_as( as = "Option<DeserializeValueLenient>" ) ]
46+ #[ derivative( PartialEq ( compare_with = "config_eq" ) ) ]
4247 pub config : Option < serde_json:: Value > ,
4348}
4449
50+ fn config_eq ( a : & Option < serde_json:: Value > , b : & Option < serde_json:: Value > ) -> bool {
51+ match ( a, b) {
52+ ( None , None ) => true ,
53+ ( Some ( serde_json:: Value :: Object ( map_a) ) , Some ( serde_json:: Value :: Object ( map_b) ) ) => {
54+ let count_a = map_a
55+ . iter ( )
56+ . filter ( |( k, _) | !IGNORE_ATTRIBUTES . contains ( & k. as_str ( ) ) )
57+ . count ( ) ;
58+
59+ let count_b = map_b
60+ . iter ( )
61+ . filter ( |( k, _) | !IGNORE_ATTRIBUTES . contains ( & k. as_str ( ) ) )
62+ . count ( ) ;
63+
64+ if count_a != count_b {
65+ return false ;
66+ }
67+
68+ map_a
69+ . iter ( )
70+ . filter ( |( k, _) | !IGNORE_ATTRIBUTES . contains ( & k. as_str ( ) ) )
71+ . all ( |( k, v) | map_b. get ( k) . map_or ( false , |v_b| v == v_b) )
72+ }
73+ _ => a == b,
74+ }
75+ }
76+
4577/// A list of notification services.
4678pub type NotificationList = Vec < Notification > ;
0 commit comments