answer/internal/service/dashboard/dashboard_service.go

255 lines
7.6 KiB
Go
Raw Normal View History

2022-11-02 15:50:32 +08:00
package dashboard
import (
"context"
2022-11-07 12:45:01 +08:00
"encoding/json"
2022-11-08 11:33:48 +08:00
"fmt"
"io"
2022-11-07 12:45:01 +08:00
"net/http"
2022-11-11 11:53:44 +08:00
"net/url"
2022-11-08 11:33:48 +08:00
"time"
2022-11-02 15:50:32 +08:00
2022-11-07 12:45:01 +08:00
"github.com/answerdev/answer/internal/base/constant"
2022-11-09 14:58:15 +08:00
"github.com/answerdev/answer/internal/base/data"
2022-11-02 16:29:10 +08:00
"github.com/answerdev/answer/internal/schema"
2022-11-02 15:50:32 +08:00
"github.com/answerdev/answer/internal/service/activity_common"
answercommon "github.com/answerdev/answer/internal/service/answer_common"
"github.com/answerdev/answer/internal/service/comment_common"
"github.com/answerdev/answer/internal/service/config"
2022-11-07 16:45:23 +08:00
"github.com/answerdev/answer/internal/service/export"
2022-11-02 15:50:32 +08:00
questioncommon "github.com/answerdev/answer/internal/service/question_common"
"github.com/answerdev/answer/internal/service/report_common"
2022-11-11 11:23:56 +08:00
"github.com/answerdev/answer/internal/service/service_config"
2022-11-03 11:12:20 +08:00
"github.com/answerdev/answer/internal/service/siteinfo_common"
2022-11-02 15:50:32 +08:00
usercommon "github.com/answerdev/answer/internal/service/user_common"
2022-11-11 11:53:44 +08:00
"github.com/answerdev/answer/pkg/dir"
2022-11-07 12:45:01 +08:00
"github.com/segmentfault/pacman/log"
2022-11-02 15:50:32 +08:00
)
type dashboardService struct {
2022-11-03 11:12:20 +08:00
questionRepo questioncommon.QuestionRepo
answerRepo answercommon.AnswerRepo
commentRepo comment_common.CommentCommonRepo
voteRepo activity_common.VoteRepo
userRepo usercommon.UserRepo
reportRepo report_common.ReportRepo
configService *config.ConfigService
siteInfoService siteinfo_common.SiteInfoCommonService
2022-11-11 11:23:56 +08:00
serviceConfig *service_config.ServiceConfig
data *data.Data
2022-11-02 15:50:32 +08:00
}
func NewDashboardService(
questionRepo questioncommon.QuestionRepo,
answerRepo answercommon.AnswerRepo,
commentRepo comment_common.CommentCommonRepo,
voteRepo activity_common.VoteRepo,
userRepo usercommon.UserRepo,
reportRepo report_common.ReportRepo,
configService *config.ConfigService,
siteInfoService siteinfo_common.SiteInfoCommonService,
2022-11-11 11:23:56 +08:00
serviceConfig *service_config.ServiceConfig,
2022-11-09 14:58:15 +08:00
data *data.Data,
) DashboardService {
return &dashboardService{
2022-11-03 11:12:20 +08:00
questionRepo: questionRepo,
answerRepo: answerRepo,
commentRepo: commentRepo,
voteRepo: voteRepo,
userRepo: userRepo,
reportRepo: reportRepo,
configService: configService,
2022-11-03 11:12:20 +08:00
siteInfoService: siteInfoService,
2022-11-11 11:23:56 +08:00
serviceConfig: serviceConfig,
data: data,
2022-11-02 15:50:32 +08:00
}
}
type DashboardService interface {
Statistical(ctx context.Context) (resp *schema.DashboardInfo, err error)
}
func (ds *dashboardService) Statistical(ctx context.Context) (*schema.DashboardInfo, error) {
dashboardInfo := ds.getFromCache(ctx)
if dashboardInfo == nil {
dashboardInfo = &schema.DashboardInfo{}
dashboardInfo.QuestionCount = ds.questionCount(ctx)
dashboardInfo.AnswerCount = ds.answerCount(ctx)
dashboardInfo.CommentCount = ds.commentCount(ctx)
dashboardInfo.UserCount = ds.userCount(ctx)
dashboardInfo.ReportCount = ds.reportCount(ctx)
dashboardInfo.VoteCount = ds.voteCount(ctx)
dashboardInfo.OccupyingStorageSpace = ds.calculateStorage()
dashboardInfo.VersionInfo.RemoteVersion = ds.remoteVersion(ctx)
2022-11-09 14:58:15 +08:00
}
dashboardInfo.SMTP = ds.smtpStatus(ctx)
dashboardInfo.HTTPS = ds.httpsStatus(ctx)
dashboardInfo.TimeZone = ds.getTimezone(ctx)
dashboardInfo.UploadingFiles = true
dashboardInfo.AppStartTime = fmt.Sprintf("%d", time.Now().Unix()-schema.AppStartTime.Unix())
2023-02-21 15:36:45 +08:00
dashboardInfo.VersionInfo.Version = constant.Version
2023-03-24 11:49:23 +08:00
dashboardInfo.VersionInfo.Revision = constant.Revision
ds.setCache(ctx, dashboardInfo)
2022-11-09 14:58:15 +08:00
return dashboardInfo, nil
}
func (ds *dashboardService) getFromCache(ctx context.Context) (dashboardInfo *schema.DashboardInfo) {
2023-08-22 16:10:41 +08:00
infoStr, exist, err := ds.data.Cache.GetString(ctx, schema.DashboardCacheKey)
2022-11-09 14:58:15 +08:00
if err != nil {
log.Errorf("get dashboard statistical from cache failed: %s", err)
return nil
}
2023-08-22 16:10:41 +08:00
if !exist {
return nil
2023-08-22 16:10:41 +08:00
}
dashboardInfo = &schema.DashboardInfo{}
if err = json.Unmarshal([]byte(infoStr), dashboardInfo); err != nil {
return nil
2022-11-09 14:58:15 +08:00
}
return dashboardInfo
}
func (ds *dashboardService) setCache(ctx context.Context, info *schema.DashboardInfo) {
infoStr, _ := json.Marshal(info)
err := ds.data.Cache.SetString(ctx, schema.DashboardCacheKey, string(infoStr), schema.DashboardCacheTime)
2022-11-09 14:58:15 +08:00
if err != nil {
log.Errorf("set dashboard statistical failed: %s", err)
2022-11-09 14:58:15 +08:00
}
}
func (ds *dashboardService) questionCount(ctx context.Context) int64 {
2022-11-02 15:50:32 +08:00
questionCount, err := ds.questionRepo.GetQuestionCount(ctx)
if err != nil {
log.Errorf("get question count failed: %s", err)
2022-11-02 15:50:32 +08:00
}
return questionCount
}
func (ds *dashboardService) answerCount(ctx context.Context) int64 {
2022-11-02 15:50:32 +08:00
answerCount, err := ds.answerRepo.GetAnswerCount(ctx)
if err != nil {
log.Errorf("get answer count failed: %s", err)
2022-11-02 15:50:32 +08:00
}
return answerCount
}
func (ds *dashboardService) commentCount(ctx context.Context) int64 {
2022-11-02 15:50:32 +08:00
commentCount, err := ds.commentRepo.GetCommentCount(ctx)
if err != nil {
log.Errorf("get comment count failed: %s", err)
}
return commentCount
}
func (ds *dashboardService) userCount(ctx context.Context) int64 {
userCount, err := ds.userRepo.GetUserCount(ctx)
if err != nil {
log.Errorf("get user count failed: %s", err)
2022-11-02 15:50:32 +08:00
}
return userCount
}
2022-11-02 15:50:32 +08:00
func (ds *dashboardService) reportCount(ctx context.Context) int64 {
reportCount, err := ds.reportRepo.GetReportCount(ctx)
if err != nil {
log.Errorf("get report count failed: %s", err)
}
return reportCount
}
// count vote
func (ds *dashboardService) voteCount(ctx context.Context) int64 {
2022-11-02 15:50:32 +08:00
typeKeys := []string{
"question.vote_up",
"question.vote_down",
"answer.vote_up",
"answer.vote_down",
}
var activityTypes []int
for _, typeKey := range typeKeys {
cfg, err := ds.configService.GetConfigByKey(ctx, typeKey)
2022-11-02 15:50:32 +08:00
if err != nil {
continue
}
activityTypes = append(activityTypes, cfg.ID)
2022-11-02 15:50:32 +08:00
}
voteCount, err := ds.voteRepo.GetVoteCount(ctx, activityTypes)
if err != nil {
log.Errorf("get vote count failed: %s", err)
2022-11-02 15:50:32 +08:00
}
return voteCount
2022-11-02 15:50:32 +08:00
}
2022-11-07 12:45:01 +08:00
func (ds *dashboardService) remoteVersion(ctx context.Context) string {
2022-11-07 12:45:01 +08:00
url := "https://answer.dev/getlatest"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("User-Agent", "Answer/"+constant.Version)
resp, err := (&http.Client{}).Do(req)
if err != nil {
log.Error("http.Client error", err)
return ""
}
defer resp.Body.Close()
respByte, err := io.ReadAll(resp.Body)
2022-11-07 12:45:01 +08:00
if err != nil {
log.Error("http.Client error", err)
return ""
}
remoteVersion := &schema.RemoteVersion{}
err = json.Unmarshal(respByte, remoteVersion)
if err != nil {
log.Error("json.Unmarshal error", err)
return ""
}
return remoteVersion.Release.Version
}
2022-11-07 16:45:23 +08:00
func (ds *dashboardService) smtpStatus(ctx context.Context) (enabled bool) {
emailConf, err := ds.configService.GetStringValue(ctx, "email.config")
2022-11-07 16:45:23 +08:00
if err != nil {
log.Errorf("get email config failed: %s", err)
return false
2022-11-07 16:45:23 +08:00
}
ec := &export.EmailConfig{}
2022-11-07 16:45:23 +08:00
err = json.Unmarshal([]byte(emailConf), ec)
if err != nil {
log.Errorf("parsing email config failed: %s", err)
return false
}
return ec.SMTPHost != ""
}
func (ds *dashboardService) httpsStatus(ctx context.Context) (enabled bool) {
siteGeneral, err := ds.siteInfoService.GetSiteGeneral(ctx)
if err != nil {
log.Errorf("get site general failed: %s", err)
return false
}
siteUrl, err := url.Parse(siteGeneral.SiteUrl)
if err != nil {
log.Errorf("parse site url failed: %s", err)
return false
}
return siteUrl.Scheme == "https"
}
func (ds *dashboardService) getTimezone(ctx context.Context) string {
siteInfoInterface, err := ds.siteInfoService.GetSiteInterface(ctx)
if err != nil {
return ""
}
return siteInfoInterface.TimeZone
}
func (ds *dashboardService) calculateStorage() string {
dirSize, err := dir.DirSize(ds.serviceConfig.UploadPath)
if err != nil {
log.Errorf("get upload dir size failed: %s", err)
return ""
2022-11-07 16:45:23 +08:00
}
return dir.FormatFileSize(dirSize)
2022-11-07 16:45:23 +08:00
}