[ABANDONED] Mastodon iOS client.
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

//
// 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)
}
}
}
}