aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/parsers/MessageParser.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/parsers/MessageParser.kt')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/parsers/MessageParser.kt85
1 files changed, 85 insertions, 0 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/parsers/MessageParser.kt b/app/src/main/kotlin/com/pitchedapps/frost/parsers/MessageParser.kt
new file mode 100644
index 00000000..dbe2c0bb
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/parsers/MessageParser.kt
@@ -0,0 +1,85 @@
+package com.pitchedapps.frost.parsers
+
+import com.pitchedapps.frost.facebook.formattedFbUrl
+import com.pitchedapps.frost.facebook.formattedFbUrlCss
+import com.pitchedapps.frost.utils.L
+import org.apache.commons.text.StringEscapeUtils
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Element
+
+/**
+ * Created by Allan Wang on 2017-10-06.
+ *
+ * In Facebook, messages are passed through scripts and loaded into view via react afterwards
+ * We can parse out the content we want directly and load it ourselves
+ *
+ */
+object MessageParser : FrostParser<Triple<List<FrostThread>, FrostLink?, List<FrostLink>>> by MessageParserImpl()
+
+data class FrostThread(val id: Int, val img: String, val title: String, val time: Long, val url: String, val unread: Boolean, val content: String?)
+
+data class FrostLink(val text: String, val href: String)
+
+private class MessageParserImpl : FrostParserBase<Triple<List<FrostThread>, FrostLink?, List<FrostLink>>>() {
+
+ override fun parseImpl(text: String): Triple<List<FrostThread>, FrostLink?, List<FrostLink>>? {
+ var content = StringEscapeUtils.unescapeEcmaScript(text)
+ val begin = content.indexOf("id=\"threadlist_rows\"")
+ if (begin <= 0) {
+ L.d("Threadlist not found")
+ return null
+ }
+ content = content.substring(begin)
+ val end = content.indexOf("</script>")
+ if (end <= 0) {
+ L.d("Script tail not found")
+ return null
+ }
+ content = content.substring(0, end).substringBeforeLast("</div>")
+ val body = Jsoup.parseBodyFragment("<div $content")
+ val threadList = body.getElementById("threadlist_rows")
+ val threads: List<FrostThread> = threadList.getElementsByAttributeValueContaining("id", "thread_fbid_")
+ .mapNotNull { parseMessage(it) }
+ val seeMore = parseLink(body.getElementById("see_older_threads"))
+ val extraLinks = threadList.nextElementSibling().select("a")
+ .mapNotNull { parseLink(it) }
+ return Triple(threads, seeMore, extraLinks)
+ }
+
+ private fun parseMessage(element: Element): FrostThread? {
+ val a = element.getElementsByTag("a").first() ?: return null
+ val abbr = element.getElementsByTag("abbr")
+ println(abbr.attr("data-store"))
+ val epoch = FrostRegex.epoch.find(abbr.attr("data-store"))
+ ?.groupValues?.getOrNull(1)?.toLongOrNull() ?: -1L
+ //fetch id
+ val id = FrostRegex.messageNotifId.find(element.id())
+ ?.groupValues?.getOrNull(1)?.toLongOrNull() ?: System.currentTimeMillis()
+ val content = element.select("span.snippet").firstOrNull()?.text()?.trim()
+ //fetch convo pic
+ val p = element.select("i.img[style*=url]")
+ val pUrl = FrostRegex.profilePicture.find(p.attr("style"))?.groups?.get(1)?.value?.formattedFbUrl ?: ""
+ L.v("url", a.attr("href"))
+ return FrostThread(
+ id = id.toInt(),
+ img = pUrl.formattedFbUrlCss,
+ title = a.text(),
+ time = epoch,
+ url = a.attr("href").formattedFbUrlCss,
+ unread = !element.hasClass("acw"),
+ content = content
+ )
+ }
+
+ private fun parseLink(element: Element?): FrostLink? {
+ val a = element?.getElementsByTag("a")?.first() ?: return null
+ return FrostLink(a.text(), a.attr("href"))
+ }
+
+ override fun debugImpl(data: Triple<List<FrostThread>, FrostLink?, List<FrostLink>>, result: MutableList<String>) {
+ result.addAll(data.first.map { it.toString() })
+ result.add("See more link:")
+ result.add("\t${data.second}")
+ result.addAll(data.third.map { it.toString() })
+ }
+}