aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbRequest.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/facebook/FbRequest.kt')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbRequest.kt98
1 files changed, 98 insertions, 0 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbRequest.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbRequest.kt
new file mode 100644
index 00000000..428043a0
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbRequest.kt
@@ -0,0 +1,98 @@
+package com.pitchedapps.frost.facebook
+
+import com.pitchedapps.frost.BuildConfig
+import com.pitchedapps.frost.utils.L
+import io.reactivex.Single
+import io.reactivex.schedulers.Schedulers
+import okhttp3.*
+import okhttp3.logging.HttpLoggingInterceptor
+import org.apache.commons.text.StringEscapeUtils
+
+/**
+ * Created by Allan Wang on 21/12/17.
+ */
+data class RequestAuth(val userId: Long = -1, val cookie: String = "", val fb_dtsg: String = "")
+
+private val client: OkHttpClient by lazy {
+ val builder = OkHttpClient.Builder()
+ if (BuildConfig.DEBUG)
+ builder.addInterceptor(HttpLoggingInterceptor()
+ .setLevel(HttpLoggingInterceptor.Level.BASIC))
+ builder.build()
+}
+
+private fun List<Pair<String, Any?>>.toForm(): RequestBody {
+ val builder = FormBody.Builder()
+ forEach { (key, value) ->
+ val v = value?.toString() ?: ""
+ builder.add(key, v)
+ }
+ return builder.build()
+}
+
+private fun String.requestBuilder() = Request.Builder()
+ .header("Cookie", this)
+ .header("User-Agent", USER_AGENT_BASIC)
+ .cacheControl(CacheControl.FORCE_NETWORK)
+
+private fun Request.Builder.call() = client.newCall(build())
+
+
+fun Pair<Long, String>.getAuth(): RequestAuth? {
+ val (userId, cookie) = this
+ val call = cookie.requestBuilder()
+ .url(FB_URL_BASE)
+ .get()
+ .call()
+ call.execute().body()?.charStream()?.useLines {
+ it.forEach {
+ val text = StringEscapeUtils.unescapeEcmaScript(it)
+ val result = FB_DTSG_MATCHER.find(text)
+ val fb_dtsg = result?.groupValues?.get(1)
+ if (fb_dtsg != null) {
+ L.d(null, "fb_dtsg for $userId: $fb_dtsg")
+ return RequestAuth(userId, cookie, fb_dtsg)
+ }
+ }
+ }
+
+ return null
+}
+
+fun RequestAuth.markNotificationRead(notifId: Long): Call {
+
+ val body = listOf(
+ "click_type" to "notification_click",
+ "id" to notifId,
+ "target_id" to "null",
+ "m_sess" to null,
+ "fb_dtsg" to fb_dtsg,
+ "__dyn" to null,
+ "__req" to null,
+ "__ajax__" to null,
+ "__user" to userId
+ )
+
+ return cookie.requestBuilder()
+ .url("${FB_URL_BASE}a/jewel_notifications_log.php")
+ .post(body.toForm())
+ .call()
+}
+
+private inline fun <T, reified R : Any, O> zip(data: Array<T>,
+ crossinline mapper: (List<R>) -> O,
+ crossinline caller: (T) -> R): Single<O> {
+ val singles = data.map { Single.fromCallable { caller(it) }.subscribeOn(Schedulers.io()) }
+ return Single.zip(singles) {
+ val results = it.mapNotNull { it as? R }
+ mapper(results)
+ }
+}
+
+fun RequestAuth.markNotificationsRead(vararg notifId: Long) = zip<Long, Boolean, Int>(notifId.toTypedArray(),
+ { it.count { it } }) {
+ val response = markNotificationRead(it).execute()
+ val buffer = CharArray(20)
+ response.body()?.charStream()?.read(buffer) ?: return@zip false
+ !buffer.toString().contains("error")
+}