aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt
blob: 85765541984dfbe7a28f63bbd59c246c1bad3b73 (plain)
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
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.v("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.v("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 &nbsp;
        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())
    }

}