You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
7.3 KiB
205 lines
7.3 KiB
//
|
|
// InstancesDataManager.swift
|
|
// elpha-ios
|
|
//
|
|
// Created by Dwayne Harris on 9/18/18.
|
|
// Copyright © 2018 Elpha. All rights reserved.
|
|
//
|
|
|
|
import Alamofire
|
|
import CoreData
|
|
import UIKit
|
|
|
|
class InstancesDataManager {
|
|
static let shared = InstancesDataManager()
|
|
|
|
let fetchLimit = 20
|
|
var instances: [ISInstanceMO] = []
|
|
var nextID: String?
|
|
var finished = false
|
|
|
|
func upsertLanguage(string: String) -> ISLanguageMO? {
|
|
let context = CoreDataManager.shared.context
|
|
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
|
|
|
let request = NSFetchRequest<ISLanguageMO>(entityName: "ISLanguage")
|
|
request.predicate = NSPredicate(format: "id == %@", string)
|
|
|
|
do {
|
|
let results = try context.fetch(request)
|
|
if let language = results.first {
|
|
return language
|
|
} else {
|
|
let language = ISLanguageMO(context: context)
|
|
language.id = string
|
|
|
|
return language
|
|
}
|
|
} catch {
|
|
print("\(error)")
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func upsertCategory(string: String) -> ISCategoryMO? {
|
|
let context = CoreDataManager.shared.context
|
|
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
|
|
|
|
let request = NSFetchRequest<ISCategoryMO>(entityName: "ISCategory")
|
|
request.predicate = NSPredicate(format: "id == %@", string)
|
|
|
|
do {
|
|
let results = try context.fetch(request)
|
|
if let category = results.first {
|
|
return category
|
|
} else {
|
|
let category = ISCategoryMO(context: context)
|
|
category.id = string
|
|
|
|
return category
|
|
}
|
|
} catch {
|
|
print("\(error)")
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func setAttributes(on instance: ISInstanceMO, with attributes: [String: Any]) {
|
|
guard let id = attributes["id"] as? String, let name = attributes["name"] as? String else {
|
|
return
|
|
}
|
|
|
|
let dateFormatter = DateFormatter()
|
|
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
|
|
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
|
|
|
|
instance.id = id
|
|
instance.name = name
|
|
instance.url = URL(string: "https://\(name)")!
|
|
instance.uptime = attributes["uptime"] as! Int32
|
|
instance.up = attributes["up"] as! Bool
|
|
instance.dead = attributes["dead"] as! Bool
|
|
instance.version = attributes["version"] as? String
|
|
instance.ipv6 = attributes["ipv6"] as! Bool
|
|
instance.users = Int64(attributes["users"] as! String)!
|
|
instance.statuses = Int64(attributes["statuses"] as! String)!
|
|
instance.connections = Int64(attributes["connections"] as! String)!
|
|
instance.openRegistrations = attributes["open_registrations"] as! Bool
|
|
instance.fetchedAt = Date()
|
|
|
|
if let activeUsers = attributes["active_users"] as? Int64 {
|
|
instance.activeUsers = activeUsers
|
|
}
|
|
|
|
if let updatedAt = attributes["updated_at"] as? String {
|
|
instance.updatedAt = dateFormatter.date(from: updatedAt)
|
|
}
|
|
|
|
if let checkedAt = attributes["checked_at"] as? String {
|
|
instance.checkedAt = dateFormatter.date(from: checkedAt)
|
|
}
|
|
|
|
if let thumbnail = attributes["thumbnail"] as? String {
|
|
instance.thumbnail = URL(string: thumbnail)!
|
|
}
|
|
|
|
if let info = attributes["info"] as? [String: Any] {
|
|
instance.shortDesc = info["short_description"] as? String
|
|
instance.fullDescription = info["full_description"] as? String
|
|
instance.topic = info["topic"] as? String
|
|
|
|
for language in info["languages"] as! [String] {
|
|
if let l = upsertLanguage(string: language) {
|
|
instance.mutableSetValue(forKey: "languages").add(l)
|
|
}
|
|
}
|
|
|
|
for category in info["categories"] as! [String] {
|
|
if let c = upsertCategory(string: category) {
|
|
instance.mutableSetValue(forKey: "categories").add(c)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func clearInstances() {
|
|
let request = NSFetchRequest<ISInstanceMO>(entityName: "ISInstance")
|
|
|
|
do {
|
|
let instances = try CoreDataManager.shared.context.fetch(request)
|
|
instances.forEach { instance in
|
|
CoreDataManager.shared.context.delete(instance)
|
|
}
|
|
} catch {
|
|
print("\(error)")
|
|
}
|
|
}
|
|
|
|
func reloadInstances(completion: @escaping (Error?) -> Void) {
|
|
nextID = nil
|
|
finished = false
|
|
|
|
loadInstances(completion: completion)
|
|
}
|
|
|
|
func loadInstances(completion: @escaping (Error?) -> Void) {
|
|
var params = [
|
|
"count=\(fetchLimit)",
|
|
"sort_by=users",
|
|
"sort_order=desc",
|
|
"include_closed=true",
|
|
"include_down=false",
|
|
]
|
|
|
|
if let nextID = nextID {
|
|
params.append("min_id=\(nextID)")
|
|
}
|
|
|
|
let requestURL = "\(Config.instancesServiceURL)\(Config.instancesServiceListEndpoint)?\(params.joined(separator: "&"))"
|
|
let headers: HTTPHeaders = ["Authorization": "Bearer \(Config.instancesServiceSecret)"]
|
|
|
|
Alamofire.request(requestURL, headers: headers).validate().responseJSON { response in
|
|
switch response.result {
|
|
case .success(let value):
|
|
guard let result = value as? [String: Any],
|
|
let pagination = result["pagination"] as? [String: Any],
|
|
let instances = result["instances"] as? [Any] else {
|
|
completion(NSError())
|
|
return
|
|
}
|
|
|
|
if let nextID = pagination["next_id"] as? String {
|
|
self.nextID = nextID
|
|
} else {
|
|
self.nextID = nil
|
|
self.finished = true
|
|
}
|
|
|
|
do {
|
|
for case let instance as [String: Any] in instances {
|
|
if let id = instance["id"] as? String {
|
|
let request = NSFetchRequest<ISInstanceMO>(entityName: "ISInstance")
|
|
request.predicate = NSPredicate(format: "id == %@", id)
|
|
|
|
let results: [ISInstanceMO] = try CoreDataManager.shared.context.fetch(request)
|
|
if let i = results.first {
|
|
self.setAttributes(on: i, with: instance)
|
|
} else {
|
|
let i = ISInstanceMO(context: CoreDataManager.shared.context)
|
|
self.setAttributes(on: i, with: instance)
|
|
}
|
|
}
|
|
}
|
|
|
|
CoreDataManager.shared.saveContext()
|
|
completion(nil)
|
|
} catch {
|
|
completion(error)
|
|
return
|
|
}
|
|
case .failure(let error):
|
|
completion(error)
|
|
}
|
|
}
|
|
}
|
|
}
|