merge from dev branch

pull/355/head
Michael Li 1 year ago
commit ae8e99b658
No known key found for this signature in database

@ -9,6 +9,7 @@ updates:
directory: "/"
schedule:
interval: "weekly"
target-branch: "dev"
reviewers:
- "rocboss"
- "alimy"

@ -7,7 +7,9 @@ on:
- dev
- 'jc/**'
- 'feature/**'
- 'r/**'
- 'x/**'
- 't/**'
paths:
- '**.go'
- 'go.mod'
@ -45,7 +47,7 @@ jobs:
name: Test
strategy:
matrix:
go-version: [ 1.18.x, 1.19.x ]
go-version: [ 1.20.x ]
platform: [ ubuntu-latest, macos-latest ]
runs-on: ${{ matrix.platform }}
steps:
@ -64,7 +66,7 @@ jobs:
name: TestOnWindows
strategy:
matrix:
go-version: [ 1.18.x, 1.19.x ]
go-version: [ 1.20.x ]
platform: [ windows-latest ]
runs-on: ${{ matrix.platform }}
steps:

4
.gitignore vendored

@ -1,5 +1,6 @@
.DS_Store
.idea
.vscode
__debug_bin
!*.example
/config.yaml
*.log
@ -7,3 +8,4 @@ paopao-ce*
/release
/data
/custom
/.custom

@ -0,0 +1,4 @@
.DS_Store
*.log
__debug_bin
settings.json

@ -0,0 +1,14 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "paopao-ce [debug]",
"type": "go",
"request": "launch",
"mode": "exec",
"program": "${workspaceFolder}/.vscode/__debug_bin",
"preLaunchTask": "go: build (debug)",
"cwd": "${workspaceFolder}"
}
]
}

@ -0,0 +1,4 @@
let launch = require('./launch.json');
launch.configurations.sort((a, b) => a.name.localeCompare(b.name));
let fs = require('fs');
fs.writeFileSync('launch.json', JSON.stringify(launch, null, 4));

21
.vscode/tasks.json vendored

@ -0,0 +1,21 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "go: build (debug)",
"type": "shell",
"command": "go",
"args": [
"build",
"-gcflags=all=-N -l",
"-tags",
"'embed go_json'",
"-o",
"${workspaceFolder}/.vscode/__debug_bin"
],
"options": {
"cwd": "${workspaceFolder}"
}
}
]
}

@ -0,0 +1,178 @@
# Changelog
All notable changes to paopao-ce are documented in this file.
## 0.4.0+dev ([`dev`](https://github.com/rocboss/paopao-ce/tree/dev))
### Added
- add `pprof` feature support [#327](https://github.com/rocboss/paopao-ce/pull/327)
- use compiler profile-guided optimization (PGO) to further optimize builds. [#327](https://github.com/rocboss/paopao-ce/pull/327)
- frontend: re-add stars page embed to profile page. [#339](https://github.com/rocboss/paopao-ce/pull/339)
- simple support for user posts filter by style(post/comment/media/star). [#345](https://github.com/rocboss/paopao-ce/pull/345)
- add user highlight tweet support include custom tweet set to highlight and list in user/profile page.
### Changed
- change man content width to 600px and optimize tweet/comment/replay text length. [#333](https://github.com/rocboss/paopao-ce/pull/333)
## 0.3.1
### Fixed
- fixed: video player assets cdn error. [&caff8c0](https://github.com/rocboss/paopao-ce/commit/caff8c052be6c8d59576011192f830fd98e17ab3 'commit caff8c0')
## 0.3.0
### Added
- add custom comment sort strategy support [#243](https://github.com/rocboss/paopao-ce/pull/243)
- add `RedisCacheIndex` feature [#250](https://github.com/rocboss/paopao-ce/pull/250)
- add `Sentry` feature [#258](https://github.com/rocboss/paopao-ce/pull/258)
- add simple tweet share feature(just copy tweet link to clipboard now) support [#264](https://github.com/rocboss/paopao-ce/pull/264)
- add default tweet max length configure in web/.env support. [&a1160ca](https://github.com/rocboss/paopao-ce/commit/a1160ca79380445157146d9eae1710543c153cce 'commit a1160ca')
Set the value of `VITE_DEFAULT_TWEET_MAX_LENGTH` in file web/.env to change the tweet max default length.
- add custom whether provide user register configure in web/.env support. [#267](https://github.com/rocboss/paopao-ce/pull/267)
Set the value of `VITE_ALLOW_USER_REGISTER` in file web/.env to custom whether provide user register feature.
```
# file: web/.env or web/.env.local
...
# 局部参数
VITE_ALLOW_USER_REGISTER=true
...
```
and disallow user register in backend(add `Web:DisallowUserRegister` feature in `config.yaml`):
```yaml
# file config.yaml
...
Features:
Default: ["Base", "Postgres", "Zinc", "LocalOSS", "LoggerZinc", "BigCacheIndex", "Friendship", "Service", "Web:DisallowUserRegister"]
...
```
- add topic follow feature support [#273](https://github.com/rocboss/paopao-ce/pull/273)
mirgration database first(sql ddl file in `scripts/migration/**/*_topic_follow.up.sql`):
```sql
CREATE TABLE `p_topic_user` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`topic_id` BIGINT UNSIGNED NOT NULL COMMENT '标签ID',
`user_id` BIGINT UNSIGNED NOT NULL COMMENT '创建者ID',
`alias_name` VARCHAR ( 255 ) COMMENT '别名',
`remark` VARCHAR ( 512 ) COMMENT '备注',
`quote_num` BIGINT UNSIGNED COMMENT '引用数',
`is_top` TINYINT UNSIGNED NOT NULL DEFAULT '0' COMMENT '是否置顶 0 为未置顶、1 为已置顶',
`created_on` BIGINT UNSIGNED NOT NULL DEFAULT '0' COMMENT '创建时间',
`modified_on` BIGINT UNSIGNED NOT NULL DEFAULT '0' COMMENT '修改时间',
`deleted_on` BIGINT UNSIGNED NOT NULL DEFAULT '0' COMMENT '删除时间',
`is_del` TINYINT UNSIGNED NOT NULL DEFAULT '0' COMMENT '是否删除 0 为未删除、1 为已删除',
`reserve_a` VARCHAR ( 255 ) COMMENT '保留字段a',
`reserve_b` VARCHAR ( 255 ) COMMENT '保留字段b',
PRIMARY KEY ( `id` ) USING BTREE,
UNIQUE KEY `idx_topic_user_uid_tid` ( `topic_id`, `user_id` ) USING BTREE
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户话题';
```
- add tweet comment thumbs up/down feature support [#275](https://github.com/rocboss/paopao-ce/pull/275)
mirgration database first(sql ddl file in `scripts/migration/**/*_comment_thumbs.up.sql`):
- add load more comments feature support [&60b217b](https://github.com/rocboss/paopao-ce/commit/60b217bcd950c69ba45cebcaa17efdf8048d5a4f 'commit 60b217b')
### Fixed
- fixed sql ddl p_contact's column `is_delete` define error (change to `is_del`) in scripts/paopao-mysql.sql [&afd8fe1](https://github.com/rocboss/paopao-ce/commit/afd8fe18d2dce08a4af846c2f822379d99a3d3b3 'commit afd8fe1')
- fixed cache index not expire in delete/add tweet error [#266](https://github.com/rocboss/paopao-ce/pull/266)
- fixed tweet's owner not allow star/collection action when tweet is private error [#274](https://github.com/rocboss/paopao-ce/pull/274)
- fixed user not list owner's collectioned private tweet error [#274](https://github.com/rocboss/paopao-ce/pull/274)
- fixed comments thumbs up/down state incorrect error [#283](https://github.com/rocboss/paopao-ce/pull/283)
### Fixed
- fixed sql ddl p_contact's column `is_delete` define error (change to `is_del`) in scripts/paopao-mysql.sql [&afd8fe1](https://github.com/rocboss/paopao-ce/commit/afd8fe18d2dce08a4af846c2f822379d99a3d3b3 'commit afd8fe1')
### Changed
- use [github.com/rueian/rueidis](https://github.com/rueian/rueidis) as Redis client [#249](https://github.com/rocboss/paopao-ce/pull/249)
the **Old** redis client configure field
```yaml
...
Redis:
Host: redis:6379
Password:
DB:
```
the **New** redis client configure field
```yaml
...
Redis:
InitAddress:
- redis:6379
Username:
Password:
SelectDB:
ConnWriteTimeout: 60 # 连接写超时时间 多少秒 默认 60秒
```
- optimize web frontend dark theme [&b082a8f](https://github.com/rocboss/paopao-ce/commit/b082a8fa5e43dd6dacf459df93fa7e243dd901ea 'commit b082a8f')
- change web frontend main content layout default size to 544px [&b082a8f](https://github.com/rocboss/paopao-ce/commit/b082a8fa5e43dd6dacf459df93fa7e243dd901ea 'commit b082a8f')
- optimize web frontend in mobile environment use Drawer to display menu [#265](https://github.com/rocboss/paopao-ce/pull/265)
- optimize Dockerfile use pre-build builder/runner image to prevent network latency problem (`bitbus/paopao-ce-backend-builder` `bitbus/paopao-ce-backend-runner`) [#265](https://github.com/rocboss/paopao-ce/pull/265)
- optimize web ui in mobile environment [#280](https://github.com/rocboss/paopao-ce/pull/280)
- optimize upload zip attachment compatible with different browsers for uploading zip mimetype [#286](https://github.com/rocboss/paopao-ce/pull/286)
- adapte meilisearch to version v1.1 [#288](https://github.com/rocboss/paopao-ce/pull/288)
### Removed
- remove `Deprecated:OldWeb` feature [#256](https://github.com/rocboss/paopao-ce/pull/256)
## 0.2.5
### Changed
- fixed sql ddl error for contact table [#281](https://github.com/rocboss/paopao-ce/pull/281)
## 0.2.4
### Added
- add PWA support for web frontend [#242](https://github.com/rocboss/paopao-ce/pull/242)
## 0.2.3
### Added
- add PostgreSQL DDL file [#229](https://github.com/rocboss/paopao-ce/pull/229)
### Changed
- optimize MySQL DDL file [#229](https://github.com/rocboss/paopao-ce/pull/229)
- optimize Sqlite3 DDL file [#229](https://github.com/rocboss/paopao-ce/pull/229)
## 0.2.2
### Fixed
- fixed add star to tweet error [#222](https://github.com/rocboss/paopao-ce/pull/222)
## 0.2.1
### Changed
- optimize docker-compose.yaml use bitbus/paopao-ce:latest as release image [#217](https://github.com/rocboss/paopao-ce/pull/217)
### Fixed
- fixed sql ddl in scripts/paopao-mysql.sql and scripts/paopao-sqlite3.sql [#217](https://github.com/rocboss/paopao-ce/pull/217)
## 0.2.0
### Added
- add `Friendship` feature [#192](https://github.com/rocboss/paopao-ce/pull/192)
- add `Lightship` feature [#198](https://github.com/rocboss/paopao-ce/pull/198)
- add `Pyroscope` feature [#199](https://github.com/rocboss/paopao-ce/pull/199)
- add new `Web` service [#196](https://github.com/rocboss/paopao-ce/pull/196)
- add `Frontend:Web` feature [#196](https://github.com/rocboss/paopao-ce/pull/196)
- add `Deprecated:OldWeb` feature [#196](https://github.com/rocboss/paopao-ce/pull/196)
### Changes
- support run multiple service in single paopao-ce instance [#196](https://github.com/rocboss/paopao-ce/pull/196)
- use [go-mir](https://github.com/alimy/mir) optimize paopao-ce source code architecture [#196](https://github.com/rocboss/paopao-ce/pull/196)
### Fixed
- some other features optimize and bug fix
---
**Older change logs can be found on [GitHub](https://github.com/rocboss/paopao-ce/releases?after=v0.2.0).**

@ -1,5 +1,7 @@
# syntax=docker/dockerfile:experimental
# build frontend
FROM node:18-alpine as frontend
FROM node:19-alpine as frontend
ARG API_HOST
ARG USE_API_HOST=yes
ARG EMBED_UI=yes
@ -11,15 +13,11 @@ RUN [ $EMBED_UI != yes ] || [ $USE_DIST != no ] || (yarn && yarn build)
RUN [ $EMBED_UI = yes ] || mkdir dist || echo ""
# build backend
FROM golang:1.18-alpine AS backend
FROM bitbus/paopao-ce-backend-builder:latest AS backend
ARG API_HOST
ARG USE_API_HOST=yes
ARG EMBED_UI=yes
ARG USE_DIST=no
RUN apk --no-cache --no-progress add --virtual \
build-deps \
build-base \
git
WORKDIR /paopao-ce
COPY . .
@ -28,19 +26,18 @@ ENV GOPROXY=https://goproxy.cn
RUN [ $EMBED_UI != yes ] || make build TAGS='embed go_json'
RUN [ $EMBED_UI = yes ] || make build TAGS='go_json'
FROM alpine:3.16
FROM bitbus/paopao-ce-backend-runner:latest
ARG API_HOST
ARG USE_API_HOST=yes
ARG EMBED_UI=yes
ARG USE_DIST=no
ENV TZ=Asia/Shanghai
RUN apk update && apk add --no-cache ca-certificates && update-ca-certificates
WORKDIR /app/paopao-ce
COPY --from=backend /paopao-ce/release/paopao-ce .
COPY configs ./configs
COPY --from=backend /paopao-ce/config.yaml.sample config.yaml
VOLUME ["/app/paopao-ce/configs"]
VOLUME ["/app/paopao-ce/custom"]
EXPOSE 8008
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD ps -ef | grep paopao-ce || exit 1
ENTRYPOINT ["/app/paopao-ce/paopao-ce"]

@ -4,37 +4,38 @@ TARGET = paopao-ce
ifeq ($(OS),Windows_NT)
TARGET := $(TARGET).exe
endif
TARGET_BIN = $(basename $(TARGET))
ifeq (n$(CGO_ENABLED),n)
CGO_ENABLED := 1
endif
RELEASE_ROOT = release
RELEASE_FILES = LICENSE README.md config.yaml.sample scripts configs
RELEASE_FILES = LICENSE README.md CHANGELOG.md config.yaml.sample docker-compose.yaml scripts docs
RELEASE_LINUX_AMD64 = $(RELEASE_ROOT)/linux-amd64/$(TARGET)
RELEASE_DARWIN_AMD64 = $(RELEASE_ROOT)/darwin-amd64/$(TARGET)
RELEASE_DARWIN_ARM64 = $(RELEASE_ROOT)/darwin-arm64/$(TARGET)
RELEASE_WINDOWS_AMD64 = $(RELEASE_ROOT)/windows-amd64/$(TARGET)
BUILD_VERSION := $(shell git describe --tags | cut -f 1 -d "-")
BUILD_VERSION := $(shell git describe --tags --always | cut -f1 -f2 -d "-")
BUILD_DATE := $(shell date +'%Y-%m-%d %H:%M:%S')
SHA_SHORT := $(shell git rev-parse --short HEAD)
TAGS = ""
MOD_NAME = github.com/rocboss/paopao-ce
LDFLAGS = -X "${MOD_NAME}/pkg/debug.version=${BUILD_VERSION}" \
-X "${MOD_NAME}/pkg/debug.buildDate=${BUILD_DATE}" \
-X "${MOD_NAME}/pkg/debug.commitID=${SHA_SHORT}" -w -s
LDFLAGS = -X "${MOD_NAME}/pkg/version.version=${BUILD_VERSION}" \
-X "${MOD_NAME}/pkg/version.buildDate=${BUILD_DATE}" \
-X "${MOD_NAME}/pkg/version.commitID=${SHA_SHORT}" -w -s
all: fmt build
build:
@go mod download
@echo Build paopao-ce
@go build -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_ROOT)/$(TARGET)
@go build -pgo=auto -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_ROOT)/$(TARGET)
run:
@go run -trimpath -gcflags "all=-N -l" -tags '$(TAGS)' -ldflags '$(LDFLAGS)' .
@go run -pgo=auto -trimpath -gcflags "all=-N -l" -tags '$(TAGS)' -ldflags '$(LDFLAGS)' .
.PHONY: release
release: linux-amd64 darwin-amd64 darwin-arm64 windows-x64
@ -50,37 +51,37 @@ release: linux-amd64 darwin-amd64 darwin-arm64 windows-x64
.PHONY: linux-amd64
linux-amd64:
@echo Build paopao-ce [linux-amd64] CGO_ENABLED=$(CGO_ENABLED)
@CGO_ENABLED=$(CGO_ENABLED) GOOS=linux GOARCH=amd64 go build -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_LINUX_AMD64)/$(TARGET)
@echo Build paopao-ce [linux-amd64] CGO_ENABLED=$(CGO_ENABLED) TAGS="'$(TAGS)'"
@CGO_ENABLED=$(CGO_ENABLED) GOOS=linux GOARCH=amd64 go build -pgo=auto -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_LINUX_AMD64)/$(TARGET_BIN)
.PHONY: darwin-amd64
darwin-amd64:
@echo Build paopao-ce [darwin-amd64] CGO_ENABLED=$(CGO_ENABLED)
@CGO_ENABLED=$(CGO_ENABLED) GOOS=darwin GOARCH=amd64 go build -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_DARWIN_AMD64)/$(TARGET)
@echo Build paopao-ce [darwin-amd64] CGO_ENABLED=$(CGO_ENABLED) TAGS="'$(TAGS)'"
@CGO_ENABLED=$(CGO_ENABLED) GOOS=darwin GOARCH=amd64 go build -pgo=auto -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_DARWIN_AMD64)/$(TARGET_BIN)
.PHONY: darwin-arm64
darwin-arm64:
@echo Build paopao-ce [darwin-arm64] CGO_ENABLED=$(CGO_ENABLED)
@CGO_ENABLED=$(CGO_ENABLED) GOOS=darwin GOARCH=arm64 go build -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_DARWIN_ARM64)/$(TARGET)
@echo Build paopao-ce [darwin-arm64] CGO_ENABLED=$(CGO_ENABLED) TAGS="'$(TAGS)'"
@CGO_ENABLED=$(CGO_ENABLED) GOOS=darwin GOARCH=arm64 go build -pgo=auto -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_DARWIN_ARM64)/$(TARGET_BIN)
.PHONY: windows-x64
windows-x64:
@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
@echo Build paopao-ce [windows-x64] CGO_ENABLED=$(CGO_ENABLED) TAGS="'$(TAGS)'"
@CGO_ENABLED=$(CGO_ENABLED) GOOS=windows GOARCH=amd64 go build -pgo=auto -trimpath -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $(RELEASE_WINDOWS_AMD64)/$(TARGET_BIN).exe
.PHONY: generate
generate: gen-mir gen-grpc
generate: gen-mir gen-rpc
.PHONY: gen-mir
gen-mir:
@go generate mirc/main.go
@go generate mirc/gen.go
@go fmt ./auto/api/...
.PHONY: gen-grpc
gen-grpc:
@rm -rf auto/rpc
.PHONY: gen-rpc
gen-rpc:
@rm -rf auto/rpc auto/connect
@buf generate proto
@go fmt ./auto/rpc/...
@go fmt ./auto/rpc/... ./auto/connect/...
.PHONY: proto-mod
proto-mod:
@ -109,9 +110,11 @@ pre-commit: fmt
.PHONY: install-protobuf-plugins
install-protobuf-plugins:
@go install github.com/bufbuild/buf/cmd/buf@v1.11.0
@go install github.com/bufbuild/buf/cmd/protoc-gen-buf-breaking@v1.11.0
@go install github.com/bufbuild/buf/cmd/protoc-gen-buf-lint@v1.11.0
@go install github.com/bufbuild/buf/cmd/buf@v1.25.0
@go install github.com/bufbuild/buf/cmd/protoc-gen-buf-breaking@v1.25.0
@go install github.com/bufbuild/buf/cmd/protoc-gen-buf-lint@v1.25.0
@go install github.com/bufbuild/connect-go/cmd/protoc-gen-connect-go@latest
@go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
@go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
@go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

@ -65,7 +65,7 @@ PaoPao主要由以下优秀的开源项目/工具构建
### 环境要求
* Go (1.18+)
* Go (1.20+)
* Node.js (14+)
* MySQL (5.7+)
* Redis
@ -194,7 +194,10 @@ PaoPao主要由以下优秀的开源项目/工具构建
docker build -t your/paopao-ce:tag --build-arg EMBED_UI=no .
# 运行
docker run -d -p 8008:8008 -v ${PWD}/config.yaml.sample:/app/paopao-ce/config.yaml your/paopao-ce:tag
mkdir custom && docker run -d -p 8008:8008 -v ${PWD}/custom:/app/paopao-ce/custom -v ${PWD}/config.yaml.sample:/app/paopao-ce/config.yaml your/paopao-ce:tag
# 或者直接运行构建好的docker image
mkdir custom && docker run -d -p 8008:8008 -v ${PWD}/custom:/app/paopao-ce/custom -v ${PWD}/config.yaml.sample:/app/paopao-ce/config.yaml bitbus/paopao-ce:latest
```
* 前端:
@ -217,8 +220,10 @@ PaoPao主要由以下优秀的开源项目/工具构建
### 方式三. 使用 docker-compose 运行
```sh
git clone https://github.com/rocboss/paopao-ce.git
docker compose up --build
# visit paopao-ce(http://127.0.0.1:8008) and phpMyadmin(http://127.0.0.1:8080)
cd paopao-ce && docker compose up -d
# visit http://localhost:8008 👀 paopao-ce
# visit http://localhost:8001 👀 RedisInsight
# visit http://localhost:8080 👀 phpMyAdmin
```
默认是使用config.yaml.sample的配置如果需要自定义配置请拷贝默认配置文件(比如config.yaml)修改后再同步配置到docker-compose.yaml如下
@ -227,8 +232,7 @@ docker compose up --build
# file: docker-compose.yaml
...
backend:
build:
context: .
image: bitbus/paopao-ce:latest
restart: always
depends_on:
- db
@ -246,8 +250,18 @@ docker compose up --build
> 注意:默认提供的 docker-compose.yaml 初衷是搭建本机开发调试环境,如果需要产品部署供外网访问,请自行调优配置参数或使用其他方式部署。
### API 文档
* `config.yaml` 添加 `Docs:OpenAPI` 功能项:
### 开发文档
#### Docs文档说明
`docs`目录提供了各种开发文档,包括:
* [deploy](docs/deploy/) - paopao-ce部署文档
* [discuss](docs/discuss/) - 开发相关的问题交流论述文档
* [openapi](docs/openapi/) - paopao-ce后端导出API文档
* [proposal](docs/proposal/) - paopao-ce功能特性提按文档
> 比如关于paopao-ce的设计定位可以参考[docs/proposal/001-关于paopao-ce的设计定位](docs/proposal/001-关于paopao-ce的设计定位.md)简要阐述了paopao-ce是如何定位自身的。
#### API文档
开发者可以在本地开启`Docs`服务浏览后端导出的API服务接口文档。
* `config.yaml` 添加 `Docs` 功能项:
```yaml
...
Features:
@ -260,7 +274,7 @@ Features:
```sh
make run TAGS='docs'
# visit http://127.0.0.1:8008/docs/openapi
# visit http://127.0.0.1:8011/docs/openapi
```
### 配置说明
@ -328,11 +342,11 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r
|`Bot` | 子服务 | WIP | 开启Bot服务|
|`NativeOBS` | 子服务 | WIP | 开启NativeOBS服务|
|`Docs` | 子服务 | WIP | 开启开发者文档服务|
|`Frontend:Web` | 子服务 | 内测 | 开启独立前端服务|
|`Frontend:EmbedWeb` | 子服务 | 内测 | 开启内嵌于后端Web API服务中的前端服务|
|`Deprecated:Web` | 子服务 | 稳定 | 开启旧的Web服务|
|`Frontend:Web` | 子服务 | 稳定 | 开启独立前端服务|
|`Frontend:EmbedWeb` | 子服务 | 稳定 | 开启内嵌于后端Web API服务中的前端服务|
|`Gorm` | 数据库 | 稳定(默认) | 使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM默认使用 `Gorm` + `MySQL`组合|
|`Sqlx`| 数据库 | WIP | 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM|
|`Sqlc`| 数据库 | WIP | 使用[sqlc](https://github.com/kyleconroy/sqlc)自动生成ORM代码|
|`MySQL`| 数据库 | 稳定(默认) | 使用MySQL作为数据库|
|`Postgres`| 数据库 | 稳定 | 使用PostgreSQL作为数据库|
|`Sqlite3`| 数据库 | 稳定 | 使用Sqlite3作为数据库|
@ -345,20 +359,26 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r
|`OSS:Retention` | 对象存储 | 内测 |基于对象存储系统的对象过期自动删除特性实现 先创建临时对象再持久化的功能|
|`OSS:TempDir` | 对象存储 | 内测 |基于对象存储系统的对象拷贝/移动特性实现 先创建临时对象再持久化的功能|
|`Redis` | 缓存 | 稳定 | Redis缓存功能 |
|`SimpleCacheIndex` | 缓存 | 稳定 | 提供简单的 广场推文列表 的缓存功能 |
|`SimpleCacheIndex` | 缓存 | Deprecated | 提供简单的 广场推文列表 的缓存功能 |
|`BigCacheIndex` | 缓存 | 稳定(推荐) | 使用[BigCache](https://github.com/allegro/bigcache)缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面 |
|`RedisCacheIndex` | 缓存 | 内测(推荐) | 使用Redis缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面 |
|`Zinc` | 搜索 | 稳定(推荐) | 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务 |
|`Meili` | 搜索 | 稳定(推荐) | 基于[Meilisearch](https://github.com/meilisearch/meilisearch)搜索引擎提供推文搜索服务 |
|`Bleve` | 搜索 | WIP | 基于[Bleve](https://github.com/blevesearch/bleve)搜索引擎提供推文搜索服务 |
|[`Sentry`](docs/proposal/23040412-关于使用sentry用于错误追踪与性能检测的设计.md) | 监控 | 内测 | 使用Sentry进行错误跟踪与性能监控 |
|`LoggerFile` | 日志 | 稳定 | 使用文件写日志 |
|`LoggerZinc` | 日志 | 稳定(推荐) | 使用[Zinc](https://github.com/zinclabs/zinc)写日志 |
|`LoggerMeili` | 日志 | 内测 | 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志 |
|`Friendship` | 关系模式 | 内测(默认) | 弱关系好友模式,类似微信朋友圈 |
|`Followship` | 关系模式 | WIP | 关注者模式类似Twitter的Follow模式 |
|[`Friendship`](docs/proposal/002-关于Friendship功能项的设计.md) | 关系模式 | 内测 | 弱关系好友模式,类似微信朋友圈 |
|[`Followship`](docs/proposal/003-关于Followship功能项的设计.md) | 关系模式 | WIP | 关注者模式类似Twitter的Follow模式 |
|[`Lightship`](docs/proposal/011-关于Lightship功能项的设计.md) | 关系模式 | 内测(默认) | 开放模式,所有推文都公开可见 |
|`Alipay` | 支付 | 稳定 | 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能 |
|`Sms` | 短信验证 | 稳定 | 开启短信验证码功能,用于手机绑定验证手机是否注册者的;功能如果没有开启,手机绑定时任意短信验证码都可以绑定手机 |
|`Docs:OpenAPI` | 开发文档 | 稳定 | 开启openapi文档功能提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi) |
|[`Pyroscope`](docs/proposal/23021510-关于使用pyroscope用于性能调试的设计.md)| 性能优化 | 内测 | 开启Pyroscope功能用于性能调试 |
|[`Pprof`](docs/proposal/23062905-添加Pprof功能特性用于获取Profile.md)| 性能优化 | 内测 | 开启Pprof功能收集Profile信息 |
|`PhoneBind` | 其他 | 稳定 | 手机绑定功能 |
|`Web:DisallowUserRegister` | 功能特性 | 稳定 | 不允许用户注册 |
> 功能项状态详情参考 [features-status](features-status.md).
@ -416,19 +436,10 @@ docker run -d --name meili -v ${PWD}/data/meili/data:/meili_data -p 7700:7700 -e
# 使用docker compose运行需要删除docker-compose.yaml中关于meili的注释
docker compose up -d meili
# 使用docker运行meilisearch的ui管理前端
docker run -d --name uirecord -p 7701:3000 bitriory/uirecord
# visit http://localhost:7701
# 使用docker compose运行meilisearch的ui管理前端需要删除docker-compose.yaml中关于uirecord的注释
docker compose up -d uirecord
# visit http://loclahost:7701
# 查看meili运行状态
docker compose ps
NAME COMMAND SERVICE STATUS PORTS
paopao-ce-meili-1 "tini -- /bin/sh -c …" meili running 0.0.0.0:7700->7700/tcp
paopao-ce-uirecord-1 "docker-entrypoint.s…" uirecord running 0.0.0.0:7701->3000/tcp
```
* 修改Meili配置
@ -480,6 +491,32 @@ MinIO: # MinIO 存储配置
...
```
#### [Pyroscope](https://github.com/pyroscope-io/pyroscope) 性能剖析
* Pyroscope运行
```sh
mkdir -p data/minio/data
# 使用Docker运行
docker run -it -p 4040:4040 pyroscope/pyroscope:latest server
# 使用docker compose运行 需要删除docker-compose.yaml中关于pyroscope的注释
docker compose up -d pyroscope
# visit http://loclahost:4040
```
* 修改Pyroscope配置
```yaml
# features中加上 MinIO
Features:
Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "Pyroscope"]
...
Pyroscope: # Pyroscope配置
AppName: "paopao-ce"
Endpoint: "http://localhost:4040" # Pyroscope server address
AuthToken: # Pyroscope authentication token
Logger: none # Pyroscope logger (standard | logrus | none)
...
```
### 源代码分支管理
**主代码库`github.com/rocboss/paopao-ce`**
```bash
@ -492,20 +529,48 @@ feature/followship
feature/mir
feature/localoss
jc/alimy
r/paopao-plus
r/paopao-pro
x/sqlc
x/sqlx
```
**分支说明**
* 分支`main`是主分支也是paopao-ce的稳定版本发布分支只有经过内部测试没有重大bug出现的稳定代码才会推进到这个分支该分支主要由`beta`分支代码演进而来,原则上**只接受bug修复PR**。`rc版本/稳定版本` 发布都应该在`main`主分支中进行。
* 分支`beta`是公测分支,代码推进到`main`主分支的候选分支;该分支主要由`dev`分支代码演进而来,**接受bug修复以及新功能优化的PR**原则上不接受新功能PR。`alpha/beta版本` 发布都应该在`beta`公测分支下进行。
* 分支`dev`是开发分支,**不定期频繁更新**,接受 *新功能PR、代码优化PR、bug修复PR***新功能PR** 都应该首先提交给`dev`分支进行合并bug修复/代码优化 后 **冻结新功能** 将代码演进合并到`beta`分支。
* `feature/*`是新功能子分支,一般新功能子分支都是 *从`dev`开发分支fork出来的*;子功能分支 **只专注于该新功能** 代码的开发/优化,待开发接近内测阶段 *提交新功能PR给`dev`分支进行review/merge*,待新功能代码演进到`beta`分支后,原则上是可以删除该分支,但也可以保留到稳定版本发布。**该分支专注于新功能的开发只接受新功能的bug修复/优化PR**。
* `jc/*`是代码库维护者的开发分支一般包含一些局部优化或者bug修复代码有时可以直接将代码merge到`dev/beta`分支原则上不允许直接merge代码到`main`主分支。
* `x/*`是技术实验分支某些技术的引入需要经过具体的代码实现与真实场景的测评考量评估后如果某项技术适合引入到paopao-ce就fork出一个`feature/*`分支作为新功能引入到paopao-ce。一般一些比较激进的技术从`dev`分支fork出一个新的`x/*`分支各种尝试、考量、评估后或丢弃、或引入到paopao-ce。
**分支说明**
| 名称 | 说明 | 备注|
| ----- | ----- | ----- |
| [`main`](https://github.com/rocboss/paopao-ce) | 主分支 |分支`main`是主分支也是paopao-ce的稳定版本发布分支只有经过内部测试没有重大bug出现的稳定代码才会推进到这个分支该分支主要由`beta`分支代码演进而来,原则上**只接受bug修复PR**。`rc版本/稳定版本` 发布都应该在`main`主分支中进行。|
| [`beta`](https://github.com/rocboss/paopao-ce/tree/beta) | 公测分支 |分支`beta`是公测分支,代码推进到`main`主分支的候选分支;该分支主要由`alpha`分支代码演进而来,**接受bug修复以及新功能优化的PR**原则上不接受新功能PR。`beta版本` 发布都应该在`beta`公测分支下进行。|
| [`alpha`](https://github.com/rocboss/paopao-ce/tree/alpha) | 内测分支 |分支`alpha`是内测分支,代码推进到`beta`分支的候选分支;该分支主要由`dev`分支代码演进而来,**接受bug修复以及新功能相关的PR**接受新功能PR。分支代码演进到一个里程碑式的阶段后**冻结所有新功能**,合并代码到`beta`公测分支进行下一阶段的持续演进。`alpha版本` 发布都应该在`alpha`内测分支下进行。|
| [`dev`](https://github.com/rocboss/paopao-ce/tree/dev) | 开发分支 | 分支`dev`是开发分支,**不定期频繁更新**,接受 *新功能PR、代码优化PR、bug修复PR***新功能PR** 都应该首先提交给`dev`分支进行合并bug修复/新功能开发/代码优化 **阶段性冻结** 后将代码演进合并到`alpha`分支。|
| `feature/*` | 子功能分支 |`feature/*`是新功能子分支,一般新功能子分支都是 *从`dev`开发分支fork出来的*;子功能分支 **只专注于该新功能** 代码的开发/优化,待开发接近内测阶段 *提交新功能PR给`dev`分支进行review/merge*,待新功能代码演进到`beta`分支后,原则上是可以删除该分支,但也可以保留到稳定版本发布。**该分支专注于新功能的开发只接受新功能的bug修复/优化PR**。|
| `jc/*` |维护者的开发分支|`jc/*`是代码库维护者的开发分支一般包含一些局部优化或者bug修复代码有时可以直接将代码merge到`dev/beta`分支原则上不允许直接merge代码到`main`主分支。|
| `x/*` |实验分支|`x/*`是技术实验分支某些技术的引入需要经过具体的代码实现与真实场景的测评考量评估后如果某项技术适合引入到paopao-ce就fork出一个`feature/*`分支作为新功能引入到paopao-ce。一般一些比较激进的技术从`dev`分支fork出一个新的`x/*`分支各种尝试、考量、评估后或丢弃、或引入到paopao-ce。|
| `t/*` | 临时分支 |`t/*`是临时发版本分支,一般 `beta` 分支演进到正式版本发布前的最后某个beta版本比如v0.2.0-beta)就从beta分支fork出一个 `t/*` 分支用于向 `main` 分支提交 PR 用于Review待 PR Reviewed 合并到 `main` 分支后,可以删除这个临时创建的分支。这样设计主要是考虑到有时合并到 `main` 分支时需要Review的时间可能会长一些而dev分支的代码又急需推进到beta分支以发布下一个alpha版本用于内测相当于为下一个测试版本发布腾地方。|
| `r/*` |发行版本分支|`r/*`是不同发行版本分支,不同发行版本各有不同的侧重点,可以根据需要选择适合的发行版本。|
**发行版本分支说明**
| 名称 | 说明 | 维护者 | 备注 |
| ----- | ----- | ----- | ----- |
|[`paopao-ce`](https://github.com/rocboss/paopao-ce/tree/dev)|paopao-ce 主发行版本|[ROC](https://github.com/rocboss 'ROC')|该分支 [数据逻辑层](https://github.com/rocboss/paopao-ce/tree/dev/internal/dao/jinzhu) 使用[gorm](https://github.com/go-gorm/gorm)作为数据逻辑层的ORM框架适配MySQL/PostgreSQL/Sqlite3数据库。|
|[`r/paopao-ce`](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce)|paopao-ce 主分支预览版本|[ROC](https://github.com/rocboss 'ROC')<br/>[北野](https://github.com/alimy 'Michael Li')|该分支 [数据逻辑层](https://github.com/rocboss/paopao-ce/tree/dev/internal/dao/jinzhu) 使用[gorm](https://github.com/go-gorm/gorm)作为数据逻辑层的ORM框架适配MySQL/PostgreSQL/Sqlite3数据库。代码较`main`分支新,是主发行版本的前瞻预览版本。|
|[`r/paopao-ce-plus`](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-plus)|paopao-ce-plus 发行版本|[北野](https://github.com/alimy 'Michael Li')|该分支 [数据逻辑层](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-plus/internal/dao/sakila) 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据逻辑层的ORM框架专注于为MySQL/PostgreSQL/Sqlite3使用更优化的查询语句以提升数据检索效率。建议熟悉[sqlx](https://github.com/jmoiron/sqlx)的开发人员可以基于此版本来做 二次开发。|
|[`r/paopao-ce-pro`](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-pro)|paopao-ce-pro 发行版本|[北野](https://github.com/alimy 'Michael Li')|该分支 [数据逻辑层](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-pro/internal/dao/slonik) 使用[sqlc](https://github.com/kyleconroy/sqlc)作为sql语句生成器自动生成ORM代码专门针对特定数据库MySQL/PostgreSQL进行查询优化熟悉[sqlc](https://github.com/kyleconroy/sqlc)的开发人员可以基于此版本来做 二次开发。(另:分支目前只使用[pgx-v5](https://github.com/jackc/pgx)适配了PostgreSQL数据库后续或许会适配MySQL/TiDB数据库。)|
|[`r/paopao-ce-xtra`](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-xtra)|paopao-ce-xtra 发行版本|[北野](https://github.com/alimy 'Michael Li')|该分支 是r/paopao-ce、r/paopao-ce-plus、r/paopao-ce-pro的合集|
|[`r/paopao-ce-mini`](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-mini)|paopao-ce-mini 发行版本|[北野](https://github.com/alimy 'Michael Li')|该分支是paopao-ce最小可用版本专注于个人部署、一键傻瓜式最简部署|
**代码分支演进图**
![](docs/proposal/.assets/000-01.png)
### 部署站点信息
* [官方 paopao.info](https://www.paopao.info)
> 具体部署站点信息请查阅 [deployed-sites](./deployed-sites.md 'deployed sites'). 欢迎站长将已部署PaoPao实例的站点信息添加到 [deployed-sites](./deployed-sites.md 'deployed sites') 列表中。
#### Collaborator's paopao account
| 昵称 | [@GitHub](https://github.com 'github.com') | [@PaoPao](https://www.paopao.info 'paopao.info') |
| ----- | ----- | ----- |
| ROC | [ROC](https://github.com/rocboss 'ROC')|[ROC](https://www.paopao.info/#/user?username=roc 'ROC @roc')|
| [北野](https://alimy.me '糊涂小栈') | [Michael Li](https://github.com/alimy 'Michael Li') | [alimy](https://www.paopao.info/#/user?username=alimy '北野 @alimy')|
| orzi!| [orzi!](https://github.com/orziz 'orzi!')||
### 其他说明
建议后端服务使用 `supervisor` 守护进程,并通过 `nginx` 反向代理后提供API给前端服务调用。

@ -1,18 +1,35 @@
## Roadmap for paopao-ce
paopao-ce roadmap.
[paopao-ce](https://github.com/rocboss/paopao-ce/tree/dev)/[paopao-ce-plus](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-plus)/[paopao-ce-pro](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-pro) features develop or optimize and bug fix roadmap.
### v0.2.0
## paopao-ce roadmap
#### dev+
* [ ] add `Followship` feature
* [ ] add `Auth:Bcrypt` feature
* [ ] add `Auth:MD5` feature (just for compatible)
* [x] add extend base ORM code for implement data logic base sqlx/sqlc
* [ ] optimize media tweet submit logic
* [ ] optimize search logic service
#### v0.3.0
* [x] remove `Deprecated:OldWeb` feature
* [x] add user topic follow feature support
* [x] add tweet link share support
* [ ] add comment thumbsUp/thumbsDown support
* [x] add `RedisCacheIndex` feature
* [x] add `Sentry` feature
#### v0.2.0
* [x] add `Friendship` feature
* [ ] add `Lightship` feature
* [ ] add `Sqlx` feature
* [x] add `Lightship` feature
* [ ] add extend base ORM code for implement data logic base sqlx/sqlc
* [x] add `Pyroscope` feature
* [x] add new `Web` service
* [x] add `Frontend:Web` feature
* [x] add `Deprecated:OldWeb` feature
* [x] support run multiple service in single paopao-ce instance
* [x] use [go-mir](https://github.com/alimy/mir) optimize paopao-ce source code architecture
### Next
* [ ] add `Followship` feature
#### Next
* [ ] add `Bleve` feature
* [ ] add `SpaceX` feature
* [ ] add `Bot` feature
@ -24,8 +41,30 @@ paopao-ce roadmap.
* [ ] add tweet resource access control base on simple RBAC support
* [ ] add user's `Activation Code` feature support
* [ ] add user block feature support
* [ ] optimize current message push logic service use `ims` module
* [ ] optimize media tweet submit logic
* [ ] add i18n support
* [ ] add reactions support
* [ ] add tweet thread like twitter support
* [ ] add short link support
* [ ] optimize topics service
* [ ] optimize current message push logic service use `ims` module
* [ ] optimize backend data logic service(optimize database CRUD operate)
* [ ] optimize search logic service
## paopao-ce-plus roadmap
#### paopao-ce-plus/v0.4.0
* [ ] adapt for paopao-ce v0.4.0
#### paopao-ce-plus/v0.3.0
* [ ] adapt for paopao-ce v0.3.0
#### paopao-ce-plus/v0.2.0
* [ ] adapt for paopao-ce v0.2.0
## paopao-ce-pro roadmap
#### paopao-ce-pro/v0.4.0
* [ ] adapt for paopao-ce v0.4.0
#### paopao-ce-pro/v0.3.0
* [ ] adapt for paopao-ce v0.3.0
#### paopao-ce-pro/v0.2.0
* [ ] adapt for paopao-ce v0.2.0

@ -1,14 +1,29 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
)
type _binding_ interface {
Bind(*gin.Context) mir.Error
}
type _render_ interface {
Render(*gin.Context)
}
type _default_ interface {
Bind(*gin.Context, any) mir.Error
Render(*gin.Context, any, mir.Error)
}
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
@ -35,6 +50,8 @@ type UserInfo struct {
}
type User interface {
_default_
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
@ -44,21 +61,8 @@ type User interface {
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) {
func RegisterUserServant(e *gin.Engine, s User) {
router := e.Group("m/v1")
// use chain for router
middlewares := s.Chain()
@ -72,30 +76,26 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
default:
}
r.RenderLogout(c, s.Logout())
s.Render(c, nil, 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)
req := new(LoginReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
s.Render(c, resp, err)
})
}
// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}
type UnimplementedUserServant struct{}
func (UnimplementedUserServant) Chain() gin.HandlersChain {
return nil
@ -110,31 +110,3 @@ func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) {
}
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() {}

@ -1,14 +1,29 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
)
type _binding_ interface {
Bind(*gin.Context) mir.Error
}
type _render_ interface {
Render(*gin.Context)
}
type _default_ interface {
Bind(*gin.Context, any) mir.Error
Render(*gin.Context, any, mir.Error)
}
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
@ -35,6 +50,8 @@ type UserInfo struct {
}
type User interface {
_default_
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
@ -44,21 +61,8 @@ type User interface {
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) {
func RegisterUserServant(e *gin.Engine, s User) {
router := e.Group("r/v1")
// use chain for router
middlewares := s.Chain()
@ -72,30 +76,26 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
default:
}
r.RenderLogout(c, s.Logout())
s.Render(c, nil, 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)
req := new(LoginReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
s.Render(c, resp, err)
})
}
// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}
type UnimplementedUserServant struct{}
func (UnimplementedUserServant) Chain() gin.HandlersChain {
return nil
@ -110,31 +110,3 @@ func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) {
}
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() {}

@ -1,14 +1,29 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
)
type _binding_ interface {
Bind(*gin.Context) mir.Error
}
type _render_ interface {
Render(*gin.Context)
}
type _default_ interface {
Bind(*gin.Context, any) mir.Error
Render(*gin.Context, any, mir.Error)
}
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
@ -35,6 +50,8 @@ type UserInfo struct {
}
type User interface {
_default_
Logout() mir.Error
Login(*LoginReq) (*LoginResp, mir.Error)
Index() mir.Error
@ -42,22 +59,8 @@ type User interface {
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) {
func RegisterUserServant(e *gin.Engine, s User) {
router := e.Group("s/v1")
// register routes info to router
@ -68,25 +71,22 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
default:
}
r.RenderLogout(c, s.Logout())
s.Render(c, nil, 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)
req := new(LoginReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/index/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
@ -94,14 +94,12 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
default:
}
r.RenderIndex(c, s.Index())
s.Render(c, nil, s.Index())
})
}
// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}
type UnimplementedUserServant struct{}
func (UnimplementedUserServant) Logout() mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
@ -116,35 +114,3 @@ func (UnimplementedUserServant) Index() mir.Error {
}
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() {}

@ -1,38 +1,43 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Admin interface {
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
type _binding_ interface {
Bind(*gin.Context) mir.Error
}
ChangeUserStatus(*web.ChangeUserStatusReq) mir.Error
type _render_ interface {
Render(*gin.Context)
}
mustEmbedUnimplementedAdminServant()
type _default_ interface {
Bind(*gin.Context, any) mir.Error
Render(*gin.Context, any, mir.Error)
}
type AdminBinding interface {
BindChangeUserStatus(*gin.Context) (*web.ChangeUserStatusReq, mir.Error)
type Admin interface {
_default_
mustEmbedUnimplementedAdminBinding()
}
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
type AdminRender interface {
RenderChangeUserStatus(*gin.Context, mir.Error)
ChangeUserStatus(*web.ChangeUserStatusReq) mir.Error
mustEmbedUnimplementedAdminRender()
mustEmbedUnimplementedAdminServant()
}
// RegisterAdminServant register Admin servant to gin
func RegisterAdminServant(e *gin.Engine, s Admin, b AdminBinding, r AdminRender) {
func RegisterAdminServant(e *gin.Engine, s Admin) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
@ -45,20 +50,17 @@ func RegisterAdminServant(e *gin.Engine, s Admin, b AdminBinding, r AdminRender)
return
default:
}
req, err := b.BindChangeUserStatus(c)
if err != nil {
r.RenderChangeUserStatus(c, err)
req := new(web.ChangeUserStatusReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderChangeUserStatus(c, s.ChangeUserStatus(req))
s.Render(c, nil, s.ChangeUserStatus(req))
})
}
// UnimplementedAdminServant can be embedded to have forward compatible implementations.
type UnimplementedAdminServant struct {
}
type UnimplementedAdminServant struct{}
func (UnimplementedAdminServant) Chain() gin.HandlersChain {
return nil
@ -69,27 +71,3 @@ func (UnimplementedAdminServant) ChangeUserStatus(req *web.ChangeUserStatusReq)
}
func (UnimplementedAdminServant) mustEmbedUnimplementedAdminServant() {}
// UnimplementedAdminRender can be embedded to have forward compatible implementations.
type UnimplementedAdminRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedAdminRender) RenderChangeUserStatus(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedAdminRender) mustEmbedUnimplementedAdminRender() {}
// UnimplementedAdminBinding can be embedded to have forward compatible implementations.
type UnimplementedAdminBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedAdminBinding) BindChangeUserStatus(c *gin.Context) (*web.ChangeUserStatusReq, mir.Error) {
obj := new(web.ChangeUserStatusReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedAdminBinding) mustEmbedUnimplementedAdminBinding() {}

@ -1,16 +1,20 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type AlipayPriv interface {
_default_
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
@ -21,24 +25,8 @@ type AlipayPriv interface {
mustEmbedUnimplementedAlipayPrivServant()
}
type AlipayPrivBinding interface {
BindUserWalletBills(*gin.Context) (*web.UserWalletBillsReq, mir.Error)
BindUserRechargeResult(*gin.Context) (*web.UserRechargeResultReq, mir.Error)
BindUserRechargeLink(*gin.Context) (*web.UserRechargeLinkReq, mir.Error)
mustEmbedUnimplementedAlipayPrivBinding()
}
type AlipayPrivRender interface {
RenderUserWalletBills(*gin.Context, *web.UserWalletBillsResp, mir.Error)
RenderUserRechargeResult(*gin.Context, *web.UserRechargeResultResp, mir.Error)
RenderUserRechargeLink(*gin.Context, *web.UserRechargeLinkResp, mir.Error)
mustEmbedUnimplementedAlipayPrivRender()
}
// RegisterAlipayPrivServant register AlipayPriv servant to gin
func RegisterAlipayPrivServant(e *gin.Engine, s AlipayPriv, b AlipayPrivBinding, r AlipayPrivRender) {
func RegisterAlipayPrivServant(e *gin.Engine, s AlipayPriv) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
@ -51,53 +39,49 @@ func RegisterAlipayPrivServant(e *gin.Engine, s AlipayPriv, b AlipayPrivBinding,
return
default:
}
req, err := b.BindUserWalletBills(c)
if err != nil {
r.RenderUserWalletBills(c, nil, err)
req := new(web.UserWalletBillsReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.UserWalletBills(req)
r.RenderUserWalletBills(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/user/recharge", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindUserRechargeResult(c)
if err != nil {
r.RenderUserRechargeResult(c, nil, err)
req := new(web.UserRechargeResultReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.UserRechargeResult(req)
r.RenderUserRechargeResult(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/user/recharge", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindUserRechargeLink(c)
if err != nil {
r.RenderUserRechargeLink(c, nil, err)
req := new(web.UserRechargeLinkReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.UserRechargeLink(req)
r.RenderUserRechargeLink(c, resp, err)
s.Render(c, resp, err)
})
}
// UnimplementedAlipayPrivServant can be embedded to have forward compatible implementations.
type UnimplementedAlipayPrivServant struct {
}
type UnimplementedAlipayPrivServant struct{}
func (UnimplementedAlipayPrivServant) Chain() gin.HandlersChain {
return nil
@ -116,47 +100,3 @@ func (UnimplementedAlipayPrivServant) UserRechargeLink(req *web.UserRechargeLink
}
func (UnimplementedAlipayPrivServant) mustEmbedUnimplementedAlipayPrivServant() {}
// UnimplementedAlipayPrivRender can be embedded to have forward compatible implementations.
type UnimplementedAlipayPrivRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedAlipayPrivRender) RenderUserWalletBills(c *gin.Context, data *web.UserWalletBillsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedAlipayPrivRender) RenderUserRechargeResult(c *gin.Context, data *web.UserRechargeResultResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedAlipayPrivRender) RenderUserRechargeLink(c *gin.Context, data *web.UserRechargeLinkResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedAlipayPrivRender) mustEmbedUnimplementedAlipayPrivRender() {}
// UnimplementedAlipayPrivBinding can be embedded to have forward compatible implementations.
type UnimplementedAlipayPrivBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedAlipayPrivBinding) BindUserWalletBills(c *gin.Context) (*web.UserWalletBillsReq, mir.Error) {
obj := new(web.UserWalletBillsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedAlipayPrivBinding) BindUserRechargeResult(c *gin.Context) (*web.UserRechargeResultReq, mir.Error) {
obj := new(web.UserRechargeResultReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedAlipayPrivBinding) BindUserRechargeLink(c *gin.Context) (*web.UserRechargeLinkReq, mir.Error) {
obj := new(web.UserRechargeLinkReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedAlipayPrivBinding) mustEmbedUnimplementedAlipayPrivBinding() {}

@ -1,35 +1,27 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type AlipayPub interface {
_default_
AlipayNotify(*web.AlipayNotifyReq) mir.Error
mustEmbedUnimplementedAlipayPubServant()
}
type AlipayPubBinding interface {
BindAlipayNotify(*gin.Context) (*web.AlipayNotifyReq, mir.Error)
mustEmbedUnimplementedAlipayPubBinding()
}
type AlipayPubRender interface {
RenderAlipayNotify(*gin.Context, mir.Error)
mustEmbedUnimplementedAlipayPubRender()
}
// RegisterAlipayPubServant register AlipayPub servant to gin
func RegisterAlipayPubServant(e *gin.Engine, s AlipayPub, b AlipayPubBinding, r AlipayPubRender) {
func RegisterAlipayPubServant(e *gin.Engine, s AlipayPub) {
router := e.Group("v1")
// register routes info to router
@ -39,47 +31,21 @@ func RegisterAlipayPubServant(e *gin.Engine, s AlipayPub, b AlipayPubBinding, r
return
default:
}
req, err := b.BindAlipayNotify(c)
if err != nil {
r.RenderAlipayNotify(c, err)
req := new(web.AlipayNotifyReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
r.RenderAlipayNotify(c, s.AlipayNotify(req))
s.Render(c, nil, s.AlipayNotify(req))
})
}
// UnimplementedAlipayPubServant can be embedded to have forward compatible implementations.
type UnimplementedAlipayPubServant struct {
}
type UnimplementedAlipayPubServant struct{}
func (UnimplementedAlipayPubServant) AlipayNotify(req *web.AlipayNotifyReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedAlipayPubServant) mustEmbedUnimplementedAlipayPubServant() {}
// UnimplementedAlipayPubRender can be embedded to have forward compatible implementations.
type UnimplementedAlipayPubRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedAlipayPubRender) RenderAlipayNotify(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedAlipayPubRender) mustEmbedUnimplementedAlipayPubRender() {}
// UnimplementedAlipayPubBinding can be embedded to have forward compatible implementations.
type UnimplementedAlipayPubBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedAlipayPubBinding) BindAlipayNotify(c *gin.Context) (*web.AlipayNotifyReq, mir.Error) {
obj := new(web.AlipayNotifyReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedAlipayPubBinding) mustEmbedUnimplementedAlipayPubBinding() {}

@ -1,16 +1,20 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Core interface {
_default_
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
@ -34,50 +38,8 @@ type Core interface {
mustEmbedUnimplementedCoreServant()
}
type CoreBinding interface {
BindTweetCollectionStatus(*gin.Context) (*web.TweetCollectionStatusReq, mir.Error)
BindTweetStarStatus(*gin.Context) (*web.TweetStarStatusReq, mir.Error)
BindSuggestTags(*gin.Context) (*web.SuggestTagsReq, mir.Error)
BindSuggestUsers(*gin.Context) (*web.SuggestUsersReq, mir.Error)
BindChangeAvatar(*gin.Context) (*web.ChangeAvatarReq, mir.Error)
BindChangeNickname(*gin.Context) (*web.ChangeNicknameReq, mir.Error)
BindChangePassword(*gin.Context) (*web.ChangePasswordReq, mir.Error)
BindUserPhoneBind(*gin.Context) (*web.UserPhoneBindReq, mir.Error)
BindGetStars(*gin.Context) (*web.GetStarsReq, mir.Error)
BindGetCollections(*gin.Context) (*web.GetCollectionsReq, mir.Error)
BindSendUserWhisper(*gin.Context) (*web.SendWhisperReq, mir.Error)
BindReadMessage(*gin.Context) (*web.ReadMessageReq, mir.Error)
BindGetMessages(*gin.Context) (*web.GetMessagesReq, mir.Error)
BindGetUnreadMsgCount(*gin.Context) (*web.GetUnreadMsgCountReq, mir.Error)
BindGetUserInfo(*gin.Context) (*web.UserInfoReq, mir.Error)
BindSyncSearchIndex(*gin.Context) (*web.SyncSearchIndexReq, mir.Error)
mustEmbedUnimplementedCoreBinding()
}
type CoreRender interface {
RenderTweetCollectionStatus(*gin.Context, *web.TweetCollectionStatusResp, mir.Error)
RenderTweetStarStatus(*gin.Context, *web.TweetStarStatusResp, mir.Error)
RenderSuggestTags(*gin.Context, *web.SuggestTagsResp, mir.Error)
RenderSuggestUsers(*gin.Context, *web.SuggestUsersResp, mir.Error)
RenderChangeAvatar(*gin.Context, mir.Error)
RenderChangeNickname(*gin.Context, mir.Error)
RenderChangePassword(*gin.Context, mir.Error)
RenderUserPhoneBind(*gin.Context, mir.Error)
RenderGetStars(*gin.Context, *web.GetStarsResp, mir.Error)
RenderGetCollections(*gin.Context, *web.GetCollectionsResp, mir.Error)
RenderSendUserWhisper(*gin.Context, mir.Error)
RenderReadMessage(*gin.Context, mir.Error)
RenderGetMessages(*gin.Context, *web.GetMessagesResp, mir.Error)
RenderGetUnreadMsgCount(*gin.Context, *web.GetUnreadMsgCountResp, mir.Error)
RenderGetUserInfo(*gin.Context, *web.UserInfoResp, mir.Error)
RenderSyncSearchIndex(*gin.Context, mir.Error)
mustEmbedUnimplementedCoreRender()
}
// RegisterCoreServant register Core servant to gin
func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) {
func RegisterCoreServant(e *gin.Engine, s Core) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
@ -90,254 +52,229 @@ func RegisterCoreServant(e *gin.Engine, s Core, b CoreBinding, r CoreRender) {
return
default:
}
req, err := b.BindTweetCollectionStatus(c)
if err != nil {
r.RenderTweetCollectionStatus(c, nil, err)
req := new(web.TweetCollectionStatusReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.TweetCollectionStatus(req)
r.RenderTweetCollectionStatus(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/post/star", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindTweetStarStatus(c)
if err != nil {
r.RenderTweetStarStatus(c, nil, err)
req := new(web.TweetStarStatusReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.TweetStarStatus(req)
r.RenderTweetStarStatus(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/suggest/tags", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindSuggestTags(c)
if err != nil {
r.RenderSuggestTags(c, nil, err)
req := new(web.SuggestTagsReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.SuggestTags(req)
r.RenderSuggestTags(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/suggest/users", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindSuggestUsers(c)
if err != nil {
r.RenderSuggestUsers(c, nil, err)
req := new(web.SuggestUsersReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.SuggestUsers(req)
r.RenderSuggestUsers(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/user/avatar", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindChangeAvatar(c)
if err != nil {
r.RenderChangeAvatar(c, err)
req := new(web.ChangeAvatarReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderChangeAvatar(c, s.ChangeAvatar(req))
s.Render(c, nil, s.ChangeAvatar(req))
})
router.Handle("POST", "/user/nickname", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindChangeNickname(c)
if err != nil {
r.RenderChangeNickname(c, err)
req := new(web.ChangeNicknameReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderChangeNickname(c, s.ChangeNickname(req))
s.Render(c, nil, s.ChangeNickname(req))
})
router.Handle("POST", "/user/password", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindChangePassword(c)
if err != nil {
r.RenderChangePassword(c, err)
req := new(web.ChangePasswordReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderChangePassword(c, s.ChangePassword(req))
s.Render(c, nil, s.ChangePassword(req))
})
router.Handle("POST", "/user/phone", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindUserPhoneBind(c)
if err != nil {
r.RenderUserPhoneBind(c, err)
req := new(web.UserPhoneBindReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderUserPhoneBind(c, s.UserPhoneBind(req))
s.Render(c, nil, s.UserPhoneBind(req))
})
router.Handle("GET", "/user/stars", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetStars(c)
if err != nil {
r.RenderGetStars(c, nil, err)
req := new(web.GetStarsReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.GetStars(req)
r.RenderGetStars(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/user/collections", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetCollections(c)
if err != nil {
r.RenderGetCollections(c, nil, err)
req := new(web.GetCollectionsReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.GetCollections(req)
r.RenderGetCollections(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/user/whisper", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindSendUserWhisper(c)
if err != nil {
r.RenderSendUserWhisper(c, err)
req := new(web.SendWhisperReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderSendUserWhisper(c, s.SendUserWhisper(req))
s.Render(c, nil, s.SendUserWhisper(req))
})
router.Handle("POST", "/user/message/read", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindReadMessage(c)
if err != nil {
r.RenderReadMessage(c, err)
req := new(web.ReadMessageReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderReadMessage(c, s.ReadMessage(req))
s.Render(c, nil, s.ReadMessage(req))
})
router.Handle("GET", "/user/messages", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetMessages(c)
if err != nil {
r.RenderGetMessages(c, nil, err)
req := new(web.GetMessagesReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.GetMessages(req)
r.RenderGetMessages(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/user/msgcount/unread", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetUnreadMsgCount(c)
if err != nil {
r.RenderGetUnreadMsgCount(c, nil, err)
req := new(web.GetUnreadMsgCountReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.GetUnreadMsgCount(req)
r.RenderGetUnreadMsgCount(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/user/info", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetUserInfo(c)
if err != nil {
r.RenderGetUserInfo(c, nil, err)
req := new(web.UserInfoReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.GetUserInfo(req)
r.RenderGetUserInfo(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/sync/index", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindSyncSearchIndex(c)
if err != nil {
r.RenderSyncSearchIndex(c, err)
req := new(web.SyncSearchIndexReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderSyncSearchIndex(c, s.SyncSearchIndex(req))
s.Render(c, nil, s.SyncSearchIndex(req))
})
}
// UnimplementedCoreServant can be embedded to have forward compatible implementations.
type UnimplementedCoreServant struct {
}
type UnimplementedCoreServant struct{}
func (UnimplementedCoreServant) Chain() gin.HandlersChain {
return nil
@ -408,177 +345,3 @@ func (UnimplementedCoreServant) SyncSearchIndex(req *web.SyncSearchIndexReq) mir
}
func (UnimplementedCoreServant) mustEmbedUnimplementedCoreServant() {}
// UnimplementedCoreRender can be embedded to have forward compatible implementations.
type UnimplementedCoreRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedCoreRender) RenderTweetCollectionStatus(c *gin.Context, data *web.TweetCollectionStatusResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderTweetStarStatus(c *gin.Context, data *web.TweetStarStatusResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderSuggestTags(c *gin.Context, data *web.SuggestTagsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderSuggestUsers(c *gin.Context, data *web.SuggestUsersResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderChangeAvatar(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) RenderChangeNickname(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) RenderChangePassword(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) RenderUserPhoneBind(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) RenderGetStars(c *gin.Context, data *web.GetStarsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderGetCollections(c *gin.Context, data *web.GetCollectionsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderSendUserWhisper(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) RenderReadMessage(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) RenderGetMessages(c *gin.Context, data *web.GetMessagesResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderGetUnreadMsgCount(c *gin.Context, data *web.GetUnreadMsgCountResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderGetUserInfo(c *gin.Context, data *web.UserInfoResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedCoreRender) RenderSyncSearchIndex(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedCoreRender) mustEmbedUnimplementedCoreRender() {}
// UnimplementedCoreBinding can be embedded to have forward compatible implementations.
type UnimplementedCoreBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedCoreBinding) BindTweetCollectionStatus(c *gin.Context) (*web.TweetCollectionStatusReq, mir.Error) {
obj := new(web.TweetCollectionStatusReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindTweetStarStatus(c *gin.Context) (*web.TweetStarStatusReq, mir.Error) {
obj := new(web.TweetStarStatusReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindSuggestTags(c *gin.Context) (*web.SuggestTagsReq, mir.Error) {
obj := new(web.SuggestTagsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindSuggestUsers(c *gin.Context) (*web.SuggestUsersReq, mir.Error) {
obj := new(web.SuggestUsersReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindChangeAvatar(c *gin.Context) (*web.ChangeAvatarReq, mir.Error) {
obj := new(web.ChangeAvatarReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindChangeNickname(c *gin.Context) (*web.ChangeNicknameReq, mir.Error) {
obj := new(web.ChangeNicknameReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindChangePassword(c *gin.Context) (*web.ChangePasswordReq, mir.Error) {
obj := new(web.ChangePasswordReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindUserPhoneBind(c *gin.Context) (*web.UserPhoneBindReq, mir.Error) {
obj := new(web.UserPhoneBindReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindGetStars(c *gin.Context) (*web.GetStarsReq, mir.Error) {
obj := new(web.GetStarsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindGetCollections(c *gin.Context) (*web.GetCollectionsReq, mir.Error) {
obj := new(web.GetCollectionsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindSendUserWhisper(c *gin.Context) (*web.SendWhisperReq, mir.Error) {
obj := new(web.SendWhisperReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindReadMessage(c *gin.Context) (*web.ReadMessageReq, mir.Error) {
obj := new(web.ReadMessageReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindGetMessages(c *gin.Context) (*web.GetMessagesReq, mir.Error) {
obj := new(web.GetMessagesReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindGetUnreadMsgCount(c *gin.Context) (*web.GetUnreadMsgCountReq, mir.Error) {
obj := new(web.GetUnreadMsgCountReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindGetUserInfo(c *gin.Context) (*web.UserInfoReq, mir.Error) {
obj := new(web.UserInfoReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) BindSyncSearchIndex(c *gin.Context) (*web.SyncSearchIndexReq, mir.Error) {
obj := new(web.SyncSearchIndexReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedCoreBinding) mustEmbedUnimplementedCoreBinding() {}

@ -1,16 +1,20 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Followship interface {
_default_
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
@ -22,26 +26,8 @@ type Followship interface {
mustEmbedUnimplementedFollowshipServant()
}
type FollowshipBinding interface {
BindListFollowers(*gin.Context) (*web.ListFollowersReq, mir.Error)
BindListFollowings(*gin.Context) (*web.ListFollowingsReq, mir.Error)
BindDeleteFollowing(*gin.Context) (*web.DeleteFollowingReq, mir.Error)
BindAddFollowing(*gin.Context) (*web.AddFollowingReq, mir.Error)
mustEmbedUnimplementedFollowshipBinding()
}
type FollowshipRender interface {
RenderListFollowers(*gin.Context, *web.ListFollowersResp, mir.Error)
RenderListFollowings(*gin.Context, *web.ListFollowingsResp, mir.Error)
RenderDeleteFollowing(*gin.Context, mir.Error)
RenderAddFollowing(*gin.Context, mir.Error)
mustEmbedUnimplementedFollowshipRender()
}
// RegisterFollowshipServant register Followship servant to gin
func RegisterFollowshipServant(e *gin.Engine, s Followship, b FollowshipBinding, r FollowshipRender) {
func RegisterFollowshipServant(e *gin.Engine, s Followship) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
@ -54,67 +40,58 @@ func RegisterFollowshipServant(e *gin.Engine, s Followship, b FollowshipBinding,
return
default:
}
req, err := b.BindListFollowers(c)
if err != nil {
r.RenderListFollowers(c, nil, err)
req := new(web.ListFollowersReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.ListFollowers(req)
r.RenderListFollowers(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/following/list", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindListFollowings(c)
if err != nil {
r.RenderListFollowings(c, nil, err)
req := new(web.ListFollowingsReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.ListFollowings(req)
r.RenderListFollowings(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/following/delete", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDeleteFollowing(c)
if err != nil {
r.RenderDeleteFollowing(c, err)
req := new(web.DeleteFollowingReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderDeleteFollowing(c, s.DeleteFollowing(req))
s.Render(c, nil, s.DeleteFollowing(req))
})
router.Handle("POST", "/following/add", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindAddFollowing(c)
if err != nil {
r.RenderAddFollowing(c, err)
req := new(web.AddFollowingReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderAddFollowing(c, s.AddFollowing(req))
s.Render(c, nil, s.AddFollowing(req))
})
}
// UnimplementedFollowshipServant can be embedded to have forward compatible implementations.
type UnimplementedFollowshipServant struct {
}
type UnimplementedFollowshipServant struct{}
func (UnimplementedFollowshipServant) Chain() gin.HandlersChain {
return nil
@ -137,57 +114,3 @@ func (UnimplementedFollowshipServant) AddFollowing(req *web.AddFollowingReq) mir
}
func (UnimplementedFollowshipServant) mustEmbedUnimplementedFollowshipServant() {}
// UnimplementedFollowshipRender can be embedded to have forward compatible implementations.
type UnimplementedFollowshipRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedFollowshipRender) RenderListFollowers(c *gin.Context, data *web.ListFollowersResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedFollowshipRender) RenderListFollowings(c *gin.Context, data *web.ListFollowingsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedFollowshipRender) RenderDeleteFollowing(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedFollowshipRender) RenderAddFollowing(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedFollowshipRender) mustEmbedUnimplementedFollowshipRender() {}
// UnimplementedFollowshipBinding can be embedded to have forward compatible implementations.
type UnimplementedFollowshipBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedFollowshipBinding) BindListFollowers(c *gin.Context) (*web.ListFollowersReq, mir.Error) {
obj := new(web.ListFollowersReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFollowshipBinding) BindListFollowings(c *gin.Context) (*web.ListFollowingsReq, mir.Error) {
obj := new(web.ListFollowingsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFollowshipBinding) BindDeleteFollowing(c *gin.Context) (*web.DeleteFollowingReq, mir.Error) {
obj := new(web.DeleteFollowingReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFollowshipBinding) BindAddFollowing(c *gin.Context) (*web.AddFollowingReq, mir.Error) {
obj := new(web.AddFollowingReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFollowshipBinding) mustEmbedUnimplementedFollowshipBinding() {}

@ -1,16 +1,20 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Friendship interface {
_default_
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
@ -23,28 +27,8 @@ type Friendship interface {
mustEmbedUnimplementedFriendshipServant()
}
type FriendshipBinding interface {
BindGetContacts(*gin.Context) (*web.GetContactsReq, mir.Error)
BindDeleteFriend(*gin.Context) (*web.DeleteFriendReq, mir.Error)
BindRejectFriend(*gin.Context) (*web.RejectFriendReq, mir.Error)
BindAddFriend(*gin.Context) (*web.AddFriendReq, mir.Error)
BindRequestingFriend(*gin.Context) (*web.RequestingFriendReq, mir.Error)
mustEmbedUnimplementedFriendshipBinding()
}
type FriendshipRender interface {
RenderGetContacts(*gin.Context, *web.GetContactsResp, mir.Error)
RenderDeleteFriend(*gin.Context, mir.Error)
RenderRejectFriend(*gin.Context, mir.Error)
RenderAddFriend(*gin.Context, mir.Error)
RenderRequestingFriend(*gin.Context, mir.Error)
mustEmbedUnimplementedFriendshipRender()
}
// RegisterFriendshipServant register Friendship servant to gin
func RegisterFriendshipServant(e *gin.Engine, s Friendship, b FriendshipBinding, r FriendshipRender) {
func RegisterFriendshipServant(e *gin.Engine, s Friendship) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
@ -57,81 +41,70 @@ func RegisterFriendshipServant(e *gin.Engine, s Friendship, b FriendshipBinding,
return
default:
}
req, err := b.BindGetContacts(c)
if err != nil {
r.RenderGetContacts(c, nil, err)
req := new(web.GetContactsReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.GetContacts(req)
r.RenderGetContacts(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/friend/delete", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDeleteFriend(c)
if err != nil {
r.RenderDeleteFriend(c, err)
req := new(web.DeleteFriendReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderDeleteFriend(c, s.DeleteFriend(req))
s.Render(c, nil, s.DeleteFriend(req))
})
router.Handle("POST", "/friend/reject", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindRejectFriend(c)
if err != nil {
r.RenderRejectFriend(c, err)
req := new(web.RejectFriendReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderRejectFriend(c, s.RejectFriend(req))
s.Render(c, nil, s.RejectFriend(req))
})
router.Handle("POST", "/friend/add", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindAddFriend(c)
if err != nil {
r.RenderAddFriend(c, err)
req := new(web.AddFriendReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderAddFriend(c, s.AddFriend(req))
s.Render(c, nil, s.AddFriend(req))
})
router.Handle("POST", "/friend/requesting", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindRequestingFriend(c)
if err != nil {
r.RenderRequestingFriend(c, err)
req := new(web.RequestingFriendReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderRequestingFriend(c, s.RequestingFriend(req))
s.Render(c, nil, s.RequestingFriend(req))
})
}
// UnimplementedFriendshipServant can be embedded to have forward compatible implementations.
type UnimplementedFriendshipServant struct {
}
type UnimplementedFriendshipServant struct{}
func (UnimplementedFriendshipServant) Chain() gin.HandlersChain {
return nil
@ -158,67 +131,3 @@ func (UnimplementedFriendshipServant) RequestingFriend(req *web.RequestingFriend
}
func (UnimplementedFriendshipServant) mustEmbedUnimplementedFriendshipServant() {}
// UnimplementedFriendshipRender can be embedded to have forward compatible implementations.
type UnimplementedFriendshipRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedFriendshipRender) RenderGetContacts(c *gin.Context, data *web.GetContactsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedFriendshipRender) RenderDeleteFriend(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedFriendshipRender) RenderRejectFriend(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedFriendshipRender) RenderAddFriend(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedFriendshipRender) RenderRequestingFriend(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedFriendshipRender) mustEmbedUnimplementedFriendshipRender() {}
// UnimplementedFriendshipBinding can be embedded to have forward compatible implementations.
type UnimplementedFriendshipBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedFriendshipBinding) BindGetContacts(c *gin.Context) (*web.GetContactsReq, mir.Error) {
obj := new(web.GetContactsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFriendshipBinding) BindDeleteFriend(c *gin.Context) (*web.DeleteFriendReq, mir.Error) {
obj := new(web.DeleteFriendReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFriendshipBinding) BindRejectFriend(c *gin.Context) (*web.RejectFriendReq, mir.Error) {
obj := new(web.RejectFriendReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFriendshipBinding) BindAddFriend(c *gin.Context) (*web.AddFriendReq, mir.Error) {
obj := new(web.AddFriendReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFriendshipBinding) BindRequestingFriend(c *gin.Context) (*web.RequestingFriendReq, mir.Error) {
obj := new(web.RequestingFriendReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedFriendshipBinding) mustEmbedUnimplementedFriendshipBinding() {}

@ -1,19 +1,25 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Loose interface {
_default_
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
TweetComments(*web.TweetCommentsReq) (*web.TweetCommentsResp, mir.Error)
TopicList(*web.TopicListReq) (*web.TopicListResp, mir.Error)
GetUserProfile(*web.GetUserProfileReq) (*web.GetUserProfileResp, mir.Error)
GetUserTweets(*web.GetUserTweetsReq) (*web.GetUserTweetsResp, mir.Error)
Timeline(*web.TimelineReq) (*web.TimelineResp, mir.Error)
@ -21,142 +27,112 @@ type Loose interface {
mustEmbedUnimplementedLooseServant()
}
type LooseBinding interface {
BindGetUserProfile(*gin.Context) (*web.GetUserProfileReq, mir.Error)
BindGetUserTweets(*gin.Context) (*web.GetUserTweetsReq, mir.Error)
BindTimeline(*gin.Context) (*web.TimelineReq, mir.Error)
mustEmbedUnimplementedLooseBinding()
}
type LooseRender interface {
RenderGetUserProfile(*gin.Context, *web.GetUserProfileResp, mir.Error)
RenderGetUserTweets(*gin.Context, *web.GetUserTweetsResp, mir.Error)
RenderTimeline(*gin.Context, *web.TimelineResp, mir.Error)
mustEmbedUnimplementedLooseRender()
}
// RegisterLooseServant register Loose servant to gin
func RegisterLooseServant(e *gin.Engine, s Loose, b LooseBinding, r LooseRender) {
func RegisterLooseServant(e *gin.Engine, s Loose) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("GET", "/post/comments", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(web.TweetCommentsReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.TweetComments(req)
s.Render(c, resp, err)
})
router.Handle("GET", "/tags", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(web.TopicListReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.TopicList(req)
s.Render(c, resp, err)
})
router.Handle("GET", "/user/profile", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetUserProfile(c)
if err != nil {
r.RenderGetUserProfile(c, nil, err)
req := new(web.GetUserProfileReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.GetUserProfile(req)
r.RenderGetUserProfile(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/user/posts", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindGetUserTweets(c)
if err != nil {
r.RenderGetUserTweets(c, nil, err)
req := new(web.GetUserTweetsReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.GetUserTweets(req)
r.RenderGetUserTweets(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/posts", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindTimeline(c)
if err != nil {
r.RenderTimeline(c, nil, err)
req := new(web.TimelineReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.Timeline(req)
r.RenderTimeline(c, resp, err)
s.Render(c, resp, err)
})
}
// UnimplementedLooseServant can be embedded to have forward compatible implementations.
type UnimplementedLooseServant struct {
}
type UnimplementedLooseServant struct{}
func (UnimplementedLooseServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedLooseServant) GetUserProfile(req *web.GetUserProfileReq) (*web.GetUserProfileResp, mir.Error) {
func (UnimplementedLooseServant) TweetComments(req *web.TweetCommentsReq) (*web.TweetCommentsResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedLooseServant) GetUserTweets(req *web.GetUserTweetsReq) (*web.GetUserTweetsResp, mir.Error) {
func (UnimplementedLooseServant) TopicList(req *web.TopicListReq) (*web.TopicListResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedLooseServant) Timeline(req *web.TimelineReq) (*web.TimelineResp, mir.Error) {
func (UnimplementedLooseServant) GetUserProfile(req *web.GetUserProfileReq) (*web.GetUserProfileResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedLooseServant) mustEmbedUnimplementedLooseServant() {}
// UnimplementedLooseRender can be embedded to have forward compatible implementations.
type UnimplementedLooseRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedLooseRender) RenderGetUserProfile(c *gin.Context, data *web.GetUserProfileResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedLooseRender) RenderGetUserTweets(c *gin.Context, data *web.GetUserTweetsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedLooseRender) RenderTimeline(c *gin.Context, data *web.TimelineResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedLooseRender) mustEmbedUnimplementedLooseRender() {}
// UnimplementedLooseBinding can be embedded to have forward compatible implementations.
type UnimplementedLooseBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedLooseBinding) BindGetUserProfile(c *gin.Context) (*web.GetUserProfileReq, mir.Error) {
obj := new(web.GetUserProfileReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedLooseBinding) BindGetUserTweets(c *gin.Context) (*web.GetUserTweetsReq, mir.Error) {
obj := new(web.GetUserTweetsReq)
err := b.BindAny(c, obj)
return obj, err
func (UnimplementedLooseServant) GetUserTweets(req *web.GetUserTweetsReq) (*web.GetUserTweetsResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (b *UnimplementedLooseBinding) BindTimeline(c *gin.Context) (*web.TimelineReq, mir.Error) {
obj := new(web.TimelineReq)
err := b.BindAny(c, obj)
return obj, err
func (UnimplementedLooseServant) Timeline(req *web.TimelineReq) (*web.TimelineResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (b *UnimplementedLooseBinding) mustEmbedUnimplementedLooseBinding() {}
func (UnimplementedLooseServant) mustEmbedUnimplementedLooseServant() {}

@ -1,24 +1,36 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Priv interface {
_default_
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
UnfollowTopic(*web.UnfollowTopicReq) mir.Error
FollowTopic(*web.FollowTopicReq) mir.Error
StickTopic(*web.StickTopicReq) (*web.StickTopicResp, mir.Error)
ThumbsDownTweetReply(*web.TweetReplyThumbsReq) mir.Error
ThumbsUpTweetReply(*web.TweetReplyThumbsReq) mir.Error
ThumbsDownTweetComment(*web.TweetCommentThumbsReq) mir.Error
ThumbsUpTweetComment(*web.TweetCommentThumbsReq) mir.Error
DeleteCommentReply(*web.DeleteCommentReplyReq) mir.Error
CreateCommentReply(*web.CreateCommentReplyReq) (*web.CreateCommentReplyResp, mir.Error)
DeleteComment(*web.DeleteCommentReq) mir.Error
CreateComment(*web.CreateCommentReq) (*web.CreateCommentResp, mir.Error)
VisibleTweet(*web.VisibleTweetReq) (*web.VisibleTweetResp, mir.Error)
HighlightTweet(*web.HighlightTweetReq) (*web.HighlightTweetResp, mir.Error)
StickTweet(*web.StickTweetReq) (*web.StickTweetResp, mir.Error)
LockTweet(*web.LockTweetReq) (*web.LockTweetResp, mir.Error)
CollectionTweet(*web.CollectionTweetReq) (*web.CollectionTweetResp, mir.Error)
@ -32,283 +44,356 @@ type Priv interface {
mustEmbedUnimplementedPrivServant()
}
type PrivBinding interface {
BindDeleteCommentReply(*gin.Context) (*web.DeleteCommentReplyReq, mir.Error)
BindCreateCommentReply(*gin.Context) (*web.CreateCommentReplyReq, mir.Error)
BindDeleteComment(*gin.Context) (*web.DeleteCommentReq, mir.Error)
BindCreateComment(*gin.Context) (*web.CreateCommentReq, mir.Error)
BindVisibleTweet(*gin.Context) (*web.VisibleTweetReq, mir.Error)
BindStickTweet(*gin.Context) (*web.StickTweetReq, mir.Error)
BindLockTweet(*gin.Context) (*web.LockTweetReq, mir.Error)
BindCollectionTweet(*gin.Context) (*web.CollectionTweetReq, mir.Error)
BindStarTweet(*gin.Context) (*web.StarTweetReq, mir.Error)
BindDeleteTweet(*gin.Context) (*web.DeleteTweetReq, mir.Error)
BindCreateTweet(*gin.Context) (*web.CreateTweetReq, mir.Error)
BindDownloadAttachment(*gin.Context) (*web.DownloadAttachmentReq, mir.Error)
BindDownloadAttachmentPrecheck(*gin.Context) (*web.DownloadAttachmentPrecheckReq, mir.Error)
BindUploadAttachment(*gin.Context) (*web.UploadAttachmentReq, mir.Error)
mustEmbedUnimplementedPrivBinding()
}
type PrivRender interface {
RenderDeleteCommentReply(*gin.Context, mir.Error)
RenderCreateCommentReply(*gin.Context, *web.CreateCommentReplyResp, mir.Error)
RenderDeleteComment(*gin.Context, mir.Error)
RenderCreateComment(*gin.Context, *web.CreateCommentResp, mir.Error)
RenderVisibleTweet(*gin.Context, *web.VisibleTweetResp, mir.Error)
RenderStickTweet(*gin.Context, *web.StickTweetResp, mir.Error)
RenderLockTweet(*gin.Context, *web.LockTweetResp, mir.Error)
RenderCollectionTweet(*gin.Context, *web.CollectionTweetResp, mir.Error)
RenderStarTweet(*gin.Context, *web.StarTweetResp, mir.Error)
RenderDeleteTweet(*gin.Context, mir.Error)
RenderCreateTweet(*gin.Context, *web.CreateTweetResp, mir.Error)
RenderDownloadAttachment(*gin.Context, *web.DownloadAttachmentResp, mir.Error)
RenderDownloadAttachmentPrecheck(*gin.Context, *web.DownloadAttachmentPrecheckResp, mir.Error)
RenderUploadAttachment(*gin.Context, *web.UploadAttachmentResp, mir.Error)
mustEmbedUnimplementedPrivRender()
}
// RegisterPrivServant register Priv servant to gin
func RegisterPrivServant(e *gin.Engine, s Priv, b PrivBinding, r PrivRender) {
func RegisterPrivServant(e *gin.Engine, s Priv) {
router := e.Group("v1")
// use chain for router
middlewares := s.Chain()
router.Use(middlewares...)
// register routes info to router
router.Handle("POST", "/topic/unfollow", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(web.UnfollowTopicReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
s.Render(c, nil, s.UnfollowTopic(req))
})
router.Handle("POST", "/topic/follow", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(web.FollowTopicReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
s.Render(c, nil, s.FollowTopic(req))
})
router.Handle("POST", "/topic/stick", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(web.StickTopicReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.StickTopic(req)
s.Render(c, resp, err)
})
router.Handle("POST", "/tweet/reply/thumbsdown", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(web.TweetReplyThumbsReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
s.Render(c, nil, s.ThumbsDownTweetReply(req))
})
router.Handle("POST", "/tweet/reply/thumbsup", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(web.TweetReplyThumbsReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
s.Render(c, nil, s.ThumbsUpTweetReply(req))
})
router.Handle("POST", "/tweet/comment/thumbsdown", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(web.TweetCommentThumbsReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
s.Render(c, nil, s.ThumbsDownTweetComment(req))
})
router.Handle("POST", "/tweet/comment/thumbsup", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(web.TweetCommentThumbsReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
s.Render(c, nil, s.ThumbsUpTweetComment(req))
})
router.Handle("DELETE", "/post/comment/reply", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDeleteCommentReply(c)
if err != nil {
r.RenderDeleteCommentReply(c, err)
req := new(web.DeleteCommentReplyReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderDeleteCommentReply(c, s.DeleteCommentReply(req))
s.Render(c, nil, s.DeleteCommentReply(req))
})
router.Handle("POST", "/post/comment/reply", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindCreateCommentReply(c)
if err != nil {
r.RenderCreateCommentReply(c, nil, err)
req := new(web.CreateCommentReplyReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.CreateCommentReply(req)
r.RenderCreateCommentReply(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("DELETE", "/post/comment", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDeleteComment(c)
if err != nil {
r.RenderDeleteComment(c, err)
req := new(web.DeleteCommentReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderDeleteComment(c, s.DeleteComment(req))
s.Render(c, nil, s.DeleteComment(req))
})
router.Handle("POST", "/post/comment", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindCreateComment(c)
if err != nil {
r.RenderCreateComment(c, nil, err)
req := new(web.CreateCommentReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.CreateComment(req)
r.RenderCreateComment(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/post/visibility", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindVisibleTweet(c)
if err != nil {
r.RenderVisibleTweet(c, nil, err)
req := new(web.VisibleTweetReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.VisibleTweet(req)
r.RenderVisibleTweet(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/post/highlight", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req := new(web.HighlightTweetReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.HighlightTweet(req)
s.Render(c, resp, err)
})
router.Handle("POST", "/post/stick", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindStickTweet(c)
if err != nil {
r.RenderStickTweet(c, nil, err)
req := new(web.StickTweetReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.StickTweet(req)
r.RenderStickTweet(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/post/lock", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindLockTweet(c)
if err != nil {
r.RenderLockTweet(c, nil, err)
req := new(web.LockTweetReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.LockTweet(req)
r.RenderLockTweet(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/post/collection", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindCollectionTweet(c)
if err != nil {
r.RenderCollectionTweet(c, nil, err)
req := new(web.CollectionTweetReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.CollectionTweet(req)
r.RenderCollectionTweet(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/post/start", func(c *gin.Context) {
router.Handle("POST", "/post/star", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindStarTweet(c)
if err != nil {
r.RenderStarTweet(c, nil, err)
req := new(web.StarTweetReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.StarTweet(req)
r.RenderStarTweet(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("DELETE", "/post", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDeleteTweet(c)
if err != nil {
r.RenderDeleteTweet(c, err)
req := new(web.DeleteTweetReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderDeleteTweet(c, s.DeleteTweet(req))
s.Render(c, nil, s.DeleteTweet(req))
})
router.Handle("POST", "/post", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindCreateTweet(c)
if err != nil {
r.RenderCreateTweet(c, nil, err)
req := new(web.CreateTweetReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.CreateTweet(req)
r.RenderCreateTweet(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/attachment", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDownloadAttachment(c)
if err != nil {
r.RenderDownloadAttachment(c, nil, err)
req := new(web.DownloadAttachmentReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.DownloadAttachment(req)
r.RenderDownloadAttachment(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/attachment/precheck", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindDownloadAttachmentPrecheck(c)
if err != nil {
r.RenderDownloadAttachmentPrecheck(c, nil, err)
req := new(web.DownloadAttachmentPrecheckReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.DownloadAttachmentPrecheck(req)
r.RenderDownloadAttachmentPrecheck(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/attachment", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindUploadAttachment(c)
if err != nil {
r.RenderUploadAttachment(c, nil, err)
req := new(web.UploadAttachmentReq)
var bv _binding_ = req
if err := bv.Bind(c); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.UploadAttachment(req)
r.RenderUploadAttachment(c, resp, err)
s.Render(c, resp, err)
})
}
// UnimplementedPrivServant can be embedded to have forward compatible implementations.
type UnimplementedPrivServant struct {
}
type UnimplementedPrivServant struct{}
func (UnimplementedPrivServant) Chain() gin.HandlersChain {
return nil
}
func (UnimplementedPrivServant) UnfollowTopic(req *web.UnfollowTopicReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) FollowTopic(req *web.FollowTopicReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) StickTopic(req *web.StickTopicReq) (*web.StickTopicResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) ThumbsDownTweetReply(req *web.TweetReplyThumbsReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) ThumbsUpTweetReply(req *web.TweetReplyThumbsReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) ThumbsDownTweetComment(req *web.TweetCommentThumbsReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) ThumbsUpTweetComment(req *web.TweetCommentThumbsReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) DeleteCommentReply(req *web.DeleteCommentReplyReq) mir.Error {
return mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
@ -329,6 +414,10 @@ func (UnimplementedPrivServant) VisibleTweet(req *web.VisibleTweetReq) (*web.Vis
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) HighlightTweet(req *web.HighlightTweetReq) (*web.HighlightTweetResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPrivServant) StickTweet(req *web.StickTweetReq) (*web.StickTweetResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
@ -366,157 +455,3 @@ func (UnimplementedPrivServant) UploadAttachment(req *web.UploadAttachmentReq) (
}
func (UnimplementedPrivServant) mustEmbedUnimplementedPrivServant() {}
// UnimplementedPrivRender can be embedded to have forward compatible implementations.
type UnimplementedPrivRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedPrivRender) RenderDeleteCommentReply(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedPrivRender) RenderCreateCommentReply(c *gin.Context, data *web.CreateCommentReplyResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderDeleteComment(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedPrivRender) RenderCreateComment(c *gin.Context, data *web.CreateCommentResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderVisibleTweet(c *gin.Context, data *web.VisibleTweetResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderStickTweet(c *gin.Context, data *web.StickTweetResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderLockTweet(c *gin.Context, data *web.LockTweetResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderCollectionTweet(c *gin.Context, data *web.CollectionTweetResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderStarTweet(c *gin.Context, data *web.StarTweetResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderDeleteTweet(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedPrivRender) RenderCreateTweet(c *gin.Context, data *web.CreateTweetResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderDownloadAttachment(c *gin.Context, data *web.DownloadAttachmentResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderDownloadAttachmentPrecheck(c *gin.Context, data *web.DownloadAttachmentPrecheckResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) RenderUploadAttachment(c *gin.Context, data *web.UploadAttachmentResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPrivRender) mustEmbedUnimplementedPrivRender() {}
// UnimplementedPrivBinding can be embedded to have forward compatible implementations.
type UnimplementedPrivBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedPrivBinding) BindDeleteCommentReply(c *gin.Context) (*web.DeleteCommentReplyReq, mir.Error) {
obj := new(web.DeleteCommentReplyReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindCreateCommentReply(c *gin.Context) (*web.CreateCommentReplyReq, mir.Error) {
obj := new(web.CreateCommentReplyReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindDeleteComment(c *gin.Context) (*web.DeleteCommentReq, mir.Error) {
obj := new(web.DeleteCommentReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindCreateComment(c *gin.Context) (*web.CreateCommentReq, mir.Error) {
obj := new(web.CreateCommentReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindVisibleTweet(c *gin.Context) (*web.VisibleTweetReq, mir.Error) {
obj := new(web.VisibleTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindStickTweet(c *gin.Context) (*web.StickTweetReq, mir.Error) {
obj := new(web.StickTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindLockTweet(c *gin.Context) (*web.LockTweetReq, mir.Error) {
obj := new(web.LockTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindCollectionTweet(c *gin.Context) (*web.CollectionTweetReq, mir.Error) {
obj := new(web.CollectionTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindStarTweet(c *gin.Context) (*web.StarTweetReq, mir.Error) {
obj := new(web.StarTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindDeleteTweet(c *gin.Context) (*web.DeleteTweetReq, mir.Error) {
obj := new(web.DeleteTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindCreateTweet(c *gin.Context) (*web.CreateTweetReq, mir.Error) {
obj := new(web.CreateTweetReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindDownloadAttachment(c *gin.Context) (*web.DownloadAttachmentReq, mir.Error) {
obj := new(web.DownloadAttachmentReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindDownloadAttachmentPrecheck(c *gin.Context) (*web.DownloadAttachmentPrecheckReq, mir.Error) {
obj := new(web.DownloadAttachmentPrecheckReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) BindUploadAttachment(c *gin.Context) (*web.UploadAttachmentReq, mir.Error) {
obj := new(web.UploadAttachmentReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPrivBinding) mustEmbedUnimplementedPrivBinding() {}

@ -1,18 +1,20 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
"github.com/rocboss/paopao-ce/internal/model/web"
)
type Pub interface {
TopicList(*web.TopicListReq) (*web.TopicListResp, mir.Error)
TweetComments(*web.TweetCommentsReq) (*web.TweetCommentsResp, mir.Error)
_default_
TweetDetail(*web.TweetDetailReq) (*web.TweetDetailResp, mir.Error)
SendCaptcha(*web.SendCaptchaReq) mir.Error
GetCaptcha() (*web.GetCaptchaResp, mir.Error)
@ -23,98 +25,38 @@ type Pub interface {
mustEmbedUnimplementedPubServant()
}
type PubBinding interface {
BindTopicList(*gin.Context) (*web.TopicListReq, mir.Error)
BindTweetComments(*gin.Context) (*web.TweetCommentsReq, mir.Error)
BindTweetDetail(*gin.Context) (*web.TweetDetailReq, mir.Error)
BindSendCaptcha(*gin.Context) (*web.SendCaptchaReq, mir.Error)
BindRegister(*gin.Context) (*web.RegisterReq, mir.Error)
BindLogin(*gin.Context) (*web.LoginReq, mir.Error)
mustEmbedUnimplementedPubBinding()
}
type PubRender interface {
RenderTopicList(*gin.Context, *web.TopicListResp, mir.Error)
RenderTweetComments(*gin.Context, *web.TweetCommentsResp, mir.Error)
RenderTweetDetail(*gin.Context, *web.TweetDetailResp, mir.Error)
RenderSendCaptcha(*gin.Context, mir.Error)
RenderGetCaptcha(*gin.Context, *web.GetCaptchaResp, mir.Error)
RenderRegister(*gin.Context, *web.RegisterResp, mir.Error)
RenderLogin(*gin.Context, *web.LoginResp, mir.Error)
RenderVersion(*gin.Context, *web.VersionResp, mir.Error)
mustEmbedUnimplementedPubRender()
}
// RegisterPubServant register Pub servant to gin
func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) {
func RegisterPubServant(e *gin.Engine, s Pub) {
router := e.Group("v1")
// register routes info to router
router.Handle("GET", "/tags", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindTopicList(c)
if err != nil {
r.RenderTopicList(c, nil, err)
return
}
resp, err := s.TopicList(req)
r.RenderTopicList(c, resp, err)
})
router.Handle("GET", "/post/comments", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindTweetComments(c)
if err != nil {
r.RenderTweetComments(c, nil, err)
return
}
resp, err := s.TweetComments(req)
r.RenderTweetComments(c, resp, err)
})
router.Handle("GET", "/post", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindTweetDetail(c)
if err != nil {
r.RenderTweetDetail(c, nil, err)
req := new(web.TweetDetailReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.TweetDetail(req)
r.RenderTweetDetail(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/captcha", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindSendCaptcha(c)
if err != nil {
r.RenderSendCaptcha(c, err)
req := new(web.SendCaptchaReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
r.RenderSendCaptcha(c, s.SendCaptcha(req))
s.Render(c, nil, s.SendCaptcha(req))
})
router.Handle("GET", "/captcha", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
@ -123,41 +65,36 @@ func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) {
}
resp, err := s.GetCaptcha()
r.RenderGetCaptcha(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/auth/register", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
return
default:
}
req, err := b.BindRegister(c)
if err != nil {
r.RenderRegister(c, nil, err)
req := new(web.RegisterReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.Register(req)
r.RenderRegister(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("POST", "/auth/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)
req := new(web.LoginReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
s.Render(c, resp, err)
})
router.Handle("GET", "/", func(c *gin.Context) {
select {
case <-c.Request.Context().Done():
@ -166,22 +103,12 @@ func RegisterPubServant(e *gin.Engine, s Pub, b PubBinding, r PubRender) {
}
resp, err := s.Version()
r.RenderVersion(c, resp, err)
s.Render(c, resp, err)
})
}
// UnimplementedPubServant can be embedded to have forward compatible implementations.
type UnimplementedPubServant struct {
}
func (UnimplementedPubServant) TopicList(req *web.TopicListReq) (*web.TopicListResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
func (UnimplementedPubServant) TweetComments(req *web.TweetCommentsReq) (*web.TweetCommentsResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
}
type UnimplementedPubServant struct{}
func (UnimplementedPubServant) TweetDetail(req *web.TweetDetailReq) (*web.TweetDetailResp, mir.Error) {
return nil, mir.Errorln(http.StatusNotImplemented, http.StatusText(http.StatusNotImplemented))
@ -208,85 +135,3 @@ func (UnimplementedPubServant) Version() (*web.VersionResp, mir.Error) {
}
func (UnimplementedPubServant) mustEmbedUnimplementedPubServant() {}
// UnimplementedPubRender can be embedded to have forward compatible implementations.
type UnimplementedPubRender struct {
RenderAny func(*gin.Context, any, mir.Error)
}
func (r *UnimplementedPubRender) RenderTopicList(c *gin.Context, data *web.TopicListResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) RenderTweetComments(c *gin.Context, data *web.TweetCommentsResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) RenderTweetDetail(c *gin.Context, data *web.TweetDetailResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) RenderSendCaptcha(c *gin.Context, err mir.Error) {
r.RenderAny(c, nil, err)
}
func (r *UnimplementedPubRender) RenderGetCaptcha(c *gin.Context, data *web.GetCaptchaResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) RenderRegister(c *gin.Context, data *web.RegisterResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) RenderLogin(c *gin.Context, data *web.LoginResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) RenderVersion(c *gin.Context, data *web.VersionResp, err mir.Error) {
r.RenderAny(c, data, err)
}
func (r *UnimplementedPubRender) mustEmbedUnimplementedPubRender() {}
// UnimplementedPubBinding can be embedded to have forward compatible implementations.
type UnimplementedPubBinding struct {
BindAny func(*gin.Context, any) mir.Error
}
func (b *UnimplementedPubBinding) BindTopicList(c *gin.Context) (*web.TopicListReq, mir.Error) {
obj := new(web.TopicListReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPubBinding) BindTweetComments(c *gin.Context) (*web.TweetCommentsReq, mir.Error) {
obj := new(web.TweetCommentsReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPubBinding) BindTweetDetail(c *gin.Context) (*web.TweetDetailReq, mir.Error) {
obj := new(web.TweetDetailReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPubBinding) BindSendCaptcha(c *gin.Context) (*web.SendCaptchaReq, mir.Error) {
obj := new(web.SendCaptchaReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPubBinding) BindRegister(c *gin.Context) (*web.RegisterReq, mir.Error) {
obj := new(web.RegisterReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPubBinding) BindLogin(c *gin.Context) (*web.LoginReq, mir.Error) {
obj := new(web.LoginReq)
err := b.BindAny(c, obj)
return obj, err
}
func (b *UnimplementedPubBinding) mustEmbedUnimplementedPubBinding() {}

@ -1,14 +1,29 @@
// Code generated by go-mir. DO NOT EDIT.
// versions:
// - mir v4.0.0
package v1
import (
"net/http"
"github.com/alimy/mir/v3"
"github.com/alimy/mir/v4"
"github.com/gin-gonic/gin"
)
type _binding_ interface {
Bind(*gin.Context) mir.Error
}
type _render_ interface {
Render(*gin.Context)
}
type _default_ interface {
Bind(*gin.Context, any) mir.Error
Render(*gin.Context, any, mir.Error)
}
type LoginReq struct {
AgentInfo AgentInfo `json:"agent_info"`
Name string `json:"name"`
@ -35,6 +50,8 @@ type UserInfo struct {
}
type User interface {
_default_
// Chain provide handlers chain for gin
Chain() gin.HandlersChain
@ -44,21 +61,8 @@ type User interface {
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) {
func RegisterUserServant(e *gin.Engine, s User) {
router := e.Group("x/v1")
// use chain for router
middlewares := s.Chain()
@ -72,30 +76,26 @@ func RegisterUserServant(e *gin.Engine, s User, b UserBinding, r UserRender) {
default:
}
r.RenderLogout(c, s.Logout())
s.Render(c, nil, 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)
req := new(LoginReq)
if err := s.Bind(c, req); err != nil {
s.Render(c, nil, err)
return
}
resp, err := s.Login(req)
r.RenderLogin(c, resp, err)
s.Render(c, resp, err)
})
}
// UnimplementedUserServant can be embedded to have forward compatible implementations.
type UnimplementedUserServant struct {
}
type UnimplementedUserServant struct{}
func (UnimplementedUserServant) Chain() gin.HandlersChain {
return nil
@ -110,31 +110,3 @@ func (UnimplementedUserServant) Login(req *LoginReq) (*LoginResp, mir.Error) {
}
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,159 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: core/v1/auth.proto
package corev1connect
import (
context "context"
errors "errors"
connect_go "github.com/bufbuild/connect-go"
v1 "github.com/rocboss/paopao-ce/auto/rpc/core/v1"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect_go.IsAtLeastVersion0_1_0
const (
// AuthenticateServiceName is the fully-qualified name of the AuthenticateService service.
AuthenticateServiceName = "core.v1.AuthenticateService"
)
// These constants are the fully-qualified names of the RPCs defined in this package. They're
// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route.
//
// Note that these are different from the fully-qualified method names used by
// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to
// reflection-formatted method names, remove the leading slash and convert the remaining slash to a
// period.
const (
// AuthenticateServicePreLoginProcedure is the fully-qualified name of the AuthenticateService's
// preLogin RPC.
AuthenticateServicePreLoginProcedure = "/core.v1.AuthenticateService/preLogin"
// AuthenticateServiceLoginProcedure is the fully-qualified name of the AuthenticateService's login
// RPC.
AuthenticateServiceLoginProcedure = "/core.v1.AuthenticateService/login"
// AuthenticateServiceLogoutProcedure is the fully-qualified name of the AuthenticateService's
// logout RPC.
AuthenticateServiceLogoutProcedure = "/core.v1.AuthenticateService/logout"
)
// AuthenticateServiceClient is a client for the core.v1.AuthenticateService service.
type AuthenticateServiceClient interface {
PreLogin(context.Context, *connect_go.Request[v1.User]) (*connect_go.Response[v1.ActionReply], error)
Login(context.Context, *connect_go.Request[v1.User]) (*connect_go.Response[v1.LoginReply], error)
Logout(context.Context, *connect_go.Request[v1.User]) (*connect_go.Response[v1.ActionReply], error)
}
// NewAuthenticateServiceClient constructs a client for the core.v1.AuthenticateService service. By
// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses,
// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the
// connect.WithGRPC() or connect.WithGRPCWeb() options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewAuthenticateServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) AuthenticateServiceClient {
baseURL = strings.TrimRight(baseURL, "/")
return &authenticateServiceClient{
preLogin: connect_go.NewClient[v1.User, v1.ActionReply](
httpClient,
baseURL+AuthenticateServicePreLoginProcedure,
opts...,
),
login: connect_go.NewClient[v1.User, v1.LoginReply](
httpClient,
baseURL+AuthenticateServiceLoginProcedure,
opts...,
),
logout: connect_go.NewClient[v1.User, v1.ActionReply](
httpClient,
baseURL+AuthenticateServiceLogoutProcedure,
opts...,
),
}
}
// authenticateServiceClient implements AuthenticateServiceClient.
type authenticateServiceClient struct {
preLogin *connect_go.Client[v1.User, v1.ActionReply]
login *connect_go.Client[v1.User, v1.LoginReply]
logout *connect_go.Client[v1.User, v1.ActionReply]
}
// PreLogin calls core.v1.AuthenticateService.preLogin.
func (c *authenticateServiceClient) PreLogin(ctx context.Context, req *connect_go.Request[v1.User]) (*connect_go.Response[v1.ActionReply], error) {
return c.preLogin.CallUnary(ctx, req)
}
// Login calls core.v1.AuthenticateService.login.
func (c *authenticateServiceClient) Login(ctx context.Context, req *connect_go.Request[v1.User]) (*connect_go.Response[v1.LoginReply], error) {
return c.login.CallUnary(ctx, req)
}
// Logout calls core.v1.AuthenticateService.logout.
func (c *authenticateServiceClient) Logout(ctx context.Context, req *connect_go.Request[v1.User]) (*connect_go.Response[v1.ActionReply], error) {
return c.logout.CallUnary(ctx, req)
}
// AuthenticateServiceHandler is an implementation of the core.v1.AuthenticateService service.
type AuthenticateServiceHandler interface {
PreLogin(context.Context, *connect_go.Request[v1.User]) (*connect_go.Response[v1.ActionReply], error)
Login(context.Context, *connect_go.Request[v1.User]) (*connect_go.Response[v1.LoginReply], error)
Logout(context.Context, *connect_go.Request[v1.User]) (*connect_go.Response[v1.ActionReply], error)
}
// NewAuthenticateServiceHandler builds an HTTP handler from the service implementation. It returns
// the path on which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewAuthenticateServiceHandler(svc AuthenticateServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) {
authenticateServicePreLoginHandler := connect_go.NewUnaryHandler(
AuthenticateServicePreLoginProcedure,
svc.PreLogin,
opts...,
)
authenticateServiceLoginHandler := connect_go.NewUnaryHandler(
AuthenticateServiceLoginProcedure,
svc.Login,
opts...,
)
authenticateServiceLogoutHandler := connect_go.NewUnaryHandler(
AuthenticateServiceLogoutProcedure,
svc.Logout,
opts...,
)
return "/core.v1.AuthenticateService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case AuthenticateServicePreLoginProcedure:
authenticateServicePreLoginHandler.ServeHTTP(w, r)
case AuthenticateServiceLoginProcedure:
authenticateServiceLoginHandler.ServeHTTP(w, r)
case AuthenticateServiceLogoutProcedure:
authenticateServiceLogoutHandler.ServeHTTP(w, r)
default:
http.NotFound(w, r)
}
})
}
// UnimplementedAuthenticateServiceHandler returns CodeUnimplemented from all methods.
type UnimplementedAuthenticateServiceHandler struct{}
func (UnimplementedAuthenticateServiceHandler) PreLogin(context.Context, *connect_go.Request[v1.User]) (*connect_go.Response[v1.ActionReply], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("core.v1.AuthenticateService.preLogin is not implemented"))
}
func (UnimplementedAuthenticateServiceHandler) Login(context.Context, *connect_go.Request[v1.User]) (*connect_go.Response[v1.LoginReply], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("core.v1.AuthenticateService.login is not implemented"))
}
func (UnimplementedAuthenticateServiceHandler) Logout(context.Context, *connect_go.Request[v1.User]) (*connect_go.Response[v1.ActionReply], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("core.v1.AuthenticateService.logout is not implemented"))
}

@ -0,0 +1,104 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: greet/v1/greet.proto
package greetv1connect
import (
context "context"
errors "errors"
connect_go "github.com/bufbuild/connect-go"
v1 "github.com/rocboss/paopao-ce/auto/rpc/greet/v1"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect_go.IsAtLeastVersion0_1_0
const (
// GreetServiceName is the fully-qualified name of the GreetService service.
GreetServiceName = "greet.v1.GreetService"
)
// These constants are the fully-qualified names of the RPCs defined in this package. They're
// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route.
//
// Note that these are different from the fully-qualified method names used by
// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to
// reflection-formatted method names, remove the leading slash and convert the remaining slash to a
// period.
const (
// GreetServiceGreetProcedure is the fully-qualified name of the GreetService's Greet RPC.
GreetServiceGreetProcedure = "/greet.v1.GreetService/Greet"
)
// GreetServiceClient is a client for the greet.v1.GreetService service.
type GreetServiceClient interface {
Greet(context.Context, *connect_go.Request[v1.GreetRequest]) (*connect_go.Response[v1.GreetResponse], error)
}
// NewGreetServiceClient constructs a client for the greet.v1.GreetService service. By default, it
// uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends
// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or
// connect.WithGRPCWeb() options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewGreetServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) GreetServiceClient {
baseURL = strings.TrimRight(baseURL, "/")
return &greetServiceClient{
greet: connect_go.NewClient[v1.GreetRequest, v1.GreetResponse](
httpClient,
baseURL+GreetServiceGreetProcedure,
opts...,
),
}
}
// greetServiceClient implements GreetServiceClient.
type greetServiceClient struct {
greet *connect_go.Client[v1.GreetRequest, v1.GreetResponse]
}
// Greet calls greet.v1.GreetService.Greet.
func (c *greetServiceClient) Greet(ctx context.Context, req *connect_go.Request[v1.GreetRequest]) (*connect_go.Response[v1.GreetResponse], error) {
return c.greet.CallUnary(ctx, req)
}
// GreetServiceHandler is an implementation of the greet.v1.GreetService service.
type GreetServiceHandler interface {
Greet(context.Context, *connect_go.Request[v1.GreetRequest]) (*connect_go.Response[v1.GreetResponse], error)
}
// NewGreetServiceHandler builds an HTTP handler from the service implementation. It returns the
// path on which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewGreetServiceHandler(svc GreetServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) {
greetServiceGreetHandler := connect_go.NewUnaryHandler(
GreetServiceGreetProcedure,
svc.Greet,
opts...,
)
return "/greet.v1.GreetService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case GreetServiceGreetProcedure:
greetServiceGreetHandler.ServeHTTP(w, r)
default:
http.NotFound(w, r)
}
})
}
// UnimplementedGreetServiceHandler returns CodeUnimplemented from all methods.
type UnimplementedGreetServiceHandler struct{}
func (UnimplementedGreetServiceHandler) Greet(context.Context, *connect_go.Request[v1.GreetRequest]) (*connect_go.Response[v1.GreetResponse], error) {
return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("greet.v1.GreetService.Greet is not implemented"))
}

@ -0,0 +1,375 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc (unknown)
// source: core/v1/auth.proto
package corev1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type User struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
PhoneNum string `protobuf:"bytes,1,opt,name=phone_num,json=phoneNum,proto3" json:"phone_num,omitempty"`
}
func (x *User) Reset() {
*x = User{}
if protoimpl.UnsafeEnabled {
mi := &file_core_v1_auth_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *User) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*User) ProtoMessage() {}
func (x *User) ProtoReflect() protoreflect.Message {
mi := &file_core_v1_auth_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use User.ProtoReflect.Descriptor instead.
func (*User) Descriptor() ([]byte, []int) {
return file_core_v1_auth_proto_rawDescGZIP(), []int{0}
}
func (x *User) GetPhoneNum() string {
if x != nil {
return x.PhoneNum
}
return ""
}
type UserVerify struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
PhoneNum string `protobuf:"bytes,1,opt,name=phone_num,json=phoneNum,proto3" json:"phone_num,omitempty"`
VerificationCode string `protobuf:"bytes,2,opt,name=verification_code,json=verificationCode,proto3" json:"verification_code,omitempty"`
}
func (x *UserVerify) Reset() {
*x = UserVerify{}
if protoimpl.UnsafeEnabled {
mi := &file_core_v1_auth_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UserVerify) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UserVerify) ProtoMessage() {}
func (x *UserVerify) ProtoReflect() protoreflect.Message {
mi := &file_core_v1_auth_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UserVerify.ProtoReflect.Descriptor instead.
func (*UserVerify) Descriptor() ([]byte, []int) {
return file_core_v1_auth_proto_rawDescGZIP(), []int{1}
}
func (x *UserVerify) GetPhoneNum() string {
if x != nil {
return x.PhoneNum
}
return ""
}
func (x *UserVerify) GetVerificationCode() string {
if x != nil {
return x.VerificationCode
}
return ""
}
type LoginReply struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
StatusCode int32 `protobuf:"varint,1,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"`
Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"`
}
func (x *LoginReply) Reset() {
*x = LoginReply{}
if protoimpl.UnsafeEnabled {
mi := &file_core_v1_auth_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *LoginReply) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LoginReply) ProtoMessage() {}
func (x *LoginReply) ProtoReflect() protoreflect.Message {
mi := &file_core_v1_auth_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LoginReply.ProtoReflect.Descriptor instead.
func (*LoginReply) Descriptor() ([]byte, []int) {
return file_core_v1_auth_proto_rawDescGZIP(), []int{2}
}
func (x *LoginReply) GetStatusCode() int32 {
if x != nil {
return x.StatusCode
}
return 0
}
func (x *LoginReply) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
type ActionReply struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
StatusCode int32 `protobuf:"varint,1,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"`
}
func (x *ActionReply) Reset() {
*x = ActionReply{}
if protoimpl.UnsafeEnabled {
mi := &file_core_v1_auth_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ActionReply) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ActionReply) ProtoMessage() {}
func (x *ActionReply) ProtoReflect() protoreflect.Message {
mi := &file_core_v1_auth_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ActionReply.ProtoReflect.Descriptor instead.
func (*ActionReply) Descriptor() ([]byte, []int) {
return file_core_v1_auth_proto_rawDescGZIP(), []int{3}
}
func (x *ActionReply) GetStatusCode() int32 {
if x != nil {
return x.StatusCode
}
return 0
}
var File_core_v1_auth_proto protoreflect.FileDescriptor
var file_core_v1_auth_proto_rawDesc = []byte{
0x0a, 0x12, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x22, 0x23, 0x0a,
0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x5f, 0x6e,
0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e,
0x75, 0x6d, 0x22, 0x56, 0x0a, 0x0a, 0x55, 0x73, 0x65, 0x72, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79,
0x12, 0x1b, 0x0a, 0x09, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x12, 0x2b, 0x0a,
0x11, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f,
0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x43, 0x0a, 0x0a, 0x4c, 0x6f,
0x67, 0x69, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74,
0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73,
0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b,
0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22,
0x2e, 0x0a, 0x0b, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1f,
0x0a, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x32,
0xa2, 0x01, 0x0a, 0x13, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65,
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x4c, 0x6f,
0x67, 0x69, 0x6e, 0x12, 0x0d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73,
0x65, 0x72, 0x1a, 0x14, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x2b, 0x0a, 0x05, 0x6c, 0x6f, 0x67, 0x69,
0x6e, 0x12, 0x0d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72,
0x1a, 0x13, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e,
0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x2d, 0x0a, 0x06, 0x6c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12,
0x0d, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x1a, 0x14,
0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52,
0x65, 0x70, 0x6c, 0x79, 0x42, 0x8b, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x72,
0x65, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50,
0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x6f,
0x63, 0x62, 0x6f, 0x73, 0x73, 0x2f, 0x70, 0x61, 0x6f, 0x70, 0x61, 0x6f, 0x2d, 0x63, 0x65, 0x2f,
0x61, 0x75, 0x74, 0x6f, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x31,
0x3b, 0x63, 0x6f, 0x72, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x43, 0x58, 0x58, 0xaa, 0x02, 0x07,
0x43, 0x6f, 0x72, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x07, 0x43, 0x6f, 0x72, 0x65, 0x5c, 0x56,
0x31, 0xe2, 0x02, 0x13, 0x43, 0x6f, 0x72, 0x65, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d,
0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x08, 0x43, 0x6f, 0x72, 0x65, 0x3a, 0x3a,
0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_core_v1_auth_proto_rawDescOnce sync.Once
file_core_v1_auth_proto_rawDescData = file_core_v1_auth_proto_rawDesc
)
func file_core_v1_auth_proto_rawDescGZIP() []byte {
file_core_v1_auth_proto_rawDescOnce.Do(func() {
file_core_v1_auth_proto_rawDescData = protoimpl.X.CompressGZIP(file_core_v1_auth_proto_rawDescData)
})
return file_core_v1_auth_proto_rawDescData
}
var file_core_v1_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_core_v1_auth_proto_goTypes = []interface{}{
(*User)(nil), // 0: core.v1.User
(*UserVerify)(nil), // 1: core.v1.UserVerify
(*LoginReply)(nil), // 2: core.v1.LoginReply
(*ActionReply)(nil), // 3: core.v1.ActionReply
}
var file_core_v1_auth_proto_depIdxs = []int32{
0, // 0: core.v1.AuthenticateService.preLogin:input_type -> core.v1.User
0, // 1: core.v1.AuthenticateService.login:input_type -> core.v1.User
0, // 2: core.v1.AuthenticateService.logout:input_type -> core.v1.User
3, // 3: core.v1.AuthenticateService.preLogin:output_type -> core.v1.ActionReply
2, // 4: core.v1.AuthenticateService.login:output_type -> core.v1.LoginReply
3, // 5: core.v1.AuthenticateService.logout:output_type -> core.v1.ActionReply
3, // [3:6] is the sub-list for method output_type
0, // [0:3] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_core_v1_auth_proto_init() }
func file_core_v1_auth_proto_init() {
if File_core_v1_auth_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_core_v1_auth_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*User); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_core_v1_auth_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UserVerify); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_core_v1_auth_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LoginReply); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_core_v1_auth_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ActionReply); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_core_v1_auth_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_core_v1_auth_proto_goTypes,
DependencyIndexes: file_core_v1_auth_proto_depIdxs,
MessageInfos: file_core_v1_auth_proto_msgTypes,
}.Build()
File_core_v1_auth_proto = out.File
file_core_v1_auth_proto_rawDesc = nil
file_core_v1_auth_proto_goTypes = nil
file_core_v1_auth_proto_depIdxs = nil
}

@ -0,0 +1,183 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc (unknown)
// source: core/v1/auth.proto
package corev1
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
const (
AuthenticateService_PreLogin_FullMethodName = "/core.v1.AuthenticateService/preLogin"
AuthenticateService_Login_FullMethodName = "/core.v1.AuthenticateService/login"
AuthenticateService_Logout_FullMethodName = "/core.v1.AuthenticateService/logout"
)
// AuthenticateServiceClient is the client API for AuthenticateService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type AuthenticateServiceClient interface {
PreLogin(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error)
Login(ctx context.Context, in *User, opts ...grpc.CallOption) (*LoginReply, error)
Logout(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error)
}
type authenticateServiceClient struct {
cc grpc.ClientConnInterface
}
func NewAuthenticateServiceClient(cc grpc.ClientConnInterface) AuthenticateServiceClient {
return &authenticateServiceClient{cc}
}
func (c *authenticateServiceClient) PreLogin(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error) {
out := new(ActionReply)
err := c.cc.Invoke(ctx, AuthenticateService_PreLogin_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authenticateServiceClient) Login(ctx context.Context, in *User, opts ...grpc.CallOption) (*LoginReply, error) {
out := new(LoginReply)
err := c.cc.Invoke(ctx, AuthenticateService_Login_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authenticateServiceClient) Logout(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error) {
out := new(ActionReply)
err := c.cc.Invoke(ctx, AuthenticateService_Logout_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// AuthenticateServiceServer is the server API for AuthenticateService service.
// All implementations must embed UnimplementedAuthenticateServiceServer
// for forward compatibility
type AuthenticateServiceServer interface {
PreLogin(context.Context, *User) (*ActionReply, error)
Login(context.Context, *User) (*LoginReply, error)
Logout(context.Context, *User) (*ActionReply, error)
mustEmbedUnimplementedAuthenticateServiceServer()
}
// UnimplementedAuthenticateServiceServer must be embedded to have forward compatible implementations.
type UnimplementedAuthenticateServiceServer struct {
}
func (UnimplementedAuthenticateServiceServer) PreLogin(context.Context, *User) (*ActionReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method PreLogin not implemented")
}
func (UnimplementedAuthenticateServiceServer) Login(context.Context, *User) (*LoginReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
}
func (UnimplementedAuthenticateServiceServer) Logout(context.Context, *User) (*ActionReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method Logout not implemented")
}
func (UnimplementedAuthenticateServiceServer) mustEmbedUnimplementedAuthenticateServiceServer() {}
// UnsafeAuthenticateServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AuthenticateServiceServer will
// result in compilation errors.
type UnsafeAuthenticateServiceServer interface {
mustEmbedUnimplementedAuthenticateServiceServer()
}
func RegisterAuthenticateServiceServer(s grpc.ServiceRegistrar, srv AuthenticateServiceServer) {
s.RegisterService(&AuthenticateService_ServiceDesc, srv)
}
func _AuthenticateService_PreLogin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(User)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthenticateServiceServer).PreLogin(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthenticateService_PreLogin_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthenticateServiceServer).PreLogin(ctx, req.(*User))
}
return interceptor(ctx, in, info, handler)
}
func _AuthenticateService_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(User)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthenticateServiceServer).Login(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthenticateService_Login_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthenticateServiceServer).Login(ctx, req.(*User))
}
return interceptor(ctx, in, info, handler)
}
func _AuthenticateService_Logout_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(User)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthenticateServiceServer).Logout(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthenticateService_Logout_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthenticateServiceServer).Logout(ctx, req.(*User))
}
return interceptor(ctx, in, info, handler)
}
// AuthenticateService_ServiceDesc is the grpc.ServiceDesc for AuthenticateService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var AuthenticateService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "core.v1.AuthenticateService",
HandlerType: (*AuthenticateServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "preLogin",
Handler: _AuthenticateService_PreLogin_Handler,
},
{
MethodName: "login",
Handler: _AuthenticateService_Login_Handler,
},
{
MethodName: "logout",
Handler: _AuthenticateService_Logout_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "core/v1/auth.proto",
}

@ -0,0 +1,220 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc (unknown)
// source: greet/v1/greet.proto
package greetv1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type GreetRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
}
func (x *GreetRequest) Reset() {
*x = GreetRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_greet_v1_greet_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GreetRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GreetRequest) ProtoMessage() {}
func (x *GreetRequest) ProtoReflect() protoreflect.Message {
mi := &file_greet_v1_greet_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GreetRequest.ProtoReflect.Descriptor instead.
func (*GreetRequest) Descriptor() ([]byte, []int) {
return file_greet_v1_greet_proto_rawDescGZIP(), []int{0}
}
func (x *GreetRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
type GreetResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Greeting string `protobuf:"bytes,1,opt,name=greeting,proto3" json:"greeting,omitempty"`
}
func (x *GreetResponse) Reset() {
*x = GreetResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_greet_v1_greet_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GreetResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GreetResponse) ProtoMessage() {}
func (x *GreetResponse) ProtoReflect() protoreflect.Message {
mi := &file_greet_v1_greet_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GreetResponse.ProtoReflect.Descriptor instead.
func (*GreetResponse) Descriptor() ([]byte, []int) {
return file_greet_v1_greet_proto_rawDescGZIP(), []int{1}
}
func (x *GreetResponse) GetGreeting() string {
if x != nil {
return x.Greeting
}
return ""
}
var File_greet_v1_greet_proto protoreflect.FileDescriptor
var file_greet_v1_greet_proto_rawDesc = []byte{
0x0a, 0x14, 0x67, 0x72, 0x65, 0x65, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x72, 0x65, 0x65, 0x74,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74, 0x2e, 0x76, 0x31,
0x22, 0x22, 0x0a, 0x0c, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2b, 0x0a, 0x0d, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e,
0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e,
0x67, 0x32, 0x4a, 0x0a, 0x0c, 0x47, 0x72, 0x65, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x12, 0x3a, 0x0a, 0x05, 0x47, 0x72, 0x65, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x72, 0x65,
0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x72, 0x65, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72,
0x65, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x93, 0x01,
0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x72, 0x65, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x42, 0x0a,
0x47, 0x72, 0x65, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x36, 0x67, 0x69,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x6f, 0x63, 0x62, 0x6f, 0x73, 0x73,
0x2f, 0x70, 0x61, 0x6f, 0x70, 0x61, 0x6f, 0x2d, 0x63, 0x65, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x2f,
0x72, 0x70, 0x63, 0x2f, 0x67, 0x72, 0x65, 0x65, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x67, 0x72, 0x65,
0x65, 0x74, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x47, 0x58, 0x58, 0xaa, 0x02, 0x08, 0x47, 0x72, 0x65,
0x65, 0x74, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x08, 0x47, 0x72, 0x65, 0x65, 0x74, 0x5c, 0x56, 0x31,
0xe2, 0x02, 0x14, 0x47, 0x72, 0x65, 0x65, 0x74, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d,
0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, 0x47, 0x72, 0x65, 0x65, 0x74, 0x3a,
0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_greet_v1_greet_proto_rawDescOnce sync.Once
file_greet_v1_greet_proto_rawDescData = file_greet_v1_greet_proto_rawDesc
)
func file_greet_v1_greet_proto_rawDescGZIP() []byte {
file_greet_v1_greet_proto_rawDescOnce.Do(func() {
file_greet_v1_greet_proto_rawDescData = protoimpl.X.CompressGZIP(file_greet_v1_greet_proto_rawDescData)
})
return file_greet_v1_greet_proto_rawDescData
}
var file_greet_v1_greet_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_greet_v1_greet_proto_goTypes = []interface{}{
(*GreetRequest)(nil), // 0: greet.v1.GreetRequest
(*GreetResponse)(nil), // 1: greet.v1.GreetResponse
}
var file_greet_v1_greet_proto_depIdxs = []int32{
0, // 0: greet.v1.GreetService.Greet:input_type -> greet.v1.GreetRequest
1, // 1: greet.v1.GreetService.Greet:output_type -> greet.v1.GreetResponse
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_greet_v1_greet_proto_init() }
func file_greet_v1_greet_proto_init() {
if File_greet_v1_greet_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_greet_v1_greet_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GreetRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_greet_v1_greet_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GreetResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_greet_v1_greet_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_greet_v1_greet_proto_goTypes,
DependencyIndexes: file_greet_v1_greet_proto_depIdxs,
MessageInfos: file_greet_v1_greet_proto_msgTypes,
}.Build()
File_greet_v1_greet_proto = out.File
file_greet_v1_greet_proto_rawDesc = nil
file_greet_v1_greet_proto_goTypes = nil
file_greet_v1_greet_proto_depIdxs = nil
}

@ -0,0 +1,109 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc (unknown)
// source: greet/v1/greet.proto
package greetv1
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
const (
GreetService_Greet_FullMethodName = "/greet.v1.GreetService/Greet"
)
// GreetServiceClient is the client API for GreetService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type GreetServiceClient interface {
Greet(ctx context.Context, in *GreetRequest, opts ...grpc.CallOption) (*GreetResponse, error)
}
type greetServiceClient struct {
cc grpc.ClientConnInterface
}
func NewGreetServiceClient(cc grpc.ClientConnInterface) GreetServiceClient {
return &greetServiceClient{cc}
}
func (c *greetServiceClient) Greet(ctx context.Context, in *GreetRequest, opts ...grpc.CallOption) (*GreetResponse, error) {
out := new(GreetResponse)
err := c.cc.Invoke(ctx, GreetService_Greet_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// GreetServiceServer is the server API for GreetService service.
// All implementations must embed UnimplementedGreetServiceServer
// for forward compatibility
type GreetServiceServer interface {
Greet(context.Context, *GreetRequest) (*GreetResponse, error)
mustEmbedUnimplementedGreetServiceServer()
}
// UnimplementedGreetServiceServer must be embedded to have forward compatible implementations.
type UnimplementedGreetServiceServer struct {
}
func (UnimplementedGreetServiceServer) Greet(context.Context, *GreetRequest) (*GreetResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Greet not implemented")
}
func (UnimplementedGreetServiceServer) mustEmbedUnimplementedGreetServiceServer() {}
// UnsafeGreetServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to GreetServiceServer will
// result in compilation errors.
type UnsafeGreetServiceServer interface {
mustEmbedUnimplementedGreetServiceServer()
}
func RegisterGreetServiceServer(s grpc.ServiceRegistrar, srv GreetServiceServer) {
s.RegisterService(&GreetService_ServiceDesc, srv)
}
func _GreetService_Greet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GreetRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GreetServiceServer).Greet(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: GreetService_Greet_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GreetServiceServer).Greet(ctx, req.(*GreetRequest))
}
return interceptor(ctx, in, info, handler)
}
// GreetService_ServiceDesc is the grpc.ServiceDesc for GreetService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var GreetService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "greet.v1.GreetService",
HandlerType: (*GreetServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Greet",
Handler: _GreetService_Greet_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "greet/v1/greet.proto",
}

@ -1,371 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc (unknown)
// source: v1/auth.proto
package v1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type User struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
PhoneNum string `protobuf:"bytes,1,opt,name=phoneNum,proto3" json:"phoneNum,omitempty"`
}
func (x *User) Reset() {
*x = User{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_auth_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *User) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*User) ProtoMessage() {}
func (x *User) ProtoReflect() protoreflect.Message {
mi := &file_v1_auth_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use User.ProtoReflect.Descriptor instead.
func (*User) Descriptor() ([]byte, []int) {
return file_v1_auth_proto_rawDescGZIP(), []int{0}
}
func (x *User) GetPhoneNum() string {
if x != nil {
return x.PhoneNum
}
return ""
}
type UserVerify struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
PhoneNum string `protobuf:"bytes,1,opt,name=phoneNum,proto3" json:"phoneNum,omitempty"`
VerificationCode string `protobuf:"bytes,2,opt,name=VerificationCode,proto3" json:"VerificationCode,omitempty"`
}
func (x *UserVerify) Reset() {
*x = UserVerify{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_auth_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UserVerify) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UserVerify) ProtoMessage() {}
func (x *UserVerify) ProtoReflect() protoreflect.Message {
mi := &file_v1_auth_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UserVerify.ProtoReflect.Descriptor instead.
func (*UserVerify) Descriptor() ([]byte, []int) {
return file_v1_auth_proto_rawDescGZIP(), []int{1}
}
func (x *UserVerify) GetPhoneNum() string {
if x != nil {
return x.PhoneNum
}
return ""
}
func (x *UserVerify) GetVerificationCode() string {
if x != nil {
return x.VerificationCode
}
return ""
}
type LoginReply struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
StatuCode int32 `protobuf:"varint,1,opt,name=statuCode,proto3" json:"statuCode,omitempty"`
Token string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"`
}
func (x *LoginReply) Reset() {
*x = LoginReply{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_auth_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *LoginReply) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LoginReply) ProtoMessage() {}
func (x *LoginReply) ProtoReflect() protoreflect.Message {
mi := &file_v1_auth_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LoginReply.ProtoReflect.Descriptor instead.
func (*LoginReply) Descriptor() ([]byte, []int) {
return file_v1_auth_proto_rawDescGZIP(), []int{2}
}
func (x *LoginReply) GetStatuCode() int32 {
if x != nil {
return x.StatuCode
}
return 0
}
func (x *LoginReply) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
type ActionReply struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
StatusCode int32 `protobuf:"varint,1,opt,name=statusCode,proto3" json:"statusCode,omitempty"`
}
func (x *ActionReply) Reset() {
*x = ActionReply{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_auth_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ActionReply) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ActionReply) ProtoMessage() {}
func (x *ActionReply) ProtoReflect() protoreflect.Message {
mi := &file_v1_auth_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ActionReply.ProtoReflect.Descriptor instead.
func (*ActionReply) Descriptor() ([]byte, []int) {
return file_v1_auth_proto_rawDescGZIP(), []int{3}
}
func (x *ActionReply) GetStatusCode() int32 {
if x != nil {
return x.StatusCode
}
return 0
}
var File_v1_auth_proto protoreflect.FileDescriptor
var file_v1_auth_proto_rawDesc = []byte{
0x0a, 0x0d, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x04, 0x61, 0x75, 0x74, 0x68, 0x22, 0x22, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a,
0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x22, 0x54, 0x0a, 0x0a, 0x55, 0x73, 0x65,
0x72, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65,
0x4e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x68, 0x6f, 0x6e, 0x65,
0x4e, 0x75, 0x6d, 0x12, 0x2a, 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x56,
0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x22,
0x40, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1c, 0x0a,
0x09, 0x73, 0x74, 0x61, 0x74, 0x75, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x75, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74,
0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65,
0x6e, 0x22, 0x2d, 0x0a, 0x0b, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79,
0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65,
0x32, 0x89, 0x01, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
0x65, 0x12, 0x29, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x0a, 0x2e,
0x61, 0x75, 0x74, 0x68, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x1a, 0x11, 0x2e, 0x61, 0x75, 0x74, 0x68,
0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x25, 0x0a, 0x05,
0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x0a, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x55, 0x73, 0x65,
0x72, 0x1a, 0x10, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65,
0x70, 0x6c, 0x79, 0x12, 0x27, 0x0a, 0x06, 0x6c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12, 0x0a, 0x2e,
0x61, 0x75, 0x74, 0x68, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x1a, 0x11, 0x2e, 0x61, 0x75, 0x74, 0x68,
0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x42, 0x6f, 0x0a, 0x08,
0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x42, 0x09, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72,
0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x72, 0x6f, 0x63, 0x62, 0x6f, 0x73, 0x73, 0x2f, 0x70, 0x61, 0x6f, 0x70, 0x61, 0x6f,
0x2d, 0x63, 0x65, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x76, 0x31, 0xa2,
0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x04, 0x41, 0x75, 0x74, 0x68, 0xca, 0x02, 0x04, 0x41,
0x75, 0x74, 0x68, 0xe2, 0x02, 0x10, 0x41, 0x75, 0x74, 0x68, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65,
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x04, 0x41, 0x75, 0x74, 0x68, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_v1_auth_proto_rawDescOnce sync.Once
file_v1_auth_proto_rawDescData = file_v1_auth_proto_rawDesc
)
func file_v1_auth_proto_rawDescGZIP() []byte {
file_v1_auth_proto_rawDescOnce.Do(func() {
file_v1_auth_proto_rawDescData = protoimpl.X.CompressGZIP(file_v1_auth_proto_rawDescData)
})
return file_v1_auth_proto_rawDescData
}
var file_v1_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_v1_auth_proto_goTypes = []interface{}{
(*User)(nil), // 0: auth.User
(*UserVerify)(nil), // 1: auth.UserVerify
(*LoginReply)(nil), // 2: auth.LoginReply
(*ActionReply)(nil), // 3: auth.ActionReply
}
var file_v1_auth_proto_depIdxs = []int32{
0, // 0: auth.Authenticate.preLogin:input_type -> auth.User
0, // 1: auth.Authenticate.login:input_type -> auth.User
0, // 2: auth.Authenticate.logout:input_type -> auth.User
3, // 3: auth.Authenticate.preLogin:output_type -> auth.ActionReply
2, // 4: auth.Authenticate.login:output_type -> auth.LoginReply
3, // 5: auth.Authenticate.logout:output_type -> auth.ActionReply
3, // [3:6] is the sub-list for method output_type
0, // [0:3] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_v1_auth_proto_init() }
func file_v1_auth_proto_init() {
if File_v1_auth_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_v1_auth_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*User); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_v1_auth_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UserVerify); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_v1_auth_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LoginReply); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_v1_auth_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ActionReply); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_v1_auth_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_v1_auth_proto_goTypes,
DependencyIndexes: file_v1_auth_proto_depIdxs,
MessageInfos: file_v1_auth_proto_msgTypes,
}.Build()
File_v1_auth_proto = out.File
file_v1_auth_proto_rawDesc = nil
file_v1_auth_proto_goTypes = nil
file_v1_auth_proto_depIdxs = nil
}

@ -1,177 +0,0 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.2.0
// - protoc (unknown)
// source: v1/auth.proto
package v1
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// AuthenticateClient is the client API for Authenticate service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type AuthenticateClient interface {
PreLogin(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error)
Login(ctx context.Context, in *User, opts ...grpc.CallOption) (*LoginReply, error)
Logout(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error)
}
type authenticateClient struct {
cc grpc.ClientConnInterface
}
func NewAuthenticateClient(cc grpc.ClientConnInterface) AuthenticateClient {
return &authenticateClient{cc}
}
func (c *authenticateClient) PreLogin(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error) {
out := new(ActionReply)
err := c.cc.Invoke(ctx, "/auth.Authenticate/preLogin", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authenticateClient) Login(ctx context.Context, in *User, opts ...grpc.CallOption) (*LoginReply, error) {
out := new(LoginReply)
err := c.cc.Invoke(ctx, "/auth.Authenticate/login", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authenticateClient) Logout(ctx context.Context, in *User, opts ...grpc.CallOption) (*ActionReply, error) {
out := new(ActionReply)
err := c.cc.Invoke(ctx, "/auth.Authenticate/logout", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// AuthenticateServer is the server API for Authenticate service.
// All implementations must embed UnimplementedAuthenticateServer
// for forward compatibility
type AuthenticateServer interface {
PreLogin(context.Context, *User) (*ActionReply, error)
Login(context.Context, *User) (*LoginReply, error)
Logout(context.Context, *User) (*ActionReply, error)
mustEmbedUnimplementedAuthenticateServer()
}
// UnimplementedAuthenticateServer must be embedded to have forward compatible implementations.
type UnimplementedAuthenticateServer struct {
}
func (UnimplementedAuthenticateServer) PreLogin(context.Context, *User) (*ActionReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method PreLogin not implemented")
}
func (UnimplementedAuthenticateServer) Login(context.Context, *User) (*LoginReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
}
func (UnimplementedAuthenticateServer) Logout(context.Context, *User) (*ActionReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method Logout not implemented")
}
func (UnimplementedAuthenticateServer) mustEmbedUnimplementedAuthenticateServer() {}
// UnsafeAuthenticateServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AuthenticateServer will
// result in compilation errors.
type UnsafeAuthenticateServer interface {
mustEmbedUnimplementedAuthenticateServer()
}
func RegisterAuthenticateServer(s grpc.ServiceRegistrar, srv AuthenticateServer) {
s.RegisterService(&Authenticate_ServiceDesc, srv)
}
func _Authenticate_PreLogin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(User)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthenticateServer).PreLogin(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/auth.Authenticate/preLogin",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthenticateServer).PreLogin(ctx, req.(*User))
}
return interceptor(ctx, in, info, handler)
}
func _Authenticate_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(User)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthenticateServer).Login(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/auth.Authenticate/login",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthenticateServer).Login(ctx, req.(*User))
}
return interceptor(ctx, in, info, handler)
}
func _Authenticate_Logout_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(User)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthenticateServer).Logout(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/auth.Authenticate/logout",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthenticateServer).Logout(ctx, req.(*User))
}
return interceptor(ctx, in, info, handler)
}
// Authenticate_ServiceDesc is the grpc.ServiceDesc for Authenticate service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var Authenticate_ServiceDesc = grpc.ServiceDesc{
ServiceName: "auth.Authenticate",
HandlerType: (*AuthenticateServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "preLogin",
Handler: _Authenticate_PreLogin_Handler,
},
{
MethodName: "login",
Handler: _Authenticate_Login_Handler,
},
{
MethodName: "logout",
Handler: _Authenticate_Logout_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "v1/auth.proto",
}

@ -14,3 +14,6 @@ plugins:
opt:
- paths=source_relative
- require_unimplemented_servers=true
- plugin: connect-go
out: auto/connect
opt: paths=source_relative

@ -0,0 +1,26 @@
#!/bin/sh
# eg.1 : sh build-image.sh
# eg.2, set image: sh build-image.sh bitbus/paopao-ce
VERSION=`git describe --tags --always | cut -f1 -f2 -d "-"` # eg.: 0.2.5
IMAGE="bitbus/paopao-ce"
if [ -n "$1" ]; then
IMAGE="$1"
fi
if [ -n "$2" ]; then
VERSION="$2"
fi
# build image
docker buildx build \
--build-arg USE_DIST="yes" \
--tag "$IMAGE:${VERSION}" \
--tag "$IMAGE:latest" \
. -f Dockerfile
# push to image rep
# if [ -n "$1" ]; then
# docker push "$IMAGE:${VERSION}"
# docker push "$IMAGE:latest"
# fi

@ -0,0 +1,11 @@
#!/bin/sh
# eg.1 : sh build-image.sh
# eg.2, set tags: sh build-image.sh 'embed go_json'
TAGS='embed go_json'
if [ -n "$1" ]; then
TAGS="$1"
fi
make release CGO_ENABLED=0 TAGS="$TAGS"

@ -8,23 +8,23 @@ App: # APP基础设置项
Server: # 服务设置
RunMode: debug
HttpIp: 0.0.0.0
HttpPort: 8008
HttpPort: 8010
ReadTimeout: 60
WriteTimeout: 60
Features:
Default: ["Base", "MySQL", "Option", "Zinc", "LocalOSS", "LoggerFile", "Friendship", "Deprecated"]
Default: ["Web", "Frontend:EmbedWeb", "Zinc", "LocalOSS", "MySQL", "BigCacheIndex", "LoggerZinc", "Friendship"]
Develop: ["Base", "MySQL", "BigCacheIndex", "Meili", "Sms", "AliOSS", "LoggerMeili", "OSS:Retention"]
Demo: ["Base", "MySQL", "Option", "Zinc", "Sms", "MinIO", "LoggerZinc", "Migration"]
Slim: ["Base", "Sqlite3", "LocalOSS", "LoggerFile", "OSS:TempDir"]
Base: ["Redis", "PhoneBind"]
Docs: ["Docs:OpenAPI"]
Deprecated: ["Deprecated:OldWeb"]
Service: ["Web", "Admin", "SpaceX", "Bot", "LocalOSS", "Mobile", "Frontend:Web", "Fronetend:EmbedWeb", "Docs"]
Service: ["Web", "Admin", "SpaceX", "Bot", "LocalOSS", "Mobile", "Frontend:Web", "Frontend:EmbedWeb", "Docs"]
Option: ["SimpleCacheIndex"]
Sms: "SmsJuhe"
WebServer: # Web服务
HttpIp: 0.0.0.0
HttpPort: 8010
HttpPort: 8008
ReadTimeout: 60
WriteTimeout: 60
AdminServer: # Admin后台运维服务
@ -84,7 +84,7 @@ BigCacheIndex: # 使用BigCache缓存泡泡广场消息流
Logger: # 日志通用配置
Level: debug # 日志级别 panic|fatal|error|warn|info|debug|trace
LoggerFile: # 使用File写日志
SavePath: data/paopao-ce/logs
SavePath: custom/data/paopao-ce/logs
FileName: app
FileExt: .log
LoggerZinc: # 使用Zinc写日志
@ -154,7 +154,7 @@ S3: # Amazon S3 存储配置
Bucket: paopao
Domain:
LocalOSS: # 本地文件OSS存储配置
SavePath: data/paopao-ce/oss
SavePath: custom/data/paopao-ce/oss
Secure: False
Bucket: paopao
Domain: 127.0.0.1:8008
@ -179,9 +179,8 @@ Postgres: # PostgreSQL数据库
SSLMode: disable
TimeZone: Asia/Shanghai
Sqlite3: # Sqlite3数据库
Path: data/sqlite3/paopao-ce.db
Path: custom/data/sqlite3/paopao-ce.db
Redis:
Host: redis:6379
Password:
DB:
InitAddress:
- redis:6379

Binary file not shown.

@ -0,0 +1,9 @@
## 部署站点
PaoPao部署站点信息。
| 名称 | 网址 | 站长 | 备注 |
| ----- | ----- | ----- | ----- |
|泡泡|[www.paopao.info](https://www.paopao.info)|[ROC](https://www.paopao.info/#/user?username=roc 'roc(@paopao.info)')|PaoPao官方站点|
|布里塔|[bulita.cn](https://bulita.cn)|[chendong](https://www.paopao.info/#/user?username=chendong 'chendong(@paopao.info)')|招聘求职等信息|
|提示词社区|[promptser.cn](https://promptser.cn)|[henryspace](https://paopao.info/#/user?username=henryspace 'henryspace(@paopao.info)')|提示词社区|
|iiBiuBiu|[iibiubiu.com](https://iibiubiu.com)|[北野](https://www.paopao.info/#/user?username=alimy 'alimy(@paopao.info)')|开发、测试备用机可以体验最新版本paopao-ce|

@ -11,9 +11,9 @@ services:
MYSQL_RANDOM_ROOT_PASSWORD: yes
volumes:
- ./scripts/paopao-mysql.sql:/docker-entrypoint-initdb.d/paopao.sql
- ./data/mysql/data:/var/lib/mysql
- ./custom/data/mysql/data:/var/lib/mysql
ports:
- 127.0.0.1::3306
- 3306:3306
networks:
- paopao-network
@ -28,15 +28,26 @@ services:
# - 9000:9000
# - 9001:9001
# volumes:
# - ./data/minio/data:/data
# - ./custom/data/minio/data:/data
# networks:
# - paopao-network
# redis:
# image: redis:7.0-alpine
# restart: always
# ports:
# - 6379:6379
# networks:
# - paopao-network
redis:
image: redis:7.0-alpine
image: redis/redis-stack:7.0.6-RC8
restart: always
ports:
- 6379:6379
- 8001:8001
environment:
REDISEARCH_ARGS: "MAXSEARCHRESULTS 5"
networks:
- paopao-network
@ -47,7 +58,7 @@ services:
ports:
- 4080:4080
volumes:
- ./data/zinc/data:/data
- ./custom/data/zinc/data:/data
environment:
ZINC_FIRST_ADMIN_USER: admin
ZINC_FIRST_ADMIN_PASSWORD: admin
@ -56,23 +67,24 @@ services:
- paopao-network
# meili:
# image: getmeili/meilisearch:v0.29.0
# image: getmeili/meilisearch:v1.2
# restart: always
# ports:
# - 7700:7700
# volumes:
# - ./data/meili/data:/meili_data
# - ./custom/data/meili/data:/meili_data
# environment:
# - MEILI_MASTER_KEY=paopao-meilisearch
# networks:
# - paopao-network
# # a ui for managing your meilisearch instances
# uirecord:
# image: bitriory/uirecord:latest
# pyroscope:
# image: pyroscope/pyroscope:latest
# restart: always
# ports:
# - 7701:3000
# - 4040:4040
# command:
# - 'server'
# networks:
# - paopao-network
@ -90,8 +102,7 @@ services:
- paopao-network
backend:
build:
context: .
image: bitbus/paopao-ce:0.3
restart: always
depends_on:
- db
@ -100,7 +111,7 @@ services:
# modify below to reflect your custom configure
volumes:
- ./config.yaml.sample:/app/paopao-ce/config.yaml
- ./data/paopao-ce/data:/app/paopao-ce/data
- ./custom:/app/paopao-ce/custom
ports:
- 8008:8008
networks:

@ -56,13 +56,15 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r
目前支持的功能集合:
| 功能项 | 类别 | 状态 | 备注 |
| ----- | ----- | ----- | ----- |
|`OldWeb` | 子服务 | 稳定(默认) | 开启旧的Web服务 |
|`Web` | 子服务 | WIP | 开启Web服务|
|`Web` | 子服务 | 内测 | 开启Web服务|
|`Admin` | 子服务 | WIP | 开启Admin后台运维服务|
|`SpaceX` | 子服务 | WIP | 开启SpaceX服务|
|`Bot` | 子服务 | WIP | 开启Bot服务|
|`NativeOBS` | 子服务 | WIP | 开启NativeOBS服务|
|`Deprecated:Web` | 子服务 | 稳定 | Deprecated(关闭) OldWeb服务|
|`Docs` | 子服务 | WIP | 开启开发者文档服务|
|`Frontend:Web` | 子服务 | 稳定 | 开启独立前端服务|
|`Frontend:EmbedWeb` | 子服务 | 稳定 | 开启内嵌于后端Web API服务中的前端服务|
|`Deprecated:Web` | 子服务 | 稳定 | 开启旧的Web服务|
|`Gorm` | 数据库 | 稳定(默认) | 使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM默认使用 `Gorm` + `MySQL`组合|
|`Sqlx`| 数据库 | WIP | 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM|
|`MySQL`| 数据库 | 稳定(默认) | 使用MySQL作为数据库|
@ -77,7 +79,7 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r
|`OSS:Retention` | 对象存储 | 内测 |基于对象存储系统的对象过期自动删除特性实现 先创建临时对象再持久化的功能|
|`OSS:TempDir` | 对象存储 | 内测 |基于对象存储系统的对象拷贝/移动特性实现 先创建临时对象再持久化的功能|
|`Redis` | 缓存 | 稳定 | Redis缓存功能 |
|`SimpleCacheIndex` | 缓存 | 稳定 | 提供简单的 广场推文列表 的缓存功能 |
|`SimpleCacheIndex` | 缓存 | Deprecated | 提供简单的 广场推文列表 的缓存功能 |
|`BigCacheIndex` | 缓存 | 稳定(推荐) | 使用[BigCache](https://github.com/allegro/bigcache)缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面 |
|`Zinc` | 搜索 | 稳定(推荐) | 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务 |
|`Meili` | 搜索 | 稳定(推荐) | 基于[Meilisearch](https://github.com/meilisearch/meilisearch)搜索引擎提供推文搜索服务 |
@ -85,11 +87,65 @@ release/paopao-ce --no-default-features --features sqlite3,localoss,loggerfile,r
|`LoggerFile` | 日志 | 稳定 | 使用文件写日志 |
|`LoggerZinc` | 日志 | 稳定(推荐) | 使用[Zinc](https://github.com/zinclabs/zinc)写日志 |
|`LoggerMeili` | 日志 | 内测 | 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志 |
|`Friendship` | 关系模式 | 内测(默认) | 弱关系好友模式,类似微信朋友圈 |
|`Followship` | 关系模式 | WIP | 关注者模式类似Twitter的Follow模式 |
|[`Friendship`](../../docs/proposal/002-关于Friendship功能项的设计.md) | 关系模式 | 内测 | 弱关系好友模式,类似微信朋友圈 |
|[`Followship`](../../docs/proposal/003-关于Followship功能项的设计.md) | 关系模式 | WIP | 关注者模式类似Twitter的Follow模式 |
|[`Lightship`](../../docs/proposal/011-关于Lightship功能项的设计.md) | 关系模式 | 内测(默认) | 开放模式,所有推文都公开可见 |
|`Alipay` | 支付 | 稳定 | 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能 |
|`Sms` | 短信验证 | 稳定 | 开启短信验证码功能,用于手机绑定验证手机是否注册者的;功能如果没有开启,手机绑定时任意短信验证码都可以绑定手机 |
|`Docs:OpenAPI` | 开发文档 | 稳定 | 开启openapi文档功能提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi) |
|`PhoneBind` | 其他 | 稳定 | 手机绑定功能 |
|`Web:DisallowUserRegister` | 功能特性 | 稳定 | 不允许用户注册 |
> 功能项状态详情参考 [features-status](../../../features-status.md).
### 按需添加自定义配置
paopao-ce提供了按需添加配置的机制paopao-ce在internal/conf/config.yaml中内嵌了一份完整的默认配置内嵌的默认配置与自定义配置config.yaml在paopao-ce启动时自动进行了配置项合并自定义的配置(./config.yaml或者./custom/config.yaml)中只需要自定义 运行时 声明Features 的相应配置即可。比如只运行Web 子服务config.yaml可以只包含如下配置(其他配置使用默认值):
```yaml
# file: config.yaml
Features:
Default: ["Sqlite3", "Zinc", "LocalOSS", "BigCacheIndex", "Web"]
WebServer: # Web服务
HttpIp: 0.0.0.0
HttpPort: 8010
ReadTimeout: 60
WriteTimeout: 60
LocalOSS: # 本地文件OSS存储配置
SavePath: data/paopao-ce/oss
Secure: True
Bucket: paopao
Domain: api.paopao.info
Zinc: # Zinc搜索配置
Host: 127.0.0.1:4080
Index: paopao-data
User: admin
Password: admin
Secure: False
```
部署paopao-ce实例时可以按需自定义配置运行时所需的配置项 多个实例部署可以使用不同配置项组合,运行不同的子服务,再通过一个统一的 Proxy(Nginx或云端proxy) 将请求桥接到具体的paopao-ce部署实例。
### 多服务同端口运行
paopao-ce提供的机制是各个子服务(gRPC/RESTful API服务)可以在一个独立端口提供业务服务也可以多个同类型的子服务RESTful API服务 或者 gRPC 服务)共享同一个端口提供服务,比如 Web/Admin/Bot 三个子服务在8010端口提供服务, 只需要配置三个子服务的HttpIp/HttpPort为相同值即可:
```yaml
# file: config.yaml
Features:
Default: ["Sqlite3", "Zinc", "LocalOSS", "BigCacheIndex", "Web", "Admin", "Bot"]
WebServer: # Web服务
HttpIp: 0.0.0.0
HttpPort: 8010
ReadTimeout: 60
WriteTimeout: 60
AdminServer: # Admin后台运维服务
HttpIp: 0.0.0.0
HttpPort: 8010
ReadTimeout: 60
WriteTimeout: 60
BotServer: # Bot服务
HttpIp: 0.0.0.0
HttpPort: 8010
ReadTimeout: 60
WriteTimeout: 60
...
```

@ -0,0 +1,30 @@
Features:
Default: ["Sqlite3", "Zinc", "LocalOSS", "LoggerFile", "BigCacheIndex", "Friendship", "Frontend:EmbedWeb", "Web"]
BigCacheIndex: # 使用BigCache缓存泡泡广场消息流
MaxIndexPage: 1024 # 最大缓存页数必须是2^n, 代表最大同时缓存多少页数据
HardMaxCacheSize: 256 # 最大缓存大小(MB)0表示无限制
WebServer: # Web服务
HttpIp: 0.0.0.0
HttpPort: 8008
ReadTimeout: 60
WriteTimeout: 60
JWT: # 鉴权加密
Secret: 18a6413dc4fe394c66345ebe501b2f26
Issuer: paopao-api
Expire: 86400
Zinc: # Zinc搜索配置
Host: 127.0.0.1:4080
Index: paopao-data
User: admin
Password: admin
Secure: False
LocalOSS: # 本地文件OSS存储配置
SavePath: custom/data/oss
Secure: True
Bucket: paopao
Domain: api.alimy.me
Sqlite3: # Sqlite3数据库
Path: custom/data/sqlite3/paopao-ce.db
Redis:
InitAddress:
- 127.0.0.1:6379

@ -3,3 +3,6 @@
* [0000-讨论样式模版](./0000-讨论样式模版.md "讨论样式模版")
* [0001-FAQs](./0001-FAQs.md "FAQs")
### paopao.info
关于paopao-ce的交流、反馈也可以直接在我们官网[paopao.info](https://www.paopao.info)进行,发布动态时记得加上标签`#paopao-ce`或类似主题相关的标签,方便话题查找。欢迎大家在[paopao.info](https://www.paopao.info)畅快愉悦的交流一起让paopao-ce的用户体验更好、更便捷。

@ -1,6 +1,6 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 000 | 北野 | 2022-11-04 |2022-11-04 | v1.0| 提议 |
| YYMMDDHH | 北野 | 2022-11-04 |2022-11-04 | v1.0| 提议 |
## <我是标题>
---- 这里写简要介绍 ----

@ -1,6 +1,6 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 003| 北野 | 2022-11-04 | 2022-11-21 | v0.1 | 提议 |
| 22110409| 北野 | 2022-11-04 | 2022-11-21 | v0.1 | 提议 |
### 关于Followship功能项的设计
Followship是实现类似Twitter Timeline模式**关注者模型**的时间线信息流广场推文列表的生成将主要与推文时间、用户的关注者相关。Twitter的推文消息流是非常智能的用户体验也非常好这得益于其背后的智能推荐算法以及完善的关注者模型体系当然还有很多其他机制共同作用下的结果。本提按作为一个总纲为paopao-ce引入类似的机制这将是一个持续完善的缓慢过程一切都是为了用户体验用户就是上帝用户需要什么paopao-ce就努力提供什么

@ -1,6 +1,6 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 002| 北野 | 2022-11-04 | 2023-01-04 | v1.0 | 提议 |
| 22110410 | 北野 | 2022-11-04 | 2023-01-04 | v1.0 | 提议 |
### Friendship功能项的设计概要
Friendship功能提供好友间分享推文信息的机制更好的帮助用户建立自己的推文分享小圈子。Friendship本质上想优化的是泡泡广场页面推文列表的生成机制开启功能后推文列表只能获取 `公开/私密/好友` 的推文,每个用户都有属于自己的个性化推文列表。在提供个性化推文列表生成机制的同时,好友体系的建立也顺便帮助用户建立自己的个性化有限范围内的灵魂社交小圈子,只有相互间拥有个性化认同感的用户才能互为好友。

@ -1,6 +1,6 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 001| 北野 | 2022-11-04 | 2022-12-19 | v1.0 | 提议 |
| 22110411 | 北野 | 2022-11-04 | 2023-01-13 | v1.1 | 提议 |
## 概述
paopao-ce是一个清新文艺的微社区提供类似Twiter/微博的推文分享服务。paopao-ce的运营形态有点类似WordPress只不过WordPress是使用PHP语言开发的博客平台提供的是博客服务而paopao-ce提供的是类似Twitter的推文分享服务。paopao-ce 让 **个人或小组织** 可以快速、方便的部署一个提供**推文分享服务**的小站点,在有限范围内形成一个友善的社交小圈子微社区。
@ -37,6 +37,10 @@ paopao-ce目前支持Redis作为缓存存储引擎提供缓存服务请参考
paopao-ce在代码实现上采用 **单体架构模式、分层设计、功能模块化**,架构设计上可能略显保守,但是在使用新技术上却非常积极,比如搜索引擎就采用了近来新星[Zinc](https://github.com/zinclabs/zinc) /[Meilisearch](https://github.com/meilisearch/meilisearch)同时也不排斥各种云端服务包括阿里云、腾讯云、华为云的对象存储服务、关系数据库服务等。paopao-ce始终秉持着 **包容并蓄、能用就上、去繁就简** 的架构思维,努力打造一个能 **稳定运行、代码清晰、功能可扩展** 的开源项目。
![](.assets/006-01.png)
## 从技术探索角度思考
IT世界是非常激动人心的新技术层出不穷在各自领域大展身手、大放异彩。作为开发者的我们首要目标当然是以产品为核心不断的优化服务体验也不吝啬于新技术的采用以达到更好的产品服务质量。新技术或者某种技术本身是需要一个环境来支撑其运行、演进脱离实际环境的技术演进犹如纸上谈兵实际效果是存疑的。开发者在研究一项(新)技术时首先当然是知其然了解其功能特性、适用场景再而知其所以然深入了解其设计原理、知悉其存在的局限等进而知其不以为然通过实践找到技术的最适合场景、知悉其不适合的场景或与其他技术配合使用扬长避短发挥各自的最佳效力以解决具体的事务。这些都是技术探索的通用流程可以看出一项技术的探索从陌生到一知半解再到了如指掌需要一个漫长的过程以及一个技术探索的环境。有些技术的探索确实需要一个具体的环境才能更好的研究与实践比如OBS、Search、Recommended discovery亦或各种云服务的使用、k8s的服务部署等都需要一个具体的环境来进行技术探索。可以说以需求驱动的技术探索也更能推进技术本身的不断演进。
说这么多这就引出了本节所要说的一个观点了paopao-ce不仅仅是作为一个提供推文分享服务的产品也能作为一些技术的探索环境。比如OBS(对象存储服务)、推文搜索服务、推文/用户推荐发现服务、广场推文消息流服务等,都可以作为相应技术领域的技术探索环境,从实践中去检验技术的有效性,更好的推进技术的学习、实践、演进。作为开发者/学习者,也能在理论学习与实际环境中实践(新)技术找到一个平衡,更好、更快的掌握一项(新)技术这也是paopao-ce的另一价值所在。**路漫漫其修远兮,吾将上下而求索**,用我们开发者的话来说,带着 **上下文(环境/需求)** 去探索(新)技术,或能事半功倍、得心应手。
## 从人文角度思考
现在的互联网世界已经非常精彩各种社交媒体平台琳琅满目使用体验也非常友好。每个社交平台都有自己的运营方式都有自己的核心用户群体也有自己的产品灵魂都在不断的进行生态演进。比如Twitter、微博都已经从最初的推文分享服务演进到一个成熟的传媒平台注册用户非常庞大日均访问PV也是一个惊人的数字这就注定了平台的运营思维是多维度考量均衡的结果只能做到让用户群体的大多数人用户体验友好并不能满足所有人的需求。大平台有大平台的运营模式小站点有小站点的维系空间。对于类似Twitter这样的推文分享服务paopao-ce提供一种小站点部署模式采用类似WordPress的运维模式**个人/小组织** 能快速、便捷的拥有一个提供推文分享服务的小站点,以填补那些在大平台下难以享受到的用户体验,享受小圈子内的自由空间。
@ -71,3 +75,6 @@ paopao-ce在代码实现上采用 **单体架构模式、分层设计、功能
#### v1.0(2022-12-19) - 北野
* 补充部分内容
#### v1.1(2023-01-13) - 北野
* 补充 从技术探索角度思考 描述

@ -1,6 +1,6 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 005| 北野 | 2022-11-21 | 2023-01-04 | v1.1 | 提议 |
| 22112109 | 北野 | 2022-11-21 | 2023-01-04 | v1.1 | 提议 |
### 引入go-mir优化后端架构设计
引入[github.com/alimy/mir/v3](https://github.com/alimy/mir)优化后端的架构设计,使得后端代码更具扩展型。

@ -1,6 +1,6 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 006| 北野 | 2022-11-23 | 2022-01-01 | v1.0 | 提议 |
| 22112309 | 北野 | 2022-11-23 | 2022-01-01 | v1.0 | 提议 |
### 关于paopao-ce的结构设计
本文档主要讨论paopao-ce目前的代码结构简要清晰的描述一个**API请求**从 **接受解析->逻辑处理->结果响应**的大概路径帮助开发人员快速了解paopao-ce代码基的基本面更好的融入paopao-ce的开发中做出PR贡献。
@ -63,7 +63,9 @@ RESTful服务与gRPC服务各自有擅长的场景在合适的场景使用最
### 更新记录
#### v0.0(2022-11-23) - 北野
* 初始文档, 先占个位置
#### v0.1(2022-12-23) - 北野
* 添加部分内容
#### v1.0(2023-01-01) - 北野
* 添加部分内容

@ -0,0 +1,47 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 22121409 | 北野 | 2022-12-14 | 2022-01-09 | v1.1 | 提议 |
### 关于Lightship功能项的设计
Lightship(开放模式)功能提供完全公开的推文分享服务,有别于[Friendship](002-关于Friendship功能项的设计.md "关于Friendship功能项的设计")、[Followship](003-关于Followship功能项的设计.md "关于Followship功能项的设计")使用Lightship用户模式部署paopao-ce用户发布的所有推文都是公开可访问的广场推文列表展示的是全站所有公开推文的Timeline Tweets。
### 场景
一般用于非常小的站点,或者推文更新不频繁的站点。
* 推文更新不频繁站点;
* 个人推文站点;
* 单纯想要所有推文公开访问;
### 需求
* 广场推文列表只展示公开可访问推文;
* 推文访问权限只能是 `公开/私密`
### 方案
#### 实现细节
* 广场推文列表只展示公开可访问推文 - 前端/后端
* 推文访问权限只能是 `公开/私密` - 前端/后端
#### 参考实现(PR):
[add Lightship feature support #198](https://github.com/rocboss/paopao-ce/pull/198)
### 疑问
1. 公开模式为什么命名为Lightship
Lightship有灯塔的意思灯塔是为航行船只指明方向的公共设施这里取其公有设施的属性指喻 开放模式下paopao-ce不需要授权公开访问推 文的意思。
1. 如何开启这个功能?
在配置文件config.yaml中的`Features`中添加`Lightship`功能项开启该功能:
```yaml
...
# features中加上 Lightship
Features:
Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "MinIO", "Lightship"]
Base: ["Redis", "PhoneBind"]
...
```
### 更新记录
#### v1.0(2022-12-14) - 北野
* 初始文档
#### v1.1(2022-01-09) - 北野
* 添加参考实现PR信息

@ -0,0 +1,21 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 23011309 | 北野 | 2023-01-13 | 2023-01-13 | v0.0 | 提议 |
### 概述
目前paopao-ce前端/后端 都使用中文提供业务服务暂时还没有提供国际化i18n机制提供国际化的业务服务。本提按提议提过在前端/后端中引入i8n机制以提供国际化业务服务。 本提按建立在[012-优化前端运行时配置获取机制的设计](012-优化前端运行时配置获取机制的设计.md)基础之上。
### 需求
* 提供i18n机制以实现业务服务的国际化 - 前端/后端
### 方案
TODO
### 疑问
1. 为什么要提供这种机制?
TODO
### 更新记录
#### v0.0(2023-01-13) - 北野
* 初始文档, 先占个位置

@ -0,0 +1,28 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 23011310 | 北野 | 2023-01-13 | 2023-01-13 | v0.0 | 提议 |
### 概述
目前的Web前端运行时配置是通过编译时配置[.env](../../web/.env)进行静态配置虽然能满足简单的功能需求但是非常不灵活。本提按提议一种由paopao-ce后端服务控制的前端运行时配置获取机制让前端更灵活的依据运行时配置提供产品服务。
### 场景
前端依据paopao-ce后端服务提供的运行时配置按需提供产品服务也可以扩展到按用户喜好自定义的配置提供产品服务比如用户设置的语言、Theme、功能特性等。
### 需求
* 前端依据运行时配置提供业务服务 - 前端
* 前端在启动时从paopao-ce后端服务获取运行时配置 - 前端/后端
* 用户可以自定义前端运行时配置如语言、Theme、功能特性等 - 前端/后端
* 用户自定义的前端运行时配置可以 创建/更新 - 前端/后端
* 后端服务提供默认前端运行时配置 - 后端
### 方案
TODO
### 疑问
1. 为什么要提供这种机制?
TODO
### 更新记录
#### v0.0(2023-01-13) - 北野
* 初始文档, 先占个位置

@ -0,0 +1,21 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 23020910| 北野 | 2023-02-09 | 2023-02-09 | v0.0 | 提议 |
### 概述
TODO
### 需求
TODO
### 方案
TODO
### 疑问
1. 为什么要引入sqlx/sqlc
TODO
### 更新记录
#### v0.0(2023-02-09) - 北野
* 初始文档, 先占个位置

@ -0,0 +1,25 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 23021310| 北野 | 2023-02-13 | 2023-02-13 | v0.0 | 提议 |
### 概述
TODO
### 需求
TODO
### 方案
TODO
### 疑问
1. 为什么要引入bcrypt
TODO
### 参考文档
* [bcrypt](https://github.com/golang/crypto/blob/master/bcrypt/bcrypt.go)
* [bcrypt module](https://pkg.go.dev/golang.org/x/crypto@v0.6.0/bcrypt)
### 更新记录
#### v0.0(2023-02-13) - 北野
* 初始文档, 先占个位置

@ -0,0 +1,53 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 23021510| 北野 | 2023-02-15 | 2023-02-16 | v1.1 | 提议 |
### 概述
Pyroscope 是一个开源的持续性能剖析平台。它能够帮你:
* 找出源代码中的性能问题和瓶颈
* 解决 CPU 利用率高的问题
* 理解应用程序的调用树call tree
* 追踪随一段时间内变化的情况
### 需求
* 开发环境下启用Pyroscope但是部署环境下禁用。
### 方案
#### 设计要点
* 使用//go:build pyroscope 可选编译app集成Pyroscope功能
* config.yaml中添加`Pyroscope` 功能来启用Pyroscope
#### 设计细节
* 参考实现(PR):
[add Pyroscope support #199](https://github.com/rocboss/paopao-ce/pull/199)
### 疑问
1. 为什么要引入Pyroscope
用于开发环境下对paopao-ce进行性能优化。
2. 如何开启这个功能?
* 构建时将 `pyroscope` 添加到TAGS中:
```sh
make run TAGS='pyroscope'
```
* 在配置文件config.yaml中的`Features`中添加`Pyroscope`功能项开启该功能:
```yaml
...
# features中加上 Friendship
Features:
Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "MinIO", "Pyroscope"]
Base: ["Redis", "PhoneBind"]
...
```
### 参考文档
* [pyroscope](https://github.com/pyroscope-io/pyroscope)
* [pyroscope client](https://github.com/pyroscope-io/client)
### 更新记录
#### v1.0(2023-02-15) - 北野
* 初始文档
#### v1.1(2023-02-16) - 北野
* 添加参考实现

@ -0,0 +1,49 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 23040412| 北野 | 2023-04-04 | 2023-04-04 | v1.0 | 提议 |
### 概述
[Sentry](https://github.com/getsentry/sentry) Sentry is a developer-first error tracking and performance monitoring platform that helps developers see what actually matters, solve quicker, and learn continuously about their applications.
### 需求
* 通过配置文件开启Sentry功能
### 方案
#### 设计要点
* config.yaml中添加`Sentry` 功能来启用Sentry功能
#### 设计细节
* 参考实现(PR):
[add Sentry feature support #258](https://github.com/rocboss/paopao-ce/pull/258)
### 疑问
1. 为什么要引入Sentry
添加一种对paopao-ce的错误追踪与性能检测机制。
2. 如何开启这个功能?
* 在配置文件config.yaml中的`Features`中添加`Sentry`功能项开启该功能:
```yaml
...
# features中加上 Sentry
Features:
Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "MinIO", "Sentry"]
Base: ["Redis", "PhoneBind"]
Sentry:
Sentry: # Sentry配置
Dsn: "http://4ea0af5cd88d4512b7e52070506c80ec@localhost:9000/2"
Debug: True
AttachStacktrace: True
TracesSampleRate: 1.0
AttachLogrus: True # logrus是否附加到Sentry
AttachGin: True # gin是否附加到Sentry
...
```
### 参考文档
* [sentry](https://github.com/getsentry/sentry)
* [self-hosted](https://develop.sentry.dev/self-hosted/)
### 更新记录
#### v1.0(2023-04-04) - 北野
* 初始文档

@ -0,0 +1,30 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 23062120| 北野 | 2023-06-21 | 2023-06-21 | v0.1 | 提议 |
### 概述
目前图片、视频、附件资源的位置信息是使用完整url的形式存储在sql表中也就是对外可取的url链接这就造成这些多媒体资源与一个网站的网址进行了
绑定,如果网站变更网址后,这些媒体资源将访问不了,除非使用原先的网址。
### 需求
* 变更网址不影响图片、视频、附件资源的获取;
* 图片、视频、附件资源的存储位置应该对外透明内部如何存储已经具体的存储位置信息不应该暴露到对外url链接中
* 图片、视频、附件资源的存储位置信息在sql表中应该存储为相对地址
### 方案
#### 设计要点
* 图片、视频、附件资源的相对位置信息存储在sql表中
* 图片、视频、附件资源的对外url地址采用动态生成的方式可以采用服务端生成或者客户端生成的方式或者通过api的参数来自定义
#### 设计细节
TODO
### 疑问
1. 为什么要优化?
解绑网站地址与图片、视频、附件资源的对应关系。
### 更新记录
#### v0.1(2023-06-21) - 北野
* 初始文档

@ -0,0 +1,25 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 23062121| 北野 | 2023-06-21 | 2023-06-21 | v0.1 | 提议 |
### 概述
数据库表的Migration优化。
### 需求
TODO
### 方案
TODO
#### 设计细节
TODO
### 疑问
1. 为什么要优化?
TODO
### 更新记录
#### v0.1(2023-06-21) - 北野
* 初始文档

@ -0,0 +1,67 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 23062905| 北野 | 2023-06-29 | 2023-06-29 | v1.0 | 提议 |
### 概述
使用net/http/pprof获取Profile信息。添加`Pprof`功能特性用于开启PprofServer服务。
### 需求
- 只在开发环境下获取profile信息
- 可以在配置文件中开启获取profile的服务
### 方案
- 添加`Pprof`功能特性
- 添加`PprofServer`服务
#### 设计细节
- 配置文件中添加`PprofServer`项用于配制http server
- 添加`Pprof`功能特性
- 添加`PprofServer`服务
- 使用`//go:build pprof`按需编译profile功能
- `PprofServer` 不能和其他服务共用一个端口
### 疑问
1. 为什么要添加`pprof`功能特性?
使用 net/http/pprof 在线获取CPU profile信息用于 [PGO](https://go.dev/doc/pgo) 编译优化。
2. 如何开启`Pprof`服务?
* 构建时将 `pprof` 添加到TAGS中:
```sh
make run TAGS='pprof'
```
* 在配置文件config.yaml中的`Features`中添加`Pprof`功能项开启该功能:
```yaml
...
# features中加上 Friendship
Features:
Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "MinIO", "Pprof"]
Base: ["Redis", "PhoneBind"]
...
```
3. 常见命令
#### Merging profiles
The pprof tool can merge multiple profiles like this:
```sh
$ go tool pprof -proto a.pprof b.pprof > merged.pprof
```
This merge is effectively a straightforward sum of samples in the input, regardless of wall duration of the profile. As a result, when profiling a small time slice of an application (e.g., a server that runs indefinitely), you likely want to ensure that all profiles have the same wall duration (i.e., all profiles are collected for 30s). Otherwise, profiles with longer wall duration will be overrepresented in the merged profile.
#### look at a 30-second CPU profile:
```sh
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
```
### 参考文档
* [PGO](https://go.dev/doc/pgo)
* [net/http/pprof](https://pkg.go.dev/net/http/pprof)
* [runtime/pprof](https://pkg.go.dev/runtime/pprof)
### 参考实现
- [#327](https://github.com/rocboss/paopao-ce/pull/327)
### 更新记录
#### v1.0(2023-06-20) - 北野
* 初始文档

@ -0,0 +1,38 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| 23062906| 北野 | 2023-06-29 | 2023-06-29 | v1.0 | 提议 |
### 概述
Beginning in Go 1.20, the Go compiler supports profile-guided optimization ([PGO](https://go.dev/doc/pgo)) to further optimize builds.
### 疑问
1. 为什么要添加`pprof`功能特性?
使用 net/http/pprof 在线获取CPU profile信息用于 [PGO](https://go.dev/doc/pgo) 编译优化。
2. 如何开启`pgo`编译优化?
The standard approach is to store a pprof CPU profile with filename default.pgo in the main package directory of the profiled binary, and build with go build -pgo=auto, which will pick up default.pgo files automatically.
3. 常见命令
#### Merging profiles
The pprof tool can merge multiple profiles like this:
```sh
$ go tool pprof -proto a.pprof b.pprof > default.pgo
```
This merge is effectively a straightforward sum of samples in the input, regardless of wall duration of the profile. As a result, when profiling a small time slice of an application (e.g., a server that runs indefinitely), you likely want to ensure that all profiles have the same wall duration (i.e., all profiles are collected for 30s). Otherwise, profiles with longer wall duration will be overrepresented in the merged profile.
#### look at a 30-second CPU profile:
```sh
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
```
### 参考文档
* [PGO](https://go.dev/doc/pgo)
* [net/http/pprof](https://pkg.go.dev/net/http/pprof)
* [runtime/pprof](https://pkg.go.dev/runtime/pprof)
### 更新记录
#### v1.0(2023-06-20) - 北野
* 初始文档

@ -1,6 +1,6 @@
## Draft
* [001-关于paopao-ce的设计定位](001-关于paopao-ce的设计定位.md "关于paopao-ce的设计定位")
* [002-关于Friendship功能项的设计](002-关于Friendship功能项的设计.md "关于Friendship功能项的设计")
* [003-关于Followship功能项的设计](003-关于Followship功能项的设计.md "关于Followship功能项的设计")
* [005-引入go-mir优化后端架构设计](005-引入go-mir优化后端架构设计.md "引入go-mir优化后端架构设计")
* [006-关于paopao-ce的结构设计](006-关于paopao-ce的结构设计.md "关于paopao-ce的结构设计")
* [22110411-关于paopao-ce的设计定位](22110411-关于paopao-ce的设计定位.md "关于paopao-ce的设计定位")
* [22110410-关于Friendship功能项的设计](22110410-关于Friendship功能项的设计.md "关于Friendship功能项的设计")
* [22110409-关于Followship功能项的设计](22110409-关于Followship功能项的设计.md "关于Followship功能项的设计")
* [22112109-引入go-mir优化后端架构设计](22112109-引入go-mir优化后端架构设计.md "引入go-mir优化后端架构设计")
* [22112309-关于paopao-ce的结构设计](22112309-关于paopao-ce的结构设计.md "关于paopao-ce的结构设计")

@ -1,8 +1,8 @@
| 编号 | 作者 | 发表时间 | 变更时间 | 版本 | 状态 |
| ----- | ----- | ----- | ----- | ----- | ----- |
| <编号000> | <作者> | <发表时间> | <变更时间> | <版本号v1.0> | <提议/提案/决议/冻结> |
| <编号YYMMDDHH> | <作者> | <发表时间> | <变更时间> | <版本号v1.0> | <提议/提案/决议/冻结> |
* 编号: 填写提案编号,三位数比如001
* 编号: 填写提案编号,六位数格式为YYMMDDHH年(后两位)+月+日+时
* 作者: 填写发表者。
* 发表时间: 填写首次发表时间,之后保持不变。
* 变更时间: 填写变更时间,首次发表时,变更时间和发表时间一样。

@ -42,7 +42,7 @@
* `Frontend:EmbedWeb` 开启内嵌于后端Web API服务中的前端服务(目前状态: 内测)
* [ ] 提按文档
* [x] 服务初始化逻辑
* `Deprecated:OldWeb` 开启旧的Web服务(目前状态: 内测)
* `Deprecated:OldWeb` 开启旧的Web服务(目前状态: 已弃,不可用)
* [ ] 提按文档
* [x] 服务初始化逻辑
@ -97,7 +97,7 @@
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `SimpleCacheIndex` 提供简单的 广场推文列表 的缓存功能能;
* `SimpleCacheIndex` 提供简单的 广场推文列表 的缓存功能能(目前状态: Deprecated)
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
@ -105,6 +105,10 @@
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* `RedisCacheIndex` 使用Redis缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面(目前状态: 内测阶段,推荐使用)
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
#### 搜索:
* `Zinc` 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务(目前状态: 稳定,推荐使用)
@ -119,6 +123,7 @@
* [ ] 提按文档
* [ ] 接口定义
* [ ] 业务逻辑实现
#### 日志:
* `LoggerFile` 使用文件写日志(目前状态: 稳定);
* [ ] 提按文档
@ -133,15 +138,25 @@
* [x] 接口定义
* [x] 业务逻辑实现
#### 监控:
* `Sentry` 使用Sentry进行错误跟踪与性能监控(目前状态: 内测);
* [x] [提按文档](docs/proposal/23040412-关于使用sentry用于错误追踪与性能检测的设计.md)
* [x] 接口定义
* [x] 业务逻辑实现
#### 关系模式:
* `Friendship` 弱关系好友模式,类似微信朋友圈(目前状态: 开发阶段);
* [x] 提按文档
* `Friendship` 弱关系好友模式,类似微信朋友圈(目前状态: 内测);
* [x] [提按文档](docs/proposal/22110410-关于Friendship功能项的设计.md)
* [x] 接口定义
* [x] 业务逻辑实现
* `Followship` 关注者模式类似Twitter的Follow模式(目前状态: WIP);
* [ ] 提按文档
* [ ] [提按文档](docs/proposal/22110409-关于Followship功能项的设计.md)
* [ ] 接口定义
* [ ] 业务逻辑实现
* `Lightship` 开放模式,所有推文都公开可见(目前状态: 内测、默认);
* [x] [提按文档](docs/proposal/22121409-关于Lightship功能项的设计.md)
* [x] 接口定义
* [x] 业务逻辑实现
### 支付:
* `Alipay` 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能;
@ -160,13 +175,27 @@
* [x] 业务逻辑实现
### 开发文档:
* `Docs:OpenAPI` 开启openapi文档功能提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi)
* `Docs:OpenAPI` 开启openapi文档功能提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi);
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* [x] 业务逻辑实现
### 性能优化
* [`Pyroscope`](docs/proposal/23021510-关于使用pyroscope用于性能调试的设计.md) 开启Pyroscope功能用于性能调试(目前状态: 内测);
* [x] 提按文档
* [x] 业务逻辑实现
* [`Pprof`](docs/proposal/23062905-添加Pprof功能特性用于获取Profile.md) 开启Pprof功能收集Profile信息(目前状态: 内测);
* [x] 提按文档
* [x] 业务逻辑实现
### 其他:
* `PhoneBind` 手机绑定功能;
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现
* [x] 业务逻辑实现
### 功能特性:
* `Web:DisallowUserRegister` 不允许用户注册;
* [ ] 提按文档
* [x] 接口定义
* [x] 业务逻辑实现

193
go.mod

@ -1,134 +1,143 @@
module github.com/rocboss/paopao-ce
go 1.18
go 1.20
require (
github.com/Masterminds/semver/v3 v3.1.1
github.com/Masterminds/semver/v3 v3.2.1
github.com/afocus/captcha v0.0.0-20191010092841-4bd1f21c8868
github.com/alimy/cfg v0.3.0
github.com/alimy/mir/v3 v3.0.0
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible
github.com/allegro/bigcache/v3 v3.0.2
github.com/bytedance/sonic v1.5.0
github.com/alimy/cfg v0.4.0
github.com/alimy/mir/v4 v4.0.0
github.com/aliyun/aliyun-oss-go-sdk v2.2.8+incompatible
github.com/allegro/bigcache/v3 v3.1.0
github.com/bufbuild/connect-go v1.10.0
github.com/bytedance/sonic v1.9.2
github.com/cockroachdb/errors v1.10.0
github.com/disintegration/imaging v1.6.2
github.com/ethereum/go-ethereum v1.10.16
github.com/fatih/color v1.13.0
github.com/fbsobreira/gotron-sdk v0.0.0-20211102183839-58a64f4da5f4
github.com/gin-contrib/cors v1.3.1
github.com/gin-gonic/gin v1.8.1
github.com/go-redis/redis/v8 v8.11.4
github.com/fatih/color v1.15.0
github.com/getsentry/sentry-go v0.23.0
github.com/gin-contrib/cors v1.4.0
github.com/gin-gonic/gin v1.9.1
github.com/go-resty/resty/v2 v2.7.0
github.com/goccy/go-json v0.9.7
github.com/gofrs/uuid v4.0.0+incompatible
github.com/golang-jwt/jwt/v4 v4.4.2
github.com/goccy/go-json v0.10.2
github.com/gofrs/uuid/v5 v5.0.0
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/golang-migrate/migrate/v4 v4.15.2
github.com/huaweicloud/huaweicloud-sdk-go-obs v3.21.12+incompatible
github.com/huaweicloud/huaweicloud-sdk-go-obs v3.23.4+incompatible
github.com/json-iterator/go v1.1.12
github.com/meilisearch/meilisearch-go v0.21.0
github.com/minio/minio-go/v7 v7.0.45
github.com/sirupsen/logrus v1.9.0
github.com/smartwalle/alipay/v3 v3.1.7
github.com/spf13/viper v1.14.0
github.com/tencentyun/cos-go-sdk-v5 v0.7.35
github.com/meilisearch/meilisearch-go v0.25.0
github.com/minio/minio-go/v7 v7.0.61
github.com/onsi/ginkgo/v2 v2.11.0
github.com/onsi/gomega v1.27.10
github.com/pyroscope-io/client v0.7.1
github.com/redis/rueidis v1.0.14
github.com/sirupsen/logrus v1.9.3
github.com/smartwalle/alipay/v3 v3.2.15
github.com/sourcegraph/conc v0.3.0
github.com/spf13/viper v1.16.0
github.com/tencentyun/cos-go-sdk-v5 v0.7.42
github.com/yinheli/mahonia v0.0.0-20131226213531-0eef680515cc
google.golang.org/grpc v1.50.1
google.golang.org/protobuf v1.28.1
gopkg.in/natefinch/lumberjack.v2 v2.0.0
go.uber.org/automaxprocs v1.5.3
google.golang.org/grpc v1.57.0
google.golang.org/protobuf v1.31.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/resty.v1 v1.12.0
gorm.io/driver/mysql v1.3.4
gorm.io/driver/postgres v1.3.7
gorm.io/driver/sqlite v1.3.4
gorm.io/gorm v1.23.4
gorm.io/plugin/dbresolver v1.1.0
gorm.io/plugin/soft_delete v1.1.0
modernc.org/sqlite v1.17.3
gorm.io/driver/mysql v1.5.1
gorm.io/driver/postgres v1.5.2
gorm.io/driver/sqlite v1.5.2
gorm.io/gorm v1.25.2
gorm.io/plugin/dbresolver v1.4.2
gorm.io/plugin/soft_delete v1.2.1
modernc.org/sqlite v1.25.0
)
require (
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
github.com/btcsuite/btcd v0.22.0-beta // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.10.1 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.12.1 // indirect
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgtype v1.11.0 // indirect
github.com/jackc/pgx/v4 v4.16.1 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.3.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/klauspost/cpuid/v2 v2.1.0 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/lib/pq v1.10.2 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/lib/pq v1.10.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.12 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-sqlite3 v1.14.17 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mozillazg/go-httpheader v0.3.1 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/mozillazg/go-httpheader v0.2.1 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/rs/xid v1.4.0 // indirect
github.com/smartwalle/crypto4go v1.0.2 // indirect
github.com/spf13/afero v1.9.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/pyroscope-io/godeltaprof v0.1.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/smartwalle/ncrypto v1.0.2 // indirect
github.com/smartwalle/ngx v1.0.6 // indirect
github.com/smartwalle/nsign v1.0.8 // indirect
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.37.1-0.20220607072126-8a320890c08d // indirect
github.com/valyala/fasthttp v1.40.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
golang.org/x/sys v0.0.0-20220908164124-27713097b956 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
golang.org/x/tools v0.1.12 // indirect
google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/image v0.0.0-20210216034530-4410531fe030 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.9.3 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/uint128 v1.1.1 // indirect
modernc.org/cc/v3 v3.36.0 // indirect
modernc.org/ccgo/v3 v3.16.6 // indirect
modernc.org/libc v1.16.7 // indirect
modernc.org/mathutil v1.4.1 // indirect
modernc.org/memory v1.1.1 // indirect
modernc.org/opt v0.1.1 // indirect
modernc.org/strutil v1.1.1 // indirect
modernc.org/token v1.0.0 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect
modernc.org/ccgo/v3 v3.16.13 // indirect
modernc.org/libc v1.24.1 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.6.0 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/strutil v1.1.3 // indirect
modernc.org/token v1.0.1 // indirect
)

621
go.sum

File diff suppressed because it is too large Load Diff

@ -0,0 +1,38 @@
package conf
import (
"sync"
"github.com/sirupsen/logrus"
"github.com/smartwalle/alipay/v3"
)
var (
_alipayClient *alipay.Client
_onceAlipay sync.Once
)
func MustAlipayClient() *alipay.Client {
_onceAlipay.Do(func() {
s := AlipaySetting
// 将 key 的验证调整到初始化阶段
client, err := alipay.New(s.AppID, s.PrivateKey, s.InProduction)
if err != nil {
logrus.Fatalf("alipay.New err: %s", err)
}
// 加载应用公钥证书
if err = client.LoadAppPublicCertFromFile(s.AppPublicCertFile); err != nil {
logrus.Fatalf("client.LoadAppPublicCertFromFile err: %s\n", err)
}
// 加载支付宝根证书
if err = client.LoadAliPayRootCertFromFile(s.RootCertFile); err != nil {
logrus.Fatalf("client.LoadAliPayRootCertFromFile err: %s\n", err)
}
// 加载支付宝公钥证书
if err = client.LoadAliPayPublicCertFromFile(s.PublicCertFile); err != nil {
logrus.Fatalf("client.LoadAliPayPublicCertFromFile err: %s\n", err)
}
_alipayClient = client
})
return _alipayClient
}

@ -6,60 +6,61 @@ package conf
import (
"log"
"sync"
"time"
"github.com/alimy/cfg"
)
var (
loggerSetting *LoggerSettingS
loggerFileSetting *LoggerFileSettingS
loggerZincSetting *LoggerZincSettingS
loggerMeiliSetting *LoggerMeiliSettingS
redisSetting *RedisSettingS
loggerSetting *loggerConf
loggerFileSetting *loggerFileConf
loggerZincSetting *loggerZincConf
loggerMeiliSetting *loggerMeiliConf
sentrySetting *sentryConf
redisSetting *redisConf
DatabaseSetting *DatabaseSetingS
MysqlSetting *MySQLSettingS
PostgresSetting *PostgresSettingS
Sqlite3Setting *Sqlite3SettingS
ServerSetting *HttpServerSettingS
WebServerSetting *HttpServerSettingS
AdminServerSetting *HttpServerSettingS
SpaceXServerSetting *HttpServerSettingS
BotServerSetting *HttpServerSettingS
LocalossServerSetting *HttpServerSettingS
FrontendWebSetting *HttpServerSettingS
DocsServerSetting *HttpServerSettingS
MobileServerSetting *GRPCServerSettingS
AppSetting *AppSettingS
CacheIndexSetting *CacheIndexSettingS
SimpleCacheIndexSetting *SimpleCacheIndexSettingS
BigCacheIndexSetting *BigCacheIndexSettingS
SmsJuheSetting *SmsJuheSettings
AlipaySetting *AlipaySettingS
TweetSearchSetting *TweetSearchS
ZincSetting *ZincSettingS
MeiliSetting *MeiliSettingS
ObjectStorage *ObjectStorageS
AliOSSSetting *AliOSSSettingS
COSSetting *COSSettingS
HuaweiOBSSetting *HuaweiOBSSettingS
MinIOSetting *MinIOSettingS
S3Setting *S3SettingS
LocalOSSSetting *LocalOSSSettingS
JWTSetting *JWTSettingS
Mutex *sync.Mutex
PyroscopeSetting *pyroscopeConf
DatabaseSetting *databaseConf
MysqlSetting *mysqlConf
PostgresSetting *postgresConf
Sqlite3Setting *sqlite3Conf
PprofServerSetting *httpServerConf
WebServerSetting *httpServerConf
AdminServerSetting *httpServerConf
SpaceXServerSetting *httpServerConf
BotServerSetting *httpServerConf
LocalossServerSetting *httpServerConf
FrontendWebSetting *httpServerConf
DocsServerSetting *httpServerConf
MobileServerSetting *grpcServerConf
AppSetting *appConf
CacheIndexSetting *cacheIndexConf
SimpleCacheIndexSetting *simpleCacheIndexConf
BigCacheIndexSetting *bigCacheIndexConf
RedisCacheIndexSetting *redisCacheIndexConf
SmsJuheSetting *smsJuheConf
AlipaySetting *alipayConf
TweetSearchSetting *tweetSearchConf
ZincSetting *zincConf
MeiliSetting *meiliConf
ObjectStorage *objectStorageConf
AliOSSSetting *aliOSSConf
COSSetting *cosConf
HuaweiOBSSetting *huaweiOBSConf
MinIOSetting *minioConf
S3Setting *s3Conf
LocalOSSSetting *localossConf
JWTSetting *jwtConf
)
func setupSetting(suite []string, noDefault bool) error {
setting, err := NewSetting()
vp, err := newViper()
if err != nil {
return err
}
// initialize features configure
ss, kv := setting.featuresInfoFrom("Features")
ss, kv := featuresInfoFrom(vp, "Features")
cfg.Initial(ss, kv)
if len(suite) > 0 {
cfg.Use(suite, noDefault)
@ -67,7 +68,7 @@ func setupSetting(suite []string, noDefault bool) error {
objects := map[string]any{
"App": &AppSetting,
"Server": &ServerSetting,
"PprofServer": &PprofServerSetting,
"WebServer": &WebServerSetting,
"AdminServer": &AdminServerSetting,
"SpaceXServer": &SpaceXServerSetting,
@ -79,8 +80,11 @@ func setupSetting(suite []string, noDefault bool) error {
"CacheIndex": &CacheIndexSetting,
"SimpleCacheIndex": &SimpleCacheIndexSetting,
"BigCacheIndex": &BigCacheIndexSetting,
"RedisCacheIndex": &RedisCacheIndexSetting,
"Alipay": &AlipaySetting,
"SmsJuhe": &SmsJuheSetting,
"Pyroscope": &PyroscopeSetting,
"Sentry": &sentrySetting,
"Logger": &loggerSetting,
"LoggerFile": &loggerFileSetting,
"LoggerZinc": &loggerZincSetting,
@ -102,27 +106,30 @@ func setupSetting(suite []string, noDefault bool) error {
"LocalOSS": &LocalOSSSetting,
"S3": &S3Setting,
}
if err = setting.Unmarshal(objects); err != nil {
return err
for k, v := range objects {
err := vp.UnmarshalKey(k, v)
if err != nil {
return err
}
}
JWTSetting.Expire *= time.Second
SimpleCacheIndexSetting.CheckTickDuration *= time.Second
SimpleCacheIndexSetting.ExpireTickDuration *= time.Second
BigCacheIndexSetting.ExpireInSecond *= time.Second
RedisCacheIndexSetting.ExpireInSecond *= time.Second
redisSetting.ConnWriteTimeout *= time.Second
Mutex = &sync.Mutex{}
return nil
}
func Initialize(suite []string, noDefault bool) {
func Initial(suite []string, noDefault bool) {
err := setupSetting(suite, noDefault)
if err != nil {
log.Fatalf("init.setupSetting err: %v", err)
}
setupLogger()
setupDBEngine()
initSentry()
}
func GetOssDomain() string {
@ -154,8 +161,9 @@ func GetOssDomain() string {
}
func RunMode() string {
if !cfg.If("Deprecated:OldWeb") {
return ServerSetting.RunMode
}
return AppSetting.RunMode
}
func UseSentryGin() bool {
return cfg.If("Sentry") && sentrySetting.AttachGin
}

@ -1,49 +1,56 @@
App: # APP基础设置项
RunMode: debug
AttachmentIncomeRate: 0.8
MaxCommentCount: 10
MaxCommentCount: 1000
DefaultContextTimeout: 60
DefaultPageSize: 10
MaxPageSize: 100
Server: # 服务设置
RunMode: debug
HttpIp: 0.0.0.0
HttpPort: 8008
ReadTimeout: 60
WriteTimeout: 60
Features:
Default: []
WebServer: # Web服务
RunMode: debug
HttpIp: 0.0.0.0
HttpPort: 8010
HttpPort: 8008
ReadTimeout: 60
WriteTimeout: 60
AdminServer: # Admin后台运维服务
RunMode: debug
HttpIp: 0.0.0.0
HttpPort: 8014
ReadTimeout: 60
WriteTimeout: 60
SpaceXServer: # SpaceX服务
RunMode: debug
HttpIp: 0.0.0.0
HttpPort: 8012
ReadTimeout: 60
WriteTimeout: 60
BotServer: # Bot服务
RunMode: debug
HttpIp: 0.0.0.0
HttpPort: 8016
ReadTimeout: 60
WriteTimeout: 60
LocalossServer: # Localoss服务
RunMode: debug
HttpIp: 0.0.0.0
HttpPort: 8018
ReadTimeout: 60
WriteTimeout: 60
PprofServer: # Pprof服务
RunMode: debug
HttpIp: 0.0.0.0
HttpPort: 6060
ReadTimeout: 60
WriteTimeout: 60
FrontendWebServer: # Web前端静态资源服务
RunMode: debug
HttpIp: 0.0.0.0
HttpPort: 8006
ReadTimeout: 60
WriteTimeout: 60
DocsServer: # 开发文档服务
RunMode: debug
HttpIp: 0.0.0.0
HttpPort: 8011
ReadTimeout: 60
@ -70,12 +77,28 @@ SimpleCacheIndex: # 缓存泡泡广场消息流
ExpireTickDuration: 300 # 每多少秒后强制过期缓存, 设置为0禁止强制使缓存过期
BigCacheIndex: # 使用BigCache缓存泡泡广场消息流
MaxIndexPage: 1024 # 最大缓存页数必须是2^n, 代表最大同时缓存多少页数据
HardMaxCacheSize: 256 # 最大缓存大小(MB)0表示无限制
Verbose: False # 是否打印cache操作的log
ExpireInSecond: 300 # 多少秒(>0)后强制过期缓存
RedisCacheIndex: # 使用Redis缓存泡泡广场消息流
Verbose: False # 是否打印cache操作的log
ExpireInSecond: 300 # 多少秒(>0)后强制过期缓存
Pyroscope: # Pyroscope配置
AppName: "paopao-ce" # application name
Endpoint: "http://localhost:4040" # Pyroscope server address
AuthToken: # Pyroscope authentication token
Logger: none # Pyroscope logger (standard | logrus | none)
Sentry: # Sentry配置
Dsn: "http://4ea0af5cd88d4512b7e52070506c80ec@localhost:9000/2"
Debug: True
AttachStacktrace: True
TracesSampleRate: 1.0
AttachLogrus: True # logrus是否附加到Sentry
AttachGin: True # gin是否附加到Sentry
Logger: # 日志通用配置
Level: debug # 日志级别 panic|fatal|error|warn|info|debug|trace
LoggerFile: # 使用File写日志
SavePath: data/paopao-ce/logs
SavePath: custom/data/paopao-ce/logs
FileName: app
FileExt: .log
LoggerZinc: # 使用Zinc写日志
@ -145,7 +168,7 @@ S3: # Amazon S3 存储配置
Bucket: paopao
Domain:
LocalOSS: # 本地文件OSS存储配置
SavePath: data/paopao-ce/oss
SavePath: custom/data/paopao-ce/oss
Secure: False
Bucket: paopao
Domain: 127.0.0.1:8008
@ -165,14 +188,18 @@ Postgres: # PostgreSQL数据库
User: paopao
Password: paopao
DBName: paopao
Schema: public
Host: localhost
Port: 5432
SSLMode: disable
TimeZone: Asia/Shanghai
ApplicationName:
Sqlite3: # Sqlite3数据库
Path: data/sqlite3/paopao-ce.db
Path: custom/data/sqlite3/paopao-ce.db
Redis:
Host: redis:6379
Password:
DB:
InitAddress:
- redis:6379
Username:
Password:
SelectDB:
ConnWriteTimeout: 60 # 连接写超时时间 多少秒 默认 60秒

@ -1,94 +1,68 @@
// Copyright 2022 ROC. All rights reserved.
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package conf
import (
"database/sql"
"sync"
"time"
"github.com/alimy/cfg"
"github.com/go-redis/redis/v8"
"github.com/sirupsen/logrus"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/schema"
"gorm.io/plugin/dbresolver"
)
var (
db *gorm.DB
Redis *redis.Client
once sync.Once
_sqldb *sql.DB
_onceSql sync.Once
)
func MustGormDB() *gorm.DB {
once.Do(func() {
const (
TableAnouncement = "user"
TableAnouncementContent = "anouncement_content"
TableAttachment = "attachment"
TableCaptcha = "captcha"
TableComment = "comment"
TableCommentContent = "comment_content"
TableCommentReply = "comment_reply"
TableContact = "contact"
TableContactGroup = "contact_group"
TableMessage = "message"
TablePost = "post"
TablePostAttachmentBill = "post_attachment_bill"
TablePostCollection = "post_collection"
TablePostContent = "post_content"
TablePostStar = "post_star"
TableTag = "tag"
TableUser = "user"
TableWalletRecharge = "wallet_recharge"
TableWalletStatement = "wallet_statement"
)
type TableNameMap map[string]string
func MustSqlDB() *sql.DB {
_onceSql.Do(func() {
var err error
if db, err = newDBEngine(); err != nil {
logrus.Fatalf("new gorm db failed: %s", err)
if _, _sqldb, err = newSqlDB(); err != nil {
logrus.Fatalf("new sql db failed: %s", err)
}
})
return db
return _sqldb
}
func newDBEngine() (*gorm.DB, error) {
newLogger := logger.New(
logrus.StandardLogger(), // io writer日志输出的目标前缀和日志包含的内容
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: DatabaseSetting.logLevel(), // 日志级别
IgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound记录未找到错误
Colorful: false, // 禁用彩色打印
},
)
config := &gorm.Config{
Logger: newLogger,
NamingStrategy: schema.NamingStrategy{
TablePrefix: DatabaseSetting.TablePrefix,
SingularTable: true,
},
}
plugin := dbresolver.Register(dbresolver.Config{}).
SetConnMaxIdleTime(time.Hour).
SetConnMaxLifetime(24 * time.Hour).
SetMaxIdleConns(MysqlSetting.MaxIdleConns).
SetMaxOpenConns(MysqlSetting.MaxOpenConns)
var (
db *gorm.DB
err error
)
func newSqlDB() (driver string, db *sql.DB, err error) {
if cfg.If("MySQL") {
logrus.Debugln("use MySQL as db")
if db, err = gorm.Open(mysql.Open(MysqlSetting.Dsn()), config); err == nil {
db.Use(plugin)
}
} else if cfg.If("Postgres") {
logrus.Debugln("use PostgreSQL as db")
db, err = gorm.Open(postgres.Open(PostgresSetting.Dsn()), config)
driver = "mysql"
db, err = sql.Open(driver, MysqlSetting.Dsn())
} else if cfg.If("PostgreSQL") || cfg.If("Postgres") {
driver = "pgx"
db, err = sql.Open(driver, PostgresSetting.Dsn())
} else if cfg.If("Sqlite3") {
logrus.Debugf("use Sqlite3 as db path:%s sqlite3InCgoEnabled:%t", Sqlite3Setting.Path, sqlite3InCgoEnabled)
db, err = gormOpenSqlite3(config)
driver, db, err = OpenSqlite3()
} else {
logrus.Debugln("use default of MySQL as db")
if db, err = gorm.Open(mysql.Open(MysqlSetting.Dsn()), config); err == nil {
db.Use(plugin)
}
driver = "mysql"
db, err = sql.Open(driver, MysqlSetting.Dsn())
}
return db, err
}
func setupDBEngine() {
Redis = redis.NewClient(&redis.Options{
Addr: redisSetting.Host,
Password: redisSetting.Password,
DB: redisSetting.DB,
})
return
}

@ -18,8 +18,9 @@ const (
sqlite3InCgoEnabled = true
)
func OpenSqlite3() (*sql.DB, error) {
return sql.Open("sqlite3", Sqlite3Setting.Dsn("sqlite3"))
func OpenSqlite3() (string, *sql.DB, error) {
db, err := sql.Open("sqlite3", Sqlite3Setting.Dsn("sqlite3"))
return "sqlite3", db, err
}
func gormOpenSqlite3(opts ...gorm.Option) (*gorm.DB, error) {

@ -0,0 +1,84 @@
// 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
import (
"sync"
"time"
"github.com/alimy/cfg"
"github.com/sirupsen/logrus"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/schema"
"gorm.io/plugin/dbresolver"
)
var (
_gormdb *gorm.DB
_onceGorm sync.Once
)
func MustGormDB() *gorm.DB {
_onceGorm.Do(func() {
var err error
if _gormdb, err = newGormDB(); err != nil {
logrus.Fatalf("new gorm db failed: %s", err)
}
})
return _gormdb
}
func newGormDB() (*gorm.DB, error) {
newLogger := logger.New(
logrus.StandardLogger(), // io writer日志输出的目标前缀和日志包含的内容
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: DatabaseSetting.logLevel(), // 日志级别
IgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound记录未找到错误
Colorful: false, // 禁用彩色打印
},
)
config := &gorm.Config{
Logger: newLogger,
NamingStrategy: schema.NamingStrategy{
TablePrefix: DatabaseSetting.TablePrefix,
SingularTable: true,
},
}
plugin := dbresolver.Register(dbresolver.Config{}).
SetConnMaxIdleTime(time.Hour).
SetConnMaxLifetime(24 * time.Hour).
SetMaxIdleConns(MysqlSetting.MaxIdleConns).
SetMaxOpenConns(MysqlSetting.MaxOpenConns)
var (
db *gorm.DB
err error
)
if cfg.If("MySQL") {
logrus.Debugln("use MySQL as db")
if db, err = gorm.Open(mysql.Open(MysqlSetting.Dsn()), config); err == nil {
db.Use(plugin)
}
} else if cfg.If("Postgres") {
logrus.Debugln("use PostgreSQL as db")
db, err = gorm.Open(postgres.Open(PostgresSetting.Dsn()), config)
} else if cfg.If("Sqlite3") {
logrus.Debugf("use Sqlite3 as db path:%s sqlite3InCgoEnabled:%t", Sqlite3Setting.Path, sqlite3InCgoEnabled)
db, err = gormOpenSqlite3(config)
} else {
logrus.Debugln("use default of MySQL as db")
if db, err = gorm.Open(mysql.Open(MysqlSetting.Dsn()), config); err == nil {
db.Use(plugin)
}
}
return db, err
}

@ -19,8 +19,9 @@ const (
sqlite3InCgoEnabled = false
)
func OpenSqlite3() (*sql.DB, error) {
return sql.Open("sqlite", Sqlite3Setting.Dsn("sqlite"))
func OpenSqlite3() (string, *sql.DB, error) {
db, err := sql.Open("sqlite", Sqlite3Setting.Dsn("sqlite"))
return "sqlite", db, err
}
func gormOpenSqlite3(opts ...gorm.Option) (*gorm.DB, error) {

@ -6,8 +6,11 @@ package conf
import (
"io"
"time"
"github.com/alimy/cfg"
"github.com/getsentry/sentry-go"
sentrylogrus "github.com/getsentry/sentry-go/logrus"
"github.com/sirupsen/logrus"
"gopkg.in/natefinch/lumberjack.v2"
)
@ -42,3 +45,16 @@ func setupLogger() {
},
})
}
func setupSentryLogrus(opts sentry.ClientOptions) {
// Send only ERROR and higher level logs to Sentry
sentryLevels := []logrus.Level{logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel}
sentryHook, err := sentrylogrus.New(sentryLevels, opts)
if err != nil {
panic(err)
}
logrus.AddHook(sentryHook)
// Flushes before calling os.Exit(1) when using logger.Fatal
// (else all defers are not called, and Sentry does not have time to send the event)
logrus.RegisterExitHandler(func() { sentryHook.Flush(5 * time.Second) })
}

@ -0,0 +1,34 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package conf
import (
"log"
"sync"
"github.com/redis/rueidis"
)
var (
_redisClient rueidis.Client
_onceRedis sync.Once
)
func MustRedisClient() rueidis.Client {
_onceRedis.Do(func() {
client, err := rueidis.NewClient(rueidis.ClientOption{
InitAddress: redisSetting.InitAddress,
Username: redisSetting.Username,
Password: redisSetting.Password,
SelectDB: redisSetting.SelectDB,
ConnWriteTimeout: redisSetting.ConnWriteTimeout,
})
if err != nil {
log.Fatalf("create a redis client failed: %s", err)
}
_redisClient = client
})
return _redisClient
}

@ -0,0 +1,35 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package conf
import (
"time"
"github.com/alimy/cfg"
"github.com/getsentry/sentry-go"
"github.com/rocboss/paopao-ce/pkg/version"
)
func initSentry() {
cfg.Be("Sentry", func() {
opts := sentry.ClientOptions{
Dsn: sentrySetting.Dsn,
Debug: sentrySetting.Debug,
AttachStacktrace: sentrySetting.AttachStacktrace,
TracesSampleRate: sentrySetting.TracesSampleRate,
}
_ = sentry.Init(opts)
if sentrySetting.AttachLogrus {
setupSentryLogrus(opts)
}
sentry.WithScope(func(scope *sentry.Scope) {
scope.SetExtras(map[string]any{
"version": version.VersionInfo(),
"time": time.Now().Local(),
})
sentry.CaptureMessage("paopao-ce sentry works!")
})
})
}

@ -1,38 +1,52 @@
// Copyright 2022 ROC. All rights reserved.
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package conf
import (
"embed"
"bytes"
_ "embed"
"fmt"
"strings"
"time"
"github.com/pyroscope-io/client/pyroscope"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
"gorm.io/gorm/logger"
)
//go:embed config.yaml
var files embed.FS
var configBytes []byte
type Setting struct {
vp *viper.Viper
type pyroscopeConf struct {
AppName string
Endpoint string
AuthToken string
Logger string
}
type sentryConf struct {
Dsn string
Debug bool
AttachStacktrace bool
TracesSampleRate float64
AttachLogrus bool
AttachGin bool
}
type LoggerSettingS struct {
type loggerConf struct {
Level string
}
type LoggerFileSettingS struct {
type loggerFileConf struct {
SavePath string
FileName string
FileExt string
}
type LoggerZincSettingS struct {
type loggerZincConf struct {
Host string
Index string
User string
@ -40,7 +54,7 @@ type LoggerZincSettingS struct {
Secure bool
}
type LoggerMeiliSettingS struct {
type loggerMeiliConf struct {
Host string
Index string
ApiKey string
@ -49,7 +63,7 @@ type LoggerMeiliSettingS struct {
MinWorker int
}
type HttpServerSettingS struct {
type httpServerConf struct {
RunMode string
HttpIp string
HttpPort string
@ -57,12 +71,12 @@ type HttpServerSettingS struct {
WriteTimeout time.Duration
}
type GRPCServerSettingS struct {
type grpcServerConf struct {
Host string
Port string
}
type AppSettingS struct {
type appConf struct {
RunMode string
MaxCommentCount int64
AttachmentIncomeRate float64
@ -71,24 +85,30 @@ type AppSettingS struct {
MaxPageSize int
}
type CacheIndexSettingS struct {
type cacheIndexConf struct {
MaxUpdateQPS int
MinWorker int
}
type SimpleCacheIndexSettingS struct {
type simpleCacheIndexConf struct {
MaxIndexSize int
CheckTickDuration time.Duration
ExpireTickDuration time.Duration
}
type BigCacheIndexSettingS struct {
MaxIndexPage int
type bigCacheIndexConf struct {
MaxIndexPage int
HardMaxCacheSize int
ExpireInSecond time.Duration
Verbose bool
}
type redisCacheIndexConf struct {
ExpireInSecond time.Duration
Verbose bool
}
type AlipaySettingS struct {
type alipayConf struct {
AppID string
PrivateKey string
RootCertFile string
@ -97,19 +117,19 @@ type AlipaySettingS struct {
InProduction bool
}
type SmsJuheSettings struct {
type smsJuheConf struct {
Gateway string
Key string
TplID string
TplVal string
}
type TweetSearchS struct {
type tweetSearchConf struct {
MaxUpdateQPS int
MinWorker int
}
type ZincSettingS struct {
type zincConf struct {
Host string
Index string
User string
@ -117,19 +137,19 @@ type ZincSettingS struct {
Secure bool
}
type MeiliSettingS struct {
type meiliConf struct {
Host string
Index string
ApiKey string
Secure bool
}
type DatabaseSetingS struct {
type databaseConf struct {
TablePrefix string
LogLevel string
}
type MySQLSettingS struct {
type mysqlConf struct {
UserName string
Password string
Host string
@ -140,18 +160,18 @@ type MySQLSettingS struct {
MaxOpenConns int
}
type PostgresSettingS map[string]string
type postgresConf map[string]string
type Sqlite3SettingS struct {
type sqlite3Conf struct {
Path string
}
type ObjectStorageS struct {
type objectStorageConf struct {
RetainInDays int
TempDir string
}
type MinIOSettingS struct {
type minioConf struct {
AccessKey string
SecretKey string
Secure bool
@ -160,7 +180,7 @@ type MinIOSettingS struct {
Domain string
}
type S3SettingS struct {
type s3Conf struct {
AccessKey string
SecretKey string
Secure bool
@ -169,7 +189,7 @@ type S3SettingS struct {
Domain string
}
type AliOSSSettingS struct {
type aliOSSConf struct {
AccessKeyID string
AccessKeySecret string
Endpoint string
@ -177,7 +197,7 @@ type AliOSSSettingS struct {
Domain string
}
type COSSettingS struct {
type cosConf struct {
SecretID string
SecretKey string
Region string
@ -185,7 +205,7 @@ type COSSettingS struct {
Domain string
}
type HuaweiOBSSettingS struct {
type huaweiOBSConf struct {
AccessKey string
SecretKey string
Endpoint string
@ -193,92 +213,36 @@ type HuaweiOBSSettingS struct {
Domain string
}
type LocalOSSSettingS struct {
type localossConf struct {
SavePath string
Secure bool
Bucket string
Domain string
}
type RedisSettingS struct {
Host string
Password string
DB int
type redisConf struct {
InitAddress []string
Username string
Password string
SelectDB int
ConnWriteTimeout time.Duration
}
type JWTSettingS struct {
type jwtConf struct {
Secret string
Issuer string
Expire time.Duration
}
func NewSetting() (*Setting, error) {
cfgFile, err := files.Open("config.yaml")
if err != nil {
return nil, err
}
defer cfgFile.Close()
vp := viper.New()
vp.SetConfigName("config")
vp.AddConfigPath(".")
vp.AddConfigPath("custom/")
vp.SetConfigType("yaml")
if err = vp.ReadConfig(cfgFile); err != nil {
return nil, err
}
if err = vp.MergeInConfig(); err != nil {
return nil, err
}
return &Setting{vp}, nil
}
func (s *Setting) ReadSection(k string, v any) error {
err := s.vp.UnmarshalKey(k, v)
if err != nil {
return err
}
return nil
}
func (s *Setting) Unmarshal(objects map[string]any) error {
for k, v := range objects {
err := s.vp.UnmarshalKey(k, v)
if err != nil {
return err
}
}
return nil
}
func (s *Setting) featuresInfoFrom(k string) (map[string][]string, map[string]string) {
sub := s.vp.Sub(k)
keys := sub.AllKeys()
suites := make(map[string][]string)
kv := make(map[string]string, len(keys))
for _, key := range sub.AllKeys() {
val := sub.Get(key)
switch v := val.(type) {
case string:
kv[key] = v
case []any:
suites[key] = sub.GetStringSlice(key)
}
}
return suites, kv
}
func (s *HttpServerSettingS) GetReadTimeout() time.Duration {
func (s *httpServerConf) GetReadTimeout() time.Duration {
return s.ReadTimeout * time.Second
}
func (s *HttpServerSettingS) GetWriteTimeout() time.Duration {
func (s *httpServerConf) GetWriteTimeout() time.Duration {
return s.WriteTimeout * time.Second
}
func (s *MySQLSettingS) Dsn() string {
func (s *mysqlConf) Dsn() string {
return fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=%s&parseTime=%t&loc=Local",
s.UserName,
s.Password,
@ -289,17 +253,27 @@ func (s *MySQLSettingS) Dsn() string {
)
}
func (s PostgresSettingS) Dsn() string {
func (s postgresConf) Dsn() string {
var params []string
for k, v := range s {
if len(v) > 0 {
params = append(params, strings.ToLower(k)+"="+v)
if len(v) == 0 {
continue
}
lk := strings.ToLower(k)
tv := strings.Trim(v, " ")
switch lk {
case "schema":
params = append(params, "search_path="+tv)
case "applicationname":
params = append(params, "application_name="+tv)
default:
params = append(params, lk+"="+tv)
}
}
return strings.Join(params, " ")
}
func (s *Sqlite3SettingS) Dsn(driverName string) string {
func (s *sqlite3Conf) Dsn(driverName string) string {
pragmas := "_foreign_keys=1&_journal_mode=WAL&_synchronous=NORMAL&_busy_timeout=8000"
if driverName == "sqlite" {
pragmas = "_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)&_pragma=synchronous(NORMAL)&_pragma=busy_timeout(8000)&_pragma=journal_size_limit(100000000)"
@ -307,7 +281,7 @@ func (s *Sqlite3SettingS) Dsn(driverName string) string {
return fmt.Sprintf("file:%s?%s", s.Path, pragmas)
}
func (s *DatabaseSetingS) logLevel() logger.LogLevel {
func (s *databaseConf) logLevel() logger.LogLevel {
switch strings.ToLower(s.LogLevel) {
case "silent":
return logger.Silent
@ -322,7 +296,36 @@ func (s *DatabaseSetingS) logLevel() logger.LogLevel {
}
}
func (s *LoggerSettingS) logLevel() logrus.Level {
func (s *databaseConf) TableNames() (res TableNameMap) {
tableNames := []string{
TableAnouncement,
TableAnouncementContent,
TableAttachment,
TableCaptcha,
TableComment,
TableCommentContent,
TableCommentReply,
TableContact,
TableContactGroup,
TableMessage,
TablePost,
TablePostAttachmentBill,
TablePostCollection,
TablePostContent,
TablePostStar,
TableTag,
TableUser,
TableWalletRecharge,
TableWalletStatement,
}
res = make(TableNameMap, len(tableNames))
for _, name := range tableNames {
res[name] = s.TablePrefix + name
}
return
}
func (s *loggerConf) logLevel() logrus.Level {
switch strings.ToLower(s.Level) {
case "panic":
return logrus.PanicLevel
@ -343,15 +346,15 @@ func (s *LoggerSettingS) logLevel() logrus.Level {
}
}
func (s *LoggerZincSettingS) Endpoint() string {
func (s *loggerZincConf) Endpoint() string {
return endpoint(s.Host, s.Secure)
}
func (s *LoggerMeiliSettingS) Endpoint() string {
func (s *loggerMeiliConf) Endpoint() string {
return endpoint(s.Host, s.Secure)
}
func (s *LoggerMeiliSettingS) minWork() int {
func (s *loggerMeiliConf) minWork() int {
if s.MinWorker < 5 {
return 5
} else if s.MinWorker > 100 {
@ -360,7 +363,7 @@ func (s *LoggerMeiliSettingS) minWork() int {
return s.MinWorker
}
func (s *LoggerMeiliSettingS) maxLogBuffer() int {
func (s *loggerMeiliConf) maxLogBuffer() int {
if s.MaxLogBuffer < 10 {
return 10
} else if s.MaxLogBuffer > 1000 {
@ -369,18 +372,28 @@ func (s *LoggerMeiliSettingS) maxLogBuffer() int {
return s.MaxLogBuffer
}
func (s *ObjectStorageS) TempDirSlash() string {
func (s *objectStorageConf) TempDirSlash() string {
return strings.Trim(s.TempDir, " /") + "/"
}
func (s *ZincSettingS) Endpoint() string {
func (s *zincConf) Endpoint() string {
return endpoint(s.Host, s.Secure)
}
func (s *MeiliSettingS) Endpoint() string {
func (s *meiliConf) Endpoint() string {
return endpoint(s.Host, s.Secure)
}
func (s *pyroscopeConf) GetLogger() (logger pyroscope.Logger) {
switch strings.ToLower(s.Logger) {
case "standard":
logger = pyroscope.StandardLogger
case "logrus":
logger = logrus.StandardLogger()
}
return
}
func endpoint(host string, secure bool) string {
schema := "http"
if secure {
@ -388,3 +401,37 @@ func endpoint(host string, secure bool) string {
}
return schema + "://" + host
}
func newViper() (*viper.Viper, error) {
vp := viper.New()
vp.SetConfigName("config")
vp.AddConfigPath(".")
vp.AddConfigPath("custom/")
vp.SetConfigType("yaml")
err := vp.ReadConfig(bytes.NewReader(configBytes))
if err != nil {
return nil, err
}
if err = vp.MergeInConfig(); err != nil {
return nil, err
}
return vp, nil
}
func featuresInfoFrom(vp *viper.Viper, k string) (map[string][]string, map[string]string) {
sub := vp.Sub(k)
keys := sub.AllKeys()
suites := make(map[string][]string)
kv := make(map[string]string, len(keys))
for _, key := range sub.AllKeys() {
val := sub.Get(key)
switch v := val.(type) {
case string:
kv[key] = v
case []any:
suites[key] = sub.GetStringSlice(key)
}
}
return suites, kv
}

@ -5,119 +5,13 @@
package core
import (
"github.com/rocboss/paopao-ce/pkg/types"
"github.com/rocboss/paopao-ce/internal/core/ms"
)
const (
ActRegisterUser act = iota
ActCreatePublicTweet
ActCreatePublicAttachment
ActCreatePublicPicture
ActCreatePublicVideo
ActCreatePrivateTweet
ActCreatePrivateAttachment
ActCreatePrivatePicture
ActCreatePrivateVideo
ActCreateFriendTweet
ActCreateFriendAttachment
ActCreateFriendPicture
ActCreateFriendVideo
ActCreatePublicComment
ActCreatePublicPicureComment
ActCreateFriendComment
ActCreateFriendPicureComment
ActCreatePrivateComment
ActCreatePrivatePicureComment
ActStickTweet
ActTopTweet
ActLockTweet
ActVisibleTweet
ActDeleteTweet
ActCreateActivationCode
)
type (
act uint8
FriendFilter map[int64]types.Empty
FriendSet map[string]types.Empty
Action struct {
Act act
UserId int64
}
)
func (f FriendFilter) IsFriend(userId int64) bool {
_, yeah := f[userId]
return yeah
}
// IsAllow default true if user is admin
func (a act) IsAllow(user *User, userId int64, isFriend bool, isActivation bool) bool {
if user.IsAdmin {
return true
}
if user.ID == userId && isActivation {
switch a {
case ActCreatePublicTweet,
ActCreatePublicAttachment,
ActCreatePublicPicture,
ActCreatePublicVideo,
ActCreatePrivateTweet,
ActCreatePrivateAttachment,
ActCreatePrivatePicture,
ActCreatePrivateVideo,
ActCreateFriendTweet,
ActCreateFriendAttachment,
ActCreateFriendPicture,
ActCreateFriendVideo,
ActCreatePrivateComment,
ActCreatePrivatePicureComment,
ActStickTweet,
ActLockTweet,
ActVisibleTweet,
ActDeleteTweet:
return true
}
}
if user.ID == userId && !isActivation {
switch a {
case ActCreatePrivateTweet,
ActCreatePrivateComment,
ActStickTweet,
ActLockTweet,
ActDeleteTweet:
return true
}
}
if isFriend && isActivation {
switch a {
case ActCreatePublicComment,
ActCreatePublicPicureComment,
ActCreateFriendComment,
ActCreateFriendPicureComment:
return true
}
}
if !isFriend && isActivation {
switch a {
case ActCreatePublicComment,
ActCreatePublicPicureComment:
return true
}
}
return false
}
// AuthorizationManageService 授权管理服务
type AuthorizationManageService interface {
IsAllow(user *User, action *Action) bool
BeFriendFilter(userId int64) FriendFilter
IsAllow(user *ms.User, action *ms.Action) bool
BeFriendFilter(userId int64) ms.FriendFilter
BeFriendIds(userId int64) ([]int64, error)
MyFriendSet(userId int64) FriendSet
MyFriendSet(userId int64) ms.FriendSet
}

@ -5,6 +5,10 @@
package core
import (
"context"
"github.com/rocboss/paopao-ce/internal/core/cs"
"github.com/rocboss/paopao-ce/internal/core/ms"
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
@ -24,6 +28,11 @@ type IndexAction struct {
Post *dbr.Post
}
type IndexActionA struct {
Act IdxAct
Tweet *cs.TweetInfo
}
func (a IdxAct) String() string {
switch a {
case IdxActNop:
@ -43,16 +52,48 @@ func (a IdxAct) String() string {
}
}
func NewIndexAction(act IdxAct, post *dbr.Post) *IndexAction {
func NewIndexAction(act IdxAct, post *ms.Post) *IndexAction {
return &IndexAction{
Act: act,
Post: post,
}
}
func NewIndexActionA(act IdxAct, tweet *cs.TweetInfo) *IndexActionA {
return &IndexActionA{
Act: act,
Tweet: tweet,
}
}
// CacheIndexService cache index service interface
type CacheIndexService interface {
IndexPostsService
SendAction(act IdxAct, post *dbr.Post)
}
// CacheIndexServantA cache index service interface
type CacheIndexServantA interface {
IndexPostsServantA
SendAction(act IdxAct, tweet *cs.TweetInfo)
}
// RedisCache memory cache by Redis
type RedisCache interface {
SetPushToSearchJob(ctx context.Context) error
DelPushToSearchJob(ctx context.Context) error
SetImgCaptcha(ctx context.Context, id string, value string) error
GetImgCaptcha(ctx context.Context, id string) (string, error)
DelImgCaptcha(ctx context.Context, id string) error
GetCountSmsCaptcha(ctx context.Context, phone string) (int64, error)
IncrCountSmsCaptcha(ctx context.Context, phone string) error
GetCountLoginErr(ctx context.Context, id int64) (int64, error)
DelCountLoginErr(ctx context.Context, id int64) error
IncrCountLoginErr(ctx context.Context, id int64) error
GetCountWhisper(ctx context.Context, uid int64) (int64, error)
IncrCountWhisper(ctx context.Context, uid int64) error
SetRechargeStatus(ctx context.Context, tradeNo string) error
DelRechargeStatus(ctx context.Context, tradeNo string) error
}

@ -5,32 +5,30 @@
package core
import (
"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
"github.com/rocboss/paopao-ce/internal/core/cs"
"github.com/rocboss/paopao-ce/internal/core/ms"
)
// CommentService 评论检索服务
type CommentService interface {
GetComments(conditions *ConditionsT, offset, limit int) ([]*Comment, error)
GetCommentByID(id int64) (*Comment, error)
GetCommentCount(conditions *ConditionsT) (int64, error)
GetCommentReplyByID(id int64) (*CommentReply, error)
GetCommentContentsByIDs(ids []int64) ([]*CommentContent, error)
GetCommentRepliesByID(ids []int64) ([]*CommentReplyFormated, error)
GetComments(conditions *ms.ConditionsT, offset, limit int) ([]*ms.Comment, error)
GetCommentByID(id int64) (*ms.Comment, error)
GetCommentCount(conditions *ms.ConditionsT) (int64, error)
GetCommentReplyByID(id int64) (*ms.CommentReply, error)
GetCommentContentsByIDs(ids []int64) ([]*ms.CommentContent, error)
GetCommentRepliesByID(ids []int64) ([]*ms.CommentReplyFormated, error)
GetCommentThumbsMap(userId int64, tweetId int64) (cs.CommentThumbsMap, cs.CommentThumbsMap, error)
}
// CommentManageService 评论管理服务
type CommentManageService interface {
DeleteComment(comment *Comment) error
CreateComment(comment *Comment) (*Comment, error)
CreateCommentReply(reply *CommentReply) (*CommentReply, error)
DeleteCommentReply(reply *CommentReply) error
CreateCommentContent(content *CommentContent) (*CommentContent, error)
DeleteComment(comment *ms.Comment) error
CreateComment(comment *ms.Comment) (*ms.Comment, error)
CreateCommentReply(reply *ms.CommentReply) (*ms.CommentReply, error)
DeleteCommentReply(reply *ms.CommentReply) error
CreateCommentContent(content *ms.CommentContent) (*ms.CommentContent, error)
ThumbsUpComment(userId int64, tweetId, commentId int64) error
ThumbsDownComment(userId int64, tweetId, commentId int64) error
ThumbsUpReply(userId int64, tweetId, commentId, replyId int64) error
ThumbsDownReply(userId int64, tweetId, commentId, replyId int64) error
}

@ -35,3 +35,14 @@ type DataService interface {
SecurityService
AttachmentCheckService
}
// WebDataServantA Web数据服务集成(版本A)
type WebDataServantA interface {
// 话题服务
TopicServantA
// 推文服务
TweetServantA
TweetManageServantA
TweetHelpServantA
}

@ -0,0 +1,19 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cs
type CommentThumbs struct {
UserID int64 `json:"user_id"`
TweetID int64 `json:"tweet_id"`
CommentID int64 `json:"comment_id"`
ReplyID int64 `json:"reply_id"`
CommentType int8 `json:"comment_type"`
IsThumbsUp int8 `json:"is_thumbs_up"`
IsThumbsDown int8 `json:"is_thumbs_down"`
}
type CommentThumbsList []*CommentThumbs
type CommentThumbsMap map[int64]*CommentThumbs

@ -0,0 +1,26 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cs
const (
ContactStatusRequesting int8 = iota + 1
ContactStatusAgree
ContactStatusReject
ContactStatusDeleted
)
type Contact struct {
ID int64 `db:"id" json:"id"`
UserId int64 `db:"user_id" json:"user_id"`
FriendId int64 `db:"friend_id" json:"friend_id"`
GroupId int64 `json:"group_id"`
Remark string `json:"remark"`
Status int8 `json:"status"` // 1请求好友, 2已同意好友, 3已拒绝好友, 4已删除好友
IsTop int8 `json:"is_top"`
IsBlack int8 `json:"is_black"`
NoticeEnable int8 `json:"notice_enable"`
IsDel int8 `json:"-"`
DeletedOn int64 `db:"-" json:"-"`
}

@ -0,0 +1,8 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
// Package cs contain core data service interface type
// model define
package cs

@ -0,0 +1,13 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cs
import "errors"
// internal core error variable for data logic implement.
var (
ErrNotImplemented = errors.New("not implemented")
ErrNoPermission = errors.New("no permission")
)

@ -0,0 +1,38 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cs
const (
// 搜索查询类型
TsQueryTypeDefault TsQueryType = "search"
TsQueryTypeTag TsQueryType = "tag"
)
type (
// TsQueryType 搜索查询类型
TsQueryType string
// TsDocList 索引条陈列表
TsDocList []TsDocItem
)
// TsQueryReq 搜索查询请求
type TsQueryReq struct {
Query string
Visibility []TweetVisibleType
Type TsQueryType
}
// TsQueryResp 搜索查询响应
type TsQueryResp struct {
Items TweetList
Total int64
}
// TsDocItem 索引条陈
type TsDocItem struct {
Post *TweetInfo
Content string
}

@ -0,0 +1,11 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cs
// TweetBox 推文列表盒子,包含其他一些关于推文列表的信息
type TweetBox struct {
Tweets TweetList
Total int64
}

@ -0,0 +1,55 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cs
const (
// 标签类型
TagTypeHot TagType = "hot"
TagTypeNew TagType = "new"
TagTypeFollow TagType = "follow"
TagTypeHotExtral TagType = "hot_extral"
)
type (
// TagType 标签类型
TagType string
// TagInfoList 标签信息列表
TagInfoList []*TagInfo
// TagList 标签列表
TagList []*TagItem
)
// TagInfo 标签信息
type TagInfo struct {
ID int64 `json:"id" db:"id"`
UserID int64 `json:"user_id" db:"user_id"`
Tag string `json:"tag"`
QuoteNum int64 `json:"quote_num" db:"quote_num"`
}
// TagItem 标签信息条陈
type TagItem struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
User *UserInfo `json:"user" db:"u"`
Tag string `json:"tag"`
QuoteNum int64 `json:"quote_num"`
IsFollowing int8 `json:"is_following"`
IsTop int8 `json:"is_top"`
}
func (t *TagInfo) Format() *TagItem {
return &TagItem{
ID: t.ID,
UserID: t.UserID,
User: &UserInfo{},
Tag: t.Tag,
QuoteNum: t.QuoteNum,
IsFollowing: 0,
IsTop: 0,
}
}

@ -0,0 +1,12 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cs
type AttachmentBill struct {
ID int64 `json:"id"`
PostID int64 `json:"post_id"`
UserID int64 `json:"user_id"`
PaidAmount int64 `json:"paid_amount"`
}

@ -0,0 +1,141 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cs
const (
// 推文内容分快类型
TweetBlockTitle TweetBlockType = iota + 1
TweetBlockText
TweetBlockImage
TweetBlockVideo
TweetBlockAudio
TweetBlockLink
TweetBlockAttachment
TweetBlockChargeAttachment
// 推文可见性
TweetVisitPublic TweetVisibleType = iota
TweetVisitPrivate
TweetVisitFriend
TweetVisitInvalid
// 附件类型
AttachmentTypeImage AttachmentType = iota + 1
AttachmentTypeVideo
AttachmentTypeOther
)
type (
// TweetBlockType 推文内容分块类型1标题2文字段落3图片地址4视频地址5语音地址6链接地址7附件资源
// TODO: 优化一下类型为 uint8 需要底层数据库同步修改
TweetBlockType int
// TweetVisibleType 推文可见性0公开1私密2好友
TweetVisibleType uint8
// AttachmentType 附件类型, 1图片 2视频 3其他
// TODO: 优化一下类型为 uint8 需要底层数据库同步修改
AttachmentType int
// TweetList 推文列表
TweetList []*TweetItem
// TweetInfoList 推文信息列表
TweetInfoList []*TweetInfo
// FavoriteList 收藏列表
FavoriteList []*FavoriteItem
// ReactionList 点赞列表
ReactionList []*ReactionItem
// TweetBlockList 推文分块列表
TweetBlockList []*TweetBlock
)
// TweetBlock 推文分块
type TweetBlock struct {
ID int64 `json:"id" binding:"-"`
PostID int64 `json:"post_id" binding:"-"`
Content string `json:"content" binding:"required"`
Type TweetBlockType `json:"type" binding:"required"`
Sort int64 `json:"sort" binding:"required"`
}
// TweetInfo 推文信息
type TweetInfo struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
CommentCount int64 `json:"comment_count"`
CollectionCount int64 `json:"collection_count"`
UpvoteCount int64 `json:"upvote_count"`
Visibility TweetVisibleType `json:"visibility"`
IsTop int `json:"is_top"`
IsEssence int `json:"is_essence"`
IsLock int `json:"is_lock"`
LatestRepliedOn int64 `json:"latest_replied_on"`
Tags string `json:"tags"`
AttachmentPrice int64 `json:"attachment_price"`
IP string `json:"ip"`
IPLoc string `json:"ip_loc"`
CreatedOn int64 `json:"created_on"`
ModifiedOn int64 `json:"modified_on"`
}
// TweetItem 一条推文信息
type TweetItem struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
User *UserInfo `db:"user" json:"user"`
Contents []*TweetBlock `db:"-" json:"contents"`
CommentCount int64 `json:"comment_count"`
CollectionCount int64 `json:"collection_count"`
UpvoteCount int64 `json:"upvote_count"`
Visibility TweetVisibleType `json:"visibility"`
IsTop int `json:"is_top"`
IsEssence int `json:"is_essence"`
IsLock int `json:"is_lock"`
LatestRepliedOn int64 `json:"latest_replied_on"`
CreatedOn int64 `json:"created_on"`
ModifiedOn int64 `json:"modified_on"`
Tags map[string]int8 `json:"tags"`
AttachmentPrice int64 `json:"attachment_price"`
IPLoc string `json:"ip_loc"`
}
type Attachment struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
FileSize int64 `json:"file_size"`
ImgWidth int `json:"img_width"`
ImgHeight int `json:"img_height"`
Type AttachmentType `json:"type"`
Content string `json:"content"`
}
// Favorite 收藏
type FavoriteItem struct {
ID int64 `json:"id"`
Tweet *TweetInfo `json:"-"`
TweetID int64 `json:"post_id"`
UserID int64 `json:"user_id"`
}
// Reaction 反应、表情符号, 点赞、喜欢等
type ReactionItem struct {
ID int64 `json:"id"`
Tweet *TweetInfo `json:"-"`
TweetID int64 `json:"post_id"`
UserID int64 `json:"user_id"`
}
type NewTweetReq struct {
Contents TweetBlockList `json:"contents" binding:"required"`
Tags []string `json:"tags" binding:"required"`
Users []string `json:"users" binding:"required"`
AttachmentPrice int64 `json:"attachment_price"`
Visibility TweetVisibleType `json:"visibility"`
ClientIP string `json:"-" binding:"-"`
}

@ -0,0 +1,58 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package cs
const (
RelationUnknow RelationTyp = iota
RelationSelf
RelationFriend
RelationFollower
RelationFollowing
RelationAdmin
RelationGuest
)
type (
// UserInfoList 用户信息列表
UserInfoList []*UserInfo
//
RelationTyp uint8
VistUser struct {
Username string
UserId int64
RelTyp RelationTyp
}
)
// UserInfo 用户基本信息
type UserInfo struct {
ID int64 `json:"id"`
Nickname string `json:"nickname"`
Username string `json:"username"`
Status int `json:"status"`
Avatar string `json:"avatar"`
IsAdmin bool `json:"is_admin"`
}
func (t RelationTyp) String() string {
switch t {
case RelationSelf:
return "self"
case RelationFriend:
return "friend"
case RelationFollower:
return "follower"
case RelationFollowing:
return "following"
case RelationAdmin:
return "admin"
case RelationUnknow:
fallthrough
default:
return "unknow relation"
}
}

@ -5,32 +5,15 @@
package core
import (
"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
"github.com/rocboss/paopao-ce/internal/core/ms"
)
// MessageService 消息服务
type MessageService interface {
CreateMessage(msg *Message) (*Message, error)
CreateMessage(msg *ms.Message) (*ms.Message, error)
GetUnreadCount(userID int64) (int64, error)
GetMessageByID(id int64) (*Message, error)
ReadMessage(message *Message) error
GetMessages(conditions *ConditionsT, offset, limit int) ([]*MessageFormated, error)
GetMessageCount(conditions *ConditionsT) (int64, error)
GetMessageByID(id int64) (*ms.Message, error)
ReadMessage(message *ms.Message) error
GetMessages(conditions *ms.ConditionsT, offset, limit int) ([]*ms.MessageFormated, error)
GetMessageCount(conditions *ms.ConditionsT) (int64, error)
}

@ -0,0 +1,115 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package ms
import (
"github.com/rocboss/paopao-ce/pkg/types"
)
const (
ActRegisterUser act = iota
ActCreatePublicTweet
ActCreatePublicAttachment
ActCreatePublicPicture
ActCreatePublicVideo
ActCreatePrivateTweet
ActCreatePrivateAttachment
ActCreatePrivatePicture
ActCreatePrivateVideo
ActCreateFriendTweet
ActCreateFriendAttachment
ActCreateFriendPicture
ActCreateFriendVideo
ActCreatePublicComment
ActCreatePublicPicureComment
ActCreateFriendComment
ActCreateFriendPicureComment
ActCreatePrivateComment
ActCreatePrivatePicureComment
ActStickTweet
ActTopTweet
ActLockTweet
ActVisibleTweet
ActDeleteTweet
ActCreateActivationCode
)
type (
act uint8
FriendFilter map[int64]types.Empty
FriendSet map[string]types.Empty
Action struct {
Act act
UserId int64
}
)
func (f FriendFilter) IsFriend(userId int64) bool {
_, yeah := f[userId]
return yeah
}
// IsAllow default true if user is admin
func (a act) IsAllow(user *User, userId int64, isFriend bool, isActivation bool) bool {
if user.IsAdmin {
return true
}
if user.ID == userId && isActivation {
switch a {
case ActCreatePublicTweet,
ActCreatePublicAttachment,
ActCreatePublicPicture,
ActCreatePublicVideo,
ActCreatePrivateTweet,
ActCreatePrivateAttachment,
ActCreatePrivatePicture,
ActCreatePrivateVideo,
ActCreateFriendTweet,
ActCreateFriendAttachment,
ActCreateFriendPicture,
ActCreateFriendVideo,
ActCreatePrivateComment,
ActCreatePrivatePicureComment,
ActStickTweet,
ActLockTweet,
ActVisibleTweet,
ActDeleteTweet:
return true
}
}
if user.ID == userId && !isActivation {
switch a {
case ActCreatePrivateTweet,
ActCreatePrivateComment,
ActStickTweet,
ActLockTweet,
ActDeleteTweet:
return true
}
}
if isFriend && isActivation {
switch a {
case ActCreatePublicComment,
ActCreatePublicPicureComment,
ActCreateFriendComment,
ActCreateFriendPicureComment:
return true
}
}
if !isFriend && isActivation {
switch a {
case ActCreatePublicComment,
ActCreatePublicPicureComment:
return true
}
}
return false
}

@ -0,0 +1,17 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package ms
import (
"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
)

@ -0,0 +1,26 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package ms
import (
"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
)

@ -1,8 +1,10 @@
// Copyright 2022 ROC. All rights reserved.
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package core
// Package ms contain core data service interface type
// model define for gorm adapter
package ms
import (
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"

@ -0,0 +1,13 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package ms
import (
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
type (
Captcha = dbr.Captcha
)

@ -0,0 +1,10 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package ms
type IndexTweetList struct {
Tweets []*PostFormated
Total int64
}

@ -0,0 +1,43 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package ms
import (
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
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
)
const (
PostVisitPublic PostVisibleT = iota
PostVisitPrivate
PostVisitFriend
PostVisitInvalid
)
type (
PostStar = dbr.PostStar
PostCollection = dbr.PostCollection
PostAttachmentBill = dbr.PostAttachmentBill
PostContent = dbr.PostContent
Attachment = dbr.Attachment
AttachmentType = dbr.AttachmentType
PostContentT = dbr.PostContentT
PostVisibleT = dbr.PostVisibleT
)

@ -0,0 +1,20 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package ms
type (
ContactItem struct {
UserId int64 `json:"user_id"`
UserName string `db:"username" json:"username"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
Phone string `json:"phone"`
}
ContactList struct {
Contacts []ContactItem `json:"contacts"`
Total int64 `json:"total"`
}
)

@ -0,0 +1,14 @@
// Copyright 2023 ROC. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
package ms
import (
"github.com/rocboss/paopao-ce/internal/dao/jinzhu/dbr"
)
type (
WalletStatement = dbr.WalletStatement
WalletRecharge = dbr.WalletRecharge
)

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

Loading…
Cancel
Save