aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/parsers
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/parsers')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/parsers/FrostParser.kt18
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/parsers/MessageParser.kt23
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/parsers/NotifParser.kt23
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/parsers/SearchParser.kt7
4 files changed, 47 insertions, 24 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/parsers/FrostParser.kt b/app/src/main/kotlin/com/pitchedapps/frost/parsers/FrostParser.kt
index 016f33e8..f0938eca 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/parsers/FrostParser.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/parsers/FrostParser.kt
@@ -9,6 +9,7 @@ import com.pitchedapps.frost.utils.frostJsoup
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
+import org.jsoup.select.Elements
/**
* Created by Allan Wang on 2017-10-06.
@@ -39,12 +40,19 @@ interface FrostParser<out T : Any> {
fun parse(cookie: String?, document: Document): ParseResponse<T>?
/**
+ * Call parsing using jsoup to fetch from given url
+ */
+ fun parseFromUrl(cookie: String?, url: String): ParseResponse<T>?
+
+ /**
* Call parsing with given data
*/
fun parseFromData(cookie: String?, text: String): ParseResponse<T>?
}
+const val FALLBACK_TIME_MOD = 1000000
+
data class FrostLink(val text: String, val href: String)
data class ParseResponse<out T>(val cookie: String, val data: T) {
@@ -68,7 +76,7 @@ internal fun <T> List<T>.toJsonString(tag: String, indent: Int) = StringBuilder(
*/
internal abstract class FrostParserBase<out T : Any>(private val redirectToText: Boolean) : FrostParser<T> {
- override final fun parse(cookie: String?) = parse(cookie, frostJsoup(cookie, url))
+ override final fun parse(cookie: String?) = parseFromUrl(cookie, url)
override final fun parseFromData(cookie: String?, text: String): ParseResponse<T>? {
cookie ?: return null
@@ -77,6 +85,9 @@ internal abstract class FrostParserBase<out T : Any>(private val redirectToText:
return ParseResponse(cookie, data)
}
+ override final fun parseFromUrl(cookie: String?, url: String): ParseResponse<T>? =
+ parse(cookie, frostJsoup(cookie, url))
+
override fun parse(cookie: String?, document: Document): ParseResponse<T>? {
cookie ?: return null
if (redirectToText)
@@ -94,7 +105,10 @@ internal abstract class FrostParserBase<out T : Any>(private val redirectToText:
* Returns the formatted url, or an empty string if nothing was found
*/
protected fun Element.getInnerImgStyle() =
- FB_CSS_URL_MATCHER.find(select("i.img[style*=url]").attr("style"))[1]?.formattedFbUrl ?: ""
+ select("i.img[style*=url]").getStyleUrl()
+
+ protected fun Elements.getStyleUrl() =
+ FB_CSS_URL_MATCHER.find(attr("style"))[1]?.formattedFbUrl
protected open fun textToDoc(text: String) = if (!redirectToText)
Jsoup.parse(text)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/parsers/MessageParser.kt b/app/src/main/kotlin/com/pitchedapps/frost/parsers/MessageParser.kt
index 9d4a2193..02c6f189 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/parsers/MessageParser.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/parsers/MessageParser.kt
@@ -16,7 +16,11 @@ import org.jsoup.nodes.Element
* We can parse out the content we want directly and load it ourselves
*
*/
-object MessageParser : FrostParser<FrostMessages> by MessageParserImpl()
+object MessageParser : FrostParser<FrostMessages> by MessageParserImpl() {
+
+ fun queryUser(cookie: String?, name: String) = parseFromUrl(cookie, "${FbItem.MESSAGES.url}/?q=$name")
+
+}
data class FrostMessages(val threads: List<FrostThread>,
val seeMore: FrostLink?,
@@ -35,7 +39,7 @@ data class FrostMessages(val threads: List<FrostThread>,
with(it) {
NotificationContent(
data = data,
- notifId = Math.abs(id.toInt()),
+ id = id,
href = url,
title = title,
text = content ?: "",
@@ -55,12 +59,13 @@ data class FrostMessages(val threads: List<FrostThread>,
* [content] optional string for thread
*/
data class FrostThread(val id: Long,
- val img: String,
+ val img: String?,
val title: String,
val time: Long,
val url: String,
val unread: Boolean,
- val content: String?)
+ val content: String?,
+ val contentImgUrl: String?)
private class MessageParserImpl : FrostParserBase<FrostMessages>(true) {
@@ -99,10 +104,11 @@ private class MessageParserImpl : FrostParserBase<FrostMessages>(true) {
val epoch = FB_EPOCH_MATCHER.find(abbr.attr("data-store"))[1]?.toLongOrNull() ?: -1L
//fetch id
val id = FB_MESSAGE_NOTIF_ID_MATCHER.find(element.id())[1]?.toLongOrNull()
- ?: System.currentTimeMillis()
- val content = element.select("span.snippet").firstOrNull()?.text()?.trim()
+ ?: System.currentTimeMillis() % FALLBACK_TIME_MOD
+ val snippet = element.select("span.snippet").firstOrNull()
+ val content = snippet?.text()?.trim()
+ val contentImg = snippet?.select("i[style*=url]")?.getStyleUrl()
val img = element.getInnerImgStyle()
- L.v("url", a.attr("href"))
return FrostThread(
id = id,
img = img,
@@ -110,7 +116,8 @@ private class MessageParserImpl : FrostParserBase<FrostMessages>(true) {
time = epoch,
url = a.attr("href").formattedFbUrl,
unread = !element.hasClass("acw"),
- content = content
+ content = content,
+ contentImgUrl = contentImg
)
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/parsers/NotifParser.kt b/app/src/main/kotlin/com/pitchedapps/frost/parsers/NotifParser.kt
index f743a43a..451eb774 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/parsers/NotifParser.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/parsers/NotifParser.kt
@@ -3,7 +3,6 @@ package com.pitchedapps.frost.parsers
import com.pitchedapps.frost.dbflow.CookieModel
import com.pitchedapps.frost.facebook.*
import com.pitchedapps.frost.services.NotificationContent
-import com.pitchedapps.frost.utils.L
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
@@ -29,10 +28,10 @@ data class FrostNotifs(
with(it) {
NotificationContent(
data = data,
- notifId = Math.abs(id.toInt()),
+ id = id,
href = url,
title = null,
- text = content ?: "",
+ text = content,
timestamp = time,
profileUrl = img
)
@@ -47,13 +46,17 @@ data class FrostNotifs(
* [url] link to thread
* [unread] true if image is unread, false otherwise
* [content] optional string for thread
+ * [timeString] text version of time from Facebook
+ * [thumbnailUrl] optional thumbnail url if existent
*/
data class FrostNotif(val id: Long,
- val img: String,
+ val img: String?,
val time: Long,
val url: String,
val unread: Boolean,
- val content: String?)
+ val content: String,
+ val timeString: String,
+ val thumbnailUrl: String?)
private class NotifParserImpl : FrostParserBase<FrostNotifs>(false) {
@@ -62,7 +65,7 @@ private class NotifParserImpl : FrostParserBase<FrostNotifs>(false) {
override fun parseImpl(doc: Document): FrostNotifs? {
val notificationList = doc.getElementById("notifications_list") ?: return null
val notifications = notificationList.getElementsByAttributeValueContaining("id", "list_notif_")
- .mapNotNull { parseNotif(it) }
+ .mapNotNull(this::parseNotif)
val seeMore = parseLink(doc.getElementsByAttributeValue("href", "/notifications.php?more").first())
return FrostNotifs(notifications, seeMore)
}
@@ -73,18 +76,20 @@ private class NotifParserImpl : FrostParserBase<FrostNotifs>(false) {
val epoch = FB_EPOCH_MATCHER.find(abbr.attr("data-store"))[1]?.toLongOrNull() ?: -1L
//fetch id
val id = FB_NOTIF_ID_MATCHER.find(element.id())[1]?.toLongOrNull()
- ?: System.currentTimeMillis()
+ ?: System.currentTimeMillis() % FALLBACK_TIME_MOD
val img = element.getInnerImgStyle()
val timeString = abbr.text()
val content = a.text().replace("\u00a0", " ").removeSuffix(timeString).trim() //remove &nbsp;
- L.v("url", a.attr("href"))
+ val thumbnail = element.selectFirst("img.thumbnail")?.attr("src")
return FrostNotif(
id = id,
img = img,
time = epoch,
url = a.attr("href").formattedFbUrl,
unread = !element.hasClass("acw"),
- content = content
+ content = content,
+ timeString = timeString,
+ thumbnailUrl = if (thumbnail?.isNotEmpty() == true) thumbnail else null
)
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/parsers/SearchParser.kt b/app/src/main/kotlin/com/pitchedapps/frost/parsers/SearchParser.kt
index bc09d4db..557e80b8 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/parsers/SearchParser.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/parsers/SearchParser.kt
@@ -1,13 +1,10 @@
package com.pitchedapps.frost.parsers
import ca.allanwang.kau.searchview.SearchItem
-import com.pitchedapps.frost.dbflow.CookieModel
import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.facebook.formattedFbUrl
import com.pitchedapps.frost.parsers.FrostSearch.Companion.create
import com.pitchedapps.frost.utils.L
-import com.pitchedapps.frost.utils.frostJsoup
-import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
@@ -18,7 +15,7 @@ object SearchParser : FrostParser<FrostSearches> by SearchParserImpl() {
fun query(cookie: String?, input: String): ParseResponse<FrostSearches>? {
val url = "${FbItem._SEARCH.url}?q=${if (input.isNotBlank()) input else "a"}"
L.i(null, "Search Query $url")
- return parse(cookie, frostJsoup(url))
+ return parseFromUrl(cookie, url)
}
}
@@ -27,7 +24,7 @@ enum class SearchKeys(val key: String) {
EVENTS("keywords_events")
}
-data class FrostSearches(val results: List<FrostSearch>) {
+data class FrostSearches(val results: List<FrostSearch>) {
override fun toString() = StringBuilder().apply {
append("FrostSearches {\n")