Compare commits

..

39 Commits

Author SHA1 Message Date
sugarBecomer 0d7d4c11a0 🐛 Login need kick 2025-11-07 12:11:50 +08:00
sugarBecomer e4d07874eb 🐛 任务执行bug和日志 2025-11-07 01:14:10 +08:00
sugarBecomer ae9984460f 🐛 取消临时err 2025-11-07 00:25:31 +08:00
sugarBecomer e38a1a4480 🐛 取消临时err 2025-11-07 00:14:41 +08:00
sugarBecomer b112f45264 🐛 onnx运行路径问题 2025-11-06 23:50:10 +08:00
sugarBecomer 6fad80b5cd 🐛 onnx运行路径问题 2025-11-06 22:39:02 +08:00
sugarBecomer 1d0e1812c8 🐛 onnx运行路径问题 2025-11-06 22:25:58 +08:00
RecordingTheSmile 40490ffe43 fix: update Dockerfile to install packages non-interactively 2025-11-06 21:31:02 +08:00
RecordingTheSmile 455b6d40de fix: update Dockerfile to include apt update before installing build-essential 2025-11-06 21:28:01 +08:00
RecordingTheSmile 62dcac103f fix: Docker构建统一使用debian镜像 2025-11-06 21:25:28 +08:00
sugarBecomer 63a83ddd5e 🐛 修改编译逻辑,安装gcc 2025-11-06 20:50:23 +08:00
sugarBecomer f8d3d6a0ad 🐛 修改编译逻辑,安装gcc 2025-11-06 20:20:41 +08:00
sugarBecomer e2eb27a5ba 🐛 修改编译逻辑,安装gcc 2025-11-06 19:52:46 +08:00
sugarBecomer 9fbeddc9f4 🐛 修改编译逻辑,安装gcc 2025-11-06 19:36:31 +08:00
sugarBecomer 289bbe3f0d 🐛 修改编译逻辑,安装gcc 2025-11-06 19:23:41 +08:00
sugarBecomer bec6a93b65 🐛 修改编译逻辑,安装gcc 2025-11-06 19:21:51 +08:00
sugarBecomer e2a41fc187 🐛 修改编译逻辑,安装gcc 2025-11-06 19:00:44 +08:00
sugarBecomer c7a04f3857 🐛 修改编译逻辑,安装gcc 2025-11-06 18:33:50 +08:00
sugarBecomer 9c5398071c 🐛 修改编译逻辑,安装gcc 2025-11-06 18:24:58 +08:00
sugarBecomer 1f6400ba5d 🐛 修改编译逻辑,安装gcc 2025-11-06 18:17:27 +08:00
sugarBecomer afe0c149dd 🐛 尝试在linux允许cgo编译 2025-11-06 18:05:17 +08:00
sugarBecomer 9b9d05a4ac 🐛 临时验证突破类型接口&版本修复 2025-11-06 17:26:19 +08:00
sugarBecomer f59cb29e4d ✨ 任务日志 2025-11-06 16:45:36 +08:00
sugarBecomer f71ee4fab4 🐛 定时任务 2025-11-06 16:31:17 +08:00
sugarBecomer 6390831f16 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	internal/framework/schedule/cpdaily_handler.go
2025-11-06 16:28:58 +08:00
sugarBecomer da2fd3111b 🐛 定时任务&图片逻辑 2025-11-06 16:27:41 +08:00
RecordingTheSmile 02f97fb4a4 fix: update OCR server URL retrieval to use gf configuration 2025-11-04 00:51:31 +08:00
RecordingTheSmile ceee685b80 fix: 今日校园任务登录问题 2025-11-04 00:32:22 +08:00
sugarBecomer 132472de12 🐛 修改余额问题 2025-11-03 21:46:01 +08:00
sugarBecomer 7d8c14a045 🐛 尝试增加redis超时时间 2025-11-03 21:23:27 +08:00
sugarBecomer 25d190c498 🐛 定时任务查询 2025-11-03 21:01:06 +08:00
sugarBecomer f1dfa61578 🐛 充值bug 2025-11-03 20:42:45 +08:00
RecordingTheSmile 2c0026267e fix: actions构建问题 2025-11-03 18:25:40 +08:00
sugarBecomer ab84984fb0 🐛 参数校验错误返回信息 2025-11-03 17:04:25 +08:00
sugarBecomer 4f6e516ade Merge remote-tracking branch 'origin/main'
# Conflicts:
#	internal/application/httpclient/cpdaily.go
2025-11-03 14:31:23 +08:00
sugarBecomer c9aeb90209 🐛 http代理关闭 代理用户鉴权忽略admin 2025-11-03 14:30:40 +08:00
RecordingTheSmile 2125fd4bde fix: 移除httpclient中的代理设置 2025-11-03 14:29:00 +08:00
RecordingTheSmile 41dfe9ff54 feat: add support for Asia/Shanghai timezone and include rootcerts dependency 2025-11-03 11:32:11 +08:00
RecordingTheSmile 18fc1cee7a fix: remove redundant line in Dockerfile build command 2025-11-02 22:39:33 +08:00
47 changed files with 574 additions and 210 deletions
+1 -1
View File
@@ -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
View File
@@ -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/
+6 -1
View File
@@ -37,4 +37,9 @@ fromName = "今日校园系统"
accessKey = "dzckoE1UlZe8XFItWQDI"
secretKey = "f8UZdnDohtwZk5HInT1Cw1QCztSGnFuPPqfSSjzu"
baseUrl = "http://s3.out"
bucket = "likedream"
bucket = "likedream"
[cpdaily]
appVersion = "5.7.0"
systemVersion = "iOS 17"
calVersion = "3.0.0"
+10 -9
View File
@@ -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
+27 -18
View File
@@ -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=
+1
View File
@@ -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())
+2 -2
View File
@@ -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 {
+19
View File
@@ -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"`
}
+24 -1
View File
@@ -5,9 +5,14 @@ import (
"fmt"
_ "image/jpeg"
_ "image/png"
"likedream-goframe/internal/framework/logger"
"os"
"path/filepath"
"runtime"
"strings"
ort "github.com/yalue/onnxruntime_go"
"go.uber.org/zap"
)
type ImageClassifier struct {
@@ -21,7 +26,25 @@ type ImageClassifier struct {
// NewImageClassifier 创建新的图片分类器
func NewImageClassifier(modelPath, classesPath string) (*ImageClassifier, error) {
// 初始化ONNX Runtime
err := ort.InitializeEnvironment()
exePath := strings.ToLower(os.Args[0])
// 获取绝对路径
absPath, err := filepath.Abs(exePath)
dir := filepath.Dir(absPath)
systemOS := runtime.GOOS
switch systemOS {
case "windows":
dir = filepath.Join(dir, "onnxruntime.dll")
break
case "darwin":
dir = filepath.Join(dir, "onnxruntime.dylib")
break
case "linux":
dir = filepath.Join(dir, "onnxruntime.so")
break
}
logger.Logger.Info("初始化onnx:", zap.String("绝对路径", absPath), zap.String("父文件夹", dir))
ort.SetSharedLibraryPath(dir)
err = ort.InitializeEnvironment()
if err != nil {
return nil, fmt.Errorf("初始化ONNX Runtime失败: %v", err)
}
+8 -1
View File
@@ -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
}
@@ -237,6 +237,7 @@ func (c *CpdailyCasLogin) Login(ctx context.Context, schoolDetail *school.School
if isCasNeedKickOut(doc) {
kickoutResponse := submitCasKickOut(ctx, loginResponseUrl.String(), doc, c.client)
handleCasLoginSuccess(ctx, kickoutResponse, schoolDetail, username, password, c.client)
return
}
message := getCasErrorMessage(doc)
+5 -4
View File
@@ -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",
+2 -3
View File
@@ -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
}
+9 -2
View File
@@ -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
}
@@ -595,9 +605,9 @@ func (c *CpdailySleepCheckTask) FillCustomForm(ctx context.Context, form map[str
} else {
// 否则,填充查寝其他参数
if signInstanceWidVar := rows["signInstanceWid"]; signInstanceWidVar != nil {
resultForm["signInstanceWid"] = gvar.New(signInstanceWidVar.String())
resultForm["SignInstanceWid"] = gvar.New(signInstanceWidVar.String())
} else {
resultForm["signInstanceWid"] = gvar.New("")
resultForm["SignInstanceWid"] = gvar.New("")
}
// 查找 isMalposition 参数
@@ -666,7 +676,6 @@ func (c *CpdailySleepCheckTask) Submit(ctx context.Context, form map[string]*gva
sign := taskhelper.GetSubmitSign(submitData)
submitData["sign"] = gvar.New(sign)
response, e := c.client.R().
SetBody(submitData).
WithContext(ctx).
+14 -2
View File
@@ -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,
})
}
}
+27
View File
@@ -0,0 +1,27 @@
package errors
import (
"errors"
"testing"
)
func TestBusinessError(t *testing.T) {
defer func() {
if err := recover(); err != nil {
of, b := Of[*BusinessError](err.(error))
t.Log(of, b)
t.Log("ok")
}
}()
err := NewBusinessError(503, "调试错误")
panic(err)
}
func Of[T error](input error) (T, bool) {
var ret T
if errors.As(input, &ret) {
return ret, true
}
return ret, false
}
+12 -12
View File
@@ -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)
}
+3 -22
View File
@@ -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 {
+5
View File
@@ -0,0 +1,5 @@
package cst
const (
BasePointCpdaily = 1
)
+3
View File
@@ -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.
+15
View File
@@ -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
+4 -4
View File
@@ -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,
},
},
}
+5
View File
@@ -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.
+1 -1
View File
@@ -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(),
+1 -1
View File
@@ -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任务日志
}
}
+2 -2
View File
@@ -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").
+1 -1
View File
@@ -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)),
}
}
+4 -4
View File
@@ -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
View File
@@ -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)
+17 -36
View File
@@ -6,13 +6,13 @@ 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"
errors2 "likedream-goframe/internal/common/errors"
"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 +40,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))
}
@@ -61,6 +58,8 @@ func (c *CpdailyTaskHandler) ProcessTask(ctx context.Context, task *asynq.Task)
if e1, ok := utils.Of[*errors.BusinessError](err); ok {
errorMessage = e1.Message()
} else if e1, ok := utils.Of[*errors2.BusinessError](err); ok {
errorMessage = e1.Message
} else {
errorMessage = "未知的错误导致任务执行失败"
}
@@ -68,11 +67,11 @@ func (c *CpdailyTaskHandler) ProcessTask(ctx context.Context, task *asynq.Task)
e = db.Global.CpTaskLog.Create().
SetCpTaskID(taskPayload.CpTaskID).
SetCpUserID(targetTask.Edges.CpUser.ID).
SetSystemUserID(targetTask.Edges.CpUser.Edges.Sysuser.ID).
SetSystemUserID(targetTask.Edges.SysUser.ID).
SetIsSuccess(false).
SetRealName("").
SetErrorMessage(errorMessage).
Exec(ctx)
Exec(context.Background())
utils.LogError(ctx, "创建任务日志失败", oops.With("task_id", taskPayload.CpTaskID).Wrap(e))
@@ -89,33 +88,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 +130,6 @@ func (c *CpdailyTaskHandler) ProcessTask(ctx context.Context, task *asynq.Task)
}
submitForm := taskExecutor.FillCustomForm(ctx, cpdailyRealTask, customFormItems, deviceID, targetTask.Edges.CpUser.Username)
taskExecutor.Submit(ctx, submitForm, targetTask.Edges.CpUser.Username, deviceID)
db.Global.CpTask.UpdateOneID(taskPayload.CpTaskID).SetTaskStatus(cptask.TaskStatusDone).AddSuccessCount(1).ExecX(ctx)
+5 -5
View File
@@ -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,8 +117,8 @@ 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.Unique(10*time.Minute),
asynq.MaxRetry(3),
asynq.Unique(1*time.Minute),
asynq.ProcessAt(execTime),
asynq.Deadline(execTime.Add(12*time.Minute)),
asynq.Queue(cst.TaskQueueCpdaily),
@@ -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)
+10
View File
@@ -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)
+38 -51
View File
@@ -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.
+8 -5
View File
@@ -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, "余额不足"))
+54
View File
@@ -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{}
}
+14 -5
View File
@@ -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("执行成功")
+32
View File
@@ -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{}
}
+4
View File
@@ -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(),
}
+2 -2
View File
@@ -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)
}
+80
View File
@@ -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
}
+15 -1
View File
@@ -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]