pull/52/head
sunface 4 years ago
parent 09c22b36fe
commit 83ecc2d214

@ -24,7 +24,7 @@ func GetTag(c *gin.Context) {
}
func GetTags(c *gin.Context) {
res, err := tags.GetTags()
res, err := models.GetTags()
if err != nil {
c.JSON(err.Status, common.RespError(err.Message))
return

@ -67,7 +67,9 @@ func Like(storyID string, userId string) *e.Error {
tx.Commit()
top.Update(storyID, count)
if models.IsIDStory(storyID) {
top.Update(storyID, count)
}
return nil
}

@ -10,6 +10,7 @@ import (
"github.com/imdotdev/im.dev/server/internal/api"
"github.com/imdotdev/im.dev/server/internal/cache"
"github.com/imdotdev/im.dev/server/internal/storage"
"github.com/imdotdev/im.dev/server/internal/top"
"github.com/imdotdev/im.dev/server/internal/user"
"github.com/imdotdev/im.dev/server/pkg/common"
"github.com/imdotdev/im.dev/server/pkg/config"
@ -46,6 +47,8 @@ func (s *Server) Start() error {
// }
go cache.Init()
go top.Init()
go func() {
router := gin.New()
router.Use(Cors())

@ -108,6 +108,7 @@ func SubmitStory(c *gin.Context) (map[string]string, *e.Error) {
return nil, e.New(http.StatusInternalServerError, e.Internal)
}
} else {
post.Updated = now
// 只有创建者自己才能更新内容
creator, _ := GetPostCreator(post.ID)
if creator != post.CreatorID {
@ -115,12 +116,13 @@ func SubmitStory(c *gin.Context) (map[string]string, *e.Error) {
}
if post.Status == models.StatusDraft {
post.Created = now
// 首次发布,需要更新创建时间
_, err = db.Conn.Exec("UPDATE story SET owner=?, slug=?, title=?, md=?, url=?, cover=?, brief=?,created=?,updated=?,status=? WHERE id=?",
post.OwnerID, post.Slug, post.Title, md, post.URL, post.Cover, post.Brief, now, now, models.StatusPublished, post.ID)
post.OwnerID, post.Slug, post.Title, md, post.URL, post.Cover, post.Brief, post.Created, post.Updated, models.StatusPublished, post.ID)
} else {
_, err = db.Conn.Exec("UPDATE story SET owner=?, slug=?, title=?, md=?, url=?, cover=?, brief=?, updated=? WHERE id=?",
post.OwnerID, post.Slug, post.Title, md, post.URL, post.Cover, post.Brief, now, post.ID)
post.OwnerID, post.Slug, post.Title, md, post.URL, post.Cover, post.Brief, post.Updated, post.ID)
}
if err != nil {
@ -130,11 +132,14 @@ func SubmitStory(c *gin.Context) (map[string]string, *e.Error) {
}
//update tags
top.RemoveTagTop(post.ID)
err = tags.UpdateTargetTags(user.ID, post.ID, post.Tags, post.Created)
if err != nil {
logger.Warn("upate tags error", "error", err)
return nil, e.New(http.StatusInternalServerError, e.Internal)
}
likes := interaction.GetLikes(post.ID)
top.Update(post.ID, likes)
return map[string]string{
"username": user.Username,

@ -68,41 +68,6 @@ func SubmitTag(tag *models.Tag) *e.Error {
return nil
}
func GetTags() (models.Tags, *e.Error) {
tags := make(models.Tags, 0)
rows, err := db.Conn.Query("SELECT id,creator,title,md,name,icon,cover from tags")
if err != nil {
if err == sql.ErrNoRows {
return tags, nil
}
logger.Warn("get tags error", "error", err)
return tags, e.New(http.StatusInternalServerError, e.Internal)
}
for rows.Next() {
var rawMd []byte
tag := &models.Tag{}
err := rows.Scan(&tag.ID, &tag.Creator, &tag.Title, &rawMd, &tag.Name, &tag.Icon, &tag.Cover)
if err != nil {
logger.Warn("scan tags error", "error", err)
continue
}
md, _ := utils.Uncompress(rawMd)
tag.Md = string(md)
tag.SetCover()
tags = append(tags, tag)
db.Conn.QueryRow("SELECT count(*) FROM tags_using WHERE tag_id=? and target_type != ?", tag.ID, models.IDTypeUser).Scan(&tag.Posts)
}
sort.Sort(tags)
return tags, nil
}
func GetTagsByIDs(ids []string) ([]*models.Tag, *e.Error) {
tags := make([]*models.Tag, 0, len(ids))
for _, id := range ids {

@ -3,6 +3,8 @@ package top
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"github.com/go-redis/redis/v8"
@ -94,6 +96,50 @@ func Update(storyID string, count int) {
}
}
func RemoveGlobalTop(storyID string) {
hots := make([]string, 0)
hots = append(hots, GlobalPrefix+TopYear)
hots = append(hots, GlobalPrefix+TopMonth)
hots = append(hots, GlobalPrefix+TopWeek)
hots = append(hots, GlobalPrefix+TopRecent)
ctx := context.Background()
for _, hot := range hots {
err := db.Redis.ZRem(ctx, hot, storyID).Err()
if err != nil {
logger.Warn("update hot error", "error", err, "key", hot, "storyID", storyID)
continue
}
}
}
func RemoveTagTop(storyID string) {
ts, _, err := models.GetTargetTags(storyID)
if err != nil {
logger.Warn("get tags error", "error", err)
return
}
hots := make([]string, 0)
for _, tag := range ts {
hots = append(hots, fmt.Sprintf(TagFormat, tag, TopYear))
hots = append(hots, fmt.Sprintf(TagFormat, tag, TopMonth))
hots = append(hots, fmt.Sprintf(TagFormat, tag, TopWeek))
hots = append(hots, fmt.Sprintf(TagFormat, tag, TopRecent))
}
ctx := context.Background()
for _, hot := range hots {
err = db.Redis.ZRem(ctx, hot, storyID).Err()
if err != nil {
logger.Warn("update hot error", "error", err, "key", hot, "storyID", storyID)
continue
}
}
}
func GetTopList(key string, start, end int64) []string {
ids := make([]string, 0)
ctx := context.Background()
@ -109,3 +155,65 @@ func GetTopList(key string, start, end int64) []string {
return ids
}
func Init() {
// 检查是否凌晨
for {
now := time.Now()
if now.Local().Hour() == 0 {
break
}
time.Sleep(1 * time.Hour)
}
// 从凌晨开始每隔24小时检查一次
for {
ctx := context.Background()
keys := []string{GlobalPrefix + TopYear, GlobalPrefix + TopMonth, GlobalPrefix + TopWeek, GlobalPrefix + TopRecent}
tags, _ := models.GetTags()
for _, tag := range tags {
keys = append(keys, fmt.Sprintf(TagFormat, tag, TopYear))
keys = append(keys, fmt.Sprintf(TagFormat, tag, TopMonth))
keys = append(keys, fmt.Sprintf(TagFormat, tag, TopWeek))
keys = append(keys, fmt.Sprintf(TagFormat, tag, TopRecent))
}
now := time.Now()
for _, k := range keys {
var maxDuration float64
if strings.HasSuffix(k, TopYear) {
maxDuration = 365 * 24
}
if strings.HasSuffix(k, TopMonth) {
maxDuration = 30 * 24
}
if strings.HasSuffix(k, TopWeek) {
maxDuration = 7 * 24
}
if strings.HasSuffix(k, TopRecent) {
maxDuration = 2 * 24
}
iter := db.Redis.ZScan(ctx, k, 0, "", 0).Iterator()
for iter.Next(ctx) {
id := iter.Val()
_, err := strconv.Atoi(id)
if err == nil {
//若是数字则是score跳过
continue
}
created := models.GetStoryCreated(id)
if now.Sub(created).Hours() > maxDuration {
err = db.Redis.ZRem(ctx, k, id).Err()
if err != nil {
logger.Warn("delete top error", "error", err, "key", k, "storyID", id)
}
}
}
}
time.Sleep(24 * time.Hour)
}
}

@ -48,6 +48,11 @@ func GetIdTypeTable(id string) string {
}
}
func IsIDStory(id string) bool {
tp := GetIDType(id)
return tp == IDTypePost || tp == IDTypeSeries || tp == IDTypeBook
}
func IdExist(id string) bool {
if id == "" {
return false

@ -90,3 +90,10 @@ func IsStoryCreator(userID string, storyID string) bool {
return false
}
func GetStoryCreated(storyID string) time.Time {
var t time.Time
db.Conn.QueryRow("SELECT created FROM story WHERE id=?", storyID).Scan(&t)
return t
}

@ -3,9 +3,11 @@ package models
import (
"database/sql"
"net/http"
"sort"
"github.com/imdotdev/im.dev/server/pkg/db"
"github.com/imdotdev/im.dev/server/pkg/e"
"github.com/imdotdev/im.dev/server/pkg/utils"
)
type Tag struct {
@ -73,3 +75,38 @@ func GetSimpleTag(id string, name string) (*Tag, *e.Error) {
return tag, nil
}
func GetTags() (Tags, *e.Error) {
tags := make(Tags, 0)
rows, err := db.Conn.Query("SELECT id,creator,title,md,name,icon,cover from tags")
if err != nil {
if err == sql.ErrNoRows {
return tags, nil
}
logger.Warn("get tags error", "error", err)
return tags, e.New(http.StatusInternalServerError, e.Internal)
}
for rows.Next() {
var rawMd []byte
tag := &Tag{}
err := rows.Scan(&tag.ID, &tag.Creator, &tag.Title, &rawMd, &tag.Name, &tag.Icon, &tag.Cover)
if err != nil {
logger.Warn("scan tags error", "error", err)
continue
}
md, _ := utils.Uncompress(rawMd)
tag.Md = string(md)
tag.SetCover()
tags = append(tags, tag)
db.Conn.QueryRow("SELECT count(*) FROM tags_using WHERE tag_id=? and target_type != ?", tag.ID, IDTypeUser).Scan(&tag.Posts)
}
sort.Sort(tags)
return tags, nil
}

Loading…
Cancel
Save