From dbc0fa09ab8e4cc00d59dae687573256d4ed683d Mon Sep 17 00:00:00 2001 From: Grant Cohoe Date: Wed, 27 Dec 2023 22:52:01 -0500 Subject: [PATCH 1/4] #244 make it build on new glibc swift --- Sources/swiftarr/Image/Image.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Sources/swiftarr/Image/Image.swift b/Sources/swiftarr/Image/Image.swift index fe2acd124..7a95a8985 100644 --- a/Sources/swiftarr/Image/Image.swift +++ b/Sources/swiftarr/Image/Image.swift @@ -356,9 +356,8 @@ public class GDImage { extension GDImage { public convenience init?(url: URL) { let inputFile = fopen(url.path, "rb") - defer { fclose(inputFile) } - guard inputFile != nil else { return nil } + defer { fclose(inputFile!) } let loadedImage: gdImagePtr? @@ -390,7 +389,7 @@ extension GDImage { // open our output file, then defer it to close let outputFile = fopen(url.path, "wb") - defer { fclose(outputFile) } + defer { fclose(outputFile!) } // write the correct output format based on the path extension switch fileType { From e7863342bacb964d9c671ca67450a9ae09e1077f Mon Sep 17 00:00:00 2001 From: Grant Cohoe Date: Wed, 27 Dec 2023 22:52:28 -0500 Subject: [PATCH 2/4] resolves #238, fixes alertwords --- Sources/swiftarr/Controllers/UserController.swift | 3 ++- Sources/swiftarr/Helpers/RedisWrapper.swift | 12 +++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Sources/swiftarr/Controllers/UserController.swift b/Sources/swiftarr/Controllers/UserController.swift index f88e79215..11578659b 100644 --- a/Sources/swiftarr/Controllers/UserController.swift +++ b/Sources/swiftarr/Controllers/UserController.swift @@ -590,6 +590,7 @@ struct UserController: APIRouteCollection { try await AlertWord.query(on: req.db).filter(\.$word == cleanParam).first() ?? AlertWord(cleanParam) try await alertword.save(on: req.db) try await AlertWordPivot(alertword: alertword, userID: cacheUser.userID).save(on: req.db) + try await req.redis.addAlertword(parameter, userID: cacheUser.userID) let keywordPivots = try await AlertWordPivot.query(on: req.db).filter(\.$user.$id == cacheUser.userID) .with(\.$alertword).all() let keywords = keywordPivots.map { $0.alertword.word } @@ -630,7 +631,7 @@ struct UserController: APIRouteCollection { pivots.removeAll { $0.id == removePivot.id } if try await alertWord.$users.$pivots.query(on: req.db).count() == 0 { try await alertWord.delete(on: req.db) - try await req.redis.removeAlertword(parameter) + try await req.redis.removeAlertword(parameter, userID: user.userID) } } let keywords = pivots.map { $0.alertword.word } diff --git a/Sources/swiftarr/Helpers/RedisWrapper.swift b/Sources/swiftarr/Helpers/RedisWrapper.swift index 1419a64ad..6ab667b89 100644 --- a/Sources/swiftarr/Helpers/RedisWrapper.swift +++ b/Sources/swiftarr/Helpers/RedisWrapper.swift @@ -137,6 +137,10 @@ extension Request.Redis { static let alertwordsRedisKey = RedisKey("alertwords") + func getAlertwordUsersRedisKey(_ word: String) -> RedisKey { + return RedisKey("alertwordUsers-\(word)") + } + // Gets all alertwords set by all users. Used to perform a set intersection against the words in a new post or twarrt. func getAllAlertwords() async throws -> Set { let alertWordArray = try await smembers(of: Request.Redis.alertwordsRedisKey).get() @@ -144,17 +148,19 @@ extension Request.Redis { return alertSet } - func addAlertword(_ word: String) async throws { + func addAlertword(_ word: String, userID: UUID) async throws { let _ = try await sadd(word, to: Request.Redis.alertwordsRedisKey).get() + let _ = try await sadd(userID, to: getAlertwordUsersRedisKey(word)).get() } - func removeAlertword(_ word: String) async throws { + func removeAlertword(_ word: String, userID: UUID) async throws { let _ = try await srem(word, from: Request.Redis.alertwordsRedisKey).get() + let _ = try await srem(userID, from: getAlertwordUsersRedisKey(word)).get() } // Gets a list of users that are alerting on a particular alertword func getUsersForAlertword(_ word: String) async throws -> [UUID] { - let userIDs = try await smembers(of: "alertwordUsers-\(word)", as: UUID.self).get().compactMap { $0 } + let userIDs = try await smembers(of: getAlertwordUsersRedisKey(word), as: UUID.self).get().compactMap { $0 } return userIDs } From 75a1ba4b267c444c5cd0ea081932989be07effcc Mon Sep 17 00:00:00 2001 From: Grant Cohoe Date: Mon, 1 Jan 2024 22:49:21 -0500 Subject: [PATCH 3/4] #246 remove user alertword properly --- Sources/swiftarr/Controllers/UserController.swift | 3 ++- Sources/swiftarr/Helpers/RedisWrapper.swift | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Sources/swiftarr/Controllers/UserController.swift b/Sources/swiftarr/Controllers/UserController.swift index 11578659b..cc53b1d64 100644 --- a/Sources/swiftarr/Controllers/UserController.swift +++ b/Sources/swiftarr/Controllers/UserController.swift @@ -631,8 +631,9 @@ struct UserController: APIRouteCollection { pivots.removeAll { $0.id == removePivot.id } if try await alertWord.$users.$pivots.query(on: req.db).count() == 0 { try await alertWord.delete(on: req.db) - try await req.redis.removeAlertword(parameter, userID: user.userID) + try await req.redis.removeAlertword(parameter) } + try await req.redis.removeUserAlertword(parameter, userID: user.userID); } let keywords = pivots.map { $0.alertword.word } return KeywordData(keywords: keywords.sorted()) diff --git a/Sources/swiftarr/Helpers/RedisWrapper.swift b/Sources/swiftarr/Helpers/RedisWrapper.swift index 6ab667b89..6ba8f7255 100644 --- a/Sources/swiftarr/Helpers/RedisWrapper.swift +++ b/Sources/swiftarr/Helpers/RedisWrapper.swift @@ -153,9 +153,16 @@ extension Request.Redis { let _ = try await sadd(userID, to: getAlertwordUsersRedisKey(word)).get() } - func removeAlertword(_ word: String, userID: UUID) async throws { + // Delete an alertword. This should only be called when there are no more users who have + // this word in their list. + func removeAlertword(_ word: String) async throws { let _ = try await srem(word, from: Request.Redis.alertwordsRedisKey).get() + } + + // Delete an alertword for a particular user. + func removeUserAlertword(_ word: String, userID: UUID) async throws { let _ = try await srem(userID, from: getAlertwordUsersRedisKey(word)).get() + let _ = try await hdel("alertwordPost-\(word)", from: userHashRedisKey(userID: userID)).get() } // Gets a list of users that are alerting on a particular alertword From 1c7c2b9ae85b9e7743dffbe15f9a3237e95b741f Mon Sep 17 00:00:00 2001 From: Grant Cohoe Date: Mon, 1 Jan 2024 23:11:05 -0500 Subject: [PATCH 4/4] #246 disable new forum alertword notifications --- Sources/swiftarr/Controllers/AlertController.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Sources/swiftarr/Controllers/AlertController.swift b/Sources/swiftarr/Controllers/AlertController.swift index eefa5cecd..6852c4574 100644 --- a/Sources/swiftarr/Controllers/AlertController.swift +++ b/Sources/swiftarr/Controllers/AlertController.swift @@ -167,7 +167,12 @@ struct AlertController: APIRouteCollection { } else { entry.forumMentionCount = value.int ?? 0 - entry.newForumMentionCount = max(0, entry.forumMentionCount - viewedCount) + // @TODO disabling newForumMentionCount until we can integrate smarts along the lines of + // "If we're marking this post as read and it contains an alertword, then increment the + // _viewed key for that word." + // Otherwise we can never clear the "new" alertword notifications. + // entry.newForumMentionCount = max(0, entry.forumMentionCount - viewedCount) + entry.newForumMentionCount = 0 } resultDict[word] = entry }