Merge branch 'dev' into feature/followship

pull/355/head
Michael Li 11 months ago
commit 79569bc450
No known key found for this signature in database

@ -47,7 +47,7 @@ jobs:
name: Test
strategy:
matrix:
go-version: [ 1.20.x ]
go-version: [ 1.20.x, 1.21.x ]
platform: [ ubuntu-latest, macos-latest ]
runs-on: ${{ matrix.platform }}
steps:
@ -66,7 +66,7 @@ jobs:
name: TestOnWindows
strategy:
matrix:
go-version: [ 1.20.x ]
go-version: [ 1.20.x, 1.21.x ]
platform: [ windows-latest ]
runs-on: ${{ matrix.platform }}
steps:

5
.gitignore vendored

@ -4,7 +4,10 @@ __debug_bin
!*.example
/config.yaml
*.log
paopao-ce*
/paopao-ce
/paopao
/.env
/.envrc
/release
/data
/custom

@ -7,11 +7,24 @@ All notable changes to paopao-ce are documented in this file.
- use compiler profile-guided optimization (PGO) to further optimize builds. [#327](https://github.com/rocboss/paopao-ce/pull/327)
- 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)
mirgration database first(sql ddl file in `scripts/migration/**/*_create_view_post_filter.up.sql`):
```sql
CREATE VIEW p_post_by_media AS SELECT post.*FROM (SELECT DISTINCT post_id FROM p_post_content WHERE (TYPE=3 OR TYPE=4 OR TYPE=7 OR TYPE=8) AND is_del=0) media JOIN p_post post ON media.post_id=post.ID WHERE post.is_del=0;
CREATE VIEW p_post_by_comment AS SELECT P.*,C.user_id comment_user_id FROM (SELECT post_id,user_id FROM p_comment WHERE is_del=0 UNION SELECT post_id,reply.user_id user_id FROM p_comment_reply reply JOIN p_comment COMMENT ON reply.comment_id=COMMENT.ID WHERE reply.is_del=0 AND COMMENT.is_del=0) C JOIN p_post P ON C.post_id=P.ID WHERE P.is_del=0;
```
- add user highlight tweet support include custom tweet set to highlight and list in user/profile page.
- add cli subcommand to start paopao-ce serve or other task. [#354](https://github.com/rocboss/paopao-ce/pull/354)
### Changed
- change man content width to 600px and optimize tweet/comment/replay text length. [#333](https://github.com/rocboss/paopao-ce/pull/333)
- change man content width to 600px and optimize tweet/comment/replay text length. [#333](https://github.com/rocboss/paopao-ce/pull/333)
- optimize embed web ui to paopao execute binary file logic. [#354](https://github.com/rocboss/paopao-ce/pull/354)
```sh
# embed web ui to execute file default
make build
# use slim model to disable embed web ui to exectute file
make build TAGS='slim embed'
```
## 0.3.1
### Fixed
- fixed: video player assets cdn error. [&caff8c0](https://github.com/rocboss/paopao-ce/commit/caff8c052be6c8d59576011192f830fd98e17ab3 'commit caff8c0')

@ -23,8 +23,8 @@ WORKDIR /paopao-ce
COPY . .
COPY --from=frontend /web/dist ./web/dist
ENV GOPROXY=https://goproxy.cn
RUN [ $EMBED_UI != yes ] || make build TAGS='embed go_json'
RUN [ $EMBED_UI = yes ] || make build TAGS='go_json'
RUN [ $EMBED_UI != yes ] || make build TAGS='go_json'
RUN [ $EMBED_UI = yes ] || make build TAGS='slim embed go_json'
FROM bitbus/paopao-ce-backend-runner:latest
ARG API_HOST
@ -34,10 +34,11 @@ ARG USE_DIST=no
ENV TZ=Asia/Shanghai
WORKDIR /app/paopao-ce
COPY --from=backend /paopao-ce/release/paopao-ce .
COPY --from=backend /paopao-ce/release/paopao .
COPY --from=backend /paopao-ce/config.yaml.sample config.yaml
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"]
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD ps -ef | grep paopao || exit 1
ENTRYPOINT ["/app/paopao-ce/paopao"]
CMD ["serve"]

@ -1,6 +1,7 @@
.PHONY: all build build-web run test clean fmt pre-commit help
TARGET = paopao-ce
PROJECT = paopao-ce
TARGET = paopao
ifeq ($(OS),Windows_NT)
TARGET := $(TARGET).exe
endif
@ -12,10 +13,10 @@ endif
RELEASE_ROOT = release
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)
RELEASE_LINUX_AMD64 = $(RELEASE_ROOT)/linux-amd64/$(PROJECT)
RELEASE_DARWIN_AMD64 = $(RELEASE_ROOT)/darwin-amd64/$(PROJECT)
RELEASE_DARWIN_ARM64 = $(RELEASE_ROOT)/darwin-arm64/$(PROJECT)
RELEASE_WINDOWS_AMD64 = $(RELEASE_ROOT)/windows-amd64/$(PROJECT)
BUILD_VERSION := $(shell git describe --tags --always | cut -f1 -f2 -d "-")
BUILD_DATE := $(shell date +'%Y-%m-%d %H:%M:%S')
@ -38,7 +39,7 @@ build-web:
@cd web && rm -rf dist/* && yarn build && cd -
run:
@go run -pgo=auto -trimpath -gcflags "all=-N -l" -tags '$(TAGS)' -ldflags '$(LDFLAGS)' .
@go run -pgo=auto -trimpath -gcflags "all=-N -l" -tags '$(TAGS)' -ldflags '$(LDFLAGS)' . serve
.PHONY: release
release: linux-amd64 darwin-amd64 darwin-arm64 windows-x64
@ -47,10 +48,10 @@ release: linux-amd64 darwin-amd64 darwin-arm64 windows-x64
@cp -rf $(RELEASE_FILES) $(RELEASE_DARWIN_AMD64)
@cp -rf $(RELEASE_FILES) $(RELEASE_DARWIN_ARM64)
@cp -rf $(RELEASE_FILES) $(RELEASE_WINDOWS_AMD64)
@cd $(RELEASE_LINUX_AMD64)/.. && rm -f *.zip && zip -r $(TARGET)-linux_amd64.zip $(TARGET) && cd -
@cd $(RELEASE_DARWIN_AMD64)/.. && rm -f *.zip && zip -r $(TARGET)-darwin_amd64.zip $(TARGET) && cd -
@cd $(RELEASE_DARWIN_ARM64)/.. && rm -f *.zip && zip -r $(TARGET)-darwin_arm64.zip $(TARGET) && cd -
@cd $(RELEASE_WINDOWS_AMD64)/.. && rm -f *.zip && zip -r $(TARGET)-windows_amd64.zip $(TARGET) && cd -
@cd $(RELEASE_LINUX_AMD64)/.. && rm -f *.zip && zip -r $(PROJECT)-linux_amd64.zip $(PROJECT) && cd -
@cd $(RELEASE_DARWIN_AMD64)/.. && rm -f *.zip && zip -r $(PROJECT)-darwin_amd64.zip $(PROJECT) && cd -
@cd $(RELEASE_DARWIN_ARM64)/.. && rm -f *.zip && zip -r $(PROJECT)-darwin_arm64.zip $(PROJECT) && cd -
@cd $(RELEASE_WINDOWS_AMD64)/.. && rm -f *.zip && zip -r $(PROJECT)-windows_amd64.zip $(PROJECT) && cd -
.PHONY: linux-amd64
linux-amd64:

@ -97,11 +97,15 @@ PaoPao主要由以下优秀的开源项目/工具构建
```
编译api服务、内嵌web前端ui:
```sh
make build TAGS='embed'
make build
```
也可以使用精简模式编译不内嵌web前端ui:
```sh
make build TAGS='slim embed'
```
编译后在`release`目录可以找到对应可执行文件。
```sh
release/paopao-ce
release/paopao
```
4. 直接运行后端

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

@ -0,0 +1,27 @@
// 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 migrate
import (
"fmt"
"github.com/rocboss/paopao-ce/cmd"
"github.com/spf13/cobra"
)
func init() {
migrateCmd := &cobra.Command{
Use: "migrate",
Short: "migrate database data",
Long: "miegrate database data when paopao-ce upgrade",
Run: migrateRun,
}
cmd.Register(migrateCmd)
}
func migrateRun(_cmd *cobra.Command, _args []string) {
// TODO: add some logic for migrate cmd feature
fmt.Println("sorry, this feature is not implemented yet.")
}

@ -0,0 +1,36 @@
// 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 cmd
import (
"github.com/spf13/cobra"
)
var (
rootCmd = &cobra.Command{
Use: "paopao",
Short: `an artistic "twitter like" community`,
Long: `an artistic "twitter like" community`,
}
)
// Setup set root command name,short-describe, long-describe
// return &cobra.Command to custom other options
func Setup(use, short, long string) *cobra.Command {
rootCmd.Use = use
rootCmd.Short = short
rootCmd.Long = long
return rootCmd
}
// Register add sub-command
func Register(cmd *cobra.Command) {
rootCmd.AddCommand(cmd)
}
// Execute start application
func Execute() {
rootCmd.Execute()
}

@ -0,0 +1,94 @@
// 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 serve
import (
"fmt"
"log"
"os"
"os/signal"
"syscall"
"time"
"github.com/alimy/cfg"
"github.com/fatih/color"
"github.com/getsentry/sentry-go"
"github.com/rocboss/paopao-ce/cmd"
"github.com/rocboss/paopao-ce/internal"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/service"
"github.com/rocboss/paopao-ce/pkg/debug"
"github.com/rocboss/paopao-ce/pkg/utils"
"github.com/rocboss/paopao-ce/pkg/version"
"github.com/sourcegraph/conc"
"github.com/spf13/cobra"
"go.uber.org/automaxprocs/maxprocs"
)
var (
noDefaultFeatures bool
features []string
)
func init() {
serveCmd := &cobra.Command{
Use: "serve",
Short: "start paopao-ce server",
Long: "start paopao-ce server",
Run: serveRun,
}
serveCmd.Flags().BoolVar(&noDefaultFeatures, "no-default-features", false, "whether not use default features")
serveCmd.Flags().StringSliceVarP(&features, "features", "f", []string{}, "use special features")
cmd.Register(serveCmd)
}
func deferFn() {
if cfg.If("Sentry") {
// Flush buffered events before the program terminates.
sentry.Flush(2 * time.Second)
}
}
func serveRun(_cmd *cobra.Command, _args []string) {
utils.PrintHelloBanner(version.VersionInfo())
// set maxprocs automatic
maxprocs.Set(maxprocs.Logger(log.Printf))
// initial configure
conf.Initial(features, noDefaultFeatures)
internal.Initial()
ss := service.MustInitService()
if len(ss) < 1 {
fmt.Fprintln(color.Output, "no service need start so just exit")
return
}
// do defer function
defer deferFn()
// start pyroscope if need
debug.StartPyroscope()
// start services
wg := conc.NewWaitGroup()
fmt.Fprintf(color.Output, "\nstarting run service...\n\n")
service.Start(wg)
// graceful stop services
wg.Go(func() {
quit := make(chan os.Signal, 1)
// kill (no param) default send syscall.SIGTERM
// kill -2 is syscall.SIGINT
// kill -9 is syscall.SIGKILL but can't be catch, so don't need add it
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
fmt.Fprintf(color.Output, "\nshutting down server...\n\n")
service.Stop()
})
wg.Wait()
}

@ -0,0 +1,25 @@
// 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 cmd
import (
"github.com/rocboss/paopao-ce/pkg/utils"
"github.com/rocboss/paopao-ce/pkg/version"
"github.com/spf13/cobra"
)
func init() {
versionCmd := &cobra.Command{
Use: "version",
Short: "show version information",
Long: "show version information",
Run: versionRun,
}
Register(versionCmd)
}
func versionRun(_cmd *cobra.Command, _args []string) {
utils.PrintHelloBanner(version.VersionInfo())
}

@ -102,7 +102,7 @@ services:
- paopao-network
backend:
image: bitbus/paopao-ce:0.3
image: bitbus/paopao-ce:0.4
restart: always
depends_on:
- db

@ -28,11 +28,12 @@ require (
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/pyroscope-io/client v0.7.2-0.20230804044655-36760e422a95
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/cobra v1.7.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
@ -76,6 +77,7 @@ require (
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/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.3.1 // indirect
@ -102,7 +104,7 @@ require (
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/pyroscope-io/godeltaprof v0.1.0 // indirect
github.com/pyroscope-io/godeltaprof v0.1.2 // 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

@ -363,6 +363,7 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@ -740,6 +741,8 @@ github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw=
@ -1105,10 +1108,10 @@ github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/pyroscope-io/client v0.7.1 h1:yFRhj3vbgjBxehvxQmedmUWJQ4CAfCHhn+itPsuWsHw=
github.com/pyroscope-io/client v0.7.1/go.mod h1:4h21iOU4pUOq0prKyDlvYRL+SCKsBc5wKiEtV+rJGqU=
github.com/pyroscope-io/godeltaprof v0.1.0 h1:UBqtjt0yZi4jTxqZmLAs34XG6ycS3vUTlhEUSq4NHLE=
github.com/pyroscope-io/godeltaprof v0.1.0/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE=
github.com/pyroscope-io/client v0.7.2-0.20230804044655-36760e422a95 h1:ZpE0l+tD3ykwYWQh/UVdIpxHmr9B6DTtOUBiGw3lB2E=
github.com/pyroscope-io/client v0.7.2-0.20230804044655-36760e422a95/go.mod h1:FEocnjn+Ngzxy6EtU9ZxXWRvQ0+pffkrBxHLnPpxwi8=
github.com/pyroscope-io/godeltaprof v0.1.2 h1:MdlEmYELd5w+lvIzmZvXGNMVzW2Qc9jDMuJaPOR75g4=
github.com/pyroscope-io/godeltaprof v0.1.2/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE=
github.com/redis/rueidis v1.0.14 h1:qdFZahk1F/2L+sZeOECx5E2N5J4Qc51b7ezSUpQXJfs=
github.com/redis/rueidis v1.0.14/go.mod h1:8B+r5wdnjwK3lTFml5VtxjzGOQAC+5UmujoD12pDrEo=
github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
@ -1130,6 +1133,7 @@ github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
@ -1185,6 +1189,8 @@ github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKv
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=

@ -29,6 +29,8 @@ const (
TableContactGroup = "contact_group"
TableMessage = "message"
TablePost = "post"
TablePostByComment = "post_by_comment"
TablePostByMedia = "post_by_media"
TablePostAttachmentBill = "post_attachment_bill"
TablePostCollection = "post_collection"
TablePostContent = "post_content"

@ -309,6 +309,8 @@ func (s *databaseConf) TableNames() (res TableNameMap) {
TableContactGroup,
TableMessage,
TablePost,
TablePostByComment,
TablePostByMedia,
TablePostAttachmentBill,
TablePostCollection,
TablePostContent,

@ -24,6 +24,8 @@ type TweetService interface {
GetPostContentsByIDs(ids []int64) ([]*ms.PostContent, error)
GetPostContentByID(id int64) (*ms.PostContent, error)
ListUserStarTweets(user *cs.VistUser, limit int, offset int) ([]*ms.PostStar, int64, error)
ListUserMediaTweets(user *cs.VistUser, limit int, offset int) ([]*ms.Post, int64, error)
ListUserCommentTweets(user *cs.VistUser, limit int, offset int) ([]*ms.Post, int64, error)
}
// TweetManageService 推文管理服务,包括创建/删除/更新推文

@ -21,6 +21,10 @@ const (
PostVisitInvalid
)
type PostByMedia = Post
type PostByComment = Post
type Post struct {
*Model
UserID int64 `json:"user_id"`

@ -21,6 +21,8 @@ var (
_contactGroup_ string
_message_ string
_post_ string
_post_by_comment_ string
_post_by_media_ string
_postAttachmentBill_ string
_postCollection_ string
_postContent_ string
@ -44,6 +46,8 @@ func initTableName() {
_contactGroup_ = m[conf.TableContactGroup]
_message_ = m[conf.TableMessage]
_post_ = m[conf.TablePost]
_post_by_comment_ = m[conf.TablePostByComment]
_post_by_media_ = m[conf.TablePostByMedia]
_postAttachmentBill_ = m[conf.TablePostAttachmentBill]
_postCollection_ = m[conf.TablePostCollection]
_postContent_ = m[conf.TablePostContent]

@ -143,7 +143,7 @@ func (s *topicSrv) GetFollowTags(userId int64, limit int, offset int) (cs.TagLis
}
// 置顶排序后处理
// TODO: 垃圾办法最好是topic_user join tag 一次查询但是gorm的join真他喵的别扭F*K
res := make(cs.TagList, len(topicIds), len(topicIds))
res := make(cs.TagList, len(topicIds))
for _, tag := range formtedTags {
res[topicIdsMap[tag.ID]] = tag
}
@ -217,10 +217,8 @@ func (s *topicSrv) tagsFormatA(userId int64, tags cs.TagList) (cs.TagList, error
func (s *topicSrv) tagsFormatB(userTopicsMap map[int64]*topicInfo, tags cs.TagInfoList) (cs.TagList, error) {
// 获取创建者User IDs
userIds := []int64{}
tagIds := []int64{}
for _, tag := range tags {
userIds = append(userIds, tag.UserID)
tagIds = append(tagIds, tag.ID)
}
users, err := (&dbr.User{}).ListUserInfoById(s.db, userIds)
if err != nil {

@ -426,6 +426,40 @@ func (s *tweetSrv) ListUserStarTweets(user *cs.VistUser, limit int, offset int)
return
}
func (s *tweetSrv) getUserTweets(db *gorm.DB, user *cs.VistUser, limit int, offset int) (res []*ms.Post, total int64, err error) {
visibilities := []core.PostVisibleT{core.PostVisitPublic}
switch user.RelTyp {
case cs.RelationAdmin, cs.RelationSelf:
visibilities = append(visibilities, core.PostVisitPrivate, core.PostVisitFriend)
case cs.RelationFriend:
visibilities = append(visibilities, core.PostVisitFriend)
case cs.RelationGuest:
fallthrough
default:
// nothing
}
db = db.Where("visibility IN ? AND is_del=0", visibilities)
err = db.Count(&total).Error
if err != nil {
return
}
if offset >= 0 && limit > 0 {
db = db.Offset(offset).Limit(limit)
}
err = db.Order("latest_replied_on DESC").Find(&res).Error
return
}
func (s *tweetSrv) ListUserMediaTweets(user *cs.VistUser, limit int, offset int) ([]*ms.Post, int64, error) {
db := s.db.Table(_post_by_media_).Where("user_id=?", user.UserId)
return s.getUserTweets(db, user, limit, offset)
}
func (s *tweetSrv) ListUserCommentTweets(user *cs.VistUser, limit int, offset int) ([]*ms.Post, int64, error) {
db := s.db.Table(_post_by_comment_).Where("comment_user_id=?", user.UserId)
return s.getUserTweets(db, user, limit, offset)
}
func (s *tweetSrv) GetUserPostStarCount(userID int64) (int64, error) {
star := &dbr.PostStar{
UserID: userID,

@ -2,8 +2,8 @@
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
//go:build !embed
// +build !embed
//go:build slim && embed
// +build slim,embed
package statick

@ -2,8 +2,8 @@
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
//go:build embed
// +build embed
//go:build !(slim && embed)
// +build !slim !embed
package statick

@ -66,14 +66,11 @@ func (s *looseSrv) GetUserTweets(req *web.GetUserTweetsReq) (res *web.GetUserTwe
if xerr != nil {
return nil, err
}
switch req.Style {
case web.UserPostsStyleComment:
res, err = s.getUserCommentTweets(req, user)
case web.UserPostsStyleComment, web.UserPostsStyleMedia:
res, err = s.listUserTweets(req, user)
case web.UserPostsStyleHighlight:
res, err = s.getUserPostTweets(req, user, true)
case web.UserPostsStyleMedia:
res, err = s.getUserMediaTweets(req, user)
case web.UserPostsStyleStar:
res, err = s.getUserStarTweets(req, user)
case web.UserPostsStylePost:
@ -84,30 +81,6 @@ func (s *looseSrv) GetUserTweets(req *web.GetUserTweetsReq) (res *web.GetUserTwe
return
}
func (s *looseSrv) getUserCommentTweets(req *web.GetUserTweetsReq, user *cs.VistUser) (*web.GetUserTweetsResp, mir.Error) {
// TODO: add implement logic
resp := base.PageRespFrom(nil, req.Page, req.PageSize, 0)
return (*web.GetUserTweetsResp)(resp), nil
}
func (s *looseSrv) getUserHighlightTweets(req *web.GetUserTweetsReq, user *cs.VistUser) (*web.GetUserTweetsResp, mir.Error) {
// TODO: add implement logic
resp := base.PageRespFrom(nil, req.Page, req.PageSize, 0)
return (*web.GetUserTweetsResp)(resp), nil
}
func (s *looseSrv) getUserMediaTweets(req *web.GetUserTweetsReq, user *cs.VistUser) (*web.GetUserTweetsResp, mir.Error) {
// TODO: add implement logic
resp := base.PageRespFrom(nil, req.Page, req.PageSize, 0)
return (*web.GetUserTweetsResp)(resp), nil
}
func (s *looseSrv) getSelfMediaTweets(req *web.GetUserTweetsReq) (*web.GetUserTweetsResp, mir.Error) {
// TODO: add implement logic
resp := base.PageRespFrom(nil, req.Page, req.PageSize, 0)
return (*web.GetUserTweetsResp)(resp), nil
}
func (s *looseSrv) getUserStarTweets(req *web.GetUserTweetsReq, user *cs.VistUser) (*web.GetUserTweetsResp, mir.Error) {
stars, totalRows, err := s.Ds.ListUserStarTweets(user, req.PageSize, (req.Page-1)*req.PageSize)
if err != nil {
@ -129,6 +102,33 @@ func (s *looseSrv) getUserStarTweets(req *web.GetUserTweetsReq, user *cs.VistUse
return (*web.GetUserTweetsResp)(resp), nil
}
func (s *looseSrv) listUserTweets(req *web.GetUserTweetsReq, user *cs.VistUser) (*web.GetUserTweetsResp, mir.Error) {
var (
tweets []*ms.Post
total int64
err error
)
if req.Style == web.UserPostsStyleComment {
tweets, total, err = s.Ds.ListUserCommentTweets(user, req.PageSize, (req.Page-1)*req.PageSize)
} else if req.Style == web.UserPostsStyleMedia {
tweets, total, err = s.Ds.ListUserMediaTweets(user, req.PageSize, (req.Page-1)*req.PageSize)
} else {
logrus.Errorf("s.listUserTweets unknow style: %s", req.Style)
return nil, web.ErrGetPostsFailed
}
if err != nil {
logrus.Errorf("s.listUserTweets err: %s", err)
return nil, web.ErrGetPostsFailed
}
postFormated, err := s.Ds.MergePosts(tweets)
if err != nil {
logrus.Errorf("s.listUserTweets err: %s", err)
return nil, web.ErrGetPostsFailed
}
resp := base.PageRespFrom(postFormated, req.Page, req.PageSize, total)
return (*web.GetUserTweetsResp)(resp), nil
}
func (s *looseSrv) getUserPostTweets(req *web.GetUserTweetsReq, user *cs.VistUser, isHighlight bool) (*web.GetUserTweetsResp, mir.Error) {
visibilities := []core.PostVisibleT{core.PostVisitPublic}
switch user.RelTyp {

@ -5,94 +5,11 @@
package main
import (
"flag"
"fmt"
"os"
"os/signal"
"strings"
"syscall"
"time"
"github.com/alimy/cfg"
"github.com/fatih/color"
"github.com/getsentry/sentry-go"
"github.com/rocboss/paopao-ce/internal"
"github.com/rocboss/paopao-ce/internal/conf"
"github.com/rocboss/paopao-ce/internal/service"
"github.com/rocboss/paopao-ce/pkg/debug"
"github.com/rocboss/paopao-ce/pkg/utils"
"github.com/rocboss/paopao-ce/pkg/version"
"github.com/sourcegraph/conc"
_ "go.uber.org/automaxprocs"
)
var (
noDefaultFeatures bool
features suites
"github.com/rocboss/paopao-ce/cmd"
_ "github.com/rocboss/paopao-ce/cmd/migrate"
_ "github.com/rocboss/paopao-ce/cmd/serve"
)
type suites []string
func (s *suites) String() string {
return strings.Join(*s, ",")
}
func (s *suites) Set(value string) error {
for _, item := range strings.Split(value, ",") {
*s = append(*s, strings.TrimSpace(item))
}
return nil
}
func init() {
flagParse()
conf.Initial(features, noDefaultFeatures)
internal.Initial()
}
func deferFn() {
if cfg.If("Sentry") {
// Flush buffered events before the program terminates.
sentry.Flush(2 * time.Second)
}
}
func flagParse() {
flag.BoolVar(&noDefaultFeatures, "no-default-features", false, "whether not use default features")
flag.Var(&features, "features", "use special features")
flag.Parse()
}
func main() {
utils.PrintHelloBanner(version.VersionInfo())
ss := service.MustInitService()
if len(ss) < 1 {
fmt.Fprintln(color.Output, "no service need start so just exit")
return
}
// do defer function
defer deferFn()
// start pyroscope if need
debug.StartPyroscope()
// start services
wg := conc.NewWaitGroup()
fmt.Fprintf(color.Output, "\nstarting run service...\n\n")
service.Start(wg)
// graceful stop services
wg.Go(func() {
quit := make(chan os.Signal, 1)
// kill (no param) default send syscall.SIGTERM
// kill -2 is syscall.SIGINT
// kill -9 is syscall.SIGKILL but can't be catch, so don't need add it
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
fmt.Fprintf(color.Output, "\nshutting down server...\n\n")
service.Stop()
})
wg.Wait()
cmd.Execute()
}

@ -21,6 +21,9 @@ func VersionInfo() string {
}
func ReadBuildInfo() *BuildInfo {
if version == "" {
version = "unknow"
}
return &BuildInfo{
Version: version,
Sum: commitID,

@ -1,3 +1,3 @@
ALTER TABLE `p_post_content` MODIFY COLUMN `content` varchar(65535) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容';
ALTER TABLE `p_comment_content` MODIFY COLUMN `content` varchar(65535) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容';
ALTER TABLE `p_comment_reply` MODIFY COLUMN `content` varchar(65535) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容';
ALTER TABLE `p_post_content` MODIFY COLUMN `content` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容';
ALTER TABLE `p_comment_content` MODIFY COLUMN `content` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容';
ALTER TABLE `p_comment_reply` MODIFY COLUMN `content` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容';

@ -0,0 +1,5 @@
DROP VIEW IF EXISTS p_post_by_media;
DROP VIEW IF EXISTS p_post_by_comment;

@ -0,0 +1,32 @@
CREATE VIEW p_post_by_media AS
SELECT post.*
FROM
( SELECT DISTINCT post_id FROM p_post_content WHERE ( TYPE = 3 OR TYPE = 4 OR TYPE = 7 OR TYPE = 8 ) AND is_del = 0 ) media
JOIN p_post post ON media.post_id = post.ID
WHERE
post.is_del = 0;
CREATE VIEW p_post_by_comment AS
SELECT P.*, C.user_id comment_user_id
FROM
(
SELECT
post_id,
user_id
FROM
p_comment
WHERE
is_del = 0 UNION
SELECT
post_id,
reply.user_id user_id
FROM
p_comment_reply reply
JOIN p_comment COMMENT ON reply.comment_id = COMMENT.ID
WHERE
reply.is_del = 0
AND COMMENT.is_del = 0
)
C JOIN p_post P ON C.post_id = P.ID
WHERE
P.is_del = 0;

@ -0,0 +1,5 @@
DROP VIEW IF EXISTS p_post_by_media;
DROP VIEW IF EXISTS p_post_by_comment;

@ -0,0 +1,32 @@
CREATE VIEW p_post_by_media AS
SELECT post.*
FROM
( SELECT DISTINCT post_id FROM p_post_content WHERE ( TYPE = 3 OR TYPE = 4 OR TYPE = 7 OR TYPE = 8 ) AND is_del = 0 ) media
JOIN p_post post ON media.post_id = post.ID
WHERE
post.is_del = 0;
CREATE VIEW p_post_by_comment AS
SELECT P.*, C.user_id comment_user_id
FROM
(
SELECT
post_id,
user_id
FROM
p_comment
WHERE
is_del = 0 UNION
SELECT
post_id,
reply.user_id user_id
FROM
p_comment_reply reply
JOIN p_comment COMMENT ON reply.comment_id = COMMENT.ID
WHERE
reply.is_del = 0
AND COMMENT.is_del = 0
)
C JOIN p_post P ON C.post_id = P.ID
WHERE
P.is_del = 0;

@ -0,0 +1,5 @@
DROP VIEW IF EXISTS p_post_by_media;
DROP VIEW IF EXISTS p_post_by_comment;

@ -0,0 +1,32 @@
CREATE VIEW p_post_by_media AS
SELECT post.*
FROM
( SELECT DISTINCT post_id FROM p_post_content WHERE ( TYPE = 3 OR TYPE = 4 OR TYPE = 7 OR TYPE = 8 ) AND is_del = 0 ) media
JOIN p_post post ON media.post_id = post.ID
WHERE
post.is_del = 0;
CREATE VIEW p_post_by_comment AS
SELECT P.*, C.user_id comment_user_id
FROM
(
SELECT
post_id,
user_id
FROM
p_comment
WHERE
is_del = 0 UNION
SELECT
post_id,
reply.user_id user_id
FROM
p_comment_reply reply
JOIN p_comment COMMENT ON reply.comment_id = COMMENT.ID
WHERE
reply.is_del = 0
AND COMMENT.is_del = 0
)
C JOIN p_post P ON C.post_id = P.ID
WHERE
P.is_del = 0;

@ -70,7 +70,7 @@ CREATE TABLE `p_comment_content` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '内容ID',
`comment_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '评论ID',
`user_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '用户ID',
`content` varchar(65535) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容',
`content` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容',
`type` tinyint unsigned NOT NULL DEFAULT '2' COMMENT '类型1标题2文字段落3图片地址4视频地址5语音地址6链接地址',
`sort` bigint unsigned NOT NULL DEFAULT '100' COMMENT '排序,越小越靠前',
`created_on` bigint unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
@ -93,7 +93,7 @@ CREATE TABLE `p_comment_reply` (
`comment_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '评论ID',
`user_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '用户ID',
`at_user_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '@用户ID',
`content` varchar(65535) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容',
`content` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容',
`ip` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'IP地址',
`ip_loc` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'IP城市地址',
`thumbs_up_count` int unsigned NOT NULL DEFAULT '0' COMMENT '点赞数',
@ -224,7 +224,7 @@ CREATE TABLE `p_post_content` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '内容ID',
`post_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT 'POST ID',
`user_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '用户ID',
`content` varchar(65535) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容',
`content` varchar(4000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容',
`type` tinyint unsigned NOT NULL DEFAULT '2' COMMENT '类型1标题2文字段落3图片地址4视频地址5语音地址6链接地址7附件资源8收费资源',
`sort` int unsigned NOT NULL DEFAULT '100' COMMENT '排序,越小越靠前',
`created_on` bigint unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
@ -395,4 +395,39 @@ CREATE TABLE `p_wallet_statement` (
KEY `idx_wallet_statement_user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10010 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='钱包流水';
DROP VIEW IF EXISTS p_post_by_media;
CREATE VIEW p_post_by_media AS
SELECT post.*
FROM
( SELECT DISTINCT post_id FROM p_post_content WHERE ( TYPE = 3 OR TYPE = 4 OR TYPE = 7 OR TYPE = 8 ) AND is_del = 0 ) media
JOIN p_post post ON media.post_id = post.ID
WHERE
post.is_del = 0;
DROP VIEW IF EXISTS p_post_by_comment;
CREATE VIEW p_post_by_comment AS
SELECT P.*, C.user_id comment_user_id
FROM
(
SELECT
post_id,
user_id
FROM
p_comment
WHERE
is_del = 0 UNION
SELECT
post_id,
reply.user_id user_id
FROM
p_comment_reply reply
JOIN p_comment COMMENT ON reply.comment_id = COMMENT.ID
WHERE
reply.is_del = 0
AND COMMENT.is_del = 0
)
C JOIN p_post P ON C.post_id = P.ID
WHERE
P.is_del = 0;
SET FOREIGN_KEY_CHECKS = 1;

@ -325,3 +325,38 @@ CREATE TABLE p_wallet_statement (
is_del SMALLINT NOT NULL DEFAULT 0
);
CREATE INDEX idx_wallet_statement_user_id ON p_wallet_statement USING btree (user_id);
DROP VIEW IF EXISTS p_post_by_media;
CREATE VIEW p_post_by_media AS
SELECT post.*
FROM
( SELECT DISTINCT post_id FROM p_post_content WHERE ( TYPE = 3 OR TYPE = 4 OR TYPE = 7 OR TYPE = 8 ) AND is_del = 0 ) media
JOIN p_post post ON media.post_id = post.ID
WHERE
post.is_del = 0;
DROP VIEW IF EXISTS p_post_by_comment;
CREATE VIEW p_post_by_comment AS
SELECT P.*, C.user_id comment_user_id
FROM
(
SELECT
post_id,
user_id
FROM
p_comment
WHERE
is_del = 0 UNION
SELECT
post_id,
reply.user_id user_id
FROM
p_comment_reply reply
JOIN p_comment COMMENT ON reply.comment_id = COMMENT.ID
WHERE
reply.is_del = 0
AND COMMENT.is_del = 0
)
C JOIN p_post P ON C.post_id = P.ID
WHERE
P.is_del = 0;

@ -356,6 +356,41 @@ CREATE TABLE "p_wallet_statement" (
PRIMARY KEY ("id")
);
DROP VIEW IF EXISTS p_post_by_media;
CREATE VIEW p_post_by_media AS
SELECT post.*
FROM
( SELECT DISTINCT post_id FROM p_post_content WHERE ( TYPE = 3 OR TYPE = 4 OR TYPE = 7 OR TYPE = 8 ) AND is_del = 0 ) media
JOIN p_post post ON media.post_id = post.ID
WHERE
post.is_del = 0;
DROP VIEW IF EXISTS p_post_by_comment;
CREATE VIEW p_post_by_comment AS
SELECT P.*, C.user_id comment_user_id
FROM
(
SELECT
post_id,
user_id
FROM
p_comment
WHERE
is_del = 0 UNION
SELECT
post_id,
reply.user_id user_id
FROM
p_comment_reply reply
JOIN p_comment COMMENT ON reply.comment_id = COMMENT.ID
WHERE
reply.is_del = 0
AND COMMENT.is_del = 0
)
C JOIN p_post P ON C.post_id = P.ID
WHERE
P.is_del = 0;
-- ----------------------------
-- Indexes structure for table p_attachment
-- ----------------------------

@ -2,8 +2,8 @@
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.
//go:build embed
// +build embed
//go:build !(slim && embed)
// +build !slim !embed
package web

Loading…
Cancel
Save