Feature: basic ranking calendar #20
This commit is contained in:
parent
af2c360e5c
commit
eae2ddbf12
8 changed files with 210 additions and 1 deletions
3
go.mod
3
go.mod
|
@ -27,5 +27,6 @@ require (
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasthttp v1.47.0 // indirect
|
github.com/valyala/fasthttp v1.47.0 // indirect
|
||||||
github.com/valyala/tcplisten v1.0.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
4
go.sum
|
@ -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-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.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.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-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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
|
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.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-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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||||
|
|
|
@ -2,12 +2,36 @@ package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
"pixivfe/models"
|
"pixivfe/models"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"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) {
|
func (p *PixivClient) GetNewestArtworks(worktype string, r18 string) ([]models.IllustShort, error) {
|
||||||
var newWorks []models.IllustShort
|
var newWorks []models.IllustShort
|
||||||
lastID := "0"
|
lastID := "0"
|
||||||
|
@ -138,3 +162,57 @@ func (p *PixivClient) GetDiscoveryArtwork(mode string, count int) ([]models.Illu
|
||||||
|
|
||||||
return artworks, nil
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -434,6 +434,47 @@ body {
|
||||||
font-weight: normal;
|
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 {
|
.switcher {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
.switcher {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
|
||||||
|
|
24
template/pages/ranking_log.jet.html
Normal file
24
template/pages/ranking_log.jet.html
Normal 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>
|
|
@ -231,6 +231,23 @@ func discovery_page(c *fiber.Ctx) error {
|
||||||
return c.Render("pages/discovery", fiber.Map{"Title": "Discovery", "Artworks": artworks})
|
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 {
|
func following_works_page(c *fiber.Ctx) error {
|
||||||
image_proxy := get_session_value(c, "image-proxy")
|
image_proxy := get_session_value(c, "image-proxy")
|
||||||
if image_proxy == nil {
|
if image_proxy == nil {
|
||||||
|
|
|
@ -39,12 +39,14 @@ func SetupRoutes(r *fiber.App) {
|
||||||
PC = NewPixivClient(5000)
|
PC = NewPixivClient(5000)
|
||||||
PC.SetSessionID(configs.Token)
|
PC.SetSessionID(configs.Token)
|
||||||
PC.SetUserAgent(configs.UserAgent)
|
PC.SetUserAgent(configs.UserAgent)
|
||||||
|
PC.AddHeader("Accept-Language", "en-US,en;q=0.5")
|
||||||
|
|
||||||
r.Get("/", index_page)
|
r.Get("/", index_page)
|
||||||
r.Get("artworks/:id/", artwork_page)
|
r.Get("artworks/:id/", artwork_page)
|
||||||
r.Get("users/:id/:category?", user_page)
|
r.Get("users/:id/:category?", user_page)
|
||||||
r.Get("newest", newest_artworks_page)
|
r.Get("newest", newest_artworks_page)
|
||||||
r.Get("ranking", ranking_page)
|
r.Get("ranking", ranking_page)
|
||||||
|
r.Get("ranking_log", ranking_log_page)
|
||||||
r.Get("tags/:name", search_page)
|
r.Get("tags/:name", search_page)
|
||||||
r.Get("discovery", discovery_page)
|
r.Get("discovery", discovery_page)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue