Merge branch 'feature/mir' into feature/sqlx

pull/351/head
Michael Li 2 years ago
commit 895aa90bc6
No known key found for this signature in database

@ -68,6 +68,18 @@ windows-x64:
@echo Build paopao-ce [windows-x64] CGO_ENABLED=$(CGO_ENABLED) @echo Build paopao-ce [windows-x64] CGO_ENABLED=$(CGO_ENABLED)
@CGO_ENABLED=$(CGO_ENABLED) GOOS=windows GOARCH=amd64 go build -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_WINDOWS_AMD64)/$(basename $(TARGET)).exe @CGO_ENABLED=$(CGO_ENABLED) GOOS=windows GOARCH=amd64 go build -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_WINDOWS_AMD64)/$(basename $(TARGET)).exe
.PHONY: generate
generate: gen-mir gen-grpc
.PHONY: gen-mir
gen-mir:
@go generate internal/mirc/main.go
@go fmt ./internal/mirc/...
.PHONY: gen-grpc
gen-grpc:
@go fmt ./internal/proto/...
clean: clean:
@go clean @go clean
@find ./release -type f -exec rm -r {} + @find ./release -type f -exec rm -r {} +

@ -65,7 +65,7 @@ PaoPao主要由以下优秀的开源项目/工具构建
* Redis * Redis
* Zinc * Zinc
\* Zinc是一款轻量级全文搜索引擎可以查阅 <https://zincsearch.com/> 安装 > Zinc是一款轻量级全文搜索引擎可以查阅 <https://zincsearch.com/> 安装
以上环境版本为PaoPao官方的开发版本仅供参考其他版本的环境未进行充分测试 以上环境版本为PaoPao官方的开发版本仅供参考其他版本的环境未进行充分测试
@ -314,40 +314,46 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r
``` ```
目前支持的功能集合: 目前支持的功能集合:
* 数据库: MySQL/Sqlite3/PostgreSQL | 功能项 | 类别 | 状态 | 备注 |
`Gorm` + `MySQL`/`Sqlite3`/`PostgreSQL` 使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM默认使用 `Grom` + `MySQL`组合(目前状态:稳定,默认,推荐使用) | ----- | ----- | ----- | ----- |
`Sqlx` + `MySQL`/`PostgreSQL` 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM(目前状态WIP) |`OldWeb` | 子服务 | 稳定(默认) | 开启旧的Web服务 |
* 对象存储: AliOSS/COS/HuaweiOBS/MinIO/LocalOSS |`Web` | 子服务 | WIP | 开启Web服务|
`AliOSS` 阿里云对象存储服务; |`Admin` | 子服务 | WIP | 开启Admin后台运维服务|
`COS` 腾讯云对象存储服务; |`SpaceX` | 子服务 | WIP | 开启SpaceX服务|
`HuaweiOBS` 华为云对象存储服务; |`Bot` | 子服务 | WIP | 开启Bot服务|
`MinIO` [MinIO](https://github.com/minio/minio)对象存储服务; |`NativeOBS` | 子服务 | WIP | 开启NativeOBS服务|
`S3` AWS S3兼容的对象存储服务 |`Deprecated:Web` | 子服务 | 稳定 | Deprecated(关闭) OldWeb服务|
`LocalOSS` 提供使用本地目录文件作为对象存储的功能,仅用于开发调试环境; |`Gorm` | 数据库 | 稳定(默认) | 使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM默认使用 `Gorm` + `MySQL`组合|
* 缓存: Redis/SimpleCacheIndex/BigCacheIndex |`Sqlx`| 数据库 | WIP | 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM|
`SimpleCacheIndex` 提供简单的 广场推文列表 的缓存功能; |`MySQL`| 数据库 | 稳定(默认) | 使用MySQL作为数据库|
`BigCacheIndex` 使用[BigCache](https://github.com/allegro/bigcache)缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面(推荐使用) |`Postgres`| 数据库 | 稳定 | 使用PostgreSQL作为数据库|
* 搜索: Zinc/Meili |`Sqlite3`| 数据库 | 稳定 | 使用Sqlite3作为数据库|
`Zinc` 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务(目前状态: 稳定,推荐使用) |`AliOSS` | 对象存储 | 稳定(推荐) |阿里云对象存储服务|
`Meili` 基于[Meilisearch](https://github.com/meilisearch/meilisearch)搜索引擎提供推文搜索服务(目前状态: 稳定,推荐使用); |`COS` | 对象存储 | 内测 |腾讯云对象存储服务|
* 日志: LoggerFile/LoggerZinc/LoggerMeili |`HuaweiOBS` | 对象存储 | 内测 |华为云对象存储服务|
`LoggerFile` 使用文件写日志(目前状态: 稳定); |`MinIO` | 对象存储 | 稳定 |[MinIO](https://github.com/minio/minio)对象存储服务|
`LoggerZinc` 使用[Zinc](https://github.com/zinclabs/zinc)写日志(目前状态: 稳定,推荐使用); |`S3` | 对象存储 | 内测 |AWS S3兼容的对象存储服务|
`LoggerMeili` 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志(目前状态: 内测阶段); |`LocalOSS` | 对象存储 | 内测 |提供使用本地目录文件作为对象存储的功能,仅用于开发调试环境|
* 用户关系模式: Friendship/Followship |`OSS:Retention` | 对象存储 | 内测 |基于对象存储系统的对象过期自动删除特性实现 先创建临时对象再持久化的功能|
`Friendship` 弱关系好友模式,类似微信朋友圈(目前状态: 开发阶段); |`OSS:TempDir` | 对象存储 | 内测 |基于对象存储系统的对象拷贝/移动特性实现 先创建临时对象再持久化的功能|
`Followship` 关注者模式类似Twitter的Follow模式(目前状态: WIP); |`Redis` | 缓存 | 稳定 | Redis缓存功能 |
* 支付: Alipay |`SimpleCacheIndex` | 缓存 | 稳定 | 提供简单的 广场推文列表 的缓存功能 |
`Alipay` 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能; |`BigCacheIndex` | 缓存 | 稳定(推荐) | 使用[BigCache](https://github.com/allegro/bigcache)缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面 |
* 短信验证码: SmsJuhe(需要开启sms) |`Zinc` | 搜索 | 稳定(推荐) | 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务 |
`Sms` 开启短信验证码功能,用于手机绑定验证手机是否注册者的;功能如果没有开启,手机绑定时任意短信验证码都可以绑定手机; |`Meili` | 搜索 | 稳定(推荐) | 基于[Meilisearch](https://github.com/meilisearch/meilisearch)搜索引擎提供推文搜索服务 |
* 开发文档: Docs:OpenAPI |`Bleve` | 搜索 | WIP | 基于[Bleve](https://github.com/blevesearch/bleve)搜索引擎提供推文搜索服务 |
`Docs:OpenAPI` 开启openapi文档功能提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi) |`LoggerFile` | 日志 | 稳定 | 使用文件写日志 |
* 其他: PhoneBind/OSS:Retention/OSS:TempDir |`LoggerZinc` | 日志 | 稳定(推荐) | 使用[Zinc](https://github.com/zinclabs/zinc)写日志 |
`PhoneBind` 手机绑定功能; |`LoggerMeili` | 日志 | 内测 | 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志 |
`OSS:Retention` 基于对象存储系统的对象过期自动删除特性实现 先创建临时对象再持久化的功能(目前状态: 内测阶段) |`Friendship` | 关系模式 | 内测(默认) | 弱关系好友模式,类似微信朋友圈 |
`OSS:TempDir` 基于对象存储系统的对象拷贝/移动特性实现 先创建临时对象再持久化的功能(目前状态: 内测阶段) |`Followship` | 关系模式 | WIP | 关注者模式类似Twitter的Follow模式 |
|`Alipay` | 支付 | 稳定 | 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能 |
|`Sms` | 短信验证 | 稳定 | 开启短信验证码功能,用于手机绑定验证手机是否注册者的;功能如果没有开启,手机绑定时任意短信验证码都可以绑定手机 |
|`Docs:OpenAPI` | 开发文档 | 稳定 | 开启openapi文档功能提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi) |
|`PhoneBind` | 其他 | 稳定 | 手机绑定功能 |
> 功能项状态详情参考 [features-status](features-status.md).
### 搭建依赖环境 ### 搭建依赖环境
#### [Zinc](https://github.com/zinclabs/zinc) 搜索引擎: #### [Zinc](https://github.com/zinclabs/zinc) 搜索引擎:
* Zinc运行 * Zinc运行
@ -498,7 +504,7 @@ jc/alimy
代码结构比较简单,很方便扩展,开发文档请参阅[docs](docs '开发文档'). 代码结构比较简单,很方便扩展,开发文档请参阅[docs](docs '开发文档').
## 👯‍♀️ 贡献 ## 👯‍♀️ 贡献
paopao-ce 是一个利用 *业余时间* 本着 **"Just for fun just do it."** 的心态 *持续有序* **开发/优化/维护**的开源项目没有KPI考核、没有Roadmap进度压力、没有技术支持日程安排或许有些许不足之处但是重在精神可嘉。 借用网络中的话 **"F\*k talk, f\*k of tech innovation, Shut up and give me your code."** 一切都因更好的体验,一切都是为了爱好,一切都在代码里;期待老铁们加入,一起开发、一起折腾、一起快乐。 paopao-ce 是一个利用 *业余时间* 本着 **"Just for fun just do it."** 的心态 *持续有序* **开发/优化/维护**的开源项目没有KPI考核、没有Roadmap进度压力、没有技术支持日程安排或许有些许不足之处但是重在精神可嘉。 借用网络中的话 **"F\*k talk, f\*k of tech innovation, Shut up and show me your code."** 一切都因更好的体验,一切都是为了爱好,一切都在代码里;期待老铁们加入,一起开发、一起折腾、一起快乐。
喜欢的朋友记得给个Star欢迎贡献PR。 喜欢的朋友记得给个Star欢迎贡献PR。

@ -1,4 +1,5 @@
App: # APP基础设置项 App: # APP基础设置项
RunMode: debug
AttachmentIncomeRate: 0.8 AttachmentIncomeRate: 0.8
MaxCommentCount: 10 MaxCommentCount: 10
DefaultContextTimeout: 60 DefaultContextTimeout: 60
@ -17,8 +18,40 @@ Features:
Slim: ["Base", "Sqlite3", "LocalOSS", "LoggerFile", "OSS:TempDir"] Slim: ["Base", "Sqlite3", "LocalOSS", "LoggerFile", "OSS:TempDir"]
Base: ["Redis", "PhoneBind"] Base: ["Redis", "PhoneBind"]
Docs: ["Docs:OpenAPI"] Docs: ["Docs:OpenAPI"]
Deprecated: ["Deprecated:OldWeb"]
Service: ["Admin", "SpaceX", "Bot", "LocalOSS"]
Option: ["SimpleCacheIndex"] Option: ["SimpleCacheIndex"]
Sms: "SmsJuhe" Sms: "SmsJuhe"
WebServer: # Web服务
HttpIp: 0.0.0.0
HttpPort: 8010
ReadTimeout: 60
WriteTimeout: 60
AdminServer: # Admin后台运维服务
HttpIp: 0.0.0.0
HttpPort: 8014
ReadTimeout: 60
WriteTimeout: 60
SpaceXServer: # SpaceX服务
HttpIp: 0.0.0.0
HttpPort: 8012
ReadTimeout: 60
WriteTimeout: 60
BotServer: # Bot服务
HttpIp: 0.0.0.0
HttpPort: 8016
ReadTimeout: 60
WriteTimeout: 60
LocalossServer: # Localoss服务
HttpIp: 0.0.0.0
HttpPort: 8018
ReadTimeout: 60
WriteTimeout: 60
DocsServer: # 开发文档服务
HttpIp: 0.0.0.0
HttpPort: 8011
ReadTimeout: 60
WriteTimeout: 60
SmsJuhe: SmsJuhe:
Gateway: https://v.juhe.cn/sms/send Gateway: https://v.juhe.cn/sms/send
Key: Key:

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
//go:build docs //go:build docs
// +build docs // +build docs

@ -0,0 +1,37 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 005| 北野 | 2022-11-21 | 2022-12-10 | v1.0 | 提议 |
### 引入go-mir优化后端架构设计
引入[github.com/alimy/mir/v3](https://github.com/alimy/mir)优化后端的架构设计,使得后端代码更具扩展型。
![](.assets/06-01.png)
### 需求
* 更方便添加后端功能项的实现;
* 优化代码结构,模块化、清晰化代码布局,使得更具扩展性;
* 兼容RESTful/gRPC 服务代码RESTful API是服务于Web/AdmingRPC API是提供给移动端(iOS/Android)的服务;
### 方案
依赖库:
* [go-mir](https://github.com/alimy/mir)
### 疑问
1. 为什么引入go-mir
* [go-mir](https://github.com/alimy/mir)是一套提供类似gRPC服务开发体验的快速开发RESTful API后端开发脚手架巧妙的借用golang语法作为DSL描述RESTful API通过代码生成的方式自动生成相对应的API接口、HTTP服务器框架初始化代码等提供类似gRPC的开发体验对后端开发者非常友好;
* 引入go-mir的另一个主要目的是加速后端服务的开发更好的保证代码风格的一致性;
* 践行 [006-关于paopao-ce的结构设计](006-关于paopao-ce的结构设计.md);
1. 为什么要兼容RESTful/gRPC服务
* RESTful API是提供给Web端使用的包括paopao-ce web端以及后期的运维端admin gRPC API是提供给移动端(iOS/Android)使用的服务;
* RESTful API天然对web端浏览器友好而gRPC生态对后端、移动端天然友好可以根据google-protocol-buffers DSL定义服务API自动生成服务端、客户端代码非常利于开发特别是移动端开发省去了编写客户端网络数据服务相关的业务逻辑只需要专注于页面逻辑编写后端数据获取的网络数据访问逻辑直接调用自动生成的gRPC API客户端代码即可大大的减轻移动端开发的心智负担;
* 后端引入gRPC主要就是考虑到移动端(iOS/Android)开发的开发效率在减轻移动端开发网络数据获取业务逻辑的心智负担上gRPC生态与RESTful生态相比优势明显因此强力引入;
* 再一个就是[go-mir](https://github.com/alimy/mir) v3为RESTful服务的开发提供类似gRPC服务的开发体验也为后端兼容RESTful/gRPC服务创造了很好的条件只要代码结构组织清晰将会有很好的后端开发体验;
>*目前移动端 iOS/Android APP还在规划中这里后续的后端gRPC API服务也是为此做准备敬请期待*
### 更新记录
#### v0.0(2022-11-21) - 北野
* 初始文档
#### v1.0(2022-12-10) - 北野
* 添加内容

@ -2,4 +2,5 @@
* [001-关于paopao-ce的设计定位](001-关于paopao-ce的设计定位.md "关于paopao-ce的设计定位") * [001-关于paopao-ce的设计定位](001-关于paopao-ce的设计定位.md "关于paopao-ce的设计定位")
* [002-关于Friendship功能项的设计](002-关于Friendship功能项的设计.md "关于Friendship功能项的设计") * [002-关于Friendship功能项的设计](002-关于Friendship功能项的设计.md "关于Friendship功能项的设计")
* [003-关于Followship功能项的设计](003-关于Followship功能项的设计.md "关于Followship功能项的设计") * [003-关于Followship功能项的设计](003-关于Followship功能项的设计.md "关于Followship功能项的设计")
* [006-关于paopao-ce的结构设计](006-关于paopao-ce的结构设计.md "关于paopao-ce的结构设计") * [005-引入go-mir优化后端架构设计](005-引入go-mir优化后端架构设计.md "引入go-mir优化后端架构设计")
* [006-关于paopao-ce的结构设计](006-关于paopao-ce的结构设计.md "关于paopao-ce的结构设计")

@ -0,0 +1,163 @@
## Features Status
功能项状态说明。
## 目前支持的功能集合
#### 子服务
* `OldWeb` 开启旧的Web服务(目前状态: 默认)
* [ ] 提按文档
* [x] 服务初始化逻辑
* [x] 接口定义
* [x] 业务逻辑实现
* `Web` 开启Web服务(目前状态: WIP)
* [ ] 提按文档
* [x] 服务初始化逻辑
* [ ] 接口定义
* [ ] 业务逻辑实现
* `Admin` 开启Admin后台运维服务(目前状态: WIP)
* [ ] 提按文档
* [x] 服务初始化逻辑
* [ ] 接口定义
* [ ] 业务逻辑实现
* `SpaceX` 开启SpaceX服务(目前状态: WIP)
* [ ] 提按文档
* [x] 服务初始化逻辑
* [ ] 接口定义
* [ ] 业务逻辑实现
* `Bot` 开启Bot服务(目前状态: WIP)
* [ ] 提按文档
* [x] 服务初始化逻辑
* [ ] 接口定义
* [ ] 业务逻辑实现
* `NativeOBS` 开启NativeOBS服务(目前状态: WIP)
* [ ] 提按文档
* [ ] 服务初始化逻辑
* [ ] 接口定义
* [ ] 业务逻辑实现
* `Deprecated:OldWeb` Deprecated(关闭)旧的Web服务(目前状态: WIP)
* [ ] 提按文档
* [x] 服务初始化逻辑
#### 数据库:
* `Gorm` + `MySQL`/`Sqlite3`/`PostgreSQL`
使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM默认使用 `Grom` + `MySQL`组合(目前状态:稳定,默认,推荐使用)
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `Sqlx` + `MySQL`/`PostgreSQL`
使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM(目前状态WIP)
* [ ] 提按文档
* [ ] 接口定义
* [ ] 业务逻辑实现
#### 对象存储:
* `AliOSS` 阿里云对象存储服务;
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `COS` 腾讯云对象存储服务;
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `HuaweiOBS` 华为云对象存储服务;
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `MinIO` [MinIO](https://github.com/minio/minio)对象存储服务;
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `S3` AWS S3兼容的对象存储服务
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `LocalOSS` 提供使用本地目录文件作为对象存储的功能,仅用于开发调试环境;
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `OSS:Retention` 基于对象存储系统的对象过期自动删除特性实现 先创建临时对象再持久化的功能(目前状态: 内测阶段)
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `OSS:TempDir` 基于对象存储系统的对象拷贝/移动特性实现 先创建临时对象再持久化的功能(目前状态: 内测阶段)
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
#### 缓存:
* `Redis` Redis缓存
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `SimpleCacheIndex` 提供简单的 广场推文列表 的缓存功能能;
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `BigCacheIndex` 使用[BigCache](https://github.com/allegro/bigcache)缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面(推荐使用)
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
#### 搜索:
* `Zinc` 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务(目前状态: 稳定,推荐使用)
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `Meili` 基于[Meilisearch](https://github.com/meilisearch/meilisearch)搜索引擎提供推文搜索服务(目前状态: 稳定,推荐使用);
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `Bleve` 基于[Bleve](https://github.com/blevesearch/bleve)搜索引擎提供推文搜索服务(目前状态: WIP);
* [ ] 提按文档
* [ ] 接口定义
* [ ] 业务逻辑实现
#### 日志:
* `LoggerFile` 使用文件写日志(目前状态: 稳定);
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `LoggerZinc` 使用[Zinc](https://github.com/zinclabs/zinc)写日志(目前状态: 稳定,推荐使用);
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `LoggerMeili` 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志(目前状态: 内测阶段);
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
#### 关系模式:
* `Friendship` 弱关系好友模式,类似微信朋友圈(目前状态: 开发阶段);
* [x] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `Followship` 关注者模式类似Twitter的Follow模式(目前状态: WIP);
* [ ] 提按文档
* [ ] 接口定义
* [ ] 业务逻辑实现
### 支付:
* `Alipay` 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能;
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
### 短信验证:
* SmsJuhe(需要开启sms)
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `Sms` 开启短信验证码功能,用于手机绑定验证手机是否注册者的;功能如果没有开启,手机绑定时任意短信验证码都可以绑定手机;
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
### 开发文档:
* `Docs:OpenAPI` 开启openapi文档功能提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi)
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
### 其他:
* `PhoneBind` 手机绑定功能;
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现

@ -5,6 +5,8 @@ go 1.18
require ( require (
github.com/Masterminds/semver/v3 v3.1.1 github.com/Masterminds/semver/v3 v3.1.1
github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868 github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868
github.com/alimy/cfg v0.1.0
github.com/alimy/mir/v3 v3.0.0-alpha.6
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible
github.com/allegro/bigcache/v3 v3.0.2 github.com/allegro/bigcache/v3 v3.0.2
github.com/bytedance/sonic v1.5.0 github.com/bytedance/sonic v1.5.0

@ -142,6 +142,10 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk=
github.com/alimy/cfg v0.1.0 h1:J7KDLEoVIjEBMGlQJb2ljad/d49gJ4Tsl2ogZ9XNhaY=
github.com/alimy/cfg v0.1.0/go.mod h1:rOxbasTH2srl6StAjNF5Vyi8bfrdkl3fLGmOYtSw81c=
github.com/alimy/mir/v3 v3.0.0-alpha.6 h1:4xcyE12MgzTbcIcYtnt3ILrVrxFjI71qhqh0JL2gB58=
github.com/alimy/mir/v3 v3.0.0-alpha.6/go.mod h1:ybhT2ijOiDn0lLwWzIY6vXdv+uzZrctS7VFfczcXBWU=
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM=
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=

@ -1,3 +1,7 @@
// Copyright 2022 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 conf package conf
import ( import (
@ -5,7 +9,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/rocboss/paopao-ce/pkg/cfg" "github.com/alimy/cfg"
) )
var ( var (
@ -19,7 +23,13 @@ var (
MysqlSetting *MySQLSettingS MysqlSetting *MySQLSettingS
PostgresSetting *PostgresSettingS PostgresSetting *PostgresSettingS
Sqlite3Setting *Sqlite3SettingS Sqlite3Setting *Sqlite3SettingS
ServerSetting *ServerSettingS ServerSetting *HttpServerSettingS
WebServerSetting *HttpServerSettingS
AdminServerSetting *HttpServerSettingS
SpaceXServerSetting *HttpServerSettingS
BotServerSetting *HttpServerSettingS
LocalossServerSetting *HttpServerSettingS
DocsServerSetting *HttpServerSettingS
AppSetting *AppSettingS AppSetting *AppSettingS
CacheIndexSetting *CacheIndexSettingS CacheIndexSetting *CacheIndexSettingS
SimpleCacheIndexSetting *SimpleCacheIndexSettingS SimpleCacheIndexSetting *SimpleCacheIndexSettingS
@ -48,7 +58,7 @@ func setupSetting(suite []string, noDefault bool) error {
// initialize features configure // initialize features configure
ss, kv := setting.featuresInfoFrom("Features") ss, kv := setting.featuresInfoFrom("Features")
cfg.Initialize(ss, kv) cfg.Initial(ss, kv)
if len(suite) > 0 { if len(suite) > 0 {
cfg.Use(suite, noDefault) cfg.Use(suite, noDefault)
} }
@ -56,6 +66,12 @@ func setupSetting(suite []string, noDefault bool) error {
objects := map[string]any{ objects := map[string]any{
"App": &AppSetting, "App": &AppSetting,
"Server": &ServerSetting, "Server": &ServerSetting,
"WebServer": &WebServerSetting,
"AdminServer": &AdminServerSetting,
"SpaceXServer": &SpaceXServerSetting,
"BotServer": &BotServerSetting,
"LocalossServer": &LocalossServerSetting,
"DocsServer": &DocsServerSetting,
"CacheIndex": &CacheIndexSetting, "CacheIndex": &CacheIndexSetting,
"SimpleCacheIndex": &SimpleCacheIndexSetting, "SimpleCacheIndex": &SimpleCacheIndexSetting,
"BigCacheIndex": &BigCacheIndexSetting, "BigCacheIndex": &BigCacheIndexSetting,
@ -134,3 +150,10 @@ func GetOssDomain() string {
} }
return uri + AliOSSSetting.Domain + "/" return uri + AliOSSSetting.Domain + "/"
} }
func RunMode() string {
if !cfg.If("Deprecated:OldWeb") {
return ServerSetting.RunMode
}
return AppSetting.RunMode
}

@ -1,11 +1,15 @@
// Copyright 2022 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 conf package conf
import ( import (
"sync" "sync"
"time" "time"
"github.com/alimy/cfg"
"github.com/go-redis/redis/v8" "github.com/go-redis/redis/v8"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"gorm.io/driver/mysql" "gorm.io/driver/mysql"
"gorm.io/driver/postgres" "gorm.io/driver/postgres"

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
//go:build cgo //go:build cgo
// +build cgo // +build cgo

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
//go:build !cgo //go:build !cgo
// +build !cgo // +build !cgo

@ -1,9 +1,13 @@
// Copyright 2022 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 conf package conf
import ( import (
"io" "io"
"github.com/rocboss/paopao-ce/pkg/cfg" "github.com/alimy/cfg"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"gopkg.in/natefinch/lumberjack.v2" "gopkg.in/natefinch/lumberjack.v2"
) )

@ -1,3 +1,7 @@
// Copyright 2022 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 conf package conf
import ( import (

@ -1,3 +1,7 @@
// Copyright 2022 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 conf package conf
import ( import (

@ -1,3 +1,7 @@
// Copyright 2022 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 conf package conf
import ( import (
@ -41,7 +45,7 @@ type LoggerMeiliSettingS struct {
MinWorker int MinWorker int
} }
type ServerSettingS struct { type HttpServerSettingS struct {
RunMode string RunMode string
HttpIp string HttpIp string
HttpPort string HttpPort string
@ -50,6 +54,7 @@ type ServerSettingS struct {
} }
type AppSettingS struct { type AppSettingS struct {
RunMode string
MaxCommentCount int64 MaxCommentCount int64
AttachmentIncomeRate float64 AttachmentIncomeRate float64
DefaultContextTimeout time.Duration DefaultContextTimeout time.Duration

@ -1,7 +1,10 @@
// Copyright 2022 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 core package core
import ( import (
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/pkg/types" "github.com/rocboss/paopao-ce/pkg/types"
) )
@ -33,23 +36,17 @@ const (
ActCreateActivationCode ActCreateActivationCode
) )
type act uint8 type (
act uint8
type FriendFilter map[int64]types.Empty
type FriendSet map[string]types.Empty
type Action struct { FriendFilter map[int64]types.Empty
Act act FriendSet map[string]types.Empty
UserId int64
}
// AuthorizationManageService 授权管理服务 Action struct {
type AuthorizationManageService interface { Act act
IsAllow(user *model.User, action *Action) bool UserId int64
BeFriendFilter(userId int64) FriendFilter }
BeFriendIds(userId int64) ([]int64, error) )
MyFriendSet(userId int64) FriendSet
}
func (f FriendFilter) IsFriend(userId int64) bool { func (f FriendFilter) IsFriend(userId int64) bool {
_, yeah := f[userId] _, yeah := f[userId]
@ -57,7 +54,7 @@ func (f FriendFilter) IsFriend(userId int64) bool {
} }
// IsAllow default true if user is admin // IsAllow default true if user is admin
func (a act) IsAllow(user *model.User, userId int64, isFriend bool, isActivation bool) bool { func (a act) IsAllow(user *User, userId int64, isFriend bool, isActivation bool) bool {
if user.IsAdmin { if user.IsAdmin {
return true return true
} }
@ -116,3 +113,11 @@ func (a act) IsAllow(user *model.User, userId int64, isFriend bool, isActivation
return false return false
} }
// AuthorizationManageService 授权管理服务
type AuthorizationManageService interface {
IsAllow(user *User, action *Action) bool
BeFriendFilter(userId int64) FriendFilter
BeFriendIds(userId int64) ([]int64, error)
MyFriendSet(userId int64) FriendSet
}

@ -1,6 +1,12 @@
// Copyright 2022 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 core package core
import "github.com/rocboss/paopao-ce/internal/model" import (
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
const ( const (
IdxActNop IdxAct = iota + 1 IdxActNop IdxAct = iota + 1
@ -15,7 +21,7 @@ type IdxAct uint8
type IndexAction struct { type IndexAction struct {
Act IdxAct Act IdxAct
Post *model.Post Post *dbr.Post
} }
func (a IdxAct) String() string { func (a IdxAct) String() string {
@ -37,7 +43,7 @@ func (a IdxAct) String() string {
} }
} }
func NewIndexAction(act IdxAct, post *model.Post) *IndexAction { func NewIndexAction(act IdxAct, post *dbr.Post) *IndexAction {
return &IndexAction{ return &IndexAction{
Act: act, Act: act,
Post: post, Post: post,
@ -48,5 +54,5 @@ func NewIndexAction(act IdxAct, post *model.Post) *IndexAction {
type CacheIndexService interface { type CacheIndexService interface {
IndexPostsService IndexPostsService
SendAction(act IdxAct, post *model.Post) SendAction(act IdxAct, post *dbr.Post)
} }

@ -1,24 +1,36 @@
// Copyright 2022 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 core package core
import ( import (
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
type (
Comment = dbr.Comment
CommentFormated = dbr.CommentFormated
CommentReply = dbr.CommentReply
CommentContent = dbr.CommentContent
CommentReplyFormated = dbr.CommentReplyFormated
) )
// CommentService 评论检索服务 // CommentService 评论检索服务
type CommentService interface { type CommentService interface {
GetComments(conditions *model.ConditionsT, offset, limit int) ([]*model.Comment, error) GetComments(conditions *ConditionsT, offset, limit int) ([]*Comment, error)
GetCommentByID(id int64) (*model.Comment, error) GetCommentByID(id int64) (*Comment, error)
GetCommentCount(conditions *model.ConditionsT) (int64, error) GetCommentCount(conditions *ConditionsT) (int64, error)
GetCommentReplyByID(id int64) (*model.CommentReply, error) GetCommentReplyByID(id int64) (*CommentReply, error)
GetCommentContentsByIDs(ids []int64) ([]*model.CommentContent, error) GetCommentContentsByIDs(ids []int64) ([]*CommentContent, error)
GetCommentRepliesByID(ids []int64) ([]*model.CommentReplyFormated, error) GetCommentRepliesByID(ids []int64) ([]*CommentReplyFormated, error)
} }
// CommentManageService 评论管理服务 // CommentManageService 评论管理服务
type CommentManageService interface { type CommentManageService interface {
DeleteComment(comment *model.Comment) error DeleteComment(comment *Comment) error
CreateComment(comment *model.Comment) (*model.Comment, error) CreateComment(comment *Comment) (*Comment, error)
CreateCommentReply(reply *model.CommentReply) (*model.CommentReply, error) CreateCommentReply(reply *CommentReply) (*CommentReply, error)
DeleteCommentReply(reply *model.CommentReply) error DeleteCommentReply(reply *CommentReply) error
CreateCommentContent(content *model.CommentContent) (*model.CommentContent, error) CreateCommentContent(content *CommentContent) (*CommentContent, error)
} }

@ -1,3 +1,7 @@
// Copyright 2022 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 core package core
// DataService 数据服务集成 // DataService 数据服务集成

@ -1,15 +1,36 @@
// Copyright 2022 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 core package core
import ( import (
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
const (
MsgTypePost = dbr.MsgTypePost
MsgtypeComment = dbr.MsgtypeComment
MsgTypeReply = dbr.MsgTypeReply
MsgTypeWhisper = dbr.MsgTypeWhisper
MsgTypeRequestingFriend = dbr.MsgTypeRequestingFriend
MsgTypeSystem = dbr.MsgTypeSystem
MsgStatusUnread = dbr.MsgStatusUnread
MsgStatusReaded = dbr.MsgStatusReaded
)
type (
Message = dbr.Message
MessageFormated = dbr.MessageFormated
) )
// MessageService 消息服务 // MessageService 消息服务
type MessageService interface { type MessageService interface {
CreateMessage(msg *model.Message) (*model.Message, error) CreateMessage(msg *Message) (*Message, error)
GetUnreadCount(userID int64) (int64, error) GetUnreadCount(userID int64) (int64, error)
GetMessageByID(id int64) (*model.Message, error) GetMessageByID(id int64) (*Message, error)
ReadMessage(message *model.Message) error ReadMessage(message *Message) error
GetMessages(conditions *model.ConditionsT, offset, limit int) ([]*model.MessageFormated, error) GetMessages(conditions *ConditionsT, offset, limit int) ([]*MessageFormated, error)
GetMessageCount(conditions *model.ConditionsT) (int64, error) GetMessageCount(conditions *ConditionsT) (int64, error)
} }

@ -1,7 +1,11 @@
// Copyright 2022 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 core package core
import ( import (
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
) )
const ( const (
@ -9,28 +13,39 @@ const (
SearchTypeTag SearchType = "tag" SearchTypeTag SearchType = "tag"
) )
type SearchType string const (
PostVisitPublic = dbr.PostVisitPublic
PostVisitPrivate = dbr.PostVisitPrivate
PostVisitFriend = dbr.PostVisitFriend
PostVisitInvalid = dbr.PostVisitInvalid
)
type QueryReq struct { type (
Query string PostVisibleT = dbr.PostVisibleT
Visibility []model.PostVisibleT
Type SearchType
}
type QueryResp struct { SearchType string
Items []*model.PostFormated
Total int64
}
type TsDocItem struct { QueryReq struct {
Post *model.Post Query string
Content string Visibility []PostVisibleT
} Type SearchType
}
QueryResp struct {
Items []*PostFormated
Total int64
}
TsDocItem struct {
Post *Post
Content string
}
)
// TweetSearchService tweet search service interface // TweetSearchService tweet search service interface
type TweetSearchService interface { type TweetSearchService interface {
IndexName() string IndexName() string
AddDocuments(data []TsDocItem, primaryKey ...string) (bool, error) AddDocuments(data []TsDocItem, primaryKey ...string) (bool, error)
DeleteDocuments(identifiers []string) error DeleteDocuments(identifiers []string) error
Search(user *model.User, q *QueryReq, offset, limit int) (*QueryResp, error) Search(user *User, q *QueryReq, offset, limit int) (*QueryResp, error)
} }

@ -1,13 +1,21 @@
// Copyright 2022 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 core package core
import ( import (
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
type (
Captcha = dbr.Captcha
) )
// SecurityService 安全相关服务 // SecurityService 安全相关服务
type SecurityService interface { type SecurityService interface {
GetLatestPhoneCaptcha(phone string) (*model.Captcha, error) GetLatestPhoneCaptcha(phone string) (*Captcha, error)
UsePhoneCaptcha(captcha *model.Captcha) error UsePhoneCaptcha(captcha *Captcha) error
SendPhoneCaptcha(phone string) error SendPhoneCaptcha(phone string) error
} }

@ -1,3 +1,7 @@
// Copyright 2022 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 core package core
import ( import (

@ -1,13 +1,22 @@
// Copyright 2022 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 core package core
import ( import (
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
type (
Tag = dbr.Tag
TagFormated = dbr.TagFormated
) )
// TopicService 话题服务 // TopicService 话题服务
type TopicService interface { type TopicService interface {
CreateTag(tag *model.Tag) (*model.Tag, error) CreateTag(tag *Tag) (*Tag, error)
DeleteTag(tag *model.Tag) error DeleteTag(tag *Tag) error
GetTags(conditions *model.ConditionsT, offset, limit int) ([]*model.Tag, error) GetTags(conditions *ConditionsT, offset, limit int) ([]*Tag, error)
GetTagsByKeyword(keyword string) ([]*model.Tag, error) GetTagsByKeyword(keyword string) ([]*Tag, error)
} }

@ -1,49 +1,83 @@
// Copyright 2022 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 core package core
import ( import (
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"github.com/rocboss/paopao-ce/internal/model/rest" )
const (
AttachmentTypeImage = dbr.AttachmentTypeImage
AttachmentTypeVideo = dbr.AttachmentTypeVideo
AttachmentTypeOther = dbr.AttachmentTypeOther
// 类型1标题2文字段落3图片地址4视频地址5语音地址6链接地址7附件资源
ContentTypeTitle = dbr.ContentTypeTitle
ContentTypeText = dbr.ContentTypeText
ContentTypeImage = dbr.ContentTypeImage
ContentTypeVideo = dbr.ContentTypeVideo
ContentTypeAudio = dbr.ContentTypeAudio
ContentTypeLink = dbr.ContentTypeLink
ContentTypeAttachment = dbr.ContentTypeAttachment
ContentTypeChargeAttachment = dbr.ContentTypeChargeAttachment
)
type (
PostStar = dbr.PostStar
PostCollection = dbr.PostCollection
PostAttachmentBill = dbr.PostAttachmentBill
PostContent = dbr.PostContent
Attachment = dbr.Attachment
AttachmentType = dbr.AttachmentType
PostContentT = dbr.PostContentT
IndexTweetList struct {
Tweets []*PostFormated
Total int64
}
) )
// TweetService 推文检索服务 // TweetService 推文检索服务
type TweetService interface { type TweetService interface {
GetPostByID(id int64) (*model.Post, error) GetPostByID(id int64) (*Post, error)
GetPosts(conditions *model.ConditionsT, offset, limit int) ([]*model.Post, error) GetPosts(conditions *ConditionsT, offset, limit int) ([]*Post, error)
GetPostCount(conditions *model.ConditionsT) (int64, error) GetPostCount(conditions *ConditionsT) (int64, error)
GetUserPostStar(postID, userID int64) (*model.PostStar, error) GetUserPostStar(postID, userID int64) (*PostStar, error)
GetUserPostStars(userID int64, offset, limit int) ([]*model.PostStar, error) GetUserPostStars(userID int64, offset, limit int) ([]*PostStar, error)
GetUserPostStarCount(userID int64) (int64, error) GetUserPostStarCount(userID int64) (int64, error)
GetUserPostCollection(postID, userID int64) (*model.PostCollection, error) GetUserPostCollection(postID, userID int64) (*PostCollection, error)
GetUserPostCollections(userID int64, offset, limit int) ([]*model.PostCollection, error) GetUserPostCollections(userID int64, offset, limit int) ([]*PostCollection, error)
GetUserPostCollectionCount(userID int64) (int64, error) GetUserPostCollectionCount(userID int64) (int64, error)
GetPostAttatchmentBill(postID, userID int64) (*model.PostAttachmentBill, error) GetPostAttatchmentBill(postID, userID int64) (*PostAttachmentBill, error)
GetPostContentsByIDs(ids []int64) ([]*model.PostContent, error) GetPostContentsByIDs(ids []int64) ([]*PostContent, error)
GetPostContentByID(id int64) (*model.PostContent, error) GetPostContentByID(id int64) (*PostContent, error)
} }
// TweetManageService 推文管理服务,包括创建/删除/更新推文 // TweetManageService 推文管理服务,包括创建/删除/更新推文
type TweetManageService interface { type TweetManageService interface {
CreateAttachment(attachment *model.Attachment) (*model.Attachment, error) CreateAttachment(attachment *Attachment) (*Attachment, error)
CreatePost(post *model.Post) (*model.Post, error) CreatePost(post *Post) (*Post, error)
DeletePost(post *model.Post) ([]string, error) DeletePost(post *Post) ([]string, error)
LockPost(post *model.Post) error LockPost(post *Post) error
StickPost(post *model.Post) error StickPost(post *Post) error
VisiblePost(post *model.Post, visibility model.PostVisibleT) error VisiblePost(post *Post, visibility PostVisibleT) error
UpdatePost(post *model.Post) error UpdatePost(post *Post) error
CreatePostStar(postID, userID int64) (*model.PostStar, error) CreatePostStar(postID, userID int64) (*PostStar, error)
DeletePostStar(p *model.PostStar) error DeletePostStar(p *PostStar) error
CreatePostCollection(postID, userID int64) (*model.PostCollection, error) CreatePostCollection(postID, userID int64) (*PostCollection, error)
DeletePostCollection(p *model.PostCollection) error DeletePostCollection(p *PostCollection) error
CreatePostContent(content *model.PostContent) (*model.PostContent, error) CreatePostContent(content *PostContent) (*PostContent, error)
} }
// TweetHelpService 推文辅助服务 // TweetHelpService 推文辅助服务
type TweetHelpService interface { type TweetHelpService interface {
RevampPosts(posts []*model.PostFormated) ([]*model.PostFormated, error) RevampPosts(posts []*PostFormated) ([]*PostFormated, error)
MergePosts(posts []*model.Post) ([]*model.PostFormated, error) MergePosts(posts []*Post) ([]*PostFormated, error)
} }
// IndexPostsService 广场首页推文列表服务 // IndexPostsService 广场首页推文列表服务
type IndexPostsService interface { type IndexPostsService interface {
IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) IndexPosts(user *User, offset int, limit int) (*IndexTweetList, error)
} }

@ -0,0 +1,24 @@
// Copyright 2022 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 core
import (
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
const (
UserStatusNormal = dbr.UserStatusNormal
UserStatusClosed = dbr.UserStatusClosed
)
type (
User = dbr.User
Post = dbr.Post
ConditionsT = dbr.ConditionsT
PostFormated = dbr.PostFormated
UserFormated = dbr.UserFormated
PostContentFormated = dbr.PostContentFormated
Model = dbr.Model
)

@ -1,19 +1,33 @@
// Copyright 2022 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 core package core
import ( type (
"github.com/rocboss/paopao-ce/internal/model" ContactItem struct {
"github.com/rocboss/paopao-ce/internal/model/rest" UserId int64 `json:"user_id"`
UserName string `json:"username"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
Phone string `json:"phone"`
}
ContactList struct {
Contacts []ContactItem `json:"contacts"`
Total int64 `json:"total"`
}
) )
// UserManageService 用户管理服务 // UserManageService 用户管理服务
type UserManageService interface { type UserManageService interface {
GetUserByID(id int64) (*model.User, error) GetUserByID(id int64) (*User, error)
GetUserByUsername(username string) (*model.User, error) GetUserByUsername(username string) (*User, error)
GetUserByPhone(phone string) (*model.User, error) GetUserByPhone(phone string) (*User, error)
GetUsersByIDs(ids []int64) ([]*model.User, error) GetUsersByIDs(ids []int64) ([]*User, error)
GetUsersByKeyword(keyword string) ([]*model.User, error) GetUsersByKeyword(keyword string) ([]*User, error)
CreateUser(user *model.User) (*model.User, error) CreateUser(user *User) (*User, error)
UpdateUser(user *model.User) error UpdateUser(user *User) error
} }
// ContactManageService 联系人管理服务 // ContactManageService 联系人管理服务
@ -22,6 +36,6 @@ type ContactManageService interface {
AddFriend(userId int64, friendId int64) error AddFriend(userId int64, friendId int64) error
RejectFriend(userId int64, friendId int64) error RejectFriend(userId int64, friendId int64) error
DeleteFriend(userId int64, friendId int64) error DeleteFriend(userId int64, friendId int64) error
GetContacts(userId int64, offset int, limit int) (*rest.ContactsResp, error) GetContacts(userId int64, offset int, limit int) (*ContactList, error)
IsFriend(userID int64, friendID int64) bool IsFriend(userID int64, friendID int64) bool
} }

@ -1,3 +1,7 @@
// Copyright 2022 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 core package core
import ( import (

@ -1,15 +1,24 @@
// Copyright 2022 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 core package core
import ( import (
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
type (
WalletStatement = dbr.WalletStatement
WalletRecharge = dbr.WalletRecharge
) )
// WalletService wallet service interface // WalletService wallet service interface
type WalletService interface { type WalletService interface {
GetUserWalletBills(userID int64, offset, limit int) ([]*model.WalletStatement, error) GetUserWalletBills(userID int64, offset, limit int) ([]*WalletStatement, error)
GetUserWalletBillCount(userID int64) (int64, error) GetUserWalletBillCount(userID int64) (int64, error)
GetRechargeByID(id int64) (*model.WalletRecharge, error) GetRechargeByID(id int64) (*WalletRecharge, error)
CreateRecharge(userId, amount int64) (*model.WalletRecharge, error) CreateRecharge(userId, amount int64) (*WalletRecharge, error)
HandleRechargeSuccess(recharge *model.WalletRecharge, tradeNo string) error HandleRechargeSuccess(recharge *WalletRecharge, tradeNo string) error
HandlePostAttachmentBought(post *model.Post, user *model.User) error HandlePostAttachmentBought(post *Post, user *User) error
} }

@ -1,3 +1,7 @@
// Copyright 2022 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 cache package cache
import ( import (
@ -11,8 +15,6 @@ import (
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/allegro/bigcache/v3" "github.com/allegro/bigcache/v3"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/model/rest"
"github.com/rocboss/paopao-ce/pkg/types" "github.com/rocboss/paopao-ce/pkg/types"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -24,7 +26,7 @@ var (
type postsEntry struct { type postsEntry struct {
key string key string
tweets *rest.IndexTweetsResp tweets *core.IndexTweetList
} }
type bigCacheIndexServant struct { type bigCacheIndexServant struct {
@ -38,7 +40,7 @@ type bigCacheIndexServant struct {
preventDuration time.Duration preventDuration time.Duration
} }
func (s *bigCacheIndexServant) IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) { func (s *bigCacheIndexServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) {
key := s.keyFrom(user, offset, limit) key := s.keyFrom(user, offset, limit)
posts, err := s.getPosts(key) posts, err := s.getPosts(key)
if err == nil { if err == nil {
@ -54,7 +56,7 @@ func (s *bigCacheIndexServant) IndexPosts(user *model.User, offset int, limit in
return posts, nil return posts, nil
} }
func (s *bigCacheIndexServant) getPosts(key string) (*rest.IndexTweetsResp, error) { func (s *bigCacheIndexServant) getPosts(key string) (*core.IndexTweetList, error) {
data, err := s.cache.Get(key) data, err := s.cache.Get(key)
if err != nil { if err != nil {
logrus.Debugf("bigCacheIndexServant.getPosts get posts by key: %s from cache err: %v", key, err) logrus.Debugf("bigCacheIndexServant.getPosts get posts by key: %s from cache err: %v", key, err)
@ -62,7 +64,7 @@ func (s *bigCacheIndexServant) getPosts(key string) (*rest.IndexTweetsResp, erro
} }
buf := bytes.NewBuffer(data) buf := bytes.NewBuffer(data)
dec := gob.NewDecoder(buf) dec := gob.NewDecoder(buf)
var resp rest.IndexTweetsResp var resp core.IndexTweetList
if err := dec.Decode(&resp); err != nil { if err := dec.Decode(&resp); err != nil {
logrus.Debugf("bigCacheIndexServant.getPosts get posts from cache in decode err: %v", err) logrus.Debugf("bigCacheIndexServant.getPosts get posts from cache in decode err: %v", err)
return nil, err return nil, err
@ -70,7 +72,7 @@ func (s *bigCacheIndexServant) getPosts(key string) (*rest.IndexTweetsResp, erro
return &resp, nil return &resp, nil
} }
func (s *bigCacheIndexServant) cachePosts(key string, tweets *rest.IndexTweetsResp) { func (s *bigCacheIndexServant) cachePosts(key string, tweets *core.IndexTweetList) {
entry := &postsEntry{key: key, tweets: tweets} entry := &postsEntry{key: key, tweets: tweets}
select { select {
case s.cachePostsCh <- entry: case s.cachePostsCh <- entry:
@ -96,7 +98,7 @@ func (s *bigCacheIndexServant) setPosts(entry *postsEntry) {
logrus.Debugf("bigCacheIndexServant.setPosts setPosts set cache by key: %s", entry.key) logrus.Debugf("bigCacheIndexServant.setPosts setPosts set cache by key: %s", entry.key)
} }
func (s *bigCacheIndexServant) keyFrom(user *model.User, offset int, limit int) string { func (s *bigCacheIndexServant) keyFrom(user *core.User, offset int, limit int) string {
var userId int64 = -1 var userId int64 = -1
if user != nil { if user != nil {
userId = user.ID userId = user.ID
@ -104,7 +106,7 @@ func (s *bigCacheIndexServant) keyFrom(user *model.User, offset int, limit int)
return fmt.Sprintf("index:%d:%d:%d", userId, offset, limit) return fmt.Sprintf("index:%d:%d:%d", userId, offset, limit)
} }
func (s *bigCacheIndexServant) SendAction(act core.IdxAct, post *model.Post) { func (s *bigCacheIndexServant) SendAction(act core.IdxAct, post *core.Post) {
action := core.NewIndexAction(act, post) action := core.NewIndexAction(act, post)
select { select {
case s.indexActionCh <- action: case s.indexActionCh <- action:
@ -134,7 +136,7 @@ func (s *bigCacheIndexServant) handleIndexAction(action *core.IndexAction) {
// 创建/删除 私密推文特殊处理 // 创建/删除 私密推文特殊处理
switch act { switch act {
case core.IdxActCreatePost, core.IdxActDeletePost: case core.IdxActCreatePost, core.IdxActDeletePost:
if post.Visibility == model.PostVisitPrivate { if post.Visibility == core.PostVisitPrivate {
s.deleteCacheByUserId(post.UserID, true) s.deleteCacheByUserId(post.UserID, true)
return return
} }

@ -1,3 +1,7 @@
// Copyright 2022 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 cache package cache
import ( import (

@ -1,10 +1,12 @@
// Copyright 2022 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 cache package cache
import ( import (
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/model/rest"
) )
var ( var (
@ -16,11 +18,11 @@ type noneCacheIndexServant struct {
ips core.IndexPostsService ips core.IndexPostsService
} }
func (s *noneCacheIndexServant) IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) { func (s *noneCacheIndexServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) {
return s.ips.IndexPosts(user, offset, limit) return s.ips.IndexPosts(user, offset, limit)
} }
func (s *noneCacheIndexServant) SendAction(_act core.IdxAct, _post *model.Post) { func (s *noneCacheIndexServant) SendAction(_act core.IdxAct, _post *core.Post) {
// empty // empty
} }

@ -1,3 +1,7 @@
// Copyright 2022 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 cache package cache
import ( import (
@ -6,8 +10,6 @@ import (
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/internal/model/rest"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -20,21 +22,21 @@ type simpleCacheIndexServant struct {
ips core.IndexPostsService ips core.IndexPostsService
indexActionCh chan core.IdxAct indexActionCh chan core.IdxAct
indexPosts *rest.IndexTweetsResp indexPosts *core.IndexTweetList
atomicIndex atomic.Value atomicIndex atomic.Value
maxIndexSize int maxIndexSize int
checkTick *time.Ticker checkTick *time.Ticker
expireIndexTick *time.Ticker expireIndexTick *time.Ticker
} }
func (s *simpleCacheIndexServant) IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) { func (s *simpleCacheIndexServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) {
cacheResp := s.atomicIndex.Load().(*rest.IndexTweetsResp) cacheResp := s.atomicIndex.Load().(*core.IndexTweetList)
end := offset + limit end := offset + limit
if cacheResp != nil { if cacheResp != nil {
size := len(cacheResp.Tweets) size := len(cacheResp.Tweets)
logrus.Debugf("simpleCacheIndexServant.IndexPosts get index posts from cache posts: %d offset:%d limit:%d start:%d, end:%d", size, offset, limit, offset, end) logrus.Debugf("simpleCacheIndexServant.IndexPosts get index posts from cache posts: %d offset:%d limit:%d start:%d, end:%d", size, offset, limit, offset, end)
if size >= end { if size >= end {
return &rest.IndexTweetsResp{ return &core.IndexTweetList{
Tweets: cacheResp.Tweets[offset:end], Tweets: cacheResp.Tweets[offset:end],
Total: cacheResp.Total, Total: cacheResp.Total,
}, nil }, nil
@ -45,7 +47,7 @@ func (s *simpleCacheIndexServant) IndexPosts(user *model.User, offset int, limit
return s.ips.IndexPosts(user, offset, limit) return s.ips.IndexPosts(user, offset, limit)
} }
func (s *simpleCacheIndexServant) SendAction(act core.IdxAct, _post *model.Post) { func (s *simpleCacheIndexServant) SendAction(act core.IdxAct, _post *core.Post) {
select { select {
case s.indexActionCh <- act: case s.indexActionCh <- act:
logrus.Debugf("simpleCacheIndexServant.SendAction send indexAction by chan: %s", act) logrus.Debugf("simpleCacheIndexServant.SendAction send indexAction by chan: %s", act)

@ -1,15 +1,19 @@
// Copyright 2022 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 dao package dao
import ( import (
"sync" "sync"
"github.com/alimy/cfg"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu" "github.com/rocboss/paopao-ce/internal/dao/jinzhu"
"github.com/rocboss/paopao-ce/internal/dao/sakila" "github.com/rocboss/paopao-ce/internal/dao/sakila"
"github.com/rocboss/paopao-ce/internal/dao/search" "github.com/rocboss/paopao-ce/internal/dao/search"
"github.com/rocboss/paopao-ce/internal/dao/slonik" "github.com/rocboss/paopao-ce/internal/dao/slonik"
"github.com/rocboss/paopao-ce/internal/dao/storage" "github.com/rocboss/paopao-ce/internal/dao/storage"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )

@ -1,8 +1,12 @@
// Copyright 2022 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 package jinzhu
import ( import (
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"github.com/rocboss/paopao-ce/pkg/types" "github.com/rocboss/paopao-ce/pkg/types"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -21,7 +25,7 @@ func newAuthorizationManageService(db *gorm.DB) core.AuthorizationManageService
} }
} }
func (s *authorizationManageServant) IsAllow(user *model.User, action *core.Action) bool { func (s *authorizationManageServant) IsAllow(user *core.User, action *core.Action) bool {
// user is activation if had bind phone // user is activation if had bind phone
isActivation := (len(user.Phone) != 0) isActivation := (len(user.Phone) != 0)
isFriend := s.isFriend(user.ID, action.UserId) isFriend := s.isFriend(user.ID, action.UserId)
@ -30,7 +34,7 @@ func (s *authorizationManageServant) IsAllow(user *model.User, action *core.Acti
} }
func (s *authorizationManageServant) MyFriendSet(userId int64) core.FriendSet { func (s *authorizationManageServant) MyFriendSet(userId int64) core.FriendSet {
ids, err := (&model.Contact{UserId: userId}).MyFriendIds(s.db) ids, err := (&dbr.Contact{UserId: userId}).MyFriendIds(s.db)
if err != nil { if err != nil {
return core.FriendSet{} return core.FriendSet{}
} }
@ -43,7 +47,7 @@ func (s *authorizationManageServant) MyFriendSet(userId int64) core.FriendSet {
} }
func (s *authorizationManageServant) BeFriendFilter(userId int64) core.FriendFilter { func (s *authorizationManageServant) BeFriendFilter(userId int64) core.FriendFilter {
ids, err := (&model.Contact{FriendId: userId}).BeFriendIds(s.db) ids, err := (&dbr.Contact{FriendId: userId}).BeFriendIds(s.db)
if err != nil { if err != nil {
return core.FriendFilter{} return core.FriendFilter{}
} }
@ -56,12 +60,12 @@ func (s *authorizationManageServant) BeFriendFilter(userId int64) core.FriendFil
} }
func (s *authorizationManageServant) BeFriendIds(userId int64) ([]int64, error) { func (s *authorizationManageServant) BeFriendIds(userId int64) ([]int64, error) {
return (&model.Contact{FriendId: userId}).BeFriendIds(s.db) return (&dbr.Contact{FriendId: userId}).BeFriendIds(s.db)
} }
func (s *authorizationManageServant) isFriend(userId int64, friendId int64) bool { func (s *authorizationManageServant) isFriend(userId int64, friendId int64) bool {
contact, err := (&model.Contact{UserId: friendId, FriendId: userId}).GetByUserFriend(s.db) contact, err := (&dbr.Contact{UserId: friendId, FriendId: userId}).GetByUserFriend(s.db)
if err == nil || contact.Status == model.ContactStatusAgree { if err == nil || contact.Status == dbr.ContactStatusAgree {
return true return true
} }
return false return false

@ -1,8 +1,12 @@
// Copyright 2022 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 package jinzhu
import ( import (
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -31,42 +35,42 @@ func newCommentManageService(db *gorm.DB) core.CommentManageService {
} }
} }
func (s *commentServant) GetComments(conditions *model.ConditionsT, offset, limit int) ([]*model.Comment, error) { func (s *commentServant) GetComments(conditions *core.ConditionsT, offset, limit int) ([]*core.Comment, error) {
return (&model.Comment{}).List(s.db, conditions, offset, limit) return (&dbr.Comment{}).List(s.db, conditions, offset, limit)
} }
func (s *commentServant) GetCommentByID(id int64) (*model.Comment, error) { func (s *commentServant) GetCommentByID(id int64) (*core.Comment, error) {
comment := &model.Comment{ comment := &dbr.Comment{
Model: &model.Model{ Model: &dbr.Model{
ID: id, ID: id,
}, },
} }
return comment.Get(s.db) return comment.Get(s.db)
} }
func (s *commentServant) GetCommentReplyByID(id int64) (*model.CommentReply, error) { func (s *commentServant) GetCommentReplyByID(id int64) (*core.CommentReply, error) {
reply := &model.CommentReply{ reply := &dbr.CommentReply{
Model: &model.Model{ Model: &dbr.Model{
ID: id, ID: id,
}, },
} }
return reply.Get(s.db) return reply.Get(s.db)
} }
func (s *commentServant) GetCommentCount(conditions *model.ConditionsT) (int64, error) { func (s *commentServant) GetCommentCount(conditions *core.ConditionsT) (int64, error) {
return (&model.Comment{}).Count(s.db, conditions) return (&dbr.Comment{}).Count(s.db, conditions)
} }
func (s *commentServant) GetCommentContentsByIDs(ids []int64) ([]*model.CommentContent, error) { func (s *commentServant) GetCommentContentsByIDs(ids []int64) ([]*core.CommentContent, error) {
commentContent := &model.CommentContent{} commentContent := &dbr.CommentContent{}
return commentContent.List(s.db, &model.ConditionsT{ return commentContent.List(s.db, &dbr.ConditionsT{
"comment_id IN ?": ids, "comment_id IN ?": ids,
}, 0, 0) }, 0, 0)
} }
func (s *commentServant) GetCommentRepliesByID(ids []int64) ([]*model.CommentReplyFormated, error) { func (s *commentServant) GetCommentRepliesByID(ids []int64) ([]*core.CommentReplyFormated, error) {
CommentReply := &model.CommentReply{} CommentReply := &dbr.CommentReply{}
replies, err := CommentReply.List(s.db, &model.ConditionsT{ replies, err := CommentReply.List(s.db, &dbr.ConditionsT{
"comment_id IN ?": ids, "comment_id IN ?": ids,
}, 0, 0) }, 0, 0)
@ -83,7 +87,7 @@ func (s *commentServant) GetCommentRepliesByID(ids []int64) ([]*model.CommentRep
if err != nil { if err != nil {
return nil, err return nil, err
} }
repliesFormated := []*model.CommentReplyFormated{} repliesFormated := []*core.CommentReplyFormated{}
for _, reply := range replies { for _, reply := range replies {
replyFormated := reply.Format() replyFormated := reply.Format()
for _, user := range users { for _, user := range users {
@ -101,22 +105,22 @@ func (s *commentServant) GetCommentRepliesByID(ids []int64) ([]*model.CommentRep
return repliesFormated, nil return repliesFormated, nil
} }
func (s *commentManageServant) DeleteComment(comment *model.Comment) error { func (s *commentManageServant) DeleteComment(comment *core.Comment) error {
return comment.Delete(s.db) return comment.Delete(s.db)
} }
func (s *commentManageServant) CreateComment(comment *model.Comment) (*model.Comment, error) { func (s *commentManageServant) CreateComment(comment *core.Comment) (*core.Comment, error) {
return comment.Create(s.db) return comment.Create(s.db)
} }
func (s *commentManageServant) CreateCommentReply(reply *model.CommentReply) (*model.CommentReply, error) { func (s *commentManageServant) CreateCommentReply(reply *core.CommentReply) (*core.CommentReply, error) {
return reply.Create(s.db) return reply.Create(s.db)
} }
func (s *commentManageServant) DeleteCommentReply(reply *model.CommentReply) error { func (s *commentManageServant) DeleteCommentReply(reply *core.CommentReply) error {
return reply.Delete(s.db) return reply.Delete(s.db)
} }
func (s *commentManageServant) CreateCommentContent(content *model.CommentContent) (*model.CommentContent, error) { func (s *commentManageServant) CreateCommentContent(content *core.CommentContent) (*core.CommentContent, error) {
return content.Create(s.db) return content.Create(s.db)
} }

@ -1,11 +1,14 @@
// Copyright 2022 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 package jinzhu
import ( import (
"time" "time"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"github.com/rocboss/paopao-ce/internal/model/rest"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -24,14 +27,14 @@ func newContactManageService(db *gorm.DB) core.ContactManageService {
} }
} }
func (s *contactManageServant) fetchOrNewContact(db *gorm.DB, userId int64, friendId int64, status int8) (*model.Contact, error) { func (s *contactManageServant) fetchOrNewContact(db *gorm.DB, userId int64, friendId int64, status int8) (*dbr.Contact, error) {
contact := &model.Contact{ contact := &dbr.Contact{
UserId: userId, UserId: userId,
FriendId: friendId, FriendId: friendId,
} }
contact, err := contact.FetchUser(db) contact, err := contact.FetchUser(db)
if err != nil { if err != nil {
contact = &model.Contact{ contact = &dbr.Contact{
UserId: userId, UserId: userId,
FriendId: friendId, FriendId: friendId,
Status: status, Status: status,
@ -54,17 +57,17 @@ func (s *contactManageServant) RequestingFriend(userId int64, friendId int64, gr
} }
}() }()
contact, e := s.fetchOrNewContact(db, userId, friendId, model.ContactStatusRequesting) contact, e := s.fetchOrNewContact(db, userId, friendId, dbr.ContactStatusRequesting)
if e != nil { if e != nil {
err = e err = e
return return
} }
// 如果已经好友,啥也不干 // 如果已经好友,啥也不干
if contact.Status == model.ContactStatusAgree { if contact.Status == dbr.ContactStatusAgree {
return nil return nil
} else if contact.Status == model.ContactStatusReject || contact.Status == model.ContactStatusDeleted { } else if contact.Status == dbr.ContactStatusReject || contact.Status == dbr.ContactStatusDeleted {
contact.Status = model.ContactStatusRequesting contact.Status = dbr.ContactStatusRequesting
contact.IsDel = 0 // remove deleted flag if needed contact.IsDel = 0 // remove deleted flag if needed
if err = contact.UpdateInUnscoped(db); err != nil { if err = contact.UpdateInUnscoped(db); err != nil {
logrus.Errorf("contactManageServant.RequestingFriend update exsit contact err:%s", err) logrus.Errorf("contactManageServant.RequestingFriend update exsit contact err:%s", err)
@ -72,13 +75,13 @@ func (s *contactManageServant) RequestingFriend(userId int64, friendId int64, gr
} }
} }
msg := &model.Message{ msg := &dbr.Message{
SenderUserID: userId, SenderUserID: userId,
ReceiverUserID: friendId, ReceiverUserID: friendId,
Type: model.MsgTypeRequestingFriend, Type: dbr.MsgTypeRequestingFriend,
Brief: "请求添加好友,并附言:", Brief: "请求添加好友,并附言:",
Content: greetings, Content: greetings,
ReplyID: int64(model.ContactStatusRequesting), ReplyID: int64(dbr.ContactStatusRequesting),
} }
if _, err = msg.Create(db); err != nil { if _, err = msg.Create(db); err != nil {
logrus.Errorf("contactManageServant.RequestingFriend create message err:%s", err) logrus.Errorf("contactManageServant.RequestingFriend create message err:%s", err)
@ -97,7 +100,7 @@ func (s *contactManageServant) AddFriend(userId int64, friendId int64) (err erro
} }
}() }()
contact := &model.Contact{ contact := &dbr.Contact{
UserId: friendId, UserId: friendId,
FriendId: userId, FriendId: userId,
} }
@ -105,23 +108,23 @@ func (s *contactManageServant) AddFriend(userId int64, friendId int64) (err erro
return return
} }
// 如果还不是请求好友,啥也不干 // 如果还不是请求好友,啥也不干
if contact.Status != model.ContactStatusRequesting { if contact.Status != dbr.ContactStatusRequesting {
logrus.Debugf("contactManageServant.AddFriend not reuesting status now so skip") logrus.Debugf("contactManageServant.AddFriend not reuesting status now so skip")
return nil return nil
} }
contact.Status = model.ContactStatusAgree contact.Status = dbr.ContactStatusAgree
if err = contact.Update(db); err != nil { if err = contact.Update(db); err != nil {
return err return err
} }
contact, err = s.fetchOrNewContact(db, userId, friendId, model.ContactStatusAgree) contact, err = s.fetchOrNewContact(db, userId, friendId, dbr.ContactStatusAgree)
if err != nil { if err != nil {
return return
} }
// 如果已经好友,啥也不干 // 如果已经好友,啥也不干
if contact.Status != model.ContactStatusAgree { if contact.Status != dbr.ContactStatusAgree {
contact.Status = model.ContactStatusAgree contact.Status = dbr.ContactStatusAgree
contact.IsDel = 0 // remove deleted flag contact.IsDel = 0 // remove deleted flag
if err = contact.UpdateInUnscoped(db); err != nil { if err = contact.UpdateInUnscoped(db); err != nil {
logrus.Errorf("contactManageServant.AddFriend update contact err:%s", err) logrus.Errorf("contactManageServant.AddFriend update contact err:%s", err)
@ -129,8 +132,8 @@ func (s *contactManageServant) AddFriend(userId int64, friendId int64) (err erro
} }
} }
args := []any{userId, friendId, friendId, userId, model.MsgTypeRequestingFriend, model.ContactStatusRequesting} args := []any{userId, friendId, friendId, userId, dbr.MsgTypeRequestingFriend, dbr.ContactStatusRequesting}
msgs, e := (&model.Message{}).FetchBy(db, model.Predicates{ msgs, e := (&dbr.Message{}).FetchBy(db, dbr.Predicates{
"((sender_user_id = ? AND receiver_user_id = ?) OR (sender_user_id = ? AND receiver_user_id = ?)) AND type = ? AND reply_id = ?": args, "((sender_user_id = ? AND receiver_user_id = ?) OR (sender_user_id = ? AND receiver_user_id = ?)) AND type = ? AND reply_id = ?": args,
}) })
if e != nil { if e != nil {
@ -138,7 +141,7 @@ func (s *contactManageServant) AddFriend(userId int64, friendId int64) (err erro
return return
} }
for _, msg := range msgs { for _, msg := range msgs {
msg.ReplyID = int64(model.ContactStatusAgree) msg.ReplyID = int64(dbr.ContactStatusAgree)
if err = msg.Update(db); err != nil { if err = msg.Update(db); err != nil {
return return
} }
@ -156,7 +159,7 @@ func (s *contactManageServant) RejectFriend(userId int64, friendId int64) (err e
} }
}() }()
contact := &model.Contact{ contact := &dbr.Contact{
UserId: friendId, UserId: friendId,
FriendId: userId, FriendId: userId,
} }
@ -164,16 +167,16 @@ func (s *contactManageServant) RejectFriend(userId int64, friendId int64) (err e
return return
} }
// 如果还不是请求好友,啥也不干 // 如果还不是请求好友,啥也不干
if contact.Status != model.ContactStatusRequesting { if contact.Status != dbr.ContactStatusRequesting {
return nil return nil
} }
contact.Status = model.ContactStatusReject contact.Status = dbr.ContactStatusReject
if err = contact.Update(db); err != nil { if err = contact.Update(db); err != nil {
return err return err
} }
args := []any{friendId, userId, model.MsgTypeRequestingFriend, model.ContactStatusRequesting} args := []any{friendId, userId, dbr.MsgTypeRequestingFriend, dbr.ContactStatusRequesting}
msgs, e := (&model.Message{}).FetchBy(db, model.Predicates{ msgs, e := (&dbr.Message{}).FetchBy(db, dbr.Predicates{
"sender_user_id = ? AND receiver_user_id = ? AND type = ? AND reply_id = ?": args, "sender_user_id = ? AND receiver_user_id = ? AND type = ? AND reply_id = ?": args,
}) })
if e != nil { if e != nil {
@ -181,7 +184,7 @@ func (s *contactManageServant) RejectFriend(userId int64, friendId int64) (err e
return return
} }
for _, msg := range msgs { for _, msg := range msgs {
msg.ReplyID = int64(model.ContactStatusReject) msg.ReplyID = int64(dbr.ContactStatusReject)
if err = msg.Update(db); err != nil { if err = msg.Update(db); err != nil {
return return
} }
@ -199,7 +202,7 @@ func (s *contactManageServant) DeleteFriend(userId int64, friendId int64) (err e
} }
}() }()
contact := &model.Contact{ contact := &dbr.Contact{
UserId: userId, UserId: userId,
FriendId: friendId, FriendId: friendId,
} }
@ -210,10 +213,10 @@ func (s *contactManageServant) DeleteFriend(userId int64, friendId int64) (err e
for _, contact := range contacts { for _, contact := range contacts {
// 如果还不是好友,啥也不干 // 如果还不是好友,啥也不干
if contact.Status != model.ContactStatusAgree { if contact.Status != dbr.ContactStatusAgree {
continue continue
} }
contact.Status = model.ContactStatusDeleted contact.Status = dbr.ContactStatusDeleted
contact.DeletedOn = time.Now().Unix() contact.DeletedOn = time.Now().Unix()
contact.IsDel = 1 contact.IsDel = 1
if err = contact.Update(db); err != nil { if err = contact.Update(db); err != nil {
@ -223,11 +226,11 @@ func (s *contactManageServant) DeleteFriend(userId int64, friendId int64) (err e
return nil return nil
} }
func (s *contactManageServant) GetContacts(userId int64, offset int, limit int) (*rest.ContactsResp, error) { func (s *contactManageServant) GetContacts(userId int64, offset int, limit int) (*core.ContactList, error) {
contact := &model.Contact{} contact := &dbr.Contact{}
condition := model.ConditionsT{ condition := dbr.ConditionsT{
"user_id": userId, "user_id": userId,
"status": model.ContactStatusAgree, "status": dbr.ContactStatusAgree,
} }
contacts, err := contact.List(s.db, condition, offset, limit) contacts, err := contact.List(s.db, condition, offset, limit)
if err != nil { if err != nil {
@ -237,13 +240,13 @@ func (s *contactManageServant) GetContacts(userId int64, offset int, limit int)
if err != nil { if err != nil {
return nil, err return nil, err
} }
resp := &rest.ContactsResp{ resp := &core.ContactList{
Contacts: make([]rest.ContactItem, 0, len(contacts)), Contacts: make([]core.ContactItem, 0, len(contacts)),
Total: total, Total: total,
} }
for _, c := range contacts { for _, c := range contacts {
if c.User != nil { if c.User != nil {
resp.Contacts = append(resp.Contacts, rest.ContactItem{ resp.Contacts = append(resp.Contacts, core.ContactItem{
UserId: c.FriendId, UserId: c.FriendId,
UserName: c.User.Username, UserName: c.User.Username,
Nickname: c.User.Nickname, Nickname: c.User.Nickname,
@ -256,12 +259,12 @@ func (s *contactManageServant) GetContacts(userId int64, offset int, limit int)
} }
func (s *contactManageServant) IsFriend(userId int64, friendId int64) bool { func (s *contactManageServant) IsFriend(userId int64, friendId int64) bool {
contact := &model.Contact{ contact := &dbr.Contact{
UserId: friendId, UserId: friendId,
FriendId: userId, FriendId: userId,
} }
contact, err := contact.GetByUserFriend(s.db) contact, err := contact.GetByUserFriend(s.db)
if err == nil && contact.Status == model.ContactStatusAgree { if err == nil && contact.Status == dbr.ContactStatusAgree {
return true return true
} }
return false return false

@ -1,13 +1,17 @@
package model // Copyright 2022 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 "gorm.io/gorm" import "gorm.io/gorm"
type AttachmentType int type AttachmentType int
const ( const (
ATTACHMENT_TYPE_IMAGE AttachmentType = iota + 1 AttachmentTypeImage AttachmentType = iota + 1
ATTACHMENT_TYPE_VIDEO AttachmentTypeVideo
ATTACHMENT_TYPE_OTHER AttachmentTypeOther
) )
type Attachment struct { type Attachment struct {

@ -1,4 +1,8 @@
package model // Copyright 2022 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 "gorm.io/gorm" import "gorm.io/gorm"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 ( import (
"time" "time"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 ( import (
"time" "time"
@ -47,7 +51,7 @@ func (c *CommentContent) Create(db *gorm.DB) (*CommentContent, error) {
} }
func (c *CommentContent) MediaContentsByCommentId(db *gorm.DB, commentIds []int64) (contents []string, err error) { func (c *CommentContent) MediaContentsByCommentId(db *gorm.DB, commentIds []int64) (contents []string, err error) {
err = db.Model(c).Where("comment_id IN ? AND type = ?", commentIds, CONTENT_TYPE_IMAGE).Select("content").Find(&contents).Error err = db.Model(c).Where("comment_id IN ? AND type = ?", commentIds, ContentTypeImage).Select("content").Find(&contents).Error
return return
} }

@ -1,4 +1,8 @@
package model // Copyright 2022 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 ( import (
"time" "time"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 ( import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 "gorm.io/gorm" import "gorm.io/gorm"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 ( import (
"time" "time"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 ( import (
"strings" "strings"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 "gorm.io/gorm" import "gorm.io/gorm"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 ( import (
"time" "time"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 ( import (
"time" "time"
@ -7,27 +11,26 @@ import (
) )
// 类型1标题2文字段落3图片地址4视频地址5语音地址6链接地址7附件资源 // 类型1标题2文字段落3图片地址4视频地址5语音地址6链接地址7附件资源
type PostContentT int type PostContentT int
const ( const (
CONTENT_TYPE_TITLE PostContentT = iota + 1 ContentTypeTitle PostContentT = iota + 1
CONTENT_TYPE_TEXT ContentTypeText
CONTENT_TYPE_IMAGE ContentTypeImage
CONTENT_TYPE_VIDEO ContentTypeVideo
CONTENT_TYPE_AUDIO ContentTypeAudio
CONTENT_TYPE_LINK ContentTypeLink
CONTENT_TYPE_ATTACHMENT ContentTypeAttachment
CONTENT_TYPE_CHARGE_ATTACHMENT ContentTypeChargeAttachment
) )
var ( var (
mediaContentType = []PostContentT{ mediaContentType = []PostContentT{
CONTENT_TYPE_IMAGE, ContentTypeImage,
CONTENT_TYPE_VIDEO, ContentTypeVideo,
CONTENT_TYPE_AUDIO, ContentTypeAudio,
CONTENT_TYPE_ATTACHMENT, ContentTypeAttachment,
CONTENT_TYPE_CHARGE_ATTACHMENT, ContentTypeChargeAttachment,
} }
) )

@ -1,4 +1,8 @@
package model // Copyright 2022 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 ( import (
"time" "time"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 ( import (
"time" "time"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 "gorm.io/gorm" import "gorm.io/gorm"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 "gorm.io/gorm" import "gorm.io/gorm"

@ -1,4 +1,8 @@
package model // Copyright 2022 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 "gorm.io/gorm" import "gorm.io/gorm"

@ -1,9 +1,12 @@
// Copyright 2022 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 package jinzhu
import ( import (
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"github.com/rocboss/paopao-ce/internal/model/rest"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -40,20 +43,20 @@ func newSimpleIndexPostsService(db *gorm.DB) core.IndexPostsService {
} }
// IndexPosts 根据userId查询广场推文列表简单做到不同用户的主页都是不同的 // IndexPosts 根据userId查询广场推文列表简单做到不同用户的主页都是不同的
func (s *indexPostsServant) IndexPosts(user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) { func (s *indexPostsServant) IndexPosts(user *core.User, offset int, limit int) (*core.IndexTweetList, error) {
predicates := model.Predicates{ predicates := dbr.Predicates{
"ORDER": []any{"is_top DESC, latest_replied_on DESC"}, "ORDER": []any{"is_top DESC, latest_replied_on DESC"},
} }
if user == nil { if user == nil {
predicates["visibility = ?"] = []any{model.PostVisitPublic} predicates["visibility = ?"] = []any{dbr.PostVisitPublic}
} else if !user.IsAdmin { } else if !user.IsAdmin {
friendIds, _ := s.ams.BeFriendIds(user.ID) friendIds, _ := s.ams.BeFriendIds(user.ID)
friendIds = append(friendIds, user.ID) friendIds = append(friendIds, user.ID)
args := []any{model.PostVisitPublic, model.PostVisitPrivate, user.ID, model.PostVisitFriend, friendIds} args := []any{dbr.PostVisitPublic, dbr.PostVisitPrivate, user.ID, dbr.PostVisitFriend, friendIds}
predicates["visibility = ? OR (visibility = ? AND user_id = ?) OR (visibility = ? AND user_id IN ?)"] = args predicates["visibility = ? OR (visibility = ? AND user_id = ?) OR (visibility = ? AND user_id IN ?)"] = args
} }
posts, err := (&model.Post{}).Fetch(s.db, predicates, offset, limit) posts, err := (&dbr.Post{}).Fetch(s.db, predicates, offset, limit)
if err != nil { if err != nil {
logrus.Debugf("gormIndexPostsServant.IndexPosts err: %v", err) logrus.Debugf("gormIndexPostsServant.IndexPosts err: %v", err)
return nil, err return nil, err
@ -63,25 +66,25 @@ func (s *indexPostsServant) IndexPosts(user *model.User, offset int, limit int)
return nil, err return nil, err
} }
total, err := (&model.Post{}).CountBy(s.db, predicates) total, err := (&dbr.Post{}).CountBy(s.db, predicates)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &rest.IndexTweetsResp{ return &core.IndexTweetList{
Tweets: formatPosts, Tweets: formatPosts,
Total: total, Total: total,
}, nil }, nil
} }
// simpleCacheIndexGetPosts simpleCacheIndex 专属获取广场推文列表函数 // simpleCacheIndexGetPosts simpleCacheIndex 专属获取广场推文列表函数
func (s *simpleIndexPostsServant) IndexPosts(_user *model.User, offset int, limit int) (*rest.IndexTweetsResp, error) { func (s *simpleIndexPostsServant) IndexPosts(_user *core.User, offset int, limit int) (*core.IndexTweetList, error) {
predicates := model.Predicates{ predicates := dbr.Predicates{
"visibility = ?": []any{model.PostVisitPublic}, "visibility = ?": []any{dbr.PostVisitPublic},
"ORDER": []any{"is_top DESC, latest_replied_on DESC"}, "ORDER": []any{"is_top DESC, latest_replied_on DESC"},
} }
posts, err := (&model.Post{}).Fetch(s.db, predicates, offset, limit) posts, err := (&dbr.Post{}).Fetch(s.db, predicates, offset, limit)
if err != nil { if err != nil {
logrus.Debugf("gormSimpleIndexPostsServant.IndexPosts err: %v", err) logrus.Debugf("gormSimpleIndexPostsServant.IndexPosts err: %v", err)
return nil, err return nil, err
@ -92,12 +95,12 @@ func (s *simpleIndexPostsServant) IndexPosts(_user *model.User, offset int, limi
return nil, err return nil, err
} }
total, err := (&model.Post{}).CountBy(s.db, predicates) total, err := (&dbr.Post{}).CountBy(s.db, predicates)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &rest.IndexTweetsResp{ return &core.IndexTweetList{
Tweets: formatPosts, Tweets: formatPosts,
Total: total, Total: total,
}, nil }, nil

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// 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. // Core service implement base gorm+mysql/postgresql/sqlite3.
// Jinzhu is the primary developer of gorm so use his name as // Jinzhu is the primary developer of gorm so use his name as
// package name as a saluter. // package name as a saluter.
@ -6,11 +10,11 @@ package jinzhu
import ( import (
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/alimy/cfg"
"github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/dao/cache" "github.com/rocboss/paopao-ce/internal/dao/cache"
"github.com/rocboss/paopao-ce/internal/dao/security" "github.com/rocboss/paopao-ce/internal/dao/security"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )

@ -1,8 +1,12 @@
// Copyright 2022 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 package jinzhu
import ( import (
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -20,37 +24,37 @@ func newMessageService(db *gorm.DB) core.MessageService {
} }
} }
func (d *messageServant) CreateMessage(msg *model.Message) (*model.Message, error) { func (d *messageServant) CreateMessage(msg *core.Message) (*core.Message, error) {
return msg.Create(d.db) return msg.Create(d.db)
} }
func (d *messageServant) GetUnreadCount(userID int64) (int64, error) { func (d *messageServant) GetUnreadCount(userID int64) (int64, error) {
return (&model.Message{}).Count(d.db, &model.ConditionsT{ return (&dbr.Message{}).Count(d.db, &dbr.ConditionsT{
"receiver_user_id": userID, "receiver_user_id": userID,
"is_read": model.MsgStatusUnread, "is_read": dbr.MsgStatusUnread,
}) })
} }
func (d *messageServant) GetMessageByID(id int64) (*model.Message, error) { func (d *messageServant) GetMessageByID(id int64) (*core.Message, error) {
return (&model.Message{ return (&dbr.Message{
Model: &model.Model{ Model: &dbr.Model{
ID: id, ID: id,
}, },
}).Get(d.db) }).Get(d.db)
} }
func (d *messageServant) ReadMessage(message *model.Message) error { func (d *messageServant) ReadMessage(message *core.Message) error {
message.IsRead = 1 message.IsRead = 1
return message.Update(d.db) return message.Update(d.db)
} }
func (d *messageServant) GetMessages(conditions *model.ConditionsT, offset, limit int) ([]*model.MessageFormated, error) { func (d *messageServant) GetMessages(conditions *core.ConditionsT, offset, limit int) ([]*core.MessageFormated, error) {
messages, err := (&model.Message{}).List(d.db, conditions, offset, limit) messages, err := (&dbr.Message{}).List(d.db, conditions, offset, limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
mfs := []*model.MessageFormated{} mfs := []*dbr.MessageFormated{}
for _, message := range messages { for _, message := range messages {
mf := message.Format() mf := message.Format()
mfs = append(mfs, mf) mfs = append(mfs, mf)
@ -59,6 +63,6 @@ func (d *messageServant) GetMessages(conditions *model.ConditionsT, offset, limi
return mfs, nil return mfs, nil
} }
func (d *messageServant) GetMessageCount(conditions *model.ConditionsT) (int64, error) { func (d *messageServant) GetMessageCount(conditions *core.ConditionsT) (int64, error) {
return (&model.Message{}).Count(d.db, conditions) return (&dbr.Message{}).Count(d.db, conditions)
} }

@ -1,3 +1,7 @@
// Copyright 2022 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 package jinzhu
import ( import (
@ -10,7 +14,7 @@ import (
"github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"github.com/rocboss/paopao-ce/pkg/json" "github.com/rocboss/paopao-ce/pkg/json"
"gopkg.in/resty.v1" "gopkg.in/resty.v1"
"gorm.io/gorm" "gorm.io/gorm"
@ -36,14 +40,14 @@ type juhePhoneCaptchaRsp struct {
} }
// 获取最新短信验证码 // 获取最新短信验证码
func (s *securityServant) GetLatestPhoneCaptcha(phone string) (*model.Captcha, error) { func (s *securityServant) GetLatestPhoneCaptcha(phone string) (*core.Captcha, error) {
return (&model.Captcha{ return (&dbr.Captcha{
Phone: phone, Phone: phone,
}).Get(s.db) }).Get(s.db)
} }
// 更新短信验证码 // 更新短信验证码
func (s *securityServant) UsePhoneCaptcha(captcha *model.Captcha) error { func (s *securityServant) UsePhoneCaptcha(captcha *core.Captcha) error {
captcha.UseTimes++ captcha.UseTimes++
return captcha.Update(s.db) return captcha.Update(s.db)
} }
@ -82,7 +86,7 @@ func (s *securityServant) SendPhoneCaptcha(phone string) error {
} }
// 写入表 // 写入表
captchaModel := &model.Captcha{ captchaModel := &dbr.Captcha{
Phone: phone, Phone: phone,
Captcha: strconv.Itoa(captcha), Captcha: strconv.Itoa(captcha),
ExpiredOn: time.Now().Add(time.Minute * time.Duration(m)).Unix(), ExpiredOn: time.Now().Add(time.Minute * time.Duration(m)).Unix(),

@ -1,10 +1,14 @@
// Copyright 2022 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 package jinzhu
import ( import (
"strings" "strings"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -22,28 +26,28 @@ func newTopicService(db *gorm.DB) core.TopicService {
} }
} }
func (s *topicServant) CreateTag(tag *model.Tag) (*model.Tag, error) { func (s *topicServant) CreateTag(tag *core.Tag) (*core.Tag, error) {
return createTag(s.db, tag) return createTag(s.db, tag)
} }
func (s *topicServant) DeleteTag(tag *model.Tag) error { func (s *topicServant) DeleteTag(tag *core.Tag) error {
return deleteTag(s.db, tag) return deleteTag(s.db, tag)
} }
func (s *topicServant) GetTags(conditions *model.ConditionsT, offset, limit int) ([]*model.Tag, error) { func (s *topicServant) GetTags(conditions *core.ConditionsT, offset, limit int) ([]*core.Tag, error) {
return (&model.Tag{}).List(s.db, conditions, offset, limit) return (&dbr.Tag{}).List(s.db, conditions, offset, limit)
} }
func (s *topicServant) GetTagsByKeyword(keyword string) ([]*model.Tag, error) { func (s *topicServant) GetTagsByKeyword(keyword string) ([]*core.Tag, error) {
tag := &model.Tag{} tag := &dbr.Tag{}
keyword = "%" + strings.Trim(keyword, " ") + "%" keyword = "%" + strings.Trim(keyword, " ") + "%"
if keyword == "%%" { if keyword == "%%" {
return tag.List(s.db, &model.ConditionsT{ return tag.List(s.db, &dbr.ConditionsT{
"ORDER": "quote_num DESC", "ORDER": "quote_num DESC",
}, 0, 6) }, 0, 6)
} else { } else {
return tag.List(s.db, &model.ConditionsT{ return tag.List(s.db, &dbr.ConditionsT{
"tag LIKE ?": keyword, "tag LIKE ?": keyword,
"ORDER": "quote_num DESC", "ORDER": "quote_num DESC",
}, 0, 6) }, 0, 6)

@ -1,3 +1,7 @@
// Copyright 2022 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 package jinzhu
import ( import (
@ -5,7 +9,7 @@ import (
"time" "time"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -48,7 +52,7 @@ func newTweetHelpService(db *gorm.DB) core.TweetHelpService {
} }
// MergePosts post数据整合 // MergePosts post数据整合
func (s *tweetHelpServant) MergePosts(posts []*model.Post) ([]*model.PostFormated, error) { func (s *tweetHelpServant) MergePosts(posts []*core.Post) ([]*core.PostFormated, error) {
postIds := make([]int64, 0, len(posts)) postIds := make([]int64, 0, len(posts))
userIds := make([]int64, 0, len(posts)) userIds := make([]int64, 0, len(posts))
for _, post := range posts { for _, post := range posts {
@ -66,18 +70,18 @@ func (s *tweetHelpServant) MergePosts(posts []*model.Post) ([]*model.PostFormate
return nil, err return nil, err
} }
userMap := make(map[int64]*model.UserFormated, len(users)) userMap := make(map[int64]*dbr.UserFormated, len(users))
for _, user := range users { for _, user := range users {
userMap[user.ID] = user.Format() userMap[user.ID] = user.Format()
} }
contentMap := make(map[int64][]*model.PostContentFormated, len(postContents)) contentMap := make(map[int64][]*dbr.PostContentFormated, len(postContents))
for _, content := range postContents { for _, content := range postContents {
contentMap[content.PostID] = append(contentMap[content.PostID], content.Format()) contentMap[content.PostID] = append(contentMap[content.PostID], content.Format())
} }
// 数据整合 // 数据整合
postsFormated := make([]*model.PostFormated, 0, len(posts)) postsFormated := make([]*dbr.PostFormated, 0, len(posts))
for _, post := range posts { for _, post := range posts {
postFormated := post.Format() postFormated := post.Format()
postFormated.User = userMap[post.UserID] postFormated.User = userMap[post.UserID]
@ -88,7 +92,7 @@ func (s *tweetHelpServant) MergePosts(posts []*model.Post) ([]*model.PostFormate
} }
// RevampPosts post数据整形修复 // RevampPosts post数据整形修复
func (s *tweetHelpServant) RevampPosts(posts []*model.PostFormated) ([]*model.PostFormated, error) { func (s *tweetHelpServant) RevampPosts(posts []*core.PostFormated) ([]*core.PostFormated, error) {
postIds := make([]int64, 0, len(posts)) postIds := make([]int64, 0, len(posts))
userIds := make([]int64, 0, len(posts)) userIds := make([]int64, 0, len(posts))
for _, post := range posts { for _, post := range posts {
@ -106,12 +110,12 @@ func (s *tweetHelpServant) RevampPosts(posts []*model.PostFormated) ([]*model.Po
return nil, err return nil, err
} }
userMap := make(map[int64]*model.UserFormated, len(users)) userMap := make(map[int64]*dbr.UserFormated, len(users))
for _, user := range users { for _, user := range users {
userMap[user.ID] = user.Format() userMap[user.ID] = user.Format()
} }
contentMap := make(map[int64][]*model.PostContentFormated, len(postContents)) contentMap := make(map[int64][]*dbr.PostContentFormated, len(postContents))
for _, content := range postContents { for _, content := range postContents {
contentMap[content.PostID] = append(contentMap[content.PostID], content.Format()) contentMap[content.PostID] = append(contentMap[content.PostID], content.Format())
} }
@ -124,23 +128,23 @@ func (s *tweetHelpServant) RevampPosts(posts []*model.PostFormated) ([]*model.Po
return posts, nil return posts, nil
} }
func (s *tweetHelpServant) getPostContentsByIDs(ids []int64) ([]*model.PostContent, error) { func (s *tweetHelpServant) getPostContentsByIDs(ids []int64) ([]*dbr.PostContent, error) {
return (&model.PostContent{}).List(s.db, &model.ConditionsT{ return (&dbr.PostContent{}).List(s.db, &dbr.ConditionsT{
"post_id IN ?": ids, "post_id IN ?": ids,
"ORDER": "sort ASC", "ORDER": "sort ASC",
}, 0, 0) }, 0, 0)
} }
func (s *tweetHelpServant) getUsersByIDs(ids []int64) ([]*model.User, error) { func (s *tweetHelpServant) getUsersByIDs(ids []int64) ([]*dbr.User, error) {
user := &model.User{} user := &dbr.User{}
return user.List(s.db, &model.ConditionsT{ return user.List(s.db, &dbr.ConditionsT{
"id IN ?": ids, "id IN ?": ids,
}, 0, 0) }, 0, 0)
} }
func (s *tweetManageServant) CreatePostCollection(postID, userID int64) (*model.PostCollection, error) { func (s *tweetManageServant) CreatePostCollection(postID, userID int64) (*core.PostCollection, error) {
collection := &model.PostCollection{ collection := &dbr.PostCollection{
PostID: postID, PostID: postID,
UserID: userID, UserID: userID,
} }
@ -148,19 +152,19 @@ func (s *tweetManageServant) CreatePostCollection(postID, userID int64) (*model.
return collection.Create(s.db) return collection.Create(s.db)
} }
func (s *tweetManageServant) DeletePostCollection(p *model.PostCollection) error { func (s *tweetManageServant) DeletePostCollection(p *core.PostCollection) error {
return p.Delete(s.db) return p.Delete(s.db)
} }
func (s *tweetManageServant) CreatePostContent(content *model.PostContent) (*model.PostContent, error) { func (s *tweetManageServant) CreatePostContent(content *core.PostContent) (*core.PostContent, error) {
return content.Create(s.db) return content.Create(s.db)
} }
func (s *tweetManageServant) CreateAttachment(attachment *model.Attachment) (*model.Attachment, error) { func (s *tweetManageServant) CreateAttachment(attachment *core.Attachment) (*core.Attachment, error) {
return attachment.Create(s.db) return attachment.Create(s.db)
} }
func (s *tweetManageServant) CreatePost(post *model.Post) (*model.Post, error) { func (s *tweetManageServant) CreatePost(post *core.Post) (*core.Post, error) {
post.LatestRepliedOn = time.Now().Unix() post.LatestRepliedOn = time.Now().Unix()
p, err := post.Create(s.db) p, err := post.Create(s.db)
if err != nil { if err != nil {
@ -170,11 +174,11 @@ func (s *tweetManageServant) CreatePost(post *model.Post) (*model.Post, error) {
return p, nil return p, nil
} }
func (s *tweetManageServant) DeletePost(post *model.Post) ([]string, error) { func (s *tweetManageServant) DeletePost(post *core.Post) ([]string, error) {
var mediaContents []string var mediaContents []string
postId := post.ID postId := post.ID
postContent := &model.PostContent{} postContent := &dbr.PostContent{}
err := s.db.Transaction( err := s.db.Transaction(
func(tx *gorm.DB) error { func(tx *gorm.DB) error {
if contents, err := postContent.MediaContentsByPostId(tx, postId); err == nil { if contents, err := postContent.MediaContentsByPostId(tx, postId); err == nil {
@ -218,8 +222,8 @@ func (s *tweetManageServant) DeletePost(post *model.Post) ([]string, error) {
} }
func (s *tweetManageServant) deleteCommentByPostId(db *gorm.DB, postId int64) ([]string, error) { func (s *tweetManageServant) deleteCommentByPostId(db *gorm.DB, postId int64) ([]string, error) {
comment := &model.Comment{} comment := &dbr.Comment{}
commentContent := &model.CommentContent{} commentContent := &dbr.CommentContent{}
// 获取推文的所有评论id // 获取推文的所有评论id
commentIds, err := comment.CommentIdsByPostId(db, postId) commentIds, err := comment.CommentIdsByPostId(db, postId)
@ -244,19 +248,19 @@ func (s *tweetManageServant) deleteCommentByPostId(db *gorm.DB, postId int64) ([
} }
// 删评论的评论 // 删评论的评论
if err = (&model.CommentReply{}).DeleteByCommentIds(db, commentIds); err != nil { if err = (&dbr.CommentReply{}).DeleteByCommentIds(db, commentIds); err != nil {
return nil, err return nil, err
} }
return mediaContents, nil return mediaContents, nil
} }
func (s *tweetManageServant) LockPost(post *model.Post) error { func (s *tweetManageServant) LockPost(post *core.Post) error {
post.IsLock = 1 - post.IsLock post.IsLock = 1 - post.IsLock
return post.Update(s.db) return post.Update(s.db)
} }
func (s *tweetManageServant) StickPost(post *model.Post) error { func (s *tweetManageServant) StickPost(post *core.Post) error {
post.IsTop = 1 - post.IsTop post.IsTop = 1 - post.IsTop
if err := post.Update(s.db); err != nil { if err := post.Update(s.db); err != nil {
return err return err
@ -265,7 +269,7 @@ func (s *tweetManageServant) StickPost(post *model.Post) error {
return nil return nil
} }
func (s *tweetManageServant) VisiblePost(post *model.Post, visibility model.PostVisibleT) error { func (s *tweetManageServant) VisiblePost(post *core.Post, visibility core.PostVisibleT) error {
oldVisibility := post.Visibility oldVisibility := post.Visibility
post.Visibility = visibility post.Visibility = visibility
// TODO: 这个判断是否可以不要呢 // TODO: 这个判断是否可以不要呢
@ -273,7 +277,7 @@ func (s *tweetManageServant) VisiblePost(post *model.Post, visibility model.Post
return nil return nil
} }
// 私密推文 特殊处理 // 私密推文 特殊处理
if visibility == model.PostVisitPrivate { if visibility == dbr.PostVisitPrivate {
// 强制取消置顶 // 强制取消置顶
// TODO: 置顶推文用户是否有权设置成私密? 后续完善 // TODO: 置顶推文用户是否有权设置成私密? 后续完善
post.IsTop = 0 post.IsTop = 0
@ -288,14 +292,14 @@ func (s *tweetManageServant) VisiblePost(post *model.Post, visibility model.Post
// tag处理 // tag处理
tags := strings.Split(post.Tags, ",") tags := strings.Split(post.Tags, ",")
for _, t := range tags { for _, t := range tags {
tag := &model.Tag{ tag := &dbr.Tag{
Tag: t, Tag: t,
} }
// TODO: 暂时宽松不处理错误,这里或许可以有优化,后续完善 // TODO: 暂时宽松不处理错误,这里或许可以有优化,后续完善
if oldVisibility == model.PostVisitPrivate { if oldVisibility == dbr.PostVisitPrivate {
// 从私密转为非私密才需要重新创建tag // 从私密转为非私密才需要重新创建tag
createTag(db, tag) createTag(db, tag)
} else if visibility == model.PostVisitPrivate { } else if visibility == dbr.PostVisitPrivate {
// 从非私密转为私密才需要删除tag // 从非私密转为私密才需要删除tag
deleteTag(db, tag) deleteTag(db, tag)
} }
@ -305,7 +309,7 @@ func (s *tweetManageServant) VisiblePost(post *model.Post, visibility model.Post
return nil return nil
} }
func (s *tweetManageServant) UpdatePost(post *model.Post) error { func (s *tweetManageServant) UpdatePost(post *core.Post) error {
if err := post.Update(s.db); err != nil { if err := post.Update(s.db); err != nil {
return err return err
} }
@ -313,104 +317,104 @@ func (s *tweetManageServant) UpdatePost(post *model.Post) error {
return nil return nil
} }
func (s *tweetManageServant) CreatePostStar(postID, userID int64) (*model.PostStar, error) { func (s *tweetManageServant) CreatePostStar(postID, userID int64) (*core.PostStar, error) {
star := &model.PostStar{ star := &dbr.PostStar{
PostID: postID, PostID: postID,
UserID: userID, UserID: userID,
} }
return star.Create(s.db) return star.Create(s.db)
} }
func (s *tweetManageServant) DeletePostStar(p *model.PostStar) error { func (s *tweetManageServant) DeletePostStar(p *core.PostStar) error {
return p.Delete(s.db) return p.Delete(s.db)
} }
func (s *tweetServant) GetPostByID(id int64) (*model.Post, error) { func (s *tweetServant) GetPostByID(id int64) (*core.Post, error) {
post := &model.Post{ post := &dbr.Post{
Model: &model.Model{ Model: &dbr.Model{
ID: id, ID: id,
}, },
} }
return post.Get(s.db) return post.Get(s.db)
} }
func (s *tweetServant) GetPosts(conditions *model.ConditionsT, offset, limit int) ([]*model.Post, error) { func (s *tweetServant) GetPosts(conditions *core.ConditionsT, offset, limit int) ([]*core.Post, error) {
return (&model.Post{}).List(s.db, conditions, offset, limit) return (&dbr.Post{}).List(s.db, conditions, offset, limit)
} }
func (s *tweetServant) GetPostCount(conditions *model.ConditionsT) (int64, error) { func (s *tweetServant) GetPostCount(conditions *core.ConditionsT) (int64, error) {
return (&model.Post{}).Count(s.db, conditions) return (&dbr.Post{}).Count(s.db, conditions)
} }
func (s *tweetServant) GetUserPostStar(postID, userID int64) (*model.PostStar, error) { func (s *tweetServant) GetUserPostStar(postID, userID int64) (*core.PostStar, error) {
star := &model.PostStar{ star := &dbr.PostStar{
PostID: postID, PostID: postID,
UserID: userID, UserID: userID,
} }
return star.Get(s.db) return star.Get(s.db)
} }
func (s *tweetServant) GetUserPostStars(userID int64, offset, limit int) ([]*model.PostStar, error) { func (s *tweetServant) GetUserPostStars(userID int64, offset, limit int) ([]*core.PostStar, error) {
star := &model.PostStar{ star := &dbr.PostStar{
UserID: userID, UserID: userID,
} }
return star.List(s.db, &model.ConditionsT{ return star.List(s.db, &dbr.ConditionsT{
"ORDER": s.db.NamingStrategy.TableName("PostStar") + ".id DESC", "ORDER": s.db.NamingStrategy.TableName("PostStar") + ".id DESC",
}, offset, limit) }, offset, limit)
} }
func (s *tweetServant) GetUserPostStarCount(userID int64) (int64, error) { func (s *tweetServant) GetUserPostStarCount(userID int64) (int64, error) {
star := &model.PostStar{ star := &dbr.PostStar{
UserID: userID, UserID: userID,
} }
return star.Count(s.db, &model.ConditionsT{}) return star.Count(s.db, &dbr.ConditionsT{})
} }
func (s *tweetServant) GetUserPostCollection(postID, userID int64) (*model.PostCollection, error) { func (s *tweetServant) GetUserPostCollection(postID, userID int64) (*core.PostCollection, error) {
star := &model.PostCollection{ star := &dbr.PostCollection{
PostID: postID, PostID: postID,
UserID: userID, UserID: userID,
} }
return star.Get(s.db) return star.Get(s.db)
} }
func (s *tweetServant) GetUserPostCollections(userID int64, offset, limit int) ([]*model.PostCollection, error) { func (s *tweetServant) GetUserPostCollections(userID int64, offset, limit int) ([]*core.PostCollection, error) {
collection := &model.PostCollection{ collection := &dbr.PostCollection{
UserID: userID, UserID: userID,
} }
return collection.List(s.db, &model.ConditionsT{ return collection.List(s.db, &dbr.ConditionsT{
"ORDER": s.db.NamingStrategy.TableName("PostCollection") + ".id DESC", "ORDER": s.db.NamingStrategy.TableName("PostCollection") + ".id DESC",
}, offset, limit) }, offset, limit)
} }
func (s *tweetServant) GetUserPostCollectionCount(userID int64) (int64, error) { func (s *tweetServant) GetUserPostCollectionCount(userID int64) (int64, error) {
collection := &model.PostCollection{ collection := &dbr.PostCollection{
UserID: userID, UserID: userID,
} }
return collection.Count(s.db, &model.ConditionsT{}) return collection.Count(s.db, &dbr.ConditionsT{})
} }
func (s *tweetServant) GetUserWalletBills(userID int64, offset, limit int) ([]*model.WalletStatement, error) { func (s *tweetServant) GetUserWalletBills(userID int64, offset, limit int) ([]*core.WalletStatement, error) {
statement := &model.WalletStatement{ statement := &dbr.WalletStatement{
UserID: userID, UserID: userID,
} }
return statement.List(s.db, &model.ConditionsT{ return statement.List(s.db, &dbr.ConditionsT{
"ORDER": "id DESC", "ORDER": "id DESC",
}, offset, limit) }, offset, limit)
} }
func (s *tweetServant) GetUserWalletBillCount(userID int64) (int64, error) { func (s *tweetServant) GetUserWalletBillCount(userID int64) (int64, error) {
statement := &model.WalletStatement{ statement := &dbr.WalletStatement{
UserID: userID, UserID: userID,
} }
return statement.Count(s.db, &model.ConditionsT{}) return statement.Count(s.db, &dbr.ConditionsT{})
} }
func (s *tweetServant) GetPostAttatchmentBill(postID, userID int64) (*model.PostAttachmentBill, error) { func (s *tweetServant) GetPostAttatchmentBill(postID, userID int64) (*core.PostAttachmentBill, error) {
bill := &model.PostAttachmentBill{ bill := &dbr.PostAttachmentBill{
PostID: postID, PostID: postID,
UserID: userID, UserID: userID,
} }
@ -418,16 +422,16 @@ func (s *tweetServant) GetPostAttatchmentBill(postID, userID int64) (*model.Post
return bill.Get(s.db) return bill.Get(s.db)
} }
func (s *tweetServant) GetPostContentsByIDs(ids []int64) ([]*model.PostContent, error) { func (s *tweetServant) GetPostContentsByIDs(ids []int64) ([]*core.PostContent, error) {
return (&model.PostContent{}).List(s.db, &model.ConditionsT{ return (&dbr.PostContent{}).List(s.db, &dbr.ConditionsT{
"post_id IN ?": ids, "post_id IN ?": ids,
"ORDER": "sort ASC", "ORDER": "sort ASC",
}, 0, 0) }, 0, 0)
} }
func (s *tweetServant) GetPostContentByID(id int64) (*model.PostContent, error) { func (s *tweetServant) GetPostContentByID(id int64) (*core.PostContent, error) {
return (&model.PostContent{ return (&dbr.PostContent{
Model: &model.Model{ Model: &dbr.Model{
ID: id, ID: id,
}, },
}).Get(s.db) }).Get(s.db)

@ -1,10 +1,14 @@
// Copyright 2022 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 package jinzhu
import ( import (
"strings" "strings"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -22,69 +26,69 @@ func newUserManageService(db *gorm.DB) core.UserManageService {
} }
} }
func (s *userManageServant) GetUserByID(id int64) (*model.User, error) { func (s *userManageServant) GetUserByID(id int64) (*core.User, error) {
user := &model.User{ user := &dbr.User{
Model: &model.Model{ Model: &dbr.Model{
ID: id, ID: id,
}, },
} }
return user.Get(s.db) return user.Get(s.db)
} }
func (s *userManageServant) GetUserByUsername(username string) (*model.User, error) { func (s *userManageServant) GetUserByUsername(username string) (*core.User, error) {
user := &model.User{ user := &dbr.User{
Username: username, Username: username,
} }
return user.Get(s.db) return user.Get(s.db)
} }
func (s *userManageServant) GetUserByPhone(phone string) (*model.User, error) { func (s *userManageServant) GetUserByPhone(phone string) (*core.User, error) {
user := &model.User{ user := &dbr.User{
Phone: phone, Phone: phone,
} }
return user.Get(s.db) return user.Get(s.db)
} }
func (s *userManageServant) GetUsersByIDs(ids []int64) ([]*model.User, error) { func (s *userManageServant) GetUsersByIDs(ids []int64) ([]*core.User, error) {
user := &model.User{} user := &dbr.User{}
return user.List(s.db, &model.ConditionsT{ return user.List(s.db, &dbr.ConditionsT{
"id IN ?": ids, "id IN ?": ids,
}, 0, 0) }, 0, 0)
} }
func (s *userManageServant) GetUsersByKeyword(keyword string) ([]*model.User, error) { func (s *userManageServant) GetUsersByKeyword(keyword string) ([]*core.User, error) {
user := &model.User{} user := &dbr.User{}
keyword = strings.Trim(keyword, " ") + "%" keyword = strings.Trim(keyword, " ") + "%"
if keyword == "%" { if keyword == "%" {
return user.List(s.db, &model.ConditionsT{ return user.List(s.db, &dbr.ConditionsT{
"ORDER": "id ASC", "ORDER": "id ASC",
}, 0, 6) }, 0, 6)
} else { } else {
return user.List(s.db, &model.ConditionsT{ return user.List(s.db, &dbr.ConditionsT{
"username LIKE ?": keyword, "username LIKE ?": keyword,
}, 0, 6) }, 0, 6)
} }
} }
func (s *userManageServant) GetTagsByKeyword(keyword string) ([]*model.Tag, error) { func (s *userManageServant) GetTagsByKeyword(keyword string) ([]*core.Tag, error) {
tag := &model.Tag{} tag := &dbr.Tag{}
keyword = "%" + strings.Trim(keyword, " ") + "%" keyword = "%" + strings.Trim(keyword, " ") + "%"
if keyword == "%%" { if keyword == "%%" {
return tag.List(s.db, &model.ConditionsT{ return tag.List(s.db, &dbr.ConditionsT{
"ORDER": "quote_num DESC", "ORDER": "quote_num DESC",
}, 0, 6) }, 0, 6)
} else { } else {
return tag.List(s.db, &model.ConditionsT{ return tag.List(s.db, &dbr.ConditionsT{
"tag LIKE ?": keyword, "tag LIKE ?": keyword,
"ORDER": "quote_num DESC", "ORDER": "quote_num DESC",
}, 0, 6) }, 0, 6)
} }
} }
func (s *userManageServant) CreateUser(user *model.User) (*model.User, error) { func (s *userManageServant) CreateUser(user *dbr.User) (*core.User, error) {
return user.Create(s.db) return user.Create(s.db)
} }
func (s *userManageServant) UpdateUser(user *model.User) error { func (s *userManageServant) UpdateUser(user *core.User) error {
return user.Update(s.db) return user.Update(s.db)
} }

@ -1,11 +1,15 @@
// Copyright 2022 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 package jinzhu
import ( import (
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"gorm.io/gorm" "gorm.io/gorm"
) )
func createTag(db *gorm.DB, tag *model.Tag) (*model.Tag, error) { func createTag(db *gorm.DB, tag *dbr.Tag) (*dbr.Tag, error) {
t, err := tag.Get(db) t, err := tag.Get(db)
if err != nil { if err != nil {
tag.QuoteNum = 1 tag.QuoteNum = 1
@ -23,7 +27,7 @@ func createTag(db *gorm.DB, tag *model.Tag) (*model.Tag, error) {
return t, nil return t, nil
} }
func deleteTag(db *gorm.DB, tag *model.Tag) error { func deleteTag(db *gorm.DB, tag *dbr.Tag) error {
tag, err := tag.Get(db) tag, err := tag.Get(db)
if err != nil { if err != nil {
return err return err
@ -33,7 +37,7 @@ func deleteTag(db *gorm.DB, tag *model.Tag) error {
} }
func deleteTags(db *gorm.DB, tags []string) error { func deleteTags(db *gorm.DB, tags []string) error {
allTags, err := (&model.Tag{}).TagsFrom(db, tags) allTags, err := (&dbr.Tag{}).TagsFrom(db, tags)
if err != nil { if err != nil {
return err return err
} }
@ -51,9 +55,9 @@ func deleteTags(db *gorm.DB, tags []string) error {
} }
// 根据IDs获取用户列表 // 根据IDs获取用户列表
func getUsersByIDs(db *gorm.DB, ids []int64) ([]*model.User, error) { func getUsersByIDs(db *gorm.DB, ids []int64) ([]*dbr.User, error) {
user := &model.User{} user := &dbr.User{}
return user.List(db, &model.ConditionsT{ return user.List(db, &dbr.ConditionsT{
"id IN ?": ids, "id IN ?": ids,
}, 0, 0) }, 0, 0)
} }

@ -1,9 +1,13 @@
// Copyright 2022 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 package jinzhu
import ( import (
"github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model" "github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
"gorm.io/gorm" "gorm.io/gorm"
) )
@ -21,17 +25,17 @@ func newWalletService(db *gorm.DB) core.WalletService {
} }
} }
func (d *walletServant) GetRechargeByID(id int64) (*model.WalletRecharge, error) { func (d *walletServant) GetRechargeByID(id int64) (*core.WalletRecharge, error) {
recharge := &model.WalletRecharge{ recharge := &dbr.WalletRecharge{
Model: &model.Model{ Model: &dbr.Model{
ID: id, ID: id,
}, },
} }
return recharge.Get(d.db) return recharge.Get(d.db)
} }
func (d *walletServant) CreateRecharge(userId, amount int64) (*model.WalletRecharge, error) { func (d *walletServant) CreateRecharge(userId, amount int64) (*core.WalletRecharge, error) {
recharge := &model.WalletRecharge{ recharge := &dbr.WalletRecharge{
UserID: userId, UserID: userId,
Amount: amount, Amount: amount,
} }
@ -39,26 +43,26 @@ func (d *walletServant) CreateRecharge(userId, amount int64) (*model.WalletRecha
return recharge.Create(d.db) return recharge.Create(d.db)
} }
func (d *walletServant) GetUserWalletBills(userID int64, offset, limit int) ([]*model.WalletStatement, error) { func (d *walletServant) GetUserWalletBills(userID int64, offset, limit int) ([]*core.WalletStatement, error) {
statement := &model.WalletStatement{ statement := &dbr.WalletStatement{
UserID: userID, UserID: userID,
} }
return statement.List(d.db, &model.ConditionsT{ return statement.List(d.db, &dbr.ConditionsT{
"ORDER": "id DESC", "ORDER": "id DESC",
}, offset, limit) }, offset, limit)
} }
func (d *walletServant) GetUserWalletBillCount(userID int64) (int64, error) { func (d *walletServant) GetUserWalletBillCount(userID int64) (int64, error) {
statement := &model.WalletStatement{ statement := &dbr.WalletStatement{
UserID: userID, UserID: userID,
} }
return statement.Count(d.db, &model.ConditionsT{}) return statement.Count(d.db, &dbr.ConditionsT{})
} }
func (d *walletServant) HandleRechargeSuccess(recharge *model.WalletRecharge, tradeNo string) error { func (d *walletServant) HandleRechargeSuccess(recharge *core.WalletRecharge, tradeNo string) error {
user, _ := (&model.User{ user, _ := (&dbr.User{
Model: &model.Model{ Model: &dbr.Model{
ID: recharge.UserID, ID: recharge.UserID,
}, },
}).Get(d.db) }).Get(d.db)
@ -71,7 +75,7 @@ func (d *walletServant) HandleRechargeSuccess(recharge *model.WalletRecharge, tr
} }
// 新增账单 // 新增账单
if err := tx.Create(&model.WalletStatement{ if err := tx.Create(&dbr.WalletStatement{
UserID: user.ID, UserID: user.ID,
ChangeAmount: recharge.Amount, ChangeAmount: recharge.Amount,
BalanceSnapshot: user.Balance + recharge.Amount, BalanceSnapshot: user.Balance + recharge.Amount,
@ -93,7 +97,7 @@ func (d *walletServant) HandleRechargeSuccess(recharge *model.WalletRecharge, tr
}) })
} }
func (d *walletServant) HandlePostAttachmentBought(post *model.Post, user *model.User) error { func (d *walletServant) HandlePostAttachmentBought(post *core.Post, user *core.User) error {
return d.db.Transaction(func(tx *gorm.DB) error { return d.db.Transaction(func(tx *gorm.DB) error {
// 扣除金额 // 扣除金额
if err := tx.Model(user).Update("balance", gorm.Expr("balance - ?", post.AttachmentPrice)).Error; err != nil { if err := tx.Model(user).Update("balance", gorm.Expr("balance - ?", post.AttachmentPrice)).Error; err != nil {
@ -102,7 +106,7 @@ func (d *walletServant) HandlePostAttachmentBought(post *model.Post, user *model
} }
// 新增账单 // 新增账单
if err := tx.Create(&model.WalletStatement{ if err := tx.Create(&dbr.WalletStatement{
PostID: post.ID, PostID: post.ID,
UserID: user.ID, UserID: user.ID,
ChangeAmount: -post.AttachmentPrice, ChangeAmount: -post.AttachmentPrice,
@ -113,7 +117,7 @@ func (d *walletServant) HandlePostAttachmentBought(post *model.Post, user *model
} }
// 新增附件购买记录 // 新增附件购买记录
if err := tx.Create(&model.PostAttachmentBill{ if err := tx.Create(&dbr.PostAttachmentBill{
PostID: post.ID, PostID: post.ID,
UserID: user.ID, UserID: user.ID,
PaidAmount: post.AttachmentPrice, PaidAmount: post.AttachmentPrice,
@ -124,8 +128,8 @@ func (d *walletServant) HandlePostAttachmentBought(post *model.Post, user *model
// 对附件主新增账单 // 对附件主新增账单
income := int64(float64(post.AttachmentPrice) * conf.AppSetting.AttachmentIncomeRate) income := int64(float64(post.AttachmentPrice) * conf.AppSetting.AttachmentIncomeRate)
if income > 0 { if income > 0 {
master := &model.User{ master := &dbr.User{
Model: &model.Model{ Model: &dbr.Model{
ID: post.UserID, ID: post.UserID,
}, },
} }
@ -137,7 +141,7 @@ func (d *walletServant) HandlePostAttachmentBought(post *model.Post, user *model
} }
// 新增账单 // 新增账单
if err := tx.Create(&model.WalletStatement{ if err := tx.Create(&dbr.WalletStatement{
PostID: post.ID, PostID: post.ID,
UserID: master.ID, UserID: master.ID,
ChangeAmount: income, ChangeAmount: income,

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
// Core service implement base sqlx+mysql. All sub-service // Core service implement base sqlx+mysql. All sub-service
// will declare here and provide initial function. // will declare here and provide initial function.

@ -1,10 +1,13 @@
// Copyright 2022 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 search package search
import ( import (
"time" "time"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -43,7 +46,7 @@ func (s *bridgeTweetSearchServant) DeleteDocuments(identifiers []string) error {
return nil return nil
} }
func (s *bridgeTweetSearchServant) Search(user *model.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { func (s *bridgeTweetSearchServant) Search(user *core.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) {
return s.ts.Search(user, q, offset, limit) return s.ts.Search(user, q, offset, limit)
} }

@ -1,8 +1,11 @@
// Copyright 2022 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 search package search
import ( import (
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/pkg/types" "github.com/rocboss/paopao-ce/pkg/types"
) )
@ -10,19 +13,19 @@ type tweetSearchFilter struct {
ams core.AuthorizationManageService ams core.AuthorizationManageService
} }
func (s *tweetSearchFilter) filterResp(user *model.User, resp *core.QueryResp) { func (s *tweetSearchFilter) filterResp(user *core.User, resp *core.QueryResp) {
// 管理员不过滤 // 管理员不过滤
if user != nil && user.IsAdmin { if user != nil && user.IsAdmin {
return return
} }
var item *model.PostFormated var item *core.PostFormated
items := resp.Items items := resp.Items
latestIndex := len(items) - 1 latestIndex := len(items) - 1
if user == nil { if user == nil {
for i := 0; i <= latestIndex; i++ { for i := 0; i <= latestIndex; i++ {
item = items[i] item = items[i]
if item.Visibility != model.PostVisitPublic { if item.Visibility != core.PostVisitPublic {
items[i] = items[latestIndex] items[i] = items[latestIndex]
items = items[:latestIndex] items = items[:latestIndex]
resp.Total-- resp.Total--
@ -36,8 +39,8 @@ func (s *tweetSearchFilter) filterResp(user *model.User, resp *core.QueryResp) {
friendFilter[user.ID] = types.Empty{} friendFilter[user.ID] = types.Empty{}
for i := 0; i <= latestIndex; i++ { for i := 0; i <= latestIndex; i++ {
item = items[i] item = items[i]
cutFriend = (item.Visibility == model.PostVisitFriend && !friendFilter.IsFriend(item.UserID)) cutFriend = (item.Visibility == core.PostVisitFriend && !friendFilter.IsFriend(item.UserID))
cutPrivate = (item.Visibility == model.PostVisitPrivate && user.ID != item.UserID) cutPrivate = (item.Visibility == core.PostVisitPrivate && user.ID != item.UserID)
if cutFriend || cutPrivate { if cutFriend || cutPrivate {
items[i] = items[latestIndex] items[i] = items[latestIndex]
items = items[:latestIndex] items = items[:latestIndex]

@ -1,3 +1,7 @@
// Copyright 2022 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 search package search
import ( import (
@ -7,7 +11,6 @@ import (
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/meilisearch/meilisearch-go" "github.com/meilisearch/meilisearch-go"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/pkg/json" "github.com/rocboss/paopao-ce/pkg/json"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -28,20 +31,20 @@ type meiliTweetSearchServant struct {
} }
type postInfo struct { type postInfo struct {
ID int64 `json:"id"` ID int64 `json:"id"`
UserID int64 `json:"user_id"` UserID int64 `json:"user_id"`
CommentCount int64 `json:"comment_count"` CommentCount int64 `json:"comment_count"`
CollectionCount int64 `json:"collection_count"` CollectionCount int64 `json:"collection_count"`
UpvoteCount int64 `json:"upvote_count"` UpvoteCount int64 `json:"upvote_count"`
Visibility model.PostVisibleT `json:"visibility"` Visibility core.PostVisibleT `json:"visibility"`
IsTop int `json:"is_top"` IsTop int `json:"is_top"`
IsEssence int `json:"is_essence"` IsEssence int `json:"is_essence"`
IsLock int `json:"is_lock"` IsLock int `json:"is_lock"`
LatestRepliedOn int64 `json:"latest_replied_on"` LatestRepliedOn int64 `json:"latest_replied_on"`
CreatedOn int64 `json:"created_on"` CreatedOn int64 `json:"created_on"`
ModifiedOn int64 `json:"modified_on"` ModifiedOn int64 `json:"modified_on"`
AttachmentPrice int64 `json:"attachment_price"` AttachmentPrice int64 `json:"attachment_price"`
IPLoc string `json:"ip_loc"` IPLoc string `json:"ip_loc"`
} }
func (s *meiliTweetSearchServant) Name() string { func (s *meiliTweetSearchServant) Name() string {
@ -78,7 +81,7 @@ func (s *meiliTweetSearchServant) DeleteDocuments(identifiers []string) error {
return nil return nil
} }
func (s *meiliTweetSearchServant) Search(user *model.User, q *core.QueryReq, offset, limit int) (resp *core.QueryResp, err error) { func (s *meiliTweetSearchServant) Search(user *core.User, q *core.QueryReq, offset, limit int) (resp *core.QueryResp, err error) {
if q.Type == core.SearchTypeDefault && q.Query != "" { if q.Type == core.SearchTypeDefault && q.Query != "" {
resp, err = s.queryByContent(user, q, offset, limit) resp, err = s.queryByContent(user, q, offset, limit)
} else if q.Type == core.SearchTypeTag && q.Query != "" { } else if q.Type == core.SearchTypeTag && q.Query != "" {
@ -96,7 +99,7 @@ func (s *meiliTweetSearchServant) Search(user *model.User, q *core.QueryReq, off
return return
} }
func (s *meiliTweetSearchServant) queryByContent(user *model.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { func (s *meiliTweetSearchServant) queryByContent(user *core.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) {
request := &meilisearch.SearchRequest{ request := &meilisearch.SearchRequest{
Offset: int64(offset), Offset: int64(offset),
Limit: int64(limit), Limit: int64(limit),
@ -117,7 +120,7 @@ func (s *meiliTweetSearchServant) queryByContent(user *model.User, q *core.Query
return s.postsFrom(resp) return s.postsFrom(resp)
} }
func (s *meiliTweetSearchServant) queryByTag(user *model.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { func (s *meiliTweetSearchServant) queryByTag(user *core.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) {
request := &meilisearch.SearchRequest{ request := &meilisearch.SearchRequest{
Offset: int64(offset), Offset: int64(offset),
Limit: int64(limit), Limit: int64(limit),
@ -141,7 +144,7 @@ func (s *meiliTweetSearchServant) queryByTag(user *model.User, q *core.QueryReq,
return s.postsFrom(resp) return s.postsFrom(resp)
} }
func (s *meiliTweetSearchServant) queryAny(user *model.User, offset, limit int) (*core.QueryResp, error) { func (s *meiliTweetSearchServant) queryAny(user *core.User, offset, limit int) (*core.QueryResp, error) {
request := &meilisearch.SearchRequest{ request := &meilisearch.SearchRequest{
Offset: int64(offset), Offset: int64(offset),
Limit: int64(limit), Limit: int64(limit),
@ -161,7 +164,7 @@ func (s *meiliTweetSearchServant) queryAny(user *model.User, offset, limit int)
return s.postsFrom(resp) return s.postsFrom(resp)
} }
func (s *meiliTweetSearchServant) filterList(user *model.User) string { func (s *meiliTweetSearchServant) filterList(user *core.User) string {
if user == nil { if user == nil {
return s.publicFilter return s.publicFilter
} }
@ -174,7 +177,7 @@ func (s *meiliTweetSearchServant) filterList(user *model.User) string {
} }
func (s *meiliTweetSearchServant) postsFrom(resp *meilisearch.SearchResponse) (*core.QueryResp, error) { func (s *meiliTweetSearchServant) postsFrom(resp *meilisearch.SearchResponse) (*core.QueryResp, error) {
posts := make([]*model.PostFormated, 0, len(resp.Hits)) posts := make([]*core.PostFormated, 0, len(resp.Hits))
for _, hit := range resp.Hits { for _, hit := range resp.Hits {
raw, err := json.Marshal(hit) raw, err := json.Marshal(hit)
if err != nil { if err != nil {
@ -184,7 +187,7 @@ func (s *meiliTweetSearchServant) postsFrom(resp *meilisearch.SearchResponse) (*
if err = json.Unmarshal(raw, p); err != nil { if err = json.Unmarshal(raw, p); err != nil {
return nil, err return nil, err
} }
posts = append(posts, &model.PostFormated{ posts = append(posts, &core.PostFormated{
ID: p.ID, ID: p.ID,
UserID: p.UserID, UserID: p.UserID,
CommentCount: p.CommentCount, CommentCount: p.CommentCount,

@ -1,3 +1,7 @@
// Copyright 2022 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 search package search
import ( import (
@ -6,7 +10,6 @@ import (
"github.com/meilisearch/meilisearch-go" "github.com/meilisearch/meilisearch-go"
"github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/pkg/zinc" "github.com/rocboss/paopao-ce/pkg/zinc"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -40,9 +43,9 @@ func NewMeiliTweetSearchService(ams core.AuthorizationManageService) (core.Tweet
}, },
client: client, client: client,
index: client.Index(s.Index), index: client.Index(s.Index),
publicFilter: fmt.Sprintf("visibility=%d", model.PostVisitPublic), publicFilter: fmt.Sprintf("visibility=%d", core.PostVisitPublic),
privateFilter: fmt.Sprintf("visibility=%d AND user_id=", model.PostVisitPrivate), privateFilter: fmt.Sprintf("visibility=%d AND user_id=", core.PostVisitPrivate),
friendFilter: fmt.Sprintf("visibility=%d", model.PostVisitFriend), friendFilter: fmt.Sprintf("visibility=%d", core.PostVisitFriend),
} }
return mts, mts return mts, mts
} }
@ -55,9 +58,9 @@ func NewZincTweetSearchService(ams core.AuthorizationManageService) (core.TweetS
}, },
indexName: s.Index, indexName: s.Index,
client: zinc.NewClient(s), client: zinc.NewClient(s),
publicFilter: fmt.Sprintf("visibility:%d", model.PostVisitPublic), publicFilter: fmt.Sprintf("visibility:%d", core.PostVisitPublic),
privateFilter: fmt.Sprintf("visibility:%d AND user_id:%%d", model.PostVisitPrivate), privateFilter: fmt.Sprintf("visibility:%d AND user_id:%%d", core.PostVisitPrivate),
friendFilter: fmt.Sprintf("visibility:%d", model.PostVisitFriend), friendFilter: fmt.Sprintf("visibility:%d", core.PostVisitFriend),
} }
zts.createIndex() zts.createIndex()

@ -1,3 +1,7 @@
// Copyright 2022 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 search package search
import ( import (
@ -5,7 +9,6 @@ import (
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/internal/model"
"github.com/rocboss/paopao-ce/pkg/json" "github.com/rocboss/paopao-ce/pkg/json"
"github.com/rocboss/paopao-ce/pkg/zinc" "github.com/rocboss/paopao-ce/pkg/zinc"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -73,7 +76,7 @@ func (s *zincTweetSearchServant) DeleteDocuments(identifiers []string) error {
return nil return nil
} }
func (s *zincTweetSearchServant) Search(user *model.User, q *core.QueryReq, offset, limit int) (resp *core.QueryResp, err error) { func (s *zincTweetSearchServant) Search(user *core.User, q *core.QueryReq, offset, limit int) (resp *core.QueryResp, err error) {
if q.Type == core.SearchTypeDefault && q.Query != "" { if q.Type == core.SearchTypeDefault && q.Query != "" {
resp, err = s.queryByContent(user, q, offset, limit) resp, err = s.queryByContent(user, q, offset, limit)
} else if q.Type == core.SearchTypeTag && q.Query != "" { } else if q.Type == core.SearchTypeTag && q.Query != "" {
@ -91,7 +94,7 @@ func (s *zincTweetSearchServant) Search(user *model.User, q *core.QueryReq, offs
return return
} }
func (s *zincTweetSearchServant) queryByContent(user *model.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { func (s *zincTweetSearchServant) queryByContent(user *core.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) {
resp, err := s.client.EsQuery(s.indexName, map[string]any{ resp, err := s.client.EsQuery(s.indexName, map[string]any{
"query": map[string]any{ "query": map[string]any{
"match_phrase": map[string]any{ "match_phrase": map[string]any{
@ -108,7 +111,7 @@ func (s *zincTweetSearchServant) queryByContent(user *model.User, q *core.QueryR
return s.postsFrom(resp) return s.postsFrom(resp)
} }
func (s *zincTweetSearchServant) queryByTag(user *model.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) { func (s *zincTweetSearchServant) queryByTag(user *core.User, q *core.QueryReq, offset, limit int) (*core.QueryResp, error) {
resp, err := s.client.ApiQuery(s.indexName, map[string]any{ resp, err := s.client.ApiQuery(s.indexName, map[string]any{
"search_type": "querystring", "search_type": "querystring",
"query": map[string]any{ "query": map[string]any{
@ -124,7 +127,7 @@ func (s *zincTweetSearchServant) queryByTag(user *model.User, q *core.QueryReq,
return s.postsFrom(resp) return s.postsFrom(resp)
} }
func (s *zincTweetSearchServant) queryAny(user *model.User, offset, limit int) (*core.QueryResp, error) { func (s *zincTweetSearchServant) queryAny(user *core.User, offset, limit int) (*core.QueryResp, error) {
queryMap := map[string]any{ queryMap := map[string]any{
"query": map[string]any{ "query": map[string]any{
"match_all": map[string]string{}, "match_all": map[string]string{},
@ -141,9 +144,9 @@ func (s *zincTweetSearchServant) queryAny(user *model.User, offset, limit int) (
} }
func (s *zincTweetSearchServant) postsFrom(resp *zinc.QueryResultT) (*core.QueryResp, error) { func (s *zincTweetSearchServant) postsFrom(resp *zinc.QueryResultT) (*core.QueryResp, error) {
posts := make([]*model.PostFormated, 0, len(resp.Hits.Hits)) posts := make([]*core.PostFormated, 0, len(resp.Hits.Hits))
for _, hit := range resp.Hits.Hits { for _, hit := range resp.Hits.Hits {
item := &model.PostFormated{} item := &core.PostFormated{}
raw, err := json.Marshal(hit.Source) raw, err := json.Marshal(hit.Source)
if err != nil { if err != nil {
return nil, err return nil, err

@ -1,3 +1,7 @@
// Copyright 2022 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 security package security
import ( import (

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
// Core service implement base sqlx+postgresql. All sub-service // Core service implement base sqlx+postgresql. All sub-service
// will declare here and provide initial function. // will declare here and provide initial function.

@ -1,3 +1,7 @@
// Copyright 2022 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 storage package storage
import ( import (

@ -1,3 +1,7 @@
// Copyright 2022 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 storage package storage
import ( import (

@ -1,3 +1,7 @@
// Copyright 2022 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 storage package storage
import ( import (

@ -1,3 +1,7 @@
// Copyright 2022 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 storage package storage
import ( import (

@ -1,3 +1,7 @@
// Copyright 2022 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 storage package storage
import ( import (

@ -1,3 +1,7 @@
// Copyright 2022 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 storage package storage
import ( import (
@ -8,13 +12,13 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/alimy/cfg"
"github.com/aliyun/aliyun-oss-go-sdk/oss" "github.com/aliyun/aliyun-oss-go-sdk/oss"
"github.com/huaweicloud/huaweicloud-sdk-go-obs/obs" "github.com/huaweicloud/huaweicloud-sdk-go-obs/obs"
"github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials" "github.com/minio/minio-go/v7/pkg/credentials"
"github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/core" "github.com/rocboss/paopao-ce/internal/core"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/tencentyun/cos-go-sdk-v5" "github.com/tencentyun/cos-go-sdk-v5"
) )

@ -1,9 +1,13 @@
// Copyright 2022 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 internal package internal
import ( import (
"github.com/rocboss/paopao-ce/internal/migration" "github.com/rocboss/paopao-ce/internal/migration"
"github.com/rocboss/paopao-ce/internal/routers/api" "github.com/rocboss/paopao-ce/internal/servants/web/broker"
"github.com/rocboss/paopao-ce/internal/service" "github.com/rocboss/paopao-ce/internal/servants/web/routers/api"
) )
func Initialize() { func Initialize() {
@ -11,6 +15,6 @@ func Initialize() {
migration.Run() migration.Run()
// initialize service // initialize service
service.Initialize() broker.Initialize()
api.Initialize() api.Initialize()
} }

@ -1,10 +1,14 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
//go:build !migration //go:build !migration
// +build !migration // +build !migration
package migration package migration
import ( import (
"github.com/rocboss/paopao-ce/pkg/cfg" "github.com/alimy/cfg"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )

@ -1,3 +1,7 @@
// Copyright 2022 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
//go:build migration //go:build migration
// +build migration // +build migration
@ -6,6 +10,7 @@ package migration
import ( import (
"database/sql" "database/sql"
"github.com/alimy/cfg"
"github.com/golang-migrate/migrate/v4" "github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database" "github.com/golang-migrate/migrate/v4/database"
"github.com/golang-migrate/migrate/v4/database/mysql" "github.com/golang-migrate/migrate/v4/database/mysql"
@ -14,7 +19,6 @@ import (
"github.com/golang-migrate/migrate/v4/source" "github.com/golang-migrate/migrate/v4/source"
"github.com/golang-migrate/migrate/v4/source/iofs" "github.com/golang-migrate/migrate/v4/source/iofs"
"github.com/rocboss/paopao-ce/internal/conf" "github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/pkg/cfg"
"github.com/rocboss/paopao-ce/scripts/migration" "github.com/rocboss/paopao-ce/scripts/migration"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )

@ -0,0 +1,2 @@
### Mirc for paopao-ce
RESTful API for paopao-ce use [go-mir](https://github.com/alimy/mir) to generate service interface code automatic.

@ -0,0 +1,140 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
)
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type User interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
Logout() mir.Error
Login(*LoginReq) (*LoginResp, mir.Error)
mustEmbedUnimplementedUserServant()
}
type UserBinding interface {
BindLogin(*gin.Context) (*LoginReq, mir.Error)
mustEmbedUnimplementedUserBinding()
}
type UserRender interface {
RenderLogout(*gin.Context, mir.Error)
RenderLogin(*gin.Context, *LoginResp, mir.Error)
mustEmbedUnimplementedUserRender()
}
// RegisterUserServant register User servant to gin
func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
router := e.Group("m/v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("POST", "/user/logout/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderLogout(c, s.Logout())
})
router.Handle("POST", "/user/login/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindLogin(c)
if err != nil {
r.RenderLogin(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
})
}
// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}
func (UnimplementedUserServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedUserServant) Logout() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {}
// UnimplementedUserRender can be embedded to have forward compatible implementations.
type UnimplementedUserRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedUserRender) mustEmbedUnimplementedUserRender() {}
// UnimplementedUserBinding can be embedded to have forward compatible implementations.
type UnimplementedUserBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) {
obj := new(LoginReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {}

@ -0,0 +1,140 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
)
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type User interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
Logout() mir.Error
Login(*LoginReq) (*LoginResp, mir.Error)
mustEmbedUnimplementedUserServant()
}
type UserBinding interface {
BindLogin(*gin.Context) (*LoginReq, mir.Error)
mustEmbedUnimplementedUserBinding()
}
type UserRender interface {
RenderLogout(*gin.Context, mir.Error)
RenderLogin(*gin.Context, *LoginResp, mir.Error)
mustEmbedUnimplementedUserRender()
}
// RegisterUserServant register User servant to gin
func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
router := e.Group("r/v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("POST", "/user/logout/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderLogout(c, s.Logout())
})
router.Handle("POST", "/user/login/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindLogin(c)
if err != nil {
r.RenderLogin(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
})
}
// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}
func (UnimplementedUserServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedUserServant) Logout() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {}
// UnimplementedUserRender can be embedded to have forward compatible implementations.
type UnimplementedUserRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedUserRender) mustEmbedUnimplementedUserRender() {}
// UnimplementedUserBinding can be embedded to have forward compatible implementations.
type UnimplementedUserBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) {
obj := new(LoginReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {}

@ -0,0 +1,150 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
)
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type User interface {
Logout() mir.Error
Login(*LoginReq) (*LoginResp, mir.Error)
Index() mir.Error
mustEmbedUnimplementedUserServant()
}
type UserBinding interface {
BindLogin(*gin.Context) (*LoginReq, mir.Error)
mustEmbedUnimplementedUserBinding()
}
type UserRender interface {
RenderLogout(*gin.Context, mir.Error)
RenderLogin(*gin.Context, *LoginResp, mir.Error)
RenderIndex(*gin.Context, mir.Error)
mustEmbedUnimplementedUserRender()
}
// RegisterUserServant register User servant to gin
func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
router := e.Group("s/v1")
// register routes info to router
router.Handle("POST", "/user/logout/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderLogout(c, s.Logout())
})
router.Handle("POST", "/user/login/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindLogin(c)
if err != nil {
r.RenderLogin(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
})
router.Handle("GET", "/index/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderIndex(c, s.Index())
})
}
// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}
func (UnimplementedUserServant) Logout() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) Index() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {}
// UnimplementedUserRender can be embedded to have forward compatible implementations.
type UnimplementedUserRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedUserRender) RenderIndex(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedUserRender) mustEmbedUnimplementedUserRender() {}
// UnimplementedUserBinding can be embedded to have forward compatible implementations.
type UnimplementedUserBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) {
obj := new(LoginReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {}

@ -0,0 +1,184 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
)
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type WebCore interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
Logout() mir.Error
Login(*LoginReq) (*LoginResp, mir.Error)
Articles() mir.Error
Index() mir.Error
mustEmbedUnimplementedWebCoreServant()
}
type WebCoreBinding interface {
BindLogin(*gin.Context) (*LoginReq, mir.Error)
mustEmbedUnimplementedWebCoreBinding()
}
type WebCoreRender interface {
RenderLogout(*gin.Context, mir.Error)
RenderLogin(*gin.Context, *LoginResp, mir.Error)
RenderArticles(*gin.Context, mir.Error)
RenderIndex(*gin.Context, mir.Error)
mustEmbedUnimplementedWebCoreRender()
}
// RegisterWebCoreServant register WebCore servant to gin
func RegisterWebCoreServant(e *gin.Engine, s WebCore, b WebCoreBinding, r WebCoreRender) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("POST", "/user/logout/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderLogout(c, s.Logout())
})
router.Handle("POST", "/user/login/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindLogin(c)
if err != nil {
r.RenderLogin(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
})
{
h := func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderArticles(c, s.Articles())
}
router.Handle("HEAD", "/articles/:category/", h)
router.Handle("GET", "/articles/:category/", h)
}
router.Handle("GET", "/index/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderIndex(c, s.Index())
})
}
// UnimplementedWebCoreServant can be embedded to have forward compatible implementations.
type UnimplementedWebCoreServant struct {
}
func (UnimplementedWebCoreServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedWebCoreServant) Logout() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedWebCoreServant) Login(req *LoginReq) (*LoginResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedWebCoreServant) Articles() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedWebCoreServant) Index() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedWebCoreServant) mustEmbedUnimplementedWebCoreServant() {}
// UnimplementedWebCoreRender can be embedded to have forward compatible implementations.
type UnimplementedWebCoreRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedWebCoreRender) RenderLogout(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedWebCoreRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedWebCoreRender) RenderArticles(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedWebCoreRender) RenderIndex(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedWebCoreRender) mustEmbedUnimplementedWebCoreRender() {}
// UnimplementedWebCoreBinding can be embedded to have forward compatible implementations.
type UnimplementedWebCoreBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedWebCoreBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) {
obj := new(LoginReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedWebCoreBinding) mustEmbedUnimplementedWebCoreBinding() {}

@ -0,0 +1,140 @@
// Code generated by go-mir. DO NOT EDIT.
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/gin-gonic/gin"
)
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type User interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
Logout() mir.Error
Login(*LoginReq) (*LoginResp, mir.Error)
mustEmbedUnimplementedUserServant()
}
type UserBinding interface {
BindLogin(*gin.Context) (*LoginReq, mir.Error)
mustEmbedUnimplementedUserBinding()
}
type UserRender interface {
RenderLogout(*gin.Context, mir.Error)
RenderLogin(*gin.Context, *LoginResp, mir.Error)
mustEmbedUnimplementedUserRender()
}
// RegisterUserServant register User servant to gin
func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
router := e.Group("x/v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("POST", "/user/logout/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
r.RenderLogout(c, s.Logout())
})
router.Handle("POST", "/user/login/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindLogin(c)
if err != nil {
r.RenderLogin(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
})
}
// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}
func (UnimplementedUserServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedUserServant) Logout() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedUserServant) mustEmbedUnimplementedUserServant() {}
// UnimplementedUserRender can be embedded to have forward compatible implementations.
type UnimplementedUserRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedUserRender) RenderLogout(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedUserRender) RenderLogin(c *gin.Context, data *LoginResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedUserRender) mustEmbedUnimplementedUserRender() {}
// UnimplementedUserBinding can be embedded to have forward compatible implementations.
type UnimplementedUserBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedUserBinding) BindLogin(c *gin.Context) (*LoginReq, mir.Error) {
obj := new(LoginReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedUserBinding) mustEmbedUnimplementedUserBinding() {}

@ -0,0 +1,32 @@
// Copyright 2022 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 main
import (
"log"
. "github.com/alimy/mir/v3/core"
. "github.com/alimy/mir/v3/engine"
_ "github.com/rocboss/paopao-ce/internal/mirc/routes/admin/v1"
_ "github.com/rocboss/paopao-ce/internal/mirc/routes/bot/v1"
_ "github.com/rocboss/paopao-ce/internal/mirc/routes/localoss/v1"
_ "github.com/rocboss/paopao-ce/internal/mirc/routes/space/v1"
_ "github.com/rocboss/paopao-ce/internal/mirc/routes/v1"
)
//go:generate go run main.go
func main() {
log.Println("generate code start")
opts := Options{
RunMode(InSerialDebugMode),
GeneratorName(GeneratorGin),
SinkPath("auto"),
}
if err := Generate(opts); err != nil {
log.Fatal(err)
}
log.Println("generate code finish")
}

@ -0,0 +1,10 @@
### RESTful API for paopao-ce
本目录包含所有RESTful API相关定义文件
|目录|系列API|备注|
| ----- | ----- | ----- |
|v1|/|Web v1版本RESTful API相关定义文件|
|admin|m|Admin后台运维系列相关RESTful API相关定义文件|
|space|x|SpaceX系列相关RESTful API相关定义文件|
|localoss|s| LocalOSS OBS系列RESTful API相关定义文件|
|bot|r| Bot系列相关RESTful API相关定义文件|

@ -0,0 +1,4 @@
### Admin系列RESTful API相关定义文件
本目录包含 Admin后台运维相关API定义文件。
* v1 - v1版本API

@ -0,0 +1,42 @@
package v1
import (
. "github.com/alimy/mir/v3"
. "github.com/alimy/mir/v3/engine"
)
func init() {
AddEntry(new(User))
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type User struct {
Chain Chain `mir:"-"`
Group Group `mir:"m/v1"`
Login func(Post, LoginReq) LoginResp `mir:"/user/login/"`
Logout func(Post) `mir:"/user/logout/"`
}

@ -0,0 +1,4 @@
### Bot系列RESTful API相关定义文件
本目录包含 Bot相关API定义文件。
* v1 - v1版本API

@ -0,0 +1,42 @@
package v1
import (
. "github.com/alimy/mir/v3"
. "github.com/alimy/mir/v3/engine"
)
func init() {
AddEntry(new(User))
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type User struct {
Chain Chain `mir:"-"`
Group Group `mir:"r/v1"`
Login func(Post, LoginReq) LoginResp `mir:"/user/login/"`
Logout func(Post) `mir:"/user/logout/"`
}

@ -0,0 +1,4 @@
### LocalOSS OBS系列RESTful API相关定义文件
本目录包含 LocalOSS OBS 系列相关API定义文件。
* v1 - v1版本API

@ -0,0 +1,42 @@
package v1
import (
. "github.com/alimy/mir/v3"
. "github.com/alimy/mir/v3/engine"
)
func init() {
AddEntry(new(User))
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type User struct {
Group Group `mir:"s/v1"`
Index func(Get) `mir:"/index/"`
Login func(Post, LoginReq) LoginResp `mir:"/user/login/"`
Logout func(Post) `mir:"/user/logout/"`
}

@ -0,0 +1,4 @@
### SpaceX系列RESTful API
本目录包含SpaceX系列RESTful API相关定义文件
* v1 - v1版本API

@ -0,0 +1,42 @@
package v1
import (
. "github.com/alimy/mir/v3"
. "github.com/alimy/mir/v3/engine"
)
func init() {
AddEntry(new(User))
}
type AgentInfo struct {
Platform string `json:"platform"`
UserAgent string `json:"user_agent"`
}
type ServerInfo struct {
ApiVer string `json:"api_ver"`
}
type UserInfo struct {
Name string `json:"name"`
}
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
Passwd string `json:"passwd"`
}
type LoginResp struct {
UserInfo
ServerInfo ServerInfo `json:"server_info"`
JwtToken string `json:"jwt_token"`
}
type User struct {
Chain Chain `mir:"-"`
Group Group `mir:"x/v1"`
Login func(Post, LoginReq) LoginResp `mir:"/user/login/"`
Logout func(Post) `mir:"/user/logout/"`
}

@ -0,0 +1,15 @@
package v1
import (
. "github.com/alimy/mir/v3"
. "github.com/alimy/mir/v3/engine"
)
func init() {
AddEntry(new(LocalOSS))
}
type LocalOSS struct {
Chain Chain `mir:"-"`
Group Group `mir:"v1"`
}

@ -0,0 +1,15 @@
package v1
import (
. "github.com/alimy/mir/v3"
. "github.com/alimy/mir/v3/engine"
)
func init() {
AddEntry(new(WebAdmin))
}
type WebAdmin struct {
Chain Chain `mir:"-"`
Group Group `mir:"v1"`
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save