├── .github └── workflows │ ├── ci.yml │ ├── golint.yml │ └── release.yml ├── .gitignore ├── LICENSE ├── README.md ├── go.mod ├── go.sum ├── http.go ├── index.html └── main.go /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [ push, pull_request, workflow_dispatch ] 4 | 5 | env: 6 | BINARY_PREFIX: "go-pixiv-proxy_" 7 | BINARY_SUFFIX: "" 8 | COMMIT_ID: "${{ github.sha }}" 9 | PR_PROMPT: "::warning:: Build artifact will not be uploaded due to the workflow is trigged by pull request." 10 | 11 | jobs: 12 | build: 13 | name: Build binary CI 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | # build and publish in parallel: linux/386, linux/amd64, windows/386, windows/amd64, darwin/amd64, darwin/arm64 18 | goos: [ linux, windows, darwin ] 19 | goarch: [ amd64, arm, arm64 ] 20 | exclude: 21 | - goos: darwin 22 | goarch: arm 23 | fail-fast: true 24 | steps: 25 | - uses: actions/checkout@v2 26 | - name: Setup Go environment 27 | uses: actions/setup-go@v2.1.3 28 | with: 29 | go-version: 1.17 30 | - name: Cache downloaded module 31 | uses: actions/cache@v2 32 | with: 33 | path: | 34 | ~/.cache/go-build 35 | ~/go/pkg/mod 36 | key: ${{ runner.os }}-go-${{ matrix.goos }}-${{ matrix.goarch }}-${{ hashFiles('**/go.sum') }} 37 | - name: Build binary file 38 | env: 39 | GOOS: ${{ matrix.goos }} 40 | GOARCH: ${{ matrix.goarch }} 41 | IS_PR: ${{ !!github.head_ref }} 42 | run: | 43 | if [ $GOOS = "windows" ]; then export BINARY_SUFFIX="$BINARY_SUFFIX.exe"; fi 44 | if $IS_PR ; then echo $PR_PROMPT; fi 45 | export BINARY_NAME="$BINARY_PREFIX$GOOS_$GOARCH$BINARY_SUFFIX" 46 | export LD_FLAGS="-w -s" 47 | go build -o "output/$BINARY_NAME" -trimpath -ldflags "$LD_FLAGS" . 48 | - name: Upload artifact 49 | uses: actions/upload-artifact@v2 50 | if: ${{ !github.head_ref }} 51 | with: 52 | name: ${{ matrix.goos }}_${{ matrix.goarch }} 53 | path: output/ 54 | -------------------------------------------------------------------------------- /.github/workflows/golint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: [push,pull_request,workflow_dispatch] 4 | 5 | jobs: 6 | golangci: 7 | name: lint 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | 12 | - name: Setup Go environment 13 | uses: actions/setup-go@v2.1.3 14 | with: 15 | go-version: 1.17 16 | 17 | - name: golangci-lint 18 | uses: golangci/golangci-lint-action@v2 19 | with: 20 | version: latest 21 | 22 | - name: Tests 23 | run: | 24 | go test $(go list ./...) 25 | 26 | - name: Commit back 27 | if: ${{ github.repository_owner == 'Mrs4s' && !github.event.pull_request }} 28 | continue-on-error: true 29 | run: | 30 | git config --local user.name 'github-actions[bot]' 31 | git config --local user.email '41898282+github-actions[bot]@users.noreply.github.com' 32 | git add --all 33 | git commit -m "ci(chore): Fix stylings" 34 | git push 35 | 36 | - name: Suggester 37 | if: ${{ github.event.pull_request }} 38 | uses: reviewdog/action-suggester@v1 39 | with: 40 | github_token: ${{ secrets.GITHUB_TOKEN }} 41 | tool_name: golangci-lint 42 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | goreleaser: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v2.3.4 14 | with: 15 | fetch-depth: 0 16 | 17 | - name: Set up Go 18 | uses: actions/setup-go@v2 19 | with: 20 | go-version: '1.17' 21 | 22 | - name: Run GoReleaser 23 | uses: goreleaser/goreleaser-action@v2 24 | with: 25 | version: latest 26 | args: release --rm-dist 27 | env: 28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | 4 | *.exe -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, 秋葉杏 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 排队姬 4 | 5 | # go-pixiv-proxy 6 | _✨ 一个简单易懂的p站图片代理! ✨_ 7 | 8 |
9 | 10 |

11 | 12 | license 13 | 14 | 15 | release 16 | 17 | 18 | GoReportCard 19 | 20 |

21 | 22 |

23 | 下载 24 | · 25 | 文档 26 |

27 | 28 | # 简介 29 | 30 | 一个简单易懂的p站图片代理! 31 | 32 | # 使用说明 33 | 34 | ## 部署 35 | 36 | ### 直接部署 37 | 38 | 从 [release](https://github.com/Akegarasu/go-pixiv-proxy/releases) 下载对应系统的可执行文件直接运行 39 | 40 | ### 启动参数 41 | 42 | `-h`: host 默认 127.0.0.1 43 | 44 | `-p`: 端口 默认 18090 45 | 46 | `-d`: 指定域名(用于主页展示示例图片可以不填) 47 | 48 | ### 环境变量 49 | 50 | 注意:环境变量会 **默认覆盖** 启动参数 51 | 52 | `GPP_HOST`: host 53 | 54 | `GPP_PORT`: 端口 55 | 56 | `GPP_DOMAIN`: 域名 57 | 58 | 59 | ## 代理图片 60 | 61 | 提供了两种代理的方法 62 | 63 | ### 替换 `i.piximg.net` 为你的域名 64 | 65 | https://i.pximg.net/img-original/img/2022/05/21/22/35/46/98505703_p0.jpg 66 | 67 | 替换为 68 | 69 | http://example.com/img-original/img/2022/05/21/22/35/46/98505703_p0.jpg 70 | 71 | ### url 后接 pid 72 | 73 | http://example.com/98505703 74 | 75 | ## 图片质量选择 76 | 77 | 针对 **url 后接 pid** 的使用方法,提供了图片质量选择的参数 78 | 79 | 使用方法:添加参数 `t` 80 | 81 | 支持 82 | 83 | - original 84 | - regular 85 | - small 86 | - thumb 87 | - mini 88 | 89 | 例子: http://example.com/98505703?t=original 90 | 91 | 92 | ## 代理 api 93 | 94 | http://example.com/api/pid 95 | 96 | ## 其他示范用例 97 | 98 | ``` 99 | 1. http://example.com/$path 100 | - http://example.com/img-original/img/0000/00/00/00/00/00/12345678_p0.png 101 | 102 | 2. http://example.com/$pid[/$p][?t=original|regular|small|thumb|mini] 103 | - http://example.com/12345678 (p0) 104 | - http://example.com/12345678/0 (p0) 105 | - http://example.com/12345678/1 (p1) 106 | - http://example.com/12345678?t=small (small image) 107 | ``` 108 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module go-pixiv-proxy 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/sirupsen/logrus v1.8.1 7 | github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 8 | github.com/tidwall/gjson v1.12.1 9 | ) 10 | 11 | require ( 12 | github.com/stretchr/testify v1.7.1 // indirect 13 | github.com/tidwall/match v1.1.1 // indirect 14 | github.com/tidwall/pretty v1.2.0 // indirect 15 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect 16 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 17 | ) 18 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 5 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 7 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 8 | github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= 9 | github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 10 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 11 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 12 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 13 | github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= 14 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 15 | github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk= 16 | github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA= 17 | github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo= 18 | github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 19 | github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= 20 | github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= 21 | github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= 22 | github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 23 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 24 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 25 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= 26 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 27 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 28 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 29 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 30 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 31 | -------------------------------------------------------------------------------- /http.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "io" 5 | "net/http" 6 | "net/url" 7 | 8 | log "github.com/sirupsen/logrus" 9 | ) 10 | 11 | var ( 12 | headers = map[string]string{ 13 | "Referer": "https://www.pixiv.net", 14 | "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36", 15 | } 16 | client = &http.Client{ 17 | Transport: &http.Transport{ 18 | Proxy: func(request *http.Request) (u *url.URL, e error) { 19 | return http.ProxyFromEnvironment(request) 20 | }, 21 | }, 22 | } 23 | ) 24 | 25 | type Context struct { 26 | rw http.ResponseWriter 27 | req *http.Request 28 | } 29 | 30 | func (c *Context) write(b []byte, status int) { 31 | c.rw.WriteHeader(status) 32 | _, err := c.rw.Write(b) 33 | if err != nil { 34 | log.Error(err) 35 | } 36 | } 37 | 38 | func (c *Context) String(status int, s string) { 39 | c.write([]byte(s), status) 40 | } 41 | 42 | func (c *Context) WriteHeader(statusCode int) { 43 | c.rw.WriteHeader(statusCode) 44 | } 45 | 46 | func proxyHttpReq(c *Context, url string, errMsg string) { 47 | resp, err := httpGet(url) 48 | if err != nil { 49 | c.String(500, errMsg) 50 | return 51 | } 52 | defer resp.Body.Close() 53 | copyHeader(c.rw.Header(), resp.Header) 54 | resp.Header.Del("Cookie") 55 | resp.Header.Del("Set-Cookie") 56 | _, _ = io.Copy(c.rw, resp.Body) 57 | } 58 | 59 | func httpGet(u string) (*http.Response, error) { 60 | req, err := http.NewRequest("GET", u, nil) 61 | if err != nil { 62 | return nil, err 63 | } 64 | for k, v := range headers { 65 | req.Header.Set(k, v) 66 | } 67 | req.Header.Set("Cookie", cookies) 68 | resp, err := client.Do(req) 69 | if err != nil { 70 | return nil, err 71 | } 72 | return resp, nil 73 | } 74 | 75 | func httpGetReadCloser(u string) (io.ReadCloser, error) { 76 | resp, err := httpGet(u) 77 | if err != nil { 78 | return nil, err 79 | } 80 | return resp.Body, nil 81 | } 82 | 83 | func httpGetBytes(url string) ([]byte, error) { 84 | body, err := httpGetReadCloser(url) 85 | if err != nil { 86 | return nil, err 87 | } 88 | defer body.Close() 89 | b, err := io.ReadAll(body) 90 | if err != nil { 91 | return nil, err 92 | } 93 | return b, nil 94 | } 95 | 96 | func copyHeader(dst, src http.Header) { 97 | for k, vv := range src { 98 | for _, v := range vv { 99 | dst.Add(k, v) 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | **go-pixiv-proxy** 5 | 6 | # 简介 7 | 8 | 一个简单易懂的p站图片代理! 9 | 10 | 项目地址 [go-pixiv-proxy](https://github.com/Akegarasu/go-pixiv-proxy) 11 | 12 | # 使用说明 13 | 14 | ## 启动参数 15 | 16 | `-h`: host 17 | 18 | `-p`: 端口 19 | 20 | `-d`: 指定域名(用于主页展示示例图片可以不填) 21 | 22 | ## 代理图片 23 | 24 | 提供了两种代理的方法 25 | 26 | ### 替换 `i.piximg.net` 为你的域名 27 | 28 | https://i.pximg.net/img-original/img/2022/05/21/22/35/46/98505703_p0.jpg 29 | 30 | 替换为 31 | 32 | http://example.com/img-original/img/2022/05/21/22/35/46/98505703_p0.jpg 33 | 34 | ### url 后接 pid 35 | 36 | http://example.com/98505703 37 | 38 | ## 图片质量选择 39 | 40 | 针对 **url 后接 pid** 的使用方法,提供了图片质量选择的参数 41 | 42 | 使用方法:添加参数 `t` 43 | 44 | 支持 45 | 46 | - original 47 | - regular 48 | - small 49 | - thumb 50 | - mini 51 | 52 | 例子: http://example.com/98505703?t=original 53 | 54 | {image-examples} 55 | 56 | ## 代理 api 57 | 58 | http://example.com/api/pid 59 | 60 | ## 其他示范用例 61 | 62 | ``` 63 | 1. http://example.com/$path 64 | - http://example.com/img-original/img/0000/00/00/00/00/00/12345678_p0.png 65 | 66 | 2. http://example.com/$pid[/$p][?t=original|regular|small|thumb|mini] 67 | - http://example.com/12345678 (p0) 68 | - http://example.com/12345678/0 (p0) 69 | - http://example.com/12345678/1 (p1) 70 | - http://example.com/12345678?t=small (small image) 71 | ``` 72 | 73 | 74 | 81 | 84 | 85 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "embed" 5 | "flag" 6 | "fmt" 7 | "net/http" 8 | "os" 9 | "strconv" 10 | "strings" 11 | 12 | log "github.com/sirupsen/logrus" 13 | easy "github.com/t-tomalak/logrus-easy-formatter" 14 | "github.com/tidwall/gjson" 15 | ) 16 | 17 | var ( 18 | host string 19 | port string 20 | domain string 21 | cookies string 22 | //go:embed index.html 23 | indexHtml string 24 | directTypes = []string{"img-original", "img-master", "c", "user-profile", "img-zip-ugoira"} 25 | imgTypes = []string{"original", "regular", "small", "thumb", "mini"} 26 | docExampleImg = `![regular](http://example.com/98505703?t=regular) 27 | 28 | ![small](http://example.com/98505703?t=small) 29 | 30 | ![thumb](http://example.com/98505703?t=thumb) 31 | 32 | ![mini](http://example.com/98505703?t=mini)` 33 | ) 34 | 35 | type Illust struct { 36 | origUrl string 37 | urls map[string]gjson.Result 38 | } 39 | 40 | func handlePixivProxy(rw http.ResponseWriter, req *http.Request) { 41 | var err error 42 | var realUrl string 43 | c := &Context{ 44 | rw: rw, 45 | req: req, 46 | } 47 | path := req.URL.Path 48 | log.Info(req.Method, " ", req.URL.String()) 49 | spl := strings.Split(path, "/")[1:] 50 | switch spl[0] { 51 | case "": 52 | c.String(200, indexHtml) 53 | return 54 | case "favicon.ico": 55 | c.WriteHeader(404) 56 | return 57 | case "api": 58 | handleIllustInfo(c) 59 | return 60 | } 61 | imgType := req.URL.Query().Get("t") 62 | if imgType == "" { 63 | imgType = "original" 64 | } 65 | if !in(imgTypes, imgType) { 66 | c.String(400, "invalid query") 67 | return 68 | } 69 | if in(directTypes, spl[0]) { 70 | realUrl = "https://i.pximg.net" + path 71 | } else { 72 | if _, err = strconv.Atoi(spl[0]); err != nil { 73 | c.String(400, "invalid query") 74 | return 75 | } 76 | illust, err := getIllust(spl[0]) 77 | if err != nil { 78 | c.String(400, "pixiv api error") 79 | return 80 | } 81 | if r, ok := illust.urls[imgType]; ok { 82 | realUrl = r.String() 83 | } else { 84 | c.String(400, "this image type not exists") 85 | return 86 | } 87 | if realUrl == "" { 88 | c.String(400, "this image needs login, set GPP_COOKIES env.") 89 | } 90 | if len(spl) > 1 { 91 | realUrl = strings.Replace(realUrl, "_p0", "_p"+spl[1], 1) 92 | } 93 | } 94 | proxyHttpReq(c, realUrl, "fetch pixiv image error") 95 | } 96 | 97 | func handleIllustInfo(c *Context) { 98 | params := strings.Split(c.req.URL.Path, "/") 99 | pid := params[len(params)-1] 100 | if _, err := strconv.Atoi(pid); err != nil { 101 | c.String(400, "pid invalid") 102 | return 103 | } 104 | proxyHttpReq(c, "https://www.pixiv.net/ajax/illust/"+pid, "pixiv api error") 105 | } 106 | 107 | func getIllust(pid string) (*Illust, error) { 108 | b, err := httpGetBytes("https://www.pixiv.net/ajax/illust/" + pid) 109 | if err != nil { 110 | return nil, err 111 | } 112 | g := gjson.ParseBytes(b) 113 | imgUrl := g.Get("body.urls.original").String() 114 | return &Illust{ 115 | origUrl: imgUrl, 116 | urls: g.Get("body.urls").Map(), 117 | }, nil 118 | } 119 | 120 | func in(orig []string, str string) bool { 121 | for _, b := range orig { 122 | if b == str { 123 | return true 124 | } 125 | } 126 | return false 127 | } 128 | 129 | func checkEnv() { 130 | if os.Getenv("GPP_HOST") != "" { 131 | host = os.Getenv("GPP_HOST") 132 | } 133 | if os.Getenv("GPP_PORT") != "" { 134 | port = os.Getenv("GPP_PORT") 135 | } 136 | if os.Getenv("GPP_DOMAIN") != "" { 137 | domain = os.Getenv("GPP_DOMAIN") 138 | } 139 | if os.Getenv("GPP_COOKIES") != "" { 140 | cookies = os.Getenv("GPP_COOKIES") 141 | } 142 | } 143 | 144 | func init() { 145 | flag.StringVar(&host, "h", "127.0.0.1", "host") 146 | flag.StringVar(&port, "p", "18090", "port") 147 | flag.StringVar(&domain, "d", "", "your domain") 148 | flag.StringVar(&cookies, "c", "", "cookie") 149 | log.SetFormatter(&easy.Formatter{ 150 | TimestampFormat: "2006-01-02 15:04:05", 151 | LogFormat: "[%lvl%][%time%]: %msg% \n", 152 | }) 153 | log.SetLevel(log.InfoLevel) 154 | } 155 | 156 | func main() { 157 | flag.Parse() 158 | checkEnv() 159 | if domain != "" { 160 | indexHtml = strings.ReplaceAll(indexHtml, "{image-examples}", docExampleImg) 161 | indexHtml = strings.ReplaceAll(indexHtml, "http://example.com", domain) 162 | } 163 | http.HandleFunc("/", handlePixivProxy) 164 | log.Infof("started: %s:%s %s", host, port, domain) 165 | err := http.ListenAndServe(fmt.Sprintf("%s:%s", host, port), nil) 166 | if err != nil { 167 | log.Error("start failed: ", err) 168 | } 169 | } 170 | --------------------------------------------------------------------------------