<commit_before>//
//  Slack.swift
//  stts
//

import Kanna

class Slack: Service {
    override var url: URL { return URL(string: "https://status.slack.com")! }

    override func updateStatus(callback: @escaping (Service) -> Void) {
        URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
            guard let selfie = self else { return }
            defer { callback(selfie) }

            guard let data = data else { return selfie._fail(error) }
            guard let body = String(data: data, encoding: .utf8) else { return selfie._fail("Unreadable response") }
            guard let doc = HTML(html: body, encoding: .utf8) else { return selfie._fail("Couldn't parse response") }

            let serviceImages = doc.css("#services .service.header img")
            guard serviceImages.count > 0 else { return selfie._fail("Unexpected response") }
            let imageURLs = serviceImages.flatMap { $0["src"] }

            var resultStatus: ServiceStatus = .undetermined
            var resultMessage = "Undetermined"

            for url in imageURLs {
                guard resultStatus != .major else { break } // No need to check the rest if major

                guard let lastPart = url.split(separator: "/").last else { continue }
                let imageName = String(lastPart).lowercased()

                let (thisStatus, thisMessage) = selfie.status(from: imageName)

                if thisStatus >= resultStatus {
                    resultStatus = thisStatus
                    resultMessage = thisMessage
                }
            }

            self?.status = resultStatus
            self?.message = resultMessage
        }.resume()
    }
}

extension Slack {
    fileprivate func status(from imageName: String) -> (ServiceStatus, String) {
        switch imageName {
        case "tableoutage.png":
            return (.major, "Outage")
        case "tableincident.png":
            return (.minor, "Incident")
        case "tablemaintenance.png":
            return (.maintenance, "Maintenance")
        case "tablenotice.png":
            return (.notice, "[!] Notice Available")
        case "tablecheck.png":
            return (.good, "No Issues")
        default:
            return (.undetermined, "Undetermined")
        }
    }
}<commit_msg>Improved Slack support and status message<commit_after>//
//  Slack.swift
//  stts
//

import Kanna

class Slack: Service {
    override var url: URL { return URL(string: "https://status.slack.com")! }

    override func updateStatus(callback: @escaping (Service) -> Void) {
        URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
            guard let selfie = self else { return }
            defer { callback(selfie) }

            guard let data = data else { return selfie._fail(error) }
            guard let body = String(data: data, encoding: .utf8) else { return selfie._fail("Unreadable response") }
            guard let doc = HTML(html: body, encoding: .utf8) else { return selfie._fail("Couldn't parse response") }

            let serviceImages = doc.css("#services .service.header img")
            guard serviceImages.count > 0 else { return selfie._fail("Unexpected response") }

            let imageURLs = serviceImages.flatMap { $0["src"] }
            let statuses = imageURLs.map { selfie.status(from: $0) }

            self?.status = statuses.max() ?? .undetermined
            self?.message = doc.css("#current_status h1").first?.text ?? "Undetermined"
        }.resume()
    }
}

extension Slack {
    fileprivate func status(from imageURL: String) -> ServiceStatus {
        guard let lastPart = imageURL.split(separator: "/").last else {
            return .undetermined
        }
        let imageName = String(lastPart).lowercased()

        switch imageName {
        case "tableoutage.png":
            return .major
        case "tableincident.png":
            return .minor
        case "tablemaintenance.png":
            return .maintenance
        case "tablenotice.png":
            return .notice
        case "tablecheck.png":
            return .good
        default:
            return .undetermined
        }
    }
}
{'fraction_non_alphanumeric': 0.10978520286396182, 'fraction_numerical': 0.002386634844868735, 'mean_word_length': 2.04578488372093, 'pattern_counts': {'":': 10, '<': 3, '<?xml version=': 0, '>': 10, 'https://': 2, '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': '3712178', 'n_tokens_mistral': 1166, 'n_tokens_neox': 1102, 'n_words': 319}