refactor: remove all Shiori code

Their API is Terrible, Horrible, No Good, Very Bad[1][2]

1: It's _fine_ but I want more
2: https://en.wikipedia.org/wiki/Alexander_and_the_Terrible,_Horrible,_No_Good,_Very_Bad_Day
This commit is contained in:
Harsh Shandilya 2023-12-03 21:52:38 +05:30
parent 1d5302f26c
commit 6084e5bb30
No known key found for this signature in database
13 changed files with 0 additions and 391 deletions

View file

@ -27,7 +27,6 @@ dependencies {
implementation(libs.jsoup)
testImplementation(testFixtures(libs.eithernet))
testImplementation(libs.testcontainers)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.kotlinx.serialization.json)
testImplementation(libs.retrofit.kotlinxSerializationConverter)

View file

@ -1,53 +0,0 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.api
import com.slack.eithernet.ApiResult
import dev.msfjarvis.claw.model.shiori.AuthRequest
import dev.msfjarvis.claw.model.shiori.AuthResponse
import dev.msfjarvis.claw.model.shiori.Bookmark
import dev.msfjarvis.claw.model.shiori.BookmarkRequest
import dev.msfjarvis.claw.model.shiori.BookmarksResponse
import dev.msfjarvis.claw.model.shiori.EditedBookmark
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.HTTP
import retrofit2.http.Header
import retrofit2.http.POST
import retrofit2.http.PUT
private const val SESSION_ID_HEADER = "X-Session-Id"
interface ShioriApi {
@POST("/api/login") suspend fun login(@Body body: AuthRequest): ApiResult<AuthResponse, Unit>
@HTTP(method = "POST", path = "/api/logout", hasBody = false)
suspend fun logout(@Header(SESSION_ID_HEADER) sessionId: String): ApiResult<Unit, Unit>
@GET("/api/bookmarks")
suspend fun getBookmarks(
@Header(SESSION_ID_HEADER) sessionId: String,
): ApiResult<BookmarksResponse, Unit>
@POST("/api/bookmarks")
suspend fun addBookmark(
@Header(SESSION_ID_HEADER) sessionId: String,
@Body bookmarkRequest: BookmarkRequest,
): ApiResult<Bookmark, Unit>
@PUT("/api/bookmarks")
suspend fun editBookmark(
@Header(SESSION_ID_HEADER) sessionId: String,
@Body bookmark: EditedBookmark,
): ApiResult<Bookmark, Unit>
@HTTP(method = "DELETE", path = "/api/bookmarks", hasBody = true)
suspend fun deleteBookmark(
@Header(SESSION_ID_HEADER) sessionId: String,
@Body ids: List<Int>,
): ApiResult<Int, Unit>
}

View file

@ -16,7 +16,6 @@ import dagger.multibindings.IntKey
import dagger.multibindings.IntoMap
import dev.msfjarvis.claw.api.LobstersApi
import dev.msfjarvis.claw.api.LobstersSearchApi
import dev.msfjarvis.claw.api.ShioriApi
import dev.msfjarvis.claw.api.converters.CSRFTokenConverter
import dev.msfjarvis.claw.api.converters.SearchConverter
import javax.inject.Named
@ -74,8 +73,6 @@ object RetrofitModule {
@Provides
fun provideSearchApi(@SearchApi retrofit: Retrofit): LobstersSearchApi = retrofit.create()
@Provides fun provideShioriApi(retrofit: Retrofit): ShioriApi = retrofit.create()
@Provides
@IntKey(0)
@IntoMap

View file

@ -1,173 +0,0 @@
/*
* Copyright © 2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.api
import com.google.common.truth.Truth.assertThat
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import com.slack.eithernet.ApiResultCallAdapterFactory
import com.slack.eithernet.ApiResultConverterFactory
import com.slack.eithernet.successOrNull
import dev.msfjarvis.claw.model.shiori.AuthRequest
import dev.msfjarvis.claw.model.shiori.AuthResponse
import dev.msfjarvis.claw.model.shiori.Bookmark
import dev.msfjarvis.claw.model.shiori.BookmarkRequest
import dev.msfjarvis.claw.model.shiori.BookmarksResponse
import dev.msfjarvis.claw.model.shiori.EditedBookmark
import dev.msfjarvis.claw.model.shiori.Tag
import dev.msfjarvis.claw.util.TestUtils.assertIs
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.Json
import okhttp3.MediaType
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.testcontainers.containers.GenericContainer
import retrofit2.Retrofit
import retrofit2.create
class ShioriApiTest {
private lateinit var credentials: AuthResponse
@BeforeEach
fun setUp() {
container.start()
runBlocking {
credentials =
requireNotNull(api.login(AuthRequest(USER, PASSWORD)).successOrNull()) { "Login failed" }
}
}
@AfterEach
fun tearDown() {
container.stop()
}
@Test
fun getBookmarks() = runTest {
val response = api.getBookmarks(credentials.session).successOrNull()
assertIs<BookmarksResponse>(response)
assertThat(response.page).isEqualTo(1)
assertThat(response.bookmarks).isEmpty()
}
@Test
fun addBookmark() = runTest {
val response =
api
.addBookmark(
credentials.session,
BookmarkRequest(
"https://example.com",
false,
0,
emptyList(),
"Example Domain",
"""
This domain is for use in illustrative examples in documents.
You may use this domain in literature without prior coordination or asking for permission.
"""
.trimIndent(),
)
)
.successOrNull()
assertIs<Bookmark>(response)
assertThat(response.url).isEqualTo("https://example.com")
assertThat(response.title).isEqualTo("Example Domain")
assertThat(response.excerpt)
.isEqualTo(
"""
This domain is for use in illustrative examples in documents.
You may use this domain in literature without prior coordination or asking for permission.
"""
.trimIndent()
)
assertThat(response.id).isAtLeast(0)
}
@Test
fun editBookmark() = runTest {
val response =
api
.addBookmark(
credentials.session,
BookmarkRequest(
"https://example.com",
false,
0,
emptyList(),
"Example Domain",
"""
This domain is for use in illustrative examples in documents.
You may use this domain in literature without prior coordination or asking for permission.
"""
.trimIndent(),
)
)
.successOrNull()
assertIs<Bookmark>(response)
assertThat(response.tags).isEmpty()
val newBookmark =
EditedBookmark(
id = response.id,
url = response.url,
title = response.title,
tags = listOf(Tag("examples")),
)
val edited = api.editBookmark(credentials.session, newBookmark).successOrNull()
assertIs<Bookmark>(edited)
assertThat(edited.tags).isNotEmpty()
assertThat(edited.tags).containsExactly(Tag("examples"))
}
@Test
fun deleteBookmark() = runTest {
val response =
api
.addBookmark(
credentials.session,
BookmarkRequest(
"https://example.com",
false,
0,
emptyList(),
"Example Domain",
"""
This domain is for use in illustrative examples in documents.
You may use this domain in literature without prior coordination or asking for permission.
"""
.trimIndent(),
)
)
.successOrNull()
assertIs<Bookmark>(response)
val count = api.deleteBookmark(credentials.session, listOf(response.id)).successOrNull()
assertThat(count).isEqualTo(1)
}
companion object {
// Default settings for the container
private const val USER = "shiori"
private const val PASSWORD = "gopher"
private val container =
GenericContainer("ghcr.io/go-shiori/shiori:v1.5.5").withExposedPorts(8080)
private val json = Json { ignoreUnknownKeys = true }
private val api
get() =
Retrofit.Builder()
.baseUrl("http://${container.host}:${container.firstMappedPort}")
.addConverterFactory(ApiResultConverterFactory)
.addConverterFactory(json.asConverterFactory(MediaType.get("application/json")))
.addCallAdapterFactory(ApiResultCallAdapterFactory)
.build()
.create<ShioriApi>()
}
}