Notifications.swift 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. // Copyright (C) 2016 Inigo Valentin
  2. //
  3. // This file is part of the Gasteizko Margolariak IOS app.
  4. //
  5. // The Gasteizko Margolariak IOS app is free software: you can
  6. // redistribute it and/or modify it under the terms of the
  7. // GNU General Public License as published by the Free Software
  8. // Foundation, either version 3 of the License, or (at your
  9. // option) any later version.
  10. //
  11. // The Gasteizko Margolariak IOS app is distributed in the
  12. // hope that it will be useful, but WITHOUT ANY WARRANTY;
  13. // without even the implied warranty of MERCHANTABILITY or
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
  15. // Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public
  18. // License along with the Gasteizko Margolariak IOS app.
  19. // If not, see <http://www.gnu.org/licenses/>.
  20. import Foundation
  21. import CoreData
  22. import UIKit
  23. import UserNotifications
  24. /**
  25. Class to fetch notifications from the server.
  26. */
  27. class Notifications{
  28. /**
  29. Starts the sync process.
  30. Always asynchronously.
  31. */
  32. init(){
  33. let url = buildUrl();
  34. notification(url: url)
  35. }
  36. /**
  37. Builds the URL to perform the sync against.
  38. :returns: The URL.
  39. */
  40. func buildUrl() -> URL{
  41. let url = URL(string: "https://margolariak.com/API/v1/notifications.php")
  42. return url!
  43. }
  44. /**
  45. Performs an asynchronous request.
  46. It fetches the info from the server and stores as Core Data
  47. :param: url The url to sync.
  48. */
  49. func notification(url: URL){
  50. NSLog(":NOTIFICATION:LOG: Notification fetch started.")
  51. //Synchronously get data
  52. let task = URLSession.shared.dataTask(with: url) { data, response, error in
  53. guard error == nil else {
  54. NSLog(":NOTIFICATION:ERROR: Unknown error.")
  55. return
  56. }
  57. guard let data = data else {
  58. NSLog(":NOTIFICATION:ERROR: Data is empty.")
  59. return
  60. }
  61. let strData: String = String(data:data, encoding: String.Encoding.utf8)!
  62. if strData.length > 0{
  63. NSLog(":NOTIFICATION:LOG: Notifications received.")
  64. let dataNotification: [String] = self.getData(data: strData)
  65. self.saveNotifications(entries: dataNotification)
  66. }
  67. }
  68. task.resume()
  69. }
  70. /**
  71. Extracts notifications from the raw data received.
  72. :param: param Received data in JSON format.
  73. :return: Array of strings containing the notifications.
  74. */
  75. func getData(data: String) -> [String]{
  76. //Separate the entries
  77. var entries : [String] = data.components(separatedBy: "},{")
  78. //Modify the first and the last one to remove bracers
  79. entries[0] = entries[0].subStr(start: 1, end: entries[0].length - 1)
  80. entries[entries.count - 1] = entries[entries.count - 1].subStr(start: 0, end: entries[entries.count - 1].length - 2)
  81. //Return the array
  82. return entries
  83. }
  84. /**
  85. Saves the data in the table.
  86. :param: entries Array of strings containing the rows of the table, in JSON format.
  87. */
  88. func saveNotifications(entries : [String]){
  89. let dateFormatter = DateFormatter()
  90. dateFormatter.timeZone = TimeZone.ReferenceType.local
  91. //Set up context
  92. let appDelegate = UIApplication.shared.delegate as! AppDelegate
  93. let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
  94. context.persistentStoreCoordinator = appDelegate.persistentStoreCoordinator
  95. let entity = NSEntityDescription.entity(forEntityName: "Notification", in: context)
  96. var row: NSManagedObject
  97. //Loop new entries
  98. for entry in entries{
  99. //Get id
  100. var str = entry
  101. let id: Int = Int(str.subStr(start : str.indexOf(target : "\"id\":")! + 6, end : str.indexOf(target : ",\"")! - 2))!
  102. //Get title_es
  103. str = str.subStr(start : str.indexOf(target : ",\"")! + 1, end : str.length - 1)
  104. let title_es: String = str.subStr(start : str.indexOf(target : "\"title_es\":")! + 12, end : str.indexOf(target : ",\"")! - 2)
  105. //Get title_en
  106. str = str.subStr(start : str.indexOf(target : ",\"")! + 1, end : str.length - 1)
  107. let title_en: String = str.subStr(start : str.indexOf(target : "\"title_en\":")! + 12, end : str.indexOf(target : ",\"")! - 2)
  108. //Get title_eu
  109. str = str.subStr(start : str.indexOf(target : ",\"")! + 1, end : str.length - 1)
  110. let title_eu: String = str.subStr(start : str.indexOf(target : "\"title_eu\":")! + 12, end : str.indexOf(target : ",\"")! - 2)
  111. //Get text_es
  112. str = str.subStr(start : str.indexOf(target : ",\"")! + 1, end : str.length - 1)
  113. let text_es: String = str.subStr(start : str.indexOf(target : "\"text_es\":")! + 11, end : str.indexOf(target : ",\"")! - 2)
  114. //Get text_en
  115. str = str.subStr(start : str.indexOf(target : ",\"")! + 1, end : str.length - 1)
  116. let text_en: String = str.subStr(start : str.indexOf(target : "\"text_en\":")! + 11, end : str.indexOf(target : ",\"")! - 2)
  117. //Get text_eu
  118. str = str.subStr(start : str.indexOf(target : ",\"")! + 1, end : str.length - 1)
  119. let text_eu: String = str.subStr(start : str.indexOf(target : "\"text_eu\":")! + 11, end: str.indexOf(target : ",\"")! - 2)
  120. //Get dtime
  121. str = str.subStr(start : str.indexOf(target : ",\"")! + 1, end : str.length - 1)
  122. dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
  123. let dtime = dateFormatter.date(from : str.subStr(start : str.indexOf(target : "\"dtime\":")! + 9, end : str.indexOf(target : ",\"")! - 2))!
  124. //Get GM
  125. str = str.subStr(start : str.indexOf(target : ",\"")! + 1, end : str.length - 1)
  126. let gm: Int = Int(str.subStr(start : str.indexOf(target : "\"gm\":")! + 6, end : str.indexOf(target : ",\"")! - 2))!
  127. // Not getting seen
  128. // Save & show
  129. let fetchRequest: NSFetchRequest<Notification> = Notification.fetchRequest()
  130. fetchRequest.predicate = NSPredicate(format: "id == %i", id)
  131. fetchRequest.fetchLimit = 1
  132. do{
  133. let searchResults = try context.fetch(fetchRequest)
  134. if (searchResults.count == 0){
  135. row = NSManagedObject(entity: entity!, insertInto: context)
  136. row.setValue(id, forKey: "id")
  137. row.setValue(title_es, forKey: "title_es")
  138. row.setValue(title_en, forKey: "title_en")
  139. row.setValue(title_eu, forKey: "title_eu")
  140. row.setValue(text_es, forKey: "text_es")
  141. row.setValue(text_en, forKey: "text_en")
  142. row.setValue(text_eu, forKey: "text_eu")
  143. row.setValue(dtime, forKey: "dtime")
  144. row.setValue(gm, forKey: "gm")
  145. do {
  146. try context.save()
  147. if #available(iOS 10.0, *) {
  148. let content = UNMutableNotificationContent()
  149. let lang = getLanguage()
  150. switch lang{
  151. case "en":
  152. content.title = title_en
  153. content.body = text_en
  154. break;
  155. case "eu":
  156. content.title = title_eu
  157. content.body = text_eu
  158. break;
  159. default:
  160. content.title = title_es
  161. content.body = text_es
  162. }
  163. content.sound = UNNotificationSound.default()
  164. let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 1, repeats: false)
  165. let request = UNNotificationRequest.init(identifier: "Not\(id)", content: content, trigger: trigger)
  166. // Schedule the notification.
  167. let center = UNUserNotificationCenter.current()
  168. center.add(request) {
  169. (error) in
  170. NSLog(":NOTIFICATION:ERROR: Error showing notification \(String(describing: error))")
  171. }
  172. }
  173. else {
  174. NSLog(":NOTIFICATION:ERROR: Can't send notifications in iOS versions lower than 10. Not showing notification \(id)")
  175. }
  176. }
  177. catch let error as NSError {
  178. NSLog(":NOTIFICATION:ERROR: Could not save notification with id \(id): \(error), \(error.userInfo).")
  179. }
  180. catch {
  181. NSLog(":NOTIFICATION:ERROR: Could not save notification with id \(id).")
  182. }
  183. }
  184. }
  185. catch {
  186. NSLog(":NOTIFICATION:ERROR: Error getting notifications: \(error)")
  187. }
  188. }
  189. }
  190. /**
  191. Gets the device language. The only recognized languages are Spanish, English and Basque.
  192. If the device has another language, Spanish will be selected by default.
  193. :return: Two-letter language code.}
  194. */
  195. func getLanguage() -> String{
  196. let pre = NSLocale.preferredLanguages[0].subStr(start: 0, end: 1)
  197. if(pre == "es" || pre == "en" || pre == "eu"){
  198. return pre
  199. }
  200. else{
  201. return "es"
  202. }
  203. }
  204. }