aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2018-01-10 22:13:28 -0500
committerGitHub <noreply@github.com>2018-01-10 22:13:28 -0500
commitfd5f2a82eb968b5d50f586925ebb705249062446 (patch)
tree7e2cb3edad1e2398d74eb2780a912ed05188db41 /app/src/main/kotlin/com/pitchedapps/frost/facebook/requests
parentad97b4ff946b4ba3a3f7ac880575eed9de810166 (diff)
downloadfrost-fd5f2a82eb968b5d50f586925ebb705249062446.tar.gz
frost-fd5f2a82eb968b5d50f586925ebb705249062446.tar.bz2
frost-fd5f2a82eb968b5d50f586925ebb705249062446.zip
Misc (#614)
* Add locale log * Add flyweight design for authenticator * Add option to have instant messages only * Update interceptor * Add hd image model loader (#613) * Launch image view for view full image * Update changelog * Greatly improve ImageActivity loading * Update hashes * Add back keyword filter * Clean up
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/facebook/requests')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/FbRequest.kt31
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Images.kt67
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Messages.kt32
3 files changed, 113 insertions, 17 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/FbRequest.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/FbRequest.kt
index ae8652e6..3ca37bb4 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/FbRequest.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/FbRequest.kt
@@ -2,6 +2,7 @@ package com.pitchedapps.frost.facebook.requests
import com.pitchedapps.frost.BuildConfig
import com.pitchedapps.frost.facebook.*
+import com.pitchedapps.frost.rx.RxFlyweight
import com.pitchedapps.frost.utils.L
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
@@ -12,7 +13,17 @@ import org.apache.commons.text.StringEscapeUtils
/**
* Created by Allan Wang on 21/12/17.
*/
-private val authMap: MutableMap<String, RequestAuth> = mutableMapOf()
+private class RxAuth : RxFlyweight<String, Long, RequestAuth>() {
+
+ override fun call(input: String) = input.getAuth()
+
+ override fun validate(input: String, cond: Long) =
+ System.currentTimeMillis() - cond < 3600000 // valid for an hour
+
+ override fun cache(input: String) = System.currentTimeMillis()
+}
+
+private val auth = RxAuth()
/**
* Synchronously fetch [RequestAuth] from cookie
@@ -21,18 +32,13 @@ private val authMap: MutableMap<String, RequestAuth> = mutableMapOf()
*/
fun String?.fbRequest(fail: () -> Unit = {}, action: RequestAuth.() -> Unit) {
if (this == null) return fail()
- val savedAuth = authMap[this]
- if (savedAuth != null) {
- savedAuth.action()
- } else {
- val auth = getAuth()
- if (!auth.isValid) {
- L.e { "Attempted fbrequest with invalid auth" }
- return fail()
+ auth(this).subscribe { a: RequestAuth?, _ ->
+ if (a?.isValid == true)
+ a.action()
+ else {
+ L.e { "Failed auth for ${hashCode()}" }
+ fail()
}
- authMap.put(this, auth)
- L._i { "Found auth $auth" }
- auth.action()
}
}
@@ -94,6 +100,7 @@ private fun String.requestBuilder() = Request.Builder()
fun Request.Builder.call() = client.newCall(build())!!
fun String.getAuth(): RequestAuth {
+ L.v { "Getting auth for ${hashCode()}" }
var auth = RequestAuth(cookie = this)
val id = FB_USER_MATCHER.find(this)[1]?.toLong() ?: return auth
auth = auth.copy(userId = id)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Images.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Images.kt
index 61a94ac5..fa78bbfa 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Images.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Images.kt
@@ -1,9 +1,19 @@
package com.pitchedapps.frost.facebook.requests
import com.bumptech.glide.Priority
+import com.bumptech.glide.RequestBuilder
import com.bumptech.glide.load.DataSource
+import com.bumptech.glide.load.Options
import com.bumptech.glide.load.data.DataFetcher
+import com.bumptech.glide.load.model.ModelLoader
+import com.bumptech.glide.load.model.ModelLoaderFactory
+import com.bumptech.glide.load.model.MultiModelLoaderFactory
+import com.bumptech.glide.request.RequestOptions
+import com.bumptech.glide.request.target.Target
+import com.bumptech.glide.signature.ObjectKey
+import com.pitchedapps.frost.facebook.FB_IMAGE_ID_MATCHER
import com.pitchedapps.frost.facebook.FB_URL_BASE
+import com.pitchedapps.frost.facebook.get
import okhttp3.Call
import okhttp3.Request
import java.io.IOException
@@ -17,8 +27,54 @@ fun RequestAuth.getFullSizedImage(fbid: Long) = frostRequest(::getJsonUrl) {
get()
}
-class ImageFbidFetcher(private val fbid: Long,
- private val cookie: String) : DataFetcher<InputStream> {
+/**
+ * Request loader for a potentially hd version of a url
+ * In this case, each url may potentially return an id,
+ * which may potentially be used to fetch a higher res image url
+ * The following aims to allow such loading while adhering to Glide's lifecycle
+ */
+data class HdImageMaybe(val url: String, val cookie: String) {
+
+ val id: Long by lazy { FB_IMAGE_ID_MATCHER.find(url)[1]?.toLongOrNull() ?: -1 }
+
+ val isValid: Boolean by lazy {
+ id != -1L && cookie.isNotBlank()
+ }
+
+}
+
+/*
+ * The following was a test to see if hd image loading would work
+ *
+ * It's working and tested, though the improvements aren't really worth the extra data use
+ * and reload
+ */
+
+class HdImageLoadingFactory : ModelLoaderFactory<HdImageMaybe, InputStream> {
+
+ override fun build(multiFactory: MultiModelLoaderFactory) = HdImageLoading()
+
+ override fun teardown() = Unit
+}
+
+fun <T> RequestBuilder<T>.loadWithPotentialHd(model: HdImageMaybe) =
+ thumbnail(clone().load(model.url))
+ .load(model)
+ .apply(RequestOptions().override(Target.SIZE_ORIGINAL))
+
+class HdImageLoading : ModelLoader<HdImageMaybe, InputStream> {
+
+ override fun buildLoadData(model: HdImageMaybe,
+ width: Int,
+ height: Int,
+ options: Options?): ModelLoader.LoadData<InputStream>? =
+ if (!model.isValid) null
+ else ModelLoader.LoadData(ObjectKey(model), HdImageFetcher(model))
+
+ override fun handles(model: HdImageMaybe) = model.isValid
+}
+
+class HdImageFetcher(private val model: HdImageMaybe) : DataFetcher<InputStream> {
@Volatile private var cancelled: Boolean = false
private var urlCall: Call? = null
@@ -33,10 +89,12 @@ class ImageFbidFetcher(private val fbid: Long,
override fun getDataSource(): DataSource = DataSource.REMOTE
override fun loadData(priority: Priority, callback: DataFetcher.DataCallback<in InputStream>) {
- cookie.fbRequest(fail = { callback.fail("Invalid auth") }) {
+ if (!model.isValid) return callback.fail("Model is invalid")
+ model.cookie.fbRequest(fail = { callback.fail("Invalid auth") }) {
if (cancelled) return@fbRequest callback.fail("Cancelled")
- val url = getFullSizedImage(fbid).invoke() ?: return@fbRequest callback.fail("Null url")
+ val url = getFullSizedImage(model.id).invoke() ?: return@fbRequest callback.fail("Null url")
if (cancelled) return@fbRequest callback.fail("Cancelled")
+ if (!url.contains("png") && !url.contains("jpg")) return@fbRequest callback.fail("Invalid format")
urlCall = Request.Builder().url(url).get().call()
inputStream = try {
@@ -44,7 +102,6 @@ class ImageFbidFetcher(private val fbid: Long,
} catch (e: IOException) {
null
}
-
callback.onDataReady(inputStream)
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Messages.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Messages.kt
new file mode 100644
index 00000000..0e37a61e
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/requests/Messages.kt
@@ -0,0 +1,32 @@
+package com.pitchedapps.frost.facebook.requests
+
+import com.pitchedapps.frost.facebook.FB_URL_BASE
+import okhttp3.Call
+
+/**
+ * Created by Allan Wang on 07/01/18.
+ */
+fun RequestAuth.sendMessage(group: String, content: String): FrostRequest<Boolean> {
+
+ // todo test more; only tested against tids=cid...
+ val body = listOf(
+ "tids" to group,
+ "body" to content,
+ "fb_dtsg" to fb_dtsg,
+ "__user" to userId
+ ).withEmptyData("m_sess", "__dyn", "__req", "__ajax__")
+
+ return frostRequest(::validateMessage) {
+ url("${FB_URL_BASE}messages/send")
+ post(body.toForm())
+ }
+}
+
+/**
+ * Messages are a bit weird with their responses
+ */
+private fun validateMessage(call: Call): Boolean {
+ val body = call.execute().body() ?: return false
+ // todo
+ return true
+} \ No newline at end of file