/
Unfurler.kt
52 lines (46 loc) · 1.52 KB
/
Unfurler.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package me.saket.unfurl
import me.saket.unfurl.extension.HtmlTagsBasedUnfurler
import me.saket.unfurl.extension.UnfurlerExtension
import me.saket.unfurl.extension.UnfurlerScope
import me.saket.unfurl.internal.NullableLruCache
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
class Unfurler(
cacheSize: Int = 100,
extensions: List<UnfurlerExtension> = emptyList(),
val httpClient: OkHttpClient = defaultOkHttpClient(),
val logger: UnfurlLogger = UnfurlLogger.Println,
) {
private val extensions = extensions + HtmlTagsBasedUnfurler()
private val cache = NullableLruCache<String, UnfurlResult?>(cacheSize)
private val extensionScope = object : UnfurlerScope {
override val httpClient: OkHttpClient get() = this@Unfurler.httpClient
override val logger: UnfurlLogger get() = this@Unfurler.logger
}
fun unfurl(url: String): UnfurlResult? {
return cache.computeIfAbsent(url) {
try {
url.toHttpUrlOrNull()?.let { httpUrl ->
extensions.asSequence()
.mapNotNull { it.run { extensionScope.unfurl(httpUrl) } }
.firstOrNull()
}
} catch (e: Throwable) {
logger.log(e, "Failed to unfurl '$url'")
null
}
}
}
fun unfurl(url: HttpUrl): UnfurlResult? {
return unfurl(url.toString())
}
companion object {
internal fun defaultOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.followRedirects(true)
.followSslRedirects(true)
.build()
}
}
}