@@ -0,0 +1,420 @@
1+//
2+// Model.swift
3+// GDproject
4+//
5+// Created by cstore on 23/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import Foundation
10+import Alamofire
11+
12+class Model{
13+
14+ static let invalidTocken = 498
15+
16+ private static var isValidTocken: ((Int)->())? = { responce in
17+ if responce == invalidTocken {
18+ DataStorage.standard.setIsLoggedIn(value: false, with: 0)
19+ }
20+ }
21+
22+ private static let baseUrl = "https://valera-denis.herokuapp.com"
23+ static let decoder = JSONDecoder()
24+
25+ static let authenticationURL = URL(string:"\(baseUrl)/authentication/login")!
26+ static let postsLastURL = URL(string:"\(baseUrl)/posts/last")!
27+ static let postsForUserURL = URL(string:"\(baseUrl)/posts/forUser")!
28+ static let postsPublishURL = URL(string:"\(baseUrl)/posts/publish")!
29+ static let usersURL = URL(string:"\(baseUrl)/users")!
30+ static let usersAllURL = URL(string:"\(baseUrl)/users/all")!
31+ static let channelsGetURL = URL(string: "\(baseUrl)/channels/get")!
32+ static let channelsUpdateURL = URL(string: "\(baseUrl)/channels/update")!
33+ static let channelsListURL = URL(string: "\(baseUrl)/channels")!
34+ static let channelsCreateURL = URL(string: "\(baseUrl)/channels/create")!
35+ static let channelsDeleteURL = URL(string: "\(baseUrl)/channels/delete")!
36+
37+
38+ struct QueryPosts: Codable{
39+ var users: [Int: Users]
40+ var posts: [Posts]
41+ }
42+
43+ struct Posts: Codable {
44+ var body: [Attachments]
45+ var authorId: Int
46+ var id: Int
47+ var user: Model.Users?
48+ var updated: String
49+ var tags: [String]
50+
51+ init(body: [Attachments], authorId: Int, id: Int, date: String,tags: [String]) {
52+ self.body = body
53+ self.authorId = authorId
54+ self.id = id
55+ self.updated = date
56+ self.tags = tags
57+ }
58+
59+ init(body: [Attachments], authorId: Int, id: Int, user: Model.Users, date: String, tags: [String]) {
60+ self.body = body
61+ self.authorId = authorId
62+ self.id = id
63+ self.user = user
64+ self.updated = date
65+ self.tags = tags
66+ }
67+
68+ func convertDateFormatter() -> String
69+ {
70+
71+ let dateFormatter = DateFormatter()
72+ dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"//this your string date format
73+ dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
74+ let date = dateFormatter.date(from: updated)
75+
76+ dateFormatter.dateFormat = "MMM d, yyyy HH:mm" ///this is what you want to convert format
77+ dateFormatter.timeZone = NSTimeZone.local
78+ let timeStamp = dateFormatter.string(from: date!)
79+
80+ return timeStamp
81+ }
82+ }
83+
84+ struct CreatedPost: Codable {
85+ var body = [Attachments]()
86+ var tags = [String]()
87+
88+ enum CodingKeys: String, CodingKey {
89+ case body
90+ case tags
91+ }
92+
93+ func encode(to encoder: Encoder) throws {
94+ var container = encoder.container(keyedBy: CodingKeys.self)
95+ try container.encode(body, forKey: .body)
96+ try container.encode(tags, forKey: .tags)
97+ }
98+ }
99+
100+ struct Users: Codable{
101+
102+ var middleName: String
103+ var lastName: String
104+ var firstName: String
105+ var id: Int
106+
107+ }
108+
109+ struct Attachments: Codable {
110+ var markdown: String
111+
112+ init(markdown: String) {
113+ self.markdown = markdown
114+ }
115+
116+ enum CodingKeys: String, CodingKey {
117+ case markdown
118+ }
119+
120+ func encode(to encoder: Encoder) throws {
121+ var container = encoder.container(keyedBy: CodingKeys.self)
122+ try container.encode(markdown, forKey: .markdown)
123+ }
124+ }
125+
126+ struct Channels: Codable {
127+
128+ static var fullTags = Set<String>()
129+ static var fullPeople = [Users]()
130+ static var fullPeopleDict = [Int:Users]()
131+
132+ var people: [Int]
133+ var name: String
134+ var id: Int?
135+ var tags: [String]
136+
137+ init(people: [Int], name: String, id: Int, tags: [String]) {
138+ self.id = id
139+ self.people = people
140+ self.tags = tags
141+ self.name = name
142+ }
143+
144+ init(people: [Int], name: String, tags: [String]) {
145+ self.people = people
146+ self.tags = tags
147+ self.name = name
148+ }
149+
150+ enum CodingKeys: String, CodingKey {
151+ case people
152+ case name
153+ case id
154+ case tags
155+ }
156+
157+ func encode(to encoder: Encoder) throws {
158+ var container = encoder.container(keyedBy: CodingKeys.self)
159+ try container.encode(people, forKey: .people)
160+ try container.encode(name, forKey: .name)
161+ try container.encode(id, forKey: .id)
162+ try container.encode(tags, forKey: .tags)
163+ }
164+ }
165+
166+ static func authenticate(with id: Int, completion: @escaping ((Bool)->())) {
167+
168+ let json: [String:Any] = ["authenticationId" : id]
169+ let jsonData = try? JSONSerialization.data(withJSONObject: json)
170+
171+ var request = URLRequest(url: authenticationURL)
172+ request.httpMethod = "POST"
173+
174+ // insert json data to the request
175+ request.httpBody = jsonData
176+ request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
177+
178+ AF.request(request).response { (responce) in
179+
180+ guard let realResponse = responce.response, realResponse.statusCode == 200 else
181+ {
182+ print("Not a 200 response")
183+ completion(false)
184+ return
185+ }
186+
187+ guard let json = responce.data else { return }
188+ guard let personId = Int(String(data: json, encoding: String.Encoding.utf8)!) else {
189+ completion(false)
190+ return
191+ }
192+
193+ let fields = realResponse.allHeaderFields as? [String :String]
194+
195+ let cookies = HTTPCookie.cookies(withResponseHeaderFields: fields!, for: realResponse.url!)
196+
197+ HTTPCookieStorage.shared.setCookie(cookies[0])
198+
199+ DataStorage.standard.setIsLoggedIn(value: true, with: personId)
200+ completion(true)
201+ }
202+ }
203+
204+
205+ static func getLast(completion: @escaping (((users:[Int: Users], posts:[Posts]))->())){
206+ let jsonString = "30"
207+ var request = URLRequest(url: postsLastURL)
208+
209+ request.httpMethod = "POST"
210+
211+ // insert json data to the request
212+ request.httpBody = jsonString.data(using: .utf8)
213+ request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
214+
215+ AF.request(request).responseJSON {
216+ (response) in
217+
218+ isValidTocken?(response.response?.statusCode ?? 498)
219+
220+ guard let json = response.data else { return }
221+
222+ guard let newQueery = try? decoder.decode(QueryPosts.self, from: json) else { print("no")
223+ return }
224+
225+ idUser = newQueery.users
226+ completion((newQueery.users, newQueery.posts))
227+ }
228+ }
229+
230+
231+ static func createAndPublish(body: [Attachments], tags: [String]){
232+ let jsonUpd = CreatedPost(body: body, tags: tags)
233+ var request = URLRequest(url: postsPublishURL)
234+
235+ request.httpMethod = "POST"
236+
237+ // insert json data to the request
238+ request.httpBody = try? JSONEncoder().encode(jsonUpd)
239+
240+ request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
241+ AF.request(request).response {
242+ (response) in
243+
244+ isValidTocken?(response.response?.statusCode ?? 498)
245+ }
246+ }
247+
248+
249+ static func getPostsForUser(with id: Int, completion: @escaping (([Posts])->())){
250+ let json = [
251+ "request" : id,
252+ "limit": 10
253+ ]
254+
255+ let jsonData = try? JSONSerialization.data(withJSONObject: json)
256+
257+ var request = URLRequest(url: postsForUserURL)
258+ request.httpMethod = "POST"
259+
260+ // insert json data to the request
261+ request.httpBody = jsonData
262+ request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
263+
264+ AF.request(request).responseJSON {
265+ (response) in
266+
267+ isValidTocken?(response.response?.statusCode ?? 498)
268+
269+ guard let json = response.data else { return }
270+
271+ guard let newPost = try? decoder.decode(QueryPosts.self, from: json) else { return }
272+
273+ completion(newPost.posts)
274+ }
275+ }
276+
277+ static var idUser: [Int:Users] = [:]
278+
279+ static func getUsers(for ids: [Int], completion: @escaping (([Int:Users])->())){
280+ let json = "\(Set(ids))"
281+ print(json)
282+ var request = URLRequest(url: usersURL)
283+
284+ request.httpMethod = "POST"
285+
286+ // insert json data to the request
287+ request.httpBody = json.data(using: .utf8)
288+ request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
289+
290+ AF.request(request).responseJSON {
291+ (response) in
292+
293+ isValidTocken?(response.response?.statusCode ?? 498)
294+
295+ guard let json = response.data else { return }
296+
297+ guard let users = try? decoder.decode([Users].self, from: json) else { return }
298+
299+ var dict: [Int:Users] = [:]
300+ users.forEach({ (user) in
301+ dict[user.id] = user
302+ })
303+
304+ completion(dict)
305+ }
306+ }
307+
308+ // get channel (with id): in responce -- PostQuery
309+ static func getChannel(with channelId: Int, completion: @escaping (((users:[Int: Users], posts:[Posts]))->())){
310+ let json = [
311+ "request" : channelId,
312+ "limit": 10
313+ ]
314+
315+ let jsonData = try? JSONSerialization.data(withJSONObject: json)
316+
317+ var request = URLRequest(url: channelsGetURL)
318+ request.httpMethod = "POST"
319+
320+ // insert json data to the request
321+ request.httpBody = jsonData
322+ request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
323+
324+ AF.request(request).responseJSON {
325+ (response) in
326+
327+ isValidTocken?(response.response?.statusCode ?? 498)
328+
329+
330+ guard let json = response.data else { return }
331+
332+ guard let newQueery = try? decoder.decode(QueryPosts.self, from: json) else { return }
333+
334+ idUser = newQueery.users
335+ completion((newQueery.users, newQueery.posts))
336+ }
337+ }
338+
339+
340+ static func createChannel(with channel: Channels) {
341+
342+ var request = URLRequest(url: channelsCreateURL)
343+ request.httpMethod = "POST"
344+ request.httpBody = try? JSONEncoder().encode(channel)
345+
346+ request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
347+ AF.request(request).response {
348+ (response) in
349+
350+ isValidTocken?(response.response?.statusCode ?? 498)
351+ }
352+
353+ }
354+
355+ static func channelsList(completion: @escaping (([Channels])->())){
356+ var request = URLRequest(url: channelsListURL)
357+ request.httpMethod = "POST"
358+ request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
359+
360+ AF.request(request).responseJSON { (response) in
361+
362+ isValidTocken?(response.response?.statusCode ?? 498)
363+
364+ guard let json = response.data else { return }
365+
366+ guard let channelsList = try? decoder.decode([Channels].self, from: json) else { return }
367+
368+ completion(channelsList)
369+ }
370+ }
371+
372+ static func channelsDelete(by id: Int, completion: @escaping(()->())){
373+ var request = URLRequest(url: channelsDeleteURL)
374+ request.httpMethod = "POST"
375+ request.httpBody = "\(id)".data(using: .utf8)
376+ print("\(id)")
377+ request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
378+
379+ AF.request(request).response { (response) in
380+ isValidTocken?(response.response?.statusCode ?? 498)
381+ }
382+ completion()
383+ }
384+
385+ static func updateChannel(with channel: Channels) {
386+
387+ var request = URLRequest(url: channelsUpdateURL)
388+ request.httpMethod = "POST"
389+ request.httpBody = try? JSONEncoder().encode(channel)
390+
391+ request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
392+ AF.request(request).response {
393+ (response) in
394+
395+ isValidTocken?(response.response?.statusCode ?? 498)
396+ }
397+ }
398+
399+ static func usersAllGet() {
400+ var request = URLRequest(url: usersAllURL)
401+ request.httpMethod = "POST"
402+
403+ request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
404+ AF.request(request).response {
405+ (response) in
406+ guard let json = response.data else { return }
407+
408+ guard let users = try? decoder.decode([Users].self, from: json) else { return }
409+
410+ Channels.fullPeople = users
411+ Channels.fullPeopleDict = users.reduce([Int: Users]()) { (dict, person) -> [Int: Users] in
412+ var dict = dict
413+ dict[person.id] = person
414+ return dict
415+ }
416+
417+ isValidTocken?(response.response?.statusCode ?? 498)
418+ }
419+ }
420+}