feat: 新版收藏 & 点赞 API

This commit is contained in:
HuanCheng65 2023-07-13 18:32:10 +08:00
parent 6983063838
commit 9be00b177a
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
10 changed files with 242 additions and 63 deletions

View File

@ -90,6 +90,46 @@ fun ThreadInfo.updateAgreeStatus(
) )
} }
fun ThreadInfo.updateCollectStatus(
newStatus: Int,
markPostId: Long
) = if (collectStatus != newStatus) {
this.copy(
collectStatus = newStatus,
collectMarkPid = markPostId.toString()
)
} else {
this
}
fun Post.updateAgreeStatus(
hasAgree: Int
) = if (agree != null) {
if (hasAgree != agree.hasAgree) {
if (hasAgree == 1) {
copy(
agree = agree.copy(
agreeNum = agree.agreeNum + 1,
diffAgreeNum = agree.diffAgreeNum + 1,
hasAgree = 1
)
)
} else {
copy(
agree = agree.copy(
agreeNum = agree.agreeNum - 1,
diffAgreeNum = agree.diffAgreeNum - 1,
hasAgree = 0
)
)
}
} else {
this
}
} else {
this
}
private val PbContent.picUrl: String private val PbContent.picUrl: String
get() = get() =
ImageUtil.getUrl( ImageUtil.getUrl(
@ -123,12 +163,7 @@ val List<PbContent>.renders: List<PbContentRender>
forEach { forEach {
when (it.type) { when (it.type) {
0, 9, 27 -> { 0, 9, 27 -> {
val lastRender = renders.lastOrNull() renders.appendText(it.text)
if (lastRender is TextContentRender) {
renders.removeLast()
renders.add(lastRender + it.text)
} else
renders.add(TextContentRender(it.text))
} }
1 -> { 1 -> {
@ -149,12 +184,7 @@ val List<PbContent>.renders: List<PbContentRender>
} }
} }
} }
val lastRender = renders.lastOrNull() renders.appendText(text)
if (lastRender is TextContentRender) {
renders.removeLast()
renders.add(lastRender + text)
} else
renders.add(TextContentRender(text))
} }
2 -> { 2 -> {
@ -163,12 +193,7 @@ val List<PbContent>.renders: List<PbContentRender>
it.c it.c
) )
val emoticonText = "#(${it.c})".emoticonString val emoticonText = "#(${it.c})".emoticonString
val lastRender = renders.lastOrNull() renders.appendText(emoticonText)
if (lastRender is TextContentRender) {
renders.removeLast()
renders.add(lastRender + emoticonText)
} else
renders.add(TextContentRender(emoticonText))
} }
3 -> { 3 -> {
@ -189,7 +214,6 @@ val List<PbContent>.renders: List<PbContentRender>
4 -> { 4 -> {
val text = buildAnnotatedString { val text = buildAnnotatedString {
appendInlineContent("user_icon", alternateText = "🧑")
withAnnotation(tag = "user", annotation = "${it.uid}") { withAnnotation(tag = "user", annotation = "${it.uid}") {
withStyle( withStyle(
SpanStyle( SpanStyle(
@ -205,12 +229,43 @@ val List<PbContent>.renders: List<PbContentRender>
} }
} }
} }
val lastRender = renders.lastOrNull() renders.appendText(text)
if (lastRender is TextContentRender) { }
renders.removeLast()
renders.add(lastRender + text) 5 -> {
} else if (it.src.isNotBlank()) {
renders.add(TextContentRender(text)) val width = it.bsize.split(",")[0].toInt()
val height = it.bsize.split(",")[1].toInt()
renders.add(
VideoContentRender(
videoUrl = it.link,
picUrl = it.src,
webUrl = it.text,
width = width,
height = height
)
)
} else {
val text = buildAnnotatedString {
appendInlineContent("video_icon", alternateText = "🎥")
withAnnotation(tag = "url", annotation = it.text) {
withStyle(
SpanStyle(
color = Color(
ThemeUtils.getColorByAttr(
App.INSTANCE,
R.attr.colorPrimary
)
)
)
) {
append(App.INSTANCE.getString(R.string.tag_video))
append(it.text)
}
}
}
renders.appendText(text)
}
} }
20 -> { 20 -> {
@ -234,7 +289,7 @@ val List<PbContent>.renders: List<PbContentRender>
return renders return renders
} }
val Post.contentRenders: List<PbContentRender> val Post.contentRenders: ImmutableList<PbContentRender>
get() { get() {
val renders = content.renders val renders = content.renders
@ -252,5 +307,5 @@ val Post.contentRenders: List<PbContentRender>
} else it } else it
} }
return renders return renders.toImmutableList()
} }

View File

@ -96,8 +96,9 @@ interface ITiebaApi {
*/ */
fun opAgreeFlow( fun opAgreeFlow(
threadId: String, threadId: String,
postId: String, opType: Int,
opType: Int postId: String? = null,
isSubPost: Boolean = false,
): Flow<AgreeBean> ): Flow<AgreeBean>
/** /**
@ -527,6 +528,20 @@ interface ITiebaApi {
tbs: String tbs: String
): Call<CommonResponse> ): Call<CommonResponse>
/**
* 移除收藏
*
* **需登录**
*
* @param threadId 贴子 ID
* @param tbs tbs
*/
fun removeStoreFlow(
threadId: Long,
forumId: Long,
tbs: String?
): Flow<CommonResponse>
/** /**
* 移除收藏 * 移除收藏
* *
@ -553,6 +568,19 @@ interface ITiebaApi {
tbs: String tbs: String
): Call<CommonResponse> ): Call<CommonResponse>
/**
* 添加/更新收藏
*
* **需登录**
*
* @param threadId 贴子 ID
* @param postId 收藏到的回复 ID
*/
fun addStoreFlow(
threadId: Long,
postId: Long
): Flow<CommonResponse>
/** /**
* 回复我的消息列表 * 回复我的消息列表
* *
@ -1231,11 +1259,17 @@ interface ITiebaApi {
* 贴子页Flow * 贴子页Flow
* *
* @param threadId 贴子 ID * @param threadId 贴子 ID
* @param page 页码 1 开始
*/ */
fun pbPageFlow( fun pbPageFlow(
threadId: Long, threadId: Long,
page: Int, page: Int = 0,
postId: Long = 0L,
seeLz: Boolean = false,
back: Boolean = false,
sortType: Int = 0, sortType: Int = 0,
forumId: Long? = null, forumId: Long? = null,
stType: String = "",
mark: Int = 0,
): Flow<PbPageResponse> ): Flow<PbPageResponse>
} }

View File

@ -31,6 +31,7 @@ import com.huanchengfly.tieba.post.api.models.LoginBean
import com.huanchengfly.tieba.post.api.models.MSignBean import com.huanchengfly.tieba.post.api.models.MSignBean
import com.huanchengfly.tieba.post.api.models.MessageListBean import com.huanchengfly.tieba.post.api.models.MessageListBean
import com.huanchengfly.tieba.post.api.models.MsgBean import com.huanchengfly.tieba.post.api.models.MsgBean
import com.huanchengfly.tieba.post.api.models.NewCollectDataBean
import com.huanchengfly.tieba.post.api.models.PersonalizedBean import com.huanchengfly.tieba.post.api.models.PersonalizedBean
import com.huanchengfly.tieba.post.api.models.PicPageBean import com.huanchengfly.tieba.post.api.models.PicPageBean
import com.huanchengfly.tieba.post.api.models.Profile import com.huanchengfly.tieba.post.api.models.Profile
@ -159,10 +160,16 @@ object MixedTiebaApiImpl : ITiebaApi {
override fun opAgreeFlow( override fun opAgreeFlow(
threadId: String, threadId: String,
postId: String, opType: Int,
opType: Int postId: String?,
isSubPost: Boolean
): Flow<AgreeBean> = ): Flow<AgreeBean> =
RetrofitTiebaApi.MINI_TIEBA_API.agreeFlow(postId, threadId, op_type = opType) RetrofitTiebaApi.OFFICIAL_TIEBA_API.agreeFlow(
threadId,
postId,
opType = opType,
objType = if (postId == null) 3 else if (isSubPost) 2 else 1
)
override fun disagreeFlow( override fun disagreeFlow(
threadId: String, threadId: String,
@ -393,6 +400,17 @@ object MixedTiebaApiImpl : ITiebaApi {
override fun removeStore(threadId: String, tbs: String): Call<CommonResponse> = override fun removeStore(threadId: String, tbs: String): Call<CommonResponse> =
RetrofitTiebaApi.NEW_TIEBA_API.removeStore(threadId, tbs) RetrofitTiebaApi.NEW_TIEBA_API.removeStore(threadId, tbs)
override fun removeStoreFlow(
threadId: Long,
forumId: Long,
tbs: String?
): Flow<CommonResponse> =
RetrofitTiebaApi.OFFICIAL_TIEBA_API.removeStoreFlow(
threadId.toString(),
forumId.toString(),
tbs ?: AccountUtil.getLoginInfo()!!.tbs
)
override fun removeStoreFlow(threadId: String): Flow<CommonResponse> = override fun removeStoreFlow(threadId: String): Flow<CommonResponse> =
RetrofitTiebaApi.OFFICIAL_TIEBA_API.removeStoreFlow(threadId) RetrofitTiebaApi.OFFICIAL_TIEBA_API.removeStoreFlow(threadId)
@ -405,9 +423,22 @@ object MixedTiebaApiImpl : ITiebaApi {
"0", "0",
"0" "0"
) )
).toJson(), tbs ).toJson(),
tbs
) )
override fun addStoreFlow(threadId: Long, postId: Long): Flow<CommonResponse> =
RetrofitTiebaApi.OFFICIAL_TIEBA_API.addStoreFlow(
listOf(
NewCollectDataBean(
threadId.toString(),
postId.toString(),
status = 1
)
).toJson()
)
override fun replyMe(page: Int): Call<MessageListBean> = override fun replyMe(page: Int): Call<MessageListBean> =
RetrofitTiebaApi.NEW_TIEBA_API.replyMe(page) RetrofitTiebaApi.NEW_TIEBA_API.replyMe(page)
@ -1009,8 +1040,13 @@ object MixedTiebaApiImpl : ITiebaApi {
override fun pbPageFlow( override fun pbPageFlow(
threadId: Long, threadId: Long,
page: Int, page: Int,
postId: Long,
seeLz: Boolean,
back: Boolean,
sortType: Int, sortType: Int,
forumId: Long? forumId: Long?,
stType: String,
mark: Int,
): Flow<PbPageResponse> { ): Flow<PbPageResponse> {
return RetrofitTiebaApi.OFFICIAL_PROTOBUF_TIEBA_V12_API.pbPageFlow( return RetrofitTiebaApi.OFFICIAL_PROTOBUF_TIEBA_V12_API.pbPageFlow(
buildProtobufRequestBody( buildProtobufRequestBody(
@ -1018,18 +1054,23 @@ object MixedTiebaApiImpl : ITiebaApi {
PbPageRequestData( PbPageRequestData(
common = buildCommonRequest(clientVersion = ClientVersion.TIEBA_V12), common = buildCommonRequest(clientVersion = ClientVersion.TIEBA_V12),
kz = threadId, kz = threadId,
pid = postId,
pn = page,
r = sortType,
lz = if (seeLz) 1 else 0,
forum_id = forumId ?: 0,
ad_param = com.huanchengfly.tieba.post.api.models.protos.pbPage.AdParam( ad_param = com.huanchengfly.tieba.post.api.models.protos.pbPage.AdParam(
load_count = 0, load_count = 0,
refresh_count = 1, refresh_count = 1,
is_req_ad = 1 is_req_ad = 1
), ),
mark = mark,
app_pos = buildAppPosInfo(), app_pos = buildAppPosInfo(),
back = 0, back = if (back) 1 else 0,
banner = 1, banner = 1,
broadcast_id = 0, broadcast_id = 0,
floor_rn = 4, floor_rn = 4,
floor_sort_type = 1, floor_sort_type = 1,
forum_id = forumId ?: 0,
from_push = 0, from_push = 0,
from_smart_frs = 0, from_smart_frs = 0,
immersion_video_comment_source = 0, immersion_video_comment_source = 0,
@ -1043,17 +1084,14 @@ object MixedTiebaApiImpl : ITiebaApi {
obj_source = "", obj_source = "",
ori_ugc_type = 0, ori_ugc_type = 0,
pb_rn = 0, pb_rn = 0,
pid = 0,
pn = page,
q_type = 1, q_type = 1,
r = sortType,
rn = 15, rn = 15,
s_model = 0, s_model = 0,
scr_dip = App.ScreenInfo.DENSITY.toDouble(), scr_dip = App.ScreenInfo.DENSITY.toDouble(),
scr_h = getScreenHeight(), scr_h = getScreenHeight(),
scr_w = getScreenWidth(), scr_w = getScreenWidth(),
source_type = 2, source_type = 2,
st_type = "personalize_page", st_type = stType,
thread_type = 0, thread_type = 0,
weipost = 0, weipost = 0,
with_floor = 1 with_floor = 1

View File

@ -0,0 +1,11 @@
package com.huanchengfly.tieba.post.api.models
import com.google.gson.annotations.SerializedName
data class NewCollectDataBean(
@SerializedName("tid")
val threadId: String,
@SerializedName("pid")
val postId: String,
val status: Int
)

View File

@ -327,25 +327,6 @@ interface OfficialTiebaApi {
@Field("user_id") user_id: String? = AccountUtil.getUid(), @Field("user_id") user_id: String? = AccountUtil.getUid(),
): Flow<ThreadStoreBean> ): Flow<ThreadStoreBean>
@POST("/c/c/post/rmstore")
@FormUrlEncoded
@Headers(
"${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}",
"${Header.COOKIE}: ka=open",
"${Header.DROP_HEADERS}: ${Header.CHARSET},${Header.CLIENT_TYPE}",
"${Header.NO_COMMON_PARAMS}: ${Param.OAID}",
)
fun removeStoreFlow(
@Field("tid") threadId: String,
@Field("tbs") tbs: String = AccountUtil.getLoginInfo()!!.tbs,
@Field("stoken") stoken: String = AccountUtil.getSToken()!!,
@Field("user_id") user_id: String? = AccountUtil.getUid(),
@Field("fid") fid: String = "null",
@Field("_client_version") client_version: String = "11.10.8.6",
@retrofit2.http.Header(Header.USER_AGENT) user_agent: String = "bdtb for Android $client_version",
@retrofit2.http.Header("client_user_token") client_user_token: String? = user_id,
): Flow<CommonResponse>
@Headers( @Headers(
"${Header.COOKIE}: ka=open", "${Header.COOKIE}: ka=open",
"${Header.DROP_HEADERS}: ${Header.CHARSET},${Header.CLIENT_TYPE}", "${Header.DROP_HEADERS}: ${Header.CHARSET},${Header.CLIENT_TYPE}",
@ -414,4 +395,57 @@ interface OfficialTiebaApi {
@Field("stoken") sToken: String? = AccountUtil.getSToken(), @Field("stoken") sToken: String? = AccountUtil.getSToken(),
@retrofit2.http.Header("client_user_token") client_user_token: String? = AccountUtil.getUid(), @retrofit2.http.Header("client_user_token") client_user_token: String? = AccountUtil.getUid(),
): Flow<AddPostBean> ): Flow<AddPostBean>
@POST("/c/c/post/rmstore")
@FormUrlEncoded
@Headers(
"${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}",
"${Header.COOKIE}: ka=open",
"${Header.DROP_HEADERS}: ${Header.CHARSET},${Header.CLIENT_TYPE}",
"${Header.NO_COMMON_PARAMS}: ${Param.OAID}",
)
fun removeStoreFlow(
@Field("tid") threadId: String,
@Field("fid") forumId: String = "null",
@Field("tbs") tbs: String = AccountUtil.getLoginInfo()!!.tbs,
@Field("stoken") stoken: String = AccountUtil.getSToken()!!,
@Field("user_id") user_id: String? = AccountUtil.getUid(),
@retrofit2.http.Header("client_user_token") client_user_token: String? = user_id,
): Flow<CommonResponse>
@POST("/c/c/post/addstore")
@FormUrlEncoded
@Headers(
"${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}",
"${Header.COOKIE}: ka=open",
"${Header.DROP_HEADERS}: ${Header.CHARSET},${Header.CLIENT_TYPE}",
"${Header.NO_COMMON_PARAMS}: ${Param.OAID}",
)
fun addStoreFlow(
@Field("data") data: String,
@Field("stoken") stoken: String = AccountUtil.getSToken()!!,
@retrofit2.http.Header("client_user_token") client_user_token: String? = AccountUtil.getUid(),
): Flow<CommonResponse>
@Headers(
"${Header.FORCE_LOGIN}: ${Header.FORCE_LOGIN_TRUE}",
"${Header.COOKIE}: ka=open",
"${Header.DROP_HEADERS}: ${Header.CHARSET},${Header.CLIENT_TYPE}",
"${Header.NO_COMMON_PARAMS}: ${Param.OAID}",
)
@POST("/c/c/agree/opAgree")
@FormUrlEncoded
fun agreeFlow(
@Field("thread_id") threadId: String,
@Field("post_id") postId: String? = null,
@Field("op_type") opType: Int = 0,
@Field("obj_type") objType: Int = 1,
@Field("agree_type") agreeType: Int = 2,
@retrofit2.http.Header("client_user_token") client_user_token: String? = AccountUtil.getUid(),
@Field("cuid_gid") cuid_gid: String = "",
@Field("forum_id") forumId: String = "",
@Field("personalized_rec_switch") personalizedRecSwitch: Int = 1,
@Field("tbs") tbs: String = AccountUtil.getLoginInfo()!!.tbs,
@Field("stoken") stoken: String = AccountUtil.getSToken()!!
): Flow<AgreeBean>
} }

View File

@ -203,7 +203,6 @@ private class ForumThreadListPartialChangeProducer(val type: ForumThreadListType
private fun ForumThreadListUiIntent.Agree.producePartialChange(): Flow<ForumThreadListPartialChange.Agree> = private fun ForumThreadListUiIntent.Agree.producePartialChange(): Flow<ForumThreadListPartialChange.Agree> =
TiebaApi.getInstance().opAgreeFlow( TiebaApi.getInstance().opAgreeFlow(
threadId.toString(), threadId.toString(),
postId.toString(),
hasAgree, hasAgree,
).map<AgreeBean, ForumThreadListPartialChange.Agree> { ).map<AgreeBean, ForumThreadListPartialChange.Agree> {
ForumThreadListPartialChange.Agree.Success( ForumThreadListPartialChange.Agree.Success(

View File

@ -79,7 +79,7 @@ class ConcernViewModel @Inject constructor() :
private fun ConcernUiIntent.Agree.producePartialChange(): Flow<ConcernPartialChange.Agree> = private fun ConcernUiIntent.Agree.producePartialChange(): Flow<ConcernPartialChange.Agree> =
TiebaApi.getInstance().opAgreeFlow( TiebaApi.getInstance().opAgreeFlow(
threadId.toString(), postId.toString(), hasAgree, threadId.toString(), hasAgree
).map<AgreeBean, ConcernPartialChange.Agree> { ConcernPartialChange.Agree.Success(threadId, hasAgree xor 1) } ).map<AgreeBean, ConcernPartialChange.Agree> { ConcernPartialChange.Agree.Success(threadId, hasAgree xor 1) }
.catch { emit(ConcernPartialChange.Agree.Failure(threadId, hasAgree, it)) } .catch { emit(ConcernPartialChange.Agree.Failure(threadId, hasAgree, it)) }
.onStart { emit(ConcernPartialChange.Agree.Start(threadId, hasAgree xor 1)) } .onStart { emit(ConcernPartialChange.Agree.Start(threadId, hasAgree xor 1)) }

View File

@ -100,7 +100,7 @@ class PersonalizedViewModel @Inject constructor() :
private fun PersonalizedUiIntent.Agree.producePartialChange(): Flow<PersonalizedPartialChange.Agree> = private fun PersonalizedUiIntent.Agree.producePartialChange(): Flow<PersonalizedPartialChange.Agree> =
TiebaApi.getInstance().opAgreeFlow( TiebaApi.getInstance().opAgreeFlow(
threadId.toString(), postId.toString(), hasAgree, threadId.toString(), hasAgree,
).map<AgreeBean, PersonalizedPartialChange.Agree> { ).map<AgreeBean, PersonalizedPartialChange.Agree> {
PersonalizedPartialChange.Agree.Success( PersonalizedPartialChange.Agree.Success(
threadId, threadId,

View File

@ -13,4 +13,10 @@ message Page {
int32 has_more = 6; int32 has_more = 6;
int32 has_prev = 7; int32 has_prev = 7;
int32 cur_good_id = 8; int32 cur_good_id = 8;
int32 req_num = 9;
int32 pnum = 10;
int32 tnum = 11;
int32 total_num = 12;
int32 lz_total_floor = 13;
int32 new_total_page = 14;
} }

View File

@ -36,8 +36,10 @@ message ThreadInfo {
int32 createTime = 45; int32 createTime = 45;
int32 collectStatus = 50; int32 collectStatus = 50;
string collectMarkPid = 51; string collectMarkPid = 51;
int64 post_id = 52;
int32 isMemberTop = 54; int32 isMemberTop = 54;
int64 authorId = 56; int64 authorId = 56;
string pids = 61;
optional VideoInfo videoInfo = 79; optional VideoInfo videoInfo = 79;
repeated PbContent richTitle = 111; repeated PbContent richTitle = 111;
repeated PbContent richAbstract = 112; repeated PbContent richAbstract = 112;