Skip to content

Commit

Permalink
Auto-publish announcement messages (#143)
Browse files Browse the repository at this point in the history
  • Loading branch information
MahdiBM authored Nov 26, 2023
1 parent f6ee599 commit 64b6753
Show file tree
Hide file tree
Showing 18 changed files with 7,020 additions and 3,285 deletions.
2 changes: 1 addition & 1 deletion Lambdas/GHHooks/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ enum Constants {

enum Channels: ChannelSnowflake, CaseIterable {
case logs = "1067060193982156880"
case issueAndPRs = "1123702585006768228"
case issuesAndPRs = "1123702585006768228"
case release = "431926479752921098"
case thanks = "443074453719744522"
case documentation = "484454139506458634"
Expand Down
4 changes: 2 additions & 2 deletions Lambdas/GHHooks/EventHandler/Handlers/TicketReporter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,13 @@ private extension Constants.Channels {
static func reportingChannel(repoID: Int, createdAt: Date) -> Self {
/// The change to use `.documentation` was made only after this timestamp.
if createdAt.timeIntervalSince1970 < 1_696_067_000 {
return .issueAndPRs
return .issuesAndPRs
} else {
switch repoID {
case 64560805:
return .documentation
default:
return .issueAndPRs
return .issuesAndPRs
}
}
}
Expand Down
4,167 changes: 2,836 additions & 1,331 deletions Lambdas/GitHubAPI/GeneratedSources/Client.swift

Large diffs are not rendered by default.

5,993 changes: 4,100 additions & 1,893 deletions Lambdas/GitHubAPI/GeneratedSources/Types.swift

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"location" : "https://github.com/DiscordBM/DiscordBM.git",
"state" : {
"branch" : "main",
"revision" : "32a92b363d03600686ab9b0ec7a2d4bcd3a3979a"
"revision" : "3978bb3298c336bd8712fd06c70348dab67a3f87"
}
},
{
Expand Down Expand Up @@ -68,8 +68,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/mattpolzin/OpenAPIKit.git",
"state" : {
"revision" : "b069168ebd9bac3704beab3aadff07b589aadeb2",
"version" : "3.0.0-rc.2"
"revision" : "b00b08d05e6fba0e156c06be3332b9774e172afd",
"version" : "3.1.1"
}
},
{
Expand Down Expand Up @@ -283,8 +283,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-openapi-generator",
"state" : {
"revision" : "9e62a21c5cd08f7d2485f4d5c8c7337dee17546c",
"version" : "0.3.3"
"revision" : "7f6baf7227c897f09bad0252cccac2cd57202383",
"version" : "0.3.5"
}
},
{
Expand All @@ -299,10 +299,10 @@
{
"identity" : "swift-semver",
"kind" : "remoteSourceControl",
"location" : "https://github.com/gwynne/swift-semver",
"location" : "https://github.com/gwynne/swift-semver.git",
"state" : {
"revision" : "fa2e77b914a6bcca38edc83c1a921893f6e77650",
"version" : "1.0.0-beta.1"
"revision" : "550e8b5ef6eca8ea0af4cf7cb16e7ee087c9b037",
"version" : "1.0.0"
}
},
{
Expand Down
15 changes: 13 additions & 2 deletions Sources/Penny/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ enum Constants {
case release = "431926479752921098"
case jobs = "442420282292961282"
case status = "459521920241500220"
case logs = "1067060193982156880"
case proposals = "1104650517549953094"
case thanks = "443074453719744522"
case logs = "1067060193982156880"
case issuesAndPRs = "1123702585006768228"
case evolution = "1104650517549953094"
case stackOverflow = "473249028142923787"

var id: ChannelSnowflake {
Expand All @@ -89,6 +90,16 @@ enum Constants {
Channels.jobs,
Channels.status,
].map(\.id))

static let announcementChannels: Set<ChannelSnowflake> = Set([
Channels.news,
Channels.publications,
Channels.release,
Channels.jobs,
Channels.stackOverflow,
Channels.issuesAndPRs,
Channels.evolution,
].map(\.id))
}

enum Roles: RoleSnowflake {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Penny/HandlerContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct HandlerContext: Sendable {
let cachesService: any CachesService
let discordService: DiscordService
let renderClient: RenderClient
let proposalsChecker: ProposalsChecker
let evolutionChecker: EvolutionChecker
let soChecker: SOChecker
let reactionCache: ReactionCache
}
Expand Down
29 changes: 23 additions & 6 deletions Sources/Penny/Handlers/MessageHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@ struct MessageHandler {
}

func handle() async {
let isBot = event.author?.bot == true

/// Stop the bot from responding to other bots and itself
if event.author?.bot == true { return }

await checkForNewCoins()
await checkForAutoFaqs()
await checkForPings()
await checkForGuildSubscriptionCoins()
if !isBot {
await checkForNewCoins()
await checkForAutoFaqs()
await checkForPings()
await checkForGuildSubscriptionCoins()
}
/// Check for bot messages like Penny's own messages too
await publishAnnouncementMessages()
}

func checkForNewCoins() async {
Expand Down Expand Up @@ -264,6 +268,19 @@ struct MessageHandler {
}
}

func publishAnnouncementMessages() async {
guard Constants.Channels.announcementChannels.contains(event.channel_id) else {
logger.debug("Channel \(event.channel_id) is not an announcement channel")
return
}
logger.debug("Publishing message \(event.id) that was sent in \(event.channel_id)")
/// "Publish" the message to other announcement-channel subscribers
await context.services.discordService.crosspostMessage(
channelId: event.channel_id,
messageId: event.id
)
}

func makeAuthorName(nick: String?, user: DiscordUser) -> String {
let username = user.global_name ?? user.username
if let nick, nick != username {
Expand Down
12 changes: 6 additions & 6 deletions Sources/Penny/MainService/PennyService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@ struct PennyService: MainService {
let pingsService = DefaultPingsService(httpClient: httpClient)
let faqsService = DefaultFaqsService(httpClient: httpClient)
let autoFaqsService = DefaultAutoFaqsService(httpClient: httpClient)
let proposalsService = DefaultProposalsService(httpClient: httpClient)
let evolutionService = DefaultEvolutionService(httpClient: httpClient)
let soService = DefaultSOService(httpClient: httpClient)
let discordService = DiscordService(discordClient: bot.client, cache: cache)
let proposalsChecker = ProposalsChecker(
proposalsService: proposalsService,
let evolutionChecker = EvolutionChecker(
evolutionService: evolutionService,
discordService: discordService
)
let soChecker = SOChecker(
Expand All @@ -108,7 +108,7 @@ struct PennyService: MainService {
awsClient: awsClient,
context: .init(
autoFaqsService: autoFaqsService,
proposalsChecker: proposalsChecker,
evolutionChecker: evolutionChecker,
soChecker: soChecker,
reactionCache: reactionCache
)
Expand All @@ -127,7 +127,7 @@ struct PennyService: MainService {
on: httpClient.eventLoopGroup.next()
)
),
proposalsChecker: proposalsChecker,
evolutionChecker: evolutionChecker,
soChecker: soChecker,
reactionCache: reactionCache
)
Expand All @@ -152,7 +152,7 @@ struct PennyService: MainService {
/// since it communicates through Discord and will need the Gateway connection.
await context.botStateManager.start {
/// These contain cached stuff and need to wait for `BotStateManager`.
context.services.proposalsChecker.run()
context.services.evolutionChecker.run()
context.services.soChecker.run()
}
}
Expand Down
21 changes: 8 additions & 13 deletions Sources/Penny/ProposalsChecker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import DiscordModels
import Models
import Foundation

actor ProposalsChecker {
actor EvolutionChecker {

struct Storage: Sendable, Codable {
var previousProposals: [Proposal] = []
Expand All @@ -16,16 +16,16 @@ actor ProposalsChecker {
/// The minimum time to wait before sending a queued-proposal
let queuedProposalsWaitTime: Double

let proposalsService: any ProposalsService
let evolutionService: any EvolutionService
let discordService: DiscordService
let logger = Logger(label: "ProposalsChecker")
let logger = Logger(label: "EvolutionChecker")

init(
proposalsService: any ProposalsService,
evolutionService: any EvolutionService,
discordService: DiscordService,
queuedProposalsWaitTime: Double = 29 * 60
) {
self.proposalsService = proposalsService
self.evolutionService = evolutionService
self.discordService = discordService
self.queuedProposalsWaitTime = queuedProposalsWaitTime
}
Expand All @@ -45,7 +45,7 @@ actor ProposalsChecker {
}

func check() async throws {
let proposals = try await proposalsService.list()
let proposals = try await evolutionService.list()

if self.storage.previousProposals.isEmpty {
self.storage.previousProposals = proposals
Expand Down Expand Up @@ -139,7 +139,7 @@ actor ProposalsChecker {
if Task.isCancelled { return }
/// Send the message, make sure it is successfully sent
let response = await discordService.sendMessage(
channelId: Constants.Channels.proposals.id,
channelId: Constants.Channels.evolution.id,
payload: payload
)
guard let message = try? response?.decode() else { return }
Expand All @@ -153,11 +153,6 @@ actor ProposalsChecker {
auto_archive_duration: .threeDays
)
)
/// "Publish" the message to other announcement-channel subscribers
await discordService.crosspostMessage(
channelId: message.channel_id,
messageId: message.id
)
}

private func makePayloadForNewProposal(_ proposal: Proposal) async -> Payloads.CreateMessage {
Expand Down Expand Up @@ -275,7 +270,7 @@ actor ProposalsChecker {
private func findForumPostLink(link: String) async -> ReviewLinksFinder.SimpleLink? {
let content: String
do {
content = try await proposalsService.getProposalContent(link: link)
content = try await evolutionService.getProposalContent(link: link)
} catch {
logger.error("Could not fetch proposal content", metadata: [
"link": .string(link),
Expand Down
14 changes: 7 additions & 7 deletions Sources/Penny/Services/CachesService/CachesStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ struct CachesStorage: Sendable, Codable {

struct Context {
let autoFaqsService: any AutoFaqsService
let proposalsChecker: ProposalsChecker
let evolutionChecker: EvolutionChecker
let soChecker: SOChecker
let reactionCache: ReactionCache
}

var reactionCacheData: ReactionCache.Storage?
var proposalsCheckerData: ProposalsChecker.Storage?
var evolutionCheckerData: EvolutionChecker.Storage?
var soCheckerData: SOChecker.Storage?
var autoFaqsResponseRateLimiter: DefaultAutoFaqsService.ResponseRateLimiter?

Expand All @@ -20,7 +20,7 @@ struct CachesStorage: Sendable, Codable {
static func makeFromCachedData(context: Context) async -> CachesStorage {
var storage = CachesStorage()
storage.reactionCacheData = await context.reactionCache.getCachedDataForCachesStorage()
storage.proposalsCheckerData = await context.proposalsChecker.getCachedDataForCachesStorage()
storage.evolutionCheckerData = await context.evolutionChecker.getCachedDataForCachesStorage()
storage.soCheckerData = await context.soChecker.getCachedDataForCachesStorage()
storage.autoFaqsResponseRateLimiter = await context.autoFaqsService.getCachedDataForCachesStorage()
return storage
Expand All @@ -30,8 +30,8 @@ struct CachesStorage: Sendable, Codable {
if let reactionCacheData {
await context.reactionCache.consumeCachesStorageData(reactionCacheData)
}
if let proposalsCheckerData {
await context.proposalsChecker.consumeCachesStorageData(proposalsCheckerData)
if let evolutionCheckerData {
await context.evolutionChecker.consumeCachesStorageData(evolutionCheckerData)
}
if let soCheckerData {
await context.soChecker.consumeCachesStorageData(soCheckerData)
Expand All @@ -45,15 +45,15 @@ struct CachesStorage: Sendable, Codable {
data.normalThanksMessages.count,
data.forcedInThanksChannelMessages.count]
} ?? []
let proposalsCheckerDataCounts = proposalsCheckerData.map { data in
let evolutionCheckerDataCounts = evolutionCheckerData.map { data in
[data.previousProposals.count,
data.queuedProposals.count]
} ?? []
let autoFaqsResponseRateLimiterCounts = [autoFaqsResponseRateLimiter?.count ?? 0]

Logger(label: "CachesStorage").notice("Recovered the cached stuff", metadata: [
"reactionCache_counts": .stringConvertible(reactionCacheDataCounts),
"proposalsChecker_counts": .stringConvertible(proposalsCheckerDataCounts),
"evolutionChecker_counts": .stringConvertible(evolutionCheckerDataCounts),
"soChecker_isNotNil": .stringConvertible(soCheckerData != nil),
"autoFaqsLimiter_counts": .stringConvertible(autoFaqsResponseRateLimiterCounts),
])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import AsyncHTTPClient
import Models
import NIOCore

struct DefaultProposalsService: ProposalsService {
struct DefaultEvolutionService: EvolutionService {

enum Errors: Error, CustomStringConvertible {
case emptyProposals
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Models

protocol ProposalsService: Sendable {
protocol EvolutionService: Sendable {
func list() async throws -> [Proposal]
func getProposalContent(link: String) async throws -> String
}
2 changes: 1 addition & 1 deletion Tests/Fake/FakeCacheService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public struct FakeCachesService: CachesService {

public func getCachedInfoFromRepositoryAndPopulateServices() async {
var storage = CachesStorage()
storage.proposalsCheckerData = .init(
storage.evolutionCheckerData = .init(
previousProposals: TestData.proposals,
queuedProposals: []
)
Expand Down
8 changes: 4 additions & 4 deletions Tests/Fake/FakeMainService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ public actor FakeMainService: MainService {
discordClient: manager.client,
cache: cache
)
let proposalsChecker = ProposalsChecker(
proposalsService: FakeProposalsService(),
let evolutionChecker = EvolutionChecker(
evolutionService: FakeEvolutionService(),
discordService: discordService,
queuedProposalsWaitTime: -1
)
Expand All @@ -91,7 +91,7 @@ public actor FakeMainService: MainService {
autoFaqsService: autoFaqsService,
cachesService: FakeCachesService(context: .init(
autoFaqsService: autoFaqsService,
proposalsChecker: proposalsChecker,
evolutionChecker: evolutionChecker,
soChecker: soChecker,
reactionCache: reactionCache
)),
Expand All @@ -103,7 +103,7 @@ public actor FakeMainService: MainService {
on: httpClient.eventLoopGroup.next()
)
),
proposalsChecker: proposalsChecker,
evolutionChecker: evolutionChecker,
soChecker: soChecker,
reactionCache: reactionCache
)
Expand Down
2 changes: 1 addition & 1 deletion Tests/Fake/FakeProposalsService.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@testable import Penny
import Models

public struct FakeProposalsService: ProposalsService {
public struct FakeEvolutionService: EvolutionService {

public init() { }

Expand Down
Loading

0 comments on commit 64b6753

Please sign in to comment.