OSDN Git Service

endpointを文字列のまま扱わないようにした
[kcd/KCD.git] / KCD / APIResponse.swift
1 //
2 //  APIResponse.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2017/01/20.
6 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10 import SwiftyJSON
11
12 extension JSON {
13     
14     func value(for keyPath: String) -> JSON {
15         
16         return self[keyPath.components(separatedBy: ".")]
17     }
18     
19     var last: JSON {
20         
21         let index = self.count - 1
22         
23         return self[index]
24     }
25 }
26
27 private extension Data {
28     
29     var utf8String: String? { return String(data: self, encoding: .utf8) }
30 }
31
32 func +<Key, Value> (lhs: [Key: Value], rhs: (Key, Value)) -> [Key: Value] {
33     
34     var new = lhs
35     new[rhs.0] = rhs.1
36     
37     return new
38 }
39
40 private func splitJSON(_ data: Data) -> String? {
41     
42     let prefix = "svdata="
43     
44     guard let string = data.utf8String,
45         let range = string.range(of: prefix) else {
46             
47             return Logger.shared.log("data is wrong", value: nil)
48     }
49     
50     return String(string[range.upperBound...])
51 }
52
53 private func parseParameter(_ request: URLRequest) -> [String: String]? {
54     
55     return request
56         .httpBody?
57         .utf8String?
58         .removingPercentEncoding?
59         .components(separatedBy: "&")
60         .map { $0.components(separatedBy: "=") }
61         .filter { $0.count == 2 }
62         .map { (piar: [String]) -> (String, String) in (piar[0], piar[1]) }
63         .reduce(into: [String: String]()) { (dict: inout [String: String], value: (String, String)) in
64             
65             dict[value.0] = value.1
66     }
67 }
68
69 struct ParameterValue {
70     
71     private let rawValue: String?
72     
73     var int: Int? { return rawValue.flatMap { Int($0) } }
74     var double: Double? { return rawValue.flatMap { Double($0) } }
75     var string: String? { return rawValue }
76     var bool: Bool? {
77         
78         guard let _ = rawValue else { return nil }
79         
80         if let i = self.int {
81             
82             return i != 0
83         }
84         
85         if let s = self.string?.lowercased() {
86             
87             switch s {
88             case "true", "yes", "t", "y": return true
89                 
90             default: return false
91             }
92         }
93         
94         return false
95     }
96     
97     var valid: Bool { return rawValue != nil }
98     
99     init(_ rawValue: String?) {
100         
101         self.rawValue = rawValue
102     }
103 }
104
105 struct Parameter {
106     
107     private let rawValue: [String: String]
108     
109     init(_ rawValue: [String: String]) {
110         
111         self.rawValue = rawValue
112     }
113     
114     init?(_ request: URLRequest) {
115         
116         guard let paramList = parseParameter(request) else { return nil }
117         
118         self.init(paramList)
119     }
120     
121     subscript(_ key: String) -> ParameterValue {
122         
123         return ParameterValue(rawValue[key])
124     }
125     
126     func map<T>(_ transform: (String, String) throws -> T) rethrows -> [T] {
127         
128         return try rawValue.map(transform)
129     }
130 }
131
132 extension Parameter: Equatable {
133     
134     public static func == (lhs: Parameter, rhs: Parameter) -> Bool {
135         return lhs.rawValue == rhs.rawValue
136     }
137 }
138
139 struct APIResponse {
140     
141     let api: API
142     let parameter: Parameter
143     let json: JSON
144     let date: Date
145     var success: Bool {
146         
147         if let r = json["api_result"].int { return r == 1 }
148         
149         return false
150     }
151     
152     init(api: API, parameter: Parameter, json: JSON) {
153         
154         self.api = api
155         self.parameter = parameter
156         self.json = json
157         self.date = Date()
158     }
159     
160     init?(request: URLRequest, data: Data) {
161         
162         date = Date()
163         
164         guard let josn = splitJSON(data) else {
165             
166             Logger.shared.log("Can not parse JSON")
167             return nil
168         }
169         
170         self.json = JSON(parseJSON: josn)
171         
172         guard let parameter = Parameter(request) else {
173             
174             Logger.shared.log("Can not parse Parameter")
175             return nil
176         }
177         
178         self.parameter = parameter
179         
180         guard let api = request.url?.path else {
181             
182             Logger.shared.log("URLRequest is wrong")
183             return nil
184         }
185         
186         self.api = API(endpointPath: api)
187     }
188 }