mirror of
https://codeberg.org/VnPower/PixivFE
synced 2024-12-06 19:16:23 +01:00
255 lines
8.0 KiB
Go
255 lines
8.0 KiB
Go
package core
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"codeberg.org/vnpower/pixivfe/v2/audit"
|
|
"codeberg.org/vnpower/pixivfe/v2/server/session"
|
|
"github.com/goccy/go-json"
|
|
)
|
|
|
|
type Novel struct {
|
|
Bookmarks int `json:"bookmarkCount"`
|
|
CommentCount int `json:"commentCount"`
|
|
MarkerCount int `json:"markerCount"`
|
|
CreateDate time.Time `json:"createDate"`
|
|
UploadDate time.Time `json:"uploadDate"`
|
|
Description string `json:"description"`
|
|
ID string `json:"id"`
|
|
Title string `json:"title"`
|
|
Likes int `json:"likeCount"`
|
|
Pages int `json:"pageCount"`
|
|
UserID string `json:"userId"`
|
|
UserName string `json:"userName"`
|
|
Views int `json:"viewCount"`
|
|
IsOriginal bool `json:"isOriginal"`
|
|
IsBungei bool `json:"isBungei"`
|
|
XRestrict int `json:"xRestrict"`
|
|
Restrict int `json:"restrict"`
|
|
Content string `json:"content"`
|
|
CoverURL string `json:"coverUrl"`
|
|
IsBookmarkable bool `json:"isBookmarkable"`
|
|
BookmarkData any `json:"bookmarkData"`
|
|
LikeData bool `json:"likeData"`
|
|
PollData any `json:"pollData"`
|
|
Marker any `json:"marker"`
|
|
Tags struct {
|
|
AuthorID string `json:"authorId"`
|
|
IsLocked bool `json:"isLocked"`
|
|
Tags []struct {
|
|
Name string `json:"tag"`
|
|
} `json:"tags"`
|
|
Writable bool `json:"writable"`
|
|
} `json:"tags"`
|
|
SeriesNavData struct {
|
|
SeriesType string `json:"seriesType"`
|
|
SeriesID int `json:"seriesId"`
|
|
Title string `json:"title"`
|
|
IsConcluded bool `json:"isConcluded"`
|
|
IsReplaceable bool `json:"isReplaceable"`
|
|
IsWatched bool `json:"isWatched"`
|
|
IsNotifying bool `json:"isNotifying"`
|
|
Order int `json:"order"`
|
|
Next struct {
|
|
Title string `json:"title"`
|
|
Order int `json:"order"`
|
|
ID string `json:"id"`
|
|
Available bool `json:"available"`
|
|
} `json:"next"`
|
|
Prev struct {
|
|
Title string `json:"title"`
|
|
Order int `json:"order"`
|
|
ID string `json:"id"`
|
|
Available bool `json:"available"`
|
|
} `json:"prev"`
|
|
} `json:"seriesNavData"`
|
|
HasGlossary bool `json:"hasGlossary"`
|
|
IsUnlisted bool `json:"isUnlisted"`
|
|
// seen values: zh-cn, ja
|
|
Language string `json:"language"`
|
|
CommentOff int `json:"commentOff"`
|
|
CharacterCount int `json:"characterCount"`
|
|
WordCount int `json:"wordCount"`
|
|
UseWordCount bool `json:"useWordCount"`
|
|
ReadingTime int `json:"readingTime"`
|
|
AiType int `json:"aiType"`
|
|
Genre string `json:"genre"`
|
|
Settings struct {
|
|
ViewMode int `json:"viewMode"`
|
|
// ...
|
|
} `json:"suggestedSettings"`
|
|
TextEmbeddedImages map[string]struct {
|
|
NovelImageId string `json:"novelImageId"`
|
|
SanityLevel string `json:"sl"`
|
|
Urls struct {
|
|
Two40Mw string `json:"240mw"`
|
|
Four80Mw string `json:"480mw"`
|
|
One200X1200 string `json:"1200x1200"`
|
|
One28X128 string `json:"128x128"`
|
|
Original string `json:"original"`
|
|
} `json:"urls"`
|
|
} `json:"textEmbeddedImages"`
|
|
CommentsList []Comment
|
|
UserNovels map[string]*NovelBrief `json:"userNovels"`
|
|
}
|
|
|
|
type NovelBrief struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title"`
|
|
XRestrict int `json:"xRestrict"`
|
|
Restrict int `json:"restrict"`
|
|
CoverURL string `json:"url"`
|
|
Tags []string `json:"tags"`
|
|
UserID string `json:"userId"`
|
|
UserName string `json:"userName"`
|
|
UserAvatar string `json:"profileImageUrl"`
|
|
TextCount int `json:"textCount"`
|
|
WordCount int `json:"wordCount"`
|
|
ReadingTime int `json:"readingTime"`
|
|
Description string `json:"description"`
|
|
IsBookmarkable bool `json:"isBookmarkable"`
|
|
BookmarkData any `json:"bookmarkData"`
|
|
Bookmarks int `json:"bookmarkCount"`
|
|
IsOriginal bool `json:"isOriginal"`
|
|
CreateDate time.Time `json:"createDate"`
|
|
UpdateDate time.Time `json:"updateDate"`
|
|
IsMasked bool `json:"isMasked"`
|
|
SeriesID string `json:"seriesId"`
|
|
SeriesTitle string `json:"seriesTitle"`
|
|
IsUnlisted bool `json:"isUnlisted"`
|
|
AiType int `json:"aiType"`
|
|
Genre string `json:"genre"`
|
|
}
|
|
|
|
// Novel embedded illusts
|
|
var (
|
|
re_r = regexp.MustCompile(`\[pixivimage:\d+(-\d+)?\]`)
|
|
re_d = regexp.MustCompile(`\d+(-\d+)?`)
|
|
re_t = regexp.MustCompile(`\"original\":\"(.+?)\"`)
|
|
re_u = regexp.MustCompile(`\[uploadedimage:(\d+)\]`)
|
|
re_id = regexp.MustCompile(`\d+`)
|
|
)
|
|
|
|
func GetNovelByID(auditor *audit.Auditor, r *http.Request, id string) (Novel, error) {
|
|
var novel Novel
|
|
|
|
URL := GetNovelURL(id)
|
|
|
|
resp, err := API_GET_UnwrapJson(r.Context(), auditor, URL, "", r.Header)
|
|
if err != nil {
|
|
return novel, err
|
|
}
|
|
|
|
resp, err = session.ProxyImageUrl(r, resp)
|
|
if err != nil {
|
|
return novel, err
|
|
}
|
|
|
|
err = json.Unmarshal([]byte(resp), &novel)
|
|
if err != nil {
|
|
return novel, err
|
|
}
|
|
|
|
// Clean up UserNovels map by removing null entries
|
|
if novel.UserNovels != nil {
|
|
cleanedUserNovels := make(map[string]*NovelBrief)
|
|
for id, novelBrief := range novel.UserNovels {
|
|
if novelBrief != nil {
|
|
cleanedUserNovels[id] = novelBrief
|
|
}
|
|
}
|
|
novel.UserNovels = cleanedUserNovels
|
|
}
|
|
|
|
// Initialize view mode with the novel's setting
|
|
viewMode := novel.Settings.ViewMode
|
|
|
|
// Check for Cookie_NovelViewMode override
|
|
if cookieViewMode := session.GetCookie(r, session.Cookie_NovelViewMode); cookieViewMode != "" {
|
|
if vmInt, err := strconv.Atoi(cookieViewMode); err == nil {
|
|
viewMode = vmInt
|
|
}
|
|
}
|
|
|
|
// Replace [pixivimage:...] tags with actual images
|
|
novel.Content = re_r.ReplaceAllStringFunc(novel.Content, func(s string) string {
|
|
illustid := re_d.FindString(s)
|
|
|
|
URL := GetInsertIllustURL(novel.ID, illustid)
|
|
response, err := API_GET_UnwrapJson(r.Context(), auditor, URL, "", r.Header)
|
|
if err != nil {
|
|
return "Cannot insert illust" + illustid
|
|
}
|
|
|
|
url := re_t.FindString(response)
|
|
url, err = session.ProxyImageUrl(r, url[11:]) // truncate the "original":
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
// make [pixivimage:illustid-index] jump to anchor
|
|
link := fmt.Sprintf("/artworks/%s", strings.ReplaceAll(illustid, "-", "#"))
|
|
|
|
// Styling for horizontal text (default for viewMode 0 and 1)
|
|
imgClass := "img-fluid w-100 w-md-50 rounded drop-shadow"
|
|
wrapperClass := "d-flex justify-content-start w-100 my-3"
|
|
// Styling for vertical text
|
|
if viewMode == 2 {
|
|
imgClass = "img-fluid h-100 w-100 rounded drop-shadow"
|
|
wrapperClass = "d-flex justify-content-start h-100 ms-3 me-3"
|
|
}
|
|
|
|
return fmt.Sprintf(`<div class="%s"><a href="%s" target="_blank"><img src=%s alt="%s" class="%s"/></a></div>`, wrapperClass, link, url, s, imgClass)
|
|
})
|
|
|
|
// Replace [uploadedimage:...] tags with actual images from TextEmbeddedImages
|
|
novel.Content = re_u.ReplaceAllStringFunc(novel.Content, func(s string) string {
|
|
imageId := re_id.FindString(s)
|
|
if val, ok := novel.TextEmbeddedImages[imageId]; ok {
|
|
// Styling for horizontal text (default for viewMode 0 and 1)
|
|
imgClass := "img-fluid w-100 w-md-50 rounded drop-shadow"
|
|
wrapperClass := "d-flex justify-content-start w-100 my-3"
|
|
// Styling for vertical text
|
|
if viewMode == 2 {
|
|
imgClass = "img-fluid h-100 w-100 rounded drop-shadow"
|
|
wrapperClass = "d-flex justify-content-start h-100 ms-3 me-3"
|
|
}
|
|
return fmt.Sprintf(`<div class="%s"><img src=%s alt="%s" class="%s"/></div>`, wrapperClass, val.Urls.Original, s, imgClass)
|
|
}
|
|
return s
|
|
})
|
|
|
|
return novel, nil
|
|
}
|
|
|
|
func GetNovelRelated(auditor *audit.Auditor, r *http.Request, id string) ([]NovelBrief, error) {
|
|
var novels struct {
|
|
List []NovelBrief `json:"novels"`
|
|
}
|
|
|
|
// hard-coded value, may change
|
|
URL := GetNovelRelatedURL(id, 180)
|
|
|
|
resp, err := API_GET_UnwrapJson(r.Context(), auditor, URL, "", r.Header)
|
|
if err != nil {
|
|
return novels.List, err
|
|
}
|
|
|
|
resp, err = session.ProxyImageUrl(r, resp)
|
|
if err != nil {
|
|
return novels.List, err
|
|
}
|
|
|
|
err = json.Unmarshal([]byte(resp), &novels)
|
|
if err != nil {
|
|
return novels.List, err
|
|
}
|
|
|
|
return novels.List, nil
|
|
}
|