1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| import Foundation
public class Slack { public var name: String = "Send message to Slack" public var isEnabled = true
private var message: Message?
public init(_ closure: (Slack) -> Void = { _ in }) { closure(self) } }
public extension Slack { struct Message { let token: String let channel: String let text: String let username: String?
public init( token: String, channel: String, text: String, username: String ) { self.token = token self.channel = channel self.text = text self.username = username } }
func post(message: Message) { self.message = message } }
extension Slack: Task { public func run(workflow: Workflow, completion: @escaping TaskCompletion) { guard let message = message else { completion(.failure(PumaError.invalid)) return }
let sender = MessageSender() sender.send(message: message, completion: { result in switch result { case .success: Deps.console.success("Message posted successfully") case .failure(let error): Deps.console.error("Failed: \(error.localizedDescription)") } completion(result) }) } }
private class MessageSender { struct Response: Decodable { let ok: Bool let error: String? }
func send(message: Slack.Message, completion: @escaping (Result<(), Error>) -> Void) { guard let baseUrl = URL(string: "https://slack.com/api/chat.postMessage") else { completion(.failure(PumaError.invalid)) return }
var components = URLComponents(url: baseUrl, resolvingAgainstBaseURL: false) components?.queryItems = [ URLQueryItem(name: "token", value: message.token), URLQueryItem(name: "channel", value: message.channel), URLQueryItem(name: "text", value: message.text), URLQueryItem(name: "pretty", value: "1") ]
if let username = message.username { components?.queryItems?.append( URLQueryItem(name: "username", value: username) ) }
guard let requestUrl = components?.url else { completion(.failure(PumaError.invalid)) return }
var request = URLRequest(url: requestUrl) request.allHTTPHeaderFields = [ "Accept": "application/json" ]
let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in guard let data = data else { completion(.failure(error ?? PumaError.invalid)) return }
do { let response = try JSONDecoder().decode(Response.self, from: data) if response.ok { completion(.success(())) } else { completion(.failure(PumaError.from(string: response.error))) } } catch { completion(.failure(error)) } })
task.resume() } }
|