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
get() =
ImageUtil.getUrl(
@ -123,12 +163,7 @@ val List<PbContent>.renders: List<PbContentRender>
forEach {
when (it.type) {
0, 9, 27 -> {
val lastRender = renders.lastOrNull()
if (lastRender is TextContentRender) {
renders.removeLast()
renders.add(lastRender + it.text)
} else
renders.add(TextContentRender(it.text))
renders.appendText(it.text)
}
1 -> {
@ -149,12 +184,7 @@ val List<PbContent>.renders: List<PbContentRender>
}
}
}
val lastRender = renders.lastOrNull()
if (lastRender is TextContentRender) {
renders.removeLast()
renders.add(lastRender + text)
} else
renders.add(TextContentRender(text))
renders.appendText(text)
}
2 -> {
@ -163,12 +193,7 @@ val List<PbContent>.renders: List<PbContentRender>
it.c
)
val emoticonText = "#(${it.c})".emoticonString
val lastRender = renders.lastOrNull()
if (lastRender is TextContentRender) {
renders.removeLast()
renders.add(lastRender + emoticonText)
} else
renders.add(TextContentRender(emoticonText))
renders.appendText(emoticonText)
}
3 -> {
@ -189,7 +214,6 @@ val List<PbContent>.renders: List<PbContentRender>
4 -> {
val text = buildAnnotatedString {
appendInlineContent("user_icon", alternateText = "🧑")
withAnnotation(tag = "user", annotation = "${it.uid}") {
withStyle(
SpanStyle(
@ -205,12 +229,43 @@ val List<PbContent>.renders: List<PbContentRender>
}
}
}
val lastRender = renders.lastOrNull()
if (lastRender is TextContentRender) {
renders.removeLast()
renders.add(lastRender + text)
} else
renders.add(TextContentRender(text))
renders.appendText(text)
}
5 -> {
if (it.src.isNotBlank()) {
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 -> {
@ -234,7 +289,7 @@ val List<PbContent>.renders: List<PbContentRender>
return renders
}
val Post.contentRenders: List<PbContentRender>
val Post.contentRenders: ImmutableList<PbContentRender>
get() {
val renders = content.renders
@ -252,5 +307,5 @@ val Post.contentRenders: List<PbContentRender>
} else it
}
return renders
return renders.toImmutableList()
}

View File

@ -96,8 +96,9 @@ interface ITiebaApi {
*/
fun opAgreeFlow(
threadId: String,
postId: String,
opType: Int
opType: Int,
postId: String? = null,
isSubPost: Boolean = false,
): Flow<AgreeBean>
/**
@ -527,6 +528,20 @@ interface ITiebaApi {
tbs: String
): 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
): Call<CommonResponse>
/**
* 添加/更新收藏
*
* **需登录**
*
* @param threadId 贴子 ID
* @param postId 收藏到的回复 ID
*/
fun addStoreFlow(
threadId: Long,
postId: Long
): Flow<CommonResponse>
/**
* 回复我的消息列表
*
@ -1231,11 +1259,17 @@ interface ITiebaApi {
* 贴子页Flow
*
* @param threadId 贴子 ID
* @param page 页码 1 开始
*/
fun pbPageFlow(
threadId: Long,
page: Int,
page: Int = 0,
postId: Long = 0L,
seeLz: Boolean = false,
back: Boolean = false,
sortType: Int = 0,
forumId: Long? = null,
stType: String = "",
mark: Int = 0,
): 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.MessageListBean
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.PicPageBean
import com.huanchengfly.tieba.post.api.models.Profile
@ -159,10 +160,16 @@ object MixedTiebaApiImpl : ITiebaApi {
override fun opAgreeFlow(
threadId: String,
postId: String,
opType: Int
opType: Int,
postId: String?,
isSubPost: Boolean
): 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(
threadId: String,
@ -393,6 +400,17 @@ object MixedTiebaApiImpl : ITiebaApi {
override fun removeStore(threadId: String, tbs: String): Call<CommonResponse> =
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> =
RetrofitTiebaApi.OFFICIAL_TIEBA_API.removeStoreFlow(threadId)
@ -405,9 +423,22 @@ object MixedTiebaApiImpl : ITiebaApi {
"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> =
RetrofitTiebaApi.NEW_TIEBA_API.replyMe(page)
@ -1009,8 +1040,13 @@ object MixedTiebaApiImpl : ITiebaApi {
override fun pbPageFlow(
threadId: Long,
page: Int,
postId: Long,
seeLz: Boolean,
back: Boolean,
sortType: Int,
forumId: Long?
forumId: Long?,
stType: String,
mark: Int,
): Flow<PbPageResponse> {
return RetrofitTiebaApi.OFFICIAL_PROTOBUF_TIEBA_V12_API.pbPageFlow(
buildProtobufRequestBody(
@ -1018,18 +1054,23 @@ object MixedTiebaApiImpl : ITiebaApi {
PbPageRequestData(
common = buildCommonRequest(clientVersion = ClientVersion.TIEBA_V12),
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(
load_count = 0,
refresh_count = 1,
is_req_ad = 1
),
mark = mark,
app_pos = buildAppPosInfo(),
back = 0,
back = if (back) 1 else 0,
banner = 1,
broadcast_id = 0,
floor_rn = 4,
floor_sort_type = 1,
forum_id = forumId ?: 0,
from_push = 0,
from_smart_frs = 0,
immersion_video_comment_source = 0,
@ -1043,17 +1084,14 @@ object MixedTiebaApiImpl : ITiebaApi {
obj_source = "",
ori_ugc_type = 0,
pb_rn = 0,
pid = 0,
pn = page,
q_type = 1,
r = sortType,
rn = 15,
s_model = 0,
scr_dip = App.ScreenInfo.DENSITY.toDouble(),
scr_h = getScreenHeight(),
scr_w = getScreenWidth(),
source_type = 2,
st_type = "personalize_page",
st_type = stType,
thread_type = 0,
weipost = 0,
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(),
): 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(
"${Header.COOKIE}: ka=open",
"${Header.DROP_HEADERS}: ${Header.CHARSET},${Header.CLIENT_TYPE}",
@ -414,4 +395,57 @@ interface OfficialTiebaApi {
@Field("stoken") sToken: String? = AccountUtil.getSToken(),
@retrofit2.http.Header("client_user_token") client_user_token: String? = AccountUtil.getUid(),
): 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> =
TiebaApi.getInstance().opAgreeFlow(
threadId.toString(),
postId.toString(),
hasAgree,
).map<AgreeBean, ForumThreadListPartialChange.Agree> {
ForumThreadListPartialChange.Agree.Success(

View File

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

View File

@ -13,4 +13,10 @@ message Page {
int32 has_more = 6;
int32 has_prev = 7;
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 collectStatus = 50;
string collectMarkPid = 51;
int64 post_id = 52;
int32 isMemberTop = 54;
int64 authorId = 56;
string pids = 61;
optional VideoInfo videoInfo = 79;
repeated PbContent richTitle = 111;
repeated PbContent richAbstract = 112;