废案
最近在写一个第三方Matters客户端,名字叫做「Maltaa」。鉴于环境,我决定放弃,代码现在也不会公开了。以下是产品计划的废案,一边做一边改,原本是测试发布的时候一起公布的,现在就发出来权当纪念吧。
测试站已经关掉了,内文链接也不能用了,不好意思。以下的大写Maltaa表示Maltaa软件,小写maltaa原本是Maltaa网站的域名。
## 一、阅读功能
所有阅读功能无需登入即可使用。
### 1.1 文章排序
首页(广场)提供五种排序:评论量、赞赏量、最新、最早、随缘。提供五种时间间隔,1日、3日、30日、一年、全部。
即,可以按以下顺序排列文章:24小时内评论最多、30日内获得赞赏量最多,1年内文章随缘抽取,所有文章最早,等等。
随缘排序就是由服务器随机选若干篇。随机算法为MongoDB的sampling算法,无法人工干预。
### 1.2 旧日头条
可查看过去某日的模拟首页。
(文章排序不必然与当时相同,因为文章发表日至今的评论赞赏也记作排序标准。)
### 1.3 文章预览
桌面版上,鼠标划过文章标题,可预览文章内容。
### 1.4 文章目录
根据文章内容自动生成目录。
### 1.5 用户预览
桌面版上,鼠标划过用户名,可预览用户资料。
### 1.6 文选阅读
可以逐篇阅读文选(见第3.3节,文选)。
### 1.7 订阅
可订阅用户、文选、房间等(见后),在「报摊」栏目查看,可分种类查看,可选择是否订阅评论。
### 1.8 无名模式
隐藏文章作者和评论者姓名,以随机化名代替。
### 1.9 屏蔽用户
可屏蔽任意用户。此后,此用户仿如从未存在,文章评论皆不显示。
可搭配名册功能使用,见3.3节。
### 1.10 评论排序
一级、二级评论分别提供顺时序、逆时序排序。默认均为顺时序。
(Matters排序为一级逆时序,二级顺时序。)
### 1.11 评论展开模式
一级评论、二级评论可分别设置默认展开折叠。
例如,可达成以下效果:
默认收起所有评论(只读正文),
默认展开一级评论、收起二级评论(手动展开二级评论),
默认展开一级评论,二级评论只展开两条(手动展开全部;Matters模式),
……
### 1.12 自定义CSS
可以自定义全局CSS,Maltaa的组件均已打上class,而且整个网站的CSS聚合为一份,方便修改。自定义CSS在输入的一刻即时生效。
比如,将以下语句加入自定义CSS,可以将顶栏变为彩虹色。
```
.NavBar {
background: linear-gradient(red, orange, yellow, green, blue, purple);
}
```
请注意:虽然CSS通常无害,请谨慎使用他人撰写的CSS,尤其是引用外部资源的语句。另外请留意保留配置窗口的入口——比如不要写body {display: none}进去,否则配置窗口也就打不开了。
### 1.13 键盘快捷键
ALT+1 - 广场
ALT+2 - 报摊
ALT+3 - 书房
### 1.14 RSS
RSS. 在路径里插一个/feed就行。
广场:
https://maltaa/feed/
个人(最新):
https://maltaa/feed/@Andy
### 1.15 随缘一篇
在搜索栏输入`,r`(即逗号、字母r)然后回车,可随机打开一篇文章。
## 二、创作功能
### 2.1 Markdown+富文本编辑器
Maltaa支持Markdown,同时支持富文本编辑模式(用按钮、快捷键「加粗」「加下划线」等)。
编辑器支持拖拽上传图片,支持复制粘贴上传图片。
编辑器支持全屏撰写模式。
评论也支持部分富文本功能(如加粗、插图等)。
### 2.2 纯文本编辑器
Maltaa另有一套纯文本编辑器,供简单回复使用。
### 2.3 最近草稿版本回溯
自动缓存最近的草稿编辑版本,供回溯。免疫服务端错误(「星球连线出现问题」),免疫编辑器框架错误(白屏,Ctrl+Z失效等),只要输入框输入,就会保存。
Markdown、纯文本编辑器都会保存。评论的版本也会保存。
草稿回溯数据存储在浏览器,只在本设备上有效。
### 2.4 文章编辑
Maltaa允许文章发表后再编辑。编辑效果在Maltaa上表现为正常更新,并提供版本修改记录,在Matters上表现为评论区贴出新版本,若此后再更新,不会另外贴出新版本,而是修改这条评论。
IPFS方面,处理方法如下:
1. 若原文通过Maltaa发布,IPFS原地址内容会通过Web浏览器动态更新,读者可选择阅读最终版本或最初版本;
2. 若原文通过Matters发布,则Maltaa会发布新文章版本到IPFS,产生一个新IPFS地址,附于新版本下。
### 2.5 共享编辑权
文章作者可与他人共享编辑权,授权编辑文章内容。只有作者可以共享编辑权。编辑权可以收回。作者身份本身无法让渡。
### 2.6 文章版权授权标记
可为文章和评论设置使用版权授权标记,目前提供版权所有、CC 3.0系列、和CC0(完全放弃)。
默认授权是版权所有(即没有标记)。
作者亦可设置个人默认授权,所有新文章自动附带授权标记。
转载文章可标记为「发布者不声称著作权」。不声称权益的文章,Maltaa会拒绝向Matters转发赞赏请求。
### 2.7 评论屏蔽
文章作者可为文章设置评论屏蔽政策。目前提供:
- 完全屏蔽(默认不显示任何评论),
- 屏蔽名单(特定名单上的用户的评论会默认隐藏)。
评论屏蔽系非强制设置,读者可以选择跳过屏蔽、阅读所有评论。
评论屏蔽效果只在Maltaa上生效(Matters没有类似机制,无法模拟)。
### 2.8 定时发文
设定时间,自动发布草稿。
## 三、组织功能
### 3.1 房间
目标:分流讨论,保护小众话题免受热门时事话题压制。
暂行规则如下。
1. 资格:注册用户皆可开创。
2. 数量:无限。
3. 地址:隶属用户,以rm为前缀,如/@User/rm/my-room。最短2字。
4. 名称:自选。
5. 房主:开房人为房间初始房主,房主可委任管理员。开房人为当然管理员。房主只有一人。房主不可转让主权。
6. 房客:任何人皆可加入房间,加入后可订阅房间新文。
7. 内容:房客可在房间内发文,亦可将自己旧文移入房间。房间内文章目前只可完全公开。
8. 管理:管理员可驱逐房客。内容准入方面,暂时只能后置审批(剔除文章)。管理员不可主动招纳房客、文章。
9. 排序:房内文章使用公用排序(最新、评论数、赞数等),由读者决定排序。
10. 置顶:管理员可置顶房内文章,无视排序设置。
11. 聊天:房间内置聊天室,供房客聊天,聊天内容完全公开。
12. 废弃:房间无法删除,但房主可以废弃房间,此后房间只能看不能变。
### 3.2 全局房间
与普通房间相同,但是拥有全局路径(如maltaa/rm/linguistics),全局路径是公共资源,故全局房间准入较严:
1. 开房资格:Matters帐号注册超过90日,赞赏h指数达到10(即获得至少10个赞赏的文章至少有10篇)。
2. 开房数量:每帐号限开2个全局房间。
### 3.3 集合三种:文选、名单、什锦
目标:提供手工编辑的人文推荐,组织社区、内容,破除自动筛选之单调。
文选选文,名册举人,什锦则人文皆可。
暂行规则如下。
1. 资格:注册用户皆可开创。
2. 数量:无限。
3. 地址:集合地址从属于创始用户——文选使用an前缀,如/@User/an/my-favourites;名册使用rl前缀,如/@User/rl/linguists;什锦使用mx前缀,如/@User/mx/interesting。除前缀外,地址自选,拉丁、汉字等皆可。地址可改,但不会自动重定向,改后旧链接失效。
4. 名称:自选,可改。
5. 内容:可选择Matters文章、评论进入文选,顺序自定,可另加评语。
6. 总编:集合创始人为集合之总编,总编可委任编辑。总编为当然编辑。总编暂不可转让总编权。
7. 编辑:编辑可行筛选、修改顺序、修改评语之权。用户有权拒绝总编的编辑邀约。
8. 订阅:用户可订阅集合,亦可屏蔽。若订阅集合,则收到集合新消息通知;若屏蔽,则集合提及之文章、人物,皆屏蔽。
9. 推荐:总编可选择开启他人推荐,如果开启,其他用户可以向集合推荐。推荐设置有:(1) 自荐,只允许用户推荐自己/自己的文章;(2)指定名单,只有列入指定名单的用户方可推荐;(3)全开,任何人都可以向集合推荐内容。推荐的内容需要编辑批准方会出现。
10. 集上集:集合可以另一集合为基础,另作增删。
11. 封存:总编可封存集合,此后集合内容不可改。封存亦可撤销。
12. 删除:集合暂不可删除。(当然,收录内容可删除。)
## 四、社交功能
### 4.1 私信
使用非对称加密实现的私信。
只有Maltaa的注册用户,且注册公钥者,方可接收私信。默认只有你的追踪者可以对你发送私信。
注意,私信通过Matters文章评论实现,而Matters评论本身是公开的。故,虽然私信内容是加密的,「发信人向收信人发信」这一行为本身是公开的。
### 4.2 用户、文章、房间、文选、名册推荐
可以向自己的追踪者推荐以上各式内容。文章包括站内文章和站外文章,站外文章推荐站内用户也可以评论。
### 4.3 一键摘抄金句贴
### 4.4 一键满赞
一键给5赞。
### 4.5 笔名
可用一个Maltaa账户控制多个Matters账户,方便区分笔名。
## 五、设计
Maltaa的设计思路受GreaterWrong影响比较大,GreaterWrong是Lesswrong的第三方客户端,Lesswrong又是Reddit的fork。
### 5.1 原则
一、安静。
二、用户选择。
三、主权与责任。
四、Design is how it works.
#### 5.2 屏宽适应性
Maltaa移动版和桌面版,分别设计,各自优化,不分先后。
#### 5.3 封面
Matters认为,「创作者也应该努力提高自己配图的水平」。我反对,所以Maltaa广场默认不显示封面。
#### 5.4 地址设计
两个原则:
第一,短;
第二,尽量用户自选。
以下为Maltaa地址类型表。
用户,前缀@,如maltaa/@Andy
文章,前缀td,如maltaa/td1234
全局房间,目录前缀rm,如maltaa/rm/radio
房间,目录前缀rm,隶属用户,如maltaa/@Andy/rm/radio
文选,目录前缀an,隶属用户,如maltaa/@Andy/an/games
名册,目录前缀rl,隶属用户,如maltaa/@Andy/rl/illustrators
#### 5.5 忽略标签
Maltaa忽略Matters的「标签」概念。原因是Matters标签逻辑还没有理顺:
1. 任何人都可以创建,但是创建后任何人对标签都没有额外权限,以致无人负责;
2. 任何人都可以为自己的文章挂载任何标签,标签页内容混杂;
3. 标签页只能按最新排序,连首页的热门排序都没有;
4. 去重机制弱,例如「台湾」「臺灣」「台灣」各有一个,还有重复的「中国」标签;
5. 文章内容往往本来就会提到标签文本,按标签检索与按关键字检索差别不大;
6. 社区对标签使用没有规范与惯例;
7. 文章发布后不能改标签(与此相对,「关联文章」又可以改)。
Maltaa的内容组织由「房间」和「文选」承担。
### 5.6 黑白配色
节制是美德。
### 5.7 使用中文排版传统
包括调大字号、段首挪抬、文段左右对齐、禁用斜体、汉字列表标号。
## 六、REST API
Maltaa提供REST API,供第三方(第四方?)读取Maltaa的数据缓存。
目前接口没有跨域限制,但是不建议将你的应用建在maltaa/api基础上。
因为是REST,不用解释太多了,仅列举例子若干:
```
GET https://maltaa/api/articles?sort=comments&page=0
GET https://maltaa/api/article/QXJ0aWNsZTozNzMyMg
GET https://maltaa/api/article/QXJ0aWNsZTozNzMyMg/comments
GET https://maltaa/api/user/VXNlcjoxMDcwNw
GET https://maltaa/api/comment/Q29tbWVudDoxOTg5MzI
GET https://maltaa/api/tag/VGFnOjY4OTg
// With pretty JSON output
GET https://maltaa/api/article/QXJ0aWNsZTozNzMyMg?pretty
```
附:Actionful API
Actionful是我为Matters Alpha设计的前后端整合架构,现在Matters已不用了。
maltaa实际上使用的是Actionful接口,而非REST。Actionful接口可以接收前端Redux/useReducer使用的Action格式,并在一个回复中打包前端需要的所有数据,再以Action格式回复前端。前端只需要直接把服务器回复灌进前端reducer,而不需要另行转化。
Actionful接口随前端变化,没有REST那么稳定,但是比较方便。
HTTP接口只有一个,只接受POST方法:
https://maltaa/api/action
例如,以下方法可以得到一篇文章数据、文章下的评论数据、文章和评论作者数据。作者数据在服务端去重。
```
POST https://maltaa/api/action
{
"type": "ViewArticle",
"article": "QXJ0aWNsZTozNjU4NQ"
}
```
```
{
"type": "ProvideEntities",
"data": {
"articles": [...],
"comments": [...],
"users": [...]
}
}
```
数据来往的形态请见src/definitions/Actions.ts。绝大多数返回的都是“ProvideEntities”类型,并在`action.meta.request`中回报对应的请求。
## 七、隐私与安全
### 7.1 隐私权
Maltaa依照GDPR框架为用户提供以下权力。
#### 知情权
用户使用Maltaa前可知晓Maltaa将要收集的信息。
#### 获得权、数据迁移权
用户可要求Maltaa服务器提供本账户数据打包(包括用户页、文章、赞赏、文选、名册等)。数据条目会以JSON形式存储。
限于服务器计算机能,准备数据迁移数据包需要24小时至48小时,为用户保留7天。
#### 修正权
用户可修改通过Maltaa修改自己的用户页。
#### 反对权、限制处理权
Maltaa注册用户可注销Maltaa账户。
非注册用户亦可启动「禁止跟踪」(DoNotTrack)功能,服务器不会记录来访记录。
#### 遗忘权
Maltaa用户可要求服务器:
1. 清除来访记录,
2. 清除账户数据,
3. 指令Matters清除自己的文章和评论。
#### 人工处理权
限于人力,仅在maltaa/rm/maltaa提供对自动机制的讨论。
### 7.2 Matters账户信息
为了让Maltaa用户连接Matters而不用每次署名操作都输密码,我们存储Matters的token,但是token泄露几乎等价于用户名密码泄露,所以需要特别安排,保护用户。
I. Maltaa的token服务器与主服务器分离,token本身使用存储AES加密过后的密文,这样即时token服务器遭入侵,token也不会泄露。
II. Maltaa的token服务器自己做所有的署名操作,不暴露提供token数据的接口,token只进不出,这样,即时Maltaa主服务器遭入侵,入侵者也只能通过token服务器操作,而不能拿走token。
III. Token的加密密钥是Maltaa账户明文密码的SHA,然后Maltaa不存储这个SHA,这样即使Maltaa数据库泄露,token也不会泄露。
IIII. token密钥SHA发给客户端,让客户端存储,然后每次需要操作token的时候发回来给Maltaa服务器,服务器用完之后扔掉。
V. Token密钥用HttpOnly的cookie传送,减少客户端劫持的风险。
### 7.3 加密
RSA,浏览器生成2048bit的私钥,或者用户提供自己的4096bit的私钥。
### 7.4 Bug bounty
有安全测试兴趣的朋友,欢迎对Maltaa做黑盒、白盒审查,规则如下:
1. 只执行Maltaa代码逻辑和针对maltaa网站的检验,请不要DoS,也不要社工其他用户(可以社工我);
2. 侵入型攻击请在周六日测试,请提前告诉我、将影响最小化、使用自己的测试账号,切勿窥视、修改他人数据。
3. Bug修复前请勿公开;
4. matters.news的bug,除非会影响Maltaa,请向Matters站方报告;
5. 奖励:每个bug象征性奖励5美金,暂时只能用LikeCoin中转,同时列入maltaa/humans.txt。
### 7.5 运维
maltaa使用Vultr的东京服务器,运行Ubuntu 18.04 LTS(Linux 4.15.0),nginx 1.16.1,nodejs 12.16.1。
maltaa使用CloudFlare做代理。SSL模式为Full(Strict),从用户到CloudFlare、从CloudFlare到maltaa服务器都做加密。
使用CloudFlare的风险权衡是:
1. 可以方便地隐藏服务器IP,缩小直接攻击面;
2. CloudFlare对Maltaa发动攻击的概率不大;
3. maltaa承受其他机构DDoS攻击的概率较大。
4. Troy Hunt也信任CloudFlare。
## 八、问答
### 8.1 Maltaa是什么
#### 为什么叫Maltaa?
M. Alt. A. A.,Matters alternated - Ad Alpha, Matters异构体・初心版。
#### 为什么做Maltaa?
技术试验。
#### Maltaa是「去中心化」的吗?
不是。
### 8.2 Maltaa与Matters
#### Maltaa和Matters是什么关系?
没有直接关系。Maltaa使用Matters的数据。
#### Maltaa是Matters的「分叉」「软分叉」「硬分叉」吗?
不是。Matters是闭源软件,无叉可分。Maltaa是建立在Matters API上的客户端。
#### 为什么Maltaa可以提供Matters没有的功能?
Maltaa只使用Matters公开的API,并无使用任何内部API或漏洞。
Maltaa的概念最终都映射到Matters概念,比如「文选」其实是「文章」,「私信」其实是「评论」。Maltaa将额外的信息挂载在Matters的评论、文章内容里。
#### Maltaa账户与Matters账户的关系为何?
通常一个Maltaa对应一个Matters账户。但是一个Maltaa账户也可以控制多个Matters账户。一个Matters账户只能连接到一个Maltaa账户。
Maltaa账户也可以不关联Matters账户,无法发言,但是可以正常浏览广场,还可以同步订阅、屏蔽名单等个人设置。
#### Maltaa为什么能够操作Matters?
简单来说,Maltaa不会存储你的用户名和密码,但是Maltaa会加密存储Matters提供的「token」,这个「token」可以理解为Matters站方随时收回的临时密码。
#### Maltaa与Matters的缓存同步策略为何?
从Matters到Maltaa:
最新文章:每10秒同步(若未找到新文章,则同步周期延长至1分钟)。
24小时内的文章:每小时同步。
7日内文章:每日同步。
所有公开数据:每周同步。
Maltaa用户访问的文章、评论:触发即时同步。
从Maltaa到Matters:
创制、改动立即同步到Matters。
#### 为什么不提供「热门」排序?
Matters未公布热门排序的算法,也不提供具体的「热门值」,第三方无法模拟。
#### 为什么评论不能赞、踩?
Matters未公布完整的评论投票记录,第三方无法模拟。
#### Maltaa的言论审查政策为何?
跟随Matters。
#### 为什么有时候Maltaa的最新文章比Matters还要新?
不清楚,或许是因为Matters采取了相对保守的缓存策略。
### 8.3 界面设计
#### 为什么要沿用Matters Alpha的界面风格?
一、好写。
二、我喜欢。
#### Maltaa界面我不喜欢。
Malta有自定义CSS功能,请自己动手改。做好的方案还可以发给我,我做成主题给大家用。
#### 文章末尾为什么有个「-30-」?
报业旧习,文章结尾写30,以示文章结束。
## 九、参考
Maltaa建立在众多前人之工作之上。
robertu的API文档:
https://maltaa/td11536
你想要的Matters文章ipfs地址:
https://maltaa/td6572
Vibert的第三方Matters:
https://maltaa/td9273
这应该是第一个Matters第三方Web客户端。
Deserve的消音插件:
https://maltaa/td12387
Focus Matters:
https://maltaa/td37231
用非对称加密做私信:
https://maltaa/td11352
## 十、待办、问题、想法、讨论
### 广场排序?
### 评论显示?
### RSS?
Maltaa做RSS是很方便的,不过已经有现成的了,再做一个RSS似乎增量不大。
### 配图?
Matters启动首页封面功能之后,配图日多,阻碍阅读。Maltaa已经不渲染封面了,内文配图是不是也可以一并隐藏?
但是站上也确实有图片创作者,如何避免误伤?
当然我也要理解,就是有一些读者喜欢看图的,是不是应该给他们做一个多图版主页?
如果上SSR,多主页应该怎么渲染?
### 搜索?
Maltaa目前没有全文搜索功能(因为吃服务器)。
### 广场标题上的emoji
彩色的emoji突兀。目前做法是广场强制灰度滤镜,包括emoji。有更好的方法吗?
### 主链接(Canonical Link)?
创作者为文章设置Canonical Link,在Maltaa上渲染的网页会指示浏览器前往该地址。
在没有服务端渲染的情况下,似乎做不了。
### 社交媒体分享标签?
就是maltaa/td1234分享出去,社交媒体不能主动提取出标题、封面、简介等,因为这些信息是React加载上去的,HTML里面没有。
也需要服务端渲染。
### 私密多人房间怎么做?
- 最暴力的解决方案,每个Maltaa用户都生成公私钥,发到房间里的消息,用每个房间成员的公钥加密一次。
- 用通知机制?
- 用站内隐藏文章?
### 客户端?
移动端React Native已经有技术试验,似乎可以与Maltaa整合。
桌面端选型不好选,是上React Native Mac + React Native Windows + React Native Desktop分平台做(开发量大),还是押宝Proton Native(好像没人维护了?)或者React Native Desktop Qt(在重构,风险大)?
还是绕过原生体系,牺牲性能,上Electron?
还是干脆抛开TypeScript体系,上Rust或者C++?那与现有代码如何整合?如何复用代码?
### 联邦化?
目前,如果有人开了另一个Maltaa服务器,数据与maltaa是完全隔离的,maltaa同步机制也会拒绝对方的独有数据,应否将各家的Maltaa服务器联合起来呢?
### 符合Content Security Policy的Custom CSS注入?
## 十一、敬请参与
// 本节已删
喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!