public class CreateTopicResult extends Result {

    @SerializedName("topic_id")
    private String topicId;

    public String getTopicId() {
        return topicId;
    }

    public void setTopicId(String topicId) {
        this.topicId = topicId;
    }

} public class DataResult<Data> extends Result {

    private Data data;

    public Data getData() {
        return data;
    }

    public void setData(Data data) {
        this.data = data;
    }

} public class LoginResult extends Result {

    private String id;

    @SerializedName("loginname")
    private String loginName;

    @SerializedName("avatar_url")
    private String avatarUrl;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getLoginName() {
        return loginName;
    }

    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }

    public String getAvatarUrl() { // 修复头像地址的历史遗留问题
        return FormatUtils.getCompatAvatarUrl(avatarUrl);
    }

    public void setAvatarUrl(String avatarUrl) {
        this.avatarUrl = avatarUrl;
    }

} public class Notification {

    @SerializedName("has_read_messages")
    private List<Message> hasReadMessageList;

    @SerializedName("hasnot_read_messages")
    private List<Message> hasNotReadMessageList;

    public List<Message> getHasReadMessageList() {
        return hasReadMessageList;
    }

    public void setHasReadMessageList(List<Message> hasReadMessageList) {
        this.hasReadMessageList = hasReadMessageList;
    }

    public List<Message> getHasNotReadMessageList() {
        return hasNotReadMessageList;
    }

    public void setHasNotReadMessageList(List<Message> hasNotReadMessageList) {
        this.hasNotReadMessageList = hasNotReadMessageList;
    }

} public class ReplyTopicResult extends Result {

    @SerializedName("reply_id")
    private String replyId;

    public String getReplyId() {
        return replyId;
    }

    public void setReplyId(String replyId) {
        this.replyId = replyId;
    }

} public class Result {

    private boolean success;

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

} public enum Tab {

    all(R.string.app_name),

    good(R.string.tab_good),

    unknown(R.string.tab_unknown),

    share(R.string.tab_share),

    ask(R.string.tab_ask),

    job(R.string.tab_job),

    dev(R.string.tab_dev);

    @StringRes
    private final int nameId;

    Tab(@StringRes int nameId) {
        this.nameId = nameId;
    }

    @StringRes
    public int getNameId() {
        return nameId;
    }

    public static List<Tab> getPublishableTabList() {
        List<Tab> tabList = new ArrayList<>();
        if (BuildConfig.DEBUG) {
            tabList.add(dev);
        }
        tabList.add(share);
        tabList.add(ask);
        tabList.add(job);
        return tabList;
    }

} public class Topic extends TopicSimple {

    @SerializedName("author_id")
    private String authorId;

    private Tab tab;

    private String content;

    private boolean good;

    private boolean top;

    @SerializedName("reply_count")
    private int replyCount;

    @SerializedName("visit_count")
    private int visitCount;

    @SerializedName("create_at")
    private DateTime createAt;

    public String getAuthorId() {
        return authorId;
    }

    public void setAuthorId(String authorId) {
        this.authorId = authorId;
    }

    @NonNull
    public Tab getTab() {
        return tab == null ? Tab.unknown : tab; // 接口中有些话题没有 Tab 属性，这里保证 Tab 不为空
    }

    public void setTab(Tab tab) {
        this.tab = tab;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
        cleanContentCache();
    }

    public boolean isGood() {
        return good;
    }

    public void setGood(boolean good) {
        this.good = good;
    }

    public boolean isTop() {
        return top;
    }

    public void setTop(boolean top) {
        this.top = top;
    }

    public int getReplyCount() {
        return replyCount;
    }

    public void setReplyCount(int replyCount) {
        this.replyCount = replyCount;
    }

    public int getVisitCount() {
        return visitCount;
    }

    public void setVisitCount(int visitCount) {
        this.visitCount = visitCount;
    }

    public DateTime getCreateAt() {
        return createAt;
    }

    public void setCreateAt(DateTime createAt) {
        this.createAt = createAt;
    }

    /**
     * Html渲染缓存
     */

    @SerializedName("content_html")
    private String contentHtml;

    @SerializedName("content_summary")
    private String contentSummary;

    public void markSureHandleContent() {
        if (contentHtml == null || contentSummary == null) {
            Document document;
            if (ApiDefine.MD_RENDER) {
                document = FormatUtils.handleHtml(content);
            } else {
                document = FormatUtils.handleHtml(FormatUtils.renderMarkdown(content));
            }
            if (contentHtml == null) {
                contentHtml = document.body().html();
            }
            if (contentSummary == null) {
                contentSummary = document.body().text().trim();
            }
        }
    }

    public void cleanContentCache() {
        contentHtml = null;
        contentSummary = null;
    }

    public String getContentHtml() {
        markSureHandleContent();
        return contentHtml;
    }

    public String getContentSummary() {
        markSureHandleContent();
        return contentSummary;
    }

} public class TopicWithReply extends Topic {

    @SerializedName("is_collect")
    private boolean isCollect; // 是否收藏该话题，只有调用时带有 accesstoken 时，这个字段才有可能为 true

    @SerializedName("replies")
    private List<Reply> replyList;

    public boolean isCollect() {
        return isCollect;
    }

    public void setCollect(boolean collect) {
        isCollect = collect;
    }

    public List<Reply> getReplyList() {
        return replyList;
    }

    public void setReplyList(List<Reply> replyList) {
        this.replyList = replyList;
    }

} public class UpReplyResult extends Result {

    private Reply.UpAction action;

    @NonNull
    public Reply.UpAction getAction() {
        return action == null ? Reply.UpAction.down : action;
    }

    public void setAction(Reply.UpAction action) {
        this.action = action;
    }

} public class User {

    @SerializedName("loginname")
    private String loginName;

    @SerializedName("avatar_url")
    private String avatarUrl;

    private String githubUsername;

    @SerializedName("create_at")
    private DateTime createAt;

    private int score;

    @SerializedName("recent_topics")
    private List<TopicSimple> recentTopicList;

    @SerializedName("recent_replies")
    private List<TopicSimple> recentReplyList;

    public String getLoginName() {
        return loginName;
    }

    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }

    public String getAvatarUrl() { // 修复头像地址的历史遗留问题
        return FormatUtils.getCompatAvatarUrl(avatarUrl);
    }

    public void setAvatarUrl(String avatarUrl) {
        this.avatarUrl = avatarUrl;
    }

    public String getGithubUsername() {
        return githubUsername;
    }

    public void setGithubUsername(String githubUsername) {
        this.githubUsername = githubUsername;
    }

    public DateTime getCreateAt() {
        return createAt;
    }

    public void setCreateAt(DateTime createAt) {
        this.createAt = createAt;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public List<TopicSimple> getRecentTopicList() {
        return recentTopicList;
    }

    public void setRecentTopicList(List<TopicSimple> recentTopicList) {
        this.recentTopicList = recentTopicList;
    }

    public List<TopicSimple> getRecentReplyList() {
        return recentReplyList;
    }

    public void setRecentReplyList(List<TopicSimple> recentReplyList) {
        this.recentReplyList = recentReplyList;
    }

}
import org.cnodejs.android.md.model.entity.CreateTopicResult;
import org.cnodejs.android.md.model.entity.DataResult;
import org.cnodejs.android.md.model.entity.LoginResult;
import org.cnodejs.android.md.model.entity.Notification;
import org.cnodejs.android.md.model.entity.ReplyTopicResult;
import org.cnodejs.android.md.model.entity.Result;
import org.cnodejs.android.md.model.entity.Tab;
import org.cnodejs.android.md.model.entity.Topic;
import org.cnodejs.android.md.model.entity.TopicWithReply;
import org.cnodejs.android.md.model.entity.UpReplyResult;
import org.cnodejs.android.md.model.entity.User;
import java.util.List;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Query;
package org.cnodejs.android.md.model.api;




public interface ApiService {

    //=====
    // 话题
    //=====

    @GET("topics")
    Call<DataResult<List<Topic>>> getTopicList(
            @Query("tab") Tab tab,
            @Query("page") Integer page,
            @Query("limit") Integer limit,
            @Query("mdrender") Boolean mdrender
    );

    @GET("topic/{topicId}")
    Call<DataResult<TopicWithReply>> getTopic(
            @Path("topicId") String topicId,
            @Query("accesstoken") String accessToken,
            @Query("mdrender") Boolean mdrender
    );

    @POST("topics")
    @FormUrlEncoded
    Call<CreateTopicResult> createTopic(
            @Field("accesstoken") String accessToken,
            @Field("tab") Tab tab,
            @Field("title") String title,
            @Field("content") String content
    );

    //=========
    // 话题收藏
    //=========

    @POST("topic_collect/collect")
    @FormUrlEncoded
    Call<Result> collectTopic(
            @Field("accesstoken") String accessToken,
            @Field("topic_id") String topicId
    );

    @POST("topic_collect/de_collect")
    @FormUrlEncoded
    Call<Result> decollectTopic(
            @Field("accesstoken") String accessToken,
            @Field("topic_id") String topicId
    );

    @GET("topic_collect/{loginName}")
    Call<DataResult<List<Topic>>> getCollectTopicList(
            @Path("loginName") String loginName
    );

    //=====
    // 回复
    //=====

    @POST("topic/{topicId}/replies")
    @FormUrlEncoded
    Call<ReplyTopicResult> createReply(
            @Path("topicId") String topicId,
            @Field("accesstoken") String accessToken,
            @Field("content") String content,
            @Field("reply_id") String targetId
    );

    @POST("reply/{replyId}/ups")
    @FormUrlEncoded
    Call<UpReplyResult> upReply(
            @Path("replyId") String replyId,
            @Field("accesstoken") String accessToken
    );

    //=====
    // 用户
    //=====

    @GET("user/{loginName}")
    Call<DataResult<User>> getUser(
            @Path("loginName") String loginName
    );

    @POST("accesstoken")
    @FormUrlEncoded
    Call<LoginResult> accessToken(