3
3
from pymongo import MongoClient
4
4
from pymongo .database import Database
5
5
from pymongo .collection import Collection
6
- from typing import Any , Dict , List , Optional
7
6
from pymongo .errors import ConnectionFailure
7
+ from typing import Any , Dict , List , Optional , Tuple
8
8
9
9
10
10
class NoticeDB :
@@ -87,21 +87,46 @@ def delete_successful_ntfy_subscribers(self, notice_uid: str) -> None:
87
87
88
88
# Update the document to set the subscribers list to an empty list
89
89
collection .delete_one ({"uid" : uid })
90
-
91
- def find_new_notices (self , uid_list : List [str ]) -> List [str ]:
92
- """Find and return the list of UIDs that have not been sent."""
93
- # Query for UIDs that exist in the database
94
- query = {"UID" : {"$in" : uid_list }}
95
- sent_notices = self .__find_many (query , {"UID" : 1 })
96
-
97
- # Extract UIDs that are already sent
98
- sent_uids = set ()
99
- if sent_notices :
100
- sent_uids = {notice ["UID" ] for notice in sent_notices }
101
-
102
- # Return UIDs that are not sent
103
- return [uid for uid in uid_list if uid not in sent_uids ]
104
90
91
+ def find_to_send_notices (self , latest_X_notices : List [Dict [str , str ]]) -> Tuple [List [Dict [str , str ]], List [Dict [str , str ]]]:
92
+ """Find new and modified notices compared to existing records in the database."""
93
+ # Check if latest_X_notices is empty
94
+ if not latest_X_notices :
95
+ return [], []
96
+
97
+ # Prepare a query to match all notices
98
+ latest_X_uids = [notice ['UID' ] for notice in latest_X_notices ]
99
+ query = {"UID" : {"$in" : latest_X_uids }}
100
+
101
+ # Find all existing notices that match any of the criteria
102
+ existing_notices = self .__find_many (query )
103
+ if not existing_notices :
104
+ return latest_X_notices , []
105
+
106
+ # Create a mapping of existing notices by UID
107
+ existing_notices_map = {notice ['UID' ]: notice for notice in existing_notices }
108
+
109
+ new_notices , modified_notices = [], []
110
+ for latest_notice in latest_X_notices :
111
+ uid = latest_notice .get ('UID' )
112
+
113
+ if uid not in existing_notices_map :
114
+ # New notice
115
+ new_notices .append (latest_notice )
116
+ else :
117
+ # Check if the notice is modified
118
+ existing_notice = existing_notices_map [uid ]
119
+ is_modified = any (
120
+ existing_notice .get (key ) != value
121
+ for key , value in latest_notice .items ()
122
+ if key != 'BodyData'
123
+ )
124
+
125
+ if is_modified :
126
+ modified_notices .append (latest_notice )
127
+
128
+ return new_notices , modified_notices
129
+
105
130
def save_notice (self , document : Dict ) -> str :
106
131
return self .__insert_one (document )
107
132
@@ -115,8 +140,17 @@ def __get_collection(self) -> Collection:
115
140
def __insert_one (self , document : Dict ) -> str :
116
141
"""Insert single document and return inserted ID."""
117
142
collection = self .__get_collection ()
118
- result = collection .insert_one (document )
119
- return str (result .inserted_id )
143
+
144
+ uid = document .get ('UID' )
145
+ # Use replace_one with upsert=True to overwrite or insert
146
+ result = collection .replace_one (
147
+ {"UID" : uid }, # Match criteria
148
+ document , # New document to replace with
149
+ upsert = True # Insert if not exists
150
+ )
151
+
152
+ # Return the ID of the document
153
+ return str (result .upserted_id if result .upserted_id else uid )
120
154
121
155
# Read operations
122
156
def __find_many (self , query : Optional [Dict ] = None , projection : Optional [Dict ] = None ) -> Optional [List ]:
0 commit comments