<commit_before>import Foundation
import Hash
import HMAC

public enum PusherError: Error {
    case invalidInput
    case invalidResponse
    case invalidResponseStatusCode(statusCode: Int)
}

final public class Pusher {
    
    private let appId: String
    private let appKey: String
    private let appSecret: String
    
    private let session = URLSession(configuration: URLSessionConfiguration.default)
    
    public init(appKey: String, appSecret: String, appId: String) {
        self.appId = appId
        self.appKey = appKey
        self.appSecret = appSecret
    }
    
    public func notify(interests: [String], apns: [String:Any]? = nil, gcm: [String:Any]? = nil, fcm: [String:Any]? = nil, webhookURL: URL? = nil, webhookLevel: String = "INFO", completion: @escaping (_ error: Error?) -> Void) {
    
        var bodyDictionary: [String:Any] = [
            "interests": interests
        ]
        
        if let apns = apns {
            bodyDictionary["apns"] = apns
        }

        if let gcm = gcm {
            bodyDictionary["gcm"] = gcm
        }

        if let fcm = fcm {
            bodyDictionary["fcm"] = fcm
        }

        if let webhookURL = webhookURL {
            bodyDictionary["webhook_url"] = webhookURL.absoluteString
            bodyDictionary["webhook_level"] = webhookLevel
        }
        
        do {
            
            let bodyData = try JSONSerialization.data(withJSONObject: bodyDictionary, options: [])
            let bodyMd5String = try Hash.make(.md5, try bodyData.makeBytes()).hexString
            let queries = "auth_key=\(appKey)&auth_timestamp=\(Int64(Date().timeIntervalSince1970))&auth_version=1.0&body_md5=\(bodyMd5String)"
            let authSignature = try HMAC.make(.sha256, "POST\n/server_api/v1/apps/\(appId)/notifications\n\(queries)".bytes, key: appSecret.bytes).hexString
            
            //print("\(bodyData.string)")
            
            let request = NSMutableURLRequest(url: URL(string: "https://nativepush-cluster1.pusher.com/server_api/v1/apps/\(appId)/notifications?\(queries)&auth_signature=\(authSignature)")!)
            request.httpMethod = "POST"
            request.httpBody = bodyData
            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            
            session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) in
                if let error = error {
                    completion(error)
                } else if let response = response as? HTTPURLResponse {
                    if 200 ... 299 ~= response.statusCode {
                        if let data = data {
                            print("\(data.string)")
                        }
                        completion(nil)
                    } else {
                        completion(PusherError.invalidResponseStatusCode(statusCode: response.statusCode))
                    }
                } else {
                    completion(PusherError.invalidResponse)
                }
            }).resume()
            
        } catch {
            completion(PusherError.invalidInput)
        }
        
        
    }
    
}<commit_msg>fixes for Linux build<commit_after>import Foundation
import Hash
import HMAC

public enum PusherError: Error {
    case invalidInput
    case invalidResponse
    case invalidResponseStatusCode(statusCode: Int)
}

final public class Pusher {
    
    private let appId: String
    private let appKey: String
    private let appSecret: String
    
    private let session = URLSession(configuration: URLSessionConfiguration.default)
    
    public init(appKey: String, appSecret: String, appId: String) {
        self.appId = appId
        self.appKey = appKey
        self.appSecret = appSecret
    }
    
    public func notify(interests: [String], apns: [String:Any]? = nil, gcm: [String:Any]? = nil, fcm: [String:Any]? = nil, webhookURL: URL? = nil, webhookLevel: String = "INFO", completion: @escaping (_ error: Error?) -> Void) {
    
        var bodyDictionary: [String:Any] = [
            "interests": interests
        ]
        
        if let apns = apns {
            bodyDictionary["apns"] = apns
        }

        if let gcm = gcm {
            bodyDictionary["gcm"] = gcm
        }

        if let fcm = fcm {
            bodyDictionary["fcm"] = fcm
        }

        if let webhookURL = webhookURL {
            bodyDictionary["webhook_url"] = webhookURL.absoluteString
            bodyDictionary["webhook_level"] = webhookLevel
        }
        
        do {
            
            let bodyData = try JSONSerialization.data(withJSONObject: bodyDictionary, options: [])
            let bodyMd5String = try Hash.make(.md5, try bodyData.makeBytes()).hexString
            let queries = "auth_key=\(appKey)&auth_timestamp=\(Int64(Date().timeIntervalSince1970))&auth_version=1.0&body_md5=\(bodyMd5String)"
            let authSignature = try HMAC.make(.sha256, "POST\n/server_api/v1/apps/\(appId)/notifications\n\(queries)".bytes, key: appSecret.bytes).hexString
            
            //print("\(bodyData.string)")
            
            var request = URLRequest(url: URL(string: "https://nativepush-cluster1.pusher.com/server_api/v1/apps/\(appId)/notifications?\(queries)&auth_signature=\(authSignature)")!)
            request.httpMethod = "POST"
            request.httpBody = bodyData
            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
            
            session.dataTask(with: request, completionHandler: { (data, response, error) in
                if let error = error {
                    completion(error)
                } else if let response = response as? HTTPURLResponse {
                    if 200 ... 299 ~= response.statusCode {
                        if let data = data {
                            print("\(data.string)")
                        }
                        completion(nil)
                    } else {
                        completion(PusherError.invalidResponseStatusCode(statusCode: response.statusCode))
                    }
                } else {
                    completion(PusherError.invalidResponse)
                }
            }).resume()
            
        } catch {
            completion(PusherError.invalidInput)
        }
        
        
    }
    
}
{'fraction_non_alphanumeric': 0.10171087741327892, 'fraction_numerical': 0.00753413906765029, 'mean_word_length': 1.8294849023090587, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4923412', 'n_tokens_mistral': 1750, 'n_tokens_neox': 1702, 'n_words': 363}