Skip to content

Instantly share code, notes, and snippets.

@duangsuse
Last active May 17, 2018 03:04
Show Gist options
  • Save duangsuse/6347abbcc9dea4fa58e3a91231cb443f to your computer and use it in GitHub Desktop.
Save duangsuse/6347abbcc9dea4fa58e3a91231cb443f to your computer and use it in GitHub Desktop.
GeekApk 最近设计变更

以下是 GeekApk 后端服务器所提供的 HTTP API,版本 1 GeekApk Center 服务 API 地址

Misc

  • GET / 返回 <html><h1>GeekApk API Server v{Server Version}</h1></html>

  • GET /version 返回以 : 分割的 API 版本和服务器程序版本

  • GET /ping 返回 GeekApk 服务器所见你的 IP 地址

  • GET /admins 返回以 : 分割的站点管理员 UID

  • GET /config/topic 返回话题特殊分类的 ID

  • GET /config/headline 返回头条特殊应用的 ID

  • GET /config/album 返回应用集特殊分类的 ID

  • GET /config/news 返回新闻特殊应用的 ID

  • POST /admin/:username 新建用户,返回用户 id 和 Hash,需要参数 &uid&token

  • PUT /admin/:username 修改用户 Hash,body 为 hash,需要参数 &uid&token

  • DELETE /admin/:username 删除用户,需要参数 &uid&token

Token 管理

Token 是 GeekApk 进行身份验证的一种方式

  • GET /token/:uid 需要一个 hash 参数作为请求用户的 hash,返回用户所有令牌
  • POST /token/:uid 需要一个 hash 参数身份验证,可选是否是持久化令牌 &p(✓ 或 ✗) 和 access level &l(10 以内的数字), body 为令牌内容,内容不能与现存内容冲突
  • DELETE /token/:uid 需要 hash 参数验证,body 为令牌内容
  • POST /token/:uid/check body 为令牌内容,返回令牌访问级别

令牌 JSON 对象

{
  "token": "{token}",
  "ctime": "{ctime datetime}",
  "access": "access_level_integer"
}

访问级别

其实也可以用二进制位运算设置 flag, 不过为了方便就只做了这些

  • 0 默认访问级别,拥有所有权限
  • 1 有修改用户资料的权限
  • 2 有发布修改删除消息的权限
  • 3 有发布修改删除应用的权限
  • 4 有检查用户资料的权限
  • 5 有删除用户的权限
  • 6 没有任何权限,只能用于检查用户对帐号的所有权

User

  • POST /user/search 参数 &t(name, alias, bio) body 为检索内容
  • GET /user/:uid 可以是 all, 参数 &fil (super, email, alias, bio, dev) &sort(ctime, atime, followed following) &dsc
  • PUT /user/:uid 需要 &token &uid body=对象
  • DELETE /user/:uid 需要 &token &uid

JSON

{
  "id": "id_int",
  "name": "name",
  "alias": "alias",
  "emali": "email",
  "github": "github",
  "super": "super_int",
  "bio": "bio",
  "dev_bio": "dev_bio",
  "ctime": "ctime_datetime",
  "atime": "atime_datetime",
  "following": "following_num",
  "followed": "followed_num",
  "avatar": "avatar"
}

Follow

  • GET /follow/:id
  • GET /follow/:id/following
  • POST /follow/:id 需要 &token &uid
  • DELETE /follow/:id 需要 &token &uid

Comment

  • POST /comment/search body 为检索内容
  • GET /comment/:id 返回 Comment 对象
  • GET /comment/app/:app (all) 可选 &user &sort(star like reply created updated) &toplev(✓ 或 ✗) &s(since Unix 时间)
  • POST /comment/:app 参数 &uid &token 可选 reply body 为 content 返回 id
  • PUT /comment/:id &token body 为 content
  • DELETE /comment/:id &token

JSON

{
  "id": "id_int",
  "user": "user_int",
  "target": "target_int",
  "ctime": "ctime_datetime",
  "mtime": "mtime_datetime_null",
  "reply": "reply_int_null",
  "content": "content",
  "stars": "stars_int",
  "likes": "likes_int",
  "replies": "replies_int"
}

CommentStar

  • GET /comment/:id/star 返回 star 用户 id 以 : 分割
  • GET /user/:id/cstar 返回用户的 stars
  • POST /comment/:id/star 需要参数 uid 和 token
  • DELETE /comment/:id/star 需要参数 uid 和 Token

CommentLike

  • GET /comment/:id/like 返回 like 用户 id 以 : 分割
  • GET /user/:id/like 返回用户的 likes
  • POST /comment/:id/like 需要参数 uid 和 token
  • DELETE /comment/:id/like 需要参数 uid 和 Token

App

  • POST /app/search &type(name, alias, pkg, desc) body 为内容
  • GET /app/:id 获取一个应用对象 all 可选 &cate &minapi &user &sort(star replies created updated size)
  • POST /app 参数 &uid &token &name &icon &reversion &locked 返回创建的 id
  • PUT /app/:id &token body 是 app 对象
  • DELETE /app/:id &token

JSON

{
  "id": "",
  "creator": "",
  "category": "",
  "name": "",
  "alias": "",
  "pkgname": "",
  "icon": "",
  "version": "",
  "reversion": "",
  "description": "",
  "updates": "",
  "visualizer": "",
  "optlabel": "",
  "special": "",
  "install": "",
  "previews": "",
  "apimin": "",
  "apitarget": "",
  "size": "",
  "lang": "",
  "src": "",
  "perm": "",
  "stars": "",
  "replies": "",
  "locked": "",
  "updated": ""
}

duangsuse 被玩坏了不想写那啥了

Update

  • GET /update/:app 获取所有更新
  • GET /update/:app/updated 获取最后更新时间
  • GET /update/:app/:rev 获取某版本的更新
  • POST /update/:app &token &reversion(指定 reversion) &install 发布一个更新, 返回更新 reversion
  • PUT /update/:app/:rev &token 修改一个更新 body 是对象
  • DELETE /update/:app/:rev 删除指定 reversion 的更新
{
  "app": "",
  "name": "",
  "alias": "",
  "icon": "",
  "version": "",
  "reversion": "",
  "description": "",
  "updates": "",
  "visualizer": "",
  "optlabel": "",
  "special": "",
  "install": "",
  "previews": "",
  "apimin": "",
  "apitarget": "",
  "size": "",
  "perm": "",
}

duangsuse 被玩坏了不想写那啥了

Star

  • GET /app/:id/star 返回 star 用户 id 以 : 分割
  • GET /user/:id/star 返回用户的 stars
  • POST /app/:id/star 需要参数 uid 和 token
  • DELETE /app/:id/star 需要参数 uid 和 Token

Recommend

  • GET /app/:id/recommend 返回 recommend 对象
  • GET /user/:id/recommend 返回用户的 recommend 对象
  • POST /app/:id/recommend/:r 需要参数 uid 和 token, body 为 reason
  • DELETE /app/:id/recommend/:r 需要参数 uid 和 Token

JSON

{
  "user": "uid_integer",
  "app": "app_integer",
  "recommed": "recommend_integer",
  "reason": "reason"
}

Pinned

  • GET /app/:id/pinned 返回 pinned Comment ID 以 : 分割
  • POST /app/:id/pin/:c 需要参数 token
  • DELETE /app/:id/pin/:c 需要参数 token

Misc API

Category

Category 是给应用分类的方法

  • GET /category/:id 获取 这个 Category 的描述或 all
  • POST /category 增加一个 Category, 参数 &uid &token &name 可选 &parent 返回 id
  • PUT /category/:id 更新一个 Category 的 name, body 为 name, 参数 &uid &token
  • DELETE /category/:id 删除一个 Category, 参数 &uid &token
JSON 对象
{
  "id": "id_integer",
  "name": "name",
  "parent": "parent_name"
}

Timeline

Timeline 是 GeekApk 记录分享用户活动的一种方式,记录行为完全由服务器自动且强制执行

  • GET /timeline/:uid 获取这个(组) UID 的所有 Timeline,UID 之间可以用 , 切分,也可以是 all,可用参数 &dsc(✓ 或 ✗) 倒序 &t 只返回固定类型的数据, &s 指定一个 Unix 时间只返回在那之后的数据
Timeline JSON 对象
{
  "user": "uid_integer",
  "ctime": "created_datetime",
  "type": "type_integer",
  "data": "data_integer"
}
Timeline 类型
  • 0 Follow 了某 UID
  • 1 Like 了某 Comment
  • 2 Star 了某 Comment
  • 3 发布了某 Comment
  • 4 更新了某 Comment
  • 5 在某 App 里增加了一个 Pin
  • 6 在某 App 里增加了一个 Recommend
  • 7 创建了某 App
  • 8 发布了某 App 的更新
  • 9 删除了某 App
  • 10 Star 了某 App

Private

Private table 是 GeekApk 实现插件配置云存储的方式,也作为实现 PM 的工具

  • GET /private/user/:uid/received 获取 accessable 我 UID 的所有消息,需要参数 &token,可选参数 &s 指定数据 ctime 起始,&t`类型 filter
  • GET /private/user/:uid 获取 UID 的所有记录,需要参数 &token,可选参数 &s 指定数据 ctime 起始,&t`类型 filter
  • POST /private/:uid 为 UID 的表创建一条记录 可选参数 &t类型 acc额外访问权限 body 为内容返回私有记录 ID
  • GET /private/:id 获取一条记录,可选参数 &uid &token 会自动进行权限验证,如果允许访问即返回记录
  • PUT /private/:id 更新一条记录,body 为内容,需要 &token uid 自动推导到此记录所有者
  • DELETE /private/:id 删除一条记录,需要 &token uid 自动推导到此记录所有者
JSON
{
  "id": "id_integer",
  "uid": "uid_integer",
  "type": "type_integer",
  "accessable": "accessable_integer",
  "text": "text",
  "ctime": "ctime_datetime",
  "atime": "atime_datetime_null"
}

Postage

Postage 是 GeekApk 中的「消息中心」后端支持

  • GET /postage/:uid 获取我的所有邮件,需要验证 &token 可选 &all(✓ 或 ✗) &dsc(✓ 或 ✗) &t(类型) &from(发送人), 可选参数 &s 指定数据 time 起始

没有获取所有已发送邮件的方法,不要忘记了,这只是一个把服务端自动的消息提示变成你手动控制的而已

  • PUT /postage/:uid/:from 必须 &token 可选 &type &data ignore 一个记录
  • DELETE /postage/:uid/:from 必须 &token 可选 &type &data 删除一个记录
  • POST /postage/:uid/:to 必须 &token 可选 &type &data 发送一个记录
消息类型
  • 0 Follow 了你
  • 1 在 Comment 中 At 了你
  • 2 在 Comment 中回复了你
  • 3 Like 了你的 Comment
  • 4 Star 了你的 Comment
  • 5 Star 了你的 App
  • 6 PM 了你
JSON
{
  "from": "from_integer",
  "to": "to_integer",
  "type": "type_integer",
  "data": "data_integer",
  "ignore": "ignore_boolean",
  "time": "sent_datetime"
}

以下是 WebSocket API 使用方式

WebSocket 端口一般会被开在 233如果是特殊情况 其实是无法自动支持的 WebSocket 可以向每个已经连接的客户端发送即时全站更新消息方便他们更新自己的信息 同时,WebSocket 也会向已经验证的用户发送他们自己的 Post 信息和好友 Timeline 更新信息

连接上 WebSocket 服务器时,GeekApk 服务器会向你发送一个 欢迎消息 Welcome to the GeekApk live Stream Server v{GeekApk Server Version}!,而且会向所有连接发送你已经加入的消息,会包含 Socket resource descriptor 和你 IP 的 hascode

之后你可以发送你的用户名和 Token,在验证成功后,GeekApk 服务器会发送广播已通知你已上线,会包含你的用户名信息

之后你可以发送指令查询在线人数/各类信息的最近更新时间以及向在线用户发送消息,GeekApk 会在各类信息更新时发送广播。

Welcome to the GeekApk live Stream Server v1!
New connection:(resource descriptor):(ip hashcode)
Connection:(resource descriptor):identified as:(uid):(username)
(你发送你的用户 ID 和密码)
3:sasasasasa
(你收到密码错误提示)
Bad Password
3:dasdasdads
Welcome
Connection:(your resource descriptor):identified as:3:foo
(服务器在更新时向你发送更新 ID)
02234
(你发送指令查询在线人数)
line
(服务器返回在线人数)
233
(你查询 ID 最近更新时间)
0
(服务器返回最近更新 Unix 时间)
2147483647
(你向(且只能向)某个已经登陆的非匿名用户发送即时消息(必须非匿名))
send 0 Hello, world!!!
(你收到即时消息)
Message from 0: Hello!
(你离开 live stream)

更新类型

  • 0 普通应用更新
  • 1 普通新 Comment
  • 2 新 Post(登陆后)
  • 3 头条更新
  • 4 应用集更新
  • 5 话题更新
  • 6 新闻更新

关闭连接时,GeekApk realtime 服务器会发送广播(无论是匿名用户还是已登陆用户)来通知你已经下线

到了现在头还有点大,估计是 GeekApk 还是有点复杂吧... 唉

优秀的设计是 简洁而明了的,一切应该尽可能 统一,可能的特性虽然 但底层表示 不乱,像一道彩虹,不是「满天都是花花绿绿杂乱的彩带」 是之前水平不够的原因 (现在也一样),真正的这种社区应该是 尽可能简单的,不过设计时添加了 太多莫名其妙的特性 让她变得 复杂不堪且难以理解,我决定在此进行 精简,依然保留插件设计

GeekApk 里主要还是有三大模型: 用户,应用,评论 其他的都可以省掉 (话题,头条,应用集,新闻 都可以是应用或评论) 另外还有必须要有的 PM收件箱时间线 设计 模型里偏重 星标,置顶,过滤,排序,推荐

用户系统不开放注册,需要有人开 issue 引荐一个特别不人性化但是实在没办法的事是密码是自动生成的 密码的分发和重置依赖第三方平台

用户

字段 类型 描述
id integer 用户的 唯一标识
name varchar 用户名
alias varchar 用户名
email varchar 邮件
github varchar GitHub 用户简名
super integer 超应用 AID
bio varchar 介绍
dev_bio varchar 开发者介绍
ctime datetime 创建时间
atime datetime 上线时间
following integer 跟随数
followed integer 被跟随数

follow

字段 类型 描述
user integer 跟随者 UID
followed integer 被跟随者 UID

hash

字段 类型 描述
user integer 用户
hash varchar 用户密码 SHA-256 hash
  • Filter 超级用户? 填写email? 填写bio? 有别名? 已经跟随?
  • Sort 创建时间 上线时间 跟随数 被跟随数
  • 检索 用户名 用户别名 bio

应用

字段 类型 描述
id integer 应用 AID (唯一标识)
creator integer 创建人 UID
category integer 分类 SID
name varchar 名称
alias varchar 别名
pkgname varchar 包名
icon varchar 图标链接
version varchar 版本
reversion integer 重版本 (用于标识更新)
description varchar 描述
updates varchar 更新内容
visualizer varchar applayout
optlabel varchar 操作名覆盖
special varchar 应用特殊标签
install varchar 获取链接
previews varchar 预览图片们
apimin integer Android API 最小需求
apitarget integer Android API 目标
size integer 以千字节计算的安装包体积
lang varchar 语言标识代码
src varchar 源代码地址
perm varchar 权限
stars integer 收获的 Star 数目
replies integer 收获的 评论 数目
locked boolean 是否不允许他人添加推荐 (需要用于实现应用集等)

star

字段 类型 描述
user integer Star用户
app integer 应用 AID

category

字段 类型 描述
id integer 分类 SID
name varchar 分类描述
parent varchar 父分类 描述(允许两层分类)

recommend

字段 类型 描述
user integer 推荐的 用户
app integer 在应用 n
recommend integer 推荐了 n

top

字段 类型 描述
app integer 对应应用 AID
pinned integer 置顶评论 CID
  • Filter category 最低AndroidAPI 你发布的?
  • Sort star replies created updated size
  • 检索 应用名 别名 包名 描述

评论

字段 类型 描述
id integer 回复唯一 CID
user integer 发布 用户
target integer 回复到的 应用
ctime datetime 创建时间
mtime datetime 更新时间
reply integer 回复到
content varchar Markdown 内容
stars integer Star 数目
replies integer 回复 数目
likes integer 喜欢数

like

字段 类型 描述
user integer like 的 用户
comment integer 评论 CID

comment_star

字段 类型 描述
user integer star 的 用户
comment integer 评论 CID
  • Filter 应用目标 发布用户
  • Sort star like reply created updated
  • Search 内容

收件箱

字段 类型 描述
to integer 谁的邮件?
from integer 谁发的?
type intger 类型?
data integer 数据
ignore boolean 已经阅读
time datetime 发送时间
  • Sort 发送时间
  • Filter 类型 谁发送的? 已经阅读?

Private Table

字段 类型 描述
uid integer 这是谁的私有表记录?
id integer 用户私有表记录的 ID
type integer 类型
accessable integer 谁可以访问这个信息?
text varchar 消息
ctime datetime 创建时间
mtime datetime 修改时间
  • Sort 创建时间 修改时间
  • Filter 谁可以访问这条消息 我可以访问哪条他人的消息

Timeline

字段 类型 描述
uid integer 谁发表了这个时间线?
time datetime 什么时间?
type integer 什么情况
data integer 额外数据信息
  • Sort 时间
  • Filter UID 一组UID 我所有Following的UID type
drop table if exists users;
drop table if exists follow;
drop table if exists hash;
drop table if exists apps;
drop table if exists updates;
drop table if exists star;
drop table if exists categories;
drop table if exists recommend;
drop table if exists top;
drop table if exists comments;
drop table if exists comment_star;
drop table if exists like_comment;
drop table if exists postage;
drop table if exists privtable;
drop table if exists timeline;
drop table if exists presis_tokens;
drop table if exists users;
create table users (
id smallserial primary key,
name text not null,
username text not null,
alias text,
email text,
github text,
super smallint,
bio text default '这个基友很强,居然没写介绍 QAQ',
dev_bio text,
ctime timestamp not null default now(),
atime timestamp not null default now(),
avatar text default '',
following smallint default 0,
followed smallint default 0
);
drop table if exists follow;
create table follow (
userid smallint not null,
followed smallint not null
);
drop table if exists hash;
create table hash (
userid smallint not null primary key,
hash text not null
);
drop table if exists apps;
create table apps(
id smallserial primary key,
creator smallint not null,
category smallint,
name text not null,
alias text default '',
pkgname text default '<unnamed>',
icon text,
version text default '<unversionized>',
reversion smallint not null,
description text default '(assert-not description-provided)',
updates text,
visualizer text,
optlabel text,
special text,
install text,
previews text,
apimin smallint,
apitarget smallint,
size int default 0,
lang text,
src text,
perm text,
stars smallint default 0,
replies int default 0,
locked boolean default false,
updated timestamp
);
drop table if exists updates;
create table updates(
app smallint not null,
name text not null,
alias text not null,
icon text,
version text default '<unversionized>',
reversion smallint not null,
description text default '',
updates text,
visualizer text,
optlabel text,
special text,
install text,
previews text,
apimin smallint,
apitarget smallint,
size int default 0,
perm text
);
drop table if exists star;
create table star(
userid smallint not null,
app smallint not null
);
drop table if exists categories;
create table categories (
id smallserial primary key,
name text not null,
parent text
);
drop table if exists recommend;
create table recommend(
userid smallint not null,
app smallint not null,
recommend int not null
);
drop table if exists top;
create table top(
app smallint not null,
pinned int not null
);
drop table if exists comments;
create table comments(
id serial primary key,
userid smallint not null,
target smallint not null,
ctime timestamp not null default now(),
mtime timestamp not null,
reply int,
content text not null,
stars smallint default 0,
likes smallint default 0,
replies int default 0
);
drop table if exists comment_star;
create table comment_star(
userid smallint not null,
comment int not null
);
drop table if exists like_comment;
create table like_comment(
userid smallint not null,
comment int not null
);
drop table if exists postage;
create table postage(
to_userid smallint not null,
sender smallint not null,
typed smallint default 0,
data int default 0,
ignore boolean default false,
ctime timestamp not null default now()
);
drop table if exists privtable;
create table privtable (
userid smallint not null,
id serial primary key,
ttype smallint default 0,
accessable smallint,
message text not null,
ctime timestamp not null default now(),
mtime timestamp not null
);
drop table if exists timeline;
create table timeline(
userid smallint not null,
ctime timestamp not null default now(),
ttype smallint not null default 0,
data integer not null
);
drop table if exists presis_tokens;
create table presis_tokens(
userid smallint not null,
token text not null,
ctime timestamp not null,
access_level smallint not null default 0
);
@duangsuse
Copy link
Author

内个,大家觉得没有 bug 我就做了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment