diff options
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt')
-rw-r--r-- | app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt | 107 |
1 files changed, 8 insertions, 99 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt index c4ab6161..adeefec6 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt @@ -7,18 +7,11 @@ import android.support.v4.app.NotificationManagerCompat import ca.allanwang.kau.utils.string import com.pitchedapps.frost.BuildConfig import com.pitchedapps.frost.R -import com.pitchedapps.frost.dbflow.CookieModel -import com.pitchedapps.frost.dbflow.lastNotificationTime import com.pitchedapps.frost.dbflow.loadFbCookiesSync -import com.pitchedapps.frost.facebook.FbItem -import com.pitchedapps.frost.facebook.formattedFbUrl -import com.pitchedapps.frost.parsers.MessageParser import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.frostAnswersCustom -import com.pitchedapps.frost.utils.frostJsoup import org.jetbrains.anko.doAsync -import org.jsoup.nodes.Element import java.util.concurrent.Future /** @@ -27,8 +20,7 @@ import java.util.concurrent.Future * Service to manage notifications * Will periodically check through all accounts in the db and send notifications when appropriate * - * Note that general notifications are parsed directly with Jsoup, - * but instant messages are done so with a headless webview as it is generated from JS + * All fetching is done through parsers */ class NotificationService : JobService() { @@ -36,13 +28,6 @@ class NotificationService : JobService() { val startTime = System.currentTimeMillis() - companion object { - val epochMatcher: Regex by lazy { Regex(":([0-9]*?),") } - val notifIdMatcher: Regex by lazy { Regex("notif_id\":([0-9]*?),") } - val messageNotifIdMatcher: Regex by lazy { Regex("thread_fbid_([0-9]+)") } - val profMatcher: Regex by lazy { Regex("url\\(\"(.*?)\"\\)") } - } - override fun onStopJob(params: JobParameters?): Boolean { val time = System.currentTimeMillis() - startTime L.d("Notification service has finished abruptly in $time ms") @@ -70,104 +55,28 @@ class NotificationService : JobService() { override fun onStartJob(params: JobParameters?): Boolean { L.i("Fetching notifications") future = doAsync { + val context = weakRef.get() + ?: return@doAsync L.eThrow("NotificationService had null weakRef to self") val currentId = Prefs.userId val cookies = loadFbCookiesSync() cookies.forEach { val current = it.id == currentId if (current || Prefs.notificationAllAccounts) - fetchGeneralNotifications(it) - if (Prefs.notificationsInstantMessages && (current || Prefs.notificationsImAllAccounts)) - fetchMessageNotifications(it) + NotificationType.GENERAL.fetch(context, it) + if (Prefs.notificationsInstantMessages + && (current || Prefs.notificationsImAllAccounts)) + NotificationType.MESSAGE.fetch(context, it) } finish(params) } return true } - fun logNotif(text: String): NotificationContent? { + private fun logNotif(text: String): NotificationContent? { L.eThrow("NotificationService: $text") return null } - /* - * ---------------------------------------------------------------- - * General notification logic. - * Fetch notifications -> Filter new ones -> Parse notifications -> - * Show notifications -> Show group notification - * ---------------------------------------------------------------- - */ - - fun fetchGeneralNotifications(data: CookieModel) { - L.d("Notif fetch", data.toString()) - val doc = frostJsoup(data.cookie, FbItem.NOTIFICATIONS.url) - //aclb for unread, acw for read - val unreadNotifications = (doc.getElementById("notifications_list") ?: return L.eThrow("Notification list not found")).getElementsByClass("aclb") - var notifCount = 0 - //val prevLatestEpoch = 1498931565L // for testing - val prevNotifTime = lastNotificationTime(data.id) - val prevLatestEpoch = prevNotifTime.epoch - L.v("Notif Prev Latest Epoch $prevLatestEpoch") - var newLatestEpoch = prevLatestEpoch - unreadNotifications.forEach unread@ { elem -> - val notif = parseNotification(data, elem) ?: return@unread - L.v("Notif timestamp ${notif.timestamp}") - if (notif.timestamp <= prevLatestEpoch) return@unread - NotificationType.GENERAL.createNotification(this, notif, notifCount == 0) - if (notif.timestamp > newLatestEpoch) - newLatestEpoch = notif.timestamp - notifCount++ - } - if (newLatestEpoch != prevLatestEpoch) prevNotifTime.copy(epoch = newLatestEpoch).save() - L.d("Notif new latest epoch ${lastNotificationTime(data.id).epoch}") - NotificationType.GENERAL.summaryNotification(this, data.id, notifCount) - } - - fun parseNotification(data: CookieModel, element: Element): NotificationContent? { - val a = element.getElementsByTag("a").first() ?: return logNotif("IM No a tag") - val abbr = element.getElementsByTag("abbr") - val epoch = epochMatcher.find(abbr.attr("data-store"))?.groups?.get(1)?.value?.toLong() ?: return logNotif("IM No epoch") - //fetch id - val notifId = notifIdMatcher.find(a.attr("data-store"))?.groups?.get(1)?.value?.toLong() ?: System.currentTimeMillis() - val timeString = abbr.text() - val text = a.text().replace("\u00a0", " ").removeSuffix(timeString).trim() //remove - if (Prefs.notificationKeywords.any { text.contains(it, ignoreCase = true) }) return null //notification filtered out - //fetch profpic - val p = element.select("i.img[style*=url]") - val pUrl = profMatcher.find(p.attr("style"))?.groups?.get(1)?.value?.formattedFbUrl ?: "" - return NotificationContent(data, notifId.toInt(), a.attr("href"), null, text, epoch, pUrl) - } - - /* - * ---------------------------------------------------------------- - * Instant message notification logic. - * Fetch notifications -> Filter new ones -> Parse notifications -> - * Show notifications -> Show group notification - * ---------------------------------------------------------------- - */ - - fun fetchMessageNotifications(data: CookieModel) { - L.d("Notif IM fetch", data.toString()) - val doc = frostJsoup(data.cookie, FbItem.MESSAGES.url) - val (threads, _, _) = MessageParser.parse(doc.toString()) ?: return L.e("Could not parse IM") - - var notifCount = 0 - val prevNotifTime = lastNotificationTime(data.id) - val prevLatestEpoch = prevNotifTime.epochIm - L.v("Notif Prev Latest Im Epoch $prevLatestEpoch") - var newLatestEpoch = prevLatestEpoch - threads.filter { it.unread }.forEach { notif -> - L.v("Notif Im timestamp ${notif.time}") - if (notif.time <= prevLatestEpoch) return@forEach - NotificationType.MESSAGE.createNotification(this, NotificationContent(data, notif), notifCount == 0) - if (notif.time > newLatestEpoch) - newLatestEpoch = notif.time - notifCount++ - } - if (newLatestEpoch != prevLatestEpoch) prevNotifTime.copy(epochIm = newLatestEpoch).save() - L.d("Notif new latest im epoch ${lastNotificationTime(data.id).epochIm}") - NotificationType.MESSAGE.summaryNotification(this, data.id, notifCount) - } - private fun Context.debugNotification(text: String) { if (!BuildConfig.DEBUG) return val notifBuilder = frostNotification.withDefaults() |