Skip to content

Commit

Permalink
tinygrail
Browse files Browse the repository at this point in the history
  • Loading branch information
ekibun committed Feb 21, 2019
1 parent f149204 commit 228e830
Show file tree
Hide file tree
Showing 18 changed files with 320 additions and 139 deletions.
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@
<activity
android:name=".ui.setting.SettingsActivity"
android:label="@string/title_activity_settings"
android:parentActivityName=".ui.main.MainActivity"
android:theme="@style/AppTheme.ActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.main.MainActivity" />
</activity>
</application>

Expand Down
115 changes: 5 additions & 110 deletions app/src/main/java/soko/ekibun/bangumi/api/bangumi/Bangumi.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package soko.ekibun.bangumi.api.bangumi

import android.annotation.SuppressLint
import android.util.Log
import android.webkit.CookieManager
import okhttp3.FormBody
import org.jsoup.Jsoup
Expand All @@ -24,119 +23,14 @@ import kotlin.math.min

interface Bangumi {

@GET("/search/subject/{keywords}")
fun search(@Path("keywords") keywords: String,
@SubjectType.SubjectType @Query("type") type: Int = SubjectType.ALL,
@Query("start")start: Int = 0,
@Query("max_results")max_results: Int = 10,
@Header("cookie") cookie: String = "chii_searchDateLine=0"
): Call<SearchResult>

@GET("/subject/{id}")
fun subject(@Path("id") id: Int,
@ResponseGroup.ResponseGroup @Query("responseGroup") responseGroup: String = ResponseGroup.LARGE
): Call<Subject>

@GET("/subject/{id}/ep")
fun subjectEp(@Path("id") id: Int): Call<Subject>

@GET("/user/{username}")
fun user(@Path("username") id: String
): Call<UserInfo>

@GET("/user/{username}/collection")
fun collection(@Path("username") username: String,
@Query("cat") cat: String = "all_watching"
): Call<List<SubjectCollection>>

@GET("/collection/{subject_id}")
fun collectionStatus(@Path("subject_id") subject_id: Int,
@Query("access_token") access_token: String
): Call<Collection>

@GET("/ep/{id}/status/{status}")
fun updateProgress(@Path("id") id: Int,
@SubjectProgress.EpisodeProgress.EpisodeStatus.Companion.EpStatusType
@Path("status") status: String,
@Query("access_token") access_token: String
): Call<StatusCode>

@FormUrlEncoded
@POST("/subject/{subject_id}/update/watched_eps")
fun updateWatchEps(@Path("subject_id") subject_id: Int,
@Field("watched_eps") watched_eps: String,
@Query("access_token") access_token: String
): Call<StatusCode>

@FormUrlEncoded
@POST("/ep/{id}/status/{status}")
fun updateProgress(@Path("id") id: Int,
@SubjectProgress.EpisodeProgress.EpisodeStatus.Companion.EpStatusType
@Path("status") status: String,
@Query("access_token") access_token: String,
@Field("ep_id") epIds: String
): Call<StatusCode>

@GET("/user/{username}/progress")
fun progress(@Path("username") username: String,
@Query("subject_id") subject_id: Int,
@Query("access_token") access_token: String
): Call<SubjectProgress>

@FormUrlEncoded
@POST("/collection/{subject_id}/update")
fun updateCollectionStatus(@Path("subject_id") subject_id: Int,
@Field("access_token") access_token: String,
@Field("status") status: String,
@Field("tags") tags: String,
@Field("comment") comment: String?,
@Field("rating") rating: Int,
@Field("privacy") privacy: Int = 0
): Call<Collection>

@FormUrlEncoded
@POST("/oauth/access_token")
fun accessToken(@Field("code") code : String,
@Field("redirect_uri") redirect_uri: String = REDIRECT_URL,
@Field("grant_type") grant_type : String = "authorization_code",
@Field("client_id") client_id : String = APP_ID,
@Field("client_secret") client_secret : String = APP_SECRET
): Call<AccessToken>

@FormUrlEncoded
@POST("/oauth/access_token")
fun refreshToken(@Field("refresh_token") refresh_token : String,
@Field("redirect_uri") redirect_uri: String = REDIRECT_URL,
@Field("grant_type") grant_type : String = "refresh_token",
@Field("client_id") client_id : String = APP_ID,
@Field("client_secret") client_secret : String = APP_SECRET
): Call<AccessToken>

/*
@FormUrlEncoded
@POST("/oauth/token_status")
fun tokenStatus(@Field("access_token") access_token : String
): Call<AccessToken>
*/

@GET("/calendar")
fun calendar(): Call<List<Calendar>>

/*
@GET("/{subject_type}/list/{username}/{collection_status}")
fun getCollectionList(@SubjectType.SubjectTypeName @Path("subject_type")subject_type: String,
@Path("username") username: String,
@CollectionStatusType.CollectionStatusType @Path("collection_status") collection_status: String,
@Query("page")page: Int = 1
): Call<List<SubjectCollection>>
*/

companion object {
const val SERVER = "https://bgm.tv"
private const val SERVER_API = "https://api.bgm.tv"
const val APP_ID = "bgm2315af5554b7f887"
const val APP_SECRET = "adaf4941f83f2fb3c4336ee80a087f75"
const val REDIRECT_URL = "bangumi://redirect"
fun createInstance(): Bangumi{
return Retrofit.Builder().baseUrl(SERVER_API)
.addConverterFactory(GsonConverterFactory.create())
Expand Down Expand Up @@ -199,8 +93,9 @@ interface Bangumi {

val infobox = doc.select("#infobox li")?.map{
val tip = it.selectFirst("span.tip")?.text()?:""
Pair(tip.trim(':',' '),
it.text().substring(tip.length).trim())
var value = ""
it.childNodes()?.forEach { if(it !is Element || !it.hasClass("tip")) value += it.outerHtml() }
Pair(tip.trim(':',' '), value.trim())
}
var eps_count = infobox?.firstOrNull { it.first == "话数" }?.second?.toIntOrNull()?:subject.eps_count
//air-date
Expand Down Expand Up @@ -443,8 +338,8 @@ interface Bangumi {

fun browserAirTime(@SubjectType.SubjectTypeName subject_type: String,
year: Int, month: Int,
page: Int = 1, ua: String): Call<List<Subject>>{
return ApiHelper.buildHttpCall("$SERVER/$subject_type/browser/airtime/$year-$month?page=$page", mapOf("User-Agent" to ua)){
page: Int = 1, ua: String, sub_cat: String): Call<List<Subject>>{
return ApiHelper.buildHttpCall("$SERVER/$subject_type/browser${if(sub_cat.isEmpty())"" else "/$sub_cat"}/airtime/$year-$month?page=$page", mapOf("User-Agent" to ua)){
val doc = Jsoup.parse(it.body()?.string()?:"")
val ret = ArrayList<Subject>()
doc.select(".item")?.forEach{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ object SubjectType{
ANIME to NAME_ANIME,
MUSIC to NAME_MUSIC,
GAME to NAME_GAME,
REAL to NAME_REAL
REAL to NAME_REAL,
BOOK to NAME_BOOK
)

@SuppressLint("SwitchIntDef")
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/soko/ekibun/bangumi/api/tinygrail/Tinygrail.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,30 @@ package soko.ekibun.bangumi.api.tinygrail

import org.jsoup.Jsoup
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Path
import soko.ekibun.bangumi.api.ApiHelper
import soko.ekibun.bangumi.api.bangumi.Bangumi
import soko.ekibun.bangumi.api.bangumi.bean.Episode
import soko.ekibun.bangumi.api.bangumi.bean.Images
import soko.ekibun.bangumi.api.bangumi.bean.Subject
import soko.ekibun.bangumi.api.bangumi.bean.SubjectType
import soko.ekibun.bangumi.api.tinygrail.bean.OnAir
import soko.ekibun.bangumi.api.tinygrail.bean.OnAirInfo

interface Tinygrail{
@GET("/api/episode/subject/{id}")
fun onAirInfo(@Path("id") id: Int): Call<OnAirInfo>

companion object {
fun createInstance(): Tinygrail{
return Retrofit.Builder().baseUrl("https://www.tinygrail.com")
.addConverterFactory(GsonConverterFactory.create())
.build().create(Tinygrail::class.java)
}

fun onAirList(): Call<Map<Int, Map<String,List<OnAir>>>> {
return ApiHelper.buildHttpCall("https://www.tinygrail.com/api/onair/"){
val doc = Jsoup.parse(it.body()?.string()?:"")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package soko.ekibun.bangumi.api.tinygrail.bean

data class OnAirInfo(
val State: Int = 0,
val Value: List<EpisodeOnAirInfo>? = null
){
data class EpisodeOnAirInfo(
val EpisodeId: Int = 0,
val Id: Int = 0,
val Link: String = "",
val Name: String = "",
val Site: String = ""
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ class SubjectTypeView(view: TextView, onChange:()->Unit){
}

init{
view.text = SubjectType.getDescription(typeList[selectedType]?.first?:0)
val popup = PopupMenu(view.context, view)
popup.menuInflater.inflate(R.menu.list_collection_type, popup.menu)
view.text = popup.menu.findItem(selectedType)?.title
view.setOnClickListener {
val popup = PopupMenu(view.context, view)
popup.menuInflater.inflate(R.menu.list_collection_type, popup.menu)
popup.setOnMenuItemClickListener{
selectedType = it.itemId
view.text = it.title
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ class TimeLineFragment: HomeTabFragment(R.layout.fragment_timeline){
val adapter = TimeLinePagerAdapter(view.context, this, item_pager)
item_pager?.adapter = adapter
item_tabs?.setupWithViewPager(item_pager)
item_type?.text = "好友"
val popup = PopupMenu(view.context, item_type)
popup.menuInflater.inflate(R.menu.list_timeline, popup.menu)
item_type?.text = popup.menu.findItem(adapter.selectedType)?.title
item_type?.setOnClickListener {
val popup = PopupMenu(view.context, item_type)
popup.menuInflater.inflate(R.menu.list_timeline, popup.menu)
popup.menu.findItem(R.id.timeline_type_self)?.isVisible = ((activity as? MainActivity)?.user?.username?:"").isNotEmpty()
popup.setOnMenuItemClickListener{
item_type?.text = it.title
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ import soko.ekibun.bangumi.api.ApiHelper
import soko.ekibun.bangumi.api.bangumi.Bangumi
import soko.ekibun.bangumi.api.bangumi.bean.Subject
import soko.ekibun.bangumi.ui.main.MainActivity
import soko.ekibun.bangumi.ui.main.fragment.home.fragment.collection.SubjectTypeView
import soko.ekibun.bangumi.ui.subject.SubjectActivity
import java.util.*

class IndexPagerAdapter(private val fragment: IndexFragment, private val pager: ViewPager): RecyclePagerAdapter<IndexPagerAdapter.IndexPagerViewHolder>() {
private val subjectTypeView = SubjectTypeView(fragment.item_type) {
private val indexTypeView = IndexTypeView(fragment.item_type) {
pageIndex.clear()
pager.adapter?.notifyDataSetChanged()
}
Expand All @@ -32,6 +31,8 @@ class IndexPagerAdapter(private val fragment: IndexFragment, private val pager:
private val pageIndex = SparseIntArray()
private var indexCalls = WeakHashMap<Int, Call<List<Subject>>>()
private fun loadIndex(item: IndexPagerViewHolder){
val indexType = IndexTypeView.typeList[indexTypeView.selectedType]?:return

val position = item.position
val year = position/12 + 1000
val month = position % 12 + 1
Expand All @@ -41,7 +42,7 @@ class IndexPagerAdapter(private val fragment: IndexFragment, private val pager:
item.adapter.setNewData(null)
item.view.isRefreshing = true
}
indexCalls[position] = Bangumi.browserAirTime(subjectTypeView.getTypeName(), year, month, page + 1, (fragment.activity as? MainActivity)?.ua?:"")
indexCalls[position] = Bangumi.browserAirTime(indexType.first, year, month, page + 1, (fragment.activity as? MainActivity)?.ua?:"", indexType.second)
item.adapter.isUseEmpty(false)
indexCalls[position]?.enqueue(ApiHelper.buildCallback(item.view.context, {
item.adapter.isUseEmpty(true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package soko.ekibun.bangumi.ui.main.fragment.index

import android.support.v7.widget.PopupMenu
import android.widget.TextView
import soko.ekibun.bangumi.R
import soko.ekibun.bangumi.api.bangumi.bean.SubjectType

class IndexTypeView(view: TextView, onChange:()->Unit){
companion object {
val typeList = mapOf(
R.id.collection_type_anime_all to Pair(SubjectType.NAME_ANIME, ""),
R.id.collection_type_anime_tv to Pair(SubjectType.NAME_ANIME, "tv"),
R.id.collection_type_anime_web to Pair(SubjectType.NAME_ANIME, "web"),
R.id.collection_type_anime_ova to Pair(SubjectType.NAME_ANIME, "ova"),
R.id.collection_type_anime_movie to Pair(SubjectType.NAME_ANIME, "movie"),
R.id.collection_type_anime_misc to Pair(SubjectType.NAME_ANIME, "misc"),
R.id.collection_type_book_all to Pair(SubjectType.NAME_BOOK, ""),
R.id.collection_type_book_comic to Pair(SubjectType.NAME_BOOK, "comic"),
R.id.collection_type_book_novel to Pair(SubjectType.NAME_BOOK, "novel"),
R.id.collection_type_book_illustration to Pair(SubjectType.NAME_BOOK, "illustration"),
R.id.collection_type_book_misc to Pair(SubjectType.NAME_BOOK, "misc"),
R.id.collection_type_game_all to Pair(SubjectType.NAME_GAME, ""),
R.id.collection_type_game_pc to Pair(SubjectType.NAME_GAME, "pc"),
R.id.collection_type_game_mac to Pair(SubjectType.NAME_GAME, "mac"),
R.id.collection_type_game_ps4 to Pair(SubjectType.NAME_GAME, "ps4"),
R.id.collection_type_game_xbox_one to Pair(SubjectType.NAME_GAME, "xbox_one"),
R.id.collection_type_game_ns to Pair(SubjectType.NAME_GAME, "ns"),
R.id.collection_type_game_wii_u to Pair(SubjectType.NAME_GAME, "wii_u"),
R.id.collection_type_game_ps3 to Pair(SubjectType.NAME_GAME, "ps3"),
R.id.collection_type_game_xbox360 to Pair(SubjectType.NAME_GAME, "xbox360"),
R.id.collection_type_game_wii to Pair(SubjectType.NAME_GAME, "wii"),
R.id.collection_type_game_psv to Pair(SubjectType.NAME_GAME, "psv"),
R.id.collection_type_game_3ds to Pair(SubjectType.NAME_GAME, "3ds"),
R.id.collection_type_game_iphone to Pair(SubjectType.NAME_GAME, "iphone"),
R.id.collection_type_game_android to Pair(SubjectType.NAME_GAME, "android"),
R.id.collection_type_game_arc to Pair(SubjectType.NAME_GAME, "arc"),
R.id.collection_type_game_nds to Pair(SubjectType.NAME_GAME, "nds"),
R.id.collection_type_game_psp to Pair(SubjectType.NAME_GAME, "psp"),
R.id.collection_type_game_ps2 to Pair(SubjectType.NAME_GAME, "ps2"),
R.id.collection_type_game_xbox to Pair(SubjectType.NAME_GAME, "xbox"),
R.id.collection_type_game_gamecube to Pair(SubjectType.NAME_GAME, "gamecube"),
R.id.collection_type_game_dreamcast to Pair(SubjectType.NAME_GAME, "dreamcast"),
R.id.collection_type_game_n64 to Pair(SubjectType.NAME_GAME, "n64"),
R.id.collection_type_game_ps to Pair(SubjectType.NAME_GAME, "ps"),
R.id.collection_type_game_sfc to Pair(SubjectType.NAME_GAME, "sfc"),
R.id.collection_type_game_fc to Pair(SubjectType.NAME_GAME, "fc"),
R.id.collection_type_game_ws to Pair(SubjectType.NAME_GAME, "ws"),
R.id.collection_type_game_wsc to Pair(SubjectType.NAME_GAME, "wsc"),
R.id.collection_type_game_ngp to Pair(SubjectType.NAME_GAME, "ngp"),
R.id.collection_type_game_GBA to Pair(SubjectType.NAME_GAME, "GBA"),
R.id.collection_type_game_vb to Pair(SubjectType.NAME_GAME, "vb"),
R.id.collection_type_music to Pair(SubjectType.NAME_MUSIC, ""),
R.id.collection_type_real_all to Pair(SubjectType.NAME_REAL, ""),
R.id.collection_type_real_jp to Pair(SubjectType.NAME_REAL, "jp"),
R.id.collection_type_real_en to Pair(SubjectType.NAME_REAL, "en"),
R.id.collection_type_real_cn to Pair(SubjectType.NAME_REAL, "cn"))
}
var selectedType = R.id.collection_type_anime_all

init{
val popup = PopupMenu(view.context, view)
popup.menuInflater.inflate(R.menu.list_browser_type, popup.menu)
view.text = popup.menu.findItem(selectedType)?.title?.toString()?.replace("全部", "")
view.setOnClickListener {
popup.setOnMenuItemClickListener{
if(typeList.containsKey(it.itemId)){
selectedType = it.itemId
view.text = it.title.toString().replace("全部", "")
onChange()
}
true
}
popup.show()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,11 @@ class SearchTypeView(view: TextView, onChange:()->Unit){
var selectedType = R.id.collection_type_all

init{
view.text = mapOf(R.id.collection_type_mono to "人物",
R.id.collection_type_ctr to "虚构角色",
R.id.collection_type_psn to "现实人物")[selectedType]?:SubjectType.getDescription(subjectTypeList[selectedType]?:0)

val context = ContextThemeWrapper(view.context, R.style.AppTheme_PopupOverlay)
val popup = PopupMenu(context, view)
popup.menuInflater.inflate(R.menu.list_search_type, popup.menu)
view.text = popup.menu.findItem(selectedType)?.title
view.setOnClickListener {
val context = ContextThemeWrapper(view.context, R.style.AppTheme_PopupOverlay)
val popup = PopupMenu(context, view)
popup.menuInflater.inflate(R.menu.list_search_type, popup.menu)
popup.setOnMenuItemClickListener{
selectedType = it.itemId
view.text = it.title
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class SubjectActivity : SwipeBackActivity() {
title=""

subjectPresenter.init(JsonUtil.toEntity(intent.getStringExtra(SubjectActivity.EXTRA_SUBJECT)?:"", Subject::class.java)?: {
val id = Regex("""/subject/([0-9]+)""").find(intent.data!!.toString())!!.groupValues[1].toInt()
val id = Regex("""/subject/([0-9]+)""").find(intent.data?.toString()?:"")?.groupValues?.get(1)?.toIntOrNull()?:0
Subject(id, "${Bangumi.SERVER}/subject/$id")
}())
}
Expand Down
Loading

0 comments on commit 228e830

Please sign in to comment.