public class Like {
    @SerializedName("obj_type") public String objType;      // 点赞对象类型
    @SerializedName("obj_id") public int objId;             // 点赞对象 id
    @SerializedName("count") public int count;              // 点赞数
} public class News implements Parcelable {

    @SerializedName("id") public int id;                                            // 新闻 id
    @SerializedName("title") public String title;                                   // 标题
    @SerializedName("created_at") public Date createdAt;                            // 创建时间
    @SerializedName("updated_at") public Date updatedAt;                            // 更新时间
    @SerializedName("user") public User user;                                       // 创建该话题的用户
    @SerializedName("node_name") public String nodeName;                            // 节点名称
    @SerializedName("node_id") public int nodeId;                                   // 节点 id
    @SerializedName("last_reply_user_id") public int lastReplyUserId;               // 最近一次回复的用户 id
    @SerializedName("last_reply_user_login") public String lastReplyUserLogin;      // 最近一次回复的用户登录名
    @SerializedName("replied_at") public Date repliedAt;                            // 最近一次回复时间
    @SerializedName("replies_count") public int repliesCount;                       // 回复总数量
    @SerializedName("address") public String address;                               // 具体地址

    protected News(Parcel in) {
        id = in.readInt();
        title = in.readString();
        user = in.readParcelable(User.class.getClassLoader());
        nodeName = in.readString();
        nodeId = in.readInt();
        lastReplyUserId = in.readInt();
        lastReplyUserLogin = in.readString();
        repliesCount = in.readInt();
        address = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(title);
        dest.writeParcelable(user, flags);
        dest.writeString(nodeName);
        dest.writeInt(nodeId);
        dest.writeInt(lastReplyUserId);
        dest.writeString(lastReplyUserLogin);
        dest.writeInt(repliesCount);
        dest.writeString(address);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<News> CREATOR = new Creator<News>() {
        @Override
        public News createFromParcel(Parcel in) {
            return new News(in);
        }

        @Override
        public News[] newArray(int size) {
            return new News[size];
        }
    };
} public class NewsNode {
    @SerializedName("id") public int id;                // 新闻节点 id
    @SerializedName("name") public String name;         // 名称
} public class Node {

    @SerializedName("id") public int id;                            // 节点 id
    @SerializedName("name") public String name;                     // 节点名
    @SerializedName("topics_count") public int topicsCount;         // 话题数量
    @SerializedName("summary") public String summary;               // 节点介绍
    @SerializedName("section_id") public int sectionId;             // 分类 id
    @SerializedName("sort") public int sort;                        // 排序
    @SerializedName("section_name") public String sectionName;      // 分类名
    @SerializedName("updated_at") public Date updatedAt;            // 更新时间
} public class Notification {
    @SerializedName("id") public int id;                            // 通知 id
    @SerializedName("type") public String type;                     // 类型
    @SerializedName("read") public Boolean read;                    // 是否已读
    @SerializedName("actor") public User actor;                     // 相关人员
    @SerializedName("mention_type") public String mentionType;      // 提及类型
    @SerializedName("mention") public Reply mention;                // 提及详情
    @SerializedName("topic") public Topic topic;                    // 话题
    @SerializedName("reply") public Reply reply;                    // 回复
    @SerializedName("node") public Node node;                       // 节点变更
    @SerializedName("created_at") public Date createdAt;            // 创建时间
    @SerializedName("updated_at") public Date updatedAt;            // 更新时间
} public class Photo {

    @SerializedName("image_url") public String imageUrl;
} public class Reply {

    @SerializedName("id") public int id;                        // 回复 id
    @SerializedName("body_html") public String bodyHtml;        // 回复内容详情(HTML)
    @SerializedName("created_at") public Date createdAt;        // 创建时间
    @SerializedName("updated_at") public Date updatedAt;        // 更新时间
    @SerializedName("deleted") public boolean deleted;          // 是否已经删除
    @SerializedName("user") public User user;                   // 创建该回复的用户
    @SerializedName("likes_count") public int likesCount;       // 点赞数
    @SerializedName("abilities") public Abilities abilities;    // 当前用户所拥有的权限
    @SerializedName("body") public String body;                 // 回复内容详情


    // topic 或 news 的 id
    @SerializedName(value = "feedId", alternate = { "topic_id", "news_id" })
    public int feedId;

    // topic 或 news 的标题
    @SerializedName(value = "feedTitle", alternate = { "topic_title", "news_title" })
    public String feedTitle;
} public class Sites {

    @SerializedName("name") public String name;
    @SerializedName("id") public int id;
    @SerializedName("sites") public List<Site> sites;

    public static class Site {
        @SerializedName("name") public String name;
        @SerializedName("url") public String url;
        @SerializedName("avatar_url") public String avatarUrl;
    }
} public class State {
    @SerializedName("ok") public int ok;
} public class Token {

    @SerializedName("access_token") public String accessToken;      // 用户令牌(获取相关数据使用)
    @SerializedName("token_type") public String tokenType;          // 令牌类型
    @SerializedName("expires_in") public int expiresIn;             // 过期时间
    @SerializedName("refresh_token") public String refreshToken;    // 刷新令牌(获取新的令牌)
    @SerializedName("created_at") public int createdAt;             // 创建时间
} public class Topic {
    @SerializedName("id") public int id;                                            // 话题 id
    @SerializedName("title") public String title;                                   // 标题
    @SerializedName("created_at") public Date createdAt;                            // 创建时间
    @SerializedName("updated_at") public Date updatedAt;                            // 更新时间
    @SerializedName("replied_at") public Date repliedAt;                            // 最近一次回复时间
    @SerializedName("replies_count") public int repliesCount;                       // 回复总数量
    @SerializedName("node_name") public String nodeName;                            // 节点名称
    @SerializedName("node_id") public int nodeId;                                   // 节点 id
    @SerializedName("last_reply_user_id") public int lastReplyUserId;               // 最近一次回复的用户 id
    @SerializedName("last_reply_user_login") public String lastReplyUserLogin;      // 最近一次回复的用户登录名
    @SerializedName("user") public User user;                                       // 创建该话题的用户
    @SerializedName("deleted") public boolean deleted;                              // 是否已删除
    @SerializedName("excellent") public boolean excellent;                          // 是否加精
    @SerializedName("abilities") public Abilities abilities;                        // 当前用户对该话题拥有的权限
    @SerializedName("body") public String body;                                     // 话题详情(Markdown)
    @SerializedName("body_html") public String bodyHtml;                            // 话题详情(HTML)
    @SerializedName("hits") public int hits;                                        // 浏览次数
    @SerializedName("likes_count") public int likesCount;                           // 点赞数
    @SerializedName("suggested_at") public Date suggestedAt;                        // 置顶(推荐)时间
    @SerializedName("followed") public Boolean followed;                            // 是否关注
    @SerializedName("liked") public Boolean liked;                                  // 是否喜欢
    @SerializedName("favorited") public Boolean favorited;                          // 是否收藏
} public class User implements Parcelable {
    @SerializedName("id") public int id;                                // 用户 id
    @SerializedName("login") public String login;                       // 用户名
    @SerializedName("name") public String name;                         // 昵称
    @SerializedName("avatar_url") public String avatarUrl;              // 头像链接
    @SerializedName("location") public String location;                 // 城市
    @SerializedName("company") public String company;                   // 公司
    @SerializedName("twitter") public String twitter;                   // twitter
    @SerializedName("website") public String website;                   // 网站地址
    @SerializedName("bio") public String bio;                           // 个人介绍
    @SerializedName("tagline") public String tagline;                   // 签名
    @SerializedName("github") public String github;                     // github
    @SerializedName("created_at") public String createdAt;              // 创建时间
    @SerializedName("email") public String email;                       // email
    @SerializedName("topics_count") public int topicsCount;             // 话题数量
    @SerializedName("replies_count") public int repliesCount;           // 回复数量
    @SerializedName("following_count") public int followingCount;       // 关注人数
    @SerializedName("followers_count") public int followersCount;       // 粉丝人数
    @SerializedName("favorites_count") public int favoritesCount;       // 收藏数
    @SerializedName("level") public String level;                       // 等级
    @SerializedName("level_name") public String levelName;              // 等级名称

    protected User(Parcel in) {
        id = in.readInt();
        login = in.readString();
        name = in.readString();
        avatarUrl = in.readString();
        location = in.readString();
        company = in.readString();
        twitter = in.readString();
        website = in.readString();
        bio = in.readString();
        tagline = in.readString();
        github = in.readString();
        createdAt = in.readString();
        email = in.readString();
        topicsCount = in.readInt();
        repliesCount = in.readInt();
        followingCount = in.readInt();
        followersCount = in.readInt();
        favoritesCount = in.readInt();
        level = in.readString();
        levelName = in.readString();
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel in) {
            return new User(in);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(login);
        dest.writeString(name);
        dest.writeString(avatarUrl);
        dest.writeString(location);
        dest.writeString(company);
        dest.writeString(twitter);
        dest.writeString(website);
        dest.writeString(bio);
        dest.writeString(tagline);
        dest.writeString(github);
        dest.writeString(createdAt);
        dest.writeString(email);
        dest.writeInt(topicsCount);
        dest.writeInt(repliesCount);
        dest.writeInt(followingCount);
        dest.writeInt(followersCount);
        dest.writeInt(favoritesCount);
        dest.writeString(level);
        dest.writeString(levelName);
    }
}
import java.util.List;
import io.reactivex.Flowable;
import moe.yukinoneko.diycode.bean.Like;
import moe.yukinoneko.diycode.bean.News;
import moe.yukinoneko.diycode.bean.NewsNode;
import moe.yukinoneko.diycode.bean.Node;
import moe.yukinoneko.diycode.bean.Notification;
import moe.yukinoneko.diycode.bean.Photo;
import moe.yukinoneko.diycode.bean.Reply;
import moe.yukinoneko.diycode.bean.Sites;
import moe.yukinoneko.diycode.bean.State;
import moe.yukinoneko.diycode.bean.Token;
import moe.yukinoneko.diycode.bean.Topic;
import moe.yukinoneko.diycode.bean.User;
import okhttp3.MultipartBody;
import retrofit2.http.DELETE;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import retrofit2.http.Path;
import retrofit2.http.Query;
/*
 * Copyright (c) 2017 SamuelGjk <samuel.alva@outlook.com>
 *
 * This file is part of DiyCode
 *
 * DiyCode is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DiyCode is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DiyCode. If not, see <http://www.gnu.org/licenses/>.
 */

package moe.yukinoneko.diycode.api;



/**
 * Created by SamuelGjk on 2017/3/23.
 */

public interface DiyCodeService {

    /**
     * 获取 Token (一般在登录时调用)
     *
     * @param clientId     客户端 id
     * @param clientSecret 客户端私钥
     * @param grantType    授权方式 - 密码
     * @param username     用户名
     * @param password     密码
     * @return Token 实体类
     */
    @POST(Url.OAUTH_URL)
    @FormUrlEncoded
    Flowable<Token> getToken(@Field("client_id") String clientId, @Field("client_secret") String clientSecret,
                             @Field("grant_type") String grantType, @Field("username") String username,
                             @Field("password") String password);

    /**
     * 刷新 token
     *
     * @param clientId     客户端 id
     * @param clientSecret 客户端私钥
     * @param grantType    授权方式 - Refresh Token
     * @param refreshToken token 信息
     * @return Token 实体类
     */
    @POST(Url.OAUTH_URL)
    @FormUrlEncoded
    Flowable<Token> refreshToken(@Field("client_id") String clientId, @Field("client_secret") String clientSecret,
                                 @Field("grant_type") String grantType, @Field("refresh_token") String refreshToken);

    //--------------------------------------------- Topic ------------------------------------------------------//

    /**
     * 获取 topic 列表
     *
     * @param type   类型，默认 last_actived，可选["last_actived", "recent", "no_reply", "popular", "excellent"]
     * @param nodeId 如果你需要只看某个节点的，请传此参数, 如果不传 则返回全部
     * @param offset 偏移数值，默认值 0
     * @param limit  数量极限，默认值 20，值范围 1..150
     * @return topic 列表
     */
    @GET(Url.TOPICS)
    Flowable<List<Topic>> fetchTopicsList(@Query("type") String type, @Query("node_id") Integer nodeId,
                                          @Query("offset") Integer offset, @Query("limit") Integer limit);

    /**
     * 获取 topic 内容
     *
     * @param id topic 的 id
     * @return 内容详情
     */
    @GET(Url.TOPIC)
    Flowable<Topic> fetchTopic(@Path("id") int id);

    /**
     * 创建一个新的 topic
     *
     * @param title  话题标题
     * @param body   话题内容, Markdown 格式
     * @param nodeId 节点编号
     * @return 新话题的内容详情
     */
    @POST(Url.TOPICS)
    @FormUrlEncoded
    Flowable<Topic> newTopic(@Field("title") String title, @Field("body") String body,
                             @Field("node_id") Integer nodeId);

    /**
     * 收藏话题
     *
     * @param id 被收藏的话题 id
     * @return 状态信息
     */
    @POST(Url.FAVORITE_TOPIC)
    Flowable<State> favoriteTopic(@Path("id") int id);

    /**
     * 取消收藏话题
     *
     * @param id 被收藏的话题 id
     * @return 状态信息
     */
    @POST(Url.UNFAVORITE_TOPIC)
    Flowable<State> unfavoriteTopic(@Path("id") int id);

    //----------------------------------------------------------------------------------------------------------//

    /**
     * 获取 news 列表
     *
     * @param nodeId 如果你需要只看某个节点的，请传此参数, 如果不传 则返回全部
     * @param offset 偏移数值，默认值 0
     * @param limit  数量极限，默认值 20，值范围 1..150
     * @return news 列表
     */
    @GET(Url.NEWS)
    Flowable<List<News>> fetchNewsList(@Query("node_id") Integer nodeId, @Query("offset") Integer offset,