feat 增加cn coach client
This commit is contained in:
parent
38f473928f
commit
17299b2bb8
14
go.mod
14
go.mod
@ -4,9 +4,12 @@ go 1.22.2
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.11.6
|
||||
github.com/cloudwego/hertz v0.9.1
|
||||
github.com/corpix/uarand v0.2.0
|
||||
github.com/go-resty/resty/v2 v2.13.1
|
||||
github.com/golang/glog v1.2.1
|
||||
github.com/metacubex/mihomo v1.18.4
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/timerzz/proxypool v0.0.0-20240512142241-f74bcb3534c5
|
||||
gorm.io/driver/postgres v1.5.7
|
||||
gorm.io/gorm v1.25.10
|
||||
@ -25,16 +28,19 @@ require (
|
||||
github.com/antchfx/xpath v1.3.0 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/bytedance/go-tagexpr/v2 v2.9.2 // indirect
|
||||
github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/cloudflare/circl v1.3.6 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/cloudwego/netpoll v0.6.0 // indirect
|
||||
github.com/coreos/go-iptables v0.7.0 // indirect
|
||||
github.com/corpix/uarand v0.2.0 // indirect
|
||||
github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 // indirect
|
||||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect
|
||||
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect
|
||||
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gaukas/godicttls v0.0.4 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
@ -50,6 +56,8 @@ require (
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/henrylee2cn/ameda v1.4.10 // indirect
|
||||
github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 // indirect
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240419123447-f1cffa2c0c49 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
@ -83,6 +91,7 @@ require (
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mroth/weightedrand/v2 v2.1.0 // indirect
|
||||
github.com/nyaruka/phonenumbers v1.0.55 // indirect
|
||||
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
@ -111,6 +120,9 @@ require (
|
||||
github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/temoto/robotstxt v1.1.2 // indirect
|
||||
github.com/tidwall/gjson v1.14.4 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
|
45
go.sum
45
go.sum
@ -35,18 +35,32 @@ github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xW
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/bytedance/go-tagexpr/v2 v2.9.2 h1:QySJaAIQgOEDQBLS3x9BxOWrnhqu5sQ+f6HaZIxD39I=
|
||||
github.com/bytedance/go-tagexpr/v2 v2.9.2/go.mod h1:5qsx05dYOiUXOUgnQ7w3Oz8BYs2qtM/bJokdLb79wRM=
|
||||
github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7 h1:PtwsQyQJGxf8iaPptPNaduEIu9BnrNms+pcRdHAxZaM=
|
||||
github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7/go.mod h1:2ZlV9BaUH4+NXIBF0aMdKKAnHTzqH+iMU4KUjAbL23Q=
|
||||
github.com/bytedance/mockey v1.2.1 h1:g84ngI88hz1DR4wZTL3yOuqlEcq67MretBfQUdXwrmw=
|
||||
github.com/bytedance/mockey v1.2.1/go.mod h1:+Jm/fzWZAuhEDrPXVjDf/jLM2BlLXJkwk94zf2JZ3X4=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.8.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.3.6 h1:/xbKIqSHbZXHwkhbrhrt2YOHIwYJlXH94E3tI/gDlUg=
|
||||
github.com/cloudflare/circl v1.3.6/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/hertz v0.9.1 h1:+jK9A6MDNTUVy6q/zSOlhbnp1fFMiOaPIsq0jlOfjZE=
|
||||
github.com/cloudwego/hertz v0.9.1/go.mod h1:cs8dH6unM4oaJ5k9m6pqbgLBPqakGWMG0+cthsxitsg=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cloudwego/netpoll v0.6.0 h1:JRMkrA1o8k/4quxzg6Q1XM+zIhwZsyoWlq6ef+ht31U=
|
||||
github.com/cloudwego/netpoll v0.6.0/go.mod h1:xVefXptcyheopwNDZjDPcfU6kIjZXZ4nY550k1yH9eQ=
|
||||
github.com/coreos/go-iptables v0.7.0 h1:XWM3V+MPRr5/q51NuWSgU0fqMad64Zyxs8ZUoMsamr8=
|
||||
github.com/coreos/go-iptables v0.7.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
||||
github.com/corpix/uarand v0.2.0 h1:U98xXwud/AVuCpkpgfPF7J5TQgr7R5tqT8VZP5KWbzE=
|
||||
@ -69,6 +83,7 @@ github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 h1:fuGucgPk5d
|
||||
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010/go.mod h1:JtBcj7sBuTTRupn7c2bFspMDIObMJsVK8TeUvpShPok=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
|
||||
@ -134,8 +149,15 @@ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbu
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
|
||||
github.com/google/tink/go v1.6.1/go.mod h1:IGW53kTgag+st5yPhKKwJ6u2l+SSp5/v9XF7spovjlY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/henrylee2cn/ameda v1.4.8/go.mod h1:liZulR8DgHxdK+MEwvZIylGnmcjzQ6N6f2PlWe7nEO4=
|
||||
github.com/henrylee2cn/ameda v1.4.10 h1:JdvI2Ekq7tapdPsuhrc4CaFiqw6QXFvZIULWJgQyCAk=
|
||||
github.com/henrylee2cn/ameda v1.4.10/go.mod h1:liZulR8DgHxdK+MEwvZIylGnmcjzQ6N6f2PlWe7nEO4=
|
||||
github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 h1:yE9ULgp02BhYIrO6sdV/FPe0xQM6fNHkVQW2IAymfM0=
|
||||
github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8/go.mod h1:Nhe/DM3671a5udlv2AdV2ni/MZzgfv2qrPL5nIi3EGQ=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240419123447-f1cffa2c0c49 h1:/OuvSMGT9+xnyZ+7MZQ1zdngaCCAdPoSw8B/uurZ7pg=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20240419123447-f1cffa2c0c49/go.mod h1:KclMyHxX06VrVr0DJmeFSUb1ankt7xTfoOA35pCkoic=
|
||||
@ -156,6 +178,8 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o=
|
||||
github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak=
|
||||
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
@ -217,6 +241,8 @@ github.com/mroth/weightedrand/v2 v2.1.0/go.mod h1:f2faGsfOGOwc1p94wzHKKZyTpcJUW7
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/nyaruka/phonenumbers v1.0.55 h1:bj0nTO88Y68KeUQ/n3Lo2KgK7lM1hF7L9NFuwcCl3yg=
|
||||
github.com/nyaruka/phonenumbers v1.0.55/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U=
|
||||
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 h1:1102pQc2SEPp5+xrS26wEaeb26sZy6k9/ZXlZN+eXE4=
|
||||
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7/go.mod h1:UqoUn6cHESlliMhOnKLWr+CBH+e3bazUPvFj1XZwAjs=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
@ -238,6 +264,7 @@ github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq5
|
||||
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
|
||||
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
|
||||
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@ -288,12 +315,17 @@ github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e h1:ur8uMsPIF
|
||||
github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e/go.mod h1:+e5fBW3bpPyo+3uLo513gIUblc03egGjMM0+5GKbzK8=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
@ -306,6 +338,13 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8
|
||||
github.com/temoto/robotstxt v1.1.1/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo=
|
||||
github.com/temoto/robotstxt v1.1.2 h1:W2pOjSJ6SWvldyEuiFXNxz3xZ8aiWX5LbfDiOFd7Fxg=
|
||||
github.com/temoto/robotstxt v1.1.2/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo=
|
||||
github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/timerzz/proxypool v0.0.0-20240512142241-f74bcb3534c5 h1:/UVxZzOD+N5HVX+A+kDUDVE1cJSHbh4PSfL8H+EW5nM=
|
||||
github.com/timerzz/proxypool v0.0.0-20240512142241-f74bcb3534c5/go.mod h1:Ba8aQPgnCdkBJoKGs9Fb6bPR+RHcmXhsSYVAQzREC8k=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
@ -335,6 +374,7 @@ go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
@ -389,6 +429,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/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-20210220032951-036812b2e83c/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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
@ -411,6 +452,8 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/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-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -454,6 +497,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
@ -489,6 +533,7 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -13,6 +13,13 @@ const (
|
||||
defaultFreight float64 = 100
|
||||
)
|
||||
|
||||
type Website int
|
||||
|
||||
const (
|
||||
WebSite_US_Coach_Outlet Website = iota + 1
|
||||
WebSite_CN_Coach
|
||||
)
|
||||
|
||||
type PriceStatus int
|
||||
|
||||
const (
|
||||
@ -35,6 +42,7 @@ type Product struct {
|
||||
Orderable bool `json:"orderable"`
|
||||
|
||||
USPrice float64 `json:"usPrice"`
|
||||
Website Website `json:"website" gorm:"index"`
|
||||
DiscPercent int `json:"discPercent" gorm:"index"` //折扣力度
|
||||
CNYPrice float64 `json:"cnyPrice"`
|
||||
CalMark string `json:"calMark"` //计算价格的过程
|
||||
@ -73,6 +81,15 @@ func (p *Product) BeforeSave(tx *gorm.DB) (err error) {
|
||||
}
|
||||
|
||||
func (p *Product) CalRate() {
|
||||
switch p.Website {
|
||||
case WebSite_US_Coach_Outlet:
|
||||
p.CalRateUSCoach()
|
||||
case WebSite_CN_Coach:
|
||||
p.CalRateCNCoach()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Product) CalRateUSCoach() {
|
||||
calculationProcess := make([]string, 0, 2) //存放计算过程
|
||||
if p.ExchangeRate == 0 {
|
||||
p.ExchangeRate = defaultExchangeRate
|
||||
@ -119,6 +136,15 @@ func (p *Product) CalRate() {
|
||||
p.CNYPrice = Decimal(p.CNYPrice)
|
||||
}
|
||||
|
||||
func (p *Product) CalRateCNCoach() {
|
||||
if p.DWPrice > 0 {
|
||||
// 如果有得物价格,就计算收益率
|
||||
p.Rate = Decimal((p.DWPrice - p.CNYPrice) / p.CNYPrice * 100)
|
||||
}
|
||||
|
||||
p.CNYPrice = Decimal(p.CNYPrice)
|
||||
}
|
||||
|
||||
// Decimal 保留两位小数
|
||||
func Decimal(value float64) float64 {
|
||||
return math.Trunc(value*1e2+0.5) * 1e-2
|
||||
|
@ -1,64 +0,0 @@
|
||||
package coach_client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"gitea.timerzz.com/kedaya_haitao/common/pkg/proxy"
|
||||
restry_pool "gitea.timerzz.com/kedaya_haitao/common/pkg/restry-pool"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/pkg/errors"
|
||||
proxy2 "github.com/timerzz/proxypool/pkg/proxy"
|
||||
"log/slog"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
pool *proxy.ProxyPool
|
||||
defaultTimeOut time.Duration
|
||||
}
|
||||
|
||||
func NewClient(pool *proxy.ProxyPool) *Client {
|
||||
return &Client{
|
||||
pool: pool,
|
||||
defaultTimeOut: 10 * time.Minute,
|
||||
}
|
||||
}
|
||||
|
||||
func tryRequest(ctx context.Context, urlPath string, respData any, proxyGetter func() proxy2.Proxy) error {
|
||||
for p := proxyGetter(); p != nil; p = proxyGetter() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
||||
return fmt.Errorf("超时未获取到结果,链接:%s", urlPath)
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
|
||||
}
|
||||
_, err := callByProxy(ctx, p, urlPath, respData)
|
||||
if err != nil {
|
||||
slog.Debug(err.Error())
|
||||
continue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return errors.New("未获取到可用的代理")
|
||||
}
|
||||
|
||||
func callByProxy(ctx context.Context, p proxy2.Proxy, urlPath string, result any) (*resty.Response, error) {
|
||||
addr, err := proxy.UrlToMetadata(urlPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subCtx, cancel := context.WithTimeout(ctx, time.Second*10)
|
||||
defer cancel()
|
||||
conn, err := proxy.ConnFromProxy(subCtx, p, addr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "创建conn失败")
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
var cli = restry_pool.GetRestyClient(conn)
|
||||
defer restry_pool.PutRestyClient(cli)
|
||||
return cli.R().SetResult(result).Get(urlPath)
|
||||
}
|
92
pkg/coach-client/client_cn.go
Normal file
92
pkg/coach-client/client_cn.go
Normal file
@ -0,0 +1,92 @@
|
||||
package coach_client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/cloudwego/hertz/pkg/app/client"
|
||||
"github.com/cloudwego/hertz/pkg/protocol"
|
||||
"github.com/corpix/uarand"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CN struct {
|
||||
c *client.Client
|
||||
}
|
||||
|
||||
func CNClient() (cli *CN, err error) {
|
||||
cli = new(CN)
|
||||
cli.c, err = client.NewClient()
|
||||
return
|
||||
}
|
||||
|
||||
type CNData interface {
|
||||
ItemListData
|
||||
}
|
||||
|
||||
type CNResponse[data CNData] struct {
|
||||
Data data `json:"data"`
|
||||
Msg string `json:"msg"`
|
||||
Rid string `json:"rid"`
|
||||
StatusCode string `json:"statusCode"`
|
||||
}
|
||||
|
||||
type ItemListData struct {
|
||||
Count int `json:"count"`
|
||||
CurrentPage int `json:"currentPage"`
|
||||
Items []CNItem `json:"items"`
|
||||
Size int `json:"size"`
|
||||
TotalPages int `json:"totalPages"`
|
||||
}
|
||||
|
||||
type CNItem struct {
|
||||
Code string `json:"code"`
|
||||
DiscountRateMin float64 `json:"discountRateMin"`
|
||||
Id int `json:"id"`
|
||||
Images []struct {
|
||||
Imgs []struct {
|
||||
Config string `json:"config"`
|
||||
Img string `json:"img"`
|
||||
Position int `json:"position"`
|
||||
Resource string `json:"resource"`
|
||||
Type int `json:"type"`
|
||||
} `json:"imgs"`
|
||||
ItemPropId int `json:"itemPropId"`
|
||||
} `json:"images"`
|
||||
ListPrice float64 `json:"listPrice"`
|
||||
SalePrice float64 `json:"salePrice"`
|
||||
SkuMaxPrice float64 `json:"skuMaxPrice"`
|
||||
Stock int `json:"stock"`
|
||||
Style string `json:"style"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
func (c *CN) ListItems(_ctx context.Context, page, size int) (ItemListData, error) {
|
||||
req, resp := protocol.AcquireRequest(), protocol.AcquireResponse()
|
||||
defer func() {
|
||||
protocol.ReleaseRequest(req)
|
||||
protocol.ReleaseResponse(resp)
|
||||
}()
|
||||
page = max(page, 1)
|
||||
size = max(size, 50)
|
||||
req.SetRequestURI("https://ec-api.coach.com.cn/api/v2/item/search")
|
||||
req.SetMethod("GET")
|
||||
req.SetHeader("X-Ma-C", " b55d4769f3e768630046291ee2ee26f0")
|
||||
req.SetHeader("User-Agent", uarand.GetRandom())
|
||||
req.SetQueryString(fmt.Sprintf("scope=shop&pageNo=%d&pageSize=%d", page, size))
|
||||
|
||||
ctx, cancel := context.WithTimeout(_ctx, time.Second*30)
|
||||
defer cancel()
|
||||
err := c.c.Do(ctx, req, resp)
|
||||
if err != nil {
|
||||
return ItemListData{}, err
|
||||
}
|
||||
var respData CNResponse[ItemListData]
|
||||
if err = sonic.Unmarshal(resp.Body(), &respData); err != nil {
|
||||
return ItemListData{}, err
|
||||
}
|
||||
if respData.StatusCode != "100010" {
|
||||
return ItemListData{}, fmt.Errorf("status code: %s, msg: %s", respData.StatusCode, respData.Msg)
|
||||
}
|
||||
return respData.Data, nil
|
||||
}
|
25
pkg/coach-client/client_cn_test.go
Normal file
25
pkg/coach-client/client_cn_test.go
Normal file
@ -0,0 +1,25 @@
|
||||
package coach_client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCNClient(t *testing.T) {
|
||||
cli, err := CNClient()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var page, total int
|
||||
var resp ItemListData
|
||||
var items []CNItem
|
||||
for ; page <= total; page++ {
|
||||
if resp, err = cli.ListItems(context.Background(), page, 50); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
total = resp.TotalPages
|
||||
items = append(items, resp.Items...)
|
||||
}
|
||||
t.Logf("共%d个", len(items))
|
||||
|
||||
}
|
189
pkg/coach-client/client_us.go
Normal file
189
pkg/coach-client/client_us.go
Normal file
@ -0,0 +1,189 @@
|
||||
package coach_client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"gitea.timerzz.com/kedaya_haitao/common/pkg/proxy"
|
||||
restry_pool "gitea.timerzz.com/kedaya_haitao/common/pkg/restry-pool"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/pkg/errors"
|
||||
proxy2 "github.com/timerzz/proxypool/pkg/proxy"
|
||||
"log/slog"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
type US struct {
|
||||
pool *proxy.ProxyPool
|
||||
defaultTimeOut time.Duration
|
||||
}
|
||||
|
||||
func USClient(pool *proxy.ProxyPool) *US {
|
||||
return &US{
|
||||
pool: pool,
|
||||
defaultTimeOut: 10 * time.Minute,
|
||||
}
|
||||
}
|
||||
|
||||
func tryRequest(ctx context.Context, urlPath string, respData any, proxyGetter func() proxy2.Proxy) error {
|
||||
for p := proxyGetter(); p != nil; p = proxyGetter() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
|
||||
return fmt.Errorf("超时未获取到结果,链接:%s", urlPath)
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
|
||||
}
|
||||
_, err := callByProxy(ctx, p, urlPath, respData)
|
||||
if err != nil {
|
||||
slog.Debug(err.Error())
|
||||
continue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return errors.New("未获取到可用的代理")
|
||||
}
|
||||
|
||||
func callByProxy(ctx context.Context, p proxy2.Proxy, urlPath string, result any) (*resty.Response, error) {
|
||||
addr, err := proxy.UrlToMetadata(urlPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subCtx, cancel := context.WithTimeout(ctx, time.Second*10)
|
||||
defer cancel()
|
||||
conn, err := proxy.ConnFromProxy(subCtx, p, addr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "创建conn失败")
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
var cli = restry_pool.GetRestyClient(conn)
|
||||
defer restry_pool.PutRestyClient(cli)
|
||||
return cli.R().SetResult(result).Get(urlPath)
|
||||
}
|
||||
|
||||
type Inventory struct {
|
||||
Id string `json:"id"`
|
||||
Ats int `json:"ats"`
|
||||
PreOrderable bool `json:"preorderable"`
|
||||
BackOrderable bool `json:"backorderable"`
|
||||
Orderable bool `json:"orderable"`
|
||||
AllocationResetDate time.Time `json:"allocationResetDate,omitempty"`
|
||||
Perpetual bool `json:"perpetual"`
|
||||
StockLevel int `json:"stockLevel"`
|
||||
}
|
||||
|
||||
type InventoryResponse struct {
|
||||
Inventory struct {
|
||||
Status string `json:"status"`
|
||||
InventoryListID string `json:"inventoryListID"`
|
||||
InventoryInfo Inventory `json:"inventoryInfo"`
|
||||
} `json:"inventory"`
|
||||
}
|
||||
|
||||
func (c *US) RequestInventory(ctx context.Context, pid string) (inv Inventory, err error) {
|
||||
sctx, cancel := context.WithTimeout(ctx, c.defaultTimeOut)
|
||||
defer cancel()
|
||||
var resp InventoryResponse
|
||||
urlPath := fmt.Sprintf("https://www.coachoutlet.com/api/inventory?vgId=%s&includeVariantData=false", url.QueryEscape(pid))
|
||||
err = tryRequest(sctx, urlPath, &resp, c.pool.RandomIterator())
|
||||
inv = resp.Inventory.InventoryInfo
|
||||
return
|
||||
}
|
||||
|
||||
type ProductData struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Brand string `json:"brand"`
|
||||
Inventory Inventory `json:"inventory"`
|
||||
Url string `json:"url"`
|
||||
MasterId string `json:"masterId"`
|
||||
Prices struct {
|
||||
CurrentPrice float64 `json:"currentPrice"`
|
||||
} `json:"prices"`
|
||||
Remark string `json:"-"`
|
||||
}
|
||||
|
||||
type ProductDataResponse struct {
|
||||
ProductData []*ProductData `json:"productsData"`
|
||||
}
|
||||
|
||||
func (c *US) RequestProductDetail(ctx context.Context, pid string) (data ProductData, err error) {
|
||||
sctx, cancel := context.WithTimeout(ctx, c.defaultTimeOut)
|
||||
defer cancel()
|
||||
var resp ProductDataResponse
|
||||
urlPath := fmt.Sprintf("https://www.coachoutlet.com/api/get-products?ids=%s&includeInventory=false", url.QueryEscape(pid))
|
||||
err = tryRequest(sctx, urlPath, &resp, c.pool.RandomIterator())
|
||||
if len(resp.ProductData) == 0 && err != nil {
|
||||
err = fmt.Errorf("获取详情信息为空")
|
||||
return
|
||||
}
|
||||
if len(resp.ProductData) > 0 {
|
||||
data = *resp.ProductData[0]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type PageDataResponse struct {
|
||||
PageData struct {
|
||||
Total int `json:"total"`
|
||||
Page int `json:"page"`
|
||||
TotalPages int `json:"totalPages"`
|
||||
PageSize int `json:"pageSize"`
|
||||
Products []Product `json:"products"`
|
||||
} `json:"pageData"`
|
||||
}
|
||||
type Product struct {
|
||||
Name string `json:"name"`
|
||||
Colors []Color `json:"colors"`
|
||||
VariantsOnSale []Variant `json:"variantsOnSale"`
|
||||
}
|
||||
|
||||
type Color struct {
|
||||
Id string `json:"id"` //"id": "IMDQC",
|
||||
Text string `json:"text"` //颜色的描述
|
||||
Orderable bool `json:"orderable"`
|
||||
Media Media `json:"media"`
|
||||
Url string `json:"url"` //"/products/eliza-flap-crossbody-bag-in-signature-canvas/CP009-IMDQC.html",
|
||||
VgId string `json:"vgId"` // "vgId": "CP009-IMDQC",
|
||||
MasterId string `json:"masterId"` //"masterId": "CP009"
|
||||
}
|
||||
|
||||
type Media struct {
|
||||
Thumbnail Thumbnail `json:"thumbnail"`
|
||||
}
|
||||
|
||||
type Thumbnail struct {
|
||||
Src string `json:"src"`
|
||||
}
|
||||
|
||||
type Variant struct {
|
||||
Id string `json:"id"`
|
||||
OnSale bool `json:"onSale"`
|
||||
Price Price `json:"price"`
|
||||
}
|
||||
|
||||
type Price struct {
|
||||
Sales Sales `json:"sales"`
|
||||
MarkdownDiscPercent int `json:"markdownDiscPercent"`
|
||||
}
|
||||
|
||||
type Sales struct {
|
||||
Value float64 `json:"value"`
|
||||
Currency string `json:"currency"`
|
||||
Formatted string `json:"formatted"`
|
||||
DecimalPrice string `json:"decimalPrice"`
|
||||
}
|
||||
|
||||
func (c *US) ViewAllBags(ctx context.Context, page int) (resp PageDataResponse, err error) {
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
sctx, cancel := context.WithTimeout(ctx, c.defaultTimeOut)
|
||||
defer cancel()
|
||||
urlPath := fmt.Sprintf("https://www.coachoutlet.com/api/get-shop/bags/view-all?page=%d", page)
|
||||
err = tryRequest(sctx, urlPath, &resp, c.pool.RandomIterator())
|
||||
return
|
||||
}
|
@ -9,7 +9,7 @@ import (
|
||||
func TestClient(t *testing.T) {
|
||||
subs := []string{"https://us.timerzz.com:26106/vmess/sub", "https://us.timerzz.com:26106/trojan/sub", "https://us.timerzz.com:26106/ssr/sub"}
|
||||
pool := proxy.NewProxyPool(subs)
|
||||
client := NewClient(pool)
|
||||
client := USClient(pool)
|
||||
resp, err := client.ViewAllBags(context.Background(), 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
@ -1,40 +0,0 @@
|
||||
package coach_client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type ProductData struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Brand string `json:"brand"`
|
||||
Inventory Inventory `json:"inventory"`
|
||||
Url string `json:"url"`
|
||||
MasterId string `json:"masterId"`
|
||||
Prices struct {
|
||||
CurrentPrice float64 `json:"currentPrice"`
|
||||
} `json:"prices"`
|
||||
Remark string `json:"-"`
|
||||
}
|
||||
|
||||
type ProductDataResponse struct {
|
||||
ProductData []*ProductData `json:"productsData"`
|
||||
}
|
||||
|
||||
func (c *Client) RequestProductDetail(ctx context.Context, pid string) (data ProductData, err error) {
|
||||
sctx, cancel := context.WithTimeout(ctx, c.defaultTimeOut)
|
||||
defer cancel()
|
||||
var resp ProductDataResponse
|
||||
urlPath := fmt.Sprintf("https://www.coachoutlet.com/api/get-products?ids=%s&includeInventory=false", url.QueryEscape(pid))
|
||||
err = tryRequest(sctx, urlPath, &resp, c.pool.RandomIterator())
|
||||
if len(resp.ProductData) == 0 && err != nil {
|
||||
err = fmt.Errorf("获取详情信息为空")
|
||||
return
|
||||
}
|
||||
if len(resp.ProductData) > 0 {
|
||||
data = *resp.ProductData[0]
|
||||
}
|
||||
return
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package coach_client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Inventory struct {
|
||||
Id string `json:"id"`
|
||||
Ats int `json:"ats"`
|
||||
PreOrderable bool `json:"preorderable"`
|
||||
BackOrderable bool `json:"backorderable"`
|
||||
Orderable bool `json:"orderable"`
|
||||
AllocationResetDate time.Time `json:"allocationResetDate,omitempty"`
|
||||
Perpetual bool `json:"perpetual"`
|
||||
StockLevel int `json:"stockLevel"`
|
||||
}
|
||||
|
||||
type InventoryResponse struct {
|
||||
Inventory struct {
|
||||
Status string `json:"status"`
|
||||
InventoryListID string `json:"inventoryListID"`
|
||||
InventoryInfo Inventory `json:"inventoryInfo"`
|
||||
} `json:"inventory"`
|
||||
}
|
||||
|
||||
func (c *Client) RequestInventory(ctx context.Context, pid string) (inv Inventory, err error) {
|
||||
sctx, cancel := context.WithTimeout(ctx, c.defaultTimeOut)
|
||||
defer cancel()
|
||||
var resp InventoryResponse
|
||||
urlPath := fmt.Sprintf("https://www.coachoutlet.com/api/inventory?vgId=%s&includeVariantData=false", url.QueryEscape(pid))
|
||||
err = tryRequest(sctx, urlPath, &resp, c.pool.RandomIterator())
|
||||
inv = resp.Inventory.InventoryInfo
|
||||
return
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
package coach_client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type PageDataResponse struct {
|
||||
PageData struct {
|
||||
Total int `json:"total"`
|
||||
Page int `json:"page"`
|
||||
TotalPages int `json:"totalPages"`
|
||||
PageSize int `json:"pageSize"`
|
||||
Products []Product `json:"products"`
|
||||
} `json:"pageData"`
|
||||
}
|
||||
type Product struct {
|
||||
Name string `json:"name"`
|
||||
Colors []Color `json:"colors"`
|
||||
VariantsOnSale []Variant `json:"variantsOnSale"`
|
||||
}
|
||||
|
||||
type Color struct {
|
||||
Id string `json:"id"` //"id": "IMDQC",
|
||||
Text string `json:"text"` //颜色的描述
|
||||
Orderable bool `json:"orderable"`
|
||||
Media Media `json:"media"`
|
||||
Url string `json:"url"` //"/products/eliza-flap-crossbody-bag-in-signature-canvas/CP009-IMDQC.html",
|
||||
VgId string `json:"vgId"` // "vgId": "CP009-IMDQC",
|
||||
MasterId string `json:"masterId"` //"masterId": "CP009"
|
||||
}
|
||||
|
||||
type Media struct {
|
||||
Thumbnail Thumbnail `json:"thumbnail"`
|
||||
}
|
||||
|
||||
type Thumbnail struct {
|
||||
Src string `json:"src"`
|
||||
}
|
||||
|
||||
type Variant struct {
|
||||
Id string `json:"id"`
|
||||
OnSale bool `json:"onSale"`
|
||||
Price Price `json:"price"`
|
||||
}
|
||||
|
||||
type Price struct {
|
||||
Sales Sales `json:"sales"`
|
||||
MarkdownDiscPercent int `json:"markdownDiscPercent"`
|
||||
}
|
||||
|
||||
type Sales struct {
|
||||
Value float64 `json:"value"`
|
||||
Currency string `json:"currency"`
|
||||
Formatted string `json:"formatted"`
|
||||
DecimalPrice string `json:"decimalPrice"`
|
||||
}
|
||||
|
||||
func (c *Client) ViewAllBags(ctx context.Context, page int) (resp PageDataResponse, err error) {
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
sctx, cancel := context.WithTimeout(ctx, c.defaultTimeOut)
|
||||
defer cancel()
|
||||
urlPath := fmt.Sprintf("https://www.coachoutlet.com/api/get-shop/bags/view-all?page=%d", page)
|
||||
err = tryRequest(sctx, urlPath, &resp, c.pool.RandomIterator())
|
||||
return
|
||||
}
|
@ -41,7 +41,7 @@ func NewRestyPool() *restyPool {
|
||||
return &restyPool{
|
||||
resty: sync.Pool{
|
||||
New: func() any {
|
||||
return resty.New().SetHeader("User-Agent", UserAgent).OnBeforeRequest(beforeRequest)
|
||||
return resty.New().OnBeforeRequest(beforeRequest)
|
||||
},
|
||||
},
|
||||
transport: sync.Pool{
|
||||
|
Loading…
Reference in New Issue
Block a user