mirror of
https://codeberg.org/VnPower/PixivFE
synced 2024-12-06 19:16:23 +01:00
Merge pull request 'user-len-checks' (#125) from user-len-checks into v2
Reviewed-on: https://codeberg.org/VnPower/PixivFE/pulls/125
This commit is contained in:
@@ -118,15 +118,15 @@
|
||||
|
||||
</div>
|
||||
|
||||
<!-- TODO: check whether there actually are any related works before rendering this section -->
|
||||
<!-- col-12 to display Related works at full width -->
|
||||
{{- if len(.Illust.RelatedWorks) > 0 }}
|
||||
<div class="col-12 mt-5">
|
||||
<h2>Related works</h2>
|
||||
<!-- Gradually increase the number of artworks shown per row along with device width -->
|
||||
<div class="row row-cols-2 row-cols-md-4 row-cols-lg-6 g-4">
|
||||
{{- include "fragments/small-tn" .Illust.RelatedWorks }}
|
||||
</div>
|
||||
<h2>Related works</h2>
|
||||
<!-- Gradually increase the number of artworks shown per row along with device width -->
|
||||
<div class="row row-cols-2 row-cols-md-4 row-cols-lg-6 g-4">
|
||||
{{- include "fragments/small-tn" .Illust.RelatedWorks }}
|
||||
</div>
|
||||
</div>
|
||||
{{- end }}
|
||||
|
||||
</div>
|
||||
{{- end }}
|
||||
|
||||
@@ -24,9 +24,10 @@
|
||||
Tip: For absolute URI paths, start the baseURL with a forward slash.
|
||||
*}
|
||||
|
||||
{{- block UnderlineNav(baseURL, paths, names, activeState="") }}
|
||||
{{- block UnderlineNav(baseURL, paths, names, categoryCounts, activeState="") }}
|
||||
<ul class="nav nav-underline">
|
||||
{{- range i, k := paths }}
|
||||
{{- if categoryCounts[i] > 0 }}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link
|
||||
{{ activeState == k ? "active border-custom-color fw-bold" : "fw-semibold" }}
|
||||
@@ -36,6 +37,7 @@
|
||||
{{ names[i] }}
|
||||
</a>
|
||||
</li>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
</ul>
|
||||
{{- end }}
|
||||
|
||||
+15
-12
@@ -144,9 +144,10 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{* NOTE: temporarily disabled to prevent malformed strings from appearing in i18n
|
||||
{*
|
||||
NOTE: temporarily disabled to prevent malformed strings from appearing in i18n
|
||||
<noscript>
|
||||
{* NOTE: using col-12 because noscript forces d-inline which causes justify-content-center to break *}
|
||||
<!-- NOTE: using col-12 because noscript forces d-inline which causes justify-content-center to break -->
|
||||
<div class="col-12">
|
||||
<div class="custom-card">
|
||||
<div class="custom-card-body bg-charcoal-surface1 p-4">
|
||||
@@ -398,19 +399,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-5">
|
||||
<h2>Related works</h2>
|
||||
<div class="row row-cols-1 row-cols-lg-2 g-4">
|
||||
{{- range .NovelRelated }}
|
||||
<div class="col mt-1">
|
||||
<div class="custom-novel-card bg-black p-3 py-4 thumbnail-hover-dark">
|
||||
{{- include "fragments/novel-tn" . }}
|
||||
{{- if len(.NovelRelated) > 0 }}
|
||||
<div class="col-12 mt-5">
|
||||
<h2>Related works</h2>
|
||||
<div class="row row-cols-1 row-cols-lg-2 g-4">
|
||||
{{- range .NovelRelated }}
|
||||
<div class="col mt-1">
|
||||
<div class="custom-novel-card bg-black p-3 py-4 thumbnail-hover-dark">
|
||||
{{- include "fragments/novel-tn" . }}
|
||||
</div>
|
||||
<hr class="my-0">
|
||||
</div>
|
||||
<hr class="my-0">
|
||||
{{- end }}
|
||||
</div>
|
||||
{{- end }}
|
||||
</div>
|
||||
</div>
|
||||
{{- end }}
|
||||
</div>
|
||||
|
||||
<!-- End of main content -->
|
||||
|
||||
@@ -72,7 +72,8 @@
|
||||
{{- baseURL := "/users/" + .User.ID + "/" }}
|
||||
{{- paths := slice("" + "#checkpoint", "illustrations" + "#checkpoint", "manga" + "#checkpoint", "novels" + "#checkpoint", "bookmarks" + "#checkpoint") }}
|
||||
{{- names := slice("All", "Illustrations", "Manga", "Novels", "Bookmarks") }}
|
||||
{{- yield UnderlineNav(baseURL=baseURL, paths=paths, names=names, activeState=.Category + "#checkpoint") }}
|
||||
{{- categoryCounts := slice(.User.AllCount, .User.IllustCount, .User.MangaCount, .User.NovelCount, .User.BookmarksCount) }}
|
||||
{{- yield UnderlineNav(baseURL=baseURL, paths=paths, names=names, categoryCounts=categoryCounts, activeState=.Category + "#checkpoint") }}
|
||||
</div>
|
||||
|
||||
<!-- User content -->
|
||||
@@ -103,7 +104,7 @@
|
||||
|
||||
<!-- Pagination -->
|
||||
{{- url := "/users/" + .User.ID + "/" + .Category + "?page="}}
|
||||
{{- paginationData := createPaginator(url, "#checkpoint", .Page, -1, 1, 5) }}
|
||||
{{- paginationData := createPaginator(url, "#checkpoint", .Page, .PageLimit, 1, 5) }}
|
||||
{{- yield pagination(data=paginationData) }}
|
||||
</div>
|
||||
{{- end }}
|
||||
|
||||
+1
-1
@@ -420,7 +420,7 @@ func GetArtworkByID(r *http.Request, id string, full bool) (*Illust, error) {
|
||||
idsString += fmt.Sprintf("&ids[]=%d", ids[i])
|
||||
}
|
||||
|
||||
recent, err := GetUserArtworks(r, illust.UserID, idsString)
|
||||
recent, err := GetUserArtworkList(r, illust.UserID, idsString)
|
||||
if err != nil {
|
||||
cerr <- err
|
||||
return
|
||||
|
||||
+123
-87
@@ -43,23 +43,30 @@ type FrequentTag struct {
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID string `json:"userId"`
|
||||
Name string `json:"name"`
|
||||
Avatar string `json:"imageBig"`
|
||||
Following int `json:"following"`
|
||||
MyPixiv int `json:"mypixivCount"`
|
||||
Comment HTML `json:"commentHtml"`
|
||||
Webpage string `json:"webpage"`
|
||||
SocialRaw json.RawMessage `json:"social"`
|
||||
Artworks []ArtworkBrief `json:"artworks"`
|
||||
Novels []NovelBrief `json:"novels"`
|
||||
Background map[string]any `json:"background"`
|
||||
ArtworksCount int
|
||||
FrequentTags []FrequentTag
|
||||
Social map[string]map[string]string
|
||||
BackgroundImage string
|
||||
NovelSeries []NovelSeries
|
||||
MangaSeries []MangaSeries
|
||||
ID string `json:"userId"`
|
||||
Name string `json:"name"`
|
||||
Avatar string `json:"imageBig"`
|
||||
Following int `json:"following"`
|
||||
MyPixiv int `json:"mypixivCount"`
|
||||
Comment HTML `json:"commentHtml"`
|
||||
Webpage string `json:"webpage"`
|
||||
SocialRaw json.RawMessage `json:"social"`
|
||||
Artworks []ArtworkBrief `json:"artworks"`
|
||||
Novels []NovelBrief `json:"novels"`
|
||||
Background map[string]any `json:"background"`
|
||||
CategoryItemCount int
|
||||
FrequentTags []FrequentTag
|
||||
Social map[string]map[string]string
|
||||
BackgroundImage string
|
||||
NovelSeries []NovelSeries
|
||||
MangaSeries []MangaSeries
|
||||
|
||||
// The following fields are internal to PixivFE, used to display the number of works for a given category
|
||||
AllCount int
|
||||
IllustCount int
|
||||
MangaCount int
|
||||
NovelCount int
|
||||
BookmarksCount int
|
||||
}
|
||||
|
||||
// Utility function to compute slice bounds safely
|
||||
@@ -115,7 +122,7 @@ func GetFrequentTags(r *http.Request, ids string, category UserArtCategory) ([]F
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
func GetUserArtworks(r *http.Request, id, ids string) ([]ArtworkBrief, error) {
|
||||
func GetUserArtworkList(r *http.Request, id, ids string) ([]ArtworkBrief, error) {
|
||||
var works []ArtworkBrief
|
||||
|
||||
URL := GetUserFullArtworkURL(id, ids)
|
||||
@@ -150,7 +157,7 @@ func GetUserArtworks(r *http.Request, id, ids string) ([]ArtworkBrief, error) {
|
||||
}
|
||||
|
||||
func GetUserNovels(r *http.Request, id, ids string) ([]NovelBrief, error) {
|
||||
// VnPower: we can merge this function into GetUserArtworks, but I want to make things simple for now
|
||||
// VnPower: we can merge this function into GetUserArtworks (now GetUserArtworkList), but I want to make things simple for now
|
||||
var works []NovelBrief
|
||||
|
||||
URL := GetUserFullNovelURL(id, ids)
|
||||
@@ -184,12 +191,12 @@ func GetUserNovels(r *http.Request, id, ids string) ([]NovelBrief, error) {
|
||||
return works, nil
|
||||
}
|
||||
|
||||
func GetUserArtworksIDAndSeries(r *http.Request, id string, category UserArtCategory, page int) (string, int, json.RawMessage, error) {
|
||||
func GetUserArtworksIDAndSeries(r *http.Request, id string, category UserArtCategory, page int) (string, int, int, int, int, json.RawMessage, error) {
|
||||
URL := GetUserArtworksURL(id)
|
||||
|
||||
resp, err := API_GET_UnwrapJson(r.Context(), URL, "")
|
||||
if err != nil {
|
||||
return "", -1, nil, err
|
||||
return "", -1, -1, -1, -1, nil, err
|
||||
}
|
||||
|
||||
resp = session.ProxyImageUrl(r, resp)
|
||||
@@ -204,7 +211,7 @@ func GetUserArtworksIDAndSeries(r *http.Request, id string, category UserArtCate
|
||||
|
||||
err = json.Unmarshal([]byte(resp), &body)
|
||||
if err != nil {
|
||||
return "", -1, nil, err
|
||||
return "", -1, -1, -1, -1, nil, err
|
||||
}
|
||||
|
||||
var ids []int
|
||||
@@ -213,7 +220,7 @@ func GetUserArtworksIDAndSeries(r *http.Request, id string, category UserArtCate
|
||||
// TODO: is this necessary
|
||||
err = json.Unmarshal([]byte(resp), &body)
|
||||
if err != nil {
|
||||
return "", -1, nil, err
|
||||
return "", -1, -1, -1, -1, nil, err
|
||||
}
|
||||
|
||||
var illusts map[int]string
|
||||
@@ -221,6 +228,9 @@ func GetUserArtworksIDAndSeries(r *http.Request, id string, category UserArtCate
|
||||
var novels map[int]string
|
||||
var series json.RawMessage
|
||||
count := 0
|
||||
illustCount := 0
|
||||
mangaCount := 0
|
||||
novelCount := 0
|
||||
|
||||
// Get the keys, because Pixiv only returns IDs (very evil)
|
||||
|
||||
@@ -232,6 +242,7 @@ func GetUserArtworksIDAndSeries(r *http.Request, id string, category UserArtCate
|
||||
ids = append(ids, k)
|
||||
count++
|
||||
}
|
||||
illustCount = len(illusts)
|
||||
}
|
||||
if category == UserArt_Manga || category == UserArt_Any {
|
||||
if err = json.Unmarshal(body.Mangas, &mangas); err != nil {
|
||||
@@ -241,6 +252,7 @@ func GetUserArtworksIDAndSeries(r *http.Request, id string, category UserArtCate
|
||||
ids = append(ids, k)
|
||||
count++
|
||||
}
|
||||
mangaCount = len(mangas)
|
||||
series = body.MangaSeries
|
||||
}
|
||||
if category == UserArt_Novel {
|
||||
@@ -251,6 +263,7 @@ func GetUserArtworksIDAndSeries(r *http.Request, id string, category UserArtCate
|
||||
ids = append(ids, k)
|
||||
count++
|
||||
}
|
||||
novelCount = len(novels)
|
||||
series = body.NovelSeries
|
||||
}
|
||||
|
||||
@@ -260,19 +273,75 @@ func GetUserArtworksIDAndSeries(r *http.Request, id string, category UserArtCate
|
||||
worksPerPage := 30.0
|
||||
start, end, err := computeSliceBounds(page, worksPerPage, len(ids))
|
||||
if err != nil {
|
||||
return "", -1, nil, err
|
||||
return "", -1, -1, -1, -1, nil, err
|
||||
}
|
||||
|
||||
for _, k := range ids[start:end] {
|
||||
idsString += fmt.Sprintf("&ids[]=%d", k)
|
||||
}
|
||||
|
||||
return idsString, count, series, nil
|
||||
return idsString, count, illustCount, mangaCount, novelCount, series, nil
|
||||
}
|
||||
|
||||
func GetUserArtwork(r *http.Request, id string, category UserArtCategory, page int, getTags bool) (User, error) {
|
||||
func initializeUserCounts(user *User) {
|
||||
user.AllCount = 0
|
||||
user.IllustCount = 0
|
||||
user.MangaCount = 0
|
||||
user.NovelCount = 0
|
||||
user.BookmarksCount = 0
|
||||
user.CategoryItemCount = 0
|
||||
}
|
||||
|
||||
func fetchAndProcessArtworks(r *http.Request, id, ids string, category UserArtCategory) ([]ArtworkBrief, []NovelBrief, error) {
|
||||
var artworks []ArtworkBrief
|
||||
var novels []NovelBrief
|
||||
var err error
|
||||
|
||||
if category == UserArt_Novel {
|
||||
novels, err = GetUserNovels(r, id, ids)
|
||||
} else {
|
||||
artworks, err = GetUserArtworkList(r, id, ids)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Sort the works
|
||||
if category == UserArt_Novel {
|
||||
sort.Slice(novels[:], func(i, j int) bool {
|
||||
return numberGreaterThan(novels[i].ID, novels[j].ID)
|
||||
})
|
||||
} else {
|
||||
sort.Slice(artworks[:], func(i, j int) bool {
|
||||
return numberGreaterThan(artworks[i].ID, artworks[j].ID)
|
||||
})
|
||||
}
|
||||
|
||||
return artworks, novels, nil
|
||||
}
|
||||
|
||||
func handleSeriesData(series json.RawMessage, category UserArtCategory) ([]NovelSeries, []MangaSeries) {
|
||||
var novelSeries []NovelSeries
|
||||
var mangaSeries []MangaSeries
|
||||
|
||||
if series != nil {
|
||||
if category == UserArt_Novel {
|
||||
_ = json.Unmarshal(series, &novelSeries)
|
||||
} else {
|
||||
_ = json.Unmarshal(series, &mangaSeries)
|
||||
}
|
||||
}
|
||||
|
||||
return novelSeries, mangaSeries
|
||||
}
|
||||
|
||||
func GetUserProfile(r *http.Request, id string, category UserArtCategory, page int, getTags bool) (User, error) {
|
||||
var user User
|
||||
|
||||
// Initialize all count fields
|
||||
initializeUserCounts(&user)
|
||||
|
||||
token := session.GetUserToken(r)
|
||||
|
||||
URL := GetUserInformationURL(id)
|
||||
@@ -289,75 +358,49 @@ func GetUserArtwork(r *http.Request, id string, category UserArtCategory, page i
|
||||
return user, err
|
||||
}
|
||||
|
||||
// Get counts for all categories
|
||||
_, allCount, illustCount, mangaCount, novelCount, _, err := GetUserArtworksIDAndSeries(r, id, UserArt_Any, 1)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
user.AllCount = allCount
|
||||
user.IllustCount = illustCount
|
||||
user.MangaCount = mangaCount
|
||||
user.NovelCount = novelCount
|
||||
|
||||
// Get bookmarks count
|
||||
_, bookmarksCount, err := GetUserBookmarks(r, id, "show", 1)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
user.BookmarksCount = bookmarksCount
|
||||
|
||||
if category == UserArt_Bookmarks {
|
||||
// Bookmarks
|
||||
works, count, err := GetUserBookmarks(r, id, "show", page)
|
||||
works, _, err := GetUserBookmarks(r, id, "show", page)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
||||
user.Artworks = works
|
||||
|
||||
// Public bookmarks count
|
||||
user.ArtworksCount = count
|
||||
} else if category == UserArt_Novel {
|
||||
ids, count, series, err := GetUserArtworksIDAndSeries(r, id, category, page)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
// Check if the user has artworks available or not
|
||||
works, err := GetUserNovels(r, id, ids)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
||||
// IDK but the order got shuffled even though Pixiv sorted the IDs in the response
|
||||
sort.Slice(works[:], func(i, j int) bool {
|
||||
left := works[i].ID
|
||||
right := works[j].ID
|
||||
return numberGreaterThan(left, right)
|
||||
})
|
||||
user.Novels = works
|
||||
|
||||
if getTags {
|
||||
user.FrequentTags, err = GetFrequentTags(r, ids, category)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var novelSeries []NovelSeries
|
||||
if series != nil {
|
||||
if err = json.Unmarshal(series, &novelSeries); err == nil {
|
||||
user.NovelSeries = novelSeries
|
||||
}
|
||||
}
|
||||
|
||||
// Artworks count
|
||||
user.ArtworksCount = count
|
||||
user.CategoryItemCount = bookmarksCount
|
||||
} else {
|
||||
ids, count, series, err := GetUserArtworksIDAndSeries(r, id, category, page)
|
||||
ids, count, _, _, _, series, err := GetUserArtworksIDAndSeries(r, id, category, page)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
// Check if the user has artworks available or not
|
||||
works, err := GetUserArtworks(r, id, ids)
|
||||
artworks, novels, err := fetchAndProcessArtworks(r, id, ids, category)
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
||||
// IDK but the order got shuffled even though Pixiv sorted the IDs in the response
|
||||
sort.Slice(works[:], func(i, j int) bool {
|
||||
left := works[i].ID
|
||||
right := works[j].ID
|
||||
return numberGreaterThan(left, right)
|
||||
})
|
||||
user.Artworks = works
|
||||
if category == UserArt_Novel {
|
||||
user.Novels = novels
|
||||
} else {
|
||||
user.Artworks = artworks
|
||||
}
|
||||
|
||||
if getTags {
|
||||
user.FrequentTags, err = GetFrequentTags(r, ids, category)
|
||||
@@ -367,15 +410,8 @@ func GetUserArtwork(r *http.Request, id string, category UserArtCategory, page i
|
||||
}
|
||||
}
|
||||
|
||||
var mangaSeries []MangaSeries
|
||||
if series != nil {
|
||||
if err = json.Unmarshal(series, &mangaSeries); err == nil {
|
||||
user.MangaSeries = mangaSeries
|
||||
}
|
||||
}
|
||||
|
||||
// Artworks count
|
||||
user.ArtworksCount = count
|
||||
user.NovelSeries, user.MangaSeries = handleSeriesData(series, category)
|
||||
user.CategoryItemCount = count
|
||||
}
|
||||
|
||||
err = user.ParseSocial()
|
||||
|
||||
+16
-4
@@ -33,7 +33,7 @@ func fetchData(r *http.Request, getTags bool) (userPageData, error) {
|
||||
return userPageData{}, err
|
||||
}
|
||||
|
||||
user, err := core.GetUserArtwork(r, id, category, page, getTags)
|
||||
user, err := core.GetUserProfile(r, id, category, page, getTags)
|
||||
if err != nil {
|
||||
return userPageData{}, err
|
||||
}
|
||||
@@ -47,10 +47,15 @@ func fetchData(r *http.Request, getTags bool) (userPageData, error) {
|
||||
worksPerPage = 30.0
|
||||
}
|
||||
|
||||
worksCount = user.ArtworksCount
|
||||
worksCount = user.CategoryItemCount
|
||||
pageLimit := int(math.Ceil(float64(worksCount) / worksPerPage))
|
||||
|
||||
return userPageData{user, category, pageLimit, page}, nil
|
||||
return userPageData{
|
||||
user: user,
|
||||
category: category,
|
||||
pageLimit: pageLimit,
|
||||
page: page,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func UserPage(w http.ResponseWriter, r *http.Request) error {
|
||||
@@ -59,7 +64,14 @@ func UserPage(w http.ResponseWriter, r *http.Request) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return RenderHTML(w, r, Data_user{Title: data.user.Name, User: data.user, Category: data.category, PageLimit: data.pageLimit, Page: data.page, MetaImage: data.user.BackgroundImage})
|
||||
return RenderHTML(w, r, Data_user{
|
||||
Title: data.user.Name,
|
||||
User: data.user,
|
||||
Category: data.category,
|
||||
PageLimit: data.pageLimit,
|
||||
Page: data.page,
|
||||
MetaImage: data.user.BackgroundImage,
|
||||
})
|
||||
}
|
||||
|
||||
func UserAtomFeed(w http.ResponseWriter, r *http.Request) error {
|
||||
|
||||
Reference in New Issue
Block a user