diff options
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/parsers')
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 - 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") |