<commit_before>import Bot
import Sugar
import Foundation

struct TimedMessageConfig {
    let interval: TimeInterval
    let target: String
    let announcement: (SlackTargetType) throws -> ChatPostMessage
}

final class TimedMessageService: SlackRTMEventService {
    private let config: TimedMessageConfig
    
    //MARK: - Lifecycle
    init(config: TimedMessageConfig) {
        self.config = config
    }
    
    //MARK: - Event Dispatch
    func configureEvents(slackBot: SlackBot, webApi: WebAPI, dispatcher: SlackRTMEventDispatcher) {
        dispatcher.onEvent(pong.self) { data in
            guard let timestamp = data["timestamp"] as? Int else { return }
            
            try self.pongEvent(slackBot: slackBot, webApi: webApi, timestamp: TimeInterval(timestamp))
        }
    }
    func pongEvent(slackBot: SlackBot, webApi: WebAPI, timestamp: TimeInterval) throws {
        let previous: TimeInterval = slackBot.storage.get(.in("Announcements"), key: "previousTimeStamp", or: 0)
        guard (timestamp - previous) >= self.config.interval else { return }
        
        try slackBot.storage.set(.in("Announcements"), key: "previousTimeStamp", value: timestamp)
        let data = slackBot.currentSlackModelData()
        guard let channel = data.channels.filter({ $0.name == config.target }).first
            else { return }
        
        let message = try config.announcement(channel)
        
        try webApi.execute(message)
    }
}<commit_msg>updated to use new TimerService<commit_after>import Bot
import Sugar
import Foundation

struct TimedMessageConfig {
    let interval: TimeInterval
    let target: String
    let announcement: (SlackTargetType) throws -> ChatPostMessage
}

final class TimedMessageService: SlackRTMEventService {
    private let config: TimedMessageConfig
    private var timer: TimerService?
    
    //MARK: - Lifecycle
    init(config: TimedMessageConfig) {
        self.config = config
    }
    
    //MARK: - Event Dispatch
    func configureEvents(slackBot: SlackBot, webApi: WebAPI, dispatcher: SlackRTMEventDispatcher) {
        self.timer = TimerService(id: "timedMessage", interval: self.config.interval, storage: slackBot.storage, dispatcher: dispatcher) { _ in
            try self.pongEvent(slackBot: slackBot, webApi: webApi)
        }
    }
    func pongEvent(slackBot: SlackBot, webApi: WebAPI) throws {
        let data = slackBot.currentSlackModelData()
        guard let channel = data.channels.filter({ $0.name == config.target }).first
            else { return }
        
        let message = try config.announcement(channel)
        
        try webApi.execute(message)
    }
}
{'fraction_non_alphanumeric': 0.08968105065666042, 'fraction_numerical': 0.001125703564727955, 'mean_word_length': 2.9379615952732645, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4879568', 'n_tokens_mistral': 762, 'n_tokens_neox': 743, 'n_words': 197}