Skip to content

Instantly share code, notes, and snippets.

@duangsuse
Last active May 31, 2018 15:21
Show Gist options
  • Save duangsuse/8b343e8ebe8f625ff74cf3472b94720b to your computer and use it in GitHub Desktop.
Save duangsuse/8b343e8ebe8f625ff74cf3472b94720b to your computer and use it in GitHub Desktop.
GeekApk 后端设计第一版

Complete Documentation of Project GeekApk :: Backend

这是 GeekApk Project 后端的完整文档,包含:

额外定义:

  • 通知/Timeline定义
  • WebSocket API
  • WebHooks 支持
  • 身份验证 模式

API/数据结构:

  • Postgres 表结构、限制和描述 文档
  • JSON RESTFul API 对象 文档
  • GeekApk RESTFul API 文档
  • 使用 PostgreSQL 语言编写的 database migration 程序
  • Diesel Rust Queryable, Insertable 数据结构定义

文档和设计标准

  • 应该尽可能符合 GitHub Styled Markdown 语法规范,使用合适的中文文体并合理使用 斜体 粗体 代码块 链接
  • 粗体 在强调对象描述时使用、斜体 在引用对象时使用、 代码块 在引用代码时使用、如果有必要,可以给 资源 添加链接
  • 不应该有不正确的 缩进、空格、大小写、全半角符号,中文字符(非全角标点)和 数字/英文字符 间必须添加空格

在合适的地方也可以使用 Markdown 引用 添加额外 注意事项

  • 数据库字段的英文单词的 单复数 问题: 数据库表 使用 复数其他 则使用 单数
  • 有可能为字段添加所存储数据模式描述的,则添加描述,如: install_urlicon_urlparent_category
  • 记录 创建时间更新时间 的字段使用命名 created_atupdated_at
  • RDBMS 对象引用字段使用 所引用对象单数名称 为名称,如 userapp
  • PostgreSQL 中,非类型声明的关键字 全大写,类型声明使用 PascalCased,标识符 全小写
  • Postgres 中,可能为 Null 的字段在 Rust 中表示为 Option<T>
  • PostgreSQL 中, 描述数据结构,不要设置除 NOT Null 外的 约束
  • 关于排行所用自动生成字段的问题,必须加 _num
  • 仔细检查 database migration up/down、rust struct 中字段和表的名称是否对应
  • 在数据结构中合理的增加 限制,如 版本名长度 限制
  • 其实这个文档是很可爱的 (´・ω・`)

额外定义

哪些是通知

GeekApk 里,通知 作为一种对 用户 的提醒而存在,一般在 动作执行后 直接保存等待用户阅读,GeekApk 中有这些通知:

  • 用户评论回复 的通知
  • 用户@ 提到 的通知
  • 用户用户 跟随 的通知
  • 用户评论星标 的通知

Timeline(时间线)

类似 GitHub,GeekApk 也会记录每个 用户 的公开活动并允许所有人自由查询,这个特性被称为 Timeline(时间线),GeekApk 中有这些时间线记录:

  • 用户 Follow 了某个 用户
  • 用户 Star 了某个 评论
  • 用户 创建了 某个 评论
  • 用户 更新了 某个 评论
  • 用户 发布了 某个 应用
  • 用户 发布了 某个 应用更新
  • 用户 删除了 某个 应用
  • 用户 Star 了某个 应用

WebSocket API

WebSocket 为 GeekApk 提供了即时通知推送的特性,除此之外还有查询 WebSocket 在线 和发送 即时消息 的能力

GeekApk 服务会把 WebSocket 服务开在 2333 端口上,要建立连接 URL 使用以下格式:

wss://api.geekapk.org:2333/:uid/:passhash

由于推送和送信服务只对 已登录用户 有意义,WebSocket 必须 先验证身份才可以连接

其实这个是可以有状态机描述的,我不想写,这文档也很明了了

发送

  • o 以查询 WebSocket 在线人数,服务器会返回一个 短整数(SmallInt) 的字符串表示如 123220
  • o? + 以分号 ',' 切分的 UID 短整数 列表以查询目标用户是否在线,服务器返回以 '*' 打头的 01 组成的在线状态字符串,其长度等于 UID 列表 的长度,与 UID 列表对应位置的 UID 对应,如 发送 o?12,32,43,32,43 接收 *01010
  • uid:message 以向 UID 发送一条消息,若不在线即收到发送错误

接收

  • 可能是空的字符串,代表 通知 有更新
  • 可能是一个值等于 ERROR 的字符,代表发送操作出现错误
  • 可能是一个数字字符串,代表 o 的查询结果
  • 可能是一个以 '*' 打头的字符串,代表 o? 的查询结果
  • 可能是一个包含 ':' 的字符串,在 ':' 前的部分为发送者 UID,后面的部分为 消息

WebHooks

GeekApk 可以与 第三方服务 进行 集成,服务端使用的支持方式就是 WebHooks

WebHooks 可以让 GeekApk 服务器在进行某种操作后 通知 外部服务进行相应的处理

GeekApk 目前支持 3WebHooks

  • replyToMessage 在回复指定 评论 时触发
  • commentApp 在回复指定 应用 时触发
  • newUser 在添加一个 用户 时触发

GeekApk 服务器内部使用 环境变量 存储 WebHooks 设置,同时,要应用新 WebHooks 设置需要 重启服务器

WEBHOOKS='replyToMessage:2333:https://bar.org/bot;commentApp:23:https://geekbot.com/webhook;newUser:https://webhooks.org/bot;'

触发时 GeekApk 服务器使用 POSTHTTP 方法,相应 对象IDPOST body 请求目标地址

如果请求失败,错误记录只会被打印在服务程序的 标准错误输出

身份验证和权限管理

GeekApk 使用 基于角色 的权限系统,验证需要的令牌保存在 cookie

GeekApk 有以下 3 种角色:

  • 权限汪 🐶(确信)
  • 用户
  • 未登录用户

无论是 权限汪用户 还是 未登录用户 实体都可以有多个

权限细则

权限汪(独立于用户的概念) < 未登录用户

权限汪不一定需要有一个 GeekApk 账户,实际上,权限汪只需要服务器的 管理令牌 就可以验证自己的身份

这也意味着权限汪其实只代表了 GeekApk 管理人员普通用户 的权限,但它没有普通用户所拥有的权限 233

  • 权限汪可以创建/删除 用户
  • 权限汪可以修改 用户分发密码
  • 权限汪可以停用/激活 用户
  • 权限汪可以创建/修改/删除 分类
  • 权限汪可以删除 评论
  • 权限汪可以删除 应用

权限汪需要知道服务器根据启动时 DOGETOK 环境变量设置的密码并在请求相应 管理 API 时作为 cookie 参数 doge_token 填写

用户 < 未登录用户
  • 用户不能创建 用户
  • 用户不能创建 分类
  • 用户可以 创建 未禁止创建的 实体修改/删除 自己所创建的 实体notification 记录
  • 用户可以 登录 WebSocket 平台

用户需要使用 分发密码 创建一个自己的 密码(内部表示为 passhash

在创建之后,用户也可以使用 分发密码(内部表示为 metapass)重置自己的密码

WebSocket 验证方式参见上文 WebSocket API,请求需要 验证身份 的 API 时,必须携带 geekapk_uidgeekapk_passhash 两个 cookie 来验证自己的身份,服务器 不会猜测 你需要使用的用户身份

未登录用户

除了 只读访问登录 WebSocket 平台 外没有其它限制

后端数据结构设计

GeekApk 包含的 对象 数据设计

中文名 实体名 表名 ID 描述
用户 user users uid GeekApk 用户帐号
分类 category categories tid GeekApk 应用分类
应用 app apps aid GeekApk 应用
评论 comment comments cid GeekApk 评论

对象的辅助表:

中文名 实体名 表名 所属对象 描述
跟随 follow 用户 用户跟随
密码 _security 用户 用户密码
更新 update updates 应用 应用更新
星标 stars 应用 应用星标
评论星标 comment_stars 评论 评论星标
时间线 timeline timelines 用户 时间线记录
通知 notification notifications 用户 通知条目

用户 对象关系:

  • 只能有一个 密码
  • 可以有很多个 应用
  • 可以有很多条 评论
  • 可以有很多条 跟随
  • 可以有很多个 星标
  • 可以有很多个 评论星标
  • 可以有很多条 时间线
  • 可以有很多条 通知

分类 对象关系:

  • 只能有一个 父 分类
  • 可以包含很多个 应用

应用 对象关系:

  • 只能有一个创建人 用户
  • 只能有一个归属 分类
  • 可以有很多条 评论
  • 可以有很多条 更新
  • 可以有很多条 星标

评论 对象关系:

  • 只能有一个创建人 用户
  • 只能有一个评论目标 应用
  • 只能有一个回复目标 评论
  • 可以有很多个 评论星标

排行设计:

  • 用户 可以按 创建时间、上线时间、跟随者人数 排行
  • 应用 可以按 创建时间、更新时间、星标数、评论数、体积 徘行
  • 评论 可以按 创建时间、更新时间、评论星标数、回复数 排行

分页设计: 时间线、评论、用户、应用 可以设置返回的 最大条数

检索设计:

  • 用户 可以用 简单名、用户名、别名、GitHub、自述、开发者自述 检索
  • 应用 可以用 应用名、包名、描述 检索
  • 评论 可以用 内容 检索

考虑到清晰度的原因,设计上不会添加 rate limit,但实践中有可能在文档规定外添加一定的限制

详细数据结构和限制

SmallSerialSerial 本质上不是一个类型,这里为了方便将它作为一个类型,希望大家能理解原意

用户

字段名 类型 限制
id SmallSerial PRIMARY KEY
simple_name VarChar 非空、长度小于 20 个字符、只能包含 [A-z][a-z][0-9]_ 用户的机器可读名称
avatar_url VarChar 长度小于 500 字符 用户的头像 URL
user_name VarChar 非空、长度小于 100 字符 用户名
alias VarChar 长度小于 50 字符 用户别名
github VarChar 长度小于 50 字符 GitHub 用户名
bio VarChar 非空、长度小于 500 字符 DEFAULT '' 用户自我介绍
dev_bio VarChar 长度小于 500 字符 作为开发者的自我介绍
created_at TimeStamp 非空 DEFAULT now() 用户创建时间
online_at TimeStamp 非空 DEFAULT now() 用户最近上线时间,由用户手动更新
followers_num SmallInt 非空 DEFAULT 0 用户的跟随者数目
enabled Boolean 非空 DEFAULT true 用户是否启用

分类

字段名 类型 限制
id SmallSerial PRIMARY KEY
category_name VarChar 非空 分类名,因为只有内部人员操作不加限制
parent_category SmallInt 分类

应用

字段名 类型 限制
id SmallSerial PRIMARY KEY
author_user SmallInt 非空 创建者 UID
category SmallInt 非空 归属 TID
package_name VarChar 长度小于 60 字符 包名
app_name VarChar 非空、长度小于 60 字符 应用名
alias VarChar 长度小于 60 字符 别名
icon_url VarChar 长度小于 500 字符 图标 URL
app_description VarChar 非空、长度小于 10000 字符 DEFAULT '' 应用描述
visualizer VarChar 长度小于 20 字符 应用模型视图
button_text VarChar 长度小于 60 字符 安装卸载按钮 文本覆盖
special VarChar 长度小于 12 字符 特殊标识
previews VarChar 长度小于 4000 字符 ';' 切分的预览图 URL
app_permissions VarChar 长度小于 10000 字符 '\n' 切分的权限列表
size Integer 非空 DEFAULT 0 应用安装包以 百字节 计体积
created_at TimeStamp 非空 DEFAULT now() 创建时间
updated_at TimeStamp 非空 DEFAULT now() 更新时间
stars_num SmallInt 非空 DEFAULT 0 星标数
comments_num Integer 非空 DEFAULT 0 评论数

评论

字段名 类型 限制
id Serial PRIMARY KEY
author_user SmallInt 非空 创建人 UID
app SmallInt 非空 评论 AID
reply_comment Integer 回复 CID
content VarChar 非空、长度小于 7000 字符 评论内容
stars_num SmallInt 非空 DEFAULT 0 星标数
replies_num Integer 非空 DEFAULT 0 回复数
created_at TimeStamp 非空 DEFAULT now() 创建时间
updated_at TimeStamp 修改时间

跟随

字段名 类型 限制
user SmallInt 非空 跟随者 UID
followed_user SmallInt 非空 被跟随者 UID

密码

字段名 类型 限制
user SmallInt PRIMARY KEY 目标用户
metapass VarChar 非空 分发密码
passhash VarChar SHA-256 密码取样

更新

字段名 类型 限制
app SmallInt 非空 目标 AID
version_name VarChar 非空,长度小于 40 字符 版本名
reversion SmallInt 非空 修订号
install_url VarChar 非空,长度小于 500 字符 安装 GFC
updates VarChar 非空,长度小于 6000 字符 更新内容
api_min SmallInt 最低 SDK 版本
api_target SmallInt 目标 SDK 版本

星标

字段名 类型 限制
user SmallInt 非空 操作 用户
app SmallInt 非空 目标 应用

评论星标

字段名 类型 限制
user SmallInt 非空 操作 用户
comment Integer 非空 目标 评论

时间线

字段名 类型 限制
user SmallInt 非空 用户
created_at TimeStamp 非空 DEFAULT now() 创建时间
line_type SmallInt 非空 时间线类型
line_data Integer 非空 时间线数据

通知

字段名 类型 限制
user SmallInt 非空 用户
created_at TimeStamp 非空 DEFAULT now() 创建时间
notification_type SmallInt 非空 通知类型
notification_data Integer 非空 通知数据
enabled Boolean 非空 DEFAULT false 已经阅读

PostgreSQL

用户 PSQL

CREATE TABLE users(
    id SmallSerial PRIMARY KEY,
    simple_name VarChar NOT Null,
    avatar_url VarChar,
    user_name VarChar NOT Null,
    alias VarChar,
    github VarChar,
    bio VarChar NOT Null DEFAULT '',
    dev_bio VarChar,
    created_at TimeStamp NOT Null DEFAULT now(),
    online_at TimeStamp NOT Null DEFAULT now(),
    followers_num SmallInt NOT Null DEFAULT 0,
    enabled Boolean NOT Null DEFAULT true
)
DROP TABLE users

分类 PSQL

CREATE TABLE categories(
    id SmallSerial PRIMARY KEY,
    category_name VarChar NOT Null,
    parent_category SmallInt
)
DROP TABLE categories

应用 PSQL

CREATE TABLE apps(
    id SmallSerial PRIMARY KEY,
    author_user SmallInt NOT Null,
    category SmallInt NOT Null,
    package_name VarChar,
    app_name VarChar NOT Null,
    alias VarChar,
    icon_url VarChar,
    app_description VarChar NOT Null DEFAULT '',
    visualizer VarChar,
    button_text VarChar,
    special VarChar,
    previews VarChar,
    app_permissions VarChar,
    size Integer NOT Null DEFAULT 0,
    created_at TimeStamp NOT Null DEFAULT now(),
    updated_at TimeStamp NOT Null DEFAULT now(),
    stars_num SmallInt NOT Null DEFAULT 0,
    comments_num Integer NOT Null DEFAULT 0
)
DROP TABLE apps

评论 PSQL

CREATE TABLE comments(
    id Serial PRIMARY KEY,
    author_user SmallInt NOT Null,
    app SmallInt NOT Null,
    reply_comment Integer,
    content VarChar NOT Null,
    stars_num SmallInt NOT Null DEFAULT 0,
    replies_num Integer NOT Null DEFAULT 0,
    created_at TimeStamp NOT Null DEFAULT now()
    updated_at TimeStamp
)
DROP TABLE comments

跟随 PSQL

CREATE TABLE follow(
    user SmallInt NOT Null,
    followed_user SmallInt NOT Null
)
DROP TABLE follow

密码 PSQL

CREATE TABLE _security(
    user SmallInt PRIMARY KEY,
    metapass VarChar NOT Null,
    passhash VarChar
)
DROP TABLE _security

更新 PSQL

CREATE TABLE updates(
    app SmallInt NOT Null,
    version_name VarChar NOT Null,
    reversion SmallInt NOT Null,
    install_url VarChar NOT Null,
    updates VarChar NOT Null,
    api_min SmallInt,
    api_target SmallInt
)
DROP TABLE updates

星标 PSQL

CREATE TABLE stars(
    user SmallInt NOT Null,
    app SmallInt NOT Null
)
DROP TABLE stars

评论星标 PSQL

CREATE TABLE comment_stars(
    user SmallInt NOT Null,
    comment Integer NOT Null
)
DROP TABLE comment_stars

时间线 PSQL

CREATE TABLE timelines(
    user SmallInt NOT Null,
    created_at TimeStamp NOT Null DEFAULT now(),
    line_type SmallInt NOT Null,
    line_data Integer NOT Null
)
DROP TABLE timelines

通知 PSQL

CREATE TABLE notifications(
    user SmallInt NOT Null,
    created_at TimeStamp NOT Null DEFAULT now(),
    notification_type SmallInt NOT Null,
    notification_data Integer NOT Null,
    enabled Boolean NOT Null DEFAULT false
)
DROP TABLE notifications

对应的 Rust 结构

用户 结构

#[derive(Queryable)]
pub struct User {
    id: i16,
    simple_name: String,
    avatar_url: Option<String>,
    user_name: String,
    alias: Option<String>,
    github: Option<String>,
    bio: String,
    dev_bio: Option<String>,
    created_at: SystemTime,
    online_at SystemTime,
    followers_num: i16,
    enabled: bool
}
#[derive(Insertable)]
#[table_name="users"]
pub struct NewUser<'a> {
    simple_name: String,
    avatar_url: Option<String>,
    user_name: String,
    alias: Option<String>,
    github: Option<String>,
    bio: String,
    dev_bio: Option<String>
}

分类 结构

#[derive(Queryable)]
pub struct Category {
    id: i16,
    category_name: String,
    parent_category: Option<i16>
}
#[derive(Insertable)]
#[table_name="categories"]
pub struct NewCategory<'a> {
    category_name: String,
    parent_category: Option<i16>
}

应用 结构

#[derive(Queryable)]
pub struct App {
    id: i16,
    author_user: i16,
    category: i16,
    package_name: Option<String>,
    app_name: String,
    alias: Option<String>,
    icon_url: Option<String>,
    app_description: String,
    visualizer: Option<String>,
    button_text: Option<String>,
    special: Option<String>,
    previews: Option<String>,
    app_permissions: Option<String>,
    size: i32,
    created_at: SystemTime,
    updated_at: SystemTime,
    stars_num: i16,
    comments_num: i32
}
#[derive(Insertable)]
#[table_name="apps"]
pub struct NewApp<'a> {
    author_user: i16,
    category: i16,
    package_name: Option<String>,
    app_name: String,
    alias: Option<String>,
    icon_url: Option<String>,
    app_description: String,
    visualizer: Option<String>,
    button_text: Option<String>,
    special: Option<String>,
    previews: Option<String>,
    app_permissions: Option<String>,
    size: i32
}

评论 结构

#[derive(Queryable)]
pub struct Comment {
    id: i32,
    author_user: i16,
    app: i16,
    reply_comment: Option<i32>,
    content: String,
    stars_num: i16,
    replies_num: i32,
    created_at: SystemTime,
    updated_at: Option<SystemTime>
}
#[derive(Insertable)]
#[table_name="comments"]
pub struct NewComment<'a> {
    author_user: i16,
    app: i16,
    reply_comment: Option<i32>,
    content: String
}

跟随 结构

#[derive(Queryable)]
#[table_name="follow"]
pub struct Follow {
    user: i16,
    followed_user: i16
}
#[derive(Insertable)]
#[table_name="follow"]
pub struct NewFollow<'a> {
    user: i16,
    followed_user: i16
}

密码 结构

#[derive(Queryable)]
#[table_name="_security"]
pub struct Security {
    user: i16,
    metapass: String,
    passhash: Option<String>
}
#[derive(Insertable)]
#[table_name="_security"]
pub struct NewSecurity<'a> {
    user: i16,
    metapass: String,
    passhash: Option<String>
}

更新 结构

#[derive(Queryable)]
pub struct Update {
    app: i16,
    version: String,
    reversion: i16,
    install_url: String,
    updates: String,
    api_min: Option<i16>,
    api_target: Option<i16>
}
#[derive(Insertable)]
#[table_name="updates"]
pub struct NewUpdate<'a> {
    app: i16,
    version: String,
    reversion: i16,
    install_url: String,
    updates: String,
    api_min: Option<i16>,
    api_target: Option<i16>
}

星标 结构

#[derive(Queryable)]
pub struct Star {
    user: i16,
    app: i16
}
#[derive(Insertable)]
#[table_name="stars"]
pub struct NewStar<'a> {
    user: i16,
    app: i16
}

评论星标 结构

#[derive(Queryable)]
pub struct CommentStar {
    user: i16,
    comment: i32
}
#[derive(Insertable)]
#[table_name="comment_stars"]
pub struct NewCommentStar<'a> {
    user: i16,
    comment: i32
}

时间线 结构

#[derive(Queryable)]
pub struct Timeline {
    user: i16,
    created_at: SystemTime,
    line_type: i16,
    line_data: i32
}
#[derive(Insertable)]
#[table_name="timelines"]
pub struct NewTimeline<'a> {
    user: i16,
    line_type: i16,
    line_data: i32
}

通知 结构

#[derive(Queryable)]
pub struct Notification {
    user: i16,
    created_at: SystemTime,
    notification_type: i16,
    notification_data: i32,
    enabled: bool
}
#[derive(Insertable)]
#[table_name="notifications"]
pub struct NewNotification<'a> {
    user: i16,
    notification_type: i16,
    notification_data: i32,
}

RESTFul API

如果请求使用数据的长度过长,返回 413 Payload Too Large

如果验证失败,返回 401 Unauthorized

如果找不到资源,返回 404 Not Found

如果请求类型不合适,返回 415 Unsupported Media Type

如果内容解析失败,返回 400 Bad Request

其他 API

额外访问 密码 表的内容

主页

GET / 返回主页 web.html

版本查询

GET /version 返回以 ':' 分割的 API 版本、程序版本

Ping

GET /ping 返回你的 IP 地址

Validate

以 metapass 为 body POST /validate-metapass/<uid> 获得验证是否通过(200/非 200)

以 passhash 为 body POST /validate/<uid> 获得验证是否通过(200/非 200)

修改密码

以分发密码为 body,PUT /pass/<uid> 可以创建/更新用户密码

如果成功,返回 200 OK

如果验证失败,返回 401 Unauthorized

如果找不到用户,返回 404 Not Found

WebHooks API

GET /webhooks 查询 WebHooks 配置

[
    {
        "type": "replyToMessage",
        "data": 2333,
        "url": "https://bar.org/bot"
    }
]

Admin API

以下 API 都需要 权限汪 访问权限

如果验证失败,返回 401 Unauthorized

创建用户

POST /doge/useradd

body 包含

simple_name: string,
avatar_url: string / null,
user_name: string / null,
alias: string / null,
github: string,
bio: string(optional),
dev_bio: string / null

如果返回码为 201 Created,body 就应该是以 ':' 切分的被创建的用户 UID 文本表示和 metapass

删除用户

DELETE /doge/user/<uid>

如果成功删除,返回 410 Gone

如果找不到用户,返回 404 Not Found

改变用户停用状态

PUT /doge/user/<uid>

如果成功,则返回 200 OK 和 Json

例如,

{
    "uid": 213,
    "enabled": true
}

如果找不到用户,返回 404 Not Found

修改分发密码

以新 metapass 为 body PUT /doge/user/<uid>/metapass

如果找不到用户,返回 404 Not Found

如果成功,则返回 200 OK 和 Json

例如,

{
    "uid": 233,
    "old-metapass": "old",
    "metapass": "new"
}
分类管理
CREATE

以分类名为 body POST /doge/category/<parent>

如果成功,返回 200 OK 和已创建 CID 文本表示

UPDATE

以新分类名为 body PUT /doge/category/<tid>

以新父分类为 body PUT /doge/category/<tid>/parent

如果成功,返回 200 OK 和 Json

例如,

{
    "tid": 32,
    "name": "实用工具",
    "parent": 3
}
DELETE

DELETE /doge/category/<tid>

如果成功,返回 410 Gone

删除评论

DELETE /doge/comment/<cid>

如果有子评论,删除评论也会在应用 0 下以被删除所有者身份新建顶级评论 Replies Deleted from {aid} (reply to {reply_comment}) 并将所有子评论的 reply_comment 字段修改为 该评论 ID 并且把 app 字段修改为 0,直接被删除的内容不会保留

DELETE /doge/comment/<cid>

如果添加 url 参数 recursive 则递归删除所有子评论

如果成功,返回 410 Gone

如果没找到评论,返回 404 Not Found

删除应用

DELETE /doge/comment/<cid>

如果有评论,在应用 0 下以应用发布者身份创建顶级评论 Comments Deleted from {aid} 并将所有评论的 app 字段修改为 0reply_comment 修改为评论的 cid

如果添加 url 参数 recursive 则递归删除所有评论

如果成功,返回 410 Gone

如果没找到评论,返回 404 Not Found

用户 API

额外访问 跟随 表的内容

GET /user/<uid> 可以获取目标用户的 User JSON,如果使用 short 参数就不传输一些字段(简短 JSON)

GET /user/all 可以获得全站用户 UID JSON 列表,参数

  • max=num 可以设置最大返回条数
  • s=ctime 可以设置以创建时间排行
  • s=otime 可以设置以上线时间排行
  • s=followers 可以设置以跟随人数徘行
  • m=asc/dsc 以设置是 asc 正序还是 dsc 倒序,默认正序

以关键字为 body POST /user/search 以搜索用户,返回用户 UID JSON 列表,参数

  • mode=sname/name/alias/github/bio/dev_bio简单名、用户名、别名、GitHub、自述、开发者自述 搜索
  • max=num 可以设置最大返回条数
  • s=ctime 可以设置以创建时间排行
  • s=otime 可以设置以上线时间排行
  • s=followers 可以设置以跟随人数徘行
  • m=asc/dsc 以设置是 asc 正序还是 dsc 倒序,默认正序

GET /user/<uid>/followers 可以获取目标用户的跟随者 用户 UID JSON 列表,默认排行

GET /user/<uid>/following 可以获取目标用户的跟随 用户 UID JSON 列表,默认排行

GET /user/<uid>/follow 返回 follow 状态 true/false

PUT /user/<uid>/follow 改变 follow 状态,返回新状态 true/false

GET /user/<uid>/online 可以获取用户上线时间

GET /user/<uid>/apps 可以获取用户的应用 AID JSON 列表,以更新时间排行

GET /user/<uid>/comments 可以获取用户的评论 CID JSON 列表,以发布时间排行

GET /user/<uid>/stars 可以获得用户的星标应用 AID JSON 列表

GET /user/<uid>/cstars 可以获得用户的星标评论 CID JSON 列表

GET /user/<uid>/timeline 可以获得用户的时间线 JSON 对象列表,参数

  • max=num 设置最大返回条数

GET /user/<uid>/notifications 可以获得用户的通知 JSON 对象列表,需要验证

  • all 参数以返回已阅消息

以 User JSON 为 body PUT /user/<uid> 可以更新目标用户除 id, created_at, followers_num, enabled 外的信息

PUT /user/<uid>/online 可以更新上线时间为当前时间

DELETE /user/<uid> 可以删除自己,言论和应用不会删除

分类 API

GET /category/all 获取所有分类 JSON 列表

GET /category/<tid> 获取这个分类的 JSON 对象

GET /category/<tid>/parent 获取这个分类的父分类

GET /category/<tid>/apps 获取这个分类的应用 AID JSON 列表,参数

  • max=num 条数限制
  • m=asc/dsc 以设置是 asc 正序还是 dsc 倒序,默认正序
  • s=ctime/updated/star/replies/size创建时间、更新时间、星标数、评论数、体积 排序

以关键字为 body POST /category/<tid>/search 在分类中搜索应用,返回 AID JSON 列表,参数

  • max=num 条数限制
  • s=name/pkg/desc 检索类型,应用名、包名、描述

应用 API

额外访问 星标 表的内容

以包含 author_user, category, package_name(optional), app_name, alias(optional), icon_url(optional), app_description, visualizer(optional), button_text(optional), special(optional), previews(optional), app_permissions(optional), size 的 App JSON 为 body POST /app 创建应用,返回应用 AID

GET /app/all 获取所有应用 AID JSON 列表,按更新时间排序

GET /app/<aid> 获取 App JSON,可选 short 参数获取简版对象

GET /app/<aid>/stars 获取 star 的用户 UID JSON 列表

GET /app/<aid>/star 查询星标状态,返回 true/false

PUT /app/<aid>/stars 以星标/取消星标应用,返回新状态 true/false

GET /app/<aid>/comments 获取评论列表,参数

  • max=num 条数限制
  • s=ctime/utime/stars/replies 创建时间、更新时间、评论星标数、回复数 排行

GET /app/<aid>/updates 获取更新 JSON 对象列表,以 reversion 排行

  • max=num 条数限制

以包含 version_name, reversion, install_url, updates, api_min(optional), api_target(optional) 的 Update JSON 为 body POST /app/<aid>/update 创建更新

以包含 reply_comment, content 的 comment JSON POST /app/<aid>/comment 创建评论,返回评论 CID

以 App JSON 为 body PUT /app/<aid> 更新应用的非 id, author_user, created_at, updated_at, stars_num, comments_num 字段

以关键字为 body POST /app/search 搜索应用,返回 AID JSON 列表,参数

  • max=num 条数限制
  • s=name/pkg/desc 检索类型,应用名、包名、描述

DELETE /app/<aid> 以删除应用,评论将被迁移到特殊应用 0 的评论下

评论 API

额外访问 评论星标 表的内容

GET /comment/all 获取创建时间排行的全站 CID JSON 列表

GET /comment/<cid> 获取评论 JSON 对象

以新内容为 body PUT /comment/<cid> 更新评论内容

GET /comment/<cid>/star 查询星标状态,返回 true/false

PUT /comment/<cid>/star 以星标/取消星标评论,返回新状态 true/false

GET /comment/<cid>/replies 获取回复评论的 CID JSON 列表

GET /comment/<cid>/stars 获取星标用户 UID JSON 列表

以关键字为 body POST /comment/search 搜索评论,返回 CID JSON 列表,参数

  • max=num 条数限制

DELETE /comment/<cid> 删除评论,子评论会被迁移

更新 API

以 App JSON 为 body PUT /updates/<aid>/<reversion> 更新 version_name, install_url, updates, api_min, api_target

DELETE /updates/<aid>/<reversion> 以删除指定 reversion

GET /updates/<aid> 以获得 reversion 数目

时间线 API

GET /timeline 获取全站时间线 Timeline JSON 对象列表

  • max=num 限制条数

通知 API

POST /notification/<uid>/<cid> 新建一个 @

PUT /notification/<uid>/<created> 更新 enabled 状态,返回新状态 true/false

DELETE /notification/<uid>/<created> 删除目标通知

RESTFul JSON 对象

用户 JSON

字段名 类型 描述
id number 用户 UID
simple_name string 用户简名
avatar_url string / null 用户头像链接
name string 用户名
alias string / null 用户别名
github string / null github 名
bio string 介绍(可省略)
dev_bio string / null 开发者介绍(可省略)
created_at number(datetime) 创建时间
online_at number(datetime) 上线时间
followers_num number 跟随人数
enabled boolean 启用状态

User Examples

{
    "id": 3,
    "simple_name": "rachel030219",
    "avatar_url": "https://avatars1.githubusercontent.com/u/13704467?s=460&v=4",
    "name": "Rachel",
    "alias": null,
    "github": "Rachel030219",
    "bio": "Rachel 坏耶",
    "dev_bio": "Code? Is that edible?",
    "created_at": 1527689792253,
    "online_at": 1527689792253,
    "followers_num": 15,
    "enabled": true
}
{
    "id": 233,
    "simple_name": "yuuta",
    "avatar_url": "https://avatars0.githubusercontent.com/u/17158086?s=460&v=4",
    "name": "Yuuta",
    "alias": "Trumeet",
    "github": "Trumeet",
    "bio": "Trumeet 好耶",
    "dev_bio": null,
    "created_at": 1527689792353,
    "online_at": 1527689795253,
    "followers_num": 200,
    "enabled": true
}
{
    "id": 234,
    "simple_name": "pandecheng",
    "avatar_url": "https://avatars0.githubusercontent.com/u/26184272?s=460&v=4",
    "name": "pandecheng",
    "alias": null,
    "github": "pandecheng36",
    "bio": "",
    "dev_bio": "女装大佬,图标包高产赛 **,日常修图改图",
    "created_at": 1527689892353,
    "online_at": 1527689995253,
    "followers_num": 200,
    "enabled": false
}

小潘日常被管理欺负

分类 JSON

字段名 类型 描述
id number 分类 TID
name string 分类名
parent number 父分类 TID

Category Examples

{
    "id": 1,
    "name": "应用",
    "parent": null
}
{
    "id": 2,
    "name": "工具",
    "parent": 1
}
{
    "id": 3,
    "name": "编辑器",
    "parent": 2
}

应用 JSON

字段名 类型 描述
id number 应用 AID
author number 所有者 UID
category number 分类 TID
package string / null 包名
name string 应用名
alias string / null 别名
icon_url string / null 图标链接
desc string 描述(可省略)
visual string / null 展示器名(可省略)
button string / null 按钮文本覆盖(可省略)
special string / null 特殊文本
previews string / null 预览 url 文本(可省略)
permissons string / null 权限(可省略)
size number 安装包大小
created_at number(datetime) 创建时间
updated_at number(datetime) 更新时间
stars_num number 星标数目
comments_num number 评论数目

App Examples

{
    "id": 1,
    "author": 2,
    "category": 3,
    "package": "com.drakeet.purewriter",
    "name": "纯纯写作",
    "alias": "Pure Writer",
    "icon_url": ":coolapk",
    "desc": ":apkpure",
    "visual": null,
    "button": null,
    "special": "永不打折降价",
    "previews": ":coolapk",
    "permissions": ":coolapk",
    "size": 23333,
    "created_at": 0,
    "updated_at": 0,
    "stars_num": 500,
    "comments_num": 100
}
{
    "id": 3,
    "author": 233,
    "category": 7,
    "package": "kh.android.dir",
    "name": "Dir",
    "alias": null,
    "icon_url": ":coolapk",
    "desc": ":apkpure",
    "visual": null,
    "button": "获取~/删除 QAQ/Getting...",
    "special": null,
    "previews": ":coolapk",
    "permissions": ":coolapk",
    "size": 23333,
    "created_at": 0,
    "updated_at": 0,
    "stars_num": 500,
    "comments_num": 100
}
{
    "id": 5,
    "author": 0,
    "category": 12,
    "package": "org.geekapk.virtual.news.android-pill",
    "name": "Android Pill",
    "alias": "药丸的 Android",
    "icon_url": "https://example.org/favicon.ico",
    "desc": "日常放送一点 :pill: 的 Android 资讯",
    "visual": "news",
    "button": null,
    "special": null,
    "previews": "",
    "permissions": "",
    "size": 0,
    "created_at": 0,
    "updated_at": 0,
    "stars_num": 700,
    "comments_num": 100
}

评论 JSON

字段名 类型 描述
id number 评论 CID
author number 所有者 UID
app number 所在 AID
reply number / null 回复给 CID 或不是回复
content string 内容
stars_num number 星标数目
replies_num number 回复数目
created_at number(datetime) 创建时间
updated_at number(datetime) / null 更新时间或没有更新过

Comment Examples

{
    "id": 306,
    "author": 233,
    "app": 1,
    "reply": null,
    "content": "好耶(跑",
    "stars_num": 0,
    "replies_num": 0,
    "created_at": 1527693014709,
    "updated_at": null
}
{
    "id": 500,
    "author": 234,
    "app": 5,
    "reply": 451,
    "content": "这个厉害了&em@doge/smile!&",
    "stars_num": 4,
    "replies_num": 0,
    "created_at": 1527693014809,
    "updated_at": null
}
{
    "id": 62,
    "author": 3,
    "app": 3,
    "reply": null,
    "content": "&em@emoji/fish!&",
    "stars_num": 0,
    "replies_num": 0,
    "created_at": 1527693113700,
    "updated_at": 1527693113809
}

更新 JSON

字段名 类型 描述
app number 更新目标 AID
ver string 版本名
rev number 修订号
install_url string 安装链接
updates string 更新内容
api_min number / null 最低兼容 Android API 版本
api_target number / null 目标 Android API 版本

Update Examples

{
    "app": 1,
    "ver": "3.0.0",
    "rev": 14,
    "install_url": "coolapk:com.drakeet.purewriter",
    "updates": ":coolapk",
    "api_min": 17,
    "api_target": 24
}

时间线 JSON

字段名 类型 描述
u number 用户 UID
t number 时间线类型
d number 数据
c number(datetime) 创建日期

Timeline Examples

{
    "u": 233,
    "t": 8,
    "d": 1,
    "c": 1527693113809
}

通知 JSON

字段名 类型 描述
user number 用户 UID
created_at number(datetime) 创建时间
type number 通知类型
data number 数据
enabled boolean 是否已阅

Notification Examples

{
    "user": 233,
    "created_at": 1527693113809,
    "type": 1,
    "data": 542,
    "enabled": false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment