Skip to content

Commit e62f153

Browse files
authored
Merge pull request #255 from samuel-asleep/wiki-moderator-management
Wiki moderator management
2 parents de2ae67 + da3a11e commit e62f153

6 files changed

Lines changed: 641 additions & 18 deletions

File tree

src/gxs/rsgenexchange.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,14 @@ class RsGenExchange : public RsNxsObserver, public RsTickingThread, public RsGxs
170170
*/
171171
virtual void service_tick() = 0;
172172

173-
/*!
174-
*
175-
* @return handle to token service handle for making
176-
* request to this gxs service
177-
*/
178-
RsTokenService* getTokenService();
179-
180-
void threadTick() override; /// @see RsTickingThread
173+
/*!
174+
*
175+
* @return handle to token service handle for making
176+
* request to this gxs service
177+
*/
178+
RsTokenService* getTokenService();
179+
180+
void threadTick() override; /// @see RsTickingThread
181181

182182
/*!
183183
* Policy bit pattern portion

src/retroshare/rsgxsifacehelper.h

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class RsGxsIfaceHelper
7272
mGxs(gxs), mTokenService(*gxs.getTokenService()), mMtx("GxsIfaceHelper")
7373
{}
7474

75-
~RsGxsIfaceHelper() = default;
75+
virtual ~RsGxsIfaceHelper() = default;
7676

7777
#ifdef TO_REMOVE
7878
/*!
@@ -527,6 +527,57 @@ class RsGxsIfaceHelper
527527
return st;
528528
}
529529

530+
/**
531+
* @brief Get service statistics synchronously (blocking call)
532+
* @param stats Output parameter for service statistics
533+
* @param maxWait Maximum time to wait for the operation in milliseconds (default: 10000ms)
534+
* @return true if statistics were successfully retrieved, false on timeout or error
535+
*
536+
* This is a convenience wrapper around the async token-based API.
537+
* It blocks the calling thread until results are available or timeout occurs.
538+
* Use this for simple operations like notification counting in GUI code.
539+
*/
540+
bool getServiceStatistics(
541+
GxsServiceStatistic& stats,
542+
std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000))
543+
{
544+
uint32_t token;
545+
if (!requestServiceStatistic(token))
546+
return false;
547+
548+
auto status = waitToken(token, maxWait);
549+
if (status != RsTokenService::COMPLETE)
550+
return false;
551+
552+
return getServiceStatistic(token, stats);
553+
}
554+
555+
/**
556+
* @brief Get group statistics synchronously (blocking call)
557+
* @param grpId The group ID to get statistics for
558+
* @param stats Output parameter for group statistics
559+
* @param maxWait Maximum time to wait for the operation in milliseconds (default: 10000ms)
560+
* @return true if statistics were successfully retrieved, false on timeout or error
561+
*
562+
* This is a convenience wrapper around the async token-based API.
563+
* It blocks the calling thread until results are available or timeout occurs.
564+
*/
565+
bool getGroupStatistics(
566+
const RsGxsGroupId& grpId,
567+
GxsGroupStatistic& stats,
568+
std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000))
569+
{
570+
uint32_t token;
571+
if (!requestGroupStatistic(token, grpId))
572+
return false;
573+
574+
auto status = waitToken(token, maxWait);
575+
if (status != RsTokenService::COMPLETE)
576+
return false;
577+
578+
return getGroupStatistic(token, stats);
579+
}
580+
530581
private:
531582
RsGxsIface& mGxs;
532583
RsTokenService& mTokenService;

src/retroshare/rswiki.h

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <string>
2727
#include <list>
2828
#include <vector>
29+
#include <map>
2930
#include <iostream>
3031

3132
#include "retroshare/rstokenservice.h"
@@ -67,8 +68,14 @@ extern RsWiki *rsWiki;
6768
/** Wiki Event Codes */
6869
enum class RsWikiEventCode : uint8_t
6970
{
70-
UPDATED_SNAPSHOT = 0x01,
71-
UPDATED_COLLECTION = 0x02
71+
UNKNOWN = 0x00,
72+
UPDATED_SNAPSHOT = 0x01, // Existing page modified
73+
UPDATED_COLLECTION = 0x02, // Existing wiki group modified
74+
NEW_SNAPSHOT = 0x03, // First-time page creation
75+
NEW_COLLECTION = 0x04, // New wiki group creation
76+
SUBSCRIBE_STATUS_CHANGED = 0x05, // User subscribed/unsubscribed
77+
NEW_COMMENT = 0x06, // New comment added
78+
READ_STATUS_CHANGED = 0x07 // Read/unread status changed
7279
};
7380

7481
/** Specific Wiki Event for UI updates */
@@ -80,12 +87,14 @@ struct RsGxsWikiEvent : public RsEvent
8087

8188
RsWikiEventCode mWikiEventCode;
8289
RsGxsGroupId mWikiGroupId;
90+
RsGxsMessageId mWikiMsgId;
8391

8492
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) override
8593
{
8694
RsEvent::serial_process(j, ctx);
8795
RS_SERIAL_PROCESS(mWikiEventCode);
8896
RS_SERIAL_PROCESS(mWikiGroupId);
97+
RS_SERIAL_PROCESS(mWikiMsgId);
8998
}
9099
};
91100

@@ -94,6 +103,8 @@ struct RsWikiCollection: RsGxsGenericGroupData
94103
std::string mDescription;
95104
std::string mCategory;
96105
std::string mHashTags;
106+
// Map of moderator IDs to their termination timestamps (0 means active).
107+
std::map<RsGxsId, rstime_t> mModeratorTerminationDates;
97108
};
98109

99110
class RsWikiSnapshot
@@ -135,6 +146,114 @@ class RsWiki: public RsGxsIfaceHelper
135146
virtual bool createCollection(RsWikiCollection &collection) = 0;
136147
virtual bool updateCollection(const RsWikiCollection &collection) = 0;
137148
virtual bool getCollections(const std::list<RsGxsGroupId> groupIds, std::vector<RsWikiCollection> &groups) = 0;
149+
150+
/**
151+
* @brief Get a single wiki snapshot (page/edit). Blocking API.
152+
* @param msgId Group/message identifier pair
153+
* @param snapshot Output parameter for the snapshot
154+
* @return true if snapshot was retrieved, false otherwise
155+
*/
156+
virtual bool getSnapshot(const RsGxsGrpMsgIdPair& msgId, RsWikiSnapshot& snapshot) = 0;
157+
158+
/**
159+
* @brief Get all snapshots (pages/edits) for a wiki group. Blocking API.
160+
* @param groupId The wiki group ID
161+
* @param snapshots Output vector for snapshots
162+
* @return true if snapshots were retrieved, false otherwise
163+
*/
164+
virtual bool getSnapshots(const RsGxsGroupId& groupId, std::vector<RsWikiSnapshot>& snapshots) = 0;
165+
166+
/**
167+
* @brief Get related snapshots (edit history) for a wiki page. Blocking API.
168+
* @param msgId Group/message identifier pair for the page
169+
* @param snapshots Output vector for related snapshots
170+
* @return true if related snapshots were retrieved, false otherwise
171+
*/
172+
virtual bool getRelatedSnapshots(const RsGxsGrpMsgIdPair& msgId, std::vector<RsWikiSnapshot>& snapshots) = 0;
173+
174+
/**
175+
* @brief Set message read status. Blocking API.
176+
* @param msgId Group/message identifier pair
177+
* @param read True to mark as read, false to mark as unread
178+
* @return true if status was updated, false otherwise
179+
*/
180+
virtual bool setMessageReadStatus(const RsGxsGrpMsgIdPair& msgId, bool read) = 0;
181+
182+
/* Moderator Management */
183+
/**
184+
* @brief Add a moderator to a wiki collection
185+
* @param grpId The ID of the wiki collection/group
186+
* @param moderatorId The ID of the user to add as moderator
187+
* @return true if the moderator was successfully added, false otherwise
188+
*/
189+
virtual bool addModerator(const RsGxsGroupId& grpId, const RsGxsId& moderatorId) = 0;
190+
191+
/**
192+
* @brief Remove a moderator from a wiki collection
193+
* @param grpId The ID of the wiki collection/group
194+
* @param moderatorId The ID of the moderator to remove
195+
* @return true if the moderator was successfully removed, false otherwise
196+
*/
197+
virtual bool removeModerator(const RsGxsGroupId& grpId, const RsGxsId& moderatorId) = 0;
198+
199+
/**
200+
* @brief Get the list of moderators for a wiki collection
201+
* @param grpId The ID of the wiki collection/group
202+
* @param moderators Output parameter that will contain the list of moderator IDs
203+
* @return true if the list was successfully retrieved, false otherwise
204+
*/
205+
virtual bool getModerators(const RsGxsGroupId& grpId, std::list<RsGxsId>& moderators) = 0;
206+
207+
/**
208+
* @brief Check if a user is an active moderator at a given time
209+
* @param grpId The ID of the wiki collection/group
210+
* @param authorId The ID of the user to check
211+
* @param editTime The time at which to check moderator status
212+
* @return true if the user is an active moderator at the specified time, false otherwise
213+
*/
214+
virtual bool isActiveModerator(const RsGxsGroupId& grpId, const RsGxsId& authorId, rstime_t editTime) = 0;
215+
216+
/* Content fetching for merge operations (Todo 3) */
217+
/**
218+
* @brief Get the latest page content for a snapshot lineage.
219+
* @param grpId The group ID of the wiki collection.
220+
* @param snapshotId The message ID of the snapshot (any edit in the lineage).
221+
* @param content Output parameter for page content
222+
* @return true if snapshot found and content retrieved
223+
*/
224+
virtual bool getSnapshotContent(const RsGxsGroupId& grpId,
225+
const RsGxsMessageId& snapshotId,
226+
std::string& content) = 0;
227+
228+
/**
229+
* @brief Get page content from multiple snapshots efficiently (bulk fetch)
230+
* @param grpId The group ID of the wiki collection.
231+
* @param snapshotIds Vector of snapshot message IDs to fetch
232+
* @param contents Output map of snapshotId -> content
233+
* @return true if the operation completed successfully (contents may be empty)
234+
*/
235+
virtual bool getSnapshotsContent(const RsGxsGroupId& grpId,
236+
const std::vector<RsGxsMessageId>& snapshotIds,
237+
std::map<RsGxsMessageId, std::string>& contents) = 0;
238+
239+
/* Notification support */
240+
/**
241+
* @brief Get Wiki service statistics for notification counting
242+
* @param stats Output parameter for service statistics including unread message counts
243+
* @return true if statistics were successfully retrieved, false otherwise
244+
*
245+
* This method is designed for GUI notification systems to efficiently count
246+
* new/unread messages across all Wiki collections.
247+
*/
248+
virtual bool getWikiStatistics(GxsServiceStatistic& stats) = 0;
249+
250+
/**
251+
* @brief Update read status for a wiki snapshot/comment (async)
252+
* @param token Output token for async processing
253+
* @param msgId Group/message identifier pair to update
254+
* @param read True to mark as read, false to mark as unread
255+
*/
256+
virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0;
138257
};
139258

140259
#endif

src/rsitems/rswikiitems.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,15 @@ void RsGxsWikiCollectionItem::clear()
4747
collection.mDescription.clear();
4848
collection.mCategory.clear();
4949
collection.mHashTags.clear();
50+
collection.mModeratorTerminationDates.clear();
5051
}
5152

5253
void RsGxsWikiCollectionItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
5354
{
5455
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR ,collection.mDescription,"collection.mDescription") ;
5556
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_CATEGORY,collection.mCategory ,"collection.mCategory") ;
5657
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_HASH_TAG,collection.mHashTags ,"collection.mHashTags") ;
58+
RsTypeSerializer::serial_process(j,ctx,collection.mModeratorTerminationDates,"collection.mModeratorTerminationDates") ;
5759
}
5860

5961
void RsGxsWikiSnapshotItem::clear()
@@ -77,4 +79,3 @@ void RsGxsWikiCommentItem::serial_process(RsGenericSerializer::SerializeJob j,Rs
7779
{
7880
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_COMMENT,comment.mComment,"comment.mComment") ;
7981
}
80-

0 commit comments

Comments
 (0)