Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1d0e1812c8 | |||
| 40490ffe43 | |||
| 455b6d40de | |||
| 62dcac103f | |||
| 63a83ddd5e | |||
| f8d3d6a0ad | |||
| e2eb27a5ba | |||
| 9fbeddc9f4 | |||
| 289bbe3f0d | |||
| bec6a93b65 | |||
| e2a41fc187 | |||
| c7a04f3857 | |||
| 9c5398071c | |||
| 1f6400ba5d | |||
| afe0c149dd | |||
| 9b9d05a4ac | |||
| f59cb29e4d | |||
| f71ee4fab4 | |||
| 6390831f16 | |||
| da2fd3111b | |||
| 02f97fb4a4 | |||
| ceee685b80 | |||
| 132472de12 | |||
| 7d8c14a045 | |||
| 25d190c498 | |||
| f1dfa61578 | |||
| 2c0026267e | |||
| ab84984fb0 | |||
| 4f6e516ade | |||
| c9aeb90209 | |||
| 2125fd4bde | |||
| 41dfe9ff54 | |||
| 18fc1cee7a |
@@ -29,7 +29,7 @@ jobs:
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
username: ${{ secrets.USERNAME }}
|
||||
password: ${{ secrets.PASSWORD }}
|
||||
- name: Extract metadata for Docker
|
||||
id: meta
|
||||
|
||||
+7
-5
@@ -1,14 +1,16 @@
|
||||
FROM golang:alpine AS backend-builder
|
||||
FROM golang:latest AS backend-builder
|
||||
RUN apt update
|
||||
RUN apt install -y build-essential
|
||||
WORKDIR /build
|
||||
COPY . .
|
||||
ENV CGO_ENABLED=1
|
||||
RUN go build -ldflags="-s -w" -o bin/server
|
||||
|
||||
RUN go build -ldflags="-s -w" -o bin/server cmd/server
|
||||
|
||||
RUN apk add --no-cache upx
|
||||
RUN apt install -y upx-ucl
|
||||
|
||||
RUN upx --best --lzma bin/server
|
||||
|
||||
FROM alpine:latest
|
||||
FROM golang:latest
|
||||
COPY --from=backend-builder /build/bin/server /app/server
|
||||
COPY static /app/static
|
||||
COPY static/*.so /app/
|
||||
|
||||
@@ -9,6 +9,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.6
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.71
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.84.1
|
||||
github.com/breml/rootcerts v0.3.3
|
||||
github.com/bytedance/sonic v1.14.0
|
||||
github.com/deatil/go-cryptobin v1.1.1005
|
||||
github.com/go-sql-driver/mysql v1.9.3
|
||||
@@ -20,14 +21,14 @@ require (
|
||||
github.com/joomcode/errorx v1.2.0
|
||||
github.com/redis/go-redis/v9 v9.11.0
|
||||
github.com/samber/oops v1.19.0
|
||||
github.com/shirou/gopsutil/v3 v3.24.5
|
||||
github.com/shopspring/decimal v1.4.0
|
||||
github.com/spf13/viper v1.20.1
|
||||
github.com/tidwall/gjson v1.18.0
|
||||
github.com/tidwall/match v1.1.1
|
||||
github.com/wenlng/go-captcha-assets v1.0.7
|
||||
github.com/wenlng/go-captcha/v2 v2.0.4
|
||||
github.com/wneessen/go-mail v0.6.2
|
||||
github.com/yalue/onnxruntime_go v1.22.0
|
||||
github.com/yalue/onnxruntime_go v1.9.0
|
||||
go.uber.org/automaxprocs v1.6.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/crypto v0.39.0
|
||||
@@ -61,14 +62,15 @@ require (
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-openapi/inflect v0.19.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/grokify/html-strip-tags-go v0.1.0 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.18.1 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/magiconair/properties v1.8.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
@@ -76,18 +78,17 @@ require (
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/oklog/ulid/v2 v2.1.1 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.7.0 // indirect
|
||||
github.com/samber/lo v1.51.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.12.0 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/spf13/cast v1.9.2 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // 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
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
github.com/zclconf/go-cty v1.14.4 // indirect
|
||||
github.com/zclconf/go-cty-yaml v1.1.0 // indirect
|
||||
go.opentelemetry.io/otel v1.32.0 // indirect
|
||||
|
||||
@@ -44,6 +44,8 @@ github.com/aws/smithy-go v1.22.4 h1:uqXzVZNuNexwc/xrh6Tb56u89WDlJY6HS+KC0S4QSjw=
|
||||
github.com/aws/smithy-go v1.22.4/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
||||
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
|
||||
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
|
||||
github.com/breml/rootcerts v0.3.3 h1://GnaRtQ/9BY2+GtMk2wtWxVdCRysiaPr5/xBwl7NKw=
|
||||
github.com/breml/rootcerts v0.3.3/go.mod h1:S/PKh+4d1HUn4HQovEB8hPJZO6pUZYrIhmXBhsegfXw=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
@@ -80,14 +82,14 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
|
||||
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
|
||||
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
|
||||
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
|
||||
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0 h1:EEZqu1PNRSmm+7Cqm9A/8+ObgfbMzhE1ps9Z3LD7HgM=
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.0/go.mod h1:LHrxY+2IzNTHVTPG/s5yaz1VmXbj+CQ7Hr5SeVkHiTw=
|
||||
github.com/gogf/gf/v2 v2.9.0 h1:semN5Q5qGjDQEv4620VzxcJzJlSD07gmyJ9Sy9zfbHk=
|
||||
@@ -96,6 +98,7 @@ github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeD
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
@@ -119,6 +122,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
|
||||
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
@@ -138,10 +143,10 @@ github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNs
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
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/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||
github.com/redis/go-redis/v9 v9.11.0 h1:E3S08Gl/nJNn5vkxd2i78wZxWAPNZgUNTp8WIJUAiIs=
|
||||
@@ -153,26 +158,22 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
|
||||
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
|
||||
github.com/samber/lo v1.51.0 h1:kysRYLbHy/MB7kQZf5DSN50JHmMsNEdeY24VzJFu7wI=
|
||||
github.com/samber/lo v1.51.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
|
||||
github.com/samber/oops v1.19.0 h1:sfZAwC8MmTXBRRyNc4Z1utuTPBx+hFKF5fJ9DEQRZfw=
|
||||
github.com/samber/oops v1.19.0/go.mod h1:+f+61dbiMxEMQ8gw/zTxW2pk+YGobaDM4glEHQtPOww=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
|
||||
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
|
||||
github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
|
||||
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
|
||||
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
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=
|
||||
@@ -183,14 +184,16 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/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/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/wenlng/go-captcha-assets v1.0.7 h1:tfF84A4un/i4p+TbRVHDqDPeQeatvddOfB2xbKvLVq8=
|
||||
@@ -199,9 +202,11 @@ github.com/wenlng/go-captcha/v2 v2.0.4 h1:5cSUF36ZyA03qeDMjKmeXGpbYJMXEexZIYK3Vg
|
||||
github.com/wenlng/go-captcha/v2 v2.0.4/go.mod h1:5hac1em3uXoyC5ipZ0xFv9umNM/waQvYAQdr0cx/h34=
|
||||
github.com/wneessen/go-mail v0.6.2 h1:c6V7c8D2mz868z9WJ+8zDKtUyLfZ1++uAZmo2GRFji8=
|
||||
github.com/wneessen/go-mail v0.6.2/go.mod h1:L/PYjPK3/2ZlNb2/FjEBIn9n1rUWjW+Toy531oVmeb4=
|
||||
github.com/yalue/onnxruntime_go v1.22.0 h1:SzqOfFRRrLRRAFR5VoSxABjTiQSAi8Y4ETYKrMFK1jk=
|
||||
github.com/yalue/onnxruntime_go v1.22.0/go.mod h1:b4X26A8pekNb1ACJ58wAXgNKeUCGEAQ9dmACut9Sm/4=
|
||||
github.com/yalue/onnxruntime_go v1.9.0 h1:AhgkpBjphJZsHT5karKt93xPkPFNP0Iz6ENUbNAFQU4=
|
||||
github.com/yalue/onnxruntime_go v1.9.0/go.mod h1:b4X26A8pekNb1ACJ58wAXgNKeUCGEAQ9dmACut9Sm/4=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8=
|
||||
github.com/zclconf/go-cty v1.14.4/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
|
||||
github.com/zclconf/go-cty-yaml v1.1.0 h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0=
|
||||
@@ -265,7 +270,9 @@ golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -273,6 +280,7 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
@@ -313,6 +321,7 @@ golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxb
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -52,6 +52,7 @@ func StartServer(ctx context.Context) {
|
||||
cpdailyGroup.Bind(cpdaily.NewCpUserCtrlV1())
|
||||
cpdailyGroup.Bind(cpdaily.NewCpTaskCtrlV1())
|
||||
cpdailyGroup.Bind(cpdaily.NewCpImageCtrlV1())
|
||||
cpdailyGroup.Bind(cpdaily.NewCpTaskLogCtrlV1())
|
||||
})
|
||||
|
||||
s.SetPort(port.Int())
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
|
||||
type GetRecentTasksReq struct {
|
||||
g.Meta `path:"/task/recent" method:"get" tags:"CpTask" summary:"获取最近任务"`
|
||||
UserId int64 `json:"userId"`
|
||||
Type string `json:"type"`
|
||||
UserId int64 `json:"userId"`
|
||||
Type cptask.TaskType `json:"type"`
|
||||
}
|
||||
|
||||
type AddTaskReq struct {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
type CpTaskLogListReq struct {
|
||||
g.Meta `path:"/taskLog" method:"get" tags:"CpTaskLog" summary:"获取cp任务日志"`
|
||||
TaskID int64 `json:"task_id"`
|
||||
Page int `json:"page" d:"1"`
|
||||
Size int `json:"size" d:"10"`
|
||||
}
|
||||
|
||||
type CpTaskOCRReq struct {
|
||||
g.Meta `path:"/ocr" method:"post" tags:"CpTask" summary:"OCR识别" auth:"false"`
|
||||
File *ghttp.UploadFile `json:"file"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
@@ -5,9 +5,12 @@ import (
|
||||
"fmt"
|
||||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
"likedream-goframe/internal/framework/logger"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
ort "github.com/yalue/onnxruntime_go"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type ImageClassifier struct {
|
||||
@@ -21,6 +24,9 @@ type ImageClassifier struct {
|
||||
// NewImageClassifier 创建新的图片分类器
|
||||
func NewImageClassifier(modelPath, classesPath string) (*ImageClassifier, error) {
|
||||
// 初始化ONNX Runtime
|
||||
dir := filepath.Dir(os.Args[0])
|
||||
ort.SetSharedLibraryPath(dir)
|
||||
logger.Logger.Info("初始化onnx:", zap.String("文件夹", dir))
|
||||
err := ort.InitializeEnvironment()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("初始化ONNX Runtime失败: %v", err)
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
package classifier
|
||||
|
||||
var imageClassifier, err = NewImageClassifier("./static/model.onnx", "./static/classes.txt")
|
||||
import "likedream-goframe/internal/utils"
|
||||
|
||||
var imageClassifier, _ = NewImageClassifier("static/model.onnx", "static/classes.txt")
|
||||
|
||||
// 图片数据 & 类别名称
|
||||
// return 是否匹配
|
||||
func ClassifyImage(imgData []byte, className string) bool {
|
||||
if imageClassifier == nil {
|
||||
c, err := NewImageClassifier("static/model.onnx", "static/classes.txt")
|
||||
utils.OkOrPanic(err)
|
||||
imageClassifier = c
|
||||
}
|
||||
name, _, _ := imageClassifier.PredictFromBytes(imgData)
|
||||
return className == name
|
||||
}
|
||||
|
||||
@@ -2,13 +2,14 @@ package login
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/samber/oops"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tidwall/gjson"
|
||||
"io"
|
||||
"likedream-goframe/internal/application/httpclient"
|
||||
"likedream-goframe/internal/cst"
|
||||
"likedream-goframe/internal/utils"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/samber/oops"
|
||||
"github.com/tidwall/gjson"
|
||||
"resty.dev/v3"
|
||||
)
|
||||
|
||||
@@ -28,7 +29,7 @@ func ResolveOcrCaptcha(ctx context.Context, url string, client *resty.Client) st
|
||||
_ = captchaResponse.Body.Close()
|
||||
}()
|
||||
|
||||
ocrUrl := viper.GetString(cst.ConfigOcrServerUrl)
|
||||
ocrUrl := g.Cfg().MustGetWithEnv(ctx, cst.ConfigOcrServerUrl).String()
|
||||
|
||||
ocrResponse, err := httpclient.Common.R().
|
||||
SetMultipartFields(&resty.MultipartField{
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package school
|
||||
|
||||
import "C"
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/samber/oops"
|
||||
"github.com/tidwall/gjson"
|
||||
cryptoutil2 "likedream-goframe/internal/application/cpdaily/cryptoutil"
|
||||
"likedream-goframe/internal/application/httpclient"
|
||||
"likedream-goframe/internal/common/errors"
|
||||
"likedream-goframe/internal/utils"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/samber/oops"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func GetSchoolList(ctx context.Context) []CpdailySchoolBriefInfo {
|
||||
@@ -50,7 +52,7 @@ func GetSchoolList(ctx context.Context) []CpdailySchoolBriefInfo {
|
||||
}
|
||||
|
||||
func GetSchoolDetail(ctx context.Context, tenantId string) SchoolDetailInfo {
|
||||
response, err := httpclient.Cpdaily.R().
|
||||
response, err := httpclient.Cpdaily.R().Clone(ctx).
|
||||
SetHeaders(map[string]string{
|
||||
"deviceType": "2",
|
||||
"CpdailyClientType": "CPDAILY",
|
||||
|
||||
@@ -10,14 +10,13 @@ import (
|
||||
"likedream-goframe/internal/utils"
|
||||
)
|
||||
|
||||
func GetCpdailyTaskService(ctx context.Context, Type string, cookie string, schoolId string) CpdailyTask {
|
||||
func GetCpdailyTaskService(ctx context.Context, Type cptask.TaskType, cookie string, schoolId string) CpdailyTask {
|
||||
detail := school.GetSchoolDetail(ctx, schoolId)
|
||||
cookieJar := cookiejar.NewPersistCookieJar()
|
||||
cookieJar.Deserialize(cookie)
|
||||
client := httpclient.Cpdaily.Clone(ctx)
|
||||
client.SetCookieJar(cookieJar)
|
||||
//todo 验证cookie是否有效
|
||||
switch cptask.TaskType(Type) {
|
||||
switch Type {
|
||||
case cptask.TaskTypeCollection:
|
||||
return NewCollectionTask(client, detail.WecloudUrl)
|
||||
case cptask.TaskTypeSign:
|
||||
|
||||
@@ -101,7 +101,14 @@ func (c *CpdailyCollectionTask) GetRecentTaskTitle(ctx context.Context) []string
|
||||
for title := range titleSet {
|
||||
titles = append(titles, title)
|
||||
}
|
||||
|
||||
if len(titles) == 0 {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, "没有查询到信息收集任务"), func(err error) error {
|
||||
return oops.
|
||||
With("host", c.host).
|
||||
In("CpdailyCollectionTask.Count").
|
||||
Wrap(err)
|
||||
})
|
||||
}
|
||||
return titles
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"context"
|
||||
"fmt"
|
||||
"likedream-goframe/internal/application/cpdaily"
|
||||
@@ -14,6 +13,7 @@ import (
|
||||
"likedream-goframe/internal/common/errors"
|
||||
"likedream-goframe/internal/utils"
|
||||
"math/rand/v2"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -111,7 +111,14 @@ func (c *CpdailyAutoSignTask) GetRecentTaskTitle(ctx context.Context) []string {
|
||||
for title := range titleSet {
|
||||
titles = append(titles, title)
|
||||
}
|
||||
|
||||
if len(titles) == 0 {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, "没有查询到签到任务"), func(err error) error {
|
||||
return oops.
|
||||
With("host", c.host).
|
||||
In("CpdailySignTask.Count").
|
||||
Wrap(err)
|
||||
})
|
||||
}
|
||||
return titles
|
||||
}
|
||||
|
||||
|
||||
@@ -172,6 +172,16 @@ func (c *CpdailySleepCheckTask) queryTitleByYearMonth(ctx context.Context, year,
|
||||
})
|
||||
}
|
||||
|
||||
if len(titles) == 0 {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, "没有查询到查寝任务"), func(err error) error {
|
||||
return oops.
|
||||
With("host", c.host).
|
||||
With("year", year).
|
||||
With("month", month).
|
||||
In("CpdailySleepCheckTask.Count").
|
||||
Wrap(err)
|
||||
})
|
||||
}
|
||||
return titles
|
||||
}
|
||||
|
||||
@@ -666,7 +676,7 @@ func (c *CpdailySleepCheckTask) Submit(ctx context.Context, form map[string]*gva
|
||||
sign := taskhelper.GetSubmitSign(submitData)
|
||||
|
||||
submitData["sign"] = gvar.New(sign)
|
||||
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, "临时拦截"), oops.WithContext(ctx).Wrap)
|
||||
response, e := c.client.R().
|
||||
SetBody(submitData).
|
||||
WithContext(ctx).
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package httpclient
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"likedream-goframe/internal/utils"
|
||||
"time"
|
||||
|
||||
"resty.dev/v3"
|
||||
@@ -9,5 +11,15 @@ import (
|
||||
var Cpdaily = resty.New().
|
||||
SetCookieJar(nil).
|
||||
SetTimeout(30 * time.Second).
|
||||
SetDoNotParseResponse(true).
|
||||
SetProxy("http://127.0.0.1:9000")
|
||||
SetDoNotParseResponse(true)
|
||||
|
||||
func init() {
|
||||
if !utils.IsDebug() {
|
||||
Cpdaily.SetDebug(false)
|
||||
} else {
|
||||
Cpdaily.SetProxy("http://127.0.0.1:9000").
|
||||
SetTLSClientConfig(&tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,57 +8,57 @@ import (
|
||||
"likedream-goframe/internal/utils"
|
||||
)
|
||||
|
||||
type CpTaskServiceV1 struct {
|
||||
type CpTaskCtrlV1 struct {
|
||||
}
|
||||
|
||||
func (c CpTaskServiceV1) List(ctx context.Context, req *v1.CpTaskListReq) (res *utils.Response[[]*ent.CpTask], err error) {
|
||||
func (c CpTaskCtrlV1) List(ctx context.Context, req *v1.CpTaskListReq) (res *utils.Response[[]*ent.CpTask], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTask.List(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpTaskServiceV1) GetRecentTasks(ctx context.Context, req *v1.GetRecentTasksReq) (res *utils.Response[[]string], err error) {
|
||||
func (c CpTaskCtrlV1) GetRecentTasks(ctx context.Context, req *v1.GetRecentTasksReq) (res *utils.Response[[]string], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTask.GetRecentTasks(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpTaskServiceV1) AddTask(ctx context.Context, req *v1.AddTaskReq) (res *utils.Response[any], err error) {
|
||||
func (c CpTaskCtrlV1) AddTask(ctx context.Context, req *v1.AddTaskReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTask.AddTask(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpTaskServiceV1) TaskFormData(ctx context.Context, req *v1.GetCpTaskFormReq) (res *utils.Response[any], err error) {
|
||||
func (c CpTaskCtrlV1) TaskFormData(ctx context.Context, req *v1.GetCpTaskFormReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTask.TaskFormData(ctx, req), nil
|
||||
}
|
||||
func (c CpTaskServiceV1) PutFormData(ctx context.Context, req *v1.PutCpTaskFormReq) (res *utils.Response[any], err error) {
|
||||
func (c CpTaskCtrlV1) PutFormData(ctx context.Context, req *v1.PutCpTaskFormReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTask.PutTaskFormData(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpTaskServiceV1) TaskExecute(ctx context.Context, req *v1.GetCpTaskExecuteReq) (res *utils.Response[any], err error) {
|
||||
func (c CpTaskCtrlV1) TaskExecute(ctx context.Context, req *v1.GetCpTaskExecuteReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTask.TaskExecute(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpTaskServiceV1) PostExecute(ctx context.Context, req *v1.PostCpTaskExecuteReq) (res *utils.Response[any], err error) {
|
||||
func (c CpTaskCtrlV1) PostExecute(ctx context.Context, req *v1.PostCpTaskExecuteReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTask.PostExecute(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpTaskServiceV1) Delete(ctx context.Context, req *v1.DeleteTaskReq) (res *utils.Response[any], err error) {
|
||||
func (c CpTaskCtrlV1) Delete(ctx context.Context, req *v1.DeleteTaskReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTask.Delete(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpTaskServiceV1) ExecuteNow(ctx context.Context, req *v1.ExecuteNowReq) (res *utils.Response[any], err error) {
|
||||
func (c CpTaskCtrlV1) ExecuteNow(ctx context.Context, req *v1.ExecuteNowReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTask.ExecuteNow(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpTaskServiceV1) PauseTask(ctx context.Context, req *v1.PauseTaskReq) (res *utils.Response[any], err error) {
|
||||
func (c CpTaskCtrlV1) PauseTask(ctx context.Context, req *v1.PauseTaskReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTask.PauseTask(ctx, req), nil
|
||||
}
|
||||
func NewCpTaskCtrlV1() ICpTaskCtrlV1 {
|
||||
return &CpTaskServiceV1{}
|
||||
return &CpTaskCtrlV1{}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package cpdaily
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
v1 "likedream-goframe/internal/api/v1"
|
||||
"likedream-goframe/internal/application/classifier"
|
||||
"likedream-goframe/internal/ent"
|
||||
"likedream-goframe/internal/service"
|
||||
"likedream-goframe/internal/utils"
|
||||
)
|
||||
|
||||
type CpTaskLogCtrlV1 struct {
|
||||
}
|
||||
|
||||
func (c CpTaskLogCtrlV1) OCR(ctx context.Context, req *v1.CpTaskOCRReq) (res *utils.Response[any], err error) {
|
||||
file, _ := req.File.Open()
|
||||
defer file.Close()
|
||||
bytes, _ := io.ReadAll(file)
|
||||
result := classifier.ClassifyImage(bytes, req.Name)
|
||||
return utils.SuccessWithData[any](result), nil
|
||||
}
|
||||
|
||||
func (c CpTaskLogCtrlV1) List(ctx context.Context, req *v1.CpTaskLogListReq) (res *utils.Response[[]*ent.CpTaskLog], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return service.Global.CpTaskLog.List(ctx, req), nil
|
||||
}
|
||||
|
||||
func NewCpTaskLogCtrlV1() ICpTaskLogCtrlV1 {
|
||||
return &CpTaskLogCtrlV1{}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package cpdaily
|
||||
|
||||
import (
|
||||
"context"
|
||||
v1 "likedream-goframe/internal/api/v1"
|
||||
"likedream-goframe/internal/ent"
|
||||
"likedream-goframe/internal/utils"
|
||||
)
|
||||
|
||||
type ICpTaskLogCtrlV1 interface {
|
||||
List(ctx context.Context, req *v1.CpTaskLogListReq) (res *utils.Response[[]*ent.CpTaskLog], err error)
|
||||
|
||||
OCR(ctx context.Context, req *v1.CpTaskOCRReq) (res *utils.Response[any], err error)
|
||||
}
|
||||
@@ -2,13 +2,9 @@ package cpdaily
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
v1 "likedream-goframe/internal/api/v1"
|
||||
"likedream-goframe/internal/application/filestorage"
|
||||
"likedream-goframe/internal/service"
|
||||
"likedream-goframe/internal/utils"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/samber/oops"
|
||||
)
|
||||
|
||||
type CpImageCtrlV1 struct {
|
||||
@@ -16,27 +12,12 @@ type CpImageCtrlV1 struct {
|
||||
|
||||
func (c CpImageCtrlV1) Upload(ctx context.Context, req *v1.UploadImageReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
file := req.File
|
||||
open, err := file.Open()
|
||||
utils.OkOrPanic(err, oops.WithContext(ctx).Wrap)
|
||||
key := utils.GenerateFileName("cpdaily/")
|
||||
size := filestorage.GlobalS3.UploadFile(ctx, key, open)
|
||||
return utils.SuccessWithData[any](v1.UploadImageRes{
|
||||
FileKey: key,
|
||||
FileSize: size,
|
||||
}), nil
|
||||
return service.Global.CpImage.Upload(ctx, req), nil
|
||||
}
|
||||
|
||||
func (c CpImageCtrlV1) Preview(ctx context.Context, req *v1.PreviewImageReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
key := req.Key
|
||||
file := filestorage.GlobalS3.GetFile(ctx, key)
|
||||
r := g.RequestFromCtx(ctx)
|
||||
r.Response.Header().Set("Content-Type", "image/png")
|
||||
// 将文件写入
|
||||
io.Copy(r.Response.Writer, file)
|
||||
r.Exit()
|
||||
return nil, nil
|
||||
return service.Global.CpImage.Preview(ctx, req), nil
|
||||
}
|
||||
|
||||
func NewCpImageCtrlV1() ICpImageCtrlV1 {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package cst
|
||||
|
||||
const (
|
||||
BasePointCpdaily = 1
|
||||
)
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"entgo.io/ent/dialect/sql/sqlgraph"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -75,6 +76,8 @@ var (
|
||||
DefaultCreateTime func() *ent2.CustomTime
|
||||
// DefaultUpdateTime holds the default value on creation for the "update_time" field.
|
||||
DefaultUpdateTime func() *ent2.CustomTime
|
||||
// DefaultImageID holds the default value on creation for the "image_id" field.
|
||||
DefaultImageID func() uuid.UUID
|
||||
// KeyValidator is a validator for the "key" field. It is called by the builders before save.
|
||||
KeyValidator func(string) error
|
||||
// UserIDValidator is a validator for the "user_id" field. It is called by the builders before save.
|
||||
|
||||
@@ -42,6 +42,14 @@ func (_c *CpImageCreate) SetImageID(v uuid.UUID) *CpImageCreate {
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetNillableImageID sets the "image_id" field if the given value is not nil.
|
||||
func (_c *CpImageCreate) SetNillableImageID(v *uuid.UUID) *CpImageCreate {
|
||||
if v != nil {
|
||||
_c.SetImageID(*v)
|
||||
}
|
||||
return _c
|
||||
}
|
||||
|
||||
// SetKey sets the "key" field.
|
||||
func (_c *CpImageCreate) SetKey(v string) *CpImageCreate {
|
||||
_c.mutation.SetKey(v)
|
||||
@@ -122,6 +130,13 @@ func (_c *CpImageCreate) defaults() error {
|
||||
v := cpimage.DefaultUpdateTime()
|
||||
_c.mutation.SetUpdateTime(v)
|
||||
}
|
||||
if _, ok := _c.mutation.ImageID(); !ok {
|
||||
if cpimage.DefaultImageID == nil {
|
||||
return fmt.Errorf("ent: uninitialized cpimage.DefaultImageID (forgotten import ent/runtime?)")
|
||||
}
|
||||
v := cpimage.DefaultImageID()
|
||||
_c.mutation.SetImageID(v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -30,7 +30,7 @@ var (
|
||||
Symbol: "cp_image_sys_user_images",
|
||||
Columns: []*schema.Column{CpImageColumns[7]},
|
||||
RefColumns: []*schema.Column{SysUserColumns[0]},
|
||||
OnDelete: schema.NoAction,
|
||||
OnDelete: schema.Cascade,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -104,13 +104,13 @@ var (
|
||||
Symbol: "cp_task_logs_cp_tasks_cp_task_logs",
|
||||
Columns: []*schema.Column{CpTaskLogsColumns[4]},
|
||||
RefColumns: []*schema.Column{CpTasksColumns[0]},
|
||||
OnDelete: schema.NoAction,
|
||||
OnDelete: schema.Cascade,
|
||||
},
|
||||
{
|
||||
Symbol: "cp_task_logs_cp_users_cp_task_logs",
|
||||
Columns: []*schema.Column{CpTaskLogsColumns[5]},
|
||||
RefColumns: []*schema.Column{CpUsersColumns[0]},
|
||||
OnDelete: schema.NoAction,
|
||||
OnDelete: schema.Cascade,
|
||||
},
|
||||
{
|
||||
Symbol: "cp_task_logs_sys_user_cp_task_logs",
|
||||
@@ -148,7 +148,7 @@ var (
|
||||
Symbol: "cp_users_sys_user_cpuser",
|
||||
Columns: []*schema.Column{CpUsersColumns[8]},
|
||||
RefColumns: []*schema.Column{SysUserColumns[0]},
|
||||
OnDelete: schema.NoAction,
|
||||
OnDelete: schema.Cascade,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"likedream-goframe/internal/ent/sysuser"
|
||||
"likedream-goframe/internal/framework/ent2"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
@@ -36,6 +37,10 @@ func init() {
|
||||
cpimageDescUpdateTime := cpimageMixinFields0[1].Descriptor()
|
||||
// cpimage.DefaultUpdateTime holds the default value on creation for the update_time field.
|
||||
cpimage.DefaultUpdateTime = cpimageDescUpdateTime.Default.(func() *ent2.CustomTime)
|
||||
// cpimageDescImageID is the schema descriptor for image_id field.
|
||||
cpimageDescImageID := cpimageFields[0].Descriptor()
|
||||
// cpimage.DefaultImageID holds the default value on creation for the image_id field.
|
||||
cpimage.DefaultImageID = cpimageDescImageID.Default.(func() uuid.UUID)
|
||||
// cpimageDescKey is the schema descriptor for key field.
|
||||
cpimageDescKey := cpimageFields[1].Descriptor()
|
||||
// cpimage.KeyValidator is a validator for the "key" field. It is called by the builders before save.
|
||||
|
||||
@@ -19,7 +19,7 @@ type CpImage struct {
|
||||
// Fields of the CpImage.
|
||||
func (CpImage) Fields() []ent.Field {
|
||||
return []ent.Field{
|
||||
field.UUID("image_id", uuid.New()).Unique().Immutable(),
|
||||
field.UUID("image_id", uuid.New()).Default(uuid.New).Unique().Immutable(),
|
||||
field.String("key").NotEmpty(),
|
||||
field.Int64("user_id").Positive(),
|
||||
field.String("content_type").NotEmpty(),
|
||||
|
||||
@@ -36,6 +36,6 @@ func (CpTask) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.From("cp_user", CpUser.Type).Ref("cptasks").Field("cp_user_id").Unique().Required().Annotations(entsql.OnDelete(entsql.Cascade)),
|
||||
edge.From("sys_user", SysUser.Type).Ref("cp_task").Field("user_id").Unique().Required().Annotations(entsql.OnDelete(entsql.Cascade)),
|
||||
edge.To("cp_task_logs", CpTaskLog.Type), // 任务拥有的cp任务日志
|
||||
edge.To("cp_task_logs", CpTaskLog.Type).Annotations(entsql.OnDelete(entsql.Cascade)), // 任务拥有的cp任务日志
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ func (CpUser) Fields() []ent.Field {
|
||||
func (CpUser) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.To("cptasks", CpTask.Type),
|
||||
edge.From("sysuser", SysUser.Type).Unique().Required().Field("user_id").Ref("cpuser").Annotations(entsql.OnDelete(entsql.Cascade)),
|
||||
edge.To("cp_task_logs", CpTaskLog.Type), // 用户拥有的cp任务日志
|
||||
edge.From("sysuser", SysUser.Type).Unique().Required().Field("user_id").Ref("cpuser"),
|
||||
edge.To("cp_task_logs", CpTaskLog.Type).Annotations(entsql.OnDelete(entsql.Cascade)), // 用户拥有的cp任务日志
|
||||
edge.From("school", CpSchool.Type).
|
||||
Ref("cpusers").
|
||||
Field("school_id").
|
||||
|
||||
@@ -31,7 +31,7 @@ func (SysAgent) Fields() []ent.Field {
|
||||
// Edges of the SysAgent.
|
||||
func (SysAgent) Edges() []ent.Edge {
|
||||
return []ent.Edge{
|
||||
edge.From("users", SysUser.Type).Ref("agent").Unique(),
|
||||
edge.From("users", SysUser.Type).Ref("agent").Unique().Annotations(entsql.OnDelete(entsql.Cascade)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,10 +46,10 @@ func (SysUser) Edges() []ent.Edge {
|
||||
edge.To("children", SysUser.Type).
|
||||
From("parent").
|
||||
Unique(),
|
||||
edge.To("roles", SysRole.Type), // 用户拥有角色
|
||||
edge.To("agent", SysAgent.Type).Unique(), // 用户拥有代理
|
||||
edge.To("images", CpImage.Type), // 用户拥有的图片
|
||||
edge.To("cpuser", CpUser.Type), // 用户拥有的cp用户
|
||||
edge.To("roles", SysRole.Type), // 用户拥有角色
|
||||
edge.To("agent", SysAgent.Type).Unique(), // 用户拥有代理
|
||||
edge.To("images", CpImage.Type).Annotations(entsql.OnDelete(entsql.Cascade)), // 用户拥有的图片
|
||||
edge.To("cpuser", CpUser.Type).Annotations(entsql.OnDelete(entsql.Cascade)), // 用户拥有的cp用户
|
||||
edge.To("cp_task", CpTask.Type),
|
||||
edge.To("cp_task_logs", CpTaskLog.Type), // 用户拥有的cp任务日志
|
||||
edge.To("created_cards", SysCard.Type), // 用户创建的卡
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"likedream-goframe/internal/cst"
|
||||
"likedream-goframe/internal/utils"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/redis/go-redis/v9"
|
||||
@@ -25,6 +26,9 @@ func Init(ctx context.Context) {
|
||||
redisUrl := g.Cfg().MustGetWithEnv(ctx, cst.ConfigRedisUrl).String()
|
||||
|
||||
redisOpts, e := redis.ParseURL(redisUrl)
|
||||
redisOpts.DialTimeout = 30 * time.Second
|
||||
redisOpts.ReadTimeout = 30 * time.Second
|
||||
redisOpts.WriteTimeout = 30 * time.Second
|
||||
utils.OkOrPanic(e, oops.WithContext(ctx).
|
||||
With("redisUrl", redisUrl).
|
||||
Wrap)
|
||||
|
||||
@@ -6,13 +6,12 @@ import (
|
||||
"encoding/gob"
|
||||
"likedream-goframe/internal/application/cpdaily/login"
|
||||
"likedream-goframe/internal/application/cpdaily/school"
|
||||
cpdailyTask "likedream-goframe/internal/application/cpdaily/task"
|
||||
task2 "likedream-goframe/internal/application/cpdaily/task"
|
||||
"likedream-goframe/internal/application/cpdaily/task/formtype"
|
||||
"likedream-goframe/internal/db"
|
||||
"likedream-goframe/internal/ent"
|
||||
"likedream-goframe/internal/ent/cptask"
|
||||
"likedream-goframe/internal/ent/cpuser"
|
||||
"likedream-goframe/internal/ent/sysuser"
|
||||
"likedream-goframe/internal/framework/errors"
|
||||
"likedream-goframe/internal/framework/model/email"
|
||||
email2 "likedream-goframe/internal/service/email"
|
||||
@@ -40,12 +39,9 @@ func (c *CpdailyTaskHandler) ProcessTask(ctx context.Context, task *asynq.Task)
|
||||
|
||||
// 查询指定的任务和关联今日校园用户
|
||||
targetTask, e := db.Global.CpTask.Query().Where(cptask.ID(taskPayload.CpTaskID)).
|
||||
WithCpUser(func(cuq *ent.CpUserQuery) {
|
||||
cuq.Select(cpuser.FieldSchoolID, cpuser.FieldEmail).
|
||||
WithSysuser(func(suq *ent.SysUserQuery) {
|
||||
suq.Select(sysuser.FieldID, sysuser.FieldEmail)
|
||||
})
|
||||
}).First(ctx)
|
||||
WithCpUser().
|
||||
WithSysUser().
|
||||
First(ctx)
|
||||
if ent.IsNotFound(e) {
|
||||
utils.OkOrPanic(oops.WithContext(ctx).With("task_id", taskPayload.CpTaskID).In("CpdailyTask.ProcessTask").Wrap(e))
|
||||
}
|
||||
@@ -89,33 +85,16 @@ func (c *CpdailyTaskHandler) ProcessTask(ctx context.Context, task *asynq.Task)
|
||||
|
||||
// 查询学校详情
|
||||
schoolDetail := school.GetSchoolDetail(ctx, targetTask.Edges.CpUser.SchoolID)
|
||||
|
||||
// 执行登录
|
||||
var loginClient login.CpdailyLogin
|
||||
|
||||
if schoolDetail.IsIap() {
|
||||
loginClient = login.NewIap(ctx)
|
||||
} else {
|
||||
loginClient = login.NewCas(ctx)
|
||||
restyClient := login.GetClient(ctx, targetTask.Edges.CpUser.Cookie)
|
||||
if !login.CookieEnabled(ctx, schoolDetail.WecloudUrl, restyClient) {
|
||||
loginExecutor := login.GetCpdailyLoginBySchoolInfo(ctx, &schoolDetail)
|
||||
loginExecutor.Login(ctx, &schoolDetail, targetTask.Edges.CpUser.Username, targetTask.Edges.CpUser.Password)
|
||||
cookie := loginExecutor.GetCookieString()
|
||||
db.Global.CpUser.UpdateOne(targetTask.Edges.CpUser).SetCookie(cookie).ExecX(ctx)
|
||||
restyClient = login.GetClient(ctx, cookie)
|
||||
}
|
||||
|
||||
loginClient.Login(ctx, &schoolDetail, targetTask.Edges.CpUser.Username, targetTask.Edges.CpUser.Username)
|
||||
|
||||
restyClient := loginClient.GetClient()
|
||||
|
||||
// 获取任务执行handler
|
||||
var taskExecutor cpdailyTask.CpdailyTask
|
||||
|
||||
switch targetTask.TaskType {
|
||||
case cptask.TaskTypeCollection:
|
||||
taskExecutor = cpdailyTask.NewCollectionTask(restyClient, schoolDetail.WecloudUrl)
|
||||
case cptask.TaskTypeSign:
|
||||
taskExecutor = cpdailyTask.NewAutoSignTask(restyClient, schoolDetail.WecloudUrl)
|
||||
case cptask.TaskTypeSleepCheck:
|
||||
taskExecutor = cpdailyTask.NewSleepCheckTask(restyClient, schoolDetail.WecloudUrl)
|
||||
default:
|
||||
utils.OkOrPanic(oops.WithContext(ctx).With("task_id", taskPayload.CpTaskID).In("CpdailyTask.ProcessTask").Errorf("unknown task type: %s", targetTask.TaskType))
|
||||
}
|
||||
taskExecutor := task2.GetCpdailyTaskService(ctx, targetTask.TaskType, targetTask.Edges.CpUser.Cookie, targetTask.Edges.CpUser.SchoolID)
|
||||
|
||||
cpdailyRealTask := taskExecutor.QueryFormByTitle(ctx, targetTask.Title)
|
||||
|
||||
@@ -148,7 +127,7 @@ func (c *CpdailyTaskHandler) ProcessTask(ctx context.Context, task *asynq.Task)
|
||||
}
|
||||
|
||||
submitForm := taskExecutor.FillCustomForm(ctx, cpdailyRealTask, customFormItems, deviceID, targetTask.Edges.CpUser.Username)
|
||||
|
||||
utils.OkOrPanic(errors.NewBusinessError(400, "临时错误"))
|
||||
taskExecutor.Submit(ctx, submitForm, targetTask.Edges.CpUser.Username, deviceID)
|
||||
|
||||
db.Global.CpTask.UpdateOneID(taskPayload.CpTaskID).SetTaskStatus(cptask.TaskStatusDone).AddSuccessCount(1).ExecX(ctx)
|
||||
|
||||
@@ -88,8 +88,8 @@ func (ts *TaskScanner) scanCpdailyTask() {
|
||||
minExecuteTime := currentTime.Add(-30 * time.Minute).Unix()
|
||||
|
||||
allTasks := db.Global.CpTask.Query().
|
||||
Where(cptask.NextExecuteTimeLTE(currentTime.Unix()), cptask.NextExecuteTimeNotNil(), cptask.NextExecuteTimeGT(0)).
|
||||
Select(cptask.FieldID, cptask.FieldExecuteHour, cptask.FieldExecuteMinute).
|
||||
Where(cptask.NextExecuteTimeLTE(currentTime.Unix()), cptask.NextExecuteTimeNotNil(), cptask.NextExecuteTimeGT(0), cptask.StepEQ(cptask.StepComplete), cptask.TaskStatusEQ(cptask.TaskStatusNotStart)).
|
||||
Select(cptask.FieldID, cptask.FieldExecuteHour, cptask.FieldExecuteMinute, cptask.FieldNextExecuteTime).
|
||||
AllX(ts.ctx)
|
||||
|
||||
var failedIDS []int64
|
||||
@@ -117,7 +117,7 @@ func (ts *TaskScanner) scanCpdailyTask() {
|
||||
e = utils.Catch(func() {
|
||||
queue.AddTask(ts.ctx, asynq.NewTask(cst.TaskCpdaily, payloadWriter.Bytes()),
|
||||
asynq.TaskID(fmt.Sprintf("cpdaily:task:%d", task.ID)),
|
||||
asynq.MaxRetry(5),
|
||||
asynq.MaxRetry(3),
|
||||
asynq.Unique(10*time.Minute),
|
||||
asynq.ProcessAt(execTime),
|
||||
asynq.Deadline(execTime.Add(12*time.Minute)),
|
||||
@@ -151,7 +151,7 @@ func (ts *TaskScanner) scanCpdailyTask() {
|
||||
|
||||
// 重置30分钟之前的任务到下次执行时间
|
||||
expiredTasks := db.Global.CpTask.Query().
|
||||
Where(cptask.NextExecuteTimeLT(minExecuteTime), cptask.NextExecuteTimeNotNil()).
|
||||
Where(cptask.NextExecuteTimeLT(minExecuteTime), cptask.NextExecuteTimeNotNil(), cptask.NextExecuteTimeGT(0)).
|
||||
Select(cptask.FieldID, cptask.FieldExecuteHour, cptask.FieldExecuteMinute).
|
||||
AllX(ts.ctx)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/util/gvalid"
|
||||
)
|
||||
|
||||
func ExceptionHandler(r *ghttp.Request) {
|
||||
@@ -50,6 +51,15 @@ func ExceptionHandler(r *ghttp.Request) {
|
||||
code = tmpErr.Code()
|
||||
} else if code == gcode.CodeNil {
|
||||
code = errors.CodeInternal.Code()
|
||||
} else if code == gcode.CodeValidationFailed {
|
||||
// 请求参数校验失败返回第一个错误信息
|
||||
if validationErr, ok := err.(gvalid.Error); ok {
|
||||
if firstErr := validationErr.FirstError(); firstErr != nil {
|
||||
c := errors.CodeParam
|
||||
c.SetMessage(firstErr.Error())
|
||||
code = c.Code()
|
||||
}
|
||||
}
|
||||
}
|
||||
r.Response.ClearBuffer()
|
||||
r.Response.WriteHeader(200)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"likedream-goframe/internal/ent"
|
||||
"likedream-goframe/internal/ent/sysrole"
|
||||
"likedream-goframe/internal/ent/sysuser"
|
||||
"likedream-goframe/internal/service/balance"
|
||||
"likedream-goframe/internal/utils"
|
||||
|
||||
"github.com/samber/oops"
|
||||
@@ -22,7 +23,9 @@ func NewV1() *AgentServiceV1 {
|
||||
|
||||
func (s *AgentServiceV1) List(ctx context.Context, req *v1.AgentListReq) *utils.Response[[]v1.AgentListRes] {
|
||||
query := db.Global.SysUser.Query()
|
||||
query.Where(sysuser.HasParentWith(sysuser.IDEQ(utils.GetUserInfoFromCtx(ctx).ID)))
|
||||
if !utils.IsAdminFromCtx(ctx) {
|
||||
query.Where(sysuser.HasParentWith(sysuser.IDEQ(utils.GetUserInfoFromCtx(ctx).ID)))
|
||||
}
|
||||
if req.Email != "" {
|
||||
query.Where(sysuser.EmailContains(req.Email))
|
||||
}
|
||||
@@ -109,13 +112,15 @@ func (s *AgentServiceV1) Add(ctx context.Context, req *v1.AgentAddReq) *utils.Re
|
||||
}
|
||||
|
||||
func (s *AgentServiceV1) Ban(ctx context.Context, req *v1.AgentBanReq) *utils.Response[any] {
|
||||
// 参数校验
|
||||
currentUser := utils.GetUserInfoFromCtx(ctx)
|
||||
user := db.Global.SysUser.Query().Where(sysuser.IDEQ(req.ID)).OnlyX(ctx)
|
||||
// 判断是否是自己的下级代理
|
||||
parent := user.QueryParent().OnlyX(ctx)
|
||||
if parent.ID != currentUser.ID {
|
||||
return utils.FailParam("非法的下级代理参数")
|
||||
if !utils.IsAdminFromCtx(ctx) {
|
||||
// 参数校验
|
||||
currentUser := utils.GetUserInfoFromCtx(ctx)
|
||||
// 判断是否是自己的下级代理
|
||||
parent := user.QueryParent().OnlyX(ctx)
|
||||
if parent.ID != currentUser.ID {
|
||||
return utils.FailParam("非法的下级代理参数")
|
||||
}
|
||||
}
|
||||
db.Global.SysUser.UpdateOne(user).SetBlock(req.Block).ExecX(ctx)
|
||||
return utils.SuccessWithMsg("操作成功")
|
||||
@@ -123,41 +128,20 @@ func (s *AgentServiceV1) Ban(ctx context.Context, req *v1.AgentBanReq) *utils.Re
|
||||
|
||||
func (s *AgentServiceV1) Recharge(ctx context.Context, req *v1.AgentRechargeReq) *utils.Response[any] {
|
||||
// 参数校验
|
||||
currentUser := db.Global.SysUser.Query().Where(sysuser.ID(utils.GetUserInfoFromCtx(ctx).ID)).WithAgent().WithRoles().OnlyX(ctx)
|
||||
user := db.Global.SysUser.Query().Where(sysuser.IDEQ(req.ID)).WithAgent().OnlyX(ctx)
|
||||
// 判断是否是自己的下级代理
|
||||
parent := user.QueryParent().WithAgent().FirstX(ctx)
|
||||
if parent == nil || parent.ID != currentUser.ID {
|
||||
return utils.FailParam("非法的下级代理参数")
|
||||
}
|
||||
tx, err := db.Global.Tx(ctx)
|
||||
utils.OkOrPanic(err, func(err error) error {
|
||||
return oops.
|
||||
WithContext(ctx).
|
||||
With("创建事务失败").
|
||||
Wrap(err)
|
||||
})
|
||||
if !utils.HasRole(currentUser.Edges.Roles, cst.KeyRoleAdmin) {
|
||||
parent.Balance = utils.CalculateBalance(parent.Balance, parent.Edges.Agent.Rate, req.Amount, user.Edges.Agent.Rate)
|
||||
if parent.Balance.Compare(decimal.NewFromInt(0)) < 0 {
|
||||
return utils.FailParam("余额不足")
|
||||
if !utils.IsAdminFromCtx(ctx) {
|
||||
currentUser := db.Global.SysUser.Query().Where(sysuser.ID(utils.GetUserInfoFromCtx(ctx).ID)).WithAgent().WithRoles().OnlyX(ctx)
|
||||
// 判断是否是自己的下级代理
|
||||
parent := user.QueryParent().WithAgent().FirstX(ctx)
|
||||
if parent == nil || parent.ID != currentUser.ID {
|
||||
return utils.FailParam("非法的下级代理参数")
|
||||
}
|
||||
if !utils.HasRole(currentUser.Edges.Roles, cst.KeyRoleAdmin) {
|
||||
needBalance := utils.CalculateBalance(parent.Balance, parent.Edges.Agent.Rate, req.Amount, user.Edges.Agent.Rate)
|
||||
balance.BalanceService.ChangeUserBalance(ctx, parent.ID, needBalance.Neg())
|
||||
}
|
||||
}
|
||||
tx.SysUser.UpdateOne(parent).SetBalance(parent.Balance).SaveX(ctx)
|
||||
utils.OkOrPanic(err, func(err error) error {
|
||||
return oops.
|
||||
WithContext(ctx).
|
||||
With("更新用户余额失败").
|
||||
Wrap(err)
|
||||
})
|
||||
tx.SysUser.UpdateOne(user).SetBalance(user.Balance.Add(req.Amount)).SaveX(ctx)
|
||||
utils.OkOrPanic(err, func(err error) error {
|
||||
return oops.
|
||||
WithContext(ctx).
|
||||
With("更新用户余额失败").
|
||||
Wrap(err)
|
||||
})
|
||||
err = tx.Commit()
|
||||
balance.BalanceService.ChangeUserBalance(ctx, user.ID, req.Amount)
|
||||
return utils.SuccessWithMsg("操作成功")
|
||||
}
|
||||
|
||||
@@ -170,18 +154,21 @@ func (s *AgentServiceV1) AgentPutInfoReq(ctx context.Context, req *v1.AgentPutIn
|
||||
With("创建事务失败").
|
||||
Wrap(err)
|
||||
})
|
||||
currentUser := tx.SysUser.Query().Where(sysuser.ID(utils.GetUserInfoFromCtx(ctx).ID)).WithAgent().WithRoles().OnlyX(ctx)
|
||||
defer tx.Rollback()
|
||||
user := tx.SysUser.Query().Where(sysuser.ID(req.ID)).WithParent().WithAgent().FirstX(ctx)
|
||||
if user.Edges.Parent == nil || user.Edges.Parent.ID != currentUser.ID {
|
||||
return utils.FailParam("非法的下级代理参数")
|
||||
}
|
||||
// 2. 如果没有代理权限
|
||||
if !utils.HasRole(currentUser.Edges.Roles, cst.KeyRoleAdmin) && !utils.HasRole(currentUser.Edges.Roles, cst.KeyRoleAgent) {
|
||||
return utils.FailParam("代理权限不足")
|
||||
}
|
||||
// 3. 检测代理费率或level是否低于自己
|
||||
if currentUser.Edges.Agent != nil && (req.Level > currentUser.Edges.Agent.Level || req.Rate.LessThan(currentUser.Edges.Agent.Rate)) {
|
||||
return utils.FailParam("代理等级或费率低于自己")
|
||||
if !utils.IsAdminFromCtx(ctx) {
|
||||
currentUser := tx.SysUser.Query().Where(sysuser.ID(utils.GetUserInfoFromCtx(ctx).ID)).WithAgent().WithRoles().OnlyX(ctx)
|
||||
if user.Edges.Parent == nil || user.Edges.Parent.ID != currentUser.ID {
|
||||
return utils.FailParam("非法的下级代理参数")
|
||||
}
|
||||
// 2. 如果没有代理权限
|
||||
if !utils.HasRole(currentUser.Edges.Roles, cst.KeyRoleAdmin) && !utils.HasRole(currentUser.Edges.Roles, cst.KeyRoleAgent) {
|
||||
return utils.FailParam("代理权限不足")
|
||||
}
|
||||
// 3. 检测代理费率或level是否低于自己
|
||||
if currentUser.Edges.Agent != nil && (req.Level > currentUser.Edges.Agent.Level || req.Rate.LessThan(currentUser.Edges.Agent.Rate)) {
|
||||
return utils.FailParam("代理等级或费率低于自己")
|
||||
}
|
||||
}
|
||||
// 5. 检测是否存在代理信息,
|
||||
// 将用户余额先计算为比例为1的用户余额
|
||||
@@ -201,7 +188,7 @@ func (s *AgentServiceV1) AgentPutInfoReq(ctx context.Context, req *v1.AgentPutIn
|
||||
//按照新费率计算余额
|
||||
newBalance := utils.TransformBalance(oldBalance, req.Rate)
|
||||
// 6. 更新用户余额
|
||||
tx.SysUser.UpdateOne(user).SetBalance(newBalance).SaveX(ctx)
|
||||
balance.BalanceService.ChangeUserBalance(ctx, user.ID, newBalance.Sub(oldBalance))
|
||||
err = tx.Commit()
|
||||
utils.OkOrPanic(err, func(err error) error {
|
||||
return oops.
|
||||
|
||||
@@ -6,24 +6,27 @@ import (
|
||||
"likedream-goframe/internal/db"
|
||||
"likedream-goframe/internal/ent/sysuser"
|
||||
"likedream-goframe/internal/utils"
|
||||
"sync"
|
||||
|
||||
"github.com/samber/oops"
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
var BalanceService = &BalanceServiceV1{}
|
||||
var BalanceService = &BalanceServiceV1{
|
||||
lock: sync.Mutex{},
|
||||
}
|
||||
|
||||
type BalanceServiceV1 struct {
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
func (v *BalanceServiceV1) ChangeUserBalance(ctx context.Context, userId int64, balance decimal.Decimal) {
|
||||
if utils.IsAdminFromCtx(ctx) {
|
||||
return
|
||||
}
|
||||
v.lock.Lock()
|
||||
defer v.lock.Unlock()
|
||||
tx, err := db.Global.Tx(ctx)
|
||||
utils.OkOrPanic(err, oops.WithContext(ctx).Wrap)
|
||||
defer tx.Rollback()
|
||||
user := tx.SysUser.Query().Where(sysuser.ID(userId)).WithRoles().ForUpdate().OnlyX(ctx)
|
||||
user := tx.SysUser.Query().Where(sysuser.ID(userId)).WithRoles().OnlyX(ctx)
|
||||
newBalance := user.Balance.Add(balance)
|
||||
if newBalance.LessThan(decimal.Zero) {
|
||||
utils.OkOrPanic(errors.NewBusinessError(400, "余额不足"))
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package cpdaily
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
v1 "likedream-goframe/internal/api/v1"
|
||||
"likedream-goframe/internal/application/filestorage"
|
||||
"likedream-goframe/internal/db"
|
||||
"likedream-goframe/internal/ent/cpimage"
|
||||
"likedream-goframe/internal/utils"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/google/uuid"
|
||||
"github.com/samber/oops"
|
||||
)
|
||||
|
||||
type CpImageServiceV1 struct {
|
||||
}
|
||||
|
||||
func (v CpImageServiceV1) Upload(ctx context.Context, req *v1.UploadImageReq) *utils.Response[any] {
|
||||
user := utils.GetUserInfoFromCtx(ctx)
|
||||
file := req.File
|
||||
open, err := file.Open()
|
||||
utils.OkOrPanic(err, oops.WithContext(ctx).Wrap)
|
||||
key := utils.GenerateFileName("cpdaily/")
|
||||
filestorage.GlobalS3.UploadFile(ctx, key, open)
|
||||
img := db.Global.CpImage.Create().
|
||||
SetUserID(user.ID).
|
||||
SetKey(key).
|
||||
SetContentType(file.Header.Get("Content-Type")).
|
||||
SetContentLength(file.Size).
|
||||
SaveX(ctx)
|
||||
return utils.SuccessWithData[any](v1.UploadImageRes{
|
||||
FileKey: img.ImageID.String(),
|
||||
FileSize: &file.Size,
|
||||
})
|
||||
}
|
||||
|
||||
func (v CpImageServiceV1) Preview(ctx context.Context, req *v1.PreviewImageReq) *utils.Response[any] {
|
||||
id, err := uuid.Parse(req.Key)
|
||||
utils.OkOrPanic(err, oops.WithContext(ctx).Wrap)
|
||||
cpImage := db.Global.CpImage.Query().Where(cpimage.ImageID(id)).OnlyX(ctx)
|
||||
file := filestorage.GlobalS3.GetFile(ctx, cpImage.Key)
|
||||
r := g.RequestFromCtx(ctx)
|
||||
r.Response.Header().Set("Content-Type", "image/png")
|
||||
// 将文件写入
|
||||
io.Copy(r.Response.Writer, file)
|
||||
r.Exit()
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewCpImageServiceV1() *CpImageServiceV1 {
|
||||
return &CpImageServiceV1{}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"likedream-goframe/internal/ent/sysuser"
|
||||
"likedream-goframe/internal/framework/queue"
|
||||
"likedream-goframe/internal/framework/schedule"
|
||||
"likedream-goframe/internal/service/balance"
|
||||
"likedream-goframe/internal/utils"
|
||||
"time"
|
||||
|
||||
@@ -28,6 +29,7 @@ import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/samber/oops"
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type CpTaskServiceV1 struct {
|
||||
@@ -123,7 +125,7 @@ func (v CpTaskServiceV1) TaskFormData(ctx context.Context, req *v1.GetCpTaskForm
|
||||
db.Global.CpUser.UpdateOne(cpUser).SetCookie(cpUser.Cookie).ExecX(ctx)
|
||||
client = login.GetClient(ctx, cpUser.Cookie)
|
||||
}
|
||||
taskService := task.GetCpdailyTaskService(ctx, string(cpTask.TaskType), cpUser.Cookie, cpUser.SchoolID)
|
||||
taskService := task.GetCpdailyTaskService(ctx, cpTask.TaskType, cpUser.Cookie, cpUser.SchoolID)
|
||||
formMap := taskService.QueryFormByTitle(ctx, cpTask.Title)
|
||||
formDetail := taskService.ParseFormJson(ctx, formMap)
|
||||
return utils.SuccessWithData[any](formDetail)
|
||||
@@ -172,11 +174,18 @@ func (v CpTaskServiceV1) PostExecute(ctx context.Context, req *v1.PostCpTaskExec
|
||||
if cpTask.Step == cptask.StepForm {
|
||||
utils.OkOrPanic(errors2.NewBusinessError(400, "请先完成前置参数设置"))
|
||||
}
|
||||
pointConsume := req.Frequency - cpTask.Frequency
|
||||
if req.Frequency < 1 || pointConsume < 0 {
|
||||
consume := req.Frequency - cpTask.Frequency
|
||||
if req.Frequency < 1 || consume < 0 {
|
||||
utils.OkOrPanic(errors2.NewBusinessError(400, "执行次数应不低于原有次数"))
|
||||
}
|
||||
//todo 扣积分
|
||||
//扣积分
|
||||
basePoint := decimal.NewFromInt(cst.BasePointCpdaily)
|
||||
if user.Edges.Agent != nil {
|
||||
basePoint = basePoint.Mul(user.Edges.Agent.Rate)
|
||||
}
|
||||
needPoint := basePoint.Mul(decimal.NewFromInt(int64(consume)))
|
||||
balance.BalanceService.ChangeUserBalance(ctx, user.ID, needPoint.Neg())
|
||||
// 更新任务
|
||||
e := db.WithTx(ctx, func(ctx context.Context, tx *ent.Tx) {
|
||||
cpTask := db.Global.CpTask.UpdateOne(cpTask).
|
||||
SetStep(cptask.StepComplete).
|
||||
@@ -243,7 +252,7 @@ func (v CpTaskServiceV1) ExecuteNow(ctx context.Context, req *v1.ExecuteNowReq)
|
||||
utils.OkOrPanic(errors2.NewBusinessError(400, "任务已经在执行中"))
|
||||
} else {
|
||||
g.Log().Errorf(ctx, "立即执行任务入列失败: %+v", e)
|
||||
utils.OkOrPanic(errors2.NewBusinessError(500, "任务执行失败"))
|
||||
utils.OkOrPanic(errors2.NewBusinessError(500, "任务队列中已存在此任务,立即执行任务入列失败"))
|
||||
}
|
||||
}
|
||||
return utils.SuccessWithMsg("执行成功")
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package cpdaily
|
||||
|
||||
import (
|
||||
"context"
|
||||
v1 "likedream-goframe/internal/api/v1"
|
||||
"likedream-goframe/internal/db"
|
||||
"likedream-goframe/internal/ent"
|
||||
"likedream-goframe/internal/ent/cptasklog"
|
||||
"likedream-goframe/internal/ent/sysuser"
|
||||
"likedream-goframe/internal/utils"
|
||||
)
|
||||
|
||||
type CpTaskLogServiceV1 struct {
|
||||
}
|
||||
|
||||
func (v CpTaskLogServiceV1) List(ctx context.Context, req *v1.CpTaskLogListReq) *utils.Response[[]*ent.CpTaskLog] {
|
||||
user := utils.GetUserInfoFromCtx(ctx)
|
||||
query := db.Global.CpTaskLog.Query().Where(
|
||||
cptasklog.HasSystemUserWith(sysuser.ID(user.ID)),
|
||||
cptasklog.CpTaskID(req.TaskID))
|
||||
total := query.CountX(ctx)
|
||||
var data []*ent.CpTaskLog
|
||||
if total > 0 {
|
||||
query.Limit(req.Size).Offset((req.Page - 1) * req.Size)
|
||||
data = query.AllX(ctx)
|
||||
}
|
||||
return utils.SuccessWithTotal(data, total)
|
||||
}
|
||||
|
||||
func NewCpTaskLogServiceV1() *CpTaskLogServiceV1 {
|
||||
return &CpTaskLogServiceV1{}
|
||||
}
|
||||
@@ -21,6 +21,8 @@ type globalService struct {
|
||||
User *user.UserServiceV1
|
||||
CpUser *cpdaily.CpUserServiceV1
|
||||
CpTask *cpdaily.CpTaskServiceV1
|
||||
CpImage *cpdaily.CpImageServiceV1
|
||||
CpTaskLog *cpdaily.CpTaskLogServiceV1
|
||||
Card *card.CardServiceV1
|
||||
}
|
||||
|
||||
@@ -34,5 +36,7 @@ var Global = globalService{
|
||||
User: user.NewV1(),
|
||||
CpUser: cpdaily.NewCpUserServiceV1(),
|
||||
CpTask: cpdaily.NewCpTaskServiceV1(),
|
||||
CpImage: cpdaily.NewCpImageServiceV1(),
|
||||
CpTaskLog: cpdaily.NewCpTaskLogServiceV1(),
|
||||
Card: card.NewCardServiceV1(),
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ func Pass(err *error) {
|
||||
if r := recover(); r != nil {
|
||||
e, ok := errorx.ErrorFromPanic(r)
|
||||
if ok {
|
||||
*err = e
|
||||
*err = oops.Wrap(e)
|
||||
} else {
|
||||
panic(r)
|
||||
}
|
||||
@@ -61,7 +61,7 @@ func HandleError(f func(error)) {
|
||||
if r := recover(); r != nil {
|
||||
e, ok := errorx.ErrorFromPanic(r)
|
||||
if ok {
|
||||
f(e)
|
||||
f(oops.Wrap(e))
|
||||
} else {
|
||||
panic(r)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
)
|
||||
|
||||
func IsDebug() bool {
|
||||
return isGolandDebug() || isDebugByPath()
|
||||
|
||||
}
|
||||
|
||||
func isDebugByPath() bool {
|
||||
exePath := strings.ToLower(os.Args[0])
|
||||
// 获取绝对路径
|
||||
absPath, err := filepath.Abs(exePath)
|
||||
if err != nil {
|
||||
absPath = exePath
|
||||
}
|
||||
|
||||
// 检查路径中是否包含常见的临时目录或"go-build"字样
|
||||
tmpDir := strings.ToLower(getTempDir())
|
||||
isTemp := strings.Contains(absPath, tmpDir) || strings.Contains(absPath, "go-build") || strings.Contains(absPath, "go_build_")
|
||||
return isTemp
|
||||
}
|
||||
func getTempDir() string {
|
||||
tempDir := os.TempDir()
|
||||
|
||||
// 尝试转换为长路径
|
||||
if longPath, err := filepath.EvalSymlinks(tempDir); err == nil {
|
||||
if absPath, err := filepath.Abs(longPath); err == nil {
|
||||
return absPath
|
||||
}
|
||||
return longPath
|
||||
}
|
||||
|
||||
return filepath.Dir(tempDir)
|
||||
}
|
||||
|
||||
func isGolandDebug() bool {
|
||||
// 获取当前进程ID
|
||||
pid := os.Getpid()
|
||||
|
||||
// 获取当前进程信息
|
||||
currentProcess, err := process.NewProcess(int32(pid))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 获取父进程
|
||||
parent, err := currentProcess.Parent()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 获取父进程名称
|
||||
name, err := parent.Name()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查父进程是否是dlv(Go调试器)或GoLand相关进程
|
||||
name = strings.ToLower(name)
|
||||
debugProcessNames := []string{
|
||||
"dlv.exe", "dlv",
|
||||
"goland.exe", "goland64.exe",
|
||||
"goland", "idea.exe",
|
||||
}
|
||||
|
||||
for _, debugName := range debugProcessNames {
|
||||
if strings.Contains(name, debugName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
@@ -1,13 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "go.uber.org/automaxprocs"
|
||||
"likedream-goframe/cmd/entc"
|
||||
"likedream-goframe/cmd/server"
|
||||
"likedream-goframe/internal/cst"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "time/tzdata"
|
||||
|
||||
_ "github.com/breml/rootcerts"
|
||||
|
||||
_ "go.uber.org/automaxprocs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// fix: time: unknown time zone Asia/Shanghai
|
||||
var err error
|
||||
cst.TimeZoneShangHai, err = time.LoadLocation("Asia/Shanghai")
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
args := ""
|
||||
if len(os.Args) > 1 {
|
||||
args = os.Args[1]
|
||||
|
||||
Reference in New Issue
Block a user