Update: split the files

This commit is contained in:
VnPower 2023-06-15 20:19:14 +07:00
parent 3ae1f9b1fc
commit 49112b8aa0
Signed by: vnpower
GPG key ID: 881DE3DEB966106C
8 changed files with 701 additions and 661 deletions

185
handler/artwork.go Normal file
View file

@ -0,0 +1,185 @@
package handler
import (
"errors"
"fmt"
"sort"
"strconv"
"github.com/goccy/go-json"
"pixivfe/models"
)
func (p *PixivClient) GetArtworkImages(id string) ([]models.Image, error) {
s, _ := p.TextRequest(fmt.Sprintf(ArtworkImagesURL, id))
var pr models.PixivResponse
var resp []models.ImageResponse
var images []models.Image
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return images, err
}
if pr.Error {
return images, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
err = json.Unmarshal([]byte(pr.Body), &resp)
if err != nil {
return images, err
}
// Extract and proxy every images
for _, imageRaw := range resp {
var image models.Image
image.Small = imageRaw.Urls["thumb_mini"]
image.Medium = imageRaw.Urls["small"]
image.Large = imageRaw.Urls["regular"]
image.Original = imageRaw.Urls["original"]
images = append(images, image)
}
return images, nil
}
func (p *PixivClient) GetArtworkByID(id string) (*models.Illust, error) {
s, _ := p.TextRequest(fmt.Sprintf(ArtworkInformationURL, id))
var pr models.PixivResponse
var images []models.Image
// Parse Pixiv response body
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
if pr.Error {
return nil, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
var illust struct {
*models.Illust
Recent map[int]any `json:"userIllusts"`
RawTags json.RawMessage `json:"tags"`
}
// Parse basic illust information
err = json.Unmarshal([]byte(pr.Body), &illust)
if err != nil {
return nil, err
}
// Get illust images
images, err = p.GetArtworkImages(id)
if err != nil {
return nil, err
}
illust.Images = images
// Get recent artworks
var ids []int
idsString := ""
for k := range illust.Recent {
ids = append(ids, k)
}
sort.Sort(sort.Reverse(sort.IntSlice(ids)))
count := len(ids)
for i := 0; i < 30 && i < count; i++ {
idsString += fmt.Sprintf("&ids[]=%d", ids[i])
}
recent, err := p.GetUserArtworks(illust.UserID, idsString)
if err != nil {
return nil, err
}
sort.Slice(recent[:], func(i, j int) bool {
left, _ := strconv.Atoi(recent[i].ID)
right, _ := strconv.Atoi(recent[j].ID)
return left > right
})
illust.RecentWorks = recent
// Get basic user information (the URL above does not contain avatars)
userInfo, err := p.GetUserBasicInformation(illust.UserID)
if err != nil {
return nil, err
}
illust.User = userInfo
// Extract tags
var tags struct {
Tags []struct {
Tag string `json:"tag"`
Translation map[string]string `json:"translation"`
} `json:"tags"`
}
err = json.Unmarshal(illust.RawTags, &tags)
if err != nil {
return nil, err
}
for _, tag := range tags.Tags {
var newTag models.Tag
newTag.Name = tag.Tag
newTag.TranslatedName = tag.Translation["en"]
illust.Tags = append(illust.Tags, newTag)
}
return illust.Illust, nil
}
func (p *PixivClient) GetArtworkComments(id string) ([]models.Comment, error) {
var pr models.PixivResponse
var body struct {
Comments []models.Comment `json:"comments"`
}
s, _ := p.TextRequest(fmt.Sprintf(ArtworkCommentsURL, id))
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
if pr.Error {
return nil, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
err = json.Unmarshal([]byte(pr.Body), &body)
return body.Comments, nil
}
func (p *PixivClient) GetRelatedArtworks(id string) ([]models.IllustShort, error) {
url := fmt.Sprintf(ArtworkRelatedURL, id, 30)
var pr models.PixivResponse
var body struct {
Illusts []models.IllustShort `json:"illusts"`
}
s, _ := p.TextRequest(url)
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(pr.Body), &body)
if err != nil {
return nil, err
}
return body.Illusts, nil
}

83
handler/client.go Normal file
View file

@ -0,0 +1,83 @@
package handler
import (
"errors"
"fmt"
"io/ioutil"
"net/http"
)
type PixivClient struct {
Client *http.Client
Cookie map[string]string
Header map[string]string
Lang string
}
func (p *PixivClient) SetHeader(header map[string]string) {
p.Header = header
}
func (p *PixivClient) AddHeader(key, value string) {
p.Header[key] = value
}
func (p *PixivClient) SetUserAgent(value string) {
p.AddHeader("User-Agent", value)
}
func (p *PixivClient) SetCookie(cookie map[string]string) {
p.Cookie = cookie
}
func (p *PixivClient) AddCookie(key, value string) {
p.Cookie[key] = value
}
func (p *PixivClient) SetSessionID(value string) {
p.Cookie["PHPSESSID"] = value
}
func (p *PixivClient) SetLang(lang string) {
p.Lang = lang
}
func (p *PixivClient) Request(URL string) (*http.Response, error) {
req, _ := http.NewRequest("GET", URL, nil)
// Add headers
for k, v := range p.Header {
req.Header.Add(k, v)
}
for k, v := range p.Cookie {
req.AddCookie(&http.Cookie{Name: k, Value: v})
}
// Make a request
resp, err := p.Client.Do(req)
if err != nil {
return resp, err
}
if resp.StatusCode != 200 {
return resp, errors.New(fmt.Sprintf("Pixiv returned code: %d for request %s", resp.StatusCode, URL))
}
return resp, nil
}
func (p *PixivClient) TextRequest(URL string) (string, error) {
resp, err := p.Request(URL)
if err != nil {
return "", err
}
// Extract the bytes from server's response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return string(body), err
}
return string(body), nil
}

19
handler/constants.go Normal file
View file

@ -0,0 +1,19 @@
package handler
const (
ArtworkInformationURL = "https://www.pixiv.net/ajax/illust/%s"
ArtworkImagesURL = "https://www.pixiv.net/ajax/illust/%s/pages"
ArtworkRelatedURL = "https://www.pixiv.net/ajax/illust/%s/recommend/init?limit=%d"
ArtworkCommentsURL = "https://www.pixiv.net/ajax/illusts/comments/roots?illust_id=%s&limit=100"
ArtworkNewestURL = "https://www.pixiv.net/ajax/illust/new?limit=30&type=%s&r18=%s&lastId=%s"
ArtworkRankingURL = "https://www.pixiv.net/ranking.php?format=json&mode=%s&content=%s&p=%s"
ArtworkDiscoveryURL = "https://www.pixiv.net/ajax/discovery/artworks?mode=%s&limit=%d"
SearchTagURL = "https://www.pixiv.net/ajax/search/tags/%s"
SearchArtworksURL = "https://www.pixiv.net/ajax/search/%s/%s?order=%s&mode=%s&p=%s"
SearchTopURL = "https://www.pixiv.net/ajax/search/top/%s"
UserInformationURL = "https://www.pixiv.net/ajax/user/%s?full=1"
UserBasicInformationURL = "https://www.pixiv.net/ajax/user/%s"
UserArtworksURL = "https://www.pixiv.net/ajax/user/%s/profile/all"
UserArtworksFullURL = "https://www.pixiv.net/ajax/user/%s/profile/illusts?work_category=illustManga&is_first_page=0&lang=en%s"
FrequentTagsURL = "https://www.pixiv.net/ajax/tags/frequent/illust?%s"
)

197
handler/handler.go Normal file
View file

@ -0,0 +1,197 @@
package handler
import (
"errors"
"fmt"
"math"
"pixivfe/models"
"sort"
"strconv"
"github.com/goccy/go-json"
)
func (p *PixivClient) GetUserArtworksID(id string, category string, page int) (string, int, error) {
s, _ := p.TextRequest(fmt.Sprintf(UserArtworksURL, id))
var pr models.PixivResponse
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return "", -1, err
}
if pr.Error {
return "", -1, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
var ids []int
var idsString string
var body struct {
Illusts json.RawMessage `json:"illusts"`
Mangas json.RawMessage `json:"manga"`
}
err = json.Unmarshal(pr.Body, &body)
if err != nil {
return "", -1, err
}
var illusts map[int]string
var mangas map[int]string
count := 0
if err = json.Unmarshal(body.Illusts, &illusts); err != nil {
illusts = make(map[int]string)
}
if err = json.Unmarshal(body.Mangas, &mangas); err != nil {
mangas = make(map[int]string)
}
// Get the keys, because Pixiv only returns IDs (very evil)
if category == "illustrations" || category == "artworks" {
for k := range illusts {
ids = append(ids, k)
count++
}
}
if category == "manga" || category == "artworks" {
for k := range mangas {
ids = append(ids, k)
count++
}
}
// Reverse sort the ids
sort.Sort(sort.Reverse(sort.IntSlice(ids)))
worksNumber := float64(count)
worksPerPage := 30.0
if page < 1 || float64(page) > math.Ceil(worksNumber/worksPerPage)+1.0 {
return "", -1, errors.New("Page overflow")
}
start := (page - 1) * int(worksPerPage)
end := int(math.Min(float64(page)*worksPerPage, worksNumber)) // no overflow
for _, k := range ids[start:end] {
idsString += fmt.Sprintf("&ids[]=%d", k)
}
return idsString, count, nil
}
func (p *PixivClient) GetUserArtworks(id string, ids string) ([]models.IllustShort, error) {
url := fmt.Sprintf(UserArtworksFullURL, id, ids)
var pr models.PixivResponse
var works []models.IllustShort
s, err := p.TextRequest(url)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
var body struct {
Illusts map[int]json.RawMessage `json:"works"`
}
err = json.Unmarshal(pr.Body, &body)
if err != nil {
return nil, err
}
for _, v := range body.Illusts {
var illust models.IllustShort
err = json.Unmarshal(v, &illust)
works = append(works, illust)
}
return works, nil
}
func (p *PixivClient) GetUserBasicInformation(id string) (models.UserShort, error) {
var pr models.PixivResponse
var user models.UserShort
s, _ := p.TextRequest(fmt.Sprintf(UserBasicInformationURL, id))
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return user, err
}
if pr.Error {
return user, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
err = json.Unmarshal([]byte(pr.Body), &user)
if err != nil {
return user, err
}
return user, nil
}
func (p *PixivClient) GetUserInformation(id string, category string, page int) (*models.User, error) {
var user *models.User
var pr models.PixivResponse
ids, count, err := p.GetUserArtworksID(id, category, page)
if err != nil {
return nil, err
}
s, _ := p.TextRequest(fmt.Sprintf(UserInformationURL, id))
err = json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
if pr.Error {
return nil, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
var body struct {
*models.User
Background map[string]interface{} `json:"background"`
}
// Basic user information
err = json.Unmarshal([]byte(pr.Body), &body)
if err != nil {
return nil, err
}
user = body.User
// Artworks
works, _ := p.GetUserArtworks(id, ids)
// IDK but the order got shuffled even though Pixiv sorted the IDs in the response
sort.Slice(works[:], func(i, j int) bool {
left, _ := strconv.Atoi(works[i].ID)
right, _ := strconv.Atoi(works[j].ID)
return left > right
})
user.Artworks = works
// Background image
if body.Background != nil {
user.BackgroundImage = body.Background["url"].(string)
}
// Artworks count
user.ArtworksCount = count
// Frequent tags
user.FrequentTags, err = p.GetFrequentTags(ids)
return user, nil
}

8
handler/helpers.go Normal file
View file

@ -0,0 +1,8 @@
package handler
func Min(x, y int) int {
if x < y {
return x
}
return y
}

153
handler/misc.go Normal file
View file

@ -0,0 +1,153 @@
package handler
import (
"errors"
"fmt"
"pixivfe/models"
"strings"
"github.com/goccy/go-json"
)
func (p *PixivClient) GetNewestArtworks(worktype string, r18 string) ([]models.IllustShort, error) {
var pr models.PixivResponse
var newWorks []models.IllustShort
lastID := "0"
for i := 0; i < 10; i++ {
url := fmt.Sprintf(ArtworkNewestURL, worktype, r18, lastID)
s, err := p.TextRequest(url)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
var body struct {
Illusts []models.IllustShort `json:"illusts"`
LastID string `json:"lastId"`
}
err = json.Unmarshal([]byte(pr.Body), &body)
if err != nil {
return nil, err
}
newWorks = append(newWorks, body.Illusts...)
lastID = body.LastID
}
return newWorks, nil
}
func (p *PixivClient) GetRanking(mode string, content string, page string) (models.RankingResponse, error) {
// Ranking data is formatted differently
var pr models.RankingResponse
url := fmt.Sprintf(ArtworkRankingURL, mode, content, page)
s, err := p.TextRequest(url)
if err != nil {
return pr, err
}
err = json.Unmarshal([]byte(s), &pr)
if err != nil {
return pr, err
}
return pr, nil
}
func (p *PixivClient) GetSearch(artworkType string, name string, order string, age_settings string, page string) (*models.SearchResult, error) {
var pr models.PixivResponse
url := fmt.Sprintf(SearchArtworksURL, artworkType, name, order, age_settings, page)
s, err := p.TextRequest(url)
err = json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
// IDK how to do better than this lol
temp := strings.ReplaceAll(string(pr.Body), `"illust"`, `"works"`)
temp = strings.ReplaceAll(temp, `"manga"`, `"works"`)
temp = strings.ReplaceAll(temp, `"illustManga"`, `"works"`)
var resultRaw struct {
*models.SearchResult
ArtworksRaw json.RawMessage `json:"works"`
}
var artworks models.SearchArtworks
var result *models.SearchResult
err = json.Unmarshal([]byte(temp), &resultRaw)
if err != nil {
return nil, err
}
result = resultRaw.SearchResult
err = json.Unmarshal([]byte(resultRaw.ArtworksRaw), &artworks)
if err != nil {
return nil, err
}
result.Artworks = artworks
return result, nil
}
func (p *PixivClient) GetDiscoveryArtwork(mode string, count int) ([]models.IllustShort, error) {
var artworks []models.IllustShort
for count > 0 {
var pr models.PixivResponse
itemsForRequest := Min(100, count)
count -= itemsForRequest
url := fmt.Sprintf(ArtworkDiscoveryURL, mode, itemsForRequest)
s, err := p.TextRequest(url)
if err != nil {
return artworks, err
}
err = json.Unmarshal([]byte(s), &pr)
if pr.Error {
return artworks, errors.New(pr.Message)
}
var thumbnail struct {
Data json.RawMessage `json:"thumbnails"`
}
err = json.Unmarshal([]byte(pr.Body), &thumbnail)
if err != nil {
return nil, err
}
var body struct {
Artworks []models.IllustShort `json:"illust"`
}
err = json.Unmarshal([]byte(thumbnail.Data), &body)
if err != nil {
return nil, err
}
artworks = append(artworks, body.Artworks...)
}
return artworks, nil
}

View file

@ -1,661 +0,0 @@
package handler
import (
"errors"
"fmt"
"io/ioutil"
"math"
"net/http"
"pixivfe/models"
"sort"
"strconv"
"strings"
"github.com/goccy/go-json"
)
type PixivClient struct {
Client *http.Client
Cookie map[string]string
Header map[string]string
Lang string
}
const (
ArtworkInformationURL = "https://www.pixiv.net/ajax/illust/%s"
ArtworkImagesURL = "https://www.pixiv.net/ajax/illust/%s/pages"
ArtworkRelatedURL = "https://www.pixiv.net/ajax/illust/%s/recommend/init?limit=%d"
ArtworkCommentsURL = "https://www.pixiv.net/ajax/illusts/comments/roots?illust_id=%s&limit=100"
ArtworkNewestURL = "https://www.pixiv.net/ajax/illust/new?limit=30&type=%s&r18=%s&lastId=%s"
ArtworkRankingURL = "https://www.pixiv.net/ranking.php?format=json&mode=%s&content=%s&p=%s"
ArtworkDiscoveryURL = "https://www.pixiv.net/ajax/discovery/artworks?mode=%s&limit=%d"
SearchTagURL = "https://www.pixiv.net/ajax/search/tags/%s"
SearchArtworksURL = "https://www.pixiv.net/ajax/search/%s/%s?order=%s&mode=%s&p=%s"
SearchTopURL = "https://www.pixiv.net/ajax/search/top/%s"
UserInformationURL = "https://www.pixiv.net/ajax/user/%s?full=1"
UserBasicInformationURL = "https://www.pixiv.net/ajax/user/%s"
UserArtworksURL = "https://www.pixiv.net/ajax/user/%s/profile/all"
UserArtworksFullURL = "https://www.pixiv.net/ajax/user/%s/profile/illusts?work_category=illustManga&is_first_page=0&lang=en%s"
FrequentTagsURL = "https://www.pixiv.net/ajax/tags/frequent/illust?%s"
)
func (p *PixivClient) SetHeader(header map[string]string) {
p.Header = header
}
func (p *PixivClient) AddHeader(key, value string) {
p.Header[key] = value
}
func (p *PixivClient) SetUserAgent(value string) {
p.AddHeader("User-Agent", value)
}
func (p *PixivClient) SetCookie(cookie map[string]string) {
p.Cookie = cookie
}
func (p *PixivClient) AddCookie(key, value string) {
p.Cookie[key] = value
}
func (p *PixivClient) SetSessionID(value string) {
p.Cookie["PHPSESSID"] = value
}
func (p *PixivClient) SetLang(lang string) {
p.Lang = lang
}
func (p *PixivClient) Request(URL string) (*http.Response, error) {
req, _ := http.NewRequest("GET", URL, nil)
// Add headers
for k, v := range p.Header {
req.Header.Add(k, v)
}
for k, v := range p.Cookie {
req.AddCookie(&http.Cookie{Name: k, Value: v})
}
// Make a request
resp, err := p.Client.Do(req)
if err != nil {
return resp, err
}
if resp.StatusCode != 200 {
return resp, errors.New(fmt.Sprintf("Pixiv returned code: %d for request %s", resp.StatusCode, URL))
}
return resp, nil
}
func Min(x, y int) int {
if x < y {
return x
}
return y
}
func (p *PixivClient) TextRequest(URL string) (string, error) {
resp, err := p.Request(URL)
if err != nil {
return "", err
}
// Extract the bytes from server's response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return string(body), err
}
return string(body), nil
}
func (p *PixivClient) GetArtworkImages(id string) ([]models.Image, error) {
s, _ := p.TextRequest(fmt.Sprintf(ArtworkImagesURL, id))
var pr models.PixivResponse
var resp []models.ImageResponse
var images []models.Image
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return images, err
}
if pr.Error {
return images, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
err = json.Unmarshal([]byte(pr.Body), &resp)
if err != nil {
return images, err
}
// Extract and proxy every images
for _, imageRaw := range resp {
var image models.Image
image.Small = imageRaw.Urls["thumb_mini"]
image.Medium = imageRaw.Urls["small"]
image.Large = imageRaw.Urls["regular"]
image.Original = imageRaw.Urls["original"]
images = append(images, image)
}
return images, nil
}
func (p *PixivClient) GetFrequentTags(ids string) ([]models.FrequentTag, error) {
s, _ := p.TextRequest(fmt.Sprintf(FrequentTagsURL, ids))
var pr models.PixivResponse
var tags []models.FrequentTag
// Parse Pixiv response body
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
if pr.Error {
return nil, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
err = json.Unmarshal([]byte(pr.Body), &tags)
if err != nil {
return nil, err
}
return tags, nil
}
func (p *PixivClient) GetArtworkByID(id string) (*models.Illust, error) {
s, _ := p.TextRequest(fmt.Sprintf(ArtworkInformationURL, id))
var pr models.PixivResponse
var images []models.Image
// Parse Pixiv response body
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
if pr.Error {
return nil, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
var illust struct {
*models.Illust
Recent map[int]any `json:"userIllusts"`
RawTags json.RawMessage `json:"tags"`
}
// Parse basic illust information
err = json.Unmarshal([]byte(pr.Body), &illust)
if err != nil {
return nil, err
}
// Get illust images
images, err = p.GetArtworkImages(id)
if err != nil {
return nil, err
}
illust.Images = images
// Get recent artworks
var ids []int
idsString := ""
for k := range illust.Recent {
ids = append(ids, k)
}
sort.Sort(sort.Reverse(sort.IntSlice(ids)))
count := len(ids)
for i := 0; i < 30 && i < count; i++ {
idsString += fmt.Sprintf("&ids[]=%d", ids[i])
}
recent, err := p.GetUserArtworks(illust.UserID, idsString)
if err != nil {
return nil, err
}
illust.RecentWorks = recent
// Get basic user information (the URL above does not contain avatars)
userInfo, err := p.GetUserBasicInformation(illust.UserID)
if err != nil {
return nil, err
}
illust.User = userInfo
// Extract tags
var tags struct {
Tags []struct {
Tag string `json:"tag"`
Translation map[string]string `json:"translation"`
} `json:"tags"`
}
err = json.Unmarshal(illust.RawTags, &tags)
if err != nil {
return nil, err
}
for _, tag := range tags.Tags {
var newTag models.Tag
newTag.Name = tag.Tag
newTag.TranslatedName = tag.Translation["en"]
illust.Tags = append(illust.Tags, newTag)
}
return illust.Illust, nil
}
func (p *PixivClient) GetArtworkComments(id string) ([]models.Comment, error) {
var pr models.PixivResponse
var body struct {
Comments []models.Comment `json:"comments"`
}
s, _ := p.TextRequest(fmt.Sprintf(ArtworkCommentsURL, id))
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
if pr.Error {
return nil, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
err = json.Unmarshal([]byte(pr.Body), &body)
return body.Comments, nil
}
func (p *PixivClient) GetUserArtworksID(id string, category string, page int) (string, int, error) {
s, _ := p.TextRequest(fmt.Sprintf(UserArtworksURL, id))
var pr models.PixivResponse
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return "", -1, err
}
if pr.Error {
return "", -1, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
var ids []int
var idsString string
var body struct {
Illusts json.RawMessage `json:"illusts"`
Mangas json.RawMessage `json:"manga"`
}
err = json.Unmarshal(pr.Body, &body)
if err != nil {
return "", -1, err
}
var illusts map[int]string
var mangas map[int]string
count := 0
if err = json.Unmarshal(body.Illusts, &illusts); err != nil {
illusts = make(map[int]string)
}
if err = json.Unmarshal(body.Mangas, &mangas); err != nil {
mangas = make(map[int]string)
}
// Get the keys, because Pixiv only returns IDs (very evil)
if category == "illustrations" || category == "artworks" {
for k := range illusts {
ids = append(ids, k)
count++
}
}
if category == "manga" || category == "artworks" {
for k := range mangas {
ids = append(ids, k)
count++
}
}
// Reverse sort the ids
sort.Sort(sort.Reverse(sort.IntSlice(ids)))
worksNumber := float64(count)
worksPerPage := 30.0
if page < 1 || float64(page) > math.Ceil(worksNumber/worksPerPage)+1.0 {
return "", -1, errors.New("Page overflow")
}
start := (page - 1) * int(worksPerPage)
end := int(math.Min(float64(page)*worksPerPage, worksNumber)) // no overflow
for _, k := range ids[start:end] {
idsString += fmt.Sprintf("&ids[]=%d", k)
}
return idsString, count, nil
}
func (p *PixivClient) GetRelatedArtworks(id string) ([]models.IllustShort, error) {
url := fmt.Sprintf(ArtworkRelatedURL, id, 30)
var pr models.PixivResponse
var body struct {
Illusts []models.IllustShort `json:"illusts"`
}
s, _ := p.TextRequest(url)
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(pr.Body), &body)
if err != nil {
return nil, err
}
return body.Illusts, nil
}
func (p *PixivClient) GetUserArtworks(id string, ids string) ([]models.IllustShort, error) {
url := fmt.Sprintf(UserArtworksFullURL, id, ids)
var pr models.PixivResponse
var works []models.IllustShort
s, err := p.TextRequest(url)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
var body struct {
Illusts map[int]json.RawMessage `json:"works"`
}
err = json.Unmarshal(pr.Body, &body)
if err != nil {
return nil, err
}
for _, v := range body.Illusts {
var illust models.IllustShort
err = json.Unmarshal(v, &illust)
works = append(works, illust)
}
return works, nil
}
func (p *PixivClient) GetUserBasicInformation(id string) (models.UserShort, error) {
var pr models.PixivResponse
var user models.UserShort
s, _ := p.TextRequest(fmt.Sprintf(UserBasicInformationURL, id))
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return user, err
}
if pr.Error {
return user, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
err = json.Unmarshal([]byte(pr.Body), &user)
if err != nil {
return user, err
}
return user, nil
}
func (p *PixivClient) GetUserInformation(id string, category string, page int) (*models.User, error) {
var user *models.User
var pr models.PixivResponse
ids, count, err := p.GetUserArtworksID(id, category, page)
if err != nil {
return nil, err
}
s, _ := p.TextRequest(fmt.Sprintf(UserInformationURL, id))
err = json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
if pr.Error {
return nil, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
var body struct {
*models.User
Background map[string]interface{} `json:"background"`
}
// Basic user information
err = json.Unmarshal([]byte(pr.Body), &body)
if err != nil {
return nil, err
}
user = body.User
// Artworks
works, _ := p.GetUserArtworks(id, ids)
// IDK but the order got shuffled even though Pixiv sorted the IDs in the response
sort.Slice(works[:], func(i, j int) bool {
left, _ := strconv.Atoi(works[i].ID)
right, _ := strconv.Atoi(works[j].ID)
return left > right
})
user.Artworks = works
// Background image
if body.Background != nil {
user.BackgroundImage = body.Background["url"].(string)
}
// Artworks count
user.ArtworksCount = count
// Frequent tags
user.FrequentTags, err = p.GetFrequentTags(ids)
return user, nil
}
func (p *PixivClient) GetNewestArtworks(worktype string, r18 string) ([]models.IllustShort, error) {
var pr models.PixivResponse
var newWorks []models.IllustShort
lastID := "0"
for i := 0; i < 10; i++ {
url := fmt.Sprintf(ArtworkNewestURL, worktype, r18, lastID)
s, err := p.TextRequest(url)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
var body struct {
Illusts []models.IllustShort `json:"illusts"`
LastID string `json:"lastId"`
}
err = json.Unmarshal([]byte(pr.Body), &body)
if err != nil {
return nil, err
}
newWorks = append(newWorks, body.Illusts...)
lastID = body.LastID
}
return newWorks, nil
}
func (p *PixivClient) GetRanking(mode string, content string, page string) (models.RankingResponse, error) {
// Ranking data is formatted differently
var pr models.RankingResponse
url := fmt.Sprintf(ArtworkRankingURL, mode, content, page)
s, err := p.TextRequest(url)
if err != nil {
return pr, err
}
err = json.Unmarshal([]byte(s), &pr)
if err != nil {
return pr, err
}
return pr, nil
}
func (p *PixivClient) GetTagData(name string) (models.TagDetail, error) {
var pr models.PixivResponse
var tag models.TagDetail
url := fmt.Sprintf(SearchTagURL, name)
s, err := p.TextRequest(url)
err = json.Unmarshal([]byte(s), &pr)
if err != nil {
return tag, err
}
if pr.Error {
return tag, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
err = json.Unmarshal([]byte(pr.Body), &tag)
if err != nil {
return tag, err
}
return tag, nil
}
func (p *PixivClient) GetSearch(artworkType string, name string, order string, age_settings string, page string) (*models.SearchResult, error) {
var pr models.PixivResponse
url := fmt.Sprintf(SearchArtworksURL, artworkType, name, order, age_settings, page)
s, err := p.TextRequest(url)
err = json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
// IDK how to do better than this lol
temp := strings.ReplaceAll(string(pr.Body), `"illust"`, `"works"`)
temp = strings.ReplaceAll(temp, `"manga"`, `"works"`)
temp = strings.ReplaceAll(temp, `"illustManga"`, `"works"`)
var resultRaw struct {
*models.SearchResult
ArtworksRaw json.RawMessage `json:"works"`
}
var artworks models.SearchArtworks
var result *models.SearchResult
err = json.Unmarshal([]byte(temp), &resultRaw)
if err != nil {
return nil, err
}
result = resultRaw.SearchResult
err = json.Unmarshal([]byte(resultRaw.ArtworksRaw), &artworks)
if err != nil {
return nil, err
}
result.Artworks = artworks
return result, nil
}
func (p *PixivClient) GetDiscoveryArtwork(mode string, count int) ([]models.IllustShort, error) {
var artworks []models.IllustShort
for count > 0 {
var pr models.PixivResponse
itemsForRequest := Min(100, count)
count -= itemsForRequest
url := fmt.Sprintf(ArtworkDiscoveryURL, mode, itemsForRequest)
s, err := p.TextRequest(url)
if err != nil {
return artworks, err
}
err = json.Unmarshal([]byte(s), &pr)
if pr.Error {
return artworks, errors.New(pr.Message)
}
var thumbnail struct {
Data json.RawMessage `json:"thumbnails"`
}
err = json.Unmarshal([]byte(pr.Body), &thumbnail)
if err != nil {
return nil, err
}
var body struct {
Artworks []models.IllustShort `json:"illust"`
}
err = json.Unmarshal([]byte(thumbnail.Data), &body)
if err != nil {
return nil, err
}
artworks = append(artworks, body.Artworks...)
}
return artworks, nil
}

56
handler/tag.go Normal file
View file

@ -0,0 +1,56 @@
package handler
import (
"errors"
"fmt"
"github.com/goccy/go-json"
"pixivfe/models"
)
func (p *PixivClient) GetTagData(name string) (models.TagDetail, error) {
var pr models.PixivResponse
var tag models.TagDetail
url := fmt.Sprintf(SearchTagURL, name)
s, err := p.TextRequest(url)
err = json.Unmarshal([]byte(s), &pr)
if err != nil {
return tag, err
}
if pr.Error {
return tag, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
err = json.Unmarshal([]byte(pr.Body), &tag)
if err != nil {
return tag, err
}
return tag, nil
}
func (p *PixivClient) GetFrequentTags(ids string) ([]models.FrequentTag, error) {
s, _ := p.TextRequest(fmt.Sprintf(FrequentTagsURL, ids))
var pr models.PixivResponse
var tags []models.FrequentTag
// Parse Pixiv response body
err := json.Unmarshal([]byte(s), &pr)
if err != nil {
return nil, err
}
if pr.Error {
return nil, errors.New(fmt.Sprintf("Pixiv returned error message: %s", pr.Message))
}
err = json.Unmarshal([]byte(pr.Body), &tags)
if err != nil {
return nil, err
}
return tags, nil
}