|
@@ -21,191 +21,191 @@ import java.net.URLEncoder
|
|
|
|
|
|
class BangumiApi(private val client: OkHttpClient, interceptor: BangumiInterceptor) {
|
|
|
|
|
|
- private val gson: Gson by injectLazy()
|
|
|
- private val parser = JsonParser()
|
|
|
- private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
|
|
-
|
|
|
- fun addLibManga(track: Track): Observable<Track> {
|
|
|
- val body = FormBody.Builder()
|
|
|
- .add("rating", track.score.toInt().toString())
|
|
|
- .add("status", track.toBangumiStatus())
|
|
|
- .build()
|
|
|
- val request = Request.Builder()
|
|
|
- .url("$apiUrl/collection/${track.media_id}/update")
|
|
|
- .post(body)
|
|
|
- .build()
|
|
|
- return authClient.newCall(request)
|
|
|
- .asObservableSuccess()
|
|
|
- .map {
|
|
|
- track
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- fun updateLibManga(track: Track): Observable<Track> {
|
|
|
- // chapter update
|
|
|
- val body = FormBody.Builder()
|
|
|
- .add("watched_eps", track.last_chapter_read.toString())
|
|
|
- .build()
|
|
|
- val request = Request.Builder()
|
|
|
- .url("$apiUrl/subject/${track.media_id}/update/watched_eps")
|
|
|
- .post(body)
|
|
|
- .build()
|
|
|
-
|
|
|
- // read status update
|
|
|
- val sbody = FormBody.Builder()
|
|
|
- .add("status", track.toBangumiStatus())
|
|
|
- .build()
|
|
|
- val srequest = Request.Builder()
|
|
|
- .url("$apiUrl/collection/${track.media_id}/update")
|
|
|
- .post(sbody)
|
|
|
- .build()
|
|
|
- return authClient.newCall(srequest)
|
|
|
- .asObservableSuccess()
|
|
|
- .map {
|
|
|
- track
|
|
|
- }.flatMap {
|
|
|
- authClient.newCall(request)
|
|
|
- .asObservableSuccess()
|
|
|
- .map {
|
|
|
- track
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- fun search(search: String): Observable<List<TrackSearch>> {
|
|
|
- val url = Uri.parse(
|
|
|
- "$apiUrl/search/subject/${URLEncoder.encode(search, Charsets.UTF_8.name())}").buildUpon()
|
|
|
- .appendQueryParameter("max_results", "20")
|
|
|
- .build()
|
|
|
- val request = Request.Builder()
|
|
|
- .url(url.toString())
|
|
|
- .get()
|
|
|
- .build()
|
|
|
- return authClient.newCall(request)
|
|
|
- .asObservableSuccess()
|
|
|
- .map { netResponse ->
|
|
|
- var responseBody = netResponse.body?.string().orEmpty()
|
|
|
- if (responseBody.isEmpty()) {
|
|
|
- throw Exception("Null Response")
|
|
|
+ private val gson: Gson by injectLazy()
|
|
|
+ private val parser = JsonParser()
|
|
|
+ private val authClient = client.newBuilder().addInterceptor(interceptor).build()
|
|
|
+
|
|
|
+ fun addLibManga(track: Track): Observable<Track> {
|
|
|
+ val body = FormBody.Builder()
|
|
|
+ .add("rating", track.score.toInt().toString())
|
|
|
+ .add("status", track.toBangumiStatus())
|
|
|
+ .build()
|
|
|
+ val request = Request.Builder()
|
|
|
+ .url("$apiUrl/collection/${track.media_id}/update")
|
|
|
+ .post(body)
|
|
|
+ .build()
|
|
|
+ return authClient.newCall(request)
|
|
|
+ .asObservableSuccess()
|
|
|
+ .map {
|
|
|
+ track
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fun updateLibManga(track: Track): Observable<Track> {
|
|
|
+ // chapter update
|
|
|
+ val body = FormBody.Builder()
|
|
|
+ .add("watched_eps", track.last_chapter_read.toString())
|
|
|
+ .build()
|
|
|
+ val request = Request.Builder()
|
|
|
+ .url("$apiUrl/subject/${track.media_id}/update/watched_eps")
|
|
|
+ .post(body)
|
|
|
+ .build()
|
|
|
+
|
|
|
+ // read status update
|
|
|
+ val sbody = FormBody.Builder()
|
|
|
+ .add("status", track.toBangumiStatus())
|
|
|
+ .build()
|
|
|
+ val srequest = Request.Builder()
|
|
|
+ .url("$apiUrl/collection/${track.media_id}/update")
|
|
|
+ .post(sbody)
|
|
|
+ .build()
|
|
|
+ return authClient.newCall(srequest)
|
|
|
+ .asObservableSuccess()
|
|
|
+ .map {
|
|
|
+ track
|
|
|
+ }.flatMap {
|
|
|
+ authClient.newCall(request)
|
|
|
+ .asObservableSuccess()
|
|
|
+ .map {
|
|
|
+ track
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fun search(search: String): Observable<List<TrackSearch>> {
|
|
|
+ val url = Uri.parse(
|
|
|
+ "$apiUrl/search/subject/${URLEncoder.encode(search, Charsets.UTF_8.name())}").buildUpon()
|
|
|
+ .appendQueryParameter("max_results", "20")
|
|
|
+ .build()
|
|
|
+ val request = Request.Builder()
|
|
|
+ .url(url.toString())
|
|
|
+ .get()
|
|
|
+ .build()
|
|
|
+ return authClient.newCall(request)
|
|
|
+ .asObservableSuccess()
|
|
|
+ .map { netResponse ->
|
|
|
+ var responseBody = netResponse.body?.string().orEmpty()
|
|
|
+ if (responseBody.isEmpty()) {
|
|
|
+ throw Exception("Null Response")
|
|
|
+ }
|
|
|
+ if (responseBody.contains("\"code\":404")) {
|
|
|
+ responseBody = "{\"results\":0,\"list\":[]}"
|
|
|
+ }
|
|
|
+ val response = parser.parse(responseBody).obj["list"]?.array
|
|
|
+ response?.filter { it.obj["type"].asInt == 1 }?.map { jsonToSearch(it.obj) }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun jsonToSearch(obj: JsonObject): TrackSearch {
|
|
|
+ return TrackSearch.create(TrackManager.BANGUMI).apply {
|
|
|
+ media_id = obj["id"].asInt
|
|
|
+ title = obj["name_cn"].asString
|
|
|
+ cover_url = obj["images"].obj["common"].asString
|
|
|
+ summary = obj["name"].asString
|
|
|
+ tracking_url = obj["url"].asString
|
|
|
}
|
|
|
- if(responseBody.contains("\"code\":404")){
|
|
|
- responseBody = "{\"results\":0,\"list\":[]}"
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun jsonToTrack(mangas: JsonObject): Track {
|
|
|
+ return Track.create(TrackManager.BANGUMI).apply {
|
|
|
+ title = mangas["name"].asString
|
|
|
+ media_id = mangas["id"].asInt
|
|
|
+ score = if (mangas["rating"] != null)
|
|
|
+ (if (mangas["rating"].isJsonObject) mangas["rating"].obj["score"].asFloat else 0f)
|
|
|
+ else 0f
|
|
|
+ status = Bangumi.DEFAULT_STATUS
|
|
|
+ tracking_url = mangas["url"].asString
|
|
|
}
|
|
|
- val response = parser.parse(responseBody).obj["list"]?.array
|
|
|
- response?.filter { it.obj["type"].asInt == 1 }?.map { jsonToSearch(it.obj) }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- private fun jsonToSearch(obj: JsonObject): TrackSearch {
|
|
|
- return TrackSearch.create(TrackManager.BANGUMI).apply {
|
|
|
- media_id = obj["id"].asInt
|
|
|
- title = obj["name_cn"].asString
|
|
|
- cover_url = obj["images"].obj["common"].asString
|
|
|
- summary = obj["name"].asString
|
|
|
- tracking_url = obj["url"].asString
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- private fun jsonToTrack(mangas: JsonObject): Track {
|
|
|
- return Track.create(TrackManager.BANGUMI).apply {
|
|
|
- title = mangas["name"].asString
|
|
|
- media_id = mangas["id"].asInt
|
|
|
- score = if (mangas["rating"] != null)
|
|
|
- (if (mangas["rating"].isJsonObject) mangas["rating"].obj["score"].asFloat else 0f)
|
|
|
- else 0f
|
|
|
- status = Bangumi.DEFAULT_STATUS
|
|
|
- tracking_url = mangas["url"].asString
|
|
|
+
|
|
|
+ fun findLibManga(track: Track): Observable<Track?> {
|
|
|
+ val urlMangas = "$apiUrl/subject/${track.media_id}"
|
|
|
+ val requestMangas = Request.Builder()
|
|
|
+ .url(urlMangas)
|
|
|
+ .get()
|
|
|
+ .build()
|
|
|
+
|
|
|
+ return authClient.newCall(requestMangas)
|
|
|
+ .asObservableSuccess()
|
|
|
+ .map { netResponse ->
|
|
|
+ // get comic info
|
|
|
+ val responseBody = netResponse.body?.string().orEmpty()
|
|
|
+ jsonToTrack(parser.parse(responseBody).obj)
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- fun findLibManga(track: Track): Observable<Track?> {
|
|
|
- val urlMangas = "$apiUrl/subject/${track.media_id}"
|
|
|
- val requestMangas = Request.Builder()
|
|
|
- .url(urlMangas)
|
|
|
- .get()
|
|
|
- .build()
|
|
|
-
|
|
|
- return authClient.newCall(requestMangas)
|
|
|
- .asObservableSuccess()
|
|
|
- .map { netResponse ->
|
|
|
- // get comic info
|
|
|
- val responseBody = netResponse.body?.string().orEmpty()
|
|
|
- jsonToTrack(parser.parse(responseBody).obj)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- fun statusLibManga(track: Track): Observable<Track?> {
|
|
|
- val urlUserRead = "$apiUrl/collection/${track.media_id}"
|
|
|
- val requestUserRead = Request.Builder()
|
|
|
- .url(urlUserRead)
|
|
|
- .cacheControl(CacheControl.FORCE_NETWORK)
|
|
|
- .get()
|
|
|
- .build()
|
|
|
-
|
|
|
- // todo get user readed chapter here
|
|
|
- return authClient.newCall(requestUserRead)
|
|
|
- .asObservableSuccess()
|
|
|
- .map { netResponse ->
|
|
|
- val resp = netResponse.body?.string()
|
|
|
- val coll = gson.fromJson(resp, Collection::class.java)
|
|
|
- track.status = coll.status?.id!!
|
|
|
- track.last_chapter_read = coll.ep_status!!
|
|
|
- track
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- fun accessToken(code: String): Observable<OAuth> {
|
|
|
- return client.newCall(accessTokenRequest(code)).asObservableSuccess().map { netResponse ->
|
|
|
- val responseBody = netResponse.body?.string().orEmpty()
|
|
|
- if (responseBody.isEmpty()) {
|
|
|
- throw Exception("Null Response")
|
|
|
- }
|
|
|
- gson.fromJson(responseBody, OAuth::class.java)
|
|
|
+
|
|
|
+ fun statusLibManga(track: Track): Observable<Track?> {
|
|
|
+ val urlUserRead = "$apiUrl/collection/${track.media_id}"
|
|
|
+ val requestUserRead = Request.Builder()
|
|
|
+ .url(urlUserRead)
|
|
|
+ .cacheControl(CacheControl.FORCE_NETWORK)
|
|
|
+ .get()
|
|
|
+ .build()
|
|
|
+
|
|
|
+ // todo get user readed chapter here
|
|
|
+ return authClient.newCall(requestUserRead)
|
|
|
+ .asObservableSuccess()
|
|
|
+ .map { netResponse ->
|
|
|
+ val resp = netResponse.body?.string()
|
|
|
+ val coll = gson.fromJson(resp, Collection::class.java)
|
|
|
+ track.status = coll.status?.id!!
|
|
|
+ track.last_chapter_read = coll.ep_status!!
|
|
|
+ track
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- private fun accessTokenRequest(code: String) = POST(oauthUrl,
|
|
|
- body = FormBody.Builder()
|
|
|
- .add("grant_type", "authorization_code")
|
|
|
- .add("client_id", clientId)
|
|
|
- .add("client_secret", clientSecret)
|
|
|
- .add("code", code)
|
|
|
- .add("redirect_uri", redirectUrl)
|
|
|
- .build()
|
|
|
- )
|
|
|
-
|
|
|
- companion object {
|
|
|
- private const val clientId = "bgm10555cda0762e80ca"
|
|
|
- private const val clientSecret = "8fff394a8627b4c388cbf349ec865775"
|
|
|
-
|
|
|
- private const val baseUrl = "https://bangumi.org"
|
|
|
- private const val apiUrl = "https://api.bgm.tv"
|
|
|
- private const val oauthUrl = "https://bgm.tv/oauth/access_token"
|
|
|
- private const val loginUrl = "https://bgm.tv/oauth/authorize"
|
|
|
-
|
|
|
- private const val redirectUrl = "tachiyomi://bangumi-auth"
|
|
|
- private const val baseMangaUrl = "$apiUrl/mangas"
|
|
|
-
|
|
|
- fun mangaUrl(remoteId: Int): String {
|
|
|
- return "$baseMangaUrl/$remoteId"
|
|
|
+
|
|
|
+ fun accessToken(code: String): Observable<OAuth> {
|
|
|
+ return client.newCall(accessTokenRequest(code)).asObservableSuccess().map { netResponse ->
|
|
|
+ val responseBody = netResponse.body?.string().orEmpty()
|
|
|
+ if (responseBody.isEmpty()) {
|
|
|
+ throw Exception("Null Response")
|
|
|
+ }
|
|
|
+ gson.fromJson(responseBody, OAuth::class.java)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- fun authUrl() =
|
|
|
- Uri.parse(loginUrl).buildUpon()
|
|
|
- .appendQueryParameter("client_id", clientId)
|
|
|
- .appendQueryParameter("response_type", "code")
|
|
|
- .appendQueryParameter("redirect_uri", redirectUrl)
|
|
|
- .build()
|
|
|
-
|
|
|
- fun refreshTokenRequest(token: String) = POST(oauthUrl,
|
|
|
- body = FormBody.Builder()
|
|
|
- .add("grant_type", "refresh_token")
|
|
|
- .add("client_id", clientId)
|
|
|
- .add("client_secret", clientSecret)
|
|
|
- .add("refresh_token", token)
|
|
|
- .add("redirect_uri", redirectUrl)
|
|
|
- .build())
|
|
|
- }
|
|
|
+ private fun accessTokenRequest(code: String) = POST(oauthUrl,
|
|
|
+ body = FormBody.Builder()
|
|
|
+ .add("grant_type", "authorization_code")
|
|
|
+ .add("client_id", clientId)
|
|
|
+ .add("client_secret", clientSecret)
|
|
|
+ .add("code", code)
|
|
|
+ .add("redirect_uri", redirectUrl)
|
|
|
+ .build()
|
|
|
+ )
|
|
|
+
|
|
|
+ companion object {
|
|
|
+ private const val clientId = "bgm10555cda0762e80ca"
|
|
|
+ private const val clientSecret = "8fff394a8627b4c388cbf349ec865775"
|
|
|
+
|
|
|
+ private const val baseUrl = "https://bangumi.org"
|
|
|
+ private const val apiUrl = "https://api.bgm.tv"
|
|
|
+ private const val oauthUrl = "https://bgm.tv/oauth/access_token"
|
|
|
+ private const val loginUrl = "https://bgm.tv/oauth/authorize"
|
|
|
+
|
|
|
+ private const val redirectUrl = "tachiyomi://bangumi-auth"
|
|
|
+ private const val baseMangaUrl = "$apiUrl/mangas"
|
|
|
+
|
|
|
+ fun mangaUrl(remoteId: Int): String {
|
|
|
+ return "$baseMangaUrl/$remoteId"
|
|
|
+ }
|
|
|
+
|
|
|
+ fun authUrl() =
|
|
|
+ Uri.parse(loginUrl).buildUpon()
|
|
|
+ .appendQueryParameter("client_id", clientId)
|
|
|
+ .appendQueryParameter("response_type", "code")
|
|
|
+ .appendQueryParameter("redirect_uri", redirectUrl)
|
|
|
+ .build()
|
|
|
+
|
|
|
+ fun refreshTokenRequest(token: String) = POST(oauthUrl,
|
|
|
+ body = FormBody.Builder()
|
|
|
+ .add("grant_type", "refresh_token")
|
|
|
+ .add("client_id", clientId)
|
|
|
+ .add("client_secret", clientSecret)
|
|
|
+ .add("refresh_token", token)
|
|
|
+ .add("redirect_uri", redirectUrl)
|
|
|
+ .build())
|
|
|
+ }
|
|
|
|
|
|
}
|