// // FilterV2.swift // Pachyderm // // Created by Shadowfacts on 12/2/22. // import Foundation public struct FilterV2: Decodable { public let id: String public let title: String public let context: [FilterV1.Context] public let expiresAt: Date? public let action: Action public let keywords: [Keyword] public static func update( _ filterID: String, title: String, context: [FilterV1.Context], expiresIn: TimeInterval?, action: Action, keywords keywordUpdates: [KeywordUpdate] ) -> Request { var keywordsParams = [Parameter]() for (index, update) in keywordUpdates.enumerated() { switch update { case .update(id: let id, keyword: let keyword, wholeWord: let wholeWord): keywordsParams.append("keywords_attributes[\(index)][id]" => id) keywordsParams.append("keywords_attributes[\(index)][keyword]" => keyword) keywordsParams.append("keywords_attributes[\(index)][whole_word]" => wholeWord) case .add(keyword: let keyword, wholeWord: let wholeWord): keywordsParams.append("keywords_attributes[\(index)][keyword]" => keyword) keywordsParams.append("keywords_attributes[\(index)][whole_word]" => wholeWord) case .destroy(id: let id): keywordsParams.append("keywords_attributes[\(index)][id]" => id) keywordsParams.append("keywords_attributes[\(index)][_destroy]" => true) } } return Request(method: .put, path: "/api/v2/filters/\(filterID)", body: ParametersBody([ "title" => title, "expires_in" => expiresIn, "filter_action" => action.rawValue, ] + "context" => context.contextStrings + keywordsParams)) } public static func create( title: String, context: [FilterV1.Context], expiresIn: TimeInterval?, action: Action, keywords keywordUpdates: [KeywordUpdate] ) -> Request { var keywordsParams = [Parameter]() for (index, update) in keywordUpdates.enumerated() { switch update { case .add(keyword: let keyword, wholeWord: let wholeWord): keywordsParams.append("keywords_attributes[\(index)][keyword]" => keyword) keywordsParams.append("keywords_attributes[\(index)][whole_word]" => wholeWord) default: fatalError("can only add keywords when creating filter") } } return Request(method: .post, path: "/api/v2/filters", body: ParametersBody([ "title" => title, "expires_in" => expiresIn, "filter_action" => action.rawValue, ] + "context" => context.contextStrings + keywordsParams)) } private enum CodingKeys: String, CodingKey { case id case title case context case expiresAt = "expires_at" case action = "filter_action" case keywords } } extension FilterV2 { public enum Action: String, Decodable, Hashable, CaseIterable { case warn case hide } } extension FilterV2 { public struct Keyword: Decodable { public let id: String public let keyword: String public let wholeWord: Bool public init(id: String, keyword: String, wholeWord: Bool) { self.id = id self.keyword = keyword self.wholeWord = wholeWord } private enum CodingKeys: String, CodingKey { case id case keyword case wholeWord = "whole_word" } } } extension FilterV2 { public enum KeywordUpdate { case update(id: String, keyword: String, wholeWord: Bool) case add(keyword: String, wholeWord: Bool) case destroy(id: String) } }