Feature: basic ranking calendar #20

This commit is contained in:
VnPower 2023-08-26 11:13:51 +07:00
parent af2c360e5c
commit eae2ddbf12
Signed by: vnpower
GPG key ID: 881DE3DEB966106C
8 changed files with 210 additions and 1 deletions

3
go.mod
View file

@ -27,5 +27,6 @@ require (
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.47.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sys v0.11.0 // indirect
)

4
go.sum
View file

@ -61,6 +61,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -79,6 +81,8 @@ golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=

View file

@ -2,12 +2,36 @@ package handler
import (
"fmt"
"html/template"
"net/http"
"pixivfe/models"
"strings"
"time"
"github.com/goccy/go-json"
"golang.org/x/net/html"
)
func get_weekday(n time.Weekday) int {
switch n {
case time.Sunday:
return 1
case time.Monday:
return 2
case time.Tuesday:
return 3
case time.Wednesday:
return 4
case time.Thursday:
return 5
case time.Friday:
return 6
case time.Saturday:
return 7
}
return 0
}
func (p *PixivClient) GetNewestArtworks(worktype string, r18 string) ([]models.IllustShort, error) {
var newWorks []models.IllustShort
lastID := "0"
@ -138,3 +162,57 @@ func (p *PixivClient) GetDiscoveryArtwork(mode string, count int) ([]models.Illu
return artworks, nil
}
func (p *PixivClient) GetRankingLog(mode string, date string, image_proxy string) (template.HTML, error) {
resp, err := http.Get("https://www.pixiv.net/ranking_log.php?mode=daily&date=202308")
if err != nil {
return "", err
}
defer resp.Body.Close()
// Use the html package to parse the response body from the request
doc, err := html.Parse(resp.Body)
if err != nil {
return "", err
}
// Find and print all links on the web page
var links []string
var link func(*html.Node)
link = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "img" {
for _, a := range n.Attr {
if a.Key == "data-src" {
// adds a new link entry when the attribute matches
links = append(links, models.ProxyImage(a.Val, image_proxy))
}
}
}
// traverses the HTML of the webpage from the first child node
for c := n.FirstChild; c != nil; c = c.NextSibling {
link(c)
}
}
link(doc)
now := time.Now()
year := now.Year()
month := now.Month()
lastMonth := time.Date(year, month, 0, 0, 0, 0, 0, time.UTC)
thisMonth := time.Date(year, month+1, 0, 0, 0, 0, 0, time.UTC)
renderString := ""
for i := 0; i <= get_weekday(lastMonth.Weekday()); i++ {
renderString += "<div class=\"calendar-node\"></div>"
}
for i := 0; i < thisMonth.Day(); i++ {
date := fmt.Sprintf("%d%02d%02d", year, month, i+1)
if len(links) > i {
renderString += fmt.Sprintf(`<a href="/ranking?mode=%s&date=%s"><div class="calendar-node" style="background-image: url(%s)"><span>%d</span></div></a>`, mode, date, links[i], i+1)
} else {
renderString += fmt.Sprintf(`<div class="calendar-node"><span>%d</span></div>`, i+1)
}
}
return template.HTML(renderString), nil
}

View file

@ -434,6 +434,47 @@ body {
font-weight: normal;
}
#calendar {
width: 100%;
height: auto;
}
.calendar-weeks,
.calendar-board {
max-width: 1000px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
gap: 5px;
}
.calendar-weeks div {
width: 128px;
text-align: center;
}
.calendar-node {
width: 128px;
height: 128px;
border-radius: 8px;
background-size: cover;
background-position: center;
background-color: #24283b;
position: relative;
}
.calendar-node span {
font-size: small;
color: #c0caf5;
background-color: rgba(26, 27, 38, 0.6);
position: absolute;
top: 0.3rem;
left: 0.3rem;
padding: 0.05rem 0.3rem;
display: flex;
align-items: center;
justify-content: center;
}
.switcher {
border-radius: 10px;
}

View file

@ -516,6 +516,48 @@ body {
}
}
#calendar {
width: 100%;
height: auto;
}
.calendar-weeks,
.calendar-board {
max-width: 1000px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
gap: 5px;
}
.calendar-weeks div {
width: 128px;
text-align: center;
}
.calendar-node {
width: 128px;
height: 128px;
border-radius: 8px;
background-size: cover;
background-position: center;
background-color: $bg-alt;
position: relative;
span {
font-size: small;
color: $fg;
background-color: $bg-alt-dimmed;
position: absolute;
top: 0.3rem;
left: 0.3rem;
padding: 0.05rem 0.3rem;
display: flex;
align-items: center;
justify-content: center;
}
}
.switcher {
border-radius: 10px;

View file

@ -0,0 +1,24 @@
<div class="container">
<h2>Ranking calendar</h2>
<!-- <div class="switcher">
{{ url := "/discovery?mode=" }}
<span class="switch-title">Filter</span>
<a href="{{url}}all" class="switch-button">All</a>
<a href="{{url}}safe" class="switch-button">Safe</a>
<a href="{{url}}r18" class="switch-button">R-18</a>
</div> -->
<div id="calendar">
<div class="calendar-weeks">
<div>Sun</div>
<div>Mon</div>
<div>Tue</div>
<div>Wed</div>
<div>Thu</div>
<div>Fri</div>
<div>Sat</div>
</div>
<div class="calendar-board">
{{ raw: Render }}
</div>
</div>
</div>

View file

@ -231,6 +231,23 @@ func discovery_page(c *fiber.Ctx) error {
return c.Render("pages/discovery", fiber.Map{"Title": "Discovery", "Artworks": artworks})
}
func ranking_log_page(c *fiber.Ctx) error {
image_proxy := get_session_value(c, "image-proxy")
if image_proxy == nil {
image_proxy = &configs.ProxyServer
}
mode := c.Query("mode", "daily")
date := c.Query("date", "")
render, err := PC.GetRankingLog(mode, date, *image_proxy)
if err != nil {
return err
}
return c.Render("pages/ranking_log", fiber.Map{"Title": "Ranking calendar", "Render": render})
}
func following_works_page(c *fiber.Ctx) error {
image_proxy := get_session_value(c, "image-proxy")
if image_proxy == nil {

View file

@ -39,12 +39,14 @@ func SetupRoutes(r *fiber.App) {
PC = NewPixivClient(5000)
PC.SetSessionID(configs.Token)
PC.SetUserAgent(configs.UserAgent)
PC.AddHeader("Accept-Language", "en-US,en;q=0.5")
r.Get("/", index_page)
r.Get("artworks/:id/", artwork_page)
r.Get("users/:id/:category?", user_page)
r.Get("newest", newest_artworks_page)
r.Get("ranking", ranking_page)
r.Get("ranking_log", ranking_log_page)
r.Get("tags/:name", search_page)
r.Get("discovery", discovery_page)