Add related resources parsing

This commit is contained in:
nyne
2025-05-23 16:21:58 +08:00
parent 926391dc85
commit 0bc97b1db5
4 changed files with 79 additions and 16 deletions

View File

@@ -2,7 +2,6 @@ package api
import ( import (
"encoding/json" "encoding/json"
"github.com/gofiber/fiber/v3/log"
"net/url" "net/url"
"nysoure/server/dao" "nysoure/server/dao"
"nysoure/server/model" "nysoure/server/model"
@@ -10,6 +9,8 @@ import (
"nysoure/server/utils" "nysoure/server/utils"
"strconv" "strconv"
"github.com/gofiber/fiber/v3/log"
"github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3"
) )
@@ -54,7 +55,8 @@ func handleGetResource(c fiber.Ctx) error {
if err != nil { if err != nil {
return model.NewRequestError("Invalid resource ID") return model.NewRequestError("Invalid resource ID")
} }
resource, err := service.GetResource(uint(id)) host := c.Hostname()
resource, err := service.GetResource(uint(id), host)
if err != nil { if err != nil {
return err return err
} }

View File

@@ -75,7 +75,7 @@ func serveIndexHtml(c fiber.Ctx) error {
idStr := strings.TrimPrefix(path, "/resources/") idStr := strings.TrimPrefix(path, "/resources/")
id, err := strconv.Atoi(idStr) id, err := strconv.Atoi(idStr)
if err == nil { if err == nil {
r, err := service.GetResource(uint(id)) r, err := service.GetResource(uint(id), "")
if err == nil { if err == nil {
if len(r.Images) > 0 { if len(r.Images) > 0 {
preview = fmt.Sprintf("%s/api/image/%d", serverBaseURL, r.Images[0].ID) preview = fmt.Sprintf("%s/api/image/%d", serverBaseURL, r.Images[0].ID)

View File

@@ -30,17 +30,18 @@ type ResourceView struct {
} }
type ResourceDetailView struct { type ResourceDetailView struct {
ID uint `json:"id"` ID uint `json:"id"`
Title string `json:"title"` Title string `json:"title"`
AlternativeTitles []string `json:"alternativeTitles"` AlternativeTitles []string `json:"alternativeTitles"`
Article string `json:"article"` Article string `json:"article"`
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
Tags []TagView `json:"tags"` Tags []TagView `json:"tags"`
Images []ImageView `json:"images"` Images []ImageView `json:"images"`
Files []FileView `json:"files"` Files []FileView `json:"files"`
Author UserView `json:"author"` Author UserView `json:"author"`
Views uint `json:"views"` Views uint `json:"views"`
Downloads uint `json:"downloads"` Downloads uint `json:"downloads"`
Related []ResourceView `json:"related"`
} }
func (r *Resource) ToView() ResourceView { func (r *Resource) ToView() ResourceView {

View File

@@ -1,9 +1,13 @@
package service package service
import ( import (
"github.com/gofiber/fiber/v3/log" "net/url"
"nysoure/server/dao" "nysoure/server/dao"
"nysoure/server/model" "nysoure/server/model"
"strconv"
"strings"
"github.com/gofiber/fiber/v3/log"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -55,13 +59,69 @@ func CreateResource(uid uint, params *ResourceCreateParams) (uint, error) {
return r.ID, nil return r.ID, nil
} }
func GetResource(id uint) (*model.ResourceDetailView, error) { func findRelatedResources(r model.Resource, host string) []model.ResourceView {
lines := strings.Split(r.Article, "\n")
var relatedResources []model.ResourceView
for _, line := range lines {
r := parseResourceIfPresent(line, host)
if r != nil {
relatedResources = append(relatedResources, *r)
}
}
return relatedResources
}
func parseResourceIfPresent(line string, host string) *model.ResourceView {
if len(line) < 4 {
return nil
}
if !strings.HasPrefix(line, "[") || !strings.HasSuffix(line, ")") {
return nil
}
if !strings.Contains(line, "](") {
return nil
}
splites := strings.Split(line, "(")
if len(splites) != 2 {
return nil
}
u := strings.TrimSuffix(splites[1], ")")
u = strings.TrimSpace(u)
parsed, err := url.Parse(u)
if err != nil {
return nil
}
if parsed.Hostname() != host {
return nil
}
path := parsed.Path
if !strings.HasPrefix(path, "/resources/") {
return nil
}
idStr := strings.TrimPrefix(path, "/resources/")
id, err := strconv.Atoi(idStr)
if err != nil {
return nil
}
r, err := dao.GetResourceByID(uint(id))
if err != nil {
return nil
}
v := r.ToView()
return &v
}
func GetResource(id uint, host string) (*model.ResourceDetailView, error) {
r, err := dao.GetResourceByID(id) r, err := dao.GetResourceByID(id)
_ = dao.AddResourceViewCount(id) _ = dao.AddResourceViewCount(id)
if err != nil { if err != nil {
return nil, err return nil, err
} }
v := r.ToDetailView() v := r.ToDetailView()
if host != "" {
related := findRelatedResources(r, host)
v.Related = related
}
return &v, nil return &v, nil
} }