diff --git a/core/artwork.go b/core/artwork.go index 6174160..9ab19de 100644 --- a/core/artwork.go +++ b/core/artwork.go @@ -11,7 +11,7 @@ import ( "codeberg.org/vnpower/pixivfe/v2/session" "github.com/goccy/go-json" - "github.com/gofiber/fiber/v2" + "net/http" ) // Pixiv returns 0, 1, 2 to filter SFW and/or NSFW artworks. @@ -131,7 +131,7 @@ type Illust struct { BookmarkID string } -func GetUserBasicInformation(c *fiber.Ctx, id string) (UserBrief, error) { +func GetUserBasicInformation(c *http.Request, id string) (UserBrief, error) { var user UserBrief URL := GetUserInformationURL(id) @@ -150,7 +150,7 @@ func GetUserBasicInformation(c *fiber.Ctx, id string) (UserBrief, error) { return user, nil } -func GetArtworkImages(c *fiber.Ctx, id string) ([]Image, error) { +func GetArtworkImages(c *http.Request, id string) ([]Image, error) { var resp []ImageResponse var images []Image @@ -188,7 +188,7 @@ func GetArtworkImages(c *fiber.Ctx, id string) ([]Image, error) { return images, nil } -func GetArtworkComments(c *fiber.Ctx, id string) ([]Comment, error) { +func GetArtworkComments(c *http.Request, id string) ([]Comment, error) { var body struct { Comments []Comment `json:"comments"` } @@ -209,7 +209,7 @@ func GetArtworkComments(c *fiber.Ctx, id string) ([]Comment, error) { return body.Comments, nil } -func GetRelatedArtworks(c *fiber.Ctx, id string) ([]ArtworkBrief, error) { +func GetRelatedArtworks(c *http.Request, id string) ([]ArtworkBrief, error) { var body struct { Illusts []ArtworkBrief `json:"illusts"` } @@ -232,7 +232,7 @@ func GetRelatedArtworks(c *fiber.Ctx, id string) ([]ArtworkBrief, error) { return body.Illusts, nil } -func GetArtworkByID(c *fiber.Ctx, id string, full bool) (*Illust, error) { +func GetArtworkByID(c *http.Request, id string, full bool) (*Illust, error) { URL := GetArtworkInformationURL(id) token := session.GetPixivToken(c) diff --git a/core/discovery.go b/core/discovery.go index 0127d2c..a69b9d4 100644 --- a/core/discovery.go +++ b/core/discovery.go @@ -5,11 +5,11 @@ import ( "codeberg.org/vnpower/pixivfe/v2/session" "github.com/goccy/go-json" - "github.com/gofiber/fiber/v2" + "net/http" "github.com/tidwall/gjson" ) -func GetDiscoveryArtwork(c *fiber.Ctx, mode string) ([]ArtworkBrief, error) { +func GetDiscoveryArtwork(c *http.Request, mode string) ([]ArtworkBrief, error) { token := session.GetPixivToken(c) URL := GetDiscoveryURL(mode, 100) @@ -34,7 +34,7 @@ func GetDiscoveryArtwork(c *fiber.Ctx, mode string) ([]ArtworkBrief, error) { return artworks, nil } -func GetDiscoveryNovels(c *fiber.Ctx, mode string) ([]NovelBrief, error) { +func GetDiscoveryNovels(c *http.Request, mode string) ([]NovelBrief, error) { token := session.GetPixivToken(c) URL := GetDiscoveryNovelURL(mode, 100) diff --git a/core/index.go b/core/index.go index 0ea99dc..dbd34bf 100644 --- a/core/index.go +++ b/core/index.go @@ -5,7 +5,7 @@ import ( "codeberg.org/vnpower/pixivfe/v2/session" "github.com/goccy/go-json" - "github.com/gofiber/fiber/v2" + "net/http" "github.com/tidwall/gjson" ) @@ -31,7 +31,7 @@ type LandingArtworks struct { RecommendByTags []RecommendedTags } -func GetLanding(c *fiber.Ctx, mode string) (*LandingArtworks, error) { +func GetLanding(c *http.Request, mode string) (*LandingArtworks, error) { var pages struct { Pixivision []Pixivision `json:"pixivision"` Follow []int `json:"follow"` diff --git a/core/newest.go b/core/newest.go index 1a3dc34..cd42322 100644 --- a/core/newest.go +++ b/core/newest.go @@ -3,10 +3,10 @@ package core import ( "codeberg.org/vnpower/pixivfe/v2/session" "github.com/goccy/go-json" - "github.com/gofiber/fiber/v2" + "net/http" ) -func GetNewestArtworks(c *fiber.Ctx, worktype string, r18 string) ([]ArtworkBrief, error) { +func GetNewestArtworks(c *http.Request, worktype string, r18 string) ([]ArtworkBrief, error) { token := session.GetPixivToken(c) URL := GetNewestArtworksURL(worktype, r18, "0") diff --git a/core/novel.go b/core/novel.go index d9e546b..ce06160 100644 --- a/core/novel.go +++ b/core/novel.go @@ -7,7 +7,7 @@ import ( "codeberg.org/vnpower/pixivfe/v2/session" "github.com/goccy/go-json" - "github.com/gofiber/fiber/v2" + "net/http" ) type Novel struct { @@ -89,7 +89,7 @@ type NovelBrief struct { Genre string `json:"genre"` } -func GetNovelByID(c *fiber.Ctx, id string) (Novel, error) { +func GetNovelByID(c *http.Request, id string) (Novel, error) { var novel Novel URL := GetNovelURL(id) @@ -128,7 +128,7 @@ func GetNovelByID(c *fiber.Ctx, id string) (Novel, error) { return novel, nil } -func GetNovelRelated(c *fiber.Ctx, id string) ([]NovelBrief, error) { +func GetNovelRelated(c *http.Request, id string) ([]NovelBrief, error) { var novels struct { List []NovelBrief `json:"novels"` } diff --git a/core/personal.go b/core/personal.go index c963cd4..36c0f4e 100644 --- a/core/personal.go +++ b/core/personal.go @@ -4,10 +4,10 @@ import ( "codeberg.org/vnpower/pixivfe/v2/session" "github.com/goccy/go-json" - "github.com/gofiber/fiber/v2" + "net/http" ) -func GetNewestFromFollowing(c *fiber.Ctx, mode, page string) ([]ArtworkBrief, error) { +func GetNewestFromFollowing(c *http.Request, mode, page string) ([]ArtworkBrief, error) { token := session.GetPixivToken(c) URL := GetNewestFromFollowingURL(mode, page) diff --git a/core/ranking.go b/core/ranking.go index 48b4922..77e7158 100644 --- a/core/ranking.go +++ b/core/ranking.go @@ -7,7 +7,7 @@ import ( "codeberg.org/vnpower/pixivfe/v2/session" "github.com/goccy/go-json" - "github.com/gofiber/fiber/v2" + "net/http" ) type Ranking struct { @@ -34,7 +34,7 @@ type Ranking struct { NextDate string } -func GetRanking(c *fiber.Ctx, mode, content, date, page string) (Ranking, error) { +func GetRanking(c *http.Request, mode, content, date, page string) (Ranking, error) { URL := GetRankingURL(mode, content, date, page) var ranking Ranking diff --git a/core/rankingCalendar.go b/core/rankingCalendar.go index 99cf191..645096f 100644 --- a/core/rankingCalendar.go +++ b/core/rankingCalendar.go @@ -7,7 +7,7 @@ import ( "time" "codeberg.org/vnpower/pixivfe/v2/session" - "github.com/gofiber/fiber/v2" + "golang.org/x/net/html" ) @@ -34,7 +34,7 @@ func get_weekday(n time.Weekday) int { // note(@iacore): // so the funny thing about Pixiv is that they will return this month's data for a request of a future date // is it a bug or a feature? -func GetRankingCalendar(c *fiber.Ctx, mode string, year, month int) (template.HTML, error) { +func GetRankingCalendar(c *http.Request, mode string, year, month int) (template.HTML, error) { token := session.GetPixivToken(c) URL := GetRankingCalendarURL(mode, year, month) diff --git a/core/requests.go b/core/requests.go index ffab795..9f5305b 100644 --- a/core/requests.go +++ b/core/requests.go @@ -27,18 +27,12 @@ type HttpResponse struct { const DevDir_Response = "/tmp/pixivfe-dev/resp" func CreateResponseAuditFolder() error { - if config.GlobalServerConfig.InDevelopment { - // {err := os.RemoveAll(DevDir_Response) - // if err != nil { - // log.Println(err) - // }} + // err := os.RemoveAll(DevDir_Response) + // if err != nil { + // log.Println(err) + // } - err := os.MkdirAll(DevDir_Response, 0o700) - if err != nil { - return err - } - } - return nil + return os.MkdirAll(DevDir_Response, 0o700) } func logResponseBody(body string) (string, error) { diff --git a/core/tag.go b/core/tag.go index bf0275d..63f37ad 100644 --- a/core/tag.go +++ b/core/tag.go @@ -5,7 +5,7 @@ import ( "codeberg.org/vnpower/pixivfe/v2/session" "github.com/goccy/go-json" - "github.com/gofiber/fiber/v2" + "net/http" ) type TagDetail struct { @@ -71,7 +71,7 @@ func (s SearchPageSettings) ReturnMap() map[string]string { } } -func GetTagData(c *fiber.Ctx, name string) (TagDetail, error) { +func GetTagData(c *http.Request, name string) (TagDetail, error) { var tag TagDetail URL := GetTagDetailURL(name) @@ -91,7 +91,7 @@ func GetTagData(c *fiber.Ctx, name string) (TagDetail, error) { return tag, nil } -func GetSearch(c *fiber.Ctx, settings SearchPageSettings) (*SearchResult, error) { +func GetSearch(c *http.Request, settings SearchPageSettings) (*SearchResult, error) { URL := GetSearchArtworksURL(settings.ReturnMap()) response, err := UnwrapWebAPIRequest(c.Context(), URL, "") diff --git a/core/user.go b/core/user.go index 6294e9e..b88f8df 100644 --- a/core/user.go +++ b/core/user.go @@ -9,7 +9,7 @@ import ( "codeberg.org/vnpower/pixivfe/v2/session" "github.com/goccy/go-json" - "github.com/gofiber/fiber/v2" + "net/http" ) // pixivfe internal data type. not used by pixiv. @@ -73,7 +73,7 @@ func (s *User) ParseSocial() error { return nil } -func GetFrequentTags(c *fiber.Ctx, ids string, category UserArtCategory) ([]FrequentTag, error) { +func GetFrequentTags(c *http.Request, ids string, category UserArtCategory) ([]FrequentTag, error) { var tags []FrequentTag var URL string @@ -96,7 +96,7 @@ func GetFrequentTags(c *fiber.Ctx, ids string, category UserArtCategory) ([]Freq return tags, nil } -func GetUserArtworks(c *fiber.Ctx, id, ids string) ([]ArtworkBrief, error) { +func GetUserArtworks(c *http.Request, id, ids string) ([]ArtworkBrief, error) { var works []ArtworkBrief URL := GetUserFullArtworkURL(id, ids) @@ -130,7 +130,7 @@ func GetUserArtworks(c *fiber.Ctx, id, ids string) ([]ArtworkBrief, error) { return works, nil } -func GetUserNovels(c *fiber.Ctx, id, ids string) ([]NovelBrief, error) { +func GetUserNovels(c *http.Request, id, ids string) ([]NovelBrief, error) { // VnPower: we can merge this function into GetUserArtworks, but I want to make things simple for now var works []NovelBrief @@ -165,7 +165,7 @@ func GetUserNovels(c *fiber.Ctx, id, ids string) ([]NovelBrief, error) { return works, nil } -func GetUserArtworksID(c *fiber.Ctx, id string, category UserArtCategory, page int) (string, int, error) { +func GetUserArtworksID(c *http.Request, id string, category UserArtCategory, page int) (string, int, error) { URL := GetUserArtworksURL(id) resp, err := UnwrapWebAPIRequest(c.Context(), URL, "") @@ -248,7 +248,7 @@ func GetUserArtworksID(c *fiber.Ctx, id string, category UserArtCategory, page i return idsString, count, nil } -func GetUserArtwork(c *fiber.Ctx, id string, category UserArtCategory, page int, getTags bool) (User, error) { +func GetUserArtwork(c *http.Request, id string, category UserArtCategory, page int, getTags bool) (User, error) { var user User token := session.GetPixivToken(c) @@ -354,7 +354,7 @@ func GetUserArtwork(c *fiber.Ctx, id string, category UserArtCategory, page int, return user, nil } -func GetUserBookmarks(c *fiber.Ctx, id, mode string, page int) ([]ArtworkBrief, int, error) { +func GetUserBookmarks(c *http.Request, id, mode string, page int) ([]ArtworkBrief, int, error) { page-- URL := GetUserBookmarksURL(id, mode, page) diff --git a/go.mod b/go.mod index bd6d3dc..1a05aa1 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/CloudyKit/jet/v6 v6.2.0 github.com/go-faker/faker/v4 v4.4.2 github.com/goccy/go-json v0.10.3 - github.com/gofiber/fiber/v2 v2.52.5 github.com/playwright-community/playwright-go v0.4501.1 github.com/tidwall/gjson v1.17.3 golang.org/x/net v0.28.0 @@ -16,27 +15,14 @@ require ( require ( github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect github.com/PuerkitoBio/goquery v1.9.2 // indirect - github.com/andybalholm/brotli v1.1.0 // indirect github.com/andybalholm/cascadia v1.3.2 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/go-jose/go-jose/v3 v3.0.3 // indirect github.com/go-stack/stack v1.8.1 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/klauspost/compress v1.17.9 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect - github.com/rivo/uniseg v0.4.7 // indirect github.com/stretchr/testify v1.9.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect - github.com/tinylib/msgp v1.2.0 // indirect - github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.55.0 // indirect - github.com/valyala/tcplisten v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect - golang.org/x/sys v0.24.0 // indirect golang.org/x/text v0.17.0 // indirect ) diff --git a/go.sum b/go.sum index 3a3f743..b36cb15 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,6 @@ github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oM github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE= github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk= -github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= -github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -23,31 +21,13 @@ github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo= -github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= -github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= -github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= -github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/playwright-community/playwright-go v0.4501.1 h1:kz8SIfR6nEI8blk77nTVD0K5/i37QP5rY/o8a1fG+4c= github.com/playwright-community/playwright-go v0.4501.1/go.mod h1:bpArn5TqNzmP0jroCgw4poSOG9gSeQg490iLqWAaa7w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= @@ -59,14 +39,6 @@ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY= -github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8= -github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM= -github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= -github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -93,14 +65,10 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= diff --git a/main.go b/main.go index c50117d..f360573 100644 --- a/main.go +++ b/main.go @@ -5,10 +5,10 @@ import ( "fmt" "log" "net" + "net/http" "os" "os/exec" "runtime" - "strconv" "strings" "syscall" "time" @@ -17,276 +17,196 @@ import ( "codeberg.org/vnpower/pixivfe/v2/core" "codeberg.org/vnpower/pixivfe/v2/routes" "codeberg.org/vnpower/pixivfe/v2/session" - "codeberg.org/vnpower/pixivfe/v2/utils/kmutex" - - "github.com/goccy/go-json" - "github.com/gofiber/fiber/v2" - "github.com/gofiber/fiber/v2/middleware/cache" - "github.com/gofiber/fiber/v2/middleware/compress" - "github.com/gofiber/fiber/v2/middleware/limiter" - "github.com/gofiber/fiber/v2/middleware/logger" - "github.com/gofiber/fiber/v2/middleware/recover" - fiber_utils "github.com/gofiber/fiber/v2/utils" + // "codeberg.org/vnpower/pixivfe/v2/utils/kmutex" + // "github.com/CloudyKit/jet/v6" + // "github.com/goccy/go-json" + // "net/http" + // "net/http/middleware/cache" + // "net/http/middleware/compress" + // "net/http/middleware/limiter" + // "net/http/middleware/logger" + // "net/http/middleware/recover" + // fiber_utils "net/http/utils" ) -func CanRequestSkipLimiter(c *fiber.Ctx) bool { - path := c.Path() +func CanRequestSkipLimiter(r *http.Request) bool { + path := r.URL.Path return strings.HasPrefix(path, "/img/") || strings.HasPrefix(path, "/css/") || strings.HasPrefix(path, "/js/") || strings.HasPrefix(path, "/proxy/s.pximg.net/") } -func CanRequestSkipLogger(c *fiber.Ctx) bool { +func CanRequestSkipLogger(r *http.Request) bool { // return false - path := c.Path() - return CanRequestSkipLimiter(c) || + path := r.URL.Path + return CanRequestSkipLimiter(r) || strings.HasPrefix(path, "/proxy/i.pximg.net/") } func main() { config.GlobalServerConfig.InitializeConfig() - core.CreateResponseAuditFolder() - + if config.GlobalServerConfig.InDevelopment { + core.CreateResponseAuditFolder() + } routes.InitTemplatingEngine(config.GlobalServerConfig.InDevelopment) - server := fiber.New(fiber.Config{ - AppName: "PixivFE", - DisableStartupMessage: true, - Prefork: false, - JSONEncoder: json.Marshal, - JSONDecoder: json.Unmarshal, - EnableTrustedProxyCheck: true, - TrustedProxies: []string{"0.0.0.0/0"}, - ProxyHeader: fiber.HeaderXForwardedFor, - ErrorHandler: func(c *fiber.Ctx, err error) error { - log.Println(err) + // server := fiber.New(fiber.Config{ + // AppName: "PixivFE", + // DisableStartupMessage: true, + // Prefork: false, + // JSONEncoder: json.Marshal, + // JSONDecoder: json.Unmarshal, + // EnableTrustedProxyCheck: true, + // TrustedProxies: []string{"0.0.0.0/0"}, + // ProxyHeader: fiber.HeaderXForwardedFor, + // ErrorHandler: func(c *http.Request, err error) error { + // log.Println(err) - // Status code defaults to 500 - code := fiber.StatusInternalServerError + // // Status code defaults to 500 + // code := fiber.StatusInternalServerError - // // Retrieve the custom status code if it's a *fiber.Error - // var e *fiber.Error - // if errors.As(err, &e) { - // code = e.Code - // } + // // // Retrieve the custom status code if it's a *fiber.Error + // // var e *fiber.Error + // // if errors.As(err, &e) { + // // code = e.Code + // // } - // Send custom error page - c.Status(code) - err = routes.Render(c, routes.Data_error{Title: "Error", Error: err}) - if err != nil { - return c.Status(code).SendString(fmt.Sprintf("Internal Server Error: %s", err)) - } + // // Send custom error page + // c.Status(code) + // err = routes.Render(c, routes.Data_error{Title: "Error", Error: err}) + // if err != nil { + // return c.Status(code).SendString(fmt.Sprintf("Internal Server Error: %s", err)) + // } - return nil - }, - }) + // return nil + // }, + // }) - server.Use(func(c *fiber.Ctx) error { - // Pass in values that we want to be available to all pages here - token := session.GetPixivToken(c) - pageURL := c.BaseURL() + c.OriginalURL() + // todo: limiter + // if config.GlobalServerConfig.RequestLimit > 0 { + // keyedSleepingSpot := kmutex.New() + // server.Use(limiter.New(limiter.Config{ + // Next: CanRequestSkipLimiter, + // Expiration: 30 * time.Second, + // Max: config.GlobalServerConfig.RequestLimit, + // LimiterMiddleware: limiter.SlidingWindow{}, + // LimitReached: func(c *http.Request) error { + // // limit response throughput by pacing, since not every bot reads X-RateLimit-* + // // on limit reached, they just have to wait + // // the design of this means that if they send multiple requests when reaching rate limit, they will wait even longer (since `retryAfter` is calculated before anything has slept) + // retryAfter_s := c.GetRespHeader(fiber.HeaderRetryAfter) + // retryAfter, err := strconv.ParseUint(retryAfter_s, 10, 64) + // if err != nil { + // log.Panicf("response header 'RetryAfter' should be a number: %v", err) + // } + // requestIP := c.IP() + // refcount := keyedSleepingSpot.Lock(requestIP) + // defer keyedSleepingSpot.Unlock(requestIP) + // if refcount >= 4 { // on too much concurrent requests + // // todo: maybe blackhole `requestIP` here + // log.Println("Limit Reached (Hard)!", requestIP) + // // close the connection immediately + // _ = c.Context().Conn().Close() + // return nil + // } - cookies := map[string]string{} - for _, name := range session.AllCookieNames { - value := session.GetCookie(c, name) - cookies[string(name)] = value - } + // // sleeping + // // here, sleeping is not the best solution. + // // todo: close this connection when this IP reaches hard limit + // dur := time.Duration(retryAfter) * time.Second + // log.Println("Limit Reached (Soft)! Sleeping for ", dur) + // ctx, cancel := context.WithTimeout(c.Context(), dur) + // defer cancel() + // <-ctx.Done() - c.Bind(fiber.Map{ - "BaseURL": c.BaseURL(), - "OriginalURL": c.OriginalURL(), - "PageURL": pageURL, - "LoggedIn": token != "", - "Queries": c.Queries(), - "CookieList": cookies, - }) - return c.Next() - }) + // return c.Next() + // }, + // })) + // } - if config.GlobalServerConfig.RequestLimit > 0 { - keyedSleepingSpot := kmutex.New() - server.Use(limiter.New(limiter.Config{ - Next: CanRequestSkipLimiter, - Expiration: 30 * time.Second, - Max: config.GlobalServerConfig.RequestLimit, - LimiterMiddleware: limiter.SlidingWindow{}, - LimitReached: func(c *fiber.Ctx) error { - // limit response throughput by pacing, since not every bot reads X-RateLimit-* - // on limit reached, they just have to wait - // the design of this means that if they send multiple requests when reaching rate limit, they will wait even longer (since `retryAfter` is calculated before anything has slept) - retryAfter_s := c.GetRespHeader(fiber.HeaderRetryAfter) - retryAfter, err := strconv.ParseUint(retryAfter_s, 10, 64) - if err != nil { - log.Panicf("response header 'RetryAfter' should be a number: %v", err) - } - requestIP := c.IP() - refcount := keyedSleepingSpot.Lock(requestIP) - defer keyedSleepingSpot.Unlock(requestIP) - if refcount >= 4 { // on too much concurrent requests - // todo: maybe blackhole `requestIP` here - log.Println("Limit Reached (Hard)!", requestIP) - // close the connection immediately - _ = c.Context().Conn().Close() - return nil - } + // todo: caching + // if !config.GlobalServerConfig.InDevelopment { + // server.Use(cache.New( + // cache.Config{ + // Next: func(c *http.Request) bool { + // resp_code := c.Response().StatusCode() + // if resp_code < 200 || resp_code >= 300 { + // return true + // } - // sleeping - // here, sleeping is not the best solution. - // todo: close this connection when this IP reaches hard limit - dur := time.Duration(retryAfter) * time.Second - log.Println("Limit Reached (Soft)! Sleeping for ", dur) - ctx, cancel := context.WithTimeout(c.Context(), dur) - defer cancel() - <-ctx.Done() + // // Disable cache for settings page + // return strings.Contains(c.Path(), "/settings") || c.Path() == "/" + // }, + // Expiration: 5 * time.Minute, + // CacheControl: true, + // StoreResponseHeaders: true, - return c.Next() - }, - })) - } + // KeyGenerator: func(c *http.Request) string { + // key := fiber_utils.CopyString(c.OriginalURL()) + // for _, cookieName := range session.AllCookieNames { + // cookieValue := session.GetCookie(c, cookieName) + // if cookieValue != "" { + // key += "\x00\x00" + // key += string(cookieName) + // key += "\x00" + // key += cookieValue + // } + // } + // return key + // }, + // }, + // )) + // } - server.Use(logger.New( - logger.Config{ - Format: "${time} +${latency} ${ip} ${method} ${path} ${status} ${error} \n", - Next: CanRequestSkipLogger, - CustomTags: map[string]logger.LogFunc{ - // make latency always print in seconds - logger.TagLatency: func(output logger.Buffer, c *fiber.Ctx, data *logger.Data, extraParam string) (int, error) { - latency := data.Stop.Sub(data.Start).Seconds() - return output.WriteString(fmt.Sprintf("%.6f", latency)) - }, - }, - }, - )) + router := defineRoutes() - server.Use(compress.New(compress.Config{ - Level: compress.LevelBestSpeed, // 1 - })) + main_handler := func(w http.ResponseWriter, r *http.Request) { + start_time := time.Now() - if !config.GlobalServerConfig.InDevelopment { - server.Use(cache.New( - cache.Config{ - Next: func(c *fiber.Ctx) bool { - resp_code := c.Response().StatusCode() - if resp_code < 200 || resp_code >= 300 { - return true - } + setGlobalHeaders(r) - // Disable cache for settings page - return strings.Contains(c.Path(), "/settings") || c.Path() == "/" - }, - Expiration: 5 * time.Minute, - CacheControl: true, - StoreResponseHeaders: true, + router.ServeHTTP(w, r) - KeyGenerator: func(c *fiber.Ctx) string { - key := fiber_utils.CopyString(c.OriginalURL()) - for _, cookieName := range session.AllCookieNames { - cookieValue := session.GetCookie(c, cookieName) - if cookieValue != "" { - key += "\x00\x00" - key += string(cookieName) - key += "\x00" - key += cookieValue - } - } - return key - }, - }, - )) - } - - // redirect any round with ?r=url - // could this be unsafe with cross-site scripting? - server.Use(func(c *fiber.Ctx) error { - ret := c.Query("r") + // todo: test this + // redirect any request with ?r=url + ret := r.URL.Query().Get("r") if ret != "" { - c.Redirect(ret) + // could this be unsafe since this redirects to any website? + http.Redirect(w, r, ret, http.StatusTemporaryRedirect) } - return c.Next() - }) - // Global HTTP headers - server.Use(func(c *fiber.Ctx) error { - err := c.Next() - if err != nil { - return err + end_time := time.Now() + + if !CanRequestSkipLogger(r) { + time := start_time + latency := end_time.Sub(start_time) + ip := r.RemoteAddr + method := r.Method + path := r.URL.Path + status := r.Response.Status + // err := ??? + + // todo: logger + // server.Use(logger.New( + // logger.Config{ + // Format: "${time} +${latency} ${ip} ${method} ${path} ${status} ${error} \n", + // Next: CanRequestSkipLogger, + // CustomTags: map[string]logger.LogFunc{ + // // make latency always print in seconds + // logger.TagLatency: func(output logger.Buffer, c *http.Request, data *logger.Data, extraParam string) (int, error) { + // latency := data.Stop.Sub(data.Start).Seconds() + // return output.WriteString(fmt.Sprintf("%.6f", latency)) + // }, + // }, + // }, + // )) } - if strings.HasPrefix(string(c.Response().Header.ContentType()), "text/html") { - c.Set("X-Frame-Options", "DENY") - // use this if need iframe: `X-Frame-Options: SAMEORIGIN` - c.Set("X-Content-Type-Options", "nosniff") - c.Set("Referrer-Policy", "no-referrer") - c.Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload") - c.Set("Content-Security-Policy", fmt.Sprintf("base-uri 'self'; default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' %s; media-src 'self' %s; connect-src 'self'; form-action 'self'; frame-ancestors 'none';", session.GetImageProxyOrigin(c), session.GetImageProxyOrigin(c))) - // use this if need iframe: `frame-ancestors 'self'` - c.Set("Permissions-Policy", "accelerometer=(), ambient-light-sensor=(), battery=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()") - } - return nil - }) - server.Static("/favicon.ico", "./assets/img/favicon.ico") - server.Static("/robots.txt", "./assets/robots.txt") - server.Static("/img/", "./assets/img") - server.Static("/css/", "./assets/css") - server.Static("/js/", "./assets/js") - - server.Use(recover.New(recover.Config{EnableStackTrace: config.GlobalServerConfig.InDevelopment})) - - // Routes - - server.Get("/", routes.IndexPage) - server.Get("/about", routes.AboutPage) - server.Get("/newest", routes.NewestPage) - server.Get("/discovery", routes.DiscoveryPage) - server.Get("/discovery/novel", routes.NovelDiscoveryPage) - server.Get("/ranking", routes.RankingPage) - server.Get("/rankingCalendar", routes.RankingCalendarPage) - server.Post("/rankingCalendar", routes.RankingCalendarPicker) - server.Get("/users/:id.atom.xml", routes.UserAtomFeed) - server.Get("/users/:id/:category.atom.xml", routes.UserAtomFeed) - server.Get("/users/:id/:category?", routes.UserPage) - server.Get("/artworks/:id/", routes.ArtworkPage).Name("artworks") - server.Get("/artworks-multi/:ids/", routes.ArtworkMultiPage) - server.Get("/novel/:id/", routes.NovelPage) - server.Get("/pixivision", routes.PixivisionHomePage) - server.Get("/pixivision/a/:id", routes.PixivisionArticlePage) - - // Settings group - settings := server.Group("/settings") - settings.Get("/", routes.SettingsPage) - settings.Post("/:type/:noredirect?", routes.SettingsPost) - - // Personal group - self := server.Group("/self") - self.Get("/", routes.LoginUserPage) - self.Get("/followingWorks", routes.FollowingWorksPage) - self.Get("/bookmarks", routes.LoginBookmarkPage) - self.Get("/addBookmark/:id", routes.AddBookmarkRoute) - self.Get("/deleteBookmark/:id", routes.DeleteBookmarkRoute) - self.Get("/like/:id", routes.LikeRoute) - - // Oembed group - server.Get("/oembed", routes.Oembed) - - server.Get("/tags/:name", routes.TagPage) - server.Post("/tags/:name", routes.TagPage) - server.Get("/tags", routes.TagPage) - server.Post("/tags", routes.AdvancedTagPost) - - // Legacy illust URL - server.Get("/member_illust.php", func(c *fiber.Ctx) error { - return c.Redirect("/artworks/" + c.Query("illust_id")) - }) - - // Proxy routes - proxy := server.Group("/proxy") - proxy.Get("/i.pximg.net/*", routes.IPximgProxy) - proxy.Get("/s.pximg.net/*", routes.SPximgProxy) - proxy.Get("/ugoira.com/*", routes.UgoiraProxy) + } // Initialize and start the proxy checker - ctx_timeout, cancel := context.WithTimeout(context.Background(), 10 * time.Second) + ctx_timeout, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() config.InitializeProxyChecker(ctx_timeout) @@ -306,27 +226,104 @@ func main() { } // Listen + var l net.Listener if config.GlobalServerConfig.UnixSocket != "" { ln, err := net.Listen("unix", config.GlobalServerConfig.UnixSocket) if err != nil { panic(err) } + l = ln log.Printf("Listening on domain socket %v\n", config.GlobalServerConfig.UnixSocket) - err = server.Listener(ln) - if err != nil { - panic(err) - } } else { addr := config.GlobalServerConfig.Host + ":" + config.GlobalServerConfig.Port - ln, err := net.Listen(server.Config().Network, addr) + ln, err := net.Listen("tcp", addr) if err != nil { log.Panicf("failed to listen: %v", err) } + l = ln addr = ln.Addr().String() log.Printf("Listening on http://%v/\n", addr) - err = server.Listener(ln) - if err != nil { - panic(err) - } } + http.Serve(l, http.HandlerFunc(main_handler)) +} + +// todo: if this doesn't work, need to use `w.Header()` +func setGlobalHeaders(r *http.Request) { + // Respond with global HTTP headers + header := r.Response.Header + header.Add("X-Frame-Options", "DENY") + // use this if need iframe: `X-Frame-Options: SAMEORIGIN` + header.Add("X-Content-Type-Options", "nosniff") + header.Add("Referrer-Policy", "no-referrer") + header.Add("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload") + header.Add("Content-Security-Policy", fmt.Sprintf("base-uri 'self'; default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' %s; media-src 'self' %s; connect-src 'self'; form-action 'self'; frame-ancestors 'none';", session.GetImageProxyOrigin(r), session.GetImageProxyOrigin(r))) + // use this if need iframe: `frame-ancestors 'self'` + header.Add("Permissions-Policy", "accelerometer=(), ambient-light-sensor=(), battery=(), camera=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()") +} + +func defineRoutes() http.ServeMux { + router := http.ServeMux{} + + // todo + // server.Static("/favicon.ico", "./assets/img/favicon.ico") + // server.Static("/robots.txt", "./assets/robots.txt") + // server.Static("/img/", "./assets/img") + // server.Static("/css/", "./assets/css") + // server.Static("/js/", "./assets/js") + + // server.Use(recover.New(recover.Config{EnableStackTrace: config.GlobalServerConfig.InDevelopment})) + + // // Routes + + // server.Get("/", routes.IndexPage) + // server.Get("/about", routes.AboutPage) + // server.Get("/newest", routes.NewestPage) + // server.Get("/discovery", routes.DiscoveryPage) + // server.Get("/discovery/novel", routes.NovelDiscoveryPage) + // server.Get("/ranking", routes.RankingPage) + // server.Get("/rankingCalendar", routes.RankingCalendarPage) + // server.Post("/rankingCalendar", routes.RankingCalendarPicker) + // server.Get("/users/:id.atom.xml", routes.UserAtomFeed) + // server.Get("/users/:id/:category.atom.xml", routes.UserAtomFeed) + // server.Get("/users/:id/:category?", routes.UserPage) + // server.Get("/artworks/:id/", routes.ArtworkPage).Name("artworks") + // server.Get("/artworks-multi/:ids/", routes.ArtworkMultiPage) + // server.Get("/novel/:id/", routes.NovelPage) + // server.Get("/pixivision", routes.PixivisionHomePage) + // server.Get("/pixivision/a/:id", routes.PixivisionArticlePage) + + // // Settings group + // settings := server.Group("/settings") + // settings.Get("/", routes.SettingsPage) + // settings.Post("/:type/:noredirect?", routes.SettingsPost) + + // // Personal group + // self := server.Group("/self") + // self.Get("/", routes.LoginUserPage) + // self.Get("/followingWorks", routes.FollowingWorksPage) + // self.Get("/bookmarks", routes.LoginBookmarkPage) + // self.Get("/addBookmark/:id", routes.AddBookmarkRoute) + // self.Get("/deleteBookmark/:id", routes.DeleteBookmarkRoute) + // self.Get("/like/:id", routes.LikeRoute) + + // // Oembed group + // server.Get("/oembed", routes.Oembed) + + // server.Get("/tags/:name", routes.TagPage) + // server.Post("/tags/:name", routes.TagPage) + // server.Get("/tags", routes.TagPage) + // server.Post("/tags", routes.AdvancedTagPost) + + // // Legacy illust URL + // server.Get("/member_illust.php", func(c *http.Request) error { + // return c.Redirect("/artworks/" + c.Query("illust_id")) + // }) + + // // Proxy routes + // proxy := server.Group("/proxy") + // proxy.Get("/i.pximg.net/*", routes.IPximgProxy) + // proxy.Get("/s.pximg.net/*", routes.SPximgProxy) + // proxy.Get("/ugoira.com/*", routes.UgoiraProxy) + + return router } diff --git a/routes/about.go b/routes/about.go index 3d7af7f..75c603f 100644 --- a/routes/about.go +++ b/routes/about.go @@ -2,10 +2,10 @@ package routes import ( "codeberg.org/vnpower/pixivfe/v2/config" - "github.com/gofiber/fiber/v2" + "net/http" ) -func AboutPage(c *fiber.Ctx) error { +func AboutPage(c *http.Request) error { return Render(c, Data_about{ Time: config.GlobalServerConfig.StartingTime, Version: config.GlobalServerConfig.Version, diff --git a/routes/actions.go b/routes/actions.go index f03b486..9c70473 100644 --- a/routes/actions.go +++ b/routes/actions.go @@ -8,11 +8,11 @@ import ( "net/http" "codeberg.org/vnpower/pixivfe/v2/session" - "github.com/gofiber/fiber/v2" + "net/http" "github.com/tidwall/gjson" ) -func pixivPostRequest(c *fiber.Ctx, url, payload, token, csrf string, isJSON bool) error { +func pixivPostRequest(c *http.Request, url, payload, token, csrf string, isJSON bool) error { requestBody := []byte(payload) req, err := http.NewRequest("POST", url, bytes.NewBuffer(requestBody)) @@ -60,7 +60,7 @@ func pixivPostRequest(c *fiber.Ctx, url, payload, token, csrf string, isJSON boo return nil } -func AddBookmarkRoute(c *fiber.Ctx) error { +func AddBookmarkRoute(c *http.Request) error { token := session.GetPixivToken(c) csrf := session.GetCookie(c, session.Cookie_CSRF) @@ -87,7 +87,7 @@ func AddBookmarkRoute(c *fiber.Ctx) error { return c.SendString("Success") } -func DeleteBookmarkRoute(c *fiber.Ctx) error { +func DeleteBookmarkRoute(c *http.Request) error { token := session.GetPixivToken(c) csrf := session.GetCookie(c, session.Cookie_CSRF) @@ -110,7 +110,7 @@ func DeleteBookmarkRoute(c *fiber.Ctx) error { return c.SendString("Success") } -func LikeRoute(c *fiber.Ctx) error { +func LikeRoute(c *http.Request) error { token := session.GetPixivToken(c) csrf := session.GetCookie(c, session.Cookie_CSRF) diff --git a/routes/artwork.go b/routes/artwork.go index e23e612..afcecc0 100644 --- a/routes/artwork.go +++ b/routes/artwork.go @@ -5,10 +5,10 @@ import ( "strconv" "codeberg.org/vnpower/pixivfe/v2/core" - "github.com/gofiber/fiber/v2" + "net/http" ) -func ArtworkPage(c *fiber.Ctx) error { +func ArtworkPage(c *http.Request) error { id := c.Params("id") if _, err := strconv.Atoi(id); err != nil { return fmt.Errorf("Invalid ID: %s", id) @@ -39,6 +39,6 @@ func ArtworkPage(c *fiber.Ctx) error { }) } -func PreloadImage(c *fiber.Ctx, url string) { +func PreloadImage(c *http.Request, url string) { c.Response().Header.Add("Link", fmt.Sprintf("<%s>; rel=preload; as=image", url)) } diff --git a/routes/artworkMulti.go b/routes/artworkMulti.go index fbde57c..9a8c97d 100644 --- a/routes/artworkMulti.go +++ b/routes/artworkMulti.go @@ -7,10 +7,10 @@ import ( "sync" "codeberg.org/vnpower/pixivfe/v2/core" - "github.com/gofiber/fiber/v2" + "net/http" ) -func ArtworkMultiPage(c *fiber.Ctx) error { +func ArtworkMultiPage(c *http.Request) error { ids_ := c.Params("ids") ids := strings.Split(ids_, ",") diff --git a/routes/discovery.go b/routes/discovery.go index 0ad178c..21dd3b5 100644 --- a/routes/discovery.go +++ b/routes/discovery.go @@ -3,10 +3,10 @@ package routes import ( "codeberg.org/vnpower/pixivfe/v2/core" "codeberg.org/vnpower/pixivfe/v2/utils" - "github.com/gofiber/fiber/v2" + "net/http" ) -func DiscoveryPage(c *fiber.Ctx) error { +func DiscoveryPage(c *http.Request) error { mode := c.Query("mode", "safe") works, err := core.GetDiscoveryArtwork(c, mode) @@ -19,7 +19,7 @@ func DiscoveryPage(c *fiber.Ctx) error { return Render(c, Data_discovery{Artworks: works, Title: "Discovery", Queries: urlc}) } -func NovelDiscoveryPage(c *fiber.Ctx) error { +func NovelDiscoveryPage(c *http.Request) error { mode := c.Query("mode", "safe") works, err := core.GetDiscoveryNovels(c, mode) diff --git a/routes/index.go b/routes/index.go index 961c682..33f1ca8 100644 --- a/routes/index.go +++ b/routes/index.go @@ -3,10 +3,10 @@ package routes import ( "codeberg.org/vnpower/pixivfe/v2/core" "codeberg.org/vnpower/pixivfe/v2/session" - "github.com/gofiber/fiber/v2" + "net/http" ) -func IndexPage(c *fiber.Ctx) error { +func IndexPage(c *http.Request) error { // If token is set, do the landing request... if token := session.GetPixivToken(c); token != "" { @@ -37,7 +37,7 @@ func IndexPage(c *fiber.Ctx) error { }) } -func Oembed(c *fiber.Ctx) error { +func Oembed(c *http.Request) error { pageURL := c.BaseURL() artistName := c.Query("a", "") artistURL := c.Query("u", "") diff --git a/routes/newest.go b/routes/newest.go index bfa66b1..e555dbd 100644 --- a/routes/newest.go +++ b/routes/newest.go @@ -2,10 +2,10 @@ package routes import ( "codeberg.org/vnpower/pixivfe/v2/core" - "github.com/gofiber/fiber/v2" + "net/http" ) -func NewestPage(c *fiber.Ctx) error { +func NewestPage(c *http.Request) error { worktype := c.Query("type", "illust") r18 := c.Query("r18", "false") diff --git a/routes/novel.go b/routes/novel.go index 766b5b3..8b19634 100644 --- a/routes/novel.go +++ b/routes/novel.go @@ -7,10 +7,10 @@ import ( "codeberg.org/vnpower/pixivfe/v2/core" "codeberg.org/vnpower/pixivfe/v2/session" - "github.com/gofiber/fiber/v2" + "net/http" ) -func NovelPage(c *fiber.Ctx) error { +func NovelPage(c *http.Request) error { id := c.Params("id") if _, err := strconv.Atoi(id); err != nil { return fmt.Errorf("Invalid ID: %s", id) diff --git a/routes/personal.go b/routes/personal.go index 92a2754..e627148 100644 --- a/routes/personal.go +++ b/routes/personal.go @@ -7,15 +7,15 @@ import ( "codeberg.org/vnpower/pixivfe/v2/core" "codeberg.org/vnpower/pixivfe/v2/session" - "github.com/gofiber/fiber/v2" + "net/http" ) -func PromptUserToLoginPage(c *fiber.Ctx) error { +func PromptUserToLoginPage(c *http.Request) error { c.Status(http.StatusUnauthorized) return Render(c, Data_unauthorized{}) } -func LoginUserPage(c *fiber.Ctx) error { +func LoginUserPage(c *http.Request) error { token := session.GetPixivToken(c) if token == "" { @@ -29,7 +29,7 @@ func LoginUserPage(c *fiber.Ctx) error { return nil } -func LoginBookmarkPage(c *fiber.Ctx) error { +func LoginBookmarkPage(c *http.Request) error { token := session.GetPixivToken(c) if token == "" { return PromptUserToLoginPage(c) @@ -42,7 +42,7 @@ func LoginBookmarkPage(c *fiber.Ctx) error { return nil } -func FollowingWorksPage(c *fiber.Ctx) error { +func FollowingWorksPage(c *http.Request) error { if token := session.GetPixivToken(c); token == "" { return PromptUserToLoginPage(c) } diff --git a/routes/pixivision.go b/routes/pixivision.go index f79f546..64e56d4 100644 --- a/routes/pixivision.go +++ b/routes/pixivision.go @@ -4,10 +4,10 @@ import ( "codeberg.org/vnpower/pixivfe/v2/session" "codeberg.org/vnpower/pixivision" - "github.com/gofiber/fiber/v2" + "net/http" ) -func PixivisionHomePage(c *fiber.Ctx) error { +func PixivisionHomePage(c *http.Request) error { // Note: don't process images here? data, err := pixivision.GetHomepage() if err != nil { @@ -21,7 +21,7 @@ func PixivisionHomePage(c *fiber.Ctx) error { return Render(c, Data_pixivision_index{Data: data}) } -func PixivisionArticlePage(c *fiber.Ctx) error { +func PixivisionArticlePage(c *http.Request) error { // Note: don't process images here? id := c.Params("id") data, err := pixivision.GetArticle(id) diff --git a/routes/proxy.go b/routes/proxy.go index b2765da..6afffce 100644 --- a/routes/proxy.go +++ b/routes/proxy.go @@ -5,10 +5,10 @@ import ( "io" "net/http" - "github.com/gofiber/fiber/v2" + "net/http" ) -func SPximgProxy(c *fiber.Ctx) error { +func SPximgProxy(c *http.Request) error { URL := fmt.Sprintf("https://s.pximg.net/%s", c.Params("*")) req, err := http.NewRequest("GET", URL, nil) if err != nil { @@ -33,7 +33,7 @@ func SPximgProxy(c *fiber.Ctx) error { return c.Send([]byte(body)) } -func IPximgProxy(c *fiber.Ctx) error { +func IPximgProxy(c *http.Request) error { URL := fmt.Sprintf("https://i.pximg.net/%s", c.Params("*")) req, err := http.NewRequest("GET", URL, nil) if err != nil { @@ -59,7 +59,7 @@ func IPximgProxy(c *fiber.Ctx) error { return c.Send([]byte(body)) } -func UgoiraProxy(c *fiber.Ctx) error { +func UgoiraProxy(c *http.Request) error { URL := fmt.Sprintf("https://ugoira.com/api/mp4/%s", c.Params("*")) req, err := http.NewRequest("GET", URL, nil) if err != nil { diff --git a/routes/ranking.go b/routes/ranking.go index 4ddd3e2..e3161c7 100644 --- a/routes/ranking.go +++ b/routes/ranking.go @@ -4,10 +4,10 @@ import ( "strconv" "codeberg.org/vnpower/pixivfe/v2/core" - "github.com/gofiber/fiber/v2" + "net/http" ) -func RankingPage(c *fiber.Ctx) error { +func RankingPage(c *http.Request) error { mode := c.Query("mode", "daily") content := c.Query("content", "all") date := c.Query("date", "") diff --git a/routes/rankingCalendar.go b/routes/rankingCalendar.go index 5a79193..1e6e236 100644 --- a/routes/rankingCalendar.go +++ b/routes/rankingCalendar.go @@ -6,7 +6,7 @@ import ( "time" "codeberg.org/vnpower/pixivfe/v2/core" - "github.com/gofiber/fiber/v2" + "net/http" ) type DateWrap struct { @@ -33,7 +33,7 @@ func parseDate(t time.Time) DateWrap { return d } -func RankingCalendarPicker(c *fiber.Ctx) error { +func RankingCalendarPicker(c *http.Request) error { mode := c.FormValue("mode", "daily") date := c.FormValue("date", "") @@ -45,7 +45,7 @@ func RankingCalendarPicker(c *fiber.Ctx) error { }) } -func RankingCalendarPage(c *fiber.Ctx) error { +func RankingCalendarPage(c *http.Request) error { mode := c.Query("mode", "daily") date := c.Query("date", "") diff --git a/routes/render.go b/routes/render.go index b8d2ddf..ccd2c47 100644 --- a/routes/render.go +++ b/routes/render.go @@ -3,6 +3,8 @@ package routes import ( "io" "log" + "net/http" + "net/url" "reflect" "strings" @@ -10,14 +12,14 @@ import ( "codeberg.org/vnpower/pixivfe/v2/utils" "github.com/CloudyKit/jet/v6" - "github.com/gofiber/fiber/v2" + "net/http" ) // global variable, yes. var views *jet.Set -func InitTemplatingEngine(InDevelopment bool) { - if InDevelopment { +func InitTemplatingEngine(DisableCache bool) { + if DisableCache { views = jet.NewSet( jet.NewOSFileSystemLoader("assets/views"), jet.InDevelopmentMode(), // disable cache @@ -32,30 +34,11 @@ func InitTemplatingEngine(InDevelopment bool) { } } -func Render[T any](c *fiber.Ctx, data T) error { +func Render[T any](w http.ResponseWriter, r *http.Request, data T) error { // Pass in values that we want to be available to all pages here - token := session.GetPixivToken(c) - pageURL := c.BaseURL() + c.OriginalURL() - cookies := map[string]string{} - for _, name := range session.AllCookieNames { - value := session.GetCookie(c, name) - cookies[string(name)] = value - } - - variables := jet.VarMap{} - - // The middleware at line 99 in `main.go` cannot bind these values below if we use this function. - variables.Set("BaseURL", c.BaseURL()) - variables.Set("OriginalURL", c.OriginalURL()) - variables.Set("PageURL", pageURL) - variables.Set("LoggedIn", token != "") - variables.Set("Queries", c.Queries()) - variables.Set("CookieList", cookies) - - c.Context().SetContentType("text/html; charset=utf-8") - - return RenderInner(c.Response().BodyWriter(), variables, data) + r.Response.Header.Set("content-type", "text/html; charset=utf-8") + return RenderInner(w, GetTemplatingVariables(r), data) } func RenderInner[T any](w io.Writer, variables jet.VarMap, data T) error { @@ -74,17 +57,37 @@ func RenderInner[T any](w io.Writer, variables jet.VarMap, data T) error { return template.Execute(w, variables, data) } -// func structToMap[T any](data T) map[string]any { -// result := map[string]any{} -// Type := reflect.TypeFor[T]() -// for i := 0; i < Type.NumField(); i += 1 { -// field := Type.Field(i) -// result[field.Name] = fieldName(data, field.Name) -// } -// return result -// } +func GetTemplatingVariables(r *http.Request) jet.VarMap { + // Pass in values that we want to be available to all pages here + token := session.GetPixivToken(r) + baseURL := (&url.URL{ + Scheme: r.URL.Scheme, + Opaque: r.URL.Opaque, + User: r.URL.User, + Host: r.URL.Host, + }).String() + originalURL := (&url.URL{ + Path: r.URL.Path, + RawPath: r.URL.RawPath, + OmitHost: r.URL.OmitHost, + ForceQuery: r.URL.ForceQuery, + RawQuery: r.URL.RawQuery, + Fragment: r.URL.Fragment, + RawFragment: r.URL.RawFragment, + }).String() + pageURL := r.URL.String() -// // assumes that the field `field_name` exists, panics otherwise -// func fieldName[T any](data T, field_name string) any { -// return reflect.ValueOf(data).FieldByName(field_name).Interface() -// } + cookies := map[string]string{} + for _, name := range session.AllCookieNames { + value := session.GetCookie(r, name) + cookies[string(name)] = value + } + + return jet.VarMap{}. + Set("BaseURL", baseURL). + Set("OriginalURL", originalURL). + Set("PageURL", pageURL). + Set("LoggedIn", token != ""). + Set("Queries", r.URL.Query().Encode()). + Set("CookieList", cookies) +} diff --git a/routes/settings.go b/routes/settings.go index 5f035c7..505999e 100644 --- a/routes/settings.go +++ b/routes/settings.go @@ -12,13 +12,13 @@ import ( "codeberg.org/vnpower/pixivfe/v2/config" httpc "codeberg.org/vnpower/pixivfe/v2/core" "codeberg.org/vnpower/pixivfe/v2/session" - "github.com/gofiber/fiber/v2" + "net/http" ) // todo: allow clear proxy // todo: allow clear all settings -func setToken(c *fiber.Ctx) error { +func setToken(c *http.Request) error { // Parse the value from the form token := c.FormValue("token") if token != "" { @@ -69,7 +69,7 @@ func setToken(c *fiber.Ctx) error { return errors.New("You submitted an empty/invalid form.") } -func setImageServer(c *fiber.Ctx) error { +func setImageServer(c *http.Request) error { // Parse the value from the form token := c.FormValue("image-proxy") if token != "" { @@ -80,7 +80,7 @@ func setImageServer(c *fiber.Ctx) error { return nil } -func setNovelFontType(c *fiber.Ctx) error { +func setNovelFontType(c *http.Request) error { fontType := c.FormValue("font-type") if fontType != "" { session.SetCookie(c, session.Cookie_NovelFontType, fontType) @@ -89,7 +89,7 @@ func setNovelFontType(c *fiber.Ctx) error { return nil } -func setNovelViewMode(c *fiber.Ctx) error { +func setNovelViewMode(c *http.Request) error { viewMode := c.FormValue("view-mode") if viewMode != "" { session.SetCookie(c, session.Cookie_NovelViewMode, viewMode) @@ -98,7 +98,7 @@ func setNovelViewMode(c *fiber.Ctx) error { return nil } -func setThumbnailToNewTab(c *fiber.Ctx) error { +func setThumbnailToNewTab(c *http.Request) error { ttnt := c.FormValue("ttnt") if ttnt == "_blank" || ttnt == "_self" { session.SetCookie(c, session.Cookie_ThumbnailToNewTab, ttnt) @@ -107,7 +107,7 @@ func setThumbnailToNewTab(c *fiber.Ctx) error { return nil } -func setArtworkPreview(c *fiber.Ctx) error { +func setArtworkPreview(c *http.Request) error { value := c.FormValue("app") if value == "cover" || value == "button" || value == "" { session.SetCookie(c, session.Cookie_ArtworkPreview, value) @@ -116,13 +116,13 @@ func setArtworkPreview(c *fiber.Ctx) error { return nil } -func setLogout(c *fiber.Ctx) error { +func setLogout(c *http.Request) error { session.ClearCookie(c, session.Cookie_Token) session.ClearCookie(c, session.Cookie_CSRF) return nil } -func setCookie(c *fiber.Ctx) error { +func setCookie(c *http.Request) error { key := c.FormValue("key") value := c.FormValue("value") for _, cookie_name := range session.AllCookieNames { @@ -134,7 +134,7 @@ func setCookie(c *fiber.Ctx) error { return fmt.Errorf("Invalid Cookie Name: %s", key) } -func setRawCookie(c *fiber.Ctx) error { +func setRawCookie(c *http.Request) error { raw := c.FormValue("raw") lines := strings.Split(raw, "\n") @@ -156,16 +156,16 @@ func setRawCookie(c *fiber.Ctx) error { return nil } -func resetAll(c *fiber.Ctx) error { +func resetAll(c *http.Request) error { session.ClearAllCookies(c) return nil } -func SettingsPage(c *fiber.Ctx) error { +func SettingsPage(c *http.Request) error { return Render(c, Data_settings{WorkingProxyList: config.GetWorkingProxies(), ProxyList: config.BuiltinProxyList}) } -func SettingsPost(c *fiber.Ctx) error { +func SettingsPost(c *http.Request) error { // NOTE: VnPower: Future maintainers should leave this function alone. t := c.Params("type") diff --git a/routes/tag.go b/routes/tag.go index 861490f..fe4be91 100644 --- a/routes/tag.go +++ b/routes/tag.go @@ -7,10 +7,10 @@ import ( "codeberg.org/vnpower/pixivfe/v2/core" "codeberg.org/vnpower/pixivfe/v2/utils" - "github.com/gofiber/fiber/v2" + "net/http" ) -func TagPage(c *fiber.Ctx) error { +func TagPage(c *http.Request) error { param := c.Params("name", c.Query("name")) name, err := url.PathUnescape(param) if err != nil { @@ -55,7 +55,7 @@ func TagPage(c *fiber.Ctx) error { return Render(c, Data_tag{Title: "Results for " + name, Tag: tag, Data: *result, QueriesC: urlc, TrueTag: param, Page: pageInt}) } -func AdvancedTagPost(c *fiber.Ctx) error { +func AdvancedTagPost(c *http.Request) error { return c.RedirectToRoute("/tags", fiber.Map{ "queries": map[string]string{ "name": c.Query("name", c.FormValue("name")), diff --git a/routes/user.go b/routes/user.go index 9a3b46b..41c0905 100644 --- a/routes/user.go +++ b/routes/user.go @@ -6,7 +6,7 @@ import ( "time" "codeberg.org/vnpower/pixivfe/v2/core" - "github.com/gofiber/fiber/v2" + "net/http" ) type userPageData struct { @@ -16,7 +16,7 @@ type userPageData struct { page int } -func fetchData(c *fiber.Ctx, getTags bool) (userPageData, error) { +func fetchData(c *http.Request, getTags bool) (userPageData, error) { id := c.Params("id") if _, err := strconv.Atoi(id); err != nil { return userPageData{}, err @@ -53,7 +53,7 @@ func fetchData(c *fiber.Ctx, getTags bool) (userPageData, error) { return userPageData{user, category, pageLimit, page}, nil } -func UserPage(c *fiber.Ctx) error { +func UserPage(c *http.Request) error { data, err := fetchData(c, true) if err != nil { return err @@ -62,7 +62,7 @@ func UserPage(c *fiber.Ctx) error { return Render(c, Data_user{Title: data.user.Name, User: data.user, Category: data.category, PageLimit: data.pageLimit, Page: data.page, MetaImage: data.user.BackgroundImage}) } -func UserAtomFeed(c *fiber.Ctx) error { +func UserAtomFeed(c *http.Request) error { data, err := fetchData(c, false) if err != nil { return err diff --git a/semgrep.yml b/semgrep.yml index 3acccea..fc3db00 100644 --- a/semgrep.yml +++ b/semgrep.yml @@ -11,7 +11,7 @@ rules: - pattern: | http.WebAPIRequest(...) - pattern-not-inside: | - func $FUNC(c *fiber.Ctx, ...) $RET { + func $FUNC(c *http.Request, ...) $RET { ... } # note: the below two rules autofix have slight problems. where `http` is sometimes "net/http". need minor manual tweaking after --autofix. diff --git a/session/aux.go b/session/aux.go index e937d77..cfcb472 100644 --- a/session/aux.go +++ b/session/aux.go @@ -2,18 +2,18 @@ package session import ( "log" + "net/http" "net/url" "strings" config "codeberg.org/vnpower/pixivfe/v2/config" - "github.com/gofiber/fiber/v2" ) -func GetPixivToken(c *fiber.Ctx) string { +func GetPixivToken(c *http.Request) string { return GetCookie(c, Cookie_Token) } -func GetImageProxy(c *fiber.Ctx) url.URL { +func GetImageProxy(c *http.Request) url.URL { value := GetCookie(c, Cookie_ImageProxy) if value == "" { // fall through to default case @@ -28,7 +28,7 @@ func GetImageProxy(c *fiber.Ctx) url.URL { return config.GlobalServerConfig.ProxyServer } -func ProxyImageUrl(c *fiber.Ctx, s string) string { +func ProxyImageUrl(c *http.Request, s string) string { proxyOrigin := GetImageProxyPrefix(c) s = strings.ReplaceAll(s, `https:\/\/i.pximg.net`, proxyOrigin) // s = strings.ReplaceAll(s, `https:\/\/i.pximg.net`, "/proxy/i.pximg.net") @@ -36,7 +36,7 @@ func ProxyImageUrl(c *fiber.Ctx, s string) string { return s } -func ProxyImageUrlNoEscape(c *fiber.Ctx, s string) string { +func ProxyImageUrlNoEscape(c *http.Request, s string) string { proxyOrigin := GetImageProxyPrefix(c) s = strings.ReplaceAll(s, `https://i.pximg.net`, proxyOrigin) // s = strings.ReplaceAll(s, `https:\/\/i.pximg.net`, "/proxy/i.pximg.net") @@ -44,12 +44,12 @@ func ProxyImageUrlNoEscape(c *fiber.Ctx, s string) string { return s } -func GetImageProxyOrigin(c *fiber.Ctx) string { +func GetImageProxyOrigin(c *http.Request) string { url := GetImageProxy(c) return urlAuthority(url) } -func GetImageProxyPrefix(c *fiber.Ctx) string { +func GetImageProxyPrefix(c *http.Request) string { url := GetImageProxy(c) return urlAuthority(url) + url.Path // note: not sure if url.EscapedPath() is useful here. go's standard library is trash at handling URL (:// should be part of the scheme) diff --git a/session/cookie.go b/session/cookie.go index 412a5df..7dcf90f 100644 --- a/session/cookie.go +++ b/session/cookie.go @@ -5,7 +5,7 @@ package session import ( "time" - "github.com/gofiber/fiber/v2" + "net/http" ) type CookieName string @@ -37,11 +37,11 @@ var AllCookieNames []CookieName = []CookieName{ Cookie_ShowArtAI, } -func GetCookie(c *fiber.Ctx, name CookieName, defaultValue ...string) string { +func GetCookie(c *http.Request, name CookieName, defaultValue ...string) string { return c.Cookies(string(name), defaultValue...) } -func SetCookie(c *fiber.Ctx, name CookieName, value string) { +func SetCookie(c *http.Request, name CookieName, value string) { cookie := fiber.Cookie{ Name: string(name), Value: value, @@ -57,7 +57,7 @@ func SetCookie(c *fiber.Ctx, name CookieName, value string) { var CookieExpireDelete = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) -func ClearCookie(c *fiber.Ctx, name CookieName) { +func ClearCookie(c *http.Request, name CookieName) { cookie := fiber.Cookie{ Name: string(name), Value: "", @@ -71,7 +71,7 @@ func ClearCookie(c *fiber.Ctx, name CookieName) { c.Cookie(&cookie) } -func ClearAllCookies(c *fiber.Ctx) { +func ClearAllCookies(c *http.Request) { for _, name := range AllCookieNames { ClearCookie(c, name) }