make friendship/followship feature as builtin and deprecated lightship feature

pull/362/head
Michael Li 11 months ago
parent 6b96954e57
commit d7351e7cf7
No known key found for this signature in database

@ -21,15 +21,6 @@ All notable changes to paopao-ce are documented in this file.
CREATE TABLE p_following (ID BIGSERIAL PRIMARY KEY,user_id BIGINT NOT NULL,follow_id BIGINT NOT NULL,is_del SMALLINT NOT NULL DEFAULT 0,created_on BIGINT NOT NULL DEFAULT 0,modified_on BIGINT NOT NULL DEFAULT 0,deleted_on BIGINT NOT NULL DEFAULT 0);
CREATE INDEX idx_following_user_follow ON p_following USING btree (user_id,follow_id);
```
custom set config.yaml in `Features` section add `Followship` to enable Followship feature:
```yaml
...
# add Followship to enable this feature
Features:
Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "MinIO", "Followship"]
Base: ["Redis", "PhoneBind"]
...
```
### Changed
- change man content width to 600px and optimize tweet/comment/replay text length. [#333](https://github.com/rocboss/paopao-ce/pull/333)
@ -41,6 +32,8 @@ All notable changes to paopao-ce are documented in this file.
make build TAGS='slim embed'
```
- frontend: optimize user profile page route path to domain/#/u/?s=username. [&c857142](https://github.com/rocboss/paopao-ce/commit/c857142565f0c28294344c7abc5c2df4e363b04c
- change the `Friendship` feature and `Followship` feature as builtin feature. [#362](https://github.com/rocboss/paopao-ce/pull/362)
- deprecated/remove `Lightship` feature. [#362](https://github.com/rocboss/paopao-ce/pull/362)
## 0.3.1
### Fixed

@ -373,9 +373,9 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r
|`LoggerFile` | 日志 | 稳定 | 使用文件写日志 |
|`LoggerZinc` | 日志 | 稳定(推荐) | 使用[Zinc](https://github.com/zinclabs/zinc)写日志 |
|`LoggerMeili` | 日志 | 内测 | 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志 |
|[`Friendship`](docs/proposal/002-关于Friendship功能项的设计.md) | 关系模式 | 内 | 弱关系好友模式,类似微信朋友圈 |
|[`Followship`](docs/proposal/003-关于Followship功能项的设计.md) | 关系模式 | WIP | 关注者模式类似Twitter的Follow模式 |
|[`Lightship`](docs/proposal/011-关于Lightship功能项的设计.md) | 关系模式 | 内测(默认) | 开放模式,所有推文都公开可见 |
|[`Friendship`](docs/proposal/22110410-关于Friendship功能项的设计.md) | 关系模式 | 内置 Builtin | 弱关系好友模式,类似微信朋友圈 |
|[`Followship`](docs/proposal/22110409-关于Followship功能项的设计.md) | 关系模式 | 内置 Builtin | 关注者模式类似Twitter的Follow模式 |
|[`Lightship`](docs/proposal/22121409-关于Lightship功能项的设计.md) | 关系模式 | 弃用 Deprecated | 开放模式,所有推文都公开可见 |
|`Alipay` | 支付 | 稳定 | 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能 |
|`Sms` | 短信验证 | 稳定 | 开启短信验证码功能,用于手机绑定验证手机是否注册者的;功能如果没有开启,手机绑定时任意短信验证码都可以绑定手机 |
|`Docs:OpenAPI` | 开发文档 | 稳定 | 开启openapi文档功能提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi) |

@ -12,7 +12,7 @@ Server: # 服务设置
ReadTimeout: 60
WriteTimeout: 60
Features:
Default: ["Web", "Frontend:EmbedWeb", "Meili", "LocalOSS", "MySQL", "BigCacheIndex", "LoggerFile", "Friendship", "Followship"]
Default: ["Web", "Frontend:EmbedWeb", "Meili", "LocalOSS", "MySQL", "BigCacheIndex", "LoggerFile"]
Develop: ["Base", "MySQL", "BigCacheIndex", "Meili", "Sms", "AliOSS", "LoggerMeili", "OSS:Retention"]
Demo: ["Base", "MySQL", "Option", "Zinc", "Sms", "MinIO", "LoggerZinc", "Migration"]
Slim: ["Base", "Sqlite3", "LocalOSS", "LoggerFile", "OSS:TempDir"]

@ -1,6 +1,6 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 22110409| 北野 | 2022-11-04 | 2023-08-14 | v1.0 | 提议 |
| 22110409| 北野 | 2022-11-04 | 2023-08-16 | v1.0 | 提议 |
### 关于Followship功能项的设计
Followship是实现类似Twitter Timeline模式**关注者模型**的时间线信息流广场推文列表的生成将主要与推文时间、用户的关注者相关。Twitter的推文消息流是非常智能的用户体验也非常好这得益于其背后的智能推荐算法以及完善的关注者模型体系当然还有很多其他机制共同作用下的结果。本提按作为一个总纲为paopao-ce引入类似的机制这将是一个持续完善的缓慢过程一切都是为了用户体验用户就是上帝用户需要什么paopao-ce就努力提供什么
@ -39,21 +39,16 @@
* 参考实现(PR):
[add Followship feature #355](https://github.com/rocboss/paopao-ce/pull/355)
#### 状态:
内置 Builtin
### 疑问
1. Friendship与Followship这两功能项是否可以共存还是互斥呢
理论上这两个功能项是可以共存的如果设置成共存就需要同时提供这两个机制的UI交互同时广场推文列表的生成机制也需要做相应适配可能会比较复杂。前期开发将把这两个功能设置为互斥的即**用户关系模型**只能设置为其中之一,待两个功能项都趋于稳定后,再测试这两个功能项共存后的用户体验,如果效果还不错就引入共存机制。
1. 如何开启这个功能?
在配置文件config.yaml中的`Features`中添加`Followship`功能项开启该功能:
```yaml
...
# features中加上 Followship
Features:
Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "MinIO", "Followship"]
Base: ["Redis", "PhoneBind"]
...
```
内置 Builtin
### 更新记录
#### v0.0(2022-11-04) - 北野
@ -63,4 +58,7 @@
* 添加初始内容;
#### v1.0(2023-08-14) - 北野
* 添加参考实现;
* 添加参考实现;
#### v1.1(2023-08-16) - 北野
* 添加状态信息;

@ -1,6 +1,6 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 22110410 | 北野 | 2022-11-04 | 2023-01-04 | v1.0 | 提议 |
| 22110410 | 北野 | 2022-11-04 | 2023-08-16 | v1.1 | 提议 |
### Friendship功能项的设计概要
Friendship功能提供好友间分享推文信息的机制更好的帮助用户建立自己的推文分享小圈子。Friendship本质上想优化的是泡泡广场页面推文列表的生成机制开启功能后推文列表只能获取 `公开/私密/好友` 的推文,每个用户都有属于自己的个性化推文列表。在提供个性化推文列表生成机制的同时,好友体系的建立也顺便帮助用户建立自己的个性化有限范围内的灵魂社交小圈子,只有相互间拥有个性化认同感的用户才能互为好友。
@ -30,6 +30,9 @@ Friendship功能提供好友间分享推文信息的机制更好的帮助用
* 参考实现(PR):
[add support Friendship feature #192](https://github.com/rocboss/paopao-ce/pull/192)
#### 状态:
内置 Builtin
* 预览
| |
@ -46,15 +49,7 @@ Friendship功能提供好友间分享推文信息的机制更好的帮助用
2. 如何形成这种好友体系?
形成好友体系分 **建立、维持、解除** 好友关系。Friendship提供 *建立/解除* 好友关系的机制,泡泡广场的推文列表依据这个好友体系为每个用户生成个性化推文列表。而好友关系的**维持**本质上就是用户推文的持久更新、思想的持续演化使得好友对你一直保持兴趣Friendship也为每一条推文的访问权限进行**标记(私密/好友可见)**,这可以传达这样一种信息: **“时刻让好友知道我非常在乎好友、对好友特殊关照,你看这条推文就是只有我的好友(也就是你)才可以看到,够意思吧”!** 顺便一说,每一条推文的访问权限标记(公开/私密/好友可见)是建立Friendship弱关系体系的隐性催化剂可以加速Friendship的形成。
3. 如何开启这个功能?
在配置文件config.yaml中的`Features`中添加`Friendship`功能项开启该功能:
```yaml
...
# features中加上 Friendship
Features:
Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "MinIO", "Friendship"]
Base: ["Redis", "PhoneBind"]
...
```
内置 Builtin
### 更新记录
#### v0.1(2022-11-04) - 北野
@ -65,3 +60,6 @@ Friendship功能提供好友间分享推文信息的机制更好的帮助用
#### v1.0(2023-01-04) - 北野
* 添加参考实现PR信息
#### v1.1(2023-08-16) - 北野
* 添加状态信息;

@ -1,9 +1,9 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 22121409 | 北野 | 2022-12-14 | 2022-01-09 | v1.1 | 提议 |
| 22121409 | 北野 | 2022-12-14 | 2023-08-16 | v1.2 | 提议 |
### 关于Lightship功能项的设计
Lightship(开放模式)功能提供完全公开的推文分享服务,有别于[Friendship](002-关于Friendship功能项的设计.md "关于Friendship功能项的设计")、[Followship](003-关于Followship功能项的设计.md "关于Followship功能项的设计")使用Lightship用户模式部署paopao-ce用户发布的所有推文都是公开可访问的广场推文列表展示的是全站所有公开推文的Timeline Tweets。
Lightship(开放模式)功能提供完全公开的推文分享服务,有别于[Friendship](22110410-关于Friendship功能项的设计.md "关于Friendship功能项的设计")、[Followship](22110410-关于Followship功能项的设计.md "关于Followship功能项的设计")使用Lightship用户模式部署paopao-ce用户发布的所有推文都是公开可访问的广场推文列表展示的是全站所有公开推文的Timeline Tweets。
### 场景
一般用于非常小的站点,或者推文更新不频繁的站点。
@ -24,6 +24,9 @@ Lightship(开放模式)功能提供完全公开的推文分享服务,有别于
#### 参考实现(PR):
[add Lightship feature support #198](https://github.com/rocboss/paopao-ce/pull/198)
#### 状态:
弃用 Deprecated
### 疑问
1. 公开模式为什么命名为Lightship
@ -45,3 +48,6 @@ Features:
#### v1.1(2022-01-09) - 北野
* 添加参考实现PR信息
#### v1.2(2023-08-16) - 北野
* 添加状态信息

@ -145,15 +145,15 @@
* [x] 业务逻辑实现
#### 关系模式:
* `Friendship` 弱关系好友模式,类似微信朋友圈(目前状态: 内);
* `Friendship` 弱关系好友模式,类似微信朋友圈(目前状态: 内置Builtin);
* [x] [提按文档](docs/proposal/22110410-关于Friendship功能项的设计.md)
* [x] 接口定义
* [x] 业务逻辑实现
* `Followship` 关注者模式类似Twitter的Follow模式(目前状态: WIP);
* `Followship` 关注者模式类似Twitter的Follow模式(目前状态: 内置Builtin);
* [ ] [提按文档](docs/proposal/22110409-关于Followship功能项的设计.md)
* [ ] 接口定义
* [ ] 业务逻辑实现
* `Lightship` 开放模式,所有推文都公开可见(目前状态: 内测、默认);
* `Lightship` 开放模式,所有推文都公开可见(目前状态: 弃用Deprecated);
* [x] [提按文档](docs/proposal/22121409-关于Lightship功能项的设计.md)
* [x] 接口定义
* [x] 业务逻辑实现

@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
// Core service implement base gorm+mysql/postgresql/sqlite3.
// package jinzhu Core service implement base gorm+mysql/postgresql/sqlite3.
// Jinzhu is the primary developer of gorm so use his name as
// package name as a saluter.
@ -60,24 +60,12 @@ func NewDataService() (core.DataService, core.VersionInfo) {
var (
v core.VersionInfo
cis core.CacheIndexService
ips core.IndexPostsService
)
db := conf.MustGormDB()
pvs := security.NewPhoneVerifyService()
ams := NewAuthorizationManageService()
ths := newTweetHelpService(db)
// initialize core.IndexPostsService
if cfg.If("Friendship") {
ips = newFriendIndexService(db, ams, ths)
} else if cfg.If("Followship") {
ips = newFollowIndexService(db, ths)
} else if cfg.If("Lightship") {
ips = newLightIndexService(db, ths)
} else {
// default use lightship post index service
ips = newLightIndexService(db, ths)
}
ips := newShipIndexService(db, ams, ths)
// initialize core.CacheIndexService
cfg.On(cfg.Actions{
@ -87,7 +75,6 @@ func NewDataService() (core.DataService, core.VersionInfo) {
cis, v = cache.NewSimpleCacheIndexService(ips)
},
"BigCacheIndex": func() {
// TODO: make cache index post in different scence like friendship/followship/lightship
cis, v = cache.NewBigCacheIndexService(ips, ams)
},
"RedisCacheIndex": func() {

@ -15,35 +15,23 @@ import (
)
var (
_ core.IndexPostsService = (*friendIndexSrv)(nil)
_ core.IndexPostsService = (*followIndexSrv)(nil)
_ core.IndexPostsService = (*lightIndexSrv)(nil)
_ core.IndexPostsService = (*shipIndexSrv)(nil)
_ core.IndexPostsService = (*simpleIndexPostsSrv)(nil)
)
type friendIndexSrv struct {
type shipIndexSrv struct {
ams core.AuthorizationManageService
ths core.TweetHelpService
db *gorm.DB
}
type followIndexSrv struct {
ths core.TweetHelpService
db *gorm.DB
}
type lightIndexSrv struct {
ths core.TweetHelpService
db *gorm.DB
}
type simpleIndexPostsSrv struct {
ths core.TweetHelpService
db *gorm.DB
}
// IndexPosts 根据userId查询广场推文列表简单做到不同用户的主页都是不同的
func (s *friendIndexSrv) IndexPosts(user *ms.User, offset int, limit int) (*ms.IndexTweetList, error) {
func (s *shipIndexSrv) IndexPosts(user *ms.User, offset int, limit int) (*ms.IndexTweetList, error) {
predicates := dbr.Predicates{
"ORDER": []any{"is_top DESC, latest_replied_on DESC"},
}
@ -77,60 +65,6 @@ func (s *friendIndexSrv) IndexPosts(user *ms.User, offset int, limit int) (*ms.I
}, nil
}
func (s *friendIndexSrv) TweetTimeline(userId int64, offset int, limit int) (*cs.TweetBox, error) {
// TODO
return nil, debug.ErrNotImplemented
}
// IndexPosts 根据userId查询广场推文列表
func (s *followIndexSrv) IndexPosts(user *ms.User, offset int, limit int) (*ms.IndexTweetList, error) {
// TODO
return nil, debug.ErrNotImplemented
}
func (s *followIndexSrv) TweetTimeline(userId int64, offset int, limit int) (*cs.TweetBox, error) {
// TODO
return nil, debug.ErrNotImplemented
}
// IndexPosts 根据userId查询广场推文列表获取公开可见Tweet或者所属用户的私有Tweet
func (s *lightIndexSrv) IndexPosts(user *ms.User, offset int, limit int) (*ms.IndexTweetList, error) {
predicates := dbr.Predicates{
"ORDER": []any{"is_top DESC, latest_replied_on DESC"},
}
if user == nil {
predicates["visibility = ?"] = []any{dbr.PostVisitPublic}
} else if !user.IsAdmin {
args := []any{dbr.PostVisitPublic, dbr.PostVisitPrivate, user.ID}
predicates["visibility = ? OR (visibility = ? AND user_id = ?)"] = args
}
posts, err := (&dbr.Post{}).Fetch(s.db, predicates, offset, limit)
if err != nil {
logrus.Debugf("gormIndexPostsSrv.IndexPosts err: %v", err)
return nil, err
}
formatPosts, err := s.ths.MergePosts(posts)
if err != nil {
return nil, err
}
total, err := (&dbr.Post{}).CountBy(s.db, predicates)
if err != nil {
return nil, err
}
return &ms.IndexTweetList{
Tweets: formatPosts,
Total: total,
}, nil
}
func (s *lightIndexSrv) TweetTimeline(userId int64, offset int, limit int) (*cs.TweetBox, error) {
// TODO
return nil, debug.ErrNotImplemented
}
// simpleCacheIndexGetPosts simpleCacheIndex 专属获取广场推文列表函数
func (s *simpleIndexPostsSrv) IndexPosts(_user *ms.User, offset int, limit int) (*ms.IndexTweetList, error) {
predicates := dbr.Predicates{
@ -165,28 +99,14 @@ func (s *simpleIndexPostsSrv) TweetTimeline(userId int64, offset int, limit int)
return nil, debug.ErrNotImplemented
}
func newFriendIndexService(db *gorm.DB, ams core.AuthorizationManageService, ths core.TweetHelpService) core.IndexPostsService {
return &friendIndexSrv{
func newShipIndexService(db *gorm.DB, ams core.AuthorizationManageService, ths core.TweetHelpService) core.IndexPostsService {
return &shipIndexSrv{
ams: ams,
ths: ths,
db: db,
}
}
func newFollowIndexService(db *gorm.DB, ths core.TweetHelpService) core.IndexPostsService {
return &followIndexSrv{
ths: ths,
db: db,
}
}
func newLightIndexService(db *gorm.DB, ths core.TweetHelpService) core.IndexPostsService {
return &lightIndexSrv{
ths: ths,
db: db,
}
}
func newSimpleIndexPostsService(db *gorm.DB, ths core.TweetHelpService) core.IndexPostsService {
return &simpleIndexPostsSrv{
ths: ths,

@ -32,19 +32,13 @@ func RouteWeb(e *gin.Engine) {
api.RegisterLooseServant(e, newLooseSrv(ds))
api.RegisterPrivServant(e, newPrivSrv(ds, oss))
api.RegisterPubServant(e, newPubSrv(ds))
api.RegisterFollowshipServant(e, newFollowshipSrv(ds))
api.RegisterFriendshipServant(e, newFriendshipSrv(ds))
// regster servants if needed by configure
cfg.In(cfg.Actions{
"Alipay": func() {
client := conf.MustAlipayClient()
api.RegisterAlipayPubServant(e, newAlipayPubSrv(ds))
api.RegisterAlipayPrivServant(e, newAlipayPrivSrv(ds, client))
},
"Followship": func() {
api.RegisterFollowshipServant(e, newFollowshipSrv(ds))
},
"Friendship": func() {
api.RegisterFriendshipServant(e, newFriendshipSrv(ds))
},
cfg.Be("Alipay", func() {
client := conf.MustAlipayClient()
api.RegisterAlipayPubServant(e, newAlipayPubSrv(ds))
api.RegisterAlipayPrivServant(e, newAlipayPrivSrv(ds, client))
})
}

Loading…
Cancel
Save