FezController
struct FezController : APIRouteCollection
The collection of /api/v3/fez/* route endpoints and handler functions related to Looking For Group and Seamail chats.
-
Declaration
Swift
struct FezURLQueryStruct : Content -
Required. Registers routes to the incoming router.
Declaration
Swift
func registerRoutes(_ app: Application) throws
-
/GET /api/v3/fez/typesRetrieve a list of all values for
FezTypeas strings.Declaration
Swift
func typesHandler(_ req: Request) throws -> [String]Return Value
An array of
Stringcontaining the.labelvalue for each type. -
openHandler(_:Asynchronous) GET /api/v3/fez/openRetrieve FriendlyFezzes with open slots and a startTime of no earlier than one hour ago. Results are returned sorted by start time, then by title.
URL Query Parameters:
?cruiseday=INT- Only return fezzes occuring on this day of the cruise. Embarkation Day is day 0.?type=STRING- Only return fezzes of this type, there STRING is aFezType.fromAPIString()string.?start=INT- The offset to the first result to return in the filtered + sorted array of results.?limit=INT- The maximum number of fezzes to return; defaults to 50.?hidepast=BOOLEAN- Show fezzes that started more than one hour in the past. For this endpoint, this defaults to TRUE.
Throws
A 5xx response should be reported as a likely bug, please and thank you.
Declaration
Swift
func openHandler(_ req: Request) async throws -> FezListDataReturn Value
An array of
FezDatacontaining current fezzes with open slots. -
joinedHandler(_:Asynchronous) GET /api/v3/fez/joinedRetrieve all the FriendlyFez chats that the user has joined. Results are sorted by descending fez update time.
Query Parameters:
?cruiseday=INT- Only return fezzes occuring on this day of the cruise. Embarkation Day is day 0.?type=STRING- Only return fezzes of the given fezType. SeeFezTypefor a list.?excludetype=STRING- Don’t return fezzes of the given type. SeeFezTypefor a list.?onlynew=TRUE- Only return fezzes with unread messages.?favorite=TRUE- Only return fezzes the user has favorited.?start=INT- The offset to the first result to return in the filtered + sorted array of results.?limit=INT- The maximum number of fezzes to return; defaults to 50.?search=STRING- Only show fezzes whose title, info, or any post contains the given string.?hidepast=BOOLEAN- Hide fezzes that started more than one hour in the past. For this endpoint, this defaults to FALSE.?matchID=UUID- Returns a single LFG with the given ID.?lfgtypes=BOOLEAN- Shorthand to include/exliude all the LFG types (Activity, Gaming, Dining, etc.) Acts the same as using multipletype=orexludetype=params.
Moderators and above can use the
foruserquery parameter to access pseudo-accounts:?foruser=NAME- Access the “moderator” or “twitarrteam” seamail accounts.
/GET /api/v3/fez/typesis the canonical way to get the list of acceptable values. Type and excludetype are exclusive options, obv.Throws
A 5xx response should be reported as a likely bug, please and thank you.Declaration
Swift
func joinedHandler(_ req: Request) async throws -> FezListDataReturn Value
An array of
FezDatacontaining all the fezzes joined by the user. -
ownerHandler(_:Asynchronous) GET /api/v3/fez/ownerRetrieve the FriendlyFez chats created by the user.
Note
There is no block filtering on this endpoint. In theory, a block could only apply if it were set after the fez had been joined by the second party. The owner of the fez has the ability to remove users if desired, and the fez itself is no longer visible to the non-owning party.Query Parameters:
?cruiseday=INT- Only return fezzes occuring on this day of the cruise. Embarkation Day is day 0.?type=STRING- Only return fezzes of the given fezType. SeeFezTypefor a list.?excludetype=STRING- Don’t return fezzes of the given type. SeeFezTypefor a list.?start=INT- The offset to the first result to return in the filtered + sorted array of results.?limit=INT- The maximum number of fezzes to return; defaults to 50.?hidepast=BOOLEAN- Hide fezzes that started more than one hour in the past. For this endpoint, this defaults to FALSE.?lfgtypes=BOOLEAN- Shorthand to include/exliude all the LFG types (Activity, Gaming, Dining, etc.) Acts the same as using multipletype=orexludetype=params.?favorite=TRUE- Only return fezzes the user has favorited.
Throws
A 5xx response should be reported as a likely bug, please and thank you.
Declaration
Swift
func ownerHandler(_ req: Request) async throws -> FezListDataReturn Value
An array of
FezDatacontaining all the fezzes created by the user. -
fezHandler(_:Asynchronous) GET /api/v3/fez/:fez_IDRetrieve information about the specified FriendlyFez. For users that aren’t members of the fez, this info will be the same as the info returned for
GET /api/v3/fez/open. For users that have joined the fez theFezData.MembersOnlyDatawill be populated, as will theFezPosts.Query Parameters:
?start=INT- The offset to the first post to return in the array of posts.?limit=INT- The maximum number of posts to return; defaults to 50.
Start and limit only have an effect when the user is a member of the Fez. Limit defaults to 50 and start defaults to
(readCount / limit) * limit, where readCount is how many posts the user has read already.Moderators and above can use the
foruserquery parameter to access pseudo-accounts:?foruser=NAME- Access the “moderator” or “twitarrteam” seamail accounts.
When a member calls this method, it updates the member’s
readCount, marking all posts read up tostart + limit. However, the returned readCount is the value before updating. If there’s 5 posts in the chat, and the member has read 3 of them, the returnedFezDatahas 5 posts, we return 3 inFezData.readCountfield, and update the pivot’s readCount to 5.FezPosts are ordered by creation time.Note
Posts are subject to block and mute user filtering, but mutewords are ignored in order to not suppress potentially important information.
Throws
404 error if a block between the user and fez owner applies. A 5xx response should be reported as a likely bug, please and thank you.
Declaration
Swift
func fezHandler(_ req: Request) async throws -> FezDataParameters
fezIDin the URL path.
Return Value
FezDatawith fez info and all discussion posts. -
fezMarkReadHandler(_:Asynchronous) POST /api/v3/fez/ID/markReadMark the specified
FriendlyFez(Seamail, LFG, or Private Event chat) as read for the current user. This sets the user’s read count to the fez’s current post count, effectively marking all posts as read without requiring the user to re-fetch them. Intended for chats whose latest post(s) were already rendered live via websocket, so the caller doesn’t have to re-request the thread just to clear its unread state.Throws
404 error if the fez is not available, or if the user is not a member.Declaration
Swift
func fezMarkReadHandler(_ req: Request) async throws -> HTTPStatusParameters
fezIDin URL path
Return Value
201 Created if the read count advanced; 200 OK if already marked as read.
-
formerlyJoinedFezHandler(_:Asynchronous) GET /api/v3/fez/formerQuery Parameters:
?start=INT- The offset to the first post to return in the array of posts.?limit=INT- The maximum number of posts to return; defaults to 50.
Retrieve information about (open) Seamails, Private Events, and LFGs the user was previously a member of, but no longer. Won’t return info on closed Seamails or Personal Events as their member lists cannot change.
Declaration
Swift
func formerlyJoinedFezHandler(_ req: Request) async throws -> FezListData
-
joinHandler(_:Asynchronous) POST /api/v3/fez/ID/joinAdd the current user to the FriendlyFez. If the
.maxCapacityof the fez has been reached, the user is added to the waiting list.Note
A user cannot join a fez that is owned by a blocked or blocking user. If any current participating or waitList user is in the user’s blocks, their identity is replaced by a placeholder in the returned data. It is the user’s responsibility to examine the participant list for conflicts prior to joining or attending.
Throws
400 error if the supplied ID is not a fez barrel or user is already in fez. 404 error if a block between the user and fez owner applies. A 5xx response should be reported as a likely bug, please and thank you.
Declaration
Swift
func joinHandler(_ req: Request) async throws -> ResponseParameters
fezIDin the URL path.
Return Value
FezDatacontaining the updated fez data. -
unjoinHandler(_:Asynchronous) POST /api/v3/fez/ID/unjoinRemove the current user from the FriendlyFez. If the
.maxCapacityof the fez had previously been reached, the first user from the waiting list, if any, is moved to the participant list.Throws
400 error if the supplied ID is not a fez barrel. A 5xx response should be reported as a likely bug, please and thank you.Declaration
Swift
func unjoinHandler(_ req: Request) async throws -> FezDataParameters
fezIDin the URL path.
Return Value
FezDatacontaining the updated fez data.
-
postAddHandler(_:Asynchronous) POST /api/v3/fez/ID/postAdd a
FezPostto the specifiedFriendlyFez.Open fez types are only permitted to have 1 image per post. Private fezzes (aka Seamail) cannot have any images.
Throws
404 error if the fez is not available. A 5xx response should be reported as a likely bug, please and thank you.Declaration
Swift
func postAddHandler(_ req: Request) async throws -> FezPostDataParameters
fezIDin URL path
requestBodyReturn Value
FezPostDatacontaining the user’s new post. -
addFezPost(to:Asynchronousdata: cacheUser: on: ) Declaration
Swift
func addFezPost(to fez: FriendlyFez, data: PostContentData, cacheUser: UserCacheData, on req: Request) async throws -> FezPostData -
postDeleteHandler(_:Asynchronous) POST /api/v3/fez/post/ID/deleteDELETE /api/v3/fez/post/IDDelete a
FezPost. Must be author of post.Throws
403 error if user is not the post author. 404 error if the fez is not available. A 5xx response should be reported as a likely bug, please and thank you.Declaration
Swift
func postDeleteHandler(_ req: Request) async throws -> HTTPStatusParameters
fezIDin URL path
Return Value
HTTP 204 No Content
-
reportFezPostHandler(_:Asynchronous) POST /api/v3/fez/post/ID/reportCreates a
Reportregarding the specifiedFezPost.Note
The accompanying report message is optional on the part of the submitting user, but the
ReportDatais mandatory in order to allow one. If there is no message, send an empty string in the.messagefield.Throws
400 error if the post is private.
Throws
404 error if the parent fez of the post could not be found.
Declaration
Swift
func reportFezPostHandler(_ req: Request) async throws -> HTTPStatusParameters
postIDin URL path, the ID of the post being reported.
requestBodyReportDatapayload in the HTTP body.Return Value
201 Created on success.
-
createHandler(_:Asynchronous) POST /api/v3/fez/createCreate a
FriendlyFez. The creating user is automatically added to the participant list.The list of recognized values for use in the
.fezTypefield is obtained fromGET /api/v3/fez/types.The
startTime,endTime, andlocationfields are optional. Pass nil for these fields if the values are unknown/not applicable. Clients should convert nils in these fields to “TBD” for display.Important
Do not pass “0” as the date value. Unless you really are scheduling something for the first stroke of midnight in 1970.A value of 0 in either the
.minCapacityor.maxCapacityfields indicates an undefined limit: “there is no minimum”, “there is no maximum”.FezContentDatamay optionally include afirstPost, which creates the fez’s opening post in the same call–similar to howPOST /api/v3/forum/categories/ID/createtakes afirstPost. This is ignored for.personalEventfez types, which don’t support posts. The same image-count rules that apply toPOST /api/v3/fez/ID/postapply here (0 images for Seamail types, 1 image otherwise).firstPost‘s ownpostAsModerator/postAsTwitarrTeamflags govern the post’s author independently of this call’screatedByModerator/createdByTwitarrTeamflags; set both if the fez owner and post author should match.Throws
400 error if the supplied data does not validate.Declaration
Swift
func createHandler(_ req: Request) async throws -> ResponseParameters
requestBodyFezContentDatapayload in the HTTP body.Return Value
201 Created;
FezDatacontaining the newly created fez. -
cancelHandler(_:Asynchronous) POST /api/v3/fez/ID/cancelCancel a FriendlyFez. Owner only. Cancelling a Fez is different from deleting it. A canceled fez is still visible; members may still post to it. But, a cenceled fez does not show up in searches for open fezzes, and should be clearly marked in UI to indicate that it’s been canceled.
Throws
403 error if user is not the fez owner. A 5xx response should be reported as a likely bug, please and thank you.Declaration
Swift
func cancelHandler(_ req: Request) async throws -> FezDataParameters
fezIDin URL path.
Return Value
FezDatawith the updated fez info. -
fezDeleteHandler(_:Asynchronous) POST /api/v3/fez/ID/deleteDELETE /api/v3/fez/IDDelete the specified
FriendlyFez. This soft-deletes the fez. Posts are left as-is.To delete, the user must have an access level allowing them to delete the fez. Currently this means moderators and above. The owner of a fez may Cancel the fez, which tells the members the fez was cancelled, but does not delete it. However, a Personal Event can be deleted by its creator, as that LFG type doesn’t allow participants to be added to it.
Throws
403 error if the user is not permitted to delete.Declaration
Swift
func fezDeleteHandler(_ req: Request) async throws -> HTTPStatusParameters
fezIDin URL path.
Return Value
204 No Content on success.
-
updateHandler(_:Asynchronous) POST /api/v3/fez/ID/updateUpdate the specified FriendlyFez with the supplied data. Updating a cancelled fez will un-cancel it. Does not process the initialUsers field; use the user add/remove routes to change the participants.
Note
All fields in the supplied
FezContentDatamust be filled, just as if the fez were being created from scratch. If there is demand, using a set of more efficient endpoints instead of this single monolith can be considered.Throws
400 error if the data is not valid. 403 error if user is not fez owner. A 5xx response should be reported as a likely bug, please and thank you.
Declaration
Swift
func updateHandler(_ req: Request) async throws -> FezDataParameters
fezIDin URL path.
requestBodyFezContentDatapayload in the HTTP body.Return Value
FezDatacontaining the updated fez info. -
userAddHandler(_:Asynchronous) POST /api/v3/fez/ID/user/ID/addAdd the specified
Userto the specified LFG or open chat. This lets the owner invite others.Throws
400 error if user is already in barrel. 403 error if requester is not fez owner. A 5xx response should be reported as a likely bug, please and thank you.Declaration
Swift
func userAddHandler(_ req: Request) async throws -> FezDataParameters
fezIDin URL path.
userIDin URL path.
Return Value
FezDatacontaining the updated fez info. -
userRemoveHandler(_:Asynchronous) POST /api/v3/fez/:fezID/user/:userID/removeRemove the specified
Userfrom the specified FriendlyFez. This lets a fez owner remove others. Moderators may also remove users from a fez they don’t own; this is logged in the moderator action log.Throws
400 error if user is not in the barrel. 403 error if requester is not fez owner or a moderator, or if the target user is the fez’s owner. A 5xx response should be reported as a likely bug, please and thank you.Declaration
Swift
func userRemoveHandler(_ req: Request) async throws -> FezDataParameters
fezIDin URL path.
userIDin URL path.
Return Value
FezDatacontaining the updated fez info. -
reportFezHandler(_:Asynchronous) POST /api/v3/fez/ID/reportCreates a
Reportregarding the specifiedFez. This reports on the Fez itself, not any of its posts in particular. This could mean a Fez with reportable content in its Title, Info, or Location fields, or a bunch of reportable posts in the fez.Only LFGs and Private Events can be reported at the container level this way; the resulting report’s type will be
.fezfor an LFG or.privateEventfor a Private Event. Seamail chats (open or closed) can’t be reported as a whole–report individual messages instead. Personal Events can’t be reported at all, since they’re visible only to their owner.Note
The accompanying report message is optional on the part of the submitting user, but the
ReportDatais mandatory in order to allow one. If there is no message, send an empty string in the.messagefield.Throws
403 error if the Fez is a Seamail chat or a Personal Event.
Declaration
Swift
func reportFezHandler(_ req: Request) async throws -> HTTPStatusParameters
fezIDin URL path, the Fez ID to report.
requestBodyReturn Value
201 Created on success.
-
createFezSocket(_:Asynchronous_: ) WS /api/v3/fez/:fezID/socketOpens a websocket to receive updates on the given fez. At the moment there’s only 2 messages that the client may receive:
SocketFezPostData- sent when a post is added to the fez.SocketMemberChangeData- sent when a member joins/leaves the fez.
Note that there’s a bunch of other state change that can happen with a fez; I haven’t built out code to send socket updates for them. The socket returned by this call is only intended for receiving updates; there are no client-initiated messages defined for this socket. Posting messages, leaving the fez, updating or canceling the fez and any other state changes should be performed using the various POST methods of this controller.
The server validates membership before sending out each socket message, but be sure to close the socket if the user leaves the fez. This method is designed to provide updates only while a user is viewing the fez in your app–don’t open one of these sockets for each fez a user joins and keep them open continually. Use
WS /api/v3/notification/socketfor long-term status updates.Declaration
Swift
func createFezSocket(_ req: Request, _ ws: WebSocket) async -
forwardPostToSockets(_:Asynchronous_: on: ) Declaration
Swift
func forwardPostToSockets(_ fez: FriendlyFez, _ post: FezPost, on req: Request) async throws -
Declaration
Swift
func forwardMembershipChangeToSockets(_ fez: FriendlyFez, participantID: UUID, joined: Bool, on req: Request) async throws -
muteAddHandler(_:Asynchronous) POST /api/v3/fez/:fez_ID/muteMute the specified
Fezfor the current user.Declaration
Swift
func muteAddHandler(_ req: Request) async throws -> HTTPStatusParameters
fez_IDIn the URL path.
Return Value
201 Created on success; 200 OK if already muted.
-
muteRemoveHandler(_:Asynchronous) POST /api/v3/fez/:fez_ID/mute/removeDELETE /api/v3/fez/:fez_ID/muteUnmute the specified
Fezfor the current user.Throws
400 error if the forum was not muted.Declaration
Swift
func muteRemoveHandler(_ req: Request) async throws -> HTTPStatusParameters
fez_IDIn the URL path.
Return Value
204 No Content on success; 200 OK if already not muted.
-
favoriteAddHandler(_:Asynchronous) POST /api/v3/fez/:fez_ID/favoriteFavorite the specified
Fezfor the current user. Lets the user flag a chat (Seamail, LFG, or Private Event) they intend to come back to later; offers a filter criteria similar toonlynew. Only members of the fez may favorite it. Unjoining a fez implies unfavoriting it, as the favorite flag is stored on the per-user membership pivot, which is deleted on unjoin.For privileged mailboxes (the shared
@moderator/@TwitarrTeamseamail), favoriting uses the requesting user’s ownFezParticipantpivot, not a pivot shared by the whole team, so favoriting a privileged-mailbox chat only affects the user who favorited it.Declaration
Swift
func favoriteAddHandler(_ req: Request) async throws -> HTTPStatusParameters
fez_IDIn the URL path.
Return Value
201 Created on success; 200 OK if already favorited.
-
favoriteRemoveHandler(_:Asynchronous) POST /api/v3/fez/:fez_ID/favorite/removeDELETE /api/v3/fez/:fez_ID/favoriteUnfavorite the specified
Fezfor the current user.Declaration
Swift
func favoriteRemoveHandler(_ req: Request) async throws -> HTTPStatusParameters
fez_IDIn the URL path.
Return Value
204 No Content on success; 200 OK if already not favorited.
-
getJoinedChats(_:AsynchronousurlQuery: ) Declaration
Swift
func getJoinedChats(_ req: Request, urlQuery: FezURLQueryStruct) async throws -> FezListData -
createChat(_:Asynchronousdata: ) Declaration
Swift
func createChat(_ req: Request, data: FezContentData) async throws -> FezData -
updateChat(_:Asynchronousdata: ) Declaration
Swift
func updateChat(_ req: Request, data: FezContentData) async throws -> FezData -
Declaration
Swift
func buildFezData(from fez: FriendlyFez, with pivot: FezParticipant? = nil, posts: [FezPostData]? = nil, for cacheUser: UserCacheData, on req: Request) throws -> FezData -
buildPostsForFez(_:Asynchronouspivot: on: user: as: ) Declaration
Swift
func buildPostsForFez(_ fez: FriendlyFez, pivot: FezParticipant?, on req: Request, user: UserCacheData, as effectiveUser: UserCacheData) async throws -> ([FezPostData], Paginator) -
getUserPivot(lfg:AsynchronoususerID: on: ) Declaration
Swift
func getUserPivot(lfg: FriendlyFez, userID: UUID, on db: Database) async throws -> FezParticipant? -
getUserPivotForAdd(lfg:AsynchronoususerID: on: ) Declaration
Swift
func getUserPivotForAdd(lfg: FriendlyFez, userID: UUID, on db: Database) async throws -> FezParticipant -
getOwnFezParticipant(fez:AsynchronouscacheUser: req: ) Resolves the
FezParticipantpivot to use for per-user chat settings (mute, favorite) actions. These settings are always tracked per actual user, even when the fez is a privileged mailbox chat (@moderator/@TwitarrTeamseamail) that multiple real users share access to–each real user gets their own pivot for it (seeensureFezParticipantForUser), so muting/favoriting a privileged-mailbox chat only affects the user who did it. We don’t wantgetEffectiveUser(user:req:fez:)‘s persona substitution here, only its “is this a privileged mailbox chat” signal, to decide whether to auto-create the calling user’s own pivot if they haven’t got one yet.Throws
403 error if the fez isn’t a privileged mailbox chat and the user has no existing pivot (isn’t a member).Declaration
Swift
func getOwnFezParticipant(fez: FriendlyFez, cacheUser: UserCacheData, req: Request) async throws -> FezParticipantParameters
fezThe FriendlyFez being muted/favorited.
cacheUserThe actual requesting user (never a moderator/TwitarrTeam persona).
reqThe Request for database access.
Return Value
The requesting user’s own
FezParticipantpivot for this fez. -
Ensures a FezParticipant exists for the given user and fez, creating and initializing it if needed. This is used when accessing privileged mailbox conversations to ensure per-user read tracking.
Declaration
Swift
func ensureFezParticipantForUser(fez: FriendlyFez, user: UserCacheData, on req: Request, isPrivilegedMailbox: Bool = false) async throws -> FezParticipantParameters
fezThe FriendlyFez to ensure participation for
userThe UserCacheData for the actual user (not the effective/privileged mailbox user)
reqThe Request for database access
isPrivilegedMailboxWhether this is for a privileged mailbox context (effectiveUser != cacheUser)
Return Value
The FezParticipant for the user, either existing or newly created
-
Determines the appropriate MailInbox for a fez based on privileged mailbox participants. Returns the privileged mailbox inbox if TwitarrTeam or moderator is a participant, otherwise returns nil.
Declaration
Swift
func getPrivilegedMailboxForFez(fez: FriendlyFez, on req: Request) -> MailInbox?Parameters
fezThe FriendlyFez to check
reqThe Request for userCache access
Return Value
The MailInbox if a privileged mailbox user is a participant, nil otherwise
-
Declaration
Swift
func userCanViewMemberData(user: UserCacheData, fez: FriendlyFez) -> Bool -
Validates edits against a seamail.
For seamail types (closed/open), only the title can be edited. All other fields must remain unchanged.
Throws
Abort(.forbidden) if any field other than title is being modifiedDeclaration
Swift
func guardEditSeamail(fez: FriendlyFez, data: FezContentData) throws -
Declaration
Swift
func getEffectiveUser(user: UserCacheData, req: Request) throws -> UserCacheData -
Declaration
Swift
func getEffectiveUser(user: UserCacheData, req: Request, fez: FriendlyFez) -> UserCacheData -
notifyAddedToFez(_:Asynchronousfor: by: on: ) Declaration
Swift
func notifyAddedToFez(_ fez: FriendlyFez, for addedUserIDs: [UUID], by adder: UserCacheData, on req: Request) async throws -
notifyAddedToFez(_:Asynchronousfor: by: on: ) Declaration
Swift
func notifyAddedToFez(_ fez: FriendlyFez, for participant: FezParticipant, by adder: UserCacheData, on req: Request) async throws -
redisNotifyAddedToFez(_:Asynchronoususers: by: on: ) Declaration
Swift
private func redisNotifyAddedToFez(_ fez: FriendlyFez, users: [UUID], by adder: UserCacheData, on req: Request) async throws
View on GitHub