mirror of https://github.com/readrops/Readrops.git
Guess RSS type by using konsume-xml instead of reading content by hand
This commit is contained in:
parent
1533f67de8
commit
655ab2bc83
|
@ -2,6 +2,7 @@ package com.readrops.api.localfeed
|
||||||
|
|
||||||
import android.accounts.NetworkErrorException
|
import android.accounts.NetworkErrorException
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
|
import com.gitlab.mvysny.konsumexml.konsumeXml
|
||||||
import com.readrops.api.localfeed.json.JSONFeedAdapter
|
import com.readrops.api.localfeed.json.JSONFeedAdapter
|
||||||
import com.readrops.api.localfeed.json.JSONItemsAdapter
|
import com.readrops.api.localfeed.json.JSONItemsAdapter
|
||||||
import com.readrops.api.utils.ApiUtils
|
import com.readrops.api.utils.ApiUtils
|
||||||
|
@ -49,10 +50,17 @@ class LocalRSSDataSource(private val httpClient: OkHttpClient): KoinComponent {
|
||||||
var type = LocalRSSHelper.getRSSType(contentType)
|
var type = LocalRSSHelper.getRSSType(contentType)
|
||||||
|
|
||||||
val bodyArray = response.peekBody(Long.MAX_VALUE).bytes()
|
val bodyArray = response.peekBody(Long.MAX_VALUE).bytes()
|
||||||
|
val konsumer = ByteArrayInputStream(bodyArray).konsumeXml()
|
||||||
|
|
||||||
// if we can't guess type based on content-type header, we use the content
|
// if we can't guess type based on content-type header, we use the content
|
||||||
if (type == LocalRSSHelper.RSSType.UNKNOWN)
|
if (type == LocalRSSHelper.RSSType.UNKNOWN) {
|
||||||
type = LocalRSSHelper.getRSSContentType(ByteArrayInputStream(bodyArray))
|
val rootKonsumer = konsumer.nextElement(LocalRSSHelper.RSS_ROOT_NAMES)
|
||||||
|
|
||||||
|
if (rootKonsumer != null) {
|
||||||
|
type = LocalRSSHelper.guessRSSType(rootKonsumer)
|
||||||
|
konsumer.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
// if we can't guess type even with the content, we are unable to go further
|
// if we can't guess type even with the content, we are unable to go further
|
||||||
if (type == LocalRSSHelper.RSSType.UNKNOWN) throw UnknownFormatException("Unable to guess $url RSS type")
|
if (type == LocalRSSHelper.RSSType.UNKNOWN) throw UnknownFormatException("Unable to guess $url RSS type")
|
||||||
|
|
||||||
|
@ -85,8 +93,15 @@ class LocalRSSDataSource(private val httpClient: OkHttpClient): KoinComponent {
|
||||||
|
|
||||||
var type = LocalRSSHelper.getRSSType(contentType)
|
var type = LocalRSSHelper.getRSSType(contentType)
|
||||||
|
|
||||||
if (type == LocalRSSHelper.RSSType.UNKNOWN)
|
if (type == LocalRSSHelper.RSSType.UNKNOWN) {
|
||||||
type = LocalRSSHelper.getRSSContentType(response.body?.byteStream()!!) // stream is closed in helper method
|
val konsumer = response.body!!.byteStream().konsumeXml().apply {
|
||||||
|
val rootKonsumer = nextElement(LocalRSSHelper.RSS_ROOT_NAMES)
|
||||||
|
|
||||||
|
rootKonsumer?.let { type = LocalRSSHelper.guessRSSType(rootKonsumer) }
|
||||||
|
}
|
||||||
|
|
||||||
|
konsumer.close()
|
||||||
|
}
|
||||||
|
|
||||||
type != LocalRSSHelper.RSSType.UNKNOWN
|
type != LocalRSSHelper.RSSType.UNKNOWN
|
||||||
} else false
|
} else false
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
package com.readrops.api.localfeed
|
package com.readrops.api.localfeed
|
||||||
|
|
||||||
|
import com.gitlab.mvysny.konsumexml.Konsumer
|
||||||
|
import com.gitlab.mvysny.konsumexml.Names
|
||||||
|
import com.readrops.api.utils.extensions.checkRoot
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
object LocalRSSHelper {
|
object LocalRSSHelper {
|
||||||
|
@ -14,6 +17,11 @@ object LocalRSSHelper {
|
||||||
private const val RSS_2_REGEX = "rss.*version=\"2.0\""
|
private const val RSS_2_REGEX = "rss.*version=\"2.0\""
|
||||||
private const val ATOM_REGEX = "<feed.* xmlns=\"http://www.w3.org/2005/Atom\""
|
private const val ATOM_REGEX = "<feed.* xmlns=\"http://www.w3.org/2005/Atom\""
|
||||||
|
|
||||||
|
const val RSS_1_ROOT_NAME = "rdf"
|
||||||
|
const val RSS_2_ROOT_NAME = "rss"
|
||||||
|
const val ATOM_ROOT_NAME = "feed"
|
||||||
|
val RSS_ROOT_NAMES = Names.of(RSS_1_ROOT_NAME, RSS_2_ROOT_NAME, ATOM_ROOT_NAME)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guess RSS type based on content-type header
|
* Guess RSS type based on content-type header
|
||||||
*/
|
*/
|
||||||
|
@ -56,6 +64,13 @@ object LocalRSSHelper {
|
||||||
return if (type != null) getRSSType(type) != RSSType.UNKNOWN else false
|
return if (type != null) getRSSType(type) != RSSType.UNKNOWN else false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun guessRSSType(konsumer: Konsumer): RSSType = when {
|
||||||
|
konsumer.checkRoot(RSS_1_ROOT_NAME) -> RSSType.RSS_1
|
||||||
|
konsumer.checkRoot(RSS_2_ROOT_NAME) -> RSSType.RSS_2
|
||||||
|
konsumer.checkRoot(ATOM_ROOT_NAME) -> RSSType.ATOM
|
||||||
|
else -> RSSType.UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
enum class RSSType {
|
enum class RSSType {
|
||||||
RSS_1,
|
RSS_1,
|
||||||
RSS_2,
|
RSS_2,
|
||||||
|
|
|
@ -19,3 +19,10 @@ fun Konsumer.nullableTextRecursively(): String? {
|
||||||
val text = textRecursively()
|
val text = textRecursively()
|
||||||
return if (text.isNotEmpty()) text.trim() else null
|
return if (text.isNotEmpty()) text.trim() else null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Konsumer.checkRoot(name: String): Boolean = try {
|
||||||
|
checkCurrent(name)
|
||||||
|
true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
false
|
||||||
|
}
|
Loading…
Reference in New Issue