Andy

手民

废案

最近在写一个第三方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注入?

## 十一、敬请参与

// 本节已删

再见了




1 人支持了作者

發佈評論

看不過癮?

一鍵登入,即可加入全球最優質中文創作社區