1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
package com.pitchedapps.frost.services
import android.app.IntentService
import android.app.Notification
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.support.v4.app.ActivityOptionsCompat
import android.support.v4.app.NotificationCompat
import android.support.v4.app.NotificationManagerCompat
import ca.allanwang.kau.utils.string
import com.pitchedapps.frost.R
import com.pitchedapps.frost.WebOverlayActivity
import com.pitchedapps.frost.dbflow.*
import com.pitchedapps.frost.facebook.FACEBOOK_COM
import com.pitchedapps.frost.facebook.FB_URL_BASE
import com.pitchedapps.frost.facebook.FbTab
import com.pitchedapps.frost.utils.ARG_URL
import com.pitchedapps.frost.utils.L
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
/**
* Created by Allan Wang on 2017-06-14.
*/
class NotificationService : IntentService(NotificationService::class.java.simpleName) {
companion object {
const val ARG_ID = "arg_id"
val epochMatcher: Regex by lazy { Regex(":([0-9]*),") }
val notifIdMatcher: Regex by lazy { Regex("notif_id\":([0-9]*),") }
}
override fun onHandleIntent(intent: Intent) {
val id = intent.getLongExtra(ARG_ID, -1L)
L.i("Handling notifications for $id")
if (id == -1L) return
val data = loadFbCookie(id) ?: return
L.i("Using data $data")
val doc = Jsoup.connect(FbTab.NOTIFICATIONS.url).cookie(FACEBOOK_COM, data.cookie).get()
val unreadNotifications = doc.getElementById("notifications_list").getElementsByClass("aclb")
var notifCount = 0
var latestEpoch = lastNotificationTime(data.id)
L.i("Latest Epoch $latestEpoch")
unreadNotifications.forEach {
elem ->
val notif = parseNotification(data, elem)
if (notif != null) {
if (notif.timestamp <= latestEpoch) return@forEach
notif.createNotification(this)
latestEpoch = notif.timestamp
notifCount++
}
}
if (notifCount > 0) saveNotificationTime(NotificationModel(data.id, latestEpoch))
summaryNotification(data.id, notifCount)
}
fun parseNotification(data: CookieModel, element: Element): NotificationContent? {
val a = element.getElementsByTag("a").first() ?: return null
val dataStore = a.attr("data-store")
val notifId = if (dataStore == null) System.currentTimeMillis()
else notifIdMatcher.find(dataStore)?.groups?.get(1)?.value?.toLong() ?: System.currentTimeMillis()
val abbr = element.getElementsByTag("abbr")
val timeString = abbr?.text()
var text = a.text().replace("\u00a0", " ") //remove
if (timeString != null) text = text.removeSuffix(timeString)
text = text.trim()
val abbrData = abbr?.attr("data-store")
val epoch = if (abbrData == null) -1L else epochMatcher.find(abbrData)?.groups?.get(1)?.value?.toLong() ?: -1L
return NotificationContent(data, notifId.toInt(), a.attr("href"), text, epoch)
}
data class NotificationContent(val data: CookieModel, val notifId: Int, val href: String, val text: String, val timestamp: Long) {
fun createNotification(context: Context) {
val intent = Intent(context, WebOverlayActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
intent.putExtra(ARG_URL, "$FB_URL_BASE$href")
intent.action = System.currentTimeMillis().toString() //dummy action
val group = "frost_${data.id}"
val bundle = ActivityOptionsCompat.makeCustomAnimation(context, R.anim.slide_in_right, R.anim.slide_out_right).toBundle()
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT, bundle)
val notifBuilder = NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.frost_f_24)
.setContentTitle(context.string(R.string.app_name))
.setContentText(text)
.setContentIntent(pendingIntent)
.setCategory(Notification.CATEGORY_SOCIAL)
.setSubText(data.name)
.setGroup(group)
.setAutoCancel(true)
// .setColor(context.color(R.color.facebook_blue))
if (timestamp != -1L) notifBuilder.setWhen(timestamp * 1000)
NotificationManagerCompat.from(context).notify(group, notifId, notifBuilder.build())
}
}
fun summaryNotification(userId: Long, count: Int) {
if (count <= 1) return
val notifBuilder = NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.frost_f_24)
.setContentTitle(string(R.string.app_name))
.setContentText("$count notifications")
.setGroup("frost_$userId")
.setGroupSummary(true)
.setAutoCancel(true)
NotificationManagerCompat.from(this).notify("frost_$userId", userId.toInt(), notifBuilder.build())
}
private fun log(element: Element) {
with(element) {
L.i("\n\nElement ${text()}")
attributes().forEach {
L.i("attr ${it.html()}")
}
L.i("Content ${html()}")
}
}
}
|