merge from x/gorm branch

r/paopao-ce-pro
Michael Li 1 year ago
commit 7e0006f644
No known key found for this signature in database

@ -7,6 +7,9 @@
"request": "launch", "request": "launch",
"mode": "exec", "mode": "exec",
"program": "${workspaceFolder}/.vscode/__debug_bin", "program": "${workspaceFolder}/.vscode/__debug_bin",
"args":[
"serve"
],
"preLaunchTask": "go: build (debug)", "preLaunchTask": "go: build (debug)",
"cwd": "${workspaceFolder}" "cwd": "${workspaceFolder}"
} }

@ -7,13 +7,29 @@ All notable changes to paopao-ce are documented in this file.
- use compiler profile-guided optimization (PGO) to further optimize builds. [#327](https://github.com/rocboss/paopao-ce/pull/327) - use compiler profile-guided optimization (PGO) to further optimize builds. [#327](https://github.com/rocboss/paopao-ce/pull/327)
- frontend: re-add stars page embed to profile page. [#339](https://github.com/rocboss/paopao-ce/pull/339) - frontend: re-add stars page embed to profile page. [#339](https://github.com/rocboss/paopao-ce/pull/339)
- simple support for user posts filter by style(post/comment/media/star). [#345](https://github.com/rocboss/paopao-ce/pull/345) - simple support for user posts filter by style(post/comment/media/star). [#345](https://github.com/rocboss/paopao-ce/pull/345)
mirgration database first(sql ddl file in `scripts/migration/**/*_create_view_post_filter.up.sql`): migration database first(sql ddl file in `scripts/migration/**/*_create_view_post_filter.up.sql`):
```sql ```sql
CREATE VIEW p_post_by_media AS SELECT post.*FROM (SELECT DISTINCT post_id FROM p_post_content WHERE (TYPE=3 OR TYPE=4 OR TYPE=7 OR TYPE=8) AND is_del=0) media JOIN p_post post ON media.post_id=post.ID WHERE post.is_del=0; CREATE VIEW p_post_by_media AS SELECT post.*FROM (SELECT DISTINCT post_id FROM p_post_content WHERE (TYPE=3 OR TYPE=4 OR TYPE=7 OR TYPE=8) AND is_del=0) media JOIN p_post post ON media.post_id=post.ID WHERE post.is_del=0;
CREATE VIEW p_post_by_comment AS SELECT P.*,C.user_id comment_user_id FROM (SELECT post_id,user_id FROM p_comment WHERE is_del=0 UNION SELECT post_id,reply.user_id user_id FROM p_comment_reply reply JOIN p_comment COMMENT ON reply.comment_id=COMMENT.ID WHERE reply.is_del=0 AND COMMENT.is_del=0) C JOIN p_post P ON C.post_id=P.ID WHERE P.is_del=0; CREATE VIEW p_post_by_comment AS SELECT P.*,C.user_id comment_user_id FROM (SELECT post_id,user_id FROM p_comment WHERE is_del=0 UNION SELECT post_id,reply.user_id user_id FROM p_comment_reply reply JOIN p_comment COMMENT ON reply.comment_id=COMMENT.ID WHERE reply.is_del=0 AND COMMENT.is_del=0) C JOIN p_post P ON C.post_id=P.ID WHERE P.is_del=0;
``` ```
- add user highlight tweet support include custom tweet set to highlight and list in user/profile page. - add user highlight tweet support include custom tweet set to highlight and list in user/profile page.
- add cli subcommand to start paopao-ce serve or other task. [#354](https://github.com/rocboss/paopao-ce/pull/354) - add cli subcommand to start paopao-ce serve or other task. [#354](https://github.com/rocboss/paopao-ce/pull/354)
- add `Friendship` feature . [#355](https://github.com/rocboss/paopao-ce/pull/355)
migration database first(sql ddl file in `scripts/migration/**/*_user_following.up.sql`):
```sql
DROP TABLE IF EXISTS p_following;
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 ### Changed
- change man content width to 600px and optimize tweet/comment/replay text length. [#333](https://github.com/rocboss/paopao-ce/pull/333) - change man content width to 600px and optimize tweet/comment/replay text length. [#333](https://github.com/rocboss/paopao-ce/pull/333)

@ -3,18 +3,22 @@
## paopao-ce roadmap ## paopao-ce roadmap
#### dev+ #### dev+
* [ ] add `Followship` feature
* [ ] add `Auth:Bcrypt` feature * [ ] add `Auth:Bcrypt` feature
* [ ] add `Auth:MD5` feature (just for compatible) * [ ] add `Auth:MD5` feature (just for compatible)
* [x] add extend base ORM code for implement data logic base sqlx/sqlc
* [ ] optimize media tweet submit logic * [ ] optimize media tweet submit logic
* [ ] optimize search logic service * [ ] optimize search logic service
#### v0.4.0
* [x] add `Followship` feature.
* [x] add extend base ORM code for implement data logic base sqlx/sqlc.
* [x] user/profile page add comment/highlight/media/likes sub-page.
* [x] add tweet highlight feature to enable user set a tweet as highlight.
#### v0.3.0 #### v0.3.0
* [x] remove `Deprecated:OldWeb` feature * [x] remove `Deprecated:OldWeb` feature
* [x] add user topic follow feature support * [x] add user topic follow feature support
* [x] add tweet link share support * [x] add tweet link share support
* [ ] add comment thumbsUp/thumbsDown support * [x] add comment thumbsUp/thumbsDown support
* [x] add `RedisCacheIndex` feature * [x] add `RedisCacheIndex` feature
* [x] add `Sentry` feature * [x] add `Sentry` feature

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

@ -1,6 +1,6 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 | | 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- | | ----- | ----- | ----- | ----- | ----- | ----- |
| 22110409| 北野 | 2022-11-04 | 2022-11-21 | v0.1 | 提议 | | 22110409| 北野 | 2022-11-04 | 2023-08-14 | v1.0 | 提议 |
### 关于Followship功能项的设计 ### 关于Followship功能项的设计
Followship是实现类似Twitter Timeline模式**关注者模型**的时间线信息流广场推文列表的生成将主要与推文时间、用户的关注者相关。Twitter的推文消息流是非常智能的用户体验也非常好这得益于其背后的智能推荐算法以及完善的关注者模型体系当然还有很多其他机制共同作用下的结果。本提按作为一个总纲为paopao-ce引入类似的机制这将是一个持续完善的缓慢过程一切都是为了用户体验用户就是上帝用户需要什么paopao-ce就努力提供什么 Followship是实现类似Twitter Timeline模式**关注者模型**的时间线信息流广场推文列表的生成将主要与推文时间、用户的关注者相关。Twitter的推文消息流是非常智能的用户体验也非常好这得益于其背后的智能推荐算法以及完善的关注者模型体系当然还有很多其他机制共同作用下的结果。本提按作为一个总纲为paopao-ce引入类似的机制这将是一个持续完善的缓慢过程一切都是为了用户体验用户就是上帝用户需要什么paopao-ce就努力提供什么
@ -35,6 +35,9 @@
#### 方案二 #### 方案二
在方案一的基础上通过引入 *图数据库* 实现可选需求。待研究、设计~ 在方案一的基础上通过引入 *图数据库* 实现可选需求。待研究、设计~
#### 设计细节
* 参考实现(PR):
[add Followship feature #355](https://github.com/rocboss/paopao-ce/pull/355)
### 疑问 ### 疑问
@ -58,3 +61,6 @@
#### v0.1(2022-11-21) - 北野 #### v0.1(2022-11-21) - 北野
* 添加初始内容; * 添加初始内容;
#### v1.0(2023-08-14) - 北野
* 添加参考实现;

@ -10,7 +10,7 @@ require (
github.com/aliyun/aliyun-oss-go-sdk v2.2.8+incompatible github.com/aliyun/aliyun-oss-go-sdk v2.2.8+incompatible
github.com/allegro/bigcache/v3 v3.1.0 github.com/allegro/bigcache/v3 v3.1.0
github.com/bufbuild/connect-go v1.10.0 github.com/bufbuild/connect-go v1.10.0
github.com/bytedance/sonic v1.9.2 github.com/bytedance/sonic v1.10.0
github.com/cockroachdb/errors v1.10.0 github.com/cockroachdb/errors v1.10.0
github.com/disintegration/imaging v1.6.2 github.com/disintegration/imaging v1.6.2
github.com/fatih/color v1.15.0 github.com/fatih/color v1.15.0
@ -29,8 +29,8 @@ require (
github.com/minio/minio-go/v7 v7.0.61 github.com/minio/minio-go/v7 v7.0.61
github.com/onsi/ginkgo/v2 v2.11.0 github.com/onsi/ginkgo/v2 v2.11.0
github.com/onsi/gomega v1.27.10 github.com/onsi/gomega v1.27.10
github.com/pyroscope-io/client v0.7.2-0.20230804044655-36760e422a95 github.com/pyroscope-io/client v0.7.2
github.com/redis/rueidis v1.0.14 github.com/redis/rueidis v1.0.15
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/smartwalle/alipay/v3 v3.2.15 github.com/smartwalle/alipay/v3 v3.2.15
github.com/sourcegraph/conc v0.3.0 github.com/sourcegraph/conc v0.3.0
@ -47,8 +47,8 @@ require (
gorm.io/driver/mysql v1.5.1 gorm.io/driver/mysql v1.5.1
gorm.io/driver/postgres v1.5.2 gorm.io/driver/postgres v1.5.2
gorm.io/driver/sqlite v1.5.2 gorm.io/driver/sqlite v1.5.2
gorm.io/gorm v1.25.2 gorm.io/gorm v1.25.3
gorm.io/plugin/dbresolver v1.4.2 gorm.io/plugin/dbresolver v1.4.4
gorm.io/plugin/soft_delete v1.2.1 gorm.io/plugin/soft_delete v1.2.1
modernc.org/sqlite v1.25.0 modernc.org/sqlite v1.25.0
) )
@ -58,7 +58,8 @@ require (
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230321174746-8dcc6526cfb1 // indirect github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230321174746-8dcc6526cfb1 // indirect
github.com/benbjohnson/clock v1.1.0 // indirect github.com/benbjohnson/clock v1.1.0 // indirect
github.com/bytecodealliance/wasmtime-go/v8 v8.0.0 // indirect github.com/bytecodealliance/wasmtime-go/v8 v8.0.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/clbanning/mxj v1.8.4 // indirect github.com/clbanning/mxj v1.8.4 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/redact v1.1.5 // indirect
@ -126,7 +127,6 @@ require (
github.com/smartwalle/nsign v1.0.8 // indirect github.com/smartwalle/nsign v1.0.8 // indirect
github.com/spf13/afero v1.9.5 // indirect github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.5.1 // indirect github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect github.com/stoewer/go-strcase v1.2.0 // indirect

@ -200,8 +200,9 @@ github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3k
github.com/bytecodealliance/wasmtime-go/v8 v8.0.0 h1:jP4sqm2PHgm3+eQ50zCoCdIyQFkIL/Rtkw6TT8OYPFI= github.com/bytecodealliance/wasmtime-go/v8 v8.0.0 h1:jP4sqm2PHgm3+eQ50zCoCdIyQFkIL/Rtkw6TT8OYPFI=
github.com/bytecodealliance/wasmtime-go/v8 v8.0.0/go.mod h1:tgazNLU7xSC2gfRAM8L4WyE+dgs5yp9FF5/tGebEQyM= github.com/bytecodealliance/wasmtime-go/v8 v8.0.0/go.mod h1:tgazNLU7xSC2gfRAM8L4WyE+dgs5yp9FF5/tGebEQyM=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.9.2 h1:GDaNjuWSGu09guE9Oql0MSTNhNCLlWwO8y/xM5BzcbM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.9.2/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/bytedance/sonic v1.10.0 h1:qtNZduETEIWJVIyDl01BeNxur2rW9OwTQ/yBqFRkKEk=
github.com/bytedance/sonic v1.10.0/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@ -215,8 +216,11 @@ github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOo
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@ -865,6 +869,7 @@ github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -1130,12 +1135,12 @@ github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/pyroscope-io/client v0.7.2-0.20230804044655-36760e422a95 h1:ZpE0l+tD3ykwYWQh/UVdIpxHmr9B6DTtOUBiGw3lB2E= github.com/pyroscope-io/client v0.7.2 h1:OX2qdUQsS8RSkn/3C8isD7f/P0YiZQlRbAlecAaj/R8=
github.com/pyroscope-io/client v0.7.2-0.20230804044655-36760e422a95/go.mod h1:FEocnjn+Ngzxy6EtU9ZxXWRvQ0+pffkrBxHLnPpxwi8= github.com/pyroscope-io/client v0.7.2/go.mod h1:FEocnjn+Ngzxy6EtU9ZxXWRvQ0+pffkrBxHLnPpxwi8=
github.com/pyroscope-io/godeltaprof v0.1.2 h1:MdlEmYELd5w+lvIzmZvXGNMVzW2Qc9jDMuJaPOR75g4= github.com/pyroscope-io/godeltaprof v0.1.2 h1:MdlEmYELd5w+lvIzmZvXGNMVzW2Qc9jDMuJaPOR75g4=
github.com/pyroscope-io/godeltaprof v0.1.2/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE= github.com/pyroscope-io/godeltaprof v0.1.2/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE=
github.com/redis/rueidis v1.0.14 h1:qdFZahk1F/2L+sZeOECx5E2N5J4Qc51b7ezSUpQXJfs= github.com/redis/rueidis v1.0.15 h1:KjTaoP4ab6lpxyCwgIEZ3/rqvKfKnbICe83tVaaItxQ=
github.com/redis/rueidis v1.0.14/go.mod h1:8B+r5wdnjwK3lTFml5VtxjzGOQAC+5UmujoD12pDrEo= github.com/redis/rueidis v1.0.15/go.mod h1:8B+r5wdnjwK3lTFml5VtxjzGOQAC+5UmujoD12pDrEo=
github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
@ -2050,10 +2055,11 @@ gorm.io/gorm v1.21.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.23.0/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.0/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/plugin/dbresolver v1.4.2 h1:IeLSH20ayxbo4rN6HMIQ0ccdsh/fkLK23pp6ivZrqBI= gorm.io/gorm v1.25.3 h1:zi4rHZj1anhZS2EuEODMhDisGy+Daq9jtPrNGgbQYD8=
gorm.io/plugin/dbresolver v1.4.2/go.mod h1:l4Cn87EHLEYuqUncpEeTC2tTJQkjngPSD+lo8hIvcT0= gorm.io/gorm v1.25.3/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/plugin/dbresolver v1.4.4 h1:Dtpr/jSVy48f+BnkPwdoHTLaxcE977wJ7QPt7fxI5Hs=
gorm.io/plugin/dbresolver v1.4.4/go.mod h1:l4Cn87EHLEYuqUncpEeTC2tTJQkjngPSD+lo8hIvcT0=
gorm.io/plugin/soft_delete v1.2.1 h1:qx9D/c4Xu6w5KT8LviX8DgLcB9hkKl6JC9f44Tj7cGU= gorm.io/plugin/soft_delete v1.2.1 h1:qx9D/c4Xu6w5KT8LviX8DgLcB9hkKl6JC9f44Tj7cGU=
gorm.io/plugin/soft_delete v1.2.1/go.mod h1:Zv7vQctOJTGOsJ/bWgrN1n3od0GBAZgnLjEx+cApLGk= gorm.io/plugin/soft_delete v1.2.1/go.mod h1:Zv7vQctOJTGOsJ/bWgrN1n3od0GBAZgnLjEx+cApLGk=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
@ -2160,6 +2166,7 @@ modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfp
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY= modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=
modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4= modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

@ -25,6 +25,7 @@ const (
TableComment = "comment" TableComment = "comment"
TableCommentContent = "comment_content" TableCommentContent = "comment_content"
TableCommentReply = "comment_reply" TableCommentReply = "comment_reply"
TableFollowing = "following"
TableContact = "contact" TableContact = "contact"
TableContactGroup = "contact_group" TableContactGroup = "contact_group"
TableMessage = "message" TableMessage = "message"

@ -305,6 +305,7 @@ func (s *databaseConf) TableNames() (res TableNameMap) {
TableComment, TableComment,
TableCommentContent, TableCommentContent,
TableCommentReply, TableCommentReply,
TableFollowing,
TableContact, TableContact,
TableContactGroup, TableContactGroup,
TableMessage, TableMessage,

@ -30,6 +30,7 @@ type DataService interface {
// 用户服务 // 用户服务
UserManageService UserManageService
ContactManageService ContactManageService
FollowingManageService
// 安全服务 // 安全服务
SecurityService SecurityService

@ -7,10 +7,11 @@ package ms
type ( type (
ContactItem struct { ContactItem struct {
UserId int64 `json:"user_id"` UserId int64 `json:"user_id"`
UserName string `db:"username" json:"username"` Username string `db:"username" json:"username"`
Nickname string `json:"nickname"` Nickname string `json:"nickname"`
Avatar string `json:"avatar"` Avatar string `json:"avatar"`
Phone string `json:"phone"` Phone string `json:"phone,omitempty"`
IsFollow bool `json:"is_follow,omitempty"`
} }
ContactList struct { ContactList struct {

@ -26,3 +26,13 @@ type ContactManageService interface {
GetContacts(userId int64, offset int, limit int) (*ms.ContactList, error) GetContacts(userId int64, offset int, limit int) (*ms.ContactList, error)
IsFriend(userID int64, friendID int64) bool IsFriend(userID int64, friendID int64) bool
} }
// FollowingManageService 关注管理服务
type FollowingManageService interface {
FollowUser(userId int64, followId int64) error
UnfollowUser(userId int64, followId int64) error
ListFollows(userId int64, limit, offset int) (*ms.ContactList, error)
ListFollowings(userId int64, limit, offset int) (*ms.ContactList, error)
GetFollowCount(userId int64) (int64, int64, error)
IsFollow(userId int64, followId int64) bool
}

@ -249,7 +249,7 @@ func (s *contactManageSrv) GetContacts(userId int64, offset int, limit int) (*ms
if c.User != nil { if c.User != nil {
resp.Contacts = append(resp.Contacts, ms.ContactItem{ resp.Contacts = append(resp.Contacts, ms.ContactItem{
UserId: c.FriendId, UserId: c.FriendId,
UserName: c.User.Username, Username: c.User.Username,
Nickname: c.User.Nickname, Nickname: c.User.Nickname,
Avatar: c.User.Avatar, Avatar: c.User.Avatar,
Phone: c.User.Phone, Phone: c.User.Phone,

@ -0,0 +1,87 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package dbr
import (
"github.com/sirupsen/logrus"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type Following struct {
*Model
User *User `json:"-" gorm:"foreignKey:ID;references:FollowId"`
UserId int64 `json:"user_id"`
FollowId int64 `json:"friend_id"`
}
func (f *Following) GetFollowing(db *gorm.DB, userId, followId int64) (*Following, error) {
var following Following
err := db.Omit("User").Unscoped().Where("user_id = ? AND follow_id = ?", userId, followId).First(&following).Error
if err != nil {
logrus.Debugf("Following.GetFollowing get following error:%s", err)
return nil, err
}
return &following, nil
}
func (f *Following) DelFollowing(db *gorm.DB, userId, followId int64) error {
return db.Omit("User").Unscoped().Where("user_id = ? AND follow_id = ?", userId, followId).Delete(f).Error
}
func (f *Following) ListFollows(db *gorm.DB, userId int64, limit int, offset int) (res []*Following, total int64, err error) {
db = db.Model(f).Where("user_id=?", userId)
if err = db.Count(&total).Error; err != nil {
return
}
if offset >= 0 && limit > 0 {
db = db.Offset(offset).Limit(limit)
}
db.Joins("User").Order(clause.OrderByColumn{Column: clause.Column{Table: "User", Name: "nickname"}, Desc: false})
if err = db.Find(&res).Error; err != nil {
return
}
return
}
func (f *Following) ListFollowingIds(db *gorm.DB, userId int64, limit, offset int) (ids []int64, total int64, err error) {
db = db.Model(f).Where("follow_id=?", userId)
if err = db.Count(&total).Error; err != nil {
return
}
if offset >= 0 && limit > 0 {
db = db.Offset(offset).Limit(limit)
}
if err = db.Omit("User").Select("user_id").Find(&ids).Error; err != nil {
return
}
return
}
func (f *Following) FollowCount(db *gorm.DB, userId int64) (follows int64, followings int64, err error) {
if err = db.Model(f).Where("user_id=?", userId).Count(&follows).Error; err != nil {
return
}
if err = db.Model(f).Where("follow_id=?", userId).Count(&followings).Error; err != nil {
return
}
return
}
func (s *Following) IsFollow(db *gorm.DB, userId int64, followId int64) bool {
if _, err := s.GetFollowing(db, userId, followId); err == nil {
return true
}
return false
}
func (f *Following) Create(db *gorm.DB) (*Following, error) {
err := db.Omit("User").Create(f).Error
return f, err
}
func (c *Following) UpdateInUnscoped(db *gorm.DB) error {
return db.Unscoped().Omit("User").Save(c).Error
}

@ -0,0 +1,104 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package jinzhu
import (
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/ms"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"github.com/sirupsen/logrus"
"gorm.io/gorm"
)
var (
_ core.FollowingManageService = (*followingManageSrv)(nil)
)
type followingManageSrv struct {
db *gorm.DB
f *dbr.Following
u *dbr.User
}
func newFollowingManageService(db *gorm.DB) core.FollowingManageService {
return &followingManageSrv{
db: db,
f: &dbr.Following{},
u: &dbr.User{},
}
}
func (s *followingManageSrv) FollowUser(userId int64, followId int64) error {
if _, err := s.f.GetFollowing(s.db, userId, followId); err != nil {
following := &dbr.Following{
UserId: userId,
FollowId: followId,
}
if _, err = following.Create(s.db); err != nil {
logrus.Errorf("contactManageSrv.fetchOrNewContact create new contact err:%s", err)
return err
}
}
return nil
}
func (s *followingManageSrv) UnfollowUser(userId int64, followId int64) error {
return s.f.DelFollowing(s.db, userId, followId)
}
func (s *followingManageSrv) ListFollows(userId int64, limit, offset int) (*ms.ContactList, error) {
follows, totoal, err := s.f.ListFollows(s.db, userId, limit, offset)
if err != nil {
return nil, err
}
res := &ms.ContactList{
Total: totoal,
}
for _, f := range follows {
res.Contacts = append(res.Contacts, ms.ContactItem{
UserId: f.User.ID,
Username: f.User.Username,
Nickname: f.User.Nickname,
Avatar: f.User.Avatar,
IsFollow: true,
})
}
return res, nil
}
func (s *followingManageSrv) ListFollowings(userId int64, limit, offset int) (*ms.ContactList, error) {
followingIds, totoal, err := s.f.ListFollowingIds(s.db, userId, limit, offset)
if err != nil {
return nil, err
}
followings, err := s.u.ListUserInfoById(s.db, followingIds)
if err != nil {
return nil, err
}
res := &ms.ContactList{
Total: totoal,
}
for _, user := range followings {
res.Contacts = append(res.Contacts, ms.ContactItem{
UserId: user.ID,
Username: user.Username,
Nickname: user.Nickname,
Avatar: user.Avatar,
IsFollow: s.IsFollow(userId, user.ID),
})
}
return res, nil
}
func (s *followingManageSrv) GetFollowCount(userId int64) (int64, int64, error) {
return s.f.FollowCount(s.db, userId)
}
func (s *followingManageSrv) IsFollow(userId int64, followId int64) bool {
if _, err := s.f.GetFollowing(s.db, userId, followId); err == nil {
return true
}
return false
}

@ -17,6 +17,7 @@ var (
_comment_ string _comment_ string
_commentContent_ string _commentContent_ string
_commentReply_ string _commentReply_ string
_following_ string
_contact_ string _contact_ string
_contactGroup_ string _contactGroup_ string
_message_ string _message_ string
@ -42,6 +43,7 @@ func initTableName() {
_comment_ = m[conf.TableComment] _comment_ = m[conf.TableComment]
_commentContent_ = m[conf.TableCommentContent] _commentContent_ = m[conf.TableCommentContent]
_commentReply_ = m[conf.TableCommentReply] _commentReply_ = m[conf.TableCommentReply]
_following_ = m[conf.TableFollowing]
_contact_ = m[conf.TableContact] _contact_ = m[conf.TableContact]
_contactGroup_ = m[conf.TableContactGroup] _contactGroup_ = m[conf.TableContactGroup]
_message_ = m[conf.TableMessage] _message_ = m[conf.TableMessage]

@ -42,6 +42,7 @@ type dataSrv struct {
core.CommentManageService core.CommentManageService
core.UserManageService core.UserManageService
core.ContactManageService core.ContactManageService
core.FollowingManageService
core.SecurityService core.SecurityService
core.AttachmentCheckService core.AttachmentCheckService
} }
@ -110,6 +111,7 @@ func NewDataService() (core.DataService, core.VersionInfo) {
CommentManageService: newCommentManageService(db), CommentManageService: newCommentManageService(db),
UserManageService: newUserManageService(db), UserManageService: newUserManageService(db),
ContactManageService: newContactManageService(db), ContactManageService: newContactManageService(db),
FollowingManageService: newFollowingManageService(db),
SecurityService: newSecurityService(db, pvs), SecurityService: newSecurityService(db, pvs),
AttachmentCheckService: security.NewAttachmentCheckService(), AttachmentCheckService: security.NewAttachmentCheckService(),
} }

@ -0,0 +1,56 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package slonik
import (
"github.com/jackc/pgx/v5"
"github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/core/cs"
"github.com/rocboss/paopao-ce/internal/core/ms"
)
var (
_ core.FollowingManageService = (*followingManageSrv)(nil)
)
type followingManageSrv struct {
*pgxSrv
}
func (s *followingManageSrv) FollowUser(userId int64, followId int64) error {
// TODO
return cs.ErrNotImplemented
}
func (s *followingManageSrv) UnfollowUser(userId int64, followId int64) error {
// TDOO
return cs.ErrNotImplemented
}
func (s *followingManageSrv) ListFollows(userId int64, limit, offset int) (*ms.ContactList, error) {
// TODO
return nil, cs.ErrNotImplemented
}
func (s *followingManageSrv) ListFollowings(userId int64, limit, offset int) (*ms.ContactList, error) {
// TODO
return nil, cs.ErrNotImplemented
}
func (s *followingManageSrv) GetFollowCount(userId int64) (int64, int64, error) {
// TODO
return 0, 0, cs.ErrNotImplemented
}
func (s *followingManageSrv) IsFollow(userId int64, followId int64) bool {
// TODO
return false
}
func newFollowingManageService(db *pgx.Conn) core.FollowingManageService {
return &followingManageSrv{
pgxSrv: newPgxSrv(db),
}
}

@ -33,6 +33,7 @@ type dataSrv struct {
core.CommentManageService core.CommentManageService
core.UserManageService core.UserManageService
core.ContactManageService core.ContactManageService
core.FollowingManageService
core.SecurityService core.SecurityService
core.AttachmentCheckService core.AttachmentCheckService
} }
@ -99,6 +100,7 @@ func NewDataService() (core.DataService, core.VersionInfo) {
CommentManageService: newCommentManageService(db), CommentManageService: newCommentManageService(db),
UserManageService: newUserManageService(db), UserManageService: newUserManageService(db),
ContactManageService: newContactManageService(db), ContactManageService: newContactManageService(db),
FollowingManageService: newFollowingManageService(db),
SecurityService: newSecurityService(db, pvs), SecurityService: newSecurityService(db, pvs),
AttachmentCheckService: security.NewAttachmentCheckService(), AttachmentCheckService: security.NewAttachmentCheckService(),
} }

@ -36,8 +36,8 @@ type UserInfoResp struct {
Phone string `json:"phone"` Phone string `json:"phone"`
IsAdmin bool `json:"is_admin"` IsAdmin bool `json:"is_admin"`
CreatedOn int64 `json:"created_on"` CreatedOn int64 `json:"created_on"`
Follows int `json:"follows"` Follows int64 `json:"follows"`
Followings int `json:"followings"` Followings int64 `json:"followings"`
} }
type GetUnreadMsgCountReq struct { type GetUnreadMsgCountReq struct {

@ -76,8 +76,8 @@ type GetUserProfileResp struct {
IsFriend bool `json:"is_friend"` IsFriend bool `json:"is_friend"`
IsFollowing bool `json:"is_following"` IsFollowing bool `json:"is_following"`
CreatedOn int64 `json:"created_on"` CreatedOn int64 `json:"created_on"`
Follows int `json:"follows"` Follows int64 `json:"follows"`
Followings int `json:"followings"` Followings int64 `json:"followings"`
} }
type TopicListReq struct { type TopicListReq struct {

@ -79,6 +79,11 @@ var (
ErrDeleteFriendFailed = xerror.NewError(80006, "删除好友失败") ErrDeleteFriendFailed = xerror.NewError(80006, "删除好友失败")
ErrGetContactsFailed = xerror.NewError(80007, "获取联系人列表失败") ErrGetContactsFailed = xerror.NewError(80007, "获取联系人列表失败")
ErrNoActionToSelf = xerror.NewError(80008, "不允许对自己操作") ErrNoActionToSelf = xerror.NewError(80008, "不允许对自己操作")
ErrFolloUserFailed = xerror.NewError(80100, "关注失败")
ErrUnfollowUserFailed = xerror.NewError(80101, "取消关注失败")
ErrListFollowsFailed = xerror.NewError(80102, "获取关注列表失败")
ErrListFollowingsFailed = xerror.NewError(80103, "获取粉丝列表列表失败")
ErrGetFollowCountFailed = xerror.NewError(80104, "获取关注计数信息失败")
ErrFollowTopicFailed = xerror.NewError(90001, "关注话题失败") ErrFollowTopicFailed = xerror.NewError(90001, "关注话题失败")
ErrUnfollowTopicFailed = xerror.NewError(90002, "取消关注话题失败") ErrUnfollowTopicFailed = xerror.NewError(90002, "取消关注话题失败")

@ -60,6 +60,10 @@ func (s *coreSrv) GetUserInfo(req *web.UserInfoReq) (*web.UserInfoResp, mir.Erro
if user.Model == nil || user.ID < 0 { if user.Model == nil || user.ID < 0 {
return nil, xerror.UnauthorizedAuthNotExist return nil, xerror.UnauthorizedAuthNotExist
} }
follows, followings, err := s.Ds.GetFollowCount(user.ID)
if err != nil {
return nil, web.ErrGetFollowCountFailed
}
resp := &web.UserInfoResp{ resp := &web.UserInfoResp{
Id: user.ID, Id: user.ID,
Nickname: user.Nickname, Nickname: user.Nickname,
@ -69,8 +73,8 @@ func (s *coreSrv) GetUserInfo(req *web.UserInfoReq) (*web.UserInfoResp, mir.Erro
Balance: user.Balance, Balance: user.Balance,
IsAdmin: user.IsAdmin, IsAdmin: user.IsAdmin,
CreatedOn: user.CreatedOn, CreatedOn: user.CreatedOn,
Follows: 0, // TODO Follows: follows,
Followings: 0, // TODO Followings: followings,
} }
if user.Phone != "" && len(user.Phone) == 11 { if user.Phone != "" && len(user.Phone) == 11 {
resp.Phone = user.Phone[0:3] + "****" + user.Phone[7:] resp.Phone = user.Phone[0:3] + "****" + user.Phone[7:]

@ -8,10 +8,10 @@ import (
"github.com/alimy/mir/v4" "github.com/alimy/mir/v4"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
api "github.com/rocboss/paopao-ce/auto/api/v1" api "github.com/rocboss/paopao-ce/auto/api/v1"
"github.com/rocboss/paopao-ce/internal/core/ms"
"github.com/rocboss/paopao-ce/internal/model/web" "github.com/rocboss/paopao-ce/internal/model/web"
"github.com/rocboss/paopao-ce/internal/servants/base" "github.com/rocboss/paopao-ce/internal/servants/base"
"github.com/rocboss/paopao-ce/internal/servants/chain" "github.com/rocboss/paopao-ce/internal/servants/chain"
"github.com/sirupsen/logrus"
) )
var ( var (
@ -28,27 +28,49 @@ func (s *followshipSrv) Chain() gin.HandlersChain {
} }
func (s *followshipSrv) ListFollowings(r *web.ListFollowingsReq) (*web.ListFollowingsResp, mir.Error) { func (s *followshipSrv) ListFollowings(r *web.ListFollowingsReq) (*web.ListFollowingsResp, mir.Error) {
// TODO he, err := s.Ds.GetUserByUsername(r.Username)
res := ms.ContactList{} if err != nil {
logrus.Errorf("Ds.GetUserByUsername err: %s", err)
return nil, web.ErrNoExistUsername
}
res, err := s.Ds.ListFollowings(he.ID, r.PageSize, r.Page-1)
if err != nil {
logrus.Errorf("Ds.ListFollowings err: %s", err)
return nil, web.ErrListFollowingsFailed
}
resp := base.PageRespFrom(res.Contacts, r.Page, r.PageSize, res.Total) resp := base.PageRespFrom(res.Contacts, r.Page, r.PageSize, res.Total)
return (*web.ListFollowingsResp)(resp), nil return (*web.ListFollowingsResp)(resp), nil
} }
func (s *followshipSrv) ListFollows(r *web.ListFollowsReq) (*web.ListFollowsResp, mir.Error) { func (s *followshipSrv) ListFollows(r *web.ListFollowsReq) (*web.ListFollowsResp, mir.Error) {
// TODO he, err := s.Ds.GetUserByUsername(r.Username)
res := ms.ContactList{} if err != nil {
logrus.Errorf("Ds.GetUserByUsername err: %s", err)
return nil, web.ErrNoExistUsername
}
res, err := s.Ds.ListFollows(he.ID, r.PageSize, r.Page-1)
if err != nil {
logrus.Errorf("Ds.ListFollows err: %s", err)
return nil, web.ErrListFollowsFailed
}
resp := base.PageRespFrom(res.Contacts, r.Page, r.PageSize, res.Total) resp := base.PageRespFrom(res.Contacts, r.Page, r.PageSize, res.Total)
return (*web.ListFollowsResp)(resp), nil return (*web.ListFollowsResp)(resp), nil
} }
func (s *followshipSrv) UnfollowUser(r *web.UnfollowUserReq) mir.Error { func (s *followshipSrv) UnfollowUser(r *web.UnfollowUserReq) mir.Error {
// TODO if err := s.Ds.UnfollowUser(r.User.ID, r.UserId); err != nil {
return web.ErrNotImplemented logrus.Errorf("Ds.UnfollowUser err: %s userId: %d followId: %d", err, r.User.ID, r.UserId)
return web.ErrUnfollowUserFailed
}
return nil
} }
func (s *followshipSrv) FollowUser(r *web.FollowUserReq) mir.Error { func (s *followshipSrv) FollowUser(r *web.FollowUserReq) mir.Error {
// TODO if err := s.Ds.FollowUser(r.User.ID, r.UserId); err != nil {
return web.ErrNotImplemented logrus.Errorf("Ds.FollowUser err: %s userId: %d followId: %d", err, r.User.ID, r.UserId)
return web.ErrUnfollowUserFailed
}
return nil
} }
func newFollowshipSrv(s *base.DaoServant) api.Followship { func newFollowshipSrv(s *base.DaoServant) api.Followship {

@ -177,6 +177,14 @@ func (s *looseSrv) GetUserProfile(req *web.GetUserProfileReq) (*web.GetUserProfi
if req.User != nil && req.User.ID != he.ID { if req.User != nil && req.User.ID != he.ID {
isFriend = s.Ds.IsFriend(req.User.ID, he.ID) isFriend = s.Ds.IsFriend(req.User.ID, he.ID)
} }
isFollowing := false
if req.User != nil {
isFollowing = s.Ds.IsFollow(req.User.ID, he.ID)
}
follows, followings, err := s.Ds.GetFollowCount(he.ID)
if err != nil {
return nil, web.ErrGetPostsFailed
}
return &web.GetUserProfileResp{ return &web.GetUserProfileResp{
ID: he.ID, ID: he.ID,
Nickname: he.Nickname, Nickname: he.Nickname,
@ -185,9 +193,10 @@ func (s *looseSrv) GetUserProfile(req *web.GetUserProfileReq) (*web.GetUserProfi
Avatar: he.Avatar, Avatar: he.Avatar,
IsAdmin: he.IsAdmin, IsAdmin: he.IsAdmin,
IsFriend: isFriend, IsFriend: isFriend,
IsFollowing: isFollowing,
CreatedOn: he.CreatedOn, CreatedOn: he.CreatedOn,
Follows: 0, // TODO Follows: follows,
Followings: 0, // TODO Followings: followings,
}, nil }, nil
} }

@ -0,0 +1 @@
DROP TABLE IF EXISTS `p_following`;

@ -0,0 +1,11 @@
CREATE TABLE `p_following` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint unsigned NOT NULL,
`follow_id` bigint unsigned NOT NULL,
`is_del` tinyint NOT NULL DEFAULT 0, -- 是否删除, 0否, 1是
`created_on` bigint unsigned NOT NULL DEFAULT '0',
`modified_on` bigint unsigned NOT NULL DEFAULT '0',
`deleted_on` bigint unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_following_user_follow` (`user_id`,`follow_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

@ -0,0 +1 @@
DROP TABLE IF EXISTS p_following;

@ -0,0 +1,10 @@
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, -- 是否删除, 0否, 1是
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);

@ -0,0 +1 @@
DROP TABLE IF EXISTS "p_following";

@ -0,0 +1,15 @@
CREATE TABLE "p_following" (
"id" integer NOT NULL,
"user_id" integer NOT NULL,
"follow_id" integer NOT NULL,
"is_del" integer NOT NULL,
"created_on" integer NOT NULL,
"modified_on" integer NOT NULL,
"deleted_on" integer NOT NULL,
PRIMARY KEY ("id")
);
CREATE INDEX "idx_following_user_follow"
ON "p_following" (
"user_id" ASC,
"follow_id" ASC
);

@ -318,6 +318,22 @@ CREATE TABLE `p_user` (
KEY `idx_user_phone` (`phone`) USING BTREE KEY `idx_user_phone` (`phone`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=100058 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户'; ) ENGINE=InnoDB AUTO_INCREMENT=100058 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户';
-- ----------------------------
-- Table structure for p_following
-- ----------------------------
DROP TABLE IF EXISTS `p_following`;
CREATE TABLE `p_following` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint unsigned NOT NULL,
`follow_id` bigint unsigned NOT NULL,
`is_del` tinyint NOT NULL DEFAULT 0, -- 是否删除, 0否, 1是
`created_on` bigint unsigned NOT NULL DEFAULT '0',
`modified_on` bigint unsigned NOT NULL DEFAULT '0',
`deleted_on` bigint unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`) USING BTREE,
KEY `idx_following_user_follow` (`user_id`,`follow_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ---------------------------- -- ----------------------------
-- Table structure for p_contact -- Table structure for p_contact
-- ---------------------------- -- ----------------------------

@ -287,6 +287,18 @@ CREATE TABLE p_user (
CREATE UNIQUE INDEX idx_user_username ON p_user USING btree (username); CREATE UNIQUE INDEX idx_user_username ON p_user USING btree (username);
CREATE INDEX idx_user_phone ON p_user USING btree (phone); CREATE INDEX idx_user_phone ON p_user USING btree (phone);
DROP TABLE IF EXISTS p_following;
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, -- 是否删除, 0否, 1是
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);
DROP TABLE IF EXISTS p_contact; DROP TABLE IF EXISTS p_contact;
CREATE TABLE p_contact ( CREATE TABLE p_contact (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,

@ -113,6 +113,21 @@ CREATE TABLE "p_tweet_comment_thumbs" (
"is_del" integer NOT NULL DEFAULT 0 -- 是否删除 0 为未删除、1 为已删除 "is_del" integer NOT NULL DEFAULT 0 -- 是否删除 0 为未删除、1 为已删除
); );
-- ----------------------------
-- Table structure for p_following
-- ----------------------------
DROP TABLE IF EXISTS "p_following";
CREATE TABLE "p_following" (
"id" integer NOT NULL,
"user_id" integer NOT NULL,
"follow_id" integer NOT NULL,
"is_del" integer NOT NULL,
"created_on" integer NOT NULL,
"modified_on" integer NOT NULL,
"deleted_on" integer NOT NULL,
PRIMARY KEY ("id")
);
-- ---------------------------- -- ----------------------------
-- Table structure for p_contact -- Table structure for p_contact
-- ---------------------------- -- ----------------------------
@ -464,6 +479,15 @@ ON "p_tweet_comment_thumbs"(
"tweet_id" ASC "tweet_id" ASC
); );
-- ----------------------------
-- Indexes structure for table p_following
-- ----------------------------
CREATE INDEX "idx_following_user_follow"
ON "p_following" (
"user_id" ASC,
"follow_id" ASC
);
-- ---------------------------- -- ----------------------------
-- Indexes structure for table p_contact -- Indexes structure for table p_contact
-- ---------------------------- -- ----------------------------

Loading…
Cancel
Save