Compare commits

...

86 Commits

Author SHA1 Message Date
sugarBecomer 36a6932056 🐛 opencv 2025-11-12 15:19:15 +08:00
sugarBecomer 72dab0e968 🐛 opencv 2025-11-12 15:01:33 +08:00
sugarBecomer b716434f62 🐛 opencv 2025-11-12 14:45:25 +08:00
sugarBecomer 8ed7dd77e4 🐛 opencv 2025-11-12 14:30:03 +08:00
sugarBecomer ae1c9c695e 🐛 签到问题 & opencv 2025-11-12 14:12:47 +08:00
sugarBecomer 66995c0c78 🐛 cas滑块验证码 2025-11-12 13:35:17 +08:00
sugarBecomer 120e690795 🐛 cas滑块验证码 2025-11-12 13:31:54 +08:00
sugarBecomer bc2bb25578 🐛 签到bug 2025-11-11 22:34:06 +08:00
RecordingTheSmile b37fc5cb24 fix: 签到额外信息填写问题 2025-11-11 22:29:01 +08:00
sugarBecomer 614dd9917f 🐛 签到bug 2025-11-11 22:07:57 +08:00
sugarBecomer 00bc3432bd 🐛 修复onnx环境 2025-11-11 21:48:08 +08:00
sugarBecomer ffec10d1cc ✨ 迁移积分 2025-11-11 21:31:49 +08:00
sugarBecomer 3993fa9b32 ✨ 忘记密码 & 重发邮件 2025-11-11 14:08:07 +08:00
sugarBecomer 20b92b7d1c 🐛 注册验证码 2025-11-11 12:55:53 +08:00
sugarBecomer 05b9a94d41 🐛 ai初始化 & 错误处理 2025-11-11 11:57:50 +08:00
sugarBecomer 49f4475991 🐛 干掉global id 2025-11-10 22:53:05 +08:00
sugarBecomer 76bfdd03dd 🐛 cookie更新 2025-11-10 22:20:34 +08:00
sugarBecomer c18f2fdcf7 🐛 细节问题 2025-11-10 21:51:08 +08:00
sugarBecomer 74c6154c59 🐛 验证码处理 & 查询条件 2025-11-10 21:36:59 +08:00
sugarBecomer 3dc9a5e2a4 🐛 错误的判定 2025-11-10 15:40:40 +08:00
sugarBecomer ca30fd89cb 🐛 错误的判定 2025-11-10 15:40:24 +08:00
sugarBecomer b56e18b8ce ✨ 实现ai识别提交验证码问题 2025-11-10 15:39:38 +08:00
sugarBecomer b031157f98 ✨ 调整文件结构 2025-11-10 14:46:01 +08:00
sugarBecomer 7262023382 ✨ 学习通获取课程列表 2025-11-10 14:40:38 +08:00
sugarBecomer dde5825d30 ✨ 集成ddddocr服务 2025-11-10 13:57:17 +08:00
sugarBecomer da4bc164e2 🚚 优化ai模型初始化方式 2025-11-10 13:38:41 +08:00
sugarBecomer ae95a871c8 ✨ 学习通 2025-11-09 22:18:03 +08:00
sugarBecomer 4a29772de0 🐛 下载地址返回 2025-11-09 00:58:59 +08:00
sugarBecomer 194065af8d ✨ 音乐下载 2025-11-08 23:39:02 +08:00
sugarBecomer a118b75379 🐛 立即执行参数 2025-11-08 22:24:45 +08:00
sugarBecomer 09d59162d0 🐛 遗漏的文件 2025-11-08 21:50:22 +08:00
sugarBecomer 1323bc7aa8 🐛 签到修复 & 定时重置状态 2025-11-08 21:47:08 +08:00
sugarBecomer 604245add2 🐛 修改余额 2025-11-08 00:21:53 +08:00
sugarBecomer 90bbc11712 🐛 任务立即执行但没有次数 2025-11-07 23:44:05 +08:00
sugarBecomer 948d118a4f 🐛 查寝各种问题修复 2025-11-07 23:36:02 +08:00
sugarBecomer 618d6384d9 🐛 代理信息修改 2025-11-07 20:00:05 +08:00
sugarBecomer face5ca364 🐛 代理充值 2025-11-07 19:46:25 +08:00
sugarBecomer d3869f68f8 🐛 代理设置 2025-11-07 19:45:57 +08:00
sugarBecomer 97ab3a7a1d 🐛 代理设置 2025-11-07 19:23:01 +08:00
sugarBecomer 6cc4582c87 🐛 代理设置 2025-11-07 19:13:06 +08:00
sugarBecomer 4941d4eb8a 🐛 代理设置 2025-11-07 16:55:22 +08:00
sugarBecomer 11a16a65a0 🐛 级联删除用户数据 2025-11-07 16:03:09 +08:00
sugarBecomer 71f992544e 🐛 登录问题 2025-11-07 15:56:23 +08:00
sugarBecomer 6320d6eb17 🐛 登录问题 2025-11-07 15:55:06 +08:00
sugarBecomer 6840b69f1a 🐛 登录问题 2025-11-07 15:28:54 +08:00
sugarBecomer 1ae2601209 🐛 salt寻找规则 2025-11-07 15:11:06 +08:00
sugarBecomer 07444f70df 🐛 ssl证书忽略 2025-11-07 14:59:40 +08:00
sugarBecomer 1bc04c74f3 🐛 菜单 keep alive 2025-11-07 14:30:12 +08:00
sugarBecomer dcb5cd8a4e 🐛 菜单修复 2025-11-07 14:00:45 +08:00
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
165 changed files with 6750 additions and 773 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
+54 -6
View File
@@ -1,17 +1,65 @@
FROM golang:alpine AS backend-builder
FROM golang:latest AS backend-builder
RUN apt update
RUN apt install -y build-essential
# 安装 OpenCV 开发库和依赖
RUN apt install -y \
libopencv-dev \
libopencv-core-dev \
libopencv-imgproc-dev \
libopencv-imgcodecs-dev \
libopencv-videoio-dev \
pkg-config
WORKDIR /build
COPY . .
ENV CGO_ENABLED=1
RUN go build -ldflags="-s -w" -o bin/server
RUN apk add --no-cache upx
RUN apt install -y upx-ucl
RUN upx --best --lzma bin/server
FROM alpine:latest
# 使用 ldd 检查二进制文件的依赖,并收集所有需要的 .so 文件
RUN mkdir -p /opencv-libs /qt-libs /other-libs && \
cp -P /usr/lib/x86_64-linux-gnu/libopencv*.so* /opencv-libs/ 2>/dev/null || true && \
cp -P /usr/lib/x86_64-linux-gnu/libQt5*.so* /qt-libs/ 2>/dev/null || true && \
cp -P /usr/lib/x86_64-linux-gnu/libpng*.so* /other-libs/ 2>/dev/null || true && \
cp -P /usr/lib/x86_64-linux-gnu/libjpeg*.so* /other-libs/ 2>/dev/null || true && \
cp -P /usr/lib/x86_64-linux-gnu/libtiff*.so* /other-libs/ 2>/dev/null || true && \
cp -P /usr/lib/x86_64-linux-gnu/libwebp*.so* /other-libs/ 2>/dev/null || true && \
cp -P /usr/lib/x86_64-linux-gnu/libImath*.so* /other-libs/ 2>/dev/null || true && \
cp -P /usr/lib/x86_64-linux-gnu/libIlmImf*.so* /other-libs/ 2>/dev/null || true && \
cp -P /usr/lib/x86_64-linux-gnu/libIex*.so* /other-libs/ 2>/dev/null || true && \
cp -P /usr/lib/x86_64-linux-gnu/libHalf*.so* /other-libs/ 2>/dev/null || true && \
cp -P /usr/lib/x86_64-linux-gnu/libIlmThread*.so* /other-libs/ 2>/dev/null || true
FROM golang:latest
# 安装 OpenCV 和 Qt 运行时依赖
RUN apt update && apt install -y \
libgl1 \
libglvnd0 \
libopengl0 \
libgomp1 \
libglib2.0-0 \
libglx0 \
libqt5core5a \
libqt5gui5 \
libqt5widgets5 \
libqt5test5 \
libdouble-conversion3 \
libxcb-xinerama0 \
&& rm -rf /var/lib/apt/lists/*
# 复制所有 .so 文件到运行环境
COPY --from=backend-builder /opencv-libs/* /usr/lib/x86_64-linux-gnu/
COPY --from=backend-builder /qt-libs/* /usr/lib/x86_64-linux-gnu/
COPY --from=backend-builder /other-libs/* /usr/lib/x86_64-linux-gnu/
COPY --from=backend-builder /build/bin/server /app/server
COPY static /app/static
COPY static/*.so /app/
#COPY static /app/static
#COPY static/*.so /app/
WORKDIR /app
EXPOSE 8080
RUN ls -a
+14 -1
View File
@@ -14,7 +14,20 @@ func Run() {
IDType: &field.TypeInfo{
Type: field.TypeInt64,
},
Features: gen.AllFeatures,
Features: []gen.Feature{
gen.FeaturePrivacy,
gen.FeatureIntercept,
gen.FeatureEntQL,
gen.FeatureNamedEdges,
gen.FeatureBidiEdgeRefs,
gen.FeatureSnapshot,
gen.FeatureSchemaConfig,
gen.FeatureLock,
gen.FeatureModifier,
gen.FeatureExecQuery,
gen.FeatureUpsert,
gen.FeatureVersionedMigration,
},
})
utils.OkOrPanic(err)
+4 -4
View File
@@ -4,7 +4,7 @@ import (
"context"
"likedream-goframe/internal/api"
"likedream-goframe/internal/application/filestorage"
"likedream-goframe/internal/db"
db2 "likedream-goframe/internal/common/db"
_ "likedream-goframe/internal/ent/runtime"
"likedream-goframe/internal/framework/redis"
"likedream-goframe/internal/framework/schedule"
@@ -17,10 +17,10 @@ import (
)
func Run() {
db.InitDB()
db2.InitDB()
// 如果没有数据,进行数据初始化
if !db.CheckHasData() {
db.GenerateData()
if !db2.CheckHasData() {
db2.GenerateData()
}
ctx, cancel := context.WithCancel(gctx.GetInitCtx())
+12 -5
View File
@@ -4,14 +4,16 @@ url = "https://devocr.likedream.xyz"
[database]
type = "mysql"
dsn = "test_likedream_go:EpXckXmxawDEQGxJ@tcp(database.out:3306)/test_likedream_go?parseTime=true"
dsn2 = "host=database.out user=dev password=JPmKjmpcaG3EYAJZ dbname=dev port=5432 sslmode=disable TimeZone=Asia/Shanghai"
# host=localhost user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai
[server]
port = 8090
url = "https://devocr.likedream.xyz"
openapiPath= "/api.json"
swaggerPath= "/swagger"
emailConfirmBaseUrl = "https://dev.likedream.xyz/confirm/"
emailConfirmBaseUrl = "http://localhost:3200/confirm/"
emailResetPasswordUrl = "http://localhost:3200/reset-password/"
balanceMigrateUrl = "http://localhost:3200/balance-migrate/"
[env]
# 可选值: dev, prod
mode = "dev"
@@ -30,11 +32,16 @@ smtpUsername = "demo@likedream.xyz"
smtpPassword = "baca122..."
# 发件人邮箱和显示名称
fromEmail = "demo@likedream.xyz"
fromName = "今日校园系统"
fromName = "若梦系统"
[s3]
accessKey = "dzckoE1UlZe8XFItWQDI"
secretKey = "f8UZdnDohtwZk5HInT1Cw1QCztSGnFuPPqfSSjzu"
baseUrl = "http://s3.out"
bucket = "likedream"
bucket = "likedream"
[cpdaily]
appVersion = "5.7.0"
systemVersion = "iOS 17"
calVersion = "3.0.0"
+28 -17
View File
@@ -1,6 +1,6 @@
module likedream-goframe
go 1.24
go 1.24.0
require (
entgo.io/ent v0.14.5
@@ -19,19 +19,24 @@ require (
github.com/google/uuid v1.6.0
github.com/hibiken/asynq v0.25.1
github.com/joomcode/errorx v1.2.0
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
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/thedevsaddam/gojsonq v1.9.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.12.1
go.uber.org/automaxprocs v1.6.0
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.39.0
gocv.io/x/gocv v0.42.0
golang.org/x/crypto v0.43.0
gorm.io/driver/postgres v1.6.0
gorm.io/gorm v1.31.1
resty.dev/v3 v3.0.0-beta.3
)
@@ -62,14 +67,21 @@ 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/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/pgx/v5 v5.6.0 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // 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
@@ -77,18 +89,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
@@ -98,13 +109,13 @@ require (
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/image v0.29.0 // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.27.0 // indirect
golang.org/x/mod v0.28.0 // indirect
golang.org/x/net v0.45.0 // indirect
golang.org/x/sync v0.18.0 // indirect
golang.org/x/sys v0.37.0 // indirect
golang.org/x/text v0.30.0 // indirect
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools v0.34.0 // indirect
golang.org/x/tools v0.37.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+64 -34
View File
@@ -82,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=
@@ -98,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=
@@ -110,6 +111,18 @@ github.com/hashicorp/hcl/v2 v2.18.1 h1:6nxnOJFku1EuSawSD81fuviYUV8DxFr3fp2dUi3ZY
github.com/hashicorp/hcl/v2 v2.18.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
github.com/hibiken/asynq v0.25.1 h1:phj028N0nm15n8O2ims+IvJ2gz4k2auvermngh9JhTw=
github.com/hibiken/asynq v0.25.1/go.mod h1:pazWNOLBu0FEynQRBvHA26qdIKRSmfdIfUm4HdsLmXg=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/joomcode/errorx v1.2.0 h1:7Y/fguon+9r6a/75Rv3nrUwS7nXNEcJjLShjCvz00Og=
github.com/joomcode/errorx v1.2.0/go.mod h1:Mbz68VA9hsQLT50iCQQUZ2Z1XYAKYB4EoFkFCTFyiJM=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
@@ -121,6 +134,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=
@@ -131,19 +146,21 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
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=
@@ -155,29 +172,26 @@ 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=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -185,14 +199,18 @@ 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/thedevsaddam/gojsonq v1.9.1 h1:zQulEP43nwmq5EKrNWyIgJVbqDeMdC1qzXM/f5O15a0=
github.com/thedevsaddam/gojsonq v1.9.1/go.mod h1:RBcQaITThgJAAYKH7FNp2onYodRz8URfsuEGpAch0NA=
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=
@@ -201,9 +219,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.12.1 h1:joCCmBnNjHy04jK9EMP/UV6oPPqySXlRgf3gcUcnI/g=
github.com/yalue/onnxruntime_go v1.12.1/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=
@@ -224,6 +244,8 @@ go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
gocv.io/x/gocv v0.42.0 h1:AAsrFJH2aIsQHukkCovWqj0MCGZleQpVyf5gNVRXjQI=
gocv.io/x/gocv v0.42.0/go.mod h1:zYdWMj29WAEznM3Y8NsU3A0TRq/wR/cy75jeUypThqU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -233,8 +255,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/image v0.16.0/go.mod h1:ugSZItdV4nOxyqp56HmXwH0Ry0nBCpjnZdpDaIHdoPs=
golang.org/x/image v0.29.0 h1:HcdsyR4Gsuys/Axh0rDEmlBmB68rW1U9BUdB3UVHsas=
golang.org/x/image v0.29.0/go.mod h1:RVJROnf3SLK8d26OW91j4FrIHGbsJ8QnbEocVTOWQDA=
@@ -243,8 +265,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
@@ -254,8 +276,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -264,10 +286,12 @@ golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
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/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
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=
@@ -275,13 +299,14 @@ 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=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -302,8 +327,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -312,9 +337,10 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
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=
@@ -324,6 +350,10 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
resty.dev/v3 v3.0.0-beta.3 h1:3kEwzEgCnnS6Ob4Emlk94t+I/gClyoah7SnNi67lt+E=
resty.dev/v3 v3.0.0-beta.3/go.mod h1:OgkqiPvTDtOuV4MGZuUDhwOpkY8enjOsjjMzeOHefy4=
+5 -1
View File
@@ -2,15 +2,16 @@ package api
import (
"context"
"likedream-goframe/internal/common/cst"
"likedream-goframe/internal/controller/agent"
"likedream-goframe/internal/controller/card"
"likedream-goframe/internal/controller/common"
"likedream-goframe/internal/controller/cpdaily"
"likedream-goframe/internal/controller/menu"
"likedream-goframe/internal/controller/music"
"likedream-goframe/internal/controller/role"
"likedream-goframe/internal/controller/user"
"likedream-goframe/internal/controller/user_login"
"likedream-goframe/internal/cst"
"likedream-goframe/internal/middleware"
"likedream-goframe/internal/utils"
@@ -52,6 +53,9 @@ func StartServer(ctx context.Context) {
cpdailyGroup.Bind(cpdaily.NewCpUserCtrlV1())
cpdailyGroup.Bind(cpdaily.NewCpTaskCtrlV1())
cpdailyGroup.Bind(cpdaily.NewCpImageCtrlV1())
cpdailyGroup.Bind(cpdaily.NewCpTaskLogCtrlV1())
musicGroup := group.Group("/music").Middleware(middleware.AuthHandler, middleware.PermissionHandler)
musicGroup.Bind(music.NewMusicCtrlV1())
})
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"`
}
+1
View File
@@ -31,6 +31,7 @@ type MenuAddReq struct {
Route string `json:"route"`
Component string `json:"component"`
Hidden bool `json:"hidden"`
KeepAlive bool `json:"keepAlive"`
Icon string `json:"icon"`
Order uint `json:"order"`
ParentId int64 `json:"parentId"`
+13
View File
@@ -0,0 +1,13 @@
package v1
import "github.com/gogf/gf/v2/frame/g"
type SearchMusicReq struct {
g.Meta `path:"/search" method:"get" tags:"Music" summary:"搜索音乐"`
Keyword string `json:"keyword"`
}
type DownloadMusicReq struct {
g.Meta `path:"/download" method:"get" tags:"Music" summary:"下载音乐"`
Path string `json:"path"`
}
+1
View File
@@ -16,6 +16,7 @@ type UserMenuRes struct {
Route string `json:"route"`
Component string `json:"component"`
Hidden bool `json:"hidden"`
KeepAlive bool `json:"keepAlive"`
Icon string `json:"icon"`
Children []*UserMenuRes `json:"children"`
Order uint `json:"order"`
+51 -9
View File
@@ -12,22 +12,64 @@ type CaptchaReq struct {
type UserLoginReq struct {
g.Meta `path:"/user/login" method:"POST" tags:"UserLogin" summary:"用户登录"`
Username string `json:"username" v:"required"`
Password string `json:"password" v:"required"`
CaptchaKey string `json:"captchaKey" v:"required"`
Dots []captcha.ConfirmData `json:"dots" v:"required"`
Username string `json:"username" v:"required#用户名或密码不能为空"`
Password string `json:"password" v:"required#用户名或密码不能为空"`
CaptchaKey string `json:"captchaKey" v:"required#验证码不能不能为空"`
Dots []captcha.ConfirmData `json:"dots" v:"required#验证码不能为空"`
}
type UserRegisterReq struct {
g.Meta `path:"/user/register" method:"POST" tags:"UserLogin" summary:"用户注册"`
Email string `json:"email" v:"required|email|regex:^.*@qq\\.com$#邮箱不能为空|邮箱格式不正确|必须是QQ邮箱"`
Username string `json:"username" v:"required|length:2,20#用户名不能为空|用户名长度应在2-20之间" `
Password string `json:"password" v:"required|length:6,20#密码不能为空|密码长度应在6-20之间" `
ConfirmPassword string `json:"confirmPassword" v:"required|same:password#确认密码不能为空|两次输入的密码不一致"`
InviteCode string `json:"inviteCode"`
Email string `json:"email" v:"required|email|regex:^.*@qq\\.com$#邮箱不能为空|邮箱格式不正确|必须是QQ邮箱"`
Username string `json:"username" v:"required|length:2,20#用户名不能为空|用户名长度应在2-20之间" `
Password string `json:"password" v:"required|length:6,20#密码不能为空|密码长度应在6-20之间" `
ConfirmPassword string `json:"confirmPassword" v:"required|same:password#确认密码不能为空|两次输入的密码不一致"`
InviteCode string `json:"inviteCode"`
CaptchaKey string `json:"captchaKey" v:"required#验证码不能不能为空"`
Dots []captcha.ConfirmData `json:"dots" v:"required#验证码不能为空"`
}
type UserConfirmReq struct {
g.Meta `path:"/user/confirm" method:"POST" tags:"UserLogin" summary:"邮箱二次验证"`
Token string `json:"token" v:"required"`
}
type ResendVerificationReq struct {
g.Meta `path:"/user/resendVerification" method:"POST" tags:"UserLogin" summary:"重新发送验证邮件"`
Email string `json:"email" v:"required|email|regex:^.*@qq\\.com$#邮箱不能为空|邮箱格式不正确|必须是QQ邮箱"`
CaptchaKey string `json:"captchaKey" v:"required#验证码不能不能为空"`
Dots []captcha.ConfirmData `json:"dots" v:"required#验证码不能为空"`
}
type ForgotPasswordReq struct {
g.Meta `path:"/user/forgotPassword" method:"POST" tags:"UserLogin" summary:"忘记密码-发送重置密码邮件"`
Email string `json:"email" v:"required|email|regex:^.*@qq\\.com$#邮箱不能为空|邮箱格式不正确|必须是QQ邮箱"`
CaptchaKey string `json:"captchaKey" v:"required#验证码不能不能为空"`
Dots []captcha.ConfirmData `json:"dots" v:"required#验证码不能为空"`
}
type ForgetResetPasswordReq struct {
g.Meta `path:"/user/forgetResetPassword" method:"POST" tags:"UserLogin" summary:"忘记密码-重置密码"`
Token string `json:"token" v:"required#token不能为空"`
NewPassword string `json:"newPassword" v:"required|length:6,20#密码不能为空|密码长度应在6-20之间"`
ConfirmPassword string `json:"confirmPassword" v:"required|same:newPassword#确认密码不能为空|两次输入的密码不一致"`
}
type ResetPasswordInfoReq struct {
g.Meta `path:"/user/resetPassword/info" method:"POST" tags:"UserLogin" summary:"获取重置密码用户信息"`
Token string `json:"token" v:"required#token不能为空"`
}
type RequestBalanceMigrateReq struct {
g.Meta `path:"/user/requestBalanceMigrate" method:"POST" tags:"UserLogin" summary:"请求积分转移链接"`
Email string `json:"email" v:"required|email|regex:^.*@qq\\.com$#邮箱不能为空|邮箱格式不正确|必须是QQ邮箱"`
CaptchaKey string `json:"captchaKey" v:"required#验证码不能不能为空"`
Dots []captcha.ConfirmData `json:"dots" v:"required#验证码不能为空"`
}
type BalanceMigrateReq struct {
g.Meta `path:"/user/balanceMigrate" method:"POST" tags:"UserLogin" summary:"执行积分转移" auth:"false"`
Token string `json:"token" v:"required#token不能为空"`
CaptchaKey string `json:"captchaKey" v:"required#验证码不能不能为空"`
Dots []captcha.ConfirmData `json:"dots" v:"required#验证码不能为空"`
}
@@ -0,0 +1,160 @@
package cookiejar
import (
"bytes"
"encoding/gob"
"github.com/bytedance/sonic"
"io"
"likedream-goframe/internal/utils"
"net/http"
"net/url"
"strings"
"sync"
)
type domainMap map[string]cookieMap
// AllSavePersistCookieJar 支持泛域名的 Cookie Jar
// 不同的二级域名会共享相同主域名的 cookies
// 例如: passport2.chaoxing.com 和 mooc1-api.chaoxing.com 共享 .chaoxing.com 的 cookies
type AllSavePersistCookieJar struct {
domainMap domainMap
*sync.RWMutex
}
func NewAllSavePersistCookieJar() *AllSavePersistCookieJar {
return &AllSavePersistCookieJar{
domainMap: make(domainMap),
RWMutex: &sync.RWMutex{},
}
}
// extractMainDomain 提取主域名
// 例如: passport2.chaoxing.com -> chaoxing.com
//
// mooc1-api.chaoxing.com -> chaoxing.com
// www.example.co.uk -> example.co.uk
func extractMainDomain(host string) string {
// 移除端口号
if colonIndex := strings.Index(host, ":"); colonIndex != -1 {
host = host[:colonIndex]
}
parts := strings.Split(host, ".")
if len(parts) <= 2 {
// 已经是主域名或单级域名
return host
}
// 处理特殊的二级顶级域名,如 .co.uk, .com.cn 等
// 简化处理:取最后两部分
// 更复杂的情况可以使用 publicsuffix 包
return strings.Join(parts[len(parts)-2:], ".")
}
func (a *AllSavePersistCookieJar) SetCookies(u *url.URL, cookies []*http.Cookie) {
a.Lock()
defer a.Unlock()
// 提取主域名
mainDomain := extractMainDomain(u.Host)
if _, exists := a.domainMap[mainDomain]; !exists {
a.domainMap[mainDomain] = make(cookieMap)
}
for _, cookie := range cookies {
if a.domainMap[mainDomain] == nil {
a.domainMap[mainDomain] = make(cookieMap)
}
a.domainMap[mainDomain][cookie.Name] = cookie
}
}
func (a *AllSavePersistCookieJar) Cookies(u *url.URL) []*http.Cookie {
a.RLock()
defer a.RUnlock()
// 提取主域名
mainDomain := extractMainDomain(u.Host)
if cookies, exists := a.domainMap[mainDomain]; exists {
result := make([]*http.Cookie, 0, len(cookies))
for _, cookie := range cookies {
result = append(result, cookie)
}
return result
}
return nil
}
func (a *AllSavePersistCookieJar) Serialize() string {
a.RLock()
defer a.RUnlock()
json, err := sonic.Marshal(a.domainMap)
utils.OkOrPanic(err)
return string(json)
}
func (a *AllSavePersistCookieJar) Deserialize(content string) {
a.Lock()
defer a.Unlock()
if content == "" {
a.domainMap = make(domainMap)
return
}
var domainMap domainMap
err := sonic.Unmarshal([]byte(content), &domainMap)
utils.OkOrPanic(err)
a.domainMap = domainMap
}
func (a *AllSavePersistCookieJar) SerializeBytes() []byte {
a.RLock()
defer a.RUnlock()
ret := make([]byte, 0)
retWriter := bytes.NewBuffer(ret)
err := gob.NewEncoder(retWriter).
Encode(a.domainMap)
utils.OkOrPanic(err)
return retWriter.Bytes()
}
func (a *AllSavePersistCookieJar) DeserializeBytes(content []byte) {
a.Lock()
defer a.Unlock()
if len(content) == 0 {
a.domainMap = make(domainMap)
return
}
retReader := bytes.NewBuffer(content)
var domainMap domainMap
err := gob.NewDecoder(retReader).
Decode(&domainMap)
utils.OkOrPanic(err)
a.domainMap = domainMap
}
func (a *AllSavePersistCookieJar) DeserializeReader(reader io.Reader) {
a.Lock()
defer a.Unlock()
var domainMap domainMap
err := gob.NewDecoder(reader).
Decode(&domainMap)
utils.OkOrPanic(err)
a.domainMap = domainMap
}
@@ -5,8 +5,8 @@ import (
"encoding/json"
"likedream-goframe/internal/application/cpdaily/types"
"likedream-goframe/internal/application/filestorage"
"likedream-goframe/internal/common/db"
"likedream-goframe/internal/common/errors"
"likedream-goframe/internal/db"
"likedream-goframe/internal/ent"
"likedream-goframe/internal/ent/cpimage"
"likedream-goframe/internal/utils"
@@ -75,7 +75,7 @@ func UploadImageFromStorage(ctx context.Context, host string, imageId uuid.UUID,
utils.OkOrPanic(errors.NewBusinessError(503, "上传图片失败: "+utils.ReadString(resp.Body)), oops.WithContext(ctx).With("response", utils.ReadString(resp.Body)).Wrap)
}
previewUrl := GetPreviewUrlAsync(ctx, host, targetImage.Key, taskType, client)
previewUrl := GetPreviewUrlAsync(ctx, host, imageUploadPolicy.FileName, taskType, client)
return previewUrl
}
+2 -1
View File
@@ -2,8 +2,9 @@ package cpdaily
import (
"context"
"likedream-goframe/internal/common/cst"
"github.com/gogf/gf/v2/frame/g"
"likedream-goframe/internal/cst"
)
type Info struct {
+40 -13
View File
@@ -9,17 +9,19 @@ import (
"likedream-goframe/internal/application/cookiejar"
"likedream-goframe/internal/application/cpdaily/school"
"likedream-goframe/internal/application/httpclient"
"likedream-goframe/internal/common/cst"
"likedream-goframe/internal/common/errors"
"likedream-goframe/internal/cst"
"likedream-goframe/internal/framework/redis"
"likedream-goframe/internal/utils"
"net/http"
"net/url"
"regexp"
"slices"
"strings"
"time"
"github.com/PuerkitoBio/goquery"
"github.com/avast/retry-go/v4"
"github.com/deatil/go-cryptobin/cryptobin/crypto"
"github.com/samber/oops"
"github.com/tidwall/gjson"
@@ -174,9 +176,9 @@ func (c *CpdailyCasLogin) Login(ctx context.Context, schoolDetail *school.School
if saltValue != "" {
salt = saltValue
} else {
saltMatches := saltRegexp.FindAllString(string(loginPageBytes), -1)
if len(saltMatches) > 0 {
salt = saltMatches[0]
saltMatches := saltRegexp.FindStringSubmatch(string(loginPageBytes))
if len(saltMatches) > 1 {
salt = saltMatches[1]
}
}
}
@@ -188,20 +190,35 @@ func (c *CpdailyCasLogin) Login(ctx context.Context, schoolDetail *school.School
} else {
allInputs["password"] = encryptCasPassword(password, salt)
}
var SliderCaptchaIds = []string{"1018764144934965"}
// 判断是否需要验证码
if isCasNeedCaptcha(ctx, loginResponseUrl, loginType, username, c.client) {
// 解决验证码
captchaUrl := getCasCaptchaUrl(loginResponseUrl, loginType)
// 如果是滑块验证码
if slices.Contains(SliderCaptchaIds, schoolDetail.Id) {
e := retry.Do(func() error {
return utils.Catch(func() {
captchaUrl := getCasSliderCaptchaUrl(loginResponseUrl)
verifyUrl := getCasSliderVerifyUrl(loginResponseUrl)
ResolveCasSliderCaptcha(ctx, captchaUrl, verifyUrl, c.client)
})
}, retry.MaxDelay(15*time.Second), retry.Attempts(5), retry.Context(ctx))
if e != nil {
utils.OkOrPanic(errors.NewBusinessError(503, "滑块验证码解析失败").WithInnerError(e), oops.WithContext(ctx).Wrap)
}
} else {
// 解决常规图片验证码
captchaUrl := getCasCaptchaUrl(loginResponseUrl, loginType)
captchaResult := ResolveOcrCaptcha(ctx, captchaUrl, c.client)
captchaResult := ResolveOcrCaptcha(ctx, captchaUrl, c.client)
switch loginType {
case 0:
allInputs["captchaResponse"] = captchaResult
default:
allInputs["captcha"] = captchaResult
switch loginType {
case 0:
allInputs["captchaResponse"] = captchaResult
default:
allInputs["captcha"] = captchaResult
}
}
}
loginPostResponse, err := c.client.R().
@@ -237,6 +254,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)
@@ -528,3 +546,12 @@ func getCasCaptchaUrl(url *url.URL, loginType int) string {
return fmt.Sprintf("%s://%s/authserver/getCaptcha.htl", url.Scheme, url.Host)
}
}
func getCasSliderCaptchaUrl(url *url.URL) string {
// /authserver/common/openSliderCaptcha.htl?_=1762873725346
return fmt.Sprintf("%s://%s/authserver/common/openSliderCaptcha.htl", url.Scheme, url.Host)
}
func getCasSliderVerifyUrl(url *url.URL) string {
return fmt.Sprintf("%s://%s/authserver/common/verifySliderCaptcha.htl", url.Scheme, url.Host)
}
+42 -59
View File
@@ -2,70 +2,53 @@ package login
import (
"context"
"github.com/samber/oops"
"github.com/spf13/viper"
"github.com/tidwall/gjson"
"fmt"
"io"
"likedream-goframe/internal/application/httpclient"
"likedream-goframe/internal/cst"
"likedream-goframe/internal/application/recognizer/ddddocr"
"likedream-goframe/internal/framework/logger"
"likedream-goframe/internal/utils"
"os"
"github.com/samber/oops"
"go.uber.org/zap"
"resty.dev/v3"
)
func ResolveOcrCaptcha(ctx context.Context, url string, client *resty.Client) string {
captchaResponse, err := client.R().
WithContext(ctx).
Get(url)
utils.OkOrPanic(err, func(err error) error {
return oops.
With("captchaUrl", url).
WithContext(ctx).
Wrap(err)
})
defer func() {
_ = captchaResponse.Body.Close()
}()
ocrUrl := viper.GetString(cst.ConfigOcrServerUrl)
ocrResponse, err := httpclient.Common.R().
SetMultipartFields(&resty.MultipartField{
Name: "file",
FileName: "captcha.jpg",
ContentType: captchaResponse.Header().Get("Content-Type"),
Reader: captchaResponse.Body,
}).
WithContext(ctx).
Post(ocrUrl + "/ocr")
utils.OkOrPanic(err, func(err error) error {
return oops.
With("captchaUrl", url).
WithContext(ctx).
Wrap(err)
})
defer func() {
_ = ocrResponse.Body.Close()
}()
responseBytes, err := io.ReadAll(ocrResponse.Body)
utils.OkOrPanic(err)
responseJSON := gjson.ParseBytes(responseBytes)
data := responseJSON.Get("data").String()
if data == "" {
utils.OkOrPanic(oops.
In("ResolveOcrCaptcha").
With("captchaUrl", url).
With("message", responseJSON.Get("message").String()).
WithContext(ctx).
New("OCR服务返回数据为空"))
}
codePath := DownCode2File(ctx, url, client)
img, _ := utils.ReadImg(codePath) //读取验证码图片
data := ddddocr.AutoOCRVerification(img)
return data
}
func DownCode2File(ctx context.Context, url string, client *resty.Client) string {
res, err := client.R().
WithContext(ctx).
Get(url)
utils.OkOrPanic(err, func(err error) error {
return oops.
With("captchaUrl", url).
WithContext(ctx).
Wrap(err)
})
defer res.Body.Close()
codeFileName := "code" + utils.GenerateRandomString(16) //生成验证码文件名称
codeFileName += ".png"
utils.PathExistForCreate("./assets/code/") //检测是否存在路径,如果不存在则创建
filepath := fmt.Sprintf("./assets/code/%s", codeFileName)
file, err := os.Create(filepath)
if err != nil {
logger.Logger.Error("生成验证码失败", zap.Error(err))
return ""
}
_, err = io.Copy(file, res.Body)
if err != nil {
logger.Logger.Error("生成验证码失败", zap.Error(err))
return ""
}
file.Close()
return filepath
}
@@ -0,0 +1,67 @@
package login
import (
"context"
"fmt"
"io"
"likedream-goframe/internal/application/recognizer/slider"
"likedream-goframe/internal/common/errors"
"likedream-goframe/internal/utils"
"github.com/bytedance/sonic"
"github.com/samber/oops"
"resty.dev/v3"
)
type CasSliderCaptchaReponse struct {
BigImage string `json:"bigImage"`
SmallImage string `json:"smallImage"`
TagWidth int `json:"tagWidth"`
YHeight int `json:"yHeight"`
}
type CasSliderResult struct {
ErrorCode int `json:"errorCode"`
ErrorMsg string `json:"errorMsg"`
}
func ResolveCasSliderCaptcha(ctx context.Context, captchaUrl string, verifyUrl string, client *resty.Client) {
res, err := client.R().
WithContext(ctx).
Get(captchaUrl)
utils.OkOrPanic(err, func(err error) error {
return oops.
With("captchaUrl", captchaUrl).
WithContext(ctx).
Wrap(err)
})
defer res.Body.Close()
bytes, _ := io.ReadAll(res.Body)
var captcha CasSliderCaptchaReponse
sonic.Unmarshal(bytes, &captcha)
width := slider.VerifySliderWidthByBase64(captcha.BigImage, captcha.SmallImage)
res2, err2 := client.R().
WithContext(ctx).
SetFormData(map[string]string{
"canvasLength": "280",
"moveLength": fmt.Sprintf("%d", width),
}).
Post(verifyUrl)
utils.OkOrPanic(err2, func(err error) error {
return oops.
With("verifyUrl", verifyUrl).
WithContext(ctx).
Wrap(err)
})
defer res2.Body.Close()
bytes, _ = io.ReadAll(res2.Body)
str := string(bytes)
if len(str) > 0 {
var result CasSliderResult
sonic.Unmarshal(bytes, &result)
if result.ErrorCode != 1 {
utils.OkOrPanic(oops.WithContext(ctx).Wrap(errors.NewBusinessError(500, "滑块解析错误")))
}
}
}
@@ -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",
@@ -0,0 +1,181 @@
package submitcaptcha
import (
"context"
"io"
"likedream-goframe/internal/application/cpdaily/types"
"likedream-goframe/internal/application/recognizer/classifier"
"likedream-goframe/internal/common/errors"
"likedream-goframe/internal/utils"
"strings"
"github.com/bytedance/sonic"
"resty.dev/v3"
)
type AIResolver struct {
client *resty.Client
host string
deviceId string
taskType types.TaskType
}
func NewAIResolver(client *resty.Client, host, deviceId string, taskType types.TaskType) SubmitCaptchaResolver {
return &AIResolver{
client: client,
host: host,
deviceId: deviceId,
taskType: taskType,
}
}
func (r *AIResolver) GetValidationInfo(ctx context.Context) ValidationInfo {
// GetValidationInfo 获取验证信息
reqData := map[string]string{
"deviceId": r.deviceId,
}
resp, err := r.client.R().
SetBody(reqData).
Post(r.getValidateUrl())
utils.OkOrPanic(err)
apiResp := utils.ReadJson[ApiResponse](resp.Body)
if apiResp.Datas == nil {
message := "获取提交验证码信息失败"
if apiResp.Message != "" {
message = apiResp.Message
}
utils.OkOrPanic(errors.NewBusinessError(503, message))
}
var validationInfo ValidationInfo
err = sonic.Unmarshal(apiResp.Datas, &validationInfo)
utils.OkOrPanic(err)
return validationInfo
}
func (r *AIResolver) GetCaptchaTicket(ctx context.Context, info ValidationInfo) string {
captchaInfo := r.createCaptcha(info)
codes := r.getResult(captchaInfo)
return r.submitCaptcha(info, captchaInfo, codes)
}
func (r *AIResolver) getResult(data CpSubmitCaptchaForAI) []string {
name := data.Name
infos := data.ImageInfos
var result []string
for _, item := range infos {
url := item.Path
get, err := r.client.R().Get(url)
utils.OkOrPanic(err)
defer get.Body.Close()
bytes, _ := io.ReadAll(get.Body)
//todo 将图片保存方便后面训练
//os.WriteFile(item.Code+".png", bytes, 0666)
if classifier.ClassifyImage(bytes, name) {
result = append(result, item.Code)
}
}
return result
}
// getValidateUrl 根据任务类型获取验证URL
func (r *AIResolver) getValidateUrl() string {
baseUrl := strings.TrimSuffix(r.host, "/")
switch r.taskType {
case types.TaskTypeCollection:
return baseUrl + "/wec-counselor-collector-apps/stu/collector/checkValidation"
case types.TaskTypeSign:
return baseUrl + "/wec-counselor-sign-apps/stu/sign/checkValidation"
case types.TaskTypeSleepCheck:
return baseUrl + "/wec-counselor-attendance-apps/student/attendance/checkValidation"
default:
utils.OkOrPanic(errors.NewBusinessError(400, "不支持的任务类型"))
return ""
}
}
// createCaptcha 创建验证码
func (r *AIResolver) createCaptcha(info ValidationInfo) CpSubmitCaptchaForAI {
baseUrl := strings.TrimSuffix(r.host, "/")
url := baseUrl + "/captcha-open-api/v1/captcha/create/scenesImage"
resp, err := r.client.R().
SetHeader("deviceId", r.deviceId).
SetMultipartFormData(map[string]string{
"accountKey": info.AccountKey,
"sceneCode": info.SceneCode,
"tenantId": info.TenantId,
"userId": info.UserId,
}).
Post(url)
utils.OkOrPanic(err)
apiResp := utils.ReadJson[ApiResponse](resp.Body)
if apiResp.Result == nil {
message := "获取提交验证码失败"
if apiResp.Message != "" {
message = apiResp.Message
}
utils.OkOrPanic(errors.NewBusinessError(503, message))
}
var result CpSubmitCaptchaForAI
err = sonic.Unmarshal(apiResp.Result, &result)
utils.OkOrPanic(err)
return result
}
// submitCaptcha 提交验证码
func (r *AIResolver) submitCaptcha(info ValidationInfo, submitCaptcha CpSubmitCaptchaForAI, codes []string) string {
baseUrl := strings.TrimSuffix(r.host, "/")
url := baseUrl + "/captcha-open-api/v1/captcha/validate/scenesImage"
formData := map[string]string{
"accountKey": info.AccountKey,
"sceneCode": info.SceneCode,
"tenantId": info.TenantId,
"userId": info.UserId,
"scenesImageCode": submitCaptcha.Code,
}
// 创建multipart form request
req := r.client.R().SetHeader("deviceId", r.deviceId)
// 添加基本表单数据
for key, value := range formData {
req = req.SetMultipartFormData(map[string]string{key: value})
}
// 添加验证码列表
for _, code := range codes {
req = req.SetMultipartField("scenesImageCodes", "", "", strings.NewReader(code))
}
resp, err := req.Post(url)
utils.OkOrPanic(err)
apiResp := utils.ReadJson[ApiResponse](resp.Body)
if apiResp.Code != "200" {
message := "提交验证码失败"
if apiResp.Message != "" {
message = apiResp.Message
}
utils.OkOrPanic(errors.NewBusinessError(503, message))
}
if apiResp.Result == nil {
utils.OkOrPanic(errors.NewBusinessError(503, "今日校园返回空验证码结果"))
}
var result string
err = sonic.Unmarshal(apiResp.Result, &result)
utils.OkOrPanic(err)
return result
}
@@ -20,6 +20,15 @@ type CpSubmitCaptcha struct {
RawResponseJson json.RawMessage `json:"-"`
}
type CpSubmitCaptchaForAI struct {
Code string `json:"code"`
Name string `json:"name"`
ImageInfos []struct {
Code string `json:"code"`
Path string `json:"path"`
} `json:"imageInfos"`
}
// ApiResponse 通用API响应结构体
type ApiResponse struct {
Code json.Number `json:"code"`
@@ -5,8 +5,8 @@ import (
"encoding/json"
"fmt"
"likedream-goframe/internal/application/cpdaily/types"
"likedream-goframe/internal/common/cst"
"likedream-goframe/internal/common/errors"
"likedream-goframe/internal/cst"
"likedream-goframe/internal/utils"
"strings"
+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
}
@@ -154,7 +161,7 @@ func (c *CpdailyCollectionTask) QueryFormByTitle(ctx context.Context, titleGlob
}
if matchTask == nil {
utils.OkOrPanic(errors.NewBusinessError(404, fmt.Sprintf("未找到表单信息: %s", titleGlob)), func(err error) error {
utils.OkOrPanic(errors.NewBusinessError(503, fmt.Sprintf("未找到表单信息: %s", titleGlob)), func(err error) error {
return oops.With("host", c.host).
In("CpdailyCollectionTask.QueryFormByTitle").
Wrap(err)
@@ -189,7 +196,7 @@ func (c *CpdailyCollectionTask) QueryFormByTitle(ctx context.Context, titleGlob
detailDatas := detailJSON["datas"].MapStrVar()
if len(detailDatas) == 0 {
utils.OkOrPanic(errors.NewBusinessError(404, "未找到表单数据"), func(err error) error {
utils.OkOrPanic(errors.NewBusinessError(503, "未找到表单数据"), func(err error) error {
return oops.With("host", c.host).
In("CpdailyCollectionTask.QueryFormByTitle").
With("titleGlob", titleGlob).
@@ -223,7 +230,7 @@ func (c *CpdailyCollectionTask) QueryFormByTitle(ctx context.Context, titleGlob
formDatas := formJSON["datas"].MapStrVar()
if len(formDatas) == 0 {
utils.OkOrPanic(errors.NewBusinessError(404, "未找到表单数据"), func(err error) error {
utils.OkOrPanic(errors.NewBusinessError(503, "未找到表单数据"), func(err error) error {
return oops.With("host", c.host).
In("CpdailyCollectionTask.QueryFormByTitle").
With("titleGlob", titleGlob).
+31 -27
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
}
@@ -140,8 +147,8 @@ func (c *CpdailyAutoSignTask) QueryFormByTitle(ctx context.Context, titleGlob st
findMatchTitle := func(jsonArr []any) map[string]*gvar.Var {
for _, rawJson := range jsonArr {
item, ok := rawJson.(map[string]*gvar.Var)
if !ok {
item := gvar.New(rawJson).MapStrVar()
if len(item) == 0 {
continue
}
taskName, exist := item["taskName"]
@@ -171,7 +178,7 @@ func (c *CpdailyAutoSignTask) QueryFormByTitle(ctx context.Context, titleGlob st
if matchTask == nil {
matchTask = findMatchTitle(signedTasks)
if matchTask == nil {
utils.OkOrPanic(errors.NewBusinessError(404, fmt.Sprintf("任务未找到: %s", titleGlob)), func(err error) error {
utils.OkOrPanic(errors.NewBusinessError(503, fmt.Sprintf("任务未找到: %s", titleGlob)), func(err error) error {
return oops.With("host", c.host).
In("CpdailyAutoSignTask.QueryFormByTitle").
Wrap(err)
@@ -203,7 +210,7 @@ func (c *CpdailyAutoSignTask) QueryFormByTitle(ctx context.Context, titleGlob st
formDatas := detailResponseJSON["datas"].MapStrVar()
if len(formDatas) == 0 {
utils.OkOrPanic(errors.NewBusinessError(404, "任务数据为空"), func(err error) error {
utils.OkOrPanic(errors.NewBusinessError(503, "任务数据为空"), func(err error) error {
return oops.With("host", c.host).
In("CpdailyAutoSignTask.QueryFormByTitle").
With("titleGlob", titleGlob).
@@ -286,7 +293,7 @@ func (c *CpdailyAutoSignTask) QueryFormByYearMonth(ctx context.Context, titleGlo
if matchTask == nil {
matchTask = findMatchTitle(signedTasks)
if matchTask == nil {
utils.OkOrPanic(errors.NewBusinessError(404, fmt.Sprintf("任务未找到: %s", titleGlob)), func(err error) error {
utils.OkOrPanic(errors.NewBusinessError(503, fmt.Sprintf("任务未找到: %s", titleGlob)), func(err error) error {
return oops.
With("host", c.host).
With("year", year).
@@ -325,7 +332,7 @@ func (c *CpdailyAutoSignTask) QueryFormByYearMonth(ctx context.Context, titleGlo
formDatas := detailResponseJSON["datas"].MapStrVar()
if len(formDatas) == 0 {
utils.OkOrPanic(errors.NewBusinessError(404, "任务数据为空"), func(err error) error {
utils.OkOrPanic(errors.NewBusinessError(503, "任务数据为空"), func(err error) error {
return oops.
With("host", c.host).
With("year", year).
@@ -372,23 +379,19 @@ func (c *CpdailyAutoSignTask) ParseFormJson(ctx context.Context, rawJson map[str
dto = &formtype.CpTaskFormItem{
Title: "签到具体地址",
ColName: "address",
Type: formtype.ItemTypeAddress,
Type: formtype.ItemTypeInput,
Required: true,
}
list = append(list, dto)
var current uint
if isPhoto := rows["isPhoto"]; isPhoto != nil && isPhoto.Int() == 1 {
dto = &formtype.CpTaskFormItem{
Title: "签到照片",
ColName: "signImg",
Type: formtype.ItemTypeImage,
Required: true,
Number: current,
}
list = append(list, dto)
current++
}
// 是否范围外签到
@@ -397,7 +400,6 @@ func (c *CpdailyAutoSignTask) ParseFormJson(ctx context.Context, rawJson map[str
ColName: "isMalposition",
Type: formtype.ItemTypeSingle,
Required: true,
Number: current,
Options: []formtype.CpTaskFormItemOption{
{
Content: "是",
@@ -411,7 +413,6 @@ func (c *CpdailyAutoSignTask) ParseFormJson(ctx context.Context, rawJson map[str
},
}
list = append(list, dto)
current++
// 范围外签到原因
dto = &formtype.CpTaskFormItem{
@@ -420,16 +421,15 @@ func (c *CpdailyAutoSignTask) ParseFormJson(ctx context.Context, rawJson map[str
Type: formtype.ItemTypeInput,
Required: true,
LogicWid: "abnormalReason",
Number: current,
}
list = append(list, dto)
current++
current := uint(1)
// 处理额外字段
if isNeedExtra := rows["isNeedExtra"]; isNeedExtra != nil && isNeedExtra.Int() == 1 {
extraField := rows["extraField"].Array()
for i, field := range extraField {
fieldObj := field.(map[string]*gvar.Var)
for _, field := range extraField {
fieldObj := gvar.New(field).MapStrVar()
title := fieldObj["title"].String()
isRequired := fieldObj["isRequired"].Bool()
hasOtherItems := fieldObj["hasOtherItems"].Bool()
@@ -438,16 +438,17 @@ func (c *CpdailyAutoSignTask) ParseFormJson(ctx context.Context, rawJson map[str
Title: title,
ColName: title,
Type: formtype.ItemTypeSingle,
Number: uint(i),
Number: current,
Required: isRequired,
IsOther: hasOtherItems,
}
current++
// 处理选项
extraFieldItems := fieldObj["extraFieldItems"].Array()
var options []formtype.CpTaskFormItemOption
for _, item := range extraFieldItems {
itemObj := item.(map[string]*gvar.Var)
itemObj := gvar.New(item).MapStrVar()
option := formtype.CpTaskFormItemOption{
Content: itemObj["content"].String(),
IsOtherItems: itemObj["isOtherItems"].Bool(),
@@ -532,7 +533,7 @@ func (c *CpdailyAutoSignTask) FillCustomForm(ctx context.Context, form map[strin
previewUrl := imageuploader.UploadImageFromStorage(ctx, c.host, imageId, types.TaskTypeSign, c.client)
resultForm["signImg"] = gvar.New(previewUrl)
resultForm["signPhotoUrl"] = gvar.New(previewUrl)
}
// 处理验证码
@@ -547,7 +548,9 @@ func (c *CpdailyAutoSignTask) FillCustomForm(ctx context.Context, form map[strin
ticket = submitCaptchaResolver.GetCaptchaTicket(ctx, captchaInfo)
})
}, retry.MaxDelay(15*time.Second), retry.Attempts(5), retry.Context(ctx))
utils.OkOrPanic(errors.NewBusinessError(503, "提交验证码识别失败").WithInnerError(e), oops.WithContext(ctx).Wrap)
if e != nil {
utils.OkOrPanic(errors.NewBusinessError(503, "提交验证码识别失败").WithInnerError(e), oops.WithContext(ctx).Wrap)
}
resultForm["ticket"] = gvar.New(ticket)
} else {
@@ -570,8 +573,9 @@ func (c *CpdailyAutoSignTask) FillCustomForm(ctx context.Context, form map[strin
var extraFieldItemValues []map[string]*gvar.Var
for i, field := range extraField {
current := uint(i + 1)
// 检查数字是否在范围内
found := slices.Contains(numbers, uint(i))
found := slices.Contains(numbers, current)
if !found {
utils.OkOrPanic(errors.NewBusinessError(500, "非法的额外信息数据"), oops.WithContext(ctx).Wrap)
}
@@ -579,7 +583,7 @@ func (c *CpdailyAutoSignTask) FillCustomForm(ctx context.Context, form map[strin
// 找到对应的参数
var targetParam *formtype.CpTaskFormItem
for _, v := range paramList {
if v.Number == uint(i) {
if v.Number == current {
targetParam = v
break
}
@@ -589,7 +593,7 @@ func (c *CpdailyAutoSignTask) FillCustomForm(ctx context.Context, form map[strin
continue
}
fieldObj := field.(map[string]*gvar.Var)
fieldObj := gvar.New(field).MapStrVar()
fieldTitle := fieldObj["title"].String()
if targetParam.Title != fieldTitle {
@@ -600,7 +604,7 @@ func (c *CpdailyAutoSignTask) FillCustomForm(ctx context.Context, form map[strin
var extraFieldItemValue map[string]*gvar.Var
for _, item := range extraFieldItems {
itemObj := item.(map[string]*gvar.Var)
itemObj := gvar.New(item).MapStrVar()
content := itemObj["content"].String()
if content == targetParam.Content {
+26 -17
View File
@@ -10,8 +10,8 @@ import (
"likedream-goframe/internal/application/cpdaily/task/formtype"
"likedream-goframe/internal/application/cpdaily/taskhelper"
"likedream-goframe/internal/application/cpdaily/types"
"likedream-goframe/internal/common/cst"
"likedream-goframe/internal/common/errors"
"likedream-goframe/internal/cst"
"likedream-goframe/internal/utils"
"math/rand/v2"
"strconv"
@@ -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
}
@@ -180,7 +190,11 @@ func (c *CpdailySleepCheckTask) QueryFormByTitle(ctx context.Context, titleGlob
SetBody(map[string]any{}).
WithContext(ctx).
Post(c.getReqUrl("getStuAttendacesInOneDay"))
//
response, err = c.client.R().
SetBody(map[string]any{}).
WithContext(ctx).
Post(c.getReqUrl("getStuAttendacesInOneDay"))
utils.OkOrPanic(err, func(err error) error {
return oops.With("host", c.host).
In("CpdailySleepCheckTask.QueryFormByTitle").
@@ -449,18 +463,15 @@ func (c *CpdailySleepCheckTask) ParseFormJson(ctx context.Context, rawJson map[s
}
list = append(list, dto)
var current uint = 1
if isPhoto := rows["isPhoto"]; isPhoto != nil && isPhoto.Int() == 1 {
dto = &formtype.CpTaskFormItem{
Title: "查寝照片",
ColName: "signImg",
Type: formtype.ItemTypeImage,
Required: true,
Number: current,
}
list = append(list, dto)
current++
}
// 是否范围外签到
@@ -469,7 +480,6 @@ func (c *CpdailySleepCheckTask) ParseFormJson(ctx context.Context, rawJson map[s
ColName: "isMalposition",
Type: formtype.ItemTypeSingle,
Required: true,
Number: current,
Options: []formtype.CpTaskFormItemOption{
{
Content: "是",
@@ -483,7 +493,6 @@ func (c *CpdailySleepCheckTask) ParseFormJson(ctx context.Context, rawJson map[s
},
}
list = append(list, dto)
current++
for key, item := range list {
list[key].Show = item.LogicWid == ""
@@ -519,7 +528,8 @@ func (c *CpdailySleepCheckTask) FillCustomForm(ctx context.Context, form map[str
resultForm["uaIsCpadaily"] = gvar.New(true)
// 处理验证码
submitCaptchaResolver := submitcaptcha.NewRuoliResolver(c.client, c.host, deviceId, types.TaskTypeSleepCheck)
//submitCaptchaResolver := submitcaptcha.NewRuoliResolver(c.client, c.host, deviceId, types.TaskTypeSleepCheck)
submitCaptchaResolver := submitcaptcha.NewAIResolver(c.client, c.host, deviceId, types.TaskTypeSleepCheck)
captchaInfo := submitCaptchaResolver.GetValidationInfo(ctx)
if captchaInfo.Validation {
@@ -529,9 +539,10 @@ func (c *CpdailySleepCheckTask) FillCustomForm(ctx context.Context, form map[str
return utils.Catch(func() {
ticket = submitCaptchaResolver.GetCaptchaTicket(ctx, captchaInfo)
})
}, retry.MaxDelay(15*time.Second), retry.Attempts(5), retry.Context(ctx))
utils.OkOrPanic(errors.NewBusinessError(503, "提交验证码识别失败").WithInnerError(e), oops.WithContext(ctx).Wrap)
}, retry.Delay(15*time.Second), retry.Attempts(5), retry.Context(ctx))
if e != nil {
utils.OkOrPanic(errors.NewBusinessError(503, "提交验证码识别失败").WithInnerError(e), oops.WithContext(ctx).Wrap)
}
resultForm["ticket"] = gvar.New(ticket)
} else {
resultForm["ticket"] = gvar.New("")
@@ -575,7 +586,7 @@ func (c *CpdailySleepCheckTask) FillCustomForm(ctx context.Context, form map[str
previewUrl := imageuploader.UploadImageFromStorage(ctx, c.host, imageId, types.TaskTypeSleepCheck, c.client)
resultForm["signImg"] = gvar.New(previewUrl)
resultForm["signPhotoUrl"] = gvar.New(previewUrl)
}
// 判断是否存在二维码查寝
@@ -595,9 +606,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 参数
@@ -664,9 +675,7 @@ 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).
+2 -1
View File
@@ -2,8 +2,9 @@ package filestorage
import (
"context"
"likedream-goframe/internal/common/cst"
"github.com/gogf/gf/v2/frame/g"
"likedream-goframe/internal/cst"
)
var GlobalS3 *S3
+13 -1
View File
@@ -1,6 +1,8 @@
package httpclient
import (
"crypto/tls"
"likedream-goframe/internal/utils"
"time"
"resty.dev/v3"
@@ -10,4 +12,14 @@ var Cpdaily = resty.New().
SetCookieJar(nil).
SetTimeout(30 * time.Second).
SetDoNotParseResponse(true).
SetProxy("http://127.0.0.1:9000")
SetTLSClientConfig(&tls.Config{
InsecureSkipVerify: true,
})
func init() {
if !utils.IsDebug() {
Cpdaily.SetDebug(false)
} else {
Cpdaily.SetProxy("http://127.0.0.1:9000")
}
}
+15
View File
@@ -0,0 +1,15 @@
package httpclient
import (
"crypto/tls"
"time"
"resty.dev/v3"
)
var Music = resty.New().
SetCookieJar(nil).
SetTimeout(3 * time.Minute).
SetTLSClientConfig(&tls.Config{
InsecureSkipVerify: true,
})
@@ -0,0 +1,26 @@
package httpclient
import (
"crypto/tls"
"likedream-goframe/internal/application/cookiejar"
"likedream-goframe/internal/utils"
"time"
"resty.dev/v3"
)
var Xuexitong = resty.New().
SetCookieJar(cookiejar.NewAllSavePersistCookieJar()).
SetRedirectPolicy(resty.FlexibleRedirectPolicy(20)).
SetTimeout(30 * time.Second).
SetTLSClientConfig(&tls.Config{
InsecureSkipVerify: true,
})
func init() {
if !utils.IsDebug() {
Xuexitong.SetDebug(false)
} else {
Xuexitong.SetProxy("http://127.0.0.1:9000")
}
}
+68
View File
@@ -0,0 +1,68 @@
package music
import (
"context"
"likedream-goframe/internal/application/httpclient"
"likedream-goframe/internal/common/errors"
"likedream-goframe/internal/utils"
"net/url"
"regexp"
"strings"
"github.com/PuerkitoBio/goquery"
"github.com/samber/oops"
"github.com/tidwall/gjson"
)
var MusicDownloader *Downloader
type Downloader struct {
}
func (c *Downloader) Search(ctx context.Context, keyword string) (result []MusicSearchResult) {
client := httpclient.Music.Clone(ctx)
response, err := client.R().Get("https://www.gequbao.net/s/" + url.PathEscape(keyword))
if err != nil {
utils.OkOrPanic(errors.NewBusinessError(503, "搜索出错1"), oops.WithContext(ctx).Wrap)
}
defer response.Body.Close()
reader, err := goquery.NewDocumentFromReader(response.Body)
if err != nil {
utils.OkOrPanic(errors.NewBusinessError(503, "搜索出错2"), oops.WithContext(ctx).Wrap)
}
card := reader.Find(".card")
find := card.Find(".card-text > .row:not(:first-child)")
find.Each(func(i int, item *goquery.Selection) {
selection := item.Find("a")
url, _ := selection.Attr("href")
name := strings.TrimSpace(selection.Find(".text-primary span").Text())
singer := strings.TrimSpace(selection.Find(".text-jade").Text())
result = append(result, MusicSearchResult{
Name: name,
Singer: singer,
Path: url,
})
})
return
}
func (c *Downloader) Download(ctx context.Context, url string) string {
client := httpclient.Music.Clone(ctx)
response, err := client.R().Get("https://www.gequbao.net" + url)
if err != nil {
utils.OkOrPanic(errors.NewBusinessError(503, "下载出错1"), oops.WithContext(ctx).Wrap)
}
html := response.String()
reg := regexp.MustCompile("window\\.play_id = '(.*?)';")
play_id := reg.FindStringSubmatch(html)[1]
post, err := client.R().SetBody(map[string]string{
"id": play_id,
}).Post("https://www.gequbao.net/api/play-url")
if err != nil {
utils.OkOrPanic(errors.NewBusinessError(503, "下载出错2"), oops.WithContext(ctx).Wrap)
}
download_url := gjson.Get(post.String(), "data.url").String()
// 下载音频文件
return download_url
}
+7
View File
@@ -0,0 +1,7 @@
package music
type MusicSearchResult struct {
Name string `json:"name"`
Singer string `json:"singer"`
Path string `json:"url"`
}
@@ -20,12 +20,6 @@ type ImageClassifier struct {
// NewImageClassifier 创建新的图片分类器
func NewImageClassifier(modelPath, classesPath string) (*ImageClassifier, error) {
// 初始化ONNX Runtime
err := ort.InitializeEnvironment()
if err != nil {
return nil, fmt.Errorf("初始化ONNX Runtime失败: %v", err)
}
// 加载类别名称
classes, err := loadClasses(classesPath)
if err != nil {
@@ -1,8 +1,6 @@
package classifier
var imageClassifier, err = NewImageClassifier("./static/model.onnx", "./static/classes.txt")
// 图片数据 & 类别名称
// ClassifyImage 图片数据 & 类别名称
// return 是否匹配
func ClassifyImage(imgData []byte, className string) bool {
name, _, _ := imageClassifier.PredictFromBytes(imgData)
@@ -0,0 +1,53 @@
package classifier
import (
"embed"
_ "embed"
"likedream-goframe/internal/application/recognizer"
"likedream-goframe/internal/framework/logger"
"likedream-goframe/internal/utils"
"os"
"path/filepath"
"strings"
"go.uber.org/zap"
)
//go:embed static/*
var fs embed.FS
var imageClassifier *ImageClassifier
func init() {
if !recognizer.OnnxIsInit {
recognizer.InitOnnx()
}
modelPath, classesPath := initModel()
classifier, err := NewImageClassifier(modelPath, classesPath)
if err != nil {
logger.Logger.Panic("初始化ai模型失败", zap.Error(err))
}
imageClassifier = classifier
}
func initModel() (modelPath, classesPath string) {
// 检测文件是否存在
exePath := strings.ToLower(os.Args[0])
// 获取绝对路径
absPath, _ := filepath.Abs(exePath)
staticPath := filepath.Join(filepath.Dir(absPath), "static")
if _, err := os.Stat(staticPath); os.IsNotExist(err) {
os.Mkdir(staticPath, 0755)
}
modelPath = filepath.Join(staticPath, "model.onnx")
modelBytes, err := fs.ReadFile("static/model.onnx")
utils.OkOrPanic(err)
if _, err := os.Stat(modelPath); os.IsNotExist(err) {
os.WriteFile(modelPath, modelBytes, 0644)
}
classesPath = filepath.Join(staticPath, "classes.txt")
classesBytes, err := fs.ReadFile("static/classes.txt")
utils.OkOrPanic(err)
if _, err := os.Stat(classesPath); os.IsNotExist(err) {
os.WriteFile(classesPath, classesBytes, 0644)
}
return
}
@@ -0,0 +1,109 @@
package ddddocr
import (
"fmt"
"regexp"
"strings"
"github.com/thedevsaddam/gojsonq"
ort "github.com/yalue/onnxruntime_go"
"image"
"log"
"strconv"
)
// SemiOCRVerification 半自动验证码识别(要自己传入outputShape值)
func SemiOCRVerification(img image.Image, outputShape ort.Shape) string {
img1 := ResizeImage(img, uint(64*img.Bounds().Dx()/img.Bounds().Dy()), 64)
imgGray := ConvertToGray(img1)
inputData := ImageToGrayFloatArray(imgGray)
inputShape := ort.NewShape(1, 1, 64, int64(imgGray.Bounds().Dx()))
inputTensor, err := ort.NewTensor[float32](inputShape, inputData)
if err != nil {
panic(err)
}
defer inputTensor.Destroy()
// This hypothetical network maps a 2x5 input -> 2x3x4 output.
outputTensor, err := ort.NewEmptyTensor[int64](outputShape)
defer outputTensor.Destroy()
onnxPath := initModel()
session, err := ort.NewAdvancedSession(onnxPath,
[]string{"input1"}, []string{"output"},
[]ort.Value{inputTensor}, []ort.Value{outputTensor}, nil)
defer session.Destroy()
if err != nil {
log.Fatal(err)
}
err = session.Run()
if err != nil {
fmt.Errorf(err.Error())
}
outputData := outputTensor.GetData()
codeResult := ""
for i := 0; i < len(outputData); i++ {
if outputData[i] != 0 {
codeResult += gojsonq.New().JSONString(getCharCode()).Find("[" + strconv.Itoa(int(outputData[i])) + "]").(string)
}
}
return codeResult
}
// AutoOCRVerification 全自动
func AutoOCRVerification(img image.Image) string {
img1 := ResizeImage(img, uint(64*img.Bounds().Dx()/img.Bounds().Dy()), 64)
imgGray := ConvertToGray(img1)
inputData := ImageToGrayFloatArray(imgGray)
inputShape := ort.NewShape(1, 1, 64, int64(imgGray.Bounds().Dx()))
inputTensor, err := ort.NewTensor[float32](inputShape, inputData)
if err != nil {
panic(err)
}
defer inputTensor.Destroy()
var outputShape = ort.NewShape(1, 16)
codeResult := ""
//失败一次获取输出纬度
for {
outputTensor, err := ort.NewEmptyTensor[int64](outputShape)
defer outputTensor.Destroy()
onnxPath := initModel()
session, err := ort.NewAdvancedSession(onnxPath,
[]string{"input1"}, []string{"output"},
[]ort.Value{inputTensor}, []ort.Value{outputTensor}, nil)
defer session.Destroy()
if err != nil {
log.Fatal(err)
}
err1 := session.Run()
if err1 != nil {
if strings.Contains(err1.Error(), "OrtValue shape verification failed. Current shape:") {
regex := regexp.MustCompile(`Requested shape:{(\d+),(\d+)}`)
matches := regex.FindStringSubmatch(err1.Error())
if len(matches) == 3 {
c1, _ := strconv.Atoi(matches[1])
c2, _ := strconv.Atoi(matches[2])
outputShape = ort.NewShape(int64(c1), int64(c2))
continue
}
}
fmt.Errorf(err1.Error())
return codeResult
}
outputData := outputTensor.GetData()
for i := 0; i < len(outputData); i++ {
if outputData[i] != 0 {
codeResult += gojsonq.New().JSONString(getCharCode()).Find("[" + strconv.Itoa(int(outputData[i])) + "]").(string)
}
}
break
}
return codeResult
}
@@ -0,0 +1,870 @@
package ddddocr
// 获取映射字符串
func getCharCode() string {
return `["", "掀", "袜", "顧", "徕", "榱", "荪", "浡", "其", "炎", "玉", "恩", "劣", "徽", "廉", "桂", "拂",
"鳊", "撤",
"赏", "哮", "侄", "蓮", "И", "进", "饭", "饱", "优", "楸", "礻", "蜉", "營", "伙", "杌", "修", "榜",
"准", "铒",
"戏", "赭", "襟", "彘", "彩", "雁", "闽", "坎", "聂", "氡", "辜", "苁", "潆", "摁", "月", "稇", "而",
"醴", "簉",
"卑", "妖", "埽", "嘡", "醛", "見", "煎", "汪", "秽", "迄", "噭", "焉", "钌", "瑕", "玻", "仙", "蹑",
"钀", "翦",
"丰", "矗", "2", "胚", "镊", "镡", "鍊", "帖", "僰", "淀", "吒", "冲", "挡", "粼", "螈", "缵", "孺",
"侦", "曷",
"渐", "敷", "投", "宸", "祉", "柳", "尖", "梃", "淘", "臁", "躇", "撖", "惭", "狄", "聢", "官", "狴",
"诬", "骄",
"跻", "場", "姻", "钎", "藥", "綉", "驾", "舻", "黢", "鲦", "蜣", "渖", "绹", "佰", "怜", "三", "痪",
"眍", "养",
"角", "薜", "濑", "劳", "戟", "傎", "纫", "徉", "收", "稍", "虫", "螋", "鬲", "捌", "陡", "蓟", "邳",
"蹢", "涉",
"煋", "端", "懷", "椤", "埶", "廊", "免", "秫", "猢", "睐", "臺", "擀", "布", "麃", "彗", "汊", "芄",
"遣", "胙",
"另", "癯", "徭", "疢", "茆", "忡", "'", "烃", "笕", "薤", "肆", "熛", "過", "盖", "跷", "呷", "痿",
"沖", "魍",
"讣", "庤", "弑", "诩", "庵", "履", "暮", "始", "滟", "矅", "蛹", "鸿", "啃", "铋", "沿", "鐾", "酆",
"團", "恙",
"閥", "聒", "讵", "颠", "沾", "堅", "踣", "陴", "覃", "滙", "浐", "钇", "脆", "炙", "亮", "觌", "産",
"汩", "鸭",
"斄", "堆", "掭", "揞", "鹂", "郫", "瘅", "蚂", "揩", "学", "组", "浸", "腙", "耀", "嗛", "局", "蠓",
"肠", "昏",
"I", "岑", "镯", "憧", "油", "泸", "鸟", "潇", "蕻", "褒", "瞧", "旸", "昭", "庐", "鞒", "内", "痈",
"己", "曙",
"怠", "锟", "晞", "耢", "鲢", "醦", "糕", "療", "寇", "梵", "黾", "呻", "苒", "ü", "校", "嘏", "昃",
"Ⅰ", "蕰",
"凖", "嵛", "裨", "筏", "匜", "咋", "乏", "婵", "镂", "珰", "感", "蔗", "蚵", "庞", "弢", "槟", "口",
"漉", "﹒",
"咂", "俩", "增", "硐", "襙", "绉", "卿", "距", "璱", "猖", "铚", "郚", "嬖", "缒", "阃", "扞", "V",
"望", "最",
"浔", "骜", "赃", "闻", "砍", "奸", "灶", "以", "获", "鳎", "浦", "罐", "孓", "纭", "瘀", "普", "氰",
"塮", "症",
"顷", "们", "螓", "蛸", "鵰", "册", "美", "萨", "沘", "犰", "嫌", "名", ")", "懦", "滇", "F", "垡",
"声", "毅",
"隅", "鲎", "煨", "萦", "宜", "唇", "鯨", "邛", "杲", "赜", "长", "魂", "桠", "锇", "搓", "俘", "仰",
"膘", "宦",
"歹", "遁", "猃", "噉", "幂", "糜", "嗤", "周", "剂", "曦", "暧", "焖", "髻", "釐", "泰", "窟", "檎",
"旧", "犀",
"镄", "百", "取", "岍", "逗", "叽", "呃", "鲪", "萬", "陈", "7", "習", "区", "逄", "宏", "罡", "漭",
"盗", "郿",
"般", "谢", "倪", "纵", "婶", "砧", "揖", "扪", "濒", "愤", "茓", "浞", "子", "揄", "旌", "趄", "樊",
"醑", "遄",
"婚", "汶", "矩", "裈", "弊", "呱", "铳", "勿", "蚴", "忿", "褓", "缚", "酱", "璞", "庆", "除", "礌",
"珩", "榨",
"鼢", "逞", "容", "圯", "猛", "陌", "-", "嚯", "镘", "鱾", "睚", "猬", "杜", "鳓", "燈", "計", "咣",
"炜", "睁",
"箱", "邮", "略", "馇", "逐", "雀", "僬", "髯", "奖", "俱", "-", "绗", "犏", "辱", "忑", "挽", "康",
"蝼", "栏",
"模", "辒", "•", "儋", "罱", "墈", "会", "秀", "栈", "缔", "醜", "蚣", "阮", "鼗", "眼", "湧", "沁",
"夥", "毕",
"媚", "瘳", "痣", "搴", "闿", "遍", "焰", "岣", "舱", "埌", "麿", "嘿", "靽", "体", "想", "霓", "钛",
"摽", "苑",
"芳", "技", "綮", "钅", "燠", "栾", "年", "悱", "腹", "员", "呕", "闇", "嗫", "檩", "荒", "溱", "舨",
"峙", "卒",
"洑", "预", "弯", "蔷", "叵", "锯", "慈", "牧", "患", "贇", "偷", "鲜", "锓", "躔", "嚬", "烈", "娌",
"嘲", "详",
"麺", "舒", "厨", "徵", "葹", "只", "篦", "鹀", "剕", "驳", "聍", "黧", "砾", "暅", "褫", "呈", "森",
"结", "龛",
"钲", "轧", "扔", "蕹", "赵", "涒", "冯", "渲", "缭", "坚", "趼", "鲑", "倫", "门", "班", "垚", "鞍",
"菘", "畐",
"僇", "侉", "禢", "轳", "饦", "兽", "呯", "捂", "樨", "卧", "栝", "豭", "冶", "鉰", "申", "蜈", "印",
"缨", "镫",
"蕾", "圜", "扑", "娉", "烦", "缳", "广", "峄", "獒", "铔", "奁", "醚", "倥", "蹇", "阚", "镆", "煺",
"德", "颉",
"嗅", "绷", "蒯", "祺", "崧", "往", "枨", "涡", "鲲", "瓅", "岌", "肘", "飔", "缘", "千", "棱", "溶",
"窣", "篼",
"代", "捡", "送", "咡", "术", "滑", "茜", "晾", "挤", "曳", "糈", "G", "翊", "殴", "妹", "溥", "璆",
"烩", "拙",
"襄", "几", "嘴", "D", "驮", "淙", "蹐", "合", "環", "剑", "怪", "褂", "畑", "燏", "订", "珪", "≥",
"瘟", "耷",
"槑", "衷", "猕", "迁", "霎", "槜", "﹖", "鋈", "苹", "嫣", "祜", "李", "鄒", "噢", "萄", "仝", "纨",
"直", "悛",
"拣", "远", "诏", "圧", "躬", "蝟", "總", "眆", "筻", "硇", "鳁", "眠", "钆", "泞", "猱", "宾", "酞",
"募", "螳",
"腴", "念", "宠", "唯", "怊", "勃", "M", "兿", "蟑", "妁", "掸", "拌", "铸", "讼", "诟", "锺", "Ω",
"竟", "羚",
"剽", "C", "苦", "煳", "罢", "跨", "~", "豸", "±", "俬", "捺", "彦", "钣", "鋆", "用", "缤", "搁",
"徼", "谦",
"筘", "嗨", "扮", "旇", "折", "咯", "昆", "叟", "垂", "箐", "捻", "燕", "島", "瞀", "鮮", "屡", "點",
"瘭", "恚",
"旚", "丟", "捽", "菁", "瀑", "炕", "蹩", "芒", "r", "是", "媾", "鹝", "囵", "萤", "拷", "频", "埴",
"课", "癍",
"袱", "螯", "谘", "榛", "Y", "缣", "裔", "憩", "相", "觀", "晗", "坳", "炔", "勉", "汆", "钡", "舐",
"衫", "疫",
"鲙", "蘩", "穈", "殁", "九", "泻", "咤", "構", "谆", "陕", "装", "蔡", "画", "介", "苋", "務", "敝",
"俟", "帇",
"鸺", "贸", "茗", "肃", "滪", "输", "瘗", "菽", "饹", "诉", "遐", "浑", "扎", "卟", "铀", "邗", "觋",
"嘎", "塑",
"潏", "金", "姘", "潋", "逵", "鲻", "逯", "炮", "甄", "髡", "剩", "嗬", "芴", "屋", "改", "骣", "芪",
"邠", "痋",
"珑", "帆", "狙", "八", "奔", "族", "轵", "氖", "雕", "痧", "眊", "胛", "酉", "鲼", "砣", "猸", "餮",
"郇", "沫",
"跖", "蝉", "屑", "辘", "閣", "涑", "邡", "篃", "交", "笼", "颇", "贻", "魄", "黡", "劂", "糠", "炅",
"帨", "苍",
"瓴", "粤", "莎", "朿", "埔", "绸", "齁", "鱿", "惨", "腢", "郡", "棠", "猫", "脑", "風", "蚱", "捐",
"嵌", "胱",
"馗", "竽", "泥", "辍", "怖", "雾", "絮", "淼", "筝", "碲", "悼", "龀", "の", "珥", "忐", "溲", "昕",
"荔", "掂",
"瘦", "僭", "蔌", "抺", "椅", "誉", "扯", "僜", "停", "衉", "汇", "赔", "眄", "呙", "咙", "剿", "次",
"蛟", "嗓",
"』", "汕", "詈", "帘", "踧", "姁", "血", "堪", "喜", "滩", "璎", "胄", "俨", "眚", "凌", "拽", "滔",
"⑿", "嬃",
"―", "汐", "潭", "阡", "呓", "婷", "执", "妊", "恂", "妥", "鳘", "蔫", "设", "睒", "笪", "謇", "鞋",
"谍", "黯",
"虍", "馬", "蚧", "骑", "峤", "舾", "儀", "駡", "β", "蓑", "柏", "痒", "蒇", "痕", "妍", "熠", "僻",
"爬", "迭",
"畫", "绰", "湯", "凭", "菼", "懈", "顒", "午", "箪", "糙", "址", "钼", "堵", "佘", "侍", "卤", "(",
"榚", "泽",
"溘", "蟹", "b", "燁", "颂", "菠", "榉", "鲡", "埸", "荛", "歘", "断", "邸", "贡", "礞", "蔼", "脸",
"爪", "帜",
"翡", "仟", "皎", "辆", "滫", "昔", "™", "柬", "弓", "遇", "杪", "侨", "娓", "镪", "觑", "一", "踌",
"牟", "褡",
"厩", "晌", "每", "娘", "渤", "c", "咫", "成", "颏", "孩", "鼓", "瞌", "槁", "捒", "阉", "伉", "癣",
"胞", "鲟",
"瓤", "杅", "紡", "喂", "掠", "镜", "镧", "侞", "赦", "貝", "丕", "臧", "L", "池", "彷", "棓", "锽",
"渊", "食",
"饨", "堡", "玥", "氣", "讽", "敬", "闺", "帡", "携", "哫", "珈", "魆", "哄", "旁", "喻", "泄", "畎",
"郁", "唅",
"葜", "繪", "飐", "谶", "聆", "斝", "谥", "辉", "髅", "進", "吧", "蹀", "铛", "笛", "睥", "楼", "凝",
"況", "鸷",
"苠", "饺", "沙", "缴", "块", "梢", "慝", "珐", "鄏", "霰", "迸", "氆", "趵", "棣", "鳔", "祆", "☆",
"苯", "恁",
"螨", "庭", "缠", "槠", "津", "髋", "诔", "葶", "蜾", "坻", "蒹", "摔", "向", "垩", "蹭", "淇", "筛",
"滬", "玡",
"铺", "逼", "劵", "绲", "团", "鳀", "常", "玖", "擢", "株", "铵", "樽", "弭", "醇", "糨", "璈", "曩",
"潔", "祘",
"磨", "希", "鲅", "擂", "谗", "唳", "欷", "欧", "绋", "庙", "琬", "稳", "糊", "拥", "霪", "浼", "翎",
"俜", "摸",
"筚", "巯", "墼", "苫", "缩", "镚", "婪", "圹", "咚", "儿", "蒽", "婆", "鲐", "雹", "霞", "嶪", "濠",
"琉", "澌",
"媢", "禤", "摺", "掏", "矢", "艄", "围", "呸", "寺", "拤", "氐", "柝", "跎", "僖", "挢", "茨", "涮",
"缫", "撸",
"荨", "嶷", "廋", "魋", "付", "喋", "蜗", "邙", "棹", "璪", "倡", "鞭", "游", "錦", "眬", "抒", "眈",
"培", "夏",
"黔", "獐", "皋", "戛", "鲀", "垒", "耽", "纤", "漩", "铈", "握", "窝", "芋", "濞", "截", "零", "敖",
"眸", "怦",
"噎", "簋", "掳", "妣", "湃", "璠", "殄", "觞", "桅", "笋", "鲞", "踯", "傀", "犨", "抵", "疰", "暌",
"耖", "供",
"枳", "怂", "娶", "鸩", "捣", "庸", "逡", "懋", "颃", "長", "鼫", "姮", "蹈", "耵", "乂", "骐", "殇",
"膏", "仳",
"冥", "梭", "洵", "碣", "昝", "仉", "軒", "隍", "更", "な", "嵕", "拜", "粑", "鲴", "吇", "秃", "尕",
"魃", "狨",
"臛", "蟥", "胨", "注", "谁", "张", "才", "尸", "派", "矮", "洳", "舟", "溺", "锴", "寓", "籴", "夕",
"叭", "荠",
"澼", "劃", "久", "私", "炉", "娟", "麤", "稂", "河", "纴", "夺", "亏", "焙", "。", "塗", "蜩", "栌",
"渡", "薰",
"崋", "揿", "漤", "啾", "郏", "舣", "卉", "爱", "牚", "撵", "钺", "再", "企", "笺", "疾", "承", "俾",
"瞈", "邰",
"汾", "瘛", "檫", "蒎", "觅", "绀", "掎", "U", "赓", "匳", "聘", "蛤", "跤", "嗜", "洼", "歔", "弟",
"飕", "莼",
"嫉", "那", "滈", "践", "僦", "偎", "扢", "绚", "乕", "旳", "招", "饯", "®", "攸", "鞁", "囫", "铨",
"陒", "鷄",
"畀", "韨", "經", "纾", "萸", "肴", "→", "宗", "迳", "鳞", "亚", "搂", "喀", "狮", "坦", "瞥", "采",
"姝", "钳",
"□", "剌", "維", "葸", "鼩", "公", "刀", "沩", "喔", "泺", "哉", "徨", "篝", "掊", "沕", "运", "偆",
"浒", "语",
"乇", "仪", "萝", "疍", "踽", "碡", "熰", "荞", "嚓", "天", "饰", "泵", "械", "孑", "蛰", "荟", "源",
"峡", "矜",
"睬", "噬", "腆", "婉", "‘", "等", "誓", "辀", "岖", "琖", "碜", "霍", "怼", "唛", "弈", "淑", "疆",
"晴", "镴",
"鸡", "埚", "焕", "芦", "唻", "踅", "吴", "殡", "唏", "吨", "寡", "鹉", "絲", "坉", "會", "埭", "Ⅲ",
"捏", "墅",
"卓", "叙", "徇", "柜", "各", "荭", "J", "恝", "囐", "蓉", "犋", "叡", "莺", "颌", "蒸", "饸", "疋",
"玊", "兢",
"鱽", "藍", "杳", "辂", "獘", "拔", "侪", "湍", "膂", "渔", "瘊", "雉", "稁", "職", "僤", "鄳", "祁",
"稱", "I",
"裴", "锉", "曹", "鲶", "挨", "哑", "鷪", "鏠", "煞", "师", "蛲", "牁", "琅", "告", "媒", "祭", "确",
"荚", "亰",
"蝗", "阗", "歩", "疲", "f", "唣", "愛", "郾", "棍", "山", "狲", "纽", "蚡", "栂", "馓", "诊", "猴",
"喤", "来",
"继", "桎", "嬛", "骞", "邴", "暄", "贼", "昴", "廿", "克", "耔", "彤", "鹭", "葓", "骢", "龁", "鏡",
"瀚", "赅",
"韩", "譄", "榷", "殚", "膛", "须", "、", "砖", "唶", "番", "蛘", "畴", "铠", "亢", "氓", "铰", "炻",
"筫", "迢",
"兰", "玺", "砻", "积", "莜", "吸", "监", "膦", "迪", "迷", "冷", "哀", "贳", "瞄", "器", "鹡", "惺",
"徐", "酢",
"寒", "Ⓡ", "倾", "飞", "楽", "涢", "队", "舆", "赤", "璩", "戳", "殳", "掮", "舴", "蜷", "宄", "拴",
"癌", "舛",
"婀", "抟", "靡", "骍", "揸", "思", "慧", "平", "橘", "臭", "硖", "卬", "畈", "兠", "茸", "脂", "魚",
"晩", "御",
"龋", "涣", "罨", "爍", "糌", "汧", "缐", "贽", "要", "祀", "鲊", "爼", "獯", "瀣", "棋", "肈", "佣",
"娣", "柩",
"枸", "偃", "v", "唷", "劍", "榴", "槐", "漫", "洽", "蒡", "籼", "魔", "峋", "第", "歙", "萧", "谮",
"埯", "撮",
"马", "绡", "裘", "鹋", "蓬", "显", "噶", "倒", "镳", "艽", "窬", "拳", "樯", "跋", "詹", "钥", "心",
"嶽", "嚋",
"戎", "吕", "涂", "悃", "麦", "骋", "推", "箩", "硚", "匆", "村", "五", "杨", "凑", "鞫", "镰", "伥",
"诒", "纣",
"崃", "鸻", "翰", "辌", "廛", "證", "舢", "盼", "腿", "圳", "贱", "皿", "隆", "屈", "龏", "瓒", "顏",
"↓", "赈",
"煙", "窍", "韧", "壁", "莰", "箬", "蹋", "褰", "峥", "悚", "坜", "环", "回", "疼", "渍", "蝄", "东",
"臂", "坩",
"走", "痍", "或", "蜀", "熳", "蜻", "佐", "懿", "嚅", "紗", "螭", "忖", "顶", "狡", "吲", "洣", "帛",
"呶", "柞",
"柫", "酿", "粥", "琢", "呵", "踝", "榀", "呲", "價", "鼋", "欺", "此", "背", "猎", "昱", "濡", "稚",
"欠", "暇",
"茬", "牙", "迹", "尼", "氛", "膠", "缯", "娼", "骚", "姒", "鬟", "霁", "鲔", "者", "驰", "倩", "馉",
"工", "芬",
"烙", "卦", "C", "裂", "垲", "摆", "珮", "缏", "杞", "绘", "司", "如", "姞", "荆", "挖", "跗", "伍",
"氚", "钘",
"郢", "轱", "篆", "吭", "夡", "鹫", "讷", "轺", "!", "匈", "待", "聱", "黏", "海", "蹶", "趋", "鎮",
"觊", "江",
"咸", "富", "艴", "稗", "钜", "搏", "壶", "鲮", "薪", "猞", "轰", "踪", "赣", "循", "序", "噻", "若",
"裾", "许",
"癞", "吓", "判", "踔", "查", "蚀", "[", "樓", "坌", "岳", "榄", "役", "倜", "⒂", "旭", "溆", "惯",
"咀", "跫",
"选", "囱", "污", "镶", "⒁", "淠", "氮", "酯", "寅", "芼", "炊", "夯", "郪", "农", "褲", "嘬", "蹻",
"烔", "罄",
"开", "靴", "镇", "杯", "羰", "硪", "籍", "摘", "馀", "餐", "眯", "⑴", "呗", "巫", "幤", "蒤", "蒗",
"镥", "檵",
"盛", "純", "娃", "●", "耿", "巡", "婴", "槔", "i", "颊", "Ⅳ", "栅", "绅", "邘", "冉", "碧", "使",
"熨", "羞",
"扼", "漳", "觯", "楊", "励", "逑", "咄", "之", "斤", "嘣", "鹰", "媸", "鲂", "褚", "磚", "琨", "聪",
"牖", "太",
"蓍", "涫", "≤", "虽", "鸽", "燧", "褊", "聿", "壬", "然", "疚", "莲", "悴", "簃", "颓", "坠", "瞬",
"汳", "l",
"登", "瘼", "窳", "桤", "縯", "匣", "坡", "↑", "愦", "攘", "渭", "嬢", "鲰", "性", "楚", "澈", "赪",
"達", "鄯",
"罅", "帽", "茠", "底", "嫜", "奏", "浅", "荽", "楹", "鼍", "枵", "嗔", "滍", "椴", "嵩", "氤", "搠",
"两", "榔",
"树", "吝", "基", "峂", "栎", "侮", "舸", "遂", "颡", "锷", "杼", "酔", "幄", "哽", "睢", "陔", "※",
"嚆", "宬",
"宽", "髦", "笾", "保", "蹊", "榕", "咏", "椋", "丧", "裤", "骛", "逧", "弇", "崆", "樘", "疤", "鸤",
"伞", "抚",
"诎", "诵", "豢", "佳", "差", "埝", "极", "黍", "煜", "曰", "阱", "悞", "叹", "垤", "藁", "嗵", "崔",
"卫", "珂",
"憯", "蔬", "菜", "碑", "扈", "铆", "夹", "衡", "弱", "挈", "徜", "疠", "丶", "遠", "提", "斧", "炟",
"肺", "B",
"她", "晟", "谎", "邱", "粳", "酽", "爨", "鬼", "伧", "兹", "嶓", "谤", "饕", "揶", "谱", "歡", "髪",
"餍", "泳",
"郞", "谣", "汉", "褐", "非", "刽", "缅", "饴", "齐", "兴", "涯", "芫", "凡", "褶", "晡", "努", "蚶",
"彥", "皤",
"砌", "黼", "吹", "指", "㙟", "蓁", "鹜", "話", "拊", "辨", "盎", "肌", "旘", "软", "颍", "甏", "滚",
"旦", "滨",
"间", "尴", "对", "鄘", "称", "镗", "咅", "璐", "怔", "垛", "洎", "瓮", "绨", "脚", "遒", "吊", "纸",
"蹅", "经",
"泉", "武", "汀", "歪", "败", "拾", "铪", "吼", "邹", "磊", "论", "岛", "厍", "锛", "芎", "芭", "音",
"澧", "镕",
"锒", "宙", "牵", "忱", "嫔", "麯", "澉", "擐", "砥", "撞", "痴", "盹", "畿", "厾", "酸", "俑", "脽",
"鸈", "枷",
"咨", "蔹", "诂", "胰", "董", "脶", "黩", "髓", "鉵", "澎", "鲽", "梧", "樱", "诜", "鲯", "跂", "盂",
"浴", "苻",
"锅", "實", "碁", "嘛", "氕", "艮", "涟", "绢", "姿", "茝", "砘", "簿", "穷", "镃", "∈", "抽", "事",
"誜", "窅",
"瀘", "鲹", "兖", "嵎", "陧", "榍", "轶", "柿", "藤", "薏", "娆", "骷", "梅", "摒", "睪", "剪", "羸",
"忧", "邝",
"跺", "旆", "堕", "伫", "绍", "疵", "樟", "–", "绾", "蜴", "靸", "侃", "瘘", "珧", "遨", "縠", "信",
"充", "桔",
"黇", "劬", "脒", "良", "俵", "颙", "轹", "犿", "屐", "牾", "4", "兮", "澝", "汗", "沼", "铲", "濋",
"鹬", "丝",
"妫", "重", "蒺", "磲", "曚", "尔", "国", "桐", "俣", "剐", "哼", "恹", "哧", "藔", "谓", "轨", "眩",
"痞", "添",
"鬯", "库", "梱", "婕", "蜢", "贿", "敕", "泯", "羟", "龇", "垸", "左", "肖", "辎", "鞣", "谄", "可",
"腺", "末",
"狞", "贷", "嗌", "仕", "楞", "膻", "臻", "欻", "洲", "所", "檀", "抔", "罹", "牒", "仫", "芨", "柄",
"嫩", "酒",
"祙", "渠", "的", "笨", "鳐", "楡", "过", "苡", "核", "拖", "阢", "莒", "凤", "锋", "` + "`" + `", "硎", "弁",
"鬶", "朐",
"忏", "於", "昊", "剟", "咳", "湘", "日", "满", "哨", "螵", "餪", "放", "佶", "葵", "硷", "c", "抱",
"锥", "芮",
"啻", "惊", "峁", "琊", "嶲", "撺", "煅", "屏", "袗", "鄞", "梓", "鹌", "宅", "赂", "鱼", "洱", "騳",
"E", "物",
"觏", "雙", "瑀", "上", "淩", "愀", "❋", "鄙", "憝", "沛", "硫", "产", "垯", "亁", "枭", "堰", "赑",
"趾", "庹",
"腭", "迨", "拚", "晒", "蜇", "扣", "纰", "闵", "窭", "椽", "菏", "嘁", "伛", "郸", "素", "殷", "表",
"躞", "笸",
"耻", "荧", "辛", "篑", "馈", "壮", "耩", "宛", "慰", "盡", "塆", "铯", "苏", "王", "桕", "⑧", "°",
"浚", "栉",
"朘", "虚", "骆", "坂", "秤", "鲋", "蕊", "渝", "呦", "潼", "驱", "诼", "峇", "盤", "趴", "肄", "笑",
"讹", "貋",
"穂", "啼", "趟", "暽", "傣", "蜎", "挎", "陳", "勖", "戴", "旃", "瞎", "舌", "幻", "喾", "赁", "E",
"播", "诀",
"蟛", "鹛", "骶", "輸", "連", "醳", "逅", "奉", "崖", "娩", "幔", "佃", "扅", "阔", "生", "贬", "疯",
"珀", "苶",
"屯", "裣", "蹯", "蝮", "解", "陂", "疝", "茈", "帑", "议", "仲", "埙", "竺", "峰", "遮", "涎", "穸",
"阂", "潵",
"镱", "例", "荑", "u", "脎", "衍", "轲", "⑵", "虾", "颚", "钞", "²", "伴", "根", "沣", "腌", "户",
"~", "辙",
"愧", "噤", "觥", "波", "铗", "纂", "鲺", "僚", "毐", "〇", "桼", "祗", "慢", "啵", "坏", "吗", "嗞",
"甬", "曈",
"徹", "灏", "混", "渌", "括", "脖", "汝", "現", "訇", "紅", "飘", "虢", "腱", "旄", "嬴", "昨", "孀",
"蚁", "呛",
"讳", "病", ",", "喈", "蒋", "镭", "葩", "耲", "鳈", "锄", "喘", "返", "傕", "咆", "享", "枥", "瓠",
"茳", "铱",
"脘", "暹", "廒", "爝", "橹", "瞑", "铎", "岢", "叁", "翏", "捭", "賀", "悉", "帝", "芥", "牀", "闌",
"毯", "亍",
"弧", "锆", "币", "祊", "纔", "齑", "肟", "绤", "獨", "翚", "颢", "係", "鍪", "粉", "统", "诗", "娜",
"褥", "鈺",
"湔", "呤", "犸", "湨", "泣", "蟾", "犾", "烛", "斐", "朦", "室", "诨", "榭", "煦", "醺", "敞", "燮",
"糅", "衽",
"孔", "猄", "疭", "辰", "钽", "胁", "釆", "钉", "胤", "涧", "弼", "濯", "汨", "颖", "茫", "皑", "遏",
"捃", "坭",
"燴", "肩", "滞", "玢", "巽", "砺", "蜿", "毁", "億", "骥", "本", "忽", "肚", "搽", "靰", "郴", "跆",
"客", "酣",
"α", "屎", "辩", "殂", "垝", "紫", "秦", "喇", "凶", "傧", "铐", "蘊", "補", "贤", "竿", "途", "慗",
"榖", "券",
"莠", "逆", "鳇", "误", "崟", "妇", "磷", "捧", "莸", "⇋", "绺", "稻", "填", "逋", "侈", "隶", "侵",
"翥", "惘",
"惧", "鸥", "赠", "壳", "芯", "巩", "獗", "硅", "搎", "鲛", "9", "夸", "穆", "缜", "诓", "观", "薛",
"咎", "杧",
"页", "饫", "瑟", "率", "礤", "悭", "畔", "匯", "匮", "鼠", "犒", "芡", "傍", "嫂", "啸", "鄉", "哭",
"鄱", "捷",
"靺", "嚒", "嘀", "哒", "#", "拼", "钚", "魁", "霣", "眶", "郊", "死", "愁", "箭", "鼙", "签", "害",
"斛", "睑",
"蟜", "余", "墨", "様", "读", "養", "貉", "较", "浆", "翩", "徂", "冕", "铧", "列", "诈", "穝", "缑",
"纲", "志",
"舀", "甾", "举", "馁", "ä", "畹", "榼", "垢", "襁", "麟", "灭", "佴", "镩", "酝", "柒", "梯", "傈",
"萭", "悫",
"莨", "搞", "+", "兄", "偲", "攀", "曝", "嵝", "喳", "从", "遶", "撴", ".", "鄄", "欲", "挺", "娡",
"发", "速",
"胲", "褀", "态", "行", "蚓", "坼", "适", "厦", "寐", "带", "緃", "醤", "珽", "‧", "溍", "斋", "鐀",
"朝", "欢",
"传", "築", "咪", "据", "蹜", "医", "妄", "肇", "囝", "怡", "镎", "桩", "轩", "岔", "腐", "矽", "媵",
"搒", "菔",
"拘", "D", "欃", "唧", "瞒", "郈", "绦", "吟", "撝", "醉", "镣", "匝", "拎", "砒", "顸", "袁", "驼",
"愔", "实",
"國", "奧", "胩", "府", "逾", "愕", "廷", "碌", "锖", "狩", "褴", "镢", "芷", "娥", "唤", "┌", "云",
"О", "檔",
"驴", "躯", "驺", "洃", "檑", "窴", "(", "腕", "立", "楯", "齮", "〔", "漆", "k", "芍", "蹽", "鬓",
"概", "楣",
"唐", "闲", "糗", "旱", "幸", "腽", "嗄", "迂", "镠", "顿", "扥", "圃", "烜", "馍", "佝", "岷", "童",
"悦", "┐",
"铌", "袈", "靓", "骸", "和", "乔", "灸", "泓", "临", "睿", "掖", "偿", "鐘", "犁", "祓", "鈴", "搌",
"授", "鹳",
"赢", "怅", "絪", "硬", "芙", "螅", "”", "傢", "避", "裕", "歁", "全", "衰", "仃", "媛", "鬻", "跽",
"沌", "急",
"猷", "激", "巉", "哝", "渣", "笫", "跳", "螫", "熜", "Z", "筷", "佩", "啶", "萃", "頫", "荙", "出",
"孽", "钟",
"戡", "釉", "咬", "滦", "鹇", "贯", "鹮", "具", "翁", "机", "濱", "谳", "釣", "懑", "葛", "袯", "谭",
"质", "胴",
"誊", "侗", "⑩", "静", "蚜", "溋", "嫪", "嗲", "瑭", "座", "舫", "靶", "棘", "泊", "嵖", "摧", "勋",
"僡", "藉",
"疖", "巂", "随", "罾", "崚", "猹", "憨", "苘", "斓", "鼷", "利", "谲", "剔", "艺", "箓", "蛀", "鲚",
"搐", "裟",
"捶", "绌", "揪", "帮", "缥", "匍", "冀", "杻", "逛", "邑", "禾", "郰", "黜", "丘", "樂", "滌", "緣",
"胃", "苄",
"巾", "瑜", "元", "蝶", "层", "烧", "级", "岭", "蘭", "繇", "蝓", "洞", "奢", "则", "政", "矾", "啭",
"瘠", "碴",
"忤", "身", "匠", "警", "饩", "犬", "皲", "箔", "豕", "虑", "草", "喟", "芤", "逭", "艳", "幡", "姚",
"賓", "饪",
"卯", "敌", "烽", "嫚", "黝", "豺", "㭗", "教", "偕", "板", "茹", "孤", "人", "狻", "寰", "厕", "玲",
"璨", "锵",
"搛", "勍", "匾", "聃", "奘", "垃", "焓", "喽", "嫫", "貌", "瘐", "嚰", "孟", "衔", "郎", "账", "础",
"电", "黑",
"骁", "拨", "濆", "圉", "刮", "闭", "竣", "铅", "羔", "硌", "筑", "难", "管", "苕", "眺", "嫄", "竖",
"榟", "崴",
"摭", "狐", "娑", "②", "罽", "谊", "←", "狳", "铫", "凯", "狉", "9", "肪", "崤", "莊", "妨", "缶",
"滃", "瀦",
"揉", "肫", "恧", "糯", "嵬", "5", "裆", "嚷", "稣", "隐", "仂", "て", "驹", "籽", "肢", "尘", "苈",
"撷", "镲",
"趹", "晤", "唱", "鉏", "篌", "驩", "雍", "闳", "拄", "藜", "朴", "伺", "诳", "房", "吱", "Й", "鳄",
"罿", "祧",
"酩", "郅", "耎", "尜", "绝", "禅", "揠", "鎏", "慕", "麥", "呜", "鸫", "党", "尝", "砑", "牌", "踉",
"刨", "襻",
"㾄", "螽", "谌", "止", "抑", "爻", "磬", "铄", "蓠", "委", "汲", "鹑", "╱", "嚣", "彝", "穄", "穹",
"態", "醋",
"⒀", "叼", "婳", "簌", "渥", "很", "甸", "帅", "锏", "与", "樾", "泷", "棼", "湲", "越", "祥", "短",
"顼", "阘",
"宋", "馘", "鈉", "未", "囍", "浏", "叻", "箜", "鑽", "法", "曲", "淤", "僮", "做", "强", "析", "磕",
"谠", "染",
"促", "朊", "隼", "铉", "莆", "蝣", "孛", "薮", "s", "惴", "秘", "妩", "訄", "蔓", "喷", "诡", "犷",
"酐", "酇",
"刹", "壅", "甫", "史", "孃", "髌", "螬", "擤", "漏", "寞", "奡", "悢", "颔", "岁", "耄", ";", "又",
"锭", "鲤",
"癔", "杰", "孥", "酲", "蓐", "耋", "捆", "庖", "面", "鹈", "殊", "剡", "峪", "识", "锨", "归", "茴",
"—", "菤",
"汁", "攝", "液", "鼐", "示", "讠", "男", "凍", "ò", "明", "莓", "砜", "崎", "蜂", "斡", "榫", "娅",
"钪", "昙",
"胜", "欣", "怨", "◆", "粗", "秷", "节", "市", "贩", "祟", "弍", "蒟", "烁", "糧", "蠃", "編", "黙",
"壕", "戚",
"犊", "桥", "仺", "孳", "怯", "皓", "倆", "垮", "扩", "诮", "钝", "脯", "晏", "帔", "葫", "瑾", "運",
"孬", "跄",
"掣", "癜", "掌", "墀", "禇", "耸", "蜓", "鹆", "鄢", "攰", "瘢", "暝", "鸣", "峧", "遵", "笃", "畚",
"帧", "晨",
"镔", "搜", "靠", "咐", "韓", "绮", "觉", "拦", "斲", "疽", "掐", "尽", "許", "矶", "镉", "豹", "粞",
"袋", "酵",
"蛙", "戕", "劉", "髀", "彭", "玎", "囿", "郐", "善", "睃", "結", "拧", "邯", "讧", "召", "椭", "瑪",
"痼", "庼",
"反", "疱", "屠", "荣", "君", "胍", "乙", "臬", "头", "诰", "讪", "席", "晁", ":", "理", "槿", "璘",
"禧", "呢",
"蹙", "擒", "鸲", "丐", "苓", "壑", "滥", "⑾", "炗", "礴", "耕", "卅", "唿", "苛", "寵", "窖", "麻",
"蕨", "沤",
"氢", "虔", "癃", "及", "崛", "爽", "蛔", "颤", "膲", "桢", "坐", "蟞", "儇", "葚", "骤", "誤", "寝",
"嘭", "灰",
"汹", "韂", "铮", "慒", "寶", "肽", "摅", "紧", "亞", "潸", "悯", "橛", "檗", "闹", "愿", "担", "袄",
"棚", "垟",
"塄", "婞", "麈", "麸", "暗", "咦", "跞", "谡", "盈", "磐", "慎", "瘰", "掼", "憔", "研", "被", "贮",
"莛", "至",
"呀", "庑", "矫", "摛", "怃", "缙", "磺", "即", "驻", "瘤", "偏", "℃", "嫘", "癫", "汈", "鹟", "搅",
"辅", "璀",
"阊", "绻", "瑙", "蓂", "棺", "孢", "铊", "鼒", "果", "砮", "飾", "凰", "Я", "遗", "祛", "纮", "劲",
"霹", "骃",
"绔", "薅", "瀵", "垅", "?", "轻", "惇", "怕", "啥", "哙", "燎", "缆", "匡", "怫", "卞", "朋", "酏",
"阑", "爾",
"伏", "敏", "埼", "罩", "菹", "艋", "肭", "鯭", "杋", "裀", "撬", "蕺", "惠", "大", "爇", "笈", "絷",
"琳", "谫",
"诛", "糇", "袢", "倓", "髃", "觽", "埏", "寖", "個", "筴", "外", "漯", "樭", "喁", "杀", "臑", "缇",
"裸", "巅",
"毹", "茅", "忆", "琼", "唑", "烷", "项", "隋", "约", "排", "吮", "谂", "宝", "牲", "瘫", "娄", "沂",
"醫", "拭",
"纺", "蹰", "哞", "风", "霆", "值", "酺", "侠", "螾", "埂", "育", "夷", "鮼", "怍", "鸠", "Θ", "瞳",
"阇", "耥",
"羝", "伽", "洴", "記", "楔", "颼", "沪", "邢", "冰", "昀", "阙", "洌", "嫦", "杂", "仔", "芑", "潴",
"痄", "桨",
"连", "碓", "塈", "F", "昇", "何", "桦", "晥", "驵", "旋", "药", "银", "奋", "灣", "俐", "絡", "嫁",
"浮", "为",
"鞅", "科", "颦", "潽", "镍", "鸨", "粵", "骂", "拱", "韫", "盆", "赎", "尿", "钿", "坍", "唁", "秧",
"昌", "曆",
"颋", "遭", "秭", "褔", "腋", "〉", "吉", "漓", "臆", "焘", "已", "制", "钹", "鴨", "咖", "莘", "P",
"碥", "互",
"治", "标", "膝", "伪", "浿", "纛", "郗", "看", "佧", "糖", "篓", "亡", "´", "骙", "澡", "影", "窂",
"紬", "镅",
"慌", "框", "晋", "説", "丢", "凹", "卖", "巧", "蹉", "乾", "莫", "Z", "谔", "矧", "铑", "暴", "庄",
"湿", "活",
"穿", "腩", "筣", "水", "6", "琦", "迈", "伯", "洄", "抡", "▪", "酋", "荤", "雒", "粕", "簠", "菰",
"髁", "枇",
"陲", "多", "仗", "央", "滁", "胸", "梏", "痉", "姑", "襞", "﹑", "齿", "弩", "花", "吆", "赫", "岵",
"佪", "谑",
"锤", "轴", "盐", "馄", "臜", "戢", "涠", "鸸", "糟", "孪", "禁", "蒲", "化", "疏", "痰", "脾", "刈",
"應", "珍",
"膺", "扌", "廙", "汜", "牍", "虐", "婿", "啕", "彻", "赝", "陶", "蠲", ">", "位", "屁", "醍", "粢",
"挪", "臌",
"滹", "遴", "馨", "n", "稼", "徊", "酌", "轸", "债", "朰", "程", "辞", "痊", "插", "鹩", "郄", "铝",
"狱", "叱",
"同", "寄", "搪", "蚯", "魭", "舍", "旷", "闰", "涝", "民", "嗡", "苌", "馕", "姥", "屉", "啧", "枢",
"❤", "窕",
"钊", "矬", "菂", "佑", "≠", "獬", "桁", "墟", "皖", "鼻", "它", "歇", "独", "好", "晕", "蚝", "锞",
"颈", "豚",
"聖", "裉", "扫", "岿", "悒", "佥", "苗", "妞", "晚", "圭", "茼", "脲", "摊", "窠", "狸", "抻", "场",
"呼", "囟",
"噗", "狺", "困", "瀹", "削", "衬", "谰", "蛆", "訓", "鉄", "痃", "炱", "蝻", "我", "暨", "骓", "馋",
"埤", "脞",
"晃", "螟", "洮", "泛", "掾", "穑", "米", "蕲", "玦", "讙", "逢", "劐", "袭", "凫", "僳", "畛", "晷",
"鳕", "Ë",
"愬", "坫", "鳡", "鞯", "叔", "胂", "囚", "筋", "青", "度", "涕", "琰", "﹔", "径", "陇", "睛", "链",
"状", "逶",
"蘅", "“", "庇", "邽", "纥", "踶", "爺", "狭", "钫", "桃", "弛", "淳", "办", "茕", "砸", "喱", "仅",
"潞", "杈",
"得", "咕", "俞", "检", "借", "恋", "驿", "倌", "钢", "琐", "哆", "撙", "箫", "川", "猥", "牢", "蹁",
"城", "馏",
"锡", "楝", "蛱", "奈", "瑶", "桺", "耆", "翟", "阒", "稲", "橐", "萱", "惹", "蘼", "主", "擦", "蟒",
"台", "佬",
"荫", "廖", "笏", "铕", "衣", "洇", "炒", "瀍", "崭", "圻", "洚", "契", "嫱", "倏", "晶", "了", "堠",
"勰", "椎",
"询", "梗", "飒", "锰", "览", "溇", "寻", "蓅", "【", "碇", "井", "露", "顔", "堌", "庳", "踩", "i",
"饷", "俊",
"楫", "條", "搭", "奍", "羽", "憋", "岘", "毡", "曜", "乃", "′", "针", "羲", "菓", "吩", "咩", "鞘",
"尊", "宫",
"舜", "啖", "惗", "北", "懊", "骇", "阄", "躅", "权", "缲", "肥", "铜", "《", "录", "也", "棬", "煮",
"舄", "厮",
"'", "順", "受", "霜", "新", "售", "牞", "圣", "妗", "犴", "宥", "哦", "陀", "卺", "冚", "蹒", "亸",
"禮", "骰",
"瑢", "弒", "抛", "谷", "嫰", "動", "嘌", "惩", "枣", "忌", "茡", "爵", "嘚", "郧", "丨", "敲", "帚",
"沭", "槊",
"⑶", "專", "毶", "圄", "磅", "蛭", "由", "蠹", "剜", "诫", "秆", "愠", "藓", "母", "请", "衩", "忸",
"蜕", "饽",
"晦", "倔", "腠", "痛", "品", "簧", "父", "锐", "描", "蓰", "蛴", "箍", "兕", "苜", "饼", "奚", "泗",
"裥", "皂",
"嵚", ",", "澶", "蠖", "沅", "馎", "籀", "菝", "眵", "糥", "铽", "痤", "颟", "淄", "作", "抉", "俄",
"么", "郑",
"耒", "佛", "1", "纡", "鸢", "④", "鎚", "壖", "遢", "鬈", "拢", "托", "哈", "節", "橦", "冼", "六",
"耗", "樵",
"涔", "舳", "龌", "衿", "婧", "栓", "椹", "嘘", "膊", "茁", "丹", "螃", "剖", "洧", "珞", "潺", "孱",
"呐", "萩",
"刷", "引", "说", "熟", "/", "靖", "酷", "耠", "饬", "菌", "洙", "荃", "饲", "酾", "阁", "陬", "铿",
"倻", "牮",
"鞡", "撕", "倘", "盒", "曺", "襦", "辄", "算", "塬", "潢", "羖", "湾", "续", "△", "疙", "谖", "嘅",
"遑", "篚",
"筮", "氍", "递", "尧", "G", "{", "分", "埒", "@", "蜍", "荼", "襆", "槭", "檠", "縢", "濉", "梆",
"隔", "镛",
"倞", "润", "瓯", "瓢", "蟊", "沐", "啷", "砚", "皱", "剅", "儙", "错", "幌", "滓", "砗", "郤", "喧",
"峣", "簸",
"毖", "踏", "锕", "…", "悖", "谧", "醵", "加", "镐", "泐", "傫", "胪", "缄", "卩", "蓼", "丸", "垌",
"汞", "宴",
"膙", "圊", "矻", "嚏", "漾", "幕", "駕", "葒", "绪", "袪", "镋", "杭", "澴", "鬃", "粟", "偻", "饳",
"抨", "亟",
"温", "韶", "轿", "罟", "际", "诖", "复", "坯", "骗", "*", "副", "裢", "憬", "邾", "崇", "蕈", "疮",
"粽", "炝",
"珲", "莅", "衾", "爲", "枯", "汛", "仁", "熏", "馥", "㎡", "檐", "锦", "竭", "颁", "遽", "瘙", "样",
"遛", "殍",
"湄", "消", "鳌", "痫", "鳏", "瓶", "窈", "谚", "麒", "鸹", "蟋", "横", "唠", "瘪", "媪", "侔", "鐵",
"系", "杖",
"m", "叉", "沟", "衢", "寘", "■", "弗", "建", "疣", "珣", "綦", "劈", "道", "嘈", "先", "芝", "降",
"滕", "邵",
"邺", "給", ")", "廨", "郛", "势", "氇", "坤", "昂", "焼", "奕", "闱", "朓", "毽", "还", "坨", "銭",
"龂", "銎",
"壽", "矸", "窒", "①", "玷", "蝽", "泃", "烀", "魈", "★", "慶", "K", "嘶", "酶", "呖", "殿", "乡",
"䄂", "阳",
"轪", "碱", "譬", "摩", "鳖", "刳", "地", "包", "貊", "悝", "圩", "今", "嚭", "凳", "谕", "馃", "捎",
"佯", "侬",
"愆", "微", "涤", "舔", "蛇", "筲", "助", "锾", "剧", "缧", "簪", "惚", "柢", "庾", "虹", "雪", "猡",
"脔", "亶",
"烨", "T", "锗", "芈", "女", "动", "偬", "琥", "县", "诣", "精", "嬗", "栀", "艨", "智", "冗", "闼",
"嗝", "z",
"夢", "拿", "鹲", "尤", "啮", "﹐", "ɔ", "钓", "施", "萼", "邻", "竞", "碶", "艰", "》", "翻", "馆",
"橪", "逝",
"臀", "淫", "枉", "羿", "拇", "溷", "徒", "涓", "關", "聋", "嵊", "殖", "叛", "敫", "舵", "亊", "诽",
"菱", "苎",
"破", "腚", "A", "嵋", "扊", "挂", "篷", "棂", "碟", "復", "劾", "韪", "疔", "粒", "鲵", "毙", "店",
"锻", "衮",
"寳", "◎", "斯", "倦", "醢", "曾", "茚", "荐", "隗", "芊", "豪", "亻", "哂", "堃", "宇", "桑", "匋",
"植", "亥",
"撂", "棒", "蟠", "W", "迟", "蚋", "溊", "缌", "鞚", "蚤", "適", "赌", "卣", "厚", "鲾", "匙", "槃",
"郎", "鬏",
"玳", "龄", "丈", "圮", "冑", "院", "葬", "嵐", "瓦", "孵", "漶", "星", "吐", "獍", "藠", "萍", "振",
"潜", "龉",
"匦", "粹", "諾", "畵", "峦", "&", "埕", "朵", "戒", "炳", "酪", "绂", "篁", "测", "殆", "涌", "业",
"盏", "醊",
"笆", "孰", "骊", "湛", "踰", "汎", "哲", "澙", "鲷", "√", "鄣", "亿", "螺", "吠", "伟", "凛", "骡",
"恻", "巨",
"扶", "泡", "峯", "韵", "腎", "睦", "栖", "}", "笙", "疌", "绶", "忒", "哥", "价", "纻", "薨", "漂",
"濮", "缮",
"勐", "妮", "傩", "陛", "陷", "柆", "瞭", "鲳", "烬", "喉", "固", "桡", "聊", "逦", "猊", "梻", "涵",
"栒", "逍",
"饥", "凼", "早", "姣", "蕤", "塌", "桀", "亳", "虻", "鹨", "典", "情", "怄", "商", "钍", "赚", "塥",
"煽", "垱",
"蝴", "乓", "籁", "帷", "锢", "圪", "快", "赘", "杵", "漠", "滴", "斩", "拈", "蚕", "陽", "篡", "郦",
"瞻", "郯",
"鳍", "幽", "旅", "乖", "鹖", "斫", "痂", "肸", "右", "锂", "永", "泾", "茎", "觱", "彼", "擎", "䨱",
"翱", "徝",
"醅", "求", "湫", "転", "溴", "師", "瓣", "蝠", "铭", "社", "苞", "仇", "噌", "你", "嗾", "雳", "榧",
"駹", "雯",
"叨", "遫", "氏", "航", "辗", "溢", "历", "楷", "诱", "雏", "梳", "藕", "屺", "槎", "钐", "燘", "棽",
"驸", "褪",
"清", "十", "廰", "移", "筌", "揾", "瞠", "姽", "馑", "恢", "逸", "p", "瑚", "茄", "鹧", "俗", "璟",
"栊", "买",
"瀛", "镒", "球", "氲", "缛", "講", "胀", "焒", "悲", "翕", "拗", "T", "桌", "脓", "闪", "稀", "狎",
"火", "柁",
"琴", "澍", "嗟", "龚", "楮", "噼", "隽", "栩", "焻", "哩", "藻", "瘸", "含", "偶", "界", "嘃", "昶",
"澄", "頤",
"绒", "鲁", "麝", "决", "撒", "岙", "季", "刿", "肝", "蒉", "蓇", "财", "完", "蠔", "脉", "肱", "谙",
"蜮", "郭",
"慨", "晔", "髂", "蛏", "眨", "钗", "葺", "惆", "娈", "瞵", "踞", "棁", "蝢", "嚎", "猝", "必", "剞",
"关", "咛",
"劫", "闸", "肯", "№", "莩", "哇", "蛑", "镬", "羡", "驊", "茂", "塍", "沓", "筱", "杉", "战", "茧",
"耙", "击",
"需", "腊", "酎", "畦", "葙", "鹘", "韭", "嚚", "争", "域", "伢", "鞲", "哳", "栲", "某", "翌", "哗",
"焚", "螗",
"懲", "躲", "約", "镖", "凿", "饶", "够", "剁", "铥", "应", "署", "杮", "蒂", " ", "坷", "礅", "款",
"梁", "鄜",
"髹", "選", "伤", "路", "З", "亲", "野", "啦", "捯", "憷", "鲩", "札", "怏", "塘", "绊", "愍", "簦",
"牦", "黥",
"鳜", "唉", "W", "沱", "蚺", "甪", "摉", "协", "耨", "娱", "桄", "仆", "类", "搡", "滤", "岗", "休",
"坶", "谒",
"忭", "飨", "闷", "菟", "鲣", "驷", "湜", "疡", "蚩", "萊", "䝉", "硒", "贺", "弃", "徘", "陨", "否",
"遥", "妒",
"X", "間", "觜", "跬", "夬", "羮", "喙", "赇", "鹗", "『", "砀", "残", "绿", "小", "勘", "瀌", "扉",
"耧", "衅",
"挟", "乐", "鹏", "墁", "澜", "噍", "坊", "術", "嗖", "知", "盉", "圆", "嗈", "蘖", "资", "爭", "=",
"刑", "裒",
"〈", "淸", "定", "袒", "戗", "钤", "吵", "旯", "蓝", "裎", "溅", "贰", "荏", "甥", "悌", "勤", "炽",
"换", "躜",
"!", "薄", "痱", "双", "匕", "肷", "挥", "茑", "船", "砝", "煤", "荜", "弘", "▏", "陆", "稔", "朽",
"冤", "頉",
"遊", "砰", "迎", "碎", "唪", "醪", "稆", "练", "锸", "阵", "皇", "香", "镀", "嫡", "持", "桶", "垄",
"阍", "戥",
"臣", "琛", "涘", "惶", "赙", "葆", "住", "舊", "枝", "媲", "蓣", "龅", "搦", "_", "图", "力", "纪",
"悍", "麗",
"戽", "腧", "绣", "跟", "哕", "打", "蝰", "Φ", "吞", "功", "夀", "劓", "沇", "熔", "占", "隰", "命",
"佻", "豁",
"苣", "楦", "掇", "蛛", "唢", "郜", "霉", "鲏", "予", "沸", "殻", "俯", "探", "篪", "荇", "邈", "烯",
"忮", "伸",
"岬", "×", "锧", "窸", "毪", "纩", "蛋", "讯", "骼", "叶", "楂", "犟", "站", "盘", "隈", "喝", "儣",
"兵", "尚",
"孙", "爿", "芜", "羁", "旖", "溽", "迩", "京", "7", "龃", "狝", "缦", "缁", "鲃", "怒", "故", "據",
"枫", "髙",
"亭", "耳", "飚", "O", "编", "箸", "幼", "氘", "鞮", "匐", "祯", "臃", "辫", "磋", "溝", "墙", "诚",
"阻", "档",
"歆", "璃", "悻", "婤", "映", "瑞", "牂", "话", "忠", "潘", "惋", "冬", "氦", "腔", "胬", "盔", "\"",
"饮", "贶",
"嚄", "儆", "溜", "砷", "樇", "跏", "泩", "馌", "埃", "莙", "革", "珙", "乌", "鍋", "穴", "石", "珺",
"熹", "诞",
"<", "腉", "姊", "钧", "罪", "拆", "赊", "殒", "堇", "仑", "掺", "塃", "獴", "迥", "盦", "檬", "益",
"居", "鼑",
"异", "嘻", "悔", "旮", "况", "時", "阋", "洛", "線", "#", "型", "迕", "睇", "橱", "笊", "蛞", "愚",
"茉", "镈",
"镞", "垭", "扁", "泫", "搬", "古", "书", "疸", "痨", "黟", "墉", "料", "并", "ㆍ", "裳", "鞑", "湮",
"柠", "颐",
"形", "━", "逹", "硁", "置", "韦", "瓞", "象", "殽", "均", "浓", "瞓", "椐", "洨", "乱", "襜", "终",
"優", "睹",
"敦", "鼬", "唆", "佼", "財", "瘃", "H", "痳", "勺", "依", "虎", "蕖", "玄", "缓", "滢", "^", "骅",
"诘", "弋",
":", "∩", "廪", "缈", "造", "蕉", "孖", "嫒", "寨", "意", "岽", "庶", "罗", "瞢", "酹", "蔟", "赴",
"烂", "栋",
"格", "矛", "驯", "词", "嗦", "剀", "蓓", "期", "鏢", "羑", "奴", "椱", "A", "狗", "烟", "蹬", "案",
"记", "讴",
"鳑", "侯", "霏", "焜", "沬", "份", "酦", "芗", "庚", "瑗", "鹎", "穗", "鲠", "肛", "厄", "蜔", "學",
"伊", "⑥",
"琪", "邒", "少", "霖", "蓖", "猜", "塾", "肾", "罃", "伐", "钩", "骈", "溟", "饵", "莉", "é", "刖",
"洯", "堉",
"锝", "趔", "七", "萁", "竹", "憾", "蚨", "离", "柔", "替", "侑", "飙", "气", "震", "厥", "备", "刻",
"顽", "瞽",
"腄", "雄", "燃", "旬", "简", "翠", "熥", "◇", "吃", "囡", "玙", "铷", "暖", "配", "傻", "窄", "皈",
"夼", "舂",
"乜", "苩", "攉", "雠", "茇", "锈", "酰", "粮", "祝", "考", "堍", "鳅", "彬", "▲", "孝", "蠊", "顇",
"娲", "腥",
"$", "珠", "厂", "诠", "蹓", "轼", "嵫", "捩", "硗", "胺", "证", "膀", "」", "胯", "钷", "毂", "柙",
"深", "沄",
"匹", "8", "爷", "礳", "秏", "窜", "魑", "d", "转", "烆", "屿", "眙", "極", "袤", "護", "V", "狂",
"柑", "玠",
"氩", "’", "馊", "玛", "坢", "%", "燔", "颗", "舅", "暂", "艾", "芹", "溏", "晰", "件", "琚", "仿",
"祾", "酤",
"騠", "揳", "鲫", "蜥", "仨", "牺", "步", "讓", "港", "煲", "铴", "腦", "鳝", "危", "鋪", "冠", "正",
"柽", "抍",
"掘", "控", "娴", "娀", "離", "手", "臾", "酗", "筼", "煸", "弹", "照", "哎", "毒", "颀", "诙", "刚",
"搢", "䧳",
"峒", "滋", "\\", "匀", "黉", "毓", "娠", "床", "浪", "祐", "铟", "4", "?", "凄", "飗", "蚍", "葑",
"抗", "鹞",
"糸", "红", "英", "违", "橡", "眷", "防", "缬", "龠", "察", "仍", "辇", "减", "闫", "箴", "龍", "館",
"屙", "翙",
"媽", "涴", "到", "旻", "删", "瞾", "鏖", "咭", "豨", "荘", "炭", "畼", "构", "锘", "鉫", "候", "扇",
"繄", "猩",
"瘵", "恺", "贵", "榦", "息", "恽", "胎", "狰", "雜", "辋", "璜", "硈", "泠", "呔", "蹿", "踹", "摄",
"炀", "坞",
"蹄", "裝", "赛", "蝥", "塔", "靳", "荬", "找", "仡", "淮", "比", "淆", "义", "淝", "卢", "辟", "寂",
"庒", "鳯",
"暲", "景", "邪", "腻", "赍", "甍", "讲", "哌", "嶝", "鎌", "总", "缱", "问", "磛", "谅", "拉", "靈",
"奭", "沆",
"茔", "羅", "鄠", "網", "吏", "懵", "鑫", "歌", "黹", "嵘", "涞", "碳", "崂", "婥", "赞", "镑", "購",
"幺", "鸰",
"饟", "蝌", "忝", "懒", "禺", "梽", "齉", "恳", "拯", "弥", "荡", "芾", "幪", "厌", "馒", "蜘", "欸",
"吣", "1",
"却", "榻", "碾", "袂", "錎", "钬", "無", "嬉", "笞", "蹴", "视", "雇", "创", "椟", "6", "瘁", "斜",
"傥", "喃",
"炷", "秾", "嘱", "茀", "犄", "窑", "庀", "潍", "伦", "䀲", "凉", "Р", "撻", "萜", "二", "倨", "蔑",
"捕", "勚",
"士", "鈇", "踺", "啤", "彧", "缪", "述", "傅", "颅", "畸", "畜", "滗", "慭", "琎", "斌", "参", "胳",
"骖", "稠",
"汰", "铻", "闯", "留", "蘘", "沏", "亦", "择", "華", "禽", "砟", "祼", "狃", "噫", "狼", "寤", "跪",
"浠", "·",
"费", "瓘", "鼹", "锪", "箢", "垣", "慊", "虏", "秩", "偉", "镏", "钯", "恐", "鹃", "菇", "炸", "潮",
"蟀", "硂",
"偌", "哏", "验", "桉", "阴", "初", "掴", "鹺", "峨", "赋", "舉", "裹", "赶", "土", "淋", "瘌", "沔",
"r", "赀",
"淖", "茯", "怛", "谜", "洗", "似", "舡", "纳", "晓", "R", "诐", "痹", "漪", "顺", "挛", "阎", "贝",
"钰", "惬",
"疬", "菀", "埘", "怙", "部", "译", "鲭", "窋", "敢", "夜", "撰", "珅", "特", "襕", "癖", "胡", "⒃",
"附", "擘",
"痢", "尬", "鉴", "瞋", "膨", "阽", "挲", "⒄", "骎", "帕", "缕", "计", "障", "鳆", "隹", "朔", "碹",
"当", "迦",
"氙", "蘑", "妓", "炬", "苊", "萎", "浈", "沥", "绯", "壤", "噱", "蹾", "驶", "葱", "孕", "羹", "钻",
"農", "勝",
"膈", "灿", "赆", "靿", "耱", "陪", "忙", "缰", "奶", "儒", "个", "朱", "燹", "琮", "轷", "錾", "箅",
"澳", "嗥",
"攥", "没", "匿", "鲆", "|", "矣", "他", "鸶", "芸", "B", "髑", "街", "巿", "廣", "盯", "監", "鲸",
"胭", "凬",
"寿", "挝", "绽", "+", "劝", "究", "眢", "集", "衙", "卷", "j", "跶", "牡", "畯", "貅", "销", "發",
"咱", "蓊",
"揣", "咝", "琶", "荦", "阌", "盅", "嘹", "苟", "醮", "洪", "鲧", "钒", "柱", "氨", "旰", "冽", "茭",
"嵇", "粲",
"蛾", "訾", "辔", "N", "尹", "趿", "蹲", "疟", "祠", "段", "車", "网", "⒉", "舷", "廐", "侣", "棵",
"粜", "觐",
"铼", "锁", "兒", "舁", "时", "垦", "版", "摈", "扳", "见", "腮", "嫖", "痭", "呆", "簖", "伋", "鳙",
"珊", "麂",
"既", "谴", "热", "超", "蠕", "铞", "e", "殓", "因", "锿", "文", "禊", "皙", "鑙", "爹", "鋼", "忻",
"秣", "镁",
"奠", "橉", "畺", "笮", "疹", "湝", "龟", "殃", "毵", "溃", "勢", "索", "砉", "阼", "堞", "酥", "冁",
"喊", "¥",
"幛", "娇", "锲", "蕃", "铘", "铍", "鴿", "响", "傲", "脏", "杓", "罕", "笥", "弦", "但", "缃", "扬",
"盲", "碚",
"幢", "鎖", "缺", "钋", "麽", "禳", "浃", "啄", "昧", "蒴", "帙", "琏", "咧", "舰", "亵", "浊", "豳",
"衲", "俏",
"镵", "浩", "勾", "槛", "榈", "徙", "鹤", "洹", "铂", "揎", "棕", "挦", "挫", "阆", "衹", "甚", "近",
"】", "簏",
"汽", "踮", "淌", "檇", "痔", "谝", "钙", "蕞", "蔯", "兆", "蔽", "后", "蚬", "谸", "芟", "枞", "叫",
"栗", "餘",
"营", "郝", "氯", "㺃", "狍", "冏", "庛", "纱", "泼", "碍", "认", "邓", "茵", "饧", "闟", "惝", "裙",
"噙", "忘",
"虬", "群", "S", "佗", "恼", "坟", "肮", "皮", "玃", "在", "赧", "孚", "偾", "镨", "恨", "葡", "西",
"缞", "挠",
"逃", "吾", "膪", "焦", "翘", "桧", "变", "渗", "繁", "際", "痘", "撼", "筅", "坑", "前", "玑", "数",
"融", "鲌",
"讦", "窃", "鄌", "伾", "众", "攻", "彪", "锎", "焐", "殛", "锊", "嗉", "枓", "抢", "鞠", "掩", "贾",
"搔", "皁",
"拶", "朗", "渺", "跛", "㛃", "鏾", "慥", "杆", "沈", "戍", "豫", "楠", "爆", "汤", "昉", "耘", "缡",
".", "允",
"揜", "责", "艟", "裁", "喬", "砹", "鹣", "裼", "啉", "蛳", "酮", "听", "维", "阪", "獾", "浣", "訂",
"瘿", "蜡",
"泖", "蔚", "貔", "致", "禨", "尓", "糺", "绐", "遯", "笄", "邦", "圈", "洟", "缟", "槲", "桹", "镓",
"骒", "髫",
"暾", "像", "縻", "戊", "飧", "驽", "干", "万", "绕", "披", "雅", "桊", "卡", "贲", "吡", "沧", "鳟",
"堂", "扺",
"岱", "封", "鄭", "螣", "瞩", "幞", "邕", "睫", "涩", "自", "趱", "愣", "威", "酊", "罂", "慑", "袴",
"架", "烘",
"现", "灞", "钔", "股", "興", "乍", "噜", "济", "碛", "兀", "诅", "柴", "瓿", "[", "怿", "竦", "白",
"黄", "阶",
"务", "榮", "澹", "谏", "垓", "跸", "繻", "窿", "紊", "陟", "劁", "嗑", "牯", "厉", "敛", "鮕", "嘉",
"蔻", "鼎",
"恒", "硝", "溉", "骘", "窘", "任", "裱", "处", "旨", "舶", "缸", "囹", "笠", "讥", "泜", "脊", "煊",
"淦", "牝",
"硕", "胧", "泚", "溪", "贪", "牛", "答", "瘴", "Q", "炯", "⑤", "篾", "銀", "乩", "杶", "垆", "蛐",
"苔", "啪",
"y", "玮", "琫", "寮", "邂", "後", "僵", "贴", "硭", "枚", "姆", "乎", "讶", "醭", "橥", "脱", "蒈",
"擞", "忪",
"顾", "柚", "褿", "忲", "辖", "铡", "螠", "殉", "喆", "爡", "轮", "棰", "鲉", "跃", "韬", "睡", "嘧",
"袅", "圗",
"檄", "踊", "阀", "题", "桫", "林", "沉", "禚", "散", "麇", "沦", "秋", "导", "斑", "宰", "嘞", "暑",
"笱", "搋",
"擅", "镤", "锶", "L", "厣", "有", "猗", "袆", "绞", "甭", "歧", "跣", "潦", "専", "绑", "飱", "廓",
"磔", "接",
"腓", "窎", "瑁", "飓", "蟪", "俎", "П", "缉", "䘵", "夙", "潟", "桷", "淡", "虺", "恶", "|", "驭",
"怀", "邋",
"辢", "逻", "晖", "蜃", "蜊", "溻", "冢", "尻", "礼", "厝", "亘", "酴", "饔", "悸", "戆", "什", "玚",
"馔", "哔",
"沃", "竑", "葭", "垞", "鏂", "抃", "弄", "去", "焊", "焌", "x", "苇", "與", "炼", "蛄", "莴", "阏",
"薷", "禀",
"鸯", "栽", "冒", "姓", "0", "尃", "蜞", "毗", "骟", "秸", "荸", "柈", "恬", "赡", "侏", "兑", "蝤",
"荷", "徳",
"押", "挣", "腰", "宣", "鸵", "葳", "遘", "讨", "狒", "涿", "囤", "邃", "蒜", "疑", "脍", "嘟", "鹠",
"吻", "鄹",
"耦", "华", "霸", "侥", "勒", "挞", "臊", "尺", "让", "榆", "阝", "鳚", "灾", "鲬", "艿", "Ⅱ", "锩",
"攮", "蚊",
"蔁", "唝", "涅", "挹", "淏", "鏊", "氵", "鹕", "律", "對", "粱", "恫", "挻", "滏", "叮", "‰", "鼯",
"绫", "秉",
"怩", "質", "岐", "菊", "佤", "帏", "骺", "爰", "珉", "耪", "乞", "郕", "鲱", "雷", "蒿", "不", "啐",
"侓", "郓",
"歼", "拒", "胗", "寕", "旒", "勁", "婢", "诌", "蹂", "姐", "媳", "歃", "拐", "辐", "拟", "醯", "雌",
"点", "玟",
"您", "鲨", "载", "藩", "罔", "噀", "抹", "萏", "补", "蝎", "辈", "劢", "乚", "唔", "瓜", "恿", "蟭",
"涸", "纬",
"睽", "樣", "帻", "蓥", "谯", "柯", "渴", "脁", "诲", "福", "③", "熊", "羌", "疴", "袖", "虿", "杏",
"覌", "易",
"醾", "筒", "肤", "苷", "柃", "榇", "酬", "癸", "啰", "眛", "稷", "展", "鸾", "祢", "蝾", "敵", "毛",
"痦", "老",
"赐", "单", "淹", "畋", "符", "奎", "绥", "轾", "鄺", "濩", "眦", "觎", "忾", "璋", "刘", "翳", "菪",
"簟", "胼",
"孫", "機", "獻", "低", "o", "捅", "鳥", "⑨", "卸", "废", "启", "呋", "窥", "巢", "揭", "咴", "趺",
"鲥", "空",
"膄", "崮", "锜", "络", "納", "恤", "刭", "批", "霭", "氧", "钮", "甑", "祲", "粘", "辏", "∶", "臨",
"│", "粪",
"惰", "肼", "浉", "橄", "5", "東", "8", "漁", "浜", "忍", "奂", "遹", "扃", "扦", "入", "欤", "豆",
"悠", "蕴",
"萑", "媄", "龈", "÷", "磙", "鸬", "缎", "嗯", "浕", "木", "陋", "柰", "瘩", "箨", "松", "躁", "鲇",
"彰", "恕",
"楗", "姨", "撅", "诹", "戮", "桓", "棉", "束", "嗍", "庋", "瞿", "郂", "哪", "町", "a", "铁", "洫",
"失", "栳",
"篇", "鳗", "眇", "椿", "義", "就", "都", "镌", "阖", "夭", "拃", "跚", "業", "圬", "演", "篥", "3",
"昼", "從",
"瞍", "蓦", "鼾", "坪", "觫", "鲍", "馿", "妾", "密", "奥", "耰", "佟", "嘤", "貘", "薯", "稽", "届",
"褛", "钠",
"猿", "佈", "倍", "铩", "铙", "踵", "o", "捱", "鹐", "當", "狷", "写", "遆", "钱", "姗", "寸", "综",
"挑", "礶",
"靼", "溯", "湟", "漱", "碰", "职", "味", "Λ", "璁", "壴", "给", "碘", "恭", "苴", "酚", "套", "宕",
"辽", "窀",
"催", "踢", "惟", "璧", "翔", "稿", "癀", "霈", "光", "膑", "妆", "庡", "圾", "躺", "惮", "切", "目",
"梦", "岫",
"飑", "叠", "累", "鴻", "透", "量", "妻", "沨", "俪", "屣", "挚", "w", "厅", "货", "箧", "漦", "隙",
"瘥", "妃",
"門", "鹦", "隳", "龆", "瞪", "跑", "帼", "刺", "起", "鞴", "岸", "渫", "莽", "髭", "耜", "瑛", "葉",
"宵", "绠",
"眭", "畅", "茱", "卜", "濂", "浍", "冈", "脬", "厘", "夔", "纟", "槚", "哐", "萋", "曼", "膳", "潲",
"啜", "啊",
"猾", "捉", "箕", "㐂", "藝", "艘", "園", "妲", "灵", "蚌", "范", "&", "疥", "陑", "洒", "唾", "a",
"婄", "谋",
"t", "唬", "宓", "瓷", "︰", "焗", "默", "噔", "菡", "恃", "亩", "边", "啟", "颞", "啬", "盟", "墩",
"汭", "缝",
"魇", "酡", "疗", "梾", "尾", "鹿", "锔", "溦", "酃", "囊", "掉", "罥", "报", "诤", "喹", "蕙", "割",
"蠢", "兼",
"俺", "升", "屦", "獠", "辣", "跹", "颧", "宪", "抬", "咿", "沲", "旗", "荩", "傒", "鳳", "變", "偈",
"薹", "钭",
"垧", "谪", "躐", "谀", "R", "字", "怆", "陵", "追", "迓", "舞", "卲", "捲", "麾", "税", "方", "竴",
"壹", "射",
"轫", "塞", "僧", "椠", "突", "阕", "惫", "U", "佞", "秒", "友", "視", "莹", "攒", "荻", "俅", "筐",
"能", "刓",
"拍", "浥", "揽", "谨", "军", "巷", "怵", "额", "恪", "荀", "糍", "湎", "褙", "觇", "效", "估", "噩",
"恍", "聚",
"涛", "式", "兜", "汔", "祃", "銘", "烺", "瑄", "枘", "丁", "樗", "堙", "窗", "號", "鬣", "阈", "乳",
"簇", "绳",
"淞", "]", "征", "聩", "凸", "礓", "柘", "懂", "㧎", "纷", "里", "爸", "靥", "莞", "馅", "仞", "芏",
"莳", "殪",
"煌", "落", "佚", "帱", "诶", "家", "将", "浯", "抿", "讫", "趸", "筢", "绩", "原", "专", "滂", "嗳",
"踬", "泱",
"體", "蜱", "绵", "伻", "埗", "妤", "蔺", "赳", "嘢", "梨", "鹪", "烤", "镦", "赉", "崞", "蚰", "骝",
"幅", "汴",
"丽", "访", "叩", "羼", "亓", "恸", "燥", "笤", "丑", "枰", "守", "蜚", "戈", "高", "q", "瓻", "隘",
"H", "南",
"剎", "扭", "骠", "孜", "园", "锬", "审", "¥", "罚", "购", "裰", "泔", "醌", "醒", "绎", "莪", "掬",
"睾", "鹁",
"蛊", "票", "剃", "释", "调", "黛", "撩", "篱", "茌", "敓", "蜜", "魉", "鳤", "昽", "俳", "辁", "键",
"犯", "嶙",
"狈", "邬", "枋", "婊", "憎", "督", "救", "措", "足", "码", "栟", "虼", "棻", "阅", "肊", "坛", "鸱",
"侩", "烫",
"湉", "脐", "戾", "旎", "膚", "椒", "境", "绛", "濛", "蓄", "章", "压", "窦", "彖", "阜", "咻", "神",
"存", "诺",
"課", "覺", "鲈", "渚", "「", "缢", "仓", "氅", "筇", "桴", "荥", "些", "纯", "肋", "退", "妪", "别",
"書", "租",
"嚼", "芘", "笳", "涰", "馐", "熵", "犹", "朕", "猪", "蔸", "參", "觳", "舖", "蝙", "骏", "织", "躏",
"纹", "锹",
"蛉", "撑", "氽", "茶", "俛", "誠", "胖", "崽", "炫", "乘", "把", "趑", "谵", "骧", "犍", "鸮", "灌",
"焯", "倭",
"狁", "盱", "踱", "滠", "儡", "诸", "芽", "駆", "蹼", "虱", "祇", " ", "蠡", "衄", "谬", "蒍", "婺",
"蘧", "博",
"捍", "磁", "慷", "釂", "蛩", "钕", "祎", "呑", "贫", "斗", "菅", "操", "规", "硼", "惕", "丫", "俭",
"肿", "骀",
"砼", "句", "茛", "闶", "钏", "饻", "圠", "萌", "魏", "铃", "摞", "┅", "伎", "獭", "田", "钴", "峭",
"魅", "捋",
"唼", "鹅", "祚", "嬷", "圖", "抄", "嶂", "鸳", "溧", "钵", "嗽", "墠", "锌", "愈", "併", "踟", "羯",
"翅", "纠",
"勻", "岚", "菖", "便", "祈", "毳", "屹", "掰", "倬", "扛", "巴", "拮", "绁", "跌", "飯", "嵯", "翮",
"堤", "诃",
"腑", "皆", "鄂", "胾", "片", "这", "浙", "雨", "鼱", "袼", "鹊", "厢", "蛣", "摇", "蛮", "揍", "⒅",
"啱", "薇",
"岈", "兔", "谇", "纶", "肉", "崩", "甩", "涪", "馼", "铣", "锚", "丙", "雲", "烹", "钦", "撄", "铬",
"令", "虮",
"湊", "禹", "抖", "喏", "旺", "畲", "戬", "嗷", "釜", "车", "缀", "玕", "谐", "啁", "怎", "下", "惑",
"恅", "藿",
"筰", "帐", "祸", "镝", "喵", "刁", "习", "藏", "墓", "护", "聲", "箦", "严", "按", "谛", "睨", "艚",
"歉", "蟮",
"胶", "盍", "鳃", "狯", "垫", "杠", "线", "3", "葖", "t", "熬", "虞", "嶶", "篮", "黻", "墒", "氟",
"嫠", "漕",
"腾", "哟", "玫", "撇", "垍", "靛", "翼", "淅", "省", "斥", "稞", "蠼", "谩", "埠", "蘸", "刊", "烝",
"宁", "鹚",
"龊", "苪", "袷", "诧", "细", "蒌", "焅", "2", "筹", "扒", "卮", "捞", "净", "菲", "逮", "槍", "蛎",
"莱", "黠",
"逖", "辚", "剥", "啴", "诿", "楱", "氪", "领", "嗒", "藐", "惜", "甘", "佾", "嵴", "胫", ";", "晳",
"锣", "瞅",
"缷", "耶", "搤", "策", "咽", "邀", "霾", "悟", "属", "鸪", "牴", "贞", "趁", "丞", "瘆", "豌", "著",
"饿", "筠",
"划", "璇", "损", "卵", "腒", "畏", "盥", "耐", "圏", "拓", "蒙", "鋫", "劙", "蹦", "熘", "烊", "匏",
"咔", "轘",
"沽", "菩", "罴", "磉", "炖", "假", "枪", "龙", "俸", "焱", "四", "─", "毫", "涨", "浇", "椰", "賣",
"蘇", "真",
"安", "坝", "枕", "鸼", "昵", "亨", "苤", "祷", "枧", "赟", "菑", "鳂", "戌", "悄", "種", "鳢", "嗣",
"電", "颥",
"妯", "谟", "蜒", "训", "泍", "洁", "勇", "哿", "扰", "蟆", "螂", "刃", "絜", "曪", "乒", "湖", "鞨",
"懜", "夤",
"哓", "胥", "桞", "俇", "肣", "半", "于", "橼", "锑", "熙", "甜", "槌", "盾", "屃", "缗", "共", "碗",
"凇", "笔",
"阿", "擗", "袍", "敉", "钾", "俶", "蚪", "琤", "凱", "辕", "à", "恣", "皴", "創", "寥", "妳", "腈",
"畤", "迤",
"垠", "触", "趙", "铤", "逊", "羊", "碉", "锱", "骨", "仄", "斟", "俚", "啡", "芩", "迫", "杷", "种",
"鹄", "牗",
"耑", "艇", "芰", "整", "慙", "飛", "甓", "岩", "鸦", "黎", "僊", "糁", "谈", "洋", "椑", "健", "〕",
"內", "言",
"掷", "倚", "姬", "矿", "灯", "阐", "凋", "銮", "豇", "瑰", "抓", "噪", "堋", "吁", "妈", "庥", "彳",
"鄗", "闩",
"夫", "0", "庠", "悬", "妙", "琵", "着", "首", "熣", "瞰", "揆", "燚", "条", "姜", "滘", "麓", "鳉",
"椀", "蓿",
"廠", "泌", "蝈", "倕", "丛", "耍", "且", "蝇", "凉", "豐", "泪", "臼", "服", "刍", "織", "渎", "尥",
"甙", "埋",
"珏", "援", "祖", "彊", "臱", "惦", "葴", "礁", "达", "橋", "钨", "崦", "醐", "巳", "中", "颜", "溠",
"铹", "负",
"抠", "愎", "罘", "雩", "胝", "冱", "筵", "篙", "材", "肓", "○", "迅", "腼", "橙", "仵", "茏", "慵",
"齌", "琯",
"疃", "貢", "豉", "瞟", "忉", "禄", "通", "咒", "愫", "秕", "筜", "觖", "州", "渑", "胆", "喑", "張",
"衖", "洺",
"眉", "榞", "色", "邶", "攫", "堑", "淬", "嗪", "肐", "殣", "辊", "隧", "献", "潤", "蓺", "函", "鹱",
"轭", "劭",
"椁", "膜", "亹", "侧", "貂", "哚", "磴", "蠋", "囔", "险", "伶", "世", "菥", "莶", "瘾", "燫", "延",
"∵", "毋",
"羧", "无", "雎", "曛", "沚", "巍", "g", "熄", "恰", "伷", "開", "冻", "颛", "支", "⑦", "鞥", "赖",
"试", "泮",
"联", "沮", "穰", "è", "峻", "滿", "豊", "刎", "鴈", "覆", "串", "锃", "春", "储", "矍", "哺", "评",
"猁", "愉",
"疳", "閃", "奄", "甲", "墦", "頭", "锫", "俦", "玩", "搀", "砭", "流", "橇", "泅", "琇", "趣", "∧",
"辑", "灊",
"貴", "迮", "摹", "霄", "濟", "限", "彀", "匪", "缂", "觚", "奇", "诋", "灼", "萘", "狠", "澥", "岂",
"悺", "闾",
"麋", "号", "槽", "姹", "陉", "瑯", "尉", "h", "绖", "宿", "戋", "粝", "砂", "该", "鞧", "翯", "釘",
"铢", "窨",
"設", "⒆"]`
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,33 @@
package ddddocr
import (
"embed"
_ "embed"
"likedream-goframe/internal/application/recognizer"
"os"
"path/filepath"
"strings"
)
//go:embed static/*
var fs embed.FS
func initModel() string {
if !recognizer.OnnxIsInit {
recognizer.InitOnnx()
}
// 检测文件是否存在
exePath := strings.ToLower(os.Args[0])
// 获取绝对路径
absPath, _ := filepath.Abs(exePath)
staticPath := filepath.Join(filepath.Dir(absPath), "static")
if _, err := os.Stat(staticPath); os.IsNotExist(err) {
os.Mkdir(staticPath, 0755)
}
modelPath := filepath.Join(staticPath, "common_old.onnx")
modelBytes, _ := fs.ReadFile("static/common_old.onnx")
if _, err := os.Stat(modelPath); os.IsNotExist(err) {
os.WriteFile(modelPath, modelBytes, 0644)
}
return modelPath
}
+59
View File
@@ -0,0 +1,59 @@
package recognizer
import (
"embed"
_ "embed"
"likedream-goframe/internal/framework/logger"
"os"
"path/filepath"
"runtime"
"strings"
ort "github.com/yalue/onnxruntime_go"
"go.uber.org/zap"
)
//go:embed static/*
var fs embed.FS
// OnnxIsInit 初始化onnx配置
var OnnxIsInit = false
func InitOnnx() {
name, bytes := getOnnxRuntimeName()
// 检测文件是否存在
exePath := strings.ToLower(os.Args[0])
// 获取绝对路径
absPath, _ := filepath.Abs(exePath)
filePath := filepath.Join(filepath.Dir(absPath), name)
if _, err := os.Stat(filePath); os.IsNotExist(err) {
os.WriteFile(filePath, bytes, 0644)
}
ort.SetSharedLibraryPath(filePath)
err := ort.InitializeEnvironment()
if err != nil {
logger.Logger.Panic("初始化onnx:", zap.String("绝对路径", filePath))
return
}
OnnxIsInit = true
}
func getOnnxRuntimeName() (onnxRuntimeFileName string, onnxRuntimeFileBytes []byte) {
systemOS := runtime.GOOS
switch systemOS {
case "windows":
onnxRuntimeFileName = "onnxruntime.dll"
onnxRuntimeFileBytes, _ = fs.ReadFile("static/onnxruntime.dll")
return
case "darwin":
onnxRuntimeFileName = "onnxruntime.dylib"
onnxRuntimeFileBytes, _ = fs.ReadFile("static/libonnxruntime.1.23.2.dylib")
return
case "linux":
onnxRuntimeFileName = "onnxruntime.so"
onnxRuntimeFileBytes, _ = fs.ReadFile("static/libonnxruntime.so.1.23.2")
return
}
logger.Logger.Panic("暂不支持的操作系统:", zap.String("系统名称", systemOS))
return "", nil
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,192 @@
package slider
import (
"encoding/base64"
"os"
"gocv.io/x/gocv"
)
func VerifySliderWidth(bgImgPath, sliderImgPath string) int {
// 检查背景图片文件是否存在
if _, err := os.Stat(bgImgPath); os.IsNotExist(err) {
return -1
}
// 检查滑块图片文件是否存在
if _, err := os.Stat(sliderImgPath); os.IsNotExist(err) {
return -1
}
// 读取背景图片
bgImg := gocv.IMRead(bgImgPath, gocv.IMReadColor)
if bgImg.Empty() {
return -1
}
defer bgImg.Close()
// 读取滑块图片(包含 alpha 通道)
sliderImgWithAlpha := gocv.IMRead(sliderImgPath, gocv.IMReadUnchanged)
if sliderImgWithAlpha.Empty() {
return -1
}
defer sliderImgWithAlpha.Close()
// 分离滑块图片的通道
channels := gocv.Split(sliderImgWithAlpha)
defer func() {
for i := range channels {
channels[i].Close()
}
}()
var sliderImg gocv.Mat
var mask gocv.Mat
// 如果有 alpha 通道(4通道),提取 mask
if len(channels) == 4 {
// 前3个通道是 BGR
sliderImg = gocv.NewMat()
defer sliderImg.Close()
gocv.Merge(channels[:3], &sliderImg)
// 使用 alpha 通道作为 mask
mask = channels[3].Clone()
defer mask.Close()
} else if len(channels) == 3 {
// 没有透明通道,直接使用原图
sliderImg = sliderImgWithAlpha.Clone()
defer sliderImg.Close()
mask = gocv.NewMat() // 空 mask
defer mask.Close()
} else {
return -1
}
// 创建结果矩阵用于存储匹配结果
result := gocv.NewMat()
defer result.Close()
// 直接在原图上使用模板匹配找到滑块位置
if mask.Empty() {
gocv.MatchTemplate(bgImg, sliderImg, &result, gocv.TmCcoeffNormed, gocv.NewMat())
} else {
// 带 mask 的模板匹配
gocv.MatchTemplate(bgImg, sliderImg, &result, gocv.TmCcoeffNormed, mask)
}
// 找到最佳匹配位置
_, maxVal, _, maxLoc := gocv.MinMaxLoc(result)
// 如果匹配度太低,返回 -1 表示失败
if maxVal < 0.6 {
return -1
}
// 获取原图上的 x 坐标,然后按比例缩放到目标尺寸
originalWidth := bgImg.Cols()
targetWidth := 280
scale := float64(targetWidth) / float64(originalWidth)
scaledX := int(float64(maxLoc.X) * scale)
// 返回缩放后的 x 坐标(滑块需要移动的距离)
return scaledX
}
// VerifySliderWidthByBase64 通过 base64 编码的图片计算滑块验证码需要移动的距离
// bgImgBase64: 背景图片的 base64 编码
// sliderImgBase64: 滑块图片的 base64 编码
// 返回: 滑块需要移动的 x 距离(已缩放到 280 宽度),失败返回 -1
func VerifySliderWidthByBase64(bgImgBase64, sliderImgBase64 string) int {
// 解码背景图片的 base64
bgImgData, err := base64.StdEncoding.DecodeString(bgImgBase64)
if err != nil {
return -1
}
// 解码滑块图片的 base64
sliderImgData, err := base64.StdEncoding.DecodeString(sliderImgBase64)
if err != nil {
return -1
}
// 从内存中读取背景图片
bgImg, err := gocv.IMDecode(bgImgData, gocv.IMReadColor)
if err != nil {
return -1
}
if bgImg.Empty() {
return -1
}
defer bgImg.Close()
// 从内存中读取滑块图片(包含 alpha 通道)
sliderImgWithAlpha, err := gocv.IMDecode(sliderImgData, gocv.IMReadUnchanged)
if err != nil {
return -1
}
if sliderImgWithAlpha.Empty() {
return -1
}
defer sliderImgWithAlpha.Close()
// 分离滑块图片的通道
channels := gocv.Split(sliderImgWithAlpha)
defer func() {
for i := range channels {
channels[i].Close()
}
}()
var sliderImg gocv.Mat
var mask gocv.Mat
// 如果有 alpha 通道(4通道),提取 mask
if len(channels) == 4 {
// 前3个通道是 BGR
sliderImg = gocv.NewMat()
defer sliderImg.Close()
gocv.Merge(channels[:3], &sliderImg)
// 使用 alpha 通道作为 mask
mask = channels[3].Clone()
defer mask.Close()
} else if len(channels) == 3 {
// 没有透明通道,直接使用原图
sliderImg = sliderImgWithAlpha.Clone()
defer sliderImg.Close()
mask = gocv.NewMat() // 空 mask
defer mask.Close()
} else {
return -1
}
// 创建结果矩阵用于存储匹配结果
result := gocv.NewMat()
defer result.Close()
// 直接在原图上使用模板匹配找到滑块位置
if mask.Empty() {
gocv.MatchTemplate(bgImg, sliderImg, &result, gocv.TmCcoeffNormed, gocv.NewMat())
} else {
// 带 mask 的模板匹配
gocv.MatchTemplate(bgImg, sliderImg, &result, gocv.TmCcoeffNormed, mask)
}
// 找到最佳匹配位置
_, maxVal, _, maxLoc := gocv.MinMaxLoc(result)
// 如果匹配度太低,返回 -1 表示失败
if maxVal < 0.6 {
return -1
}
// 获取原图上的 x 坐标,然后按比例缩放到目标尺寸
originalWidth := bgImg.Cols()
targetWidth := 280
scale := float64(targetWidth) / float64(originalWidth)
scaledX := int(float64(maxLoc.X) * scale)
// 返回缩放后的 x 坐标(滑块需要移动的距离)
return scaledX
}
@@ -0,0 +1,37 @@
package cryptoutil
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"likedream-goframe/internal/framework/logger"
"go.uber.org/zap"
)
const (
KEY = "u2oh6Vu^HWe4_AES"
)
func LoginEncrypt(str string) (string, error) {
key := []byte(KEY)
block, err := aes.NewCipher(key)
if err != nil {
logger.Logger.Error("aes.NewCipher err:", zap.Error(err))
return "", err
}
paddedData := pad([]byte(str), block.BlockSize())
ciphertext := make([]byte, len(paddedData))
mode := cipher.NewCBCEncrypter(block, key)
mode.CryptBlocks(ciphertext, paddedData)
data := base64.StdEncoding.EncodeToString(ciphertext)
return data, nil
}
// pad 确保数据长度是块大小的整数倍,以便符合块加密算法的要求
func pad(src []byte, blockSize int) []byte {
padding := blockSize - len(src)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(src, padText...)
}
@@ -0,0 +1,72 @@
package entity
// XueXiTCourse 课程所有信息
type XueXiTCourseJson struct {
Result int `json:"result"`
Msg string `json:"msg"`
ChannelList []ChannelItem `json:"channelList"`
Mcode string `json:"mcode"`
Createcourse int `json:"createcoursed"`
TeacherEndCourse int `json:"teacherEndCourse"`
ShowEndCourse int `json:"showEndCourse"`
HasMore bool `json:"hasMore"`
StuEndCourse int `json:"stuEndCourse"`
}
// ChannelItem 课程列表
type ChannelItem struct {
Cfid int `json:"cfid"`
Norder int `json:"norder"`
CataName string `json:"cataName"`
Cataid string `json:"cataid"`
Id int `json:"id"`
Cpi int `json:"cpi"`
Key any `json:"key"`
Content struct {
Studentcount int `json:"studentcount"`
Chatid string `json:"chatid"`
IsFiled int `json:"isFiled"`
Isthirdaq int `json:"isthirdaq"`
Isstart bool `json:"isstart"`
Isretire int `json:"isretire"`
Name string `json:"name"`
Course struct {
Data []struct {
BelongSchoolId string `json:"belongSchoolId"`
Coursestate int `json:"coursestate"`
Teacherfactor string `json:"teacherfactor"`
IsCourseSquare int `json:"isCourseSquare"`
Schools string `json:"schools"`
CourseSquareUrl string `json:"courseSquareUrl"`
Imageurl string `json:"imageurl"`
AppInfo string `json:"appInfo"`
Name string `json:"name"`
DefaultShowCatalog int `json:"defaultShowCatalog"`
Id int `json:"id"`
AppData int `json:"appData"`
} `json:"data"`
} `json:"course"`
Roletype int `json:"roletype"`
Id int `json:"id"`
State int `json:"state"`
Cpi int `json:"cpi"`
Bbsid string `json:"bbsid"`
IsSquare int `json:"isSquare"`
} `json:"content"`
Topsign int `json:"topsign"`
}
type XueXiTCourse struct {
Cpi int `json:"cpi"` // 用户唯一标识
Key string `json:"key"` // classID 在课程API中为key
CourseID string `json:"courseId"` // 课程ID
ChatID string `json:"chatId"`
CourseTeacher string `json:"courseTeacher"` // 课程老师
CourseName string `json:"courseName"` //课程名
CourseImage string `json:"courseImage"`
// 两个标识 暂时不知道有什么用
CourseDataID int `json:"courseDataId"`
ContentID int `json:"ContentID"`
IsStart bool `json:"isstart"` //是否开课了,开课了为true,没开课为false。一般来说开课才能刷,不然刷不了的
State int `json:"state"` //课程状态,0为正常,1为课程已经结束
}
@@ -0,0 +1,86 @@
package xuexitong
import (
"fmt"
"io"
"likedream-goframe/internal/utils"
"log"
"math/rand"
"os"
"strings"
"time"
"resty.dev/v3"
)
var randChar []string = []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "A", "B", "C", "D", "E", "F"}
func ApiVerifyCode(client *resty.Client, retry int) (string, error) {
if retry < 0 {
return "", fmt.Errorf("retry limit exceeded")
}
urlStr := "https://mooc1-api.chaoxing.com/processVerifyPng.ac?t=" + fmt.Sprintf("%d", time.Now().UnixMilli())
req := client.R()
req.Header.Add("User-Agent", GetUA("mobile"))
req.Header.Add("Accept", "*/*")
req.Header.Add("Host", "mooc1-api.chaoxing.com")
req.Header.Add("Connection", "keep-alive")
res, err := req.Get(urlStr)
if err != nil {
if retry > 0 {
return ApiVerifyCode(client, retry-1)
} else {
return res.String(), err
}
}
codeFileName := "code" + randChar[rand.Intn(len(randChar))] //生成验证码文件名称
for i := 0; i < 10; i++ {
codeFileName += randChar[rand.Intn(len(randChar))]
}
codeFileName += ".png"
utils.PathExistForCreate("./assets/code/") //检测是否存在路径,如果不存在则创建
filepath := fmt.Sprintf("./assets/code/%s", codeFileName)
file, err := os.Create(filepath)
if err != nil {
res.Body.Close() //立即释放
log.Println(err)
return "", err
}
_, err = io.Copy(file, res.Body)
if err != nil {
res.Body.Close() //立即释放
log.Println(err)
return "", err
}
file.Close()
if utils.IsBadImg(filepath) {
res.Body.Close() //立即释放
utils.DeleteFile(filepath) //删除坏的文件
return ApiVerifyCode(client, retry-1)
}
return filepath, nil
}
func ApiPassVerifyCode(client *resty.Client, code string, retry int) bool {
if retry < 0 {
return false
}
urlStr := "https://mooc1-api.chaoxing.com/html/processVerify.ac"
client.SetRedirectPolicy(resty.NoRedirectPolicy())
req := client.R()
req.SetMultipartField("ucode", "", "", strings.NewReader(code))
req.SetMultipartField("app", "", "", strings.NewReader("0"))
req.Header.Add("User-Agent", GetUA("mobile"))
req.Header.Add("Accept", "*/*")
req.Header.Add("Host", "mooc1-api.chaoxing.com")
req.Header.Add("Connection", "keep-alive")
res, err := req.Post(urlStr)
if err != nil {
return ApiPassVerifyCode(client, code, retry-1)
}
client.SetRedirectPolicy(resty.FlexibleRedirectPolicy(20))
return res.StatusCode() == 302
}
@@ -0,0 +1,101 @@
package xuexitong
import (
"context"
"errors"
"likedream-goframe/internal/application/recognizer/ddddocr"
"likedream-goframe/internal/application/xuexitong/entity"
"likedream-goframe/internal/framework/logger"
"likedream-goframe/internal/utils"
"strings"
"github.com/bytedance/sonic"
ort "github.com/yalue/onnxruntime_go"
"resty.dev/v3"
)
const (
ApiPullCourses = "https://mooc1-api.chaoxing.com/mycourse/backclazzdata"
)
type XuexitongCourse struct {
client *resty.Client
}
func NewXuexitongCourse(client *resty.Client) *XuexitongCourse {
return &XuexitongCourse{
client: client,
}
}
// PullCourseList 拉取学习通所有课程列表并返回
func (c *XuexitongCourse) PullCourseList(ctx context.Context, retry int) (courseList []entity.XueXiTCourse, err error) {
req := c.client.R()
req.Header.Add("User-Agent", GetUA("mobile"))
get, err := req.Get(ApiPullCourses)
if err != nil {
return nil, err
}
body := get.String()
if strings.Contains(body, "很抱歉,您所浏览的页面不存在") && retry > 0 { //防止学习通抽风
return c.PullCourseList(ctx, retry-1)
}
if strings.Contains(body, "请输入验证码") {
logger.Logger.Warn("触发验证码,正在进行AI智能识别绕过.....")
//todo ddddocr识别
succ := false
for i := 0; i < 5; i++ {
codePath, err := ApiVerifyCode(c.client, 5)
if err != nil {
return nil, err
}
if codePath == "" { //如果path为空,那么可能是账号问题
return nil, errors.New("无法正常获取学习通验证码,请检查对应url是否正常")
}
img, _ := utils.ReadImg(codePath) //读取验证码图片
codeResult := ddddocr.SemiOCRVerification(img, ort.NewShape(1, 23))
utils.DeleteFile(codePath) //删除验证码文件、
if ApiPassVerifyCode(c.client, codeResult, 5) {
succ = true
break
}
}
if !succ {
return nil, errors.New("AI验证码识别失败,请检查对应url是否正常")
}
}
var courseResult entity.XueXiTCourseJson
err = sonic.Unmarshal([]byte(body), &courseResult)
if err != nil {
return nil, err
}
for _, channel := range courseResult.ChannelList {
if channel.Content.Course.Data == nil {
continue
}
for _, v := range channel.Content.Course.Data {
flag := false
course := entity.XueXiTCourse{
Cpi: channel.Cpi,
Key: strings.Split(strings.Split(v.CourseSquareUrl, "classId=")[1], "&userId")[0],
CourseID: strings.Split(strings.Split(v.CourseSquareUrl, "courseId=")[1], "&personId")[0],
CourseTeacher: v.Teacherfactor,
CourseImage: v.Name,
CourseDataID: v.Id,
ContentID: channel.Content.Id,
IsStart: channel.Content.Isstart,
State: channel.Content.State,
}
for _, subCourse := range courseList {
if subCourse.CourseID == course.CourseID {
flag = true
break
}
}
if !flag {
courseList = append(courseList, course)
}
}
}
return courseList, nil
}
@@ -0,0 +1,76 @@
package xuexitong
import (
"context"
"likedream-goframe/internal/application/cookiejar"
"likedream-goframe/internal/application/httpclient"
"likedream-goframe/internal/application/xuexitong/cryptoutil"
"likedream-goframe/internal/framework/logger"
"net/http"
"strings"
"time"
"go.uber.org/zap"
"resty.dev/v3"
)
const (
ApiLoginWeb = "https://passport2.chaoxing.com/fanyalogin"
)
type XuexitongLogin struct {
client *resty.Client
}
func NewXuexitongLogin(ctx context.Context) *XuexitongLogin {
return &XuexitongLogin{
client: httpclient.Xuexitong.Clone(ctx),
}
}
func (c *XuexitongLogin) Login(ctx context.Context, username, password string, retry int) (err error) {
usernameEncrypted, err := cryptoutil.LoginEncrypt(username)
if err != nil {
logger.Logger.Error("LoginEncrypt err:", zap.Error(err))
return err
}
passwordEncrypted, err := cryptoutil.LoginEncrypt(password)
if err != nil {
logger.Logger.Error("LoginEncrypt err:", zap.Error(err))
return err
}
resp, err := c.client.R().SetFormData(map[string]string{
"fid": "-1",
"uname": usernameEncrypted,
"password": passwordEncrypted,
"refer": "http%3A%2F%2Fi.mooc.chaoxing.com",
"t": "true",
"forbidotherlogin": "0",
"validate": "",
"doubleFactorLogin": "0",
"independentId": "0",
"independentNameId": "0",
}).Post(ApiLoginWeb)
if err != nil {
logger.Logger.Error("LoginPost err:", zap.Error(err))
return err
}
body := resp.String()
//触发风控直接重新登录
if strings.Contains(body, "很抱歉,您所浏览的页面暂时不能访问!") && retry > 0 {
time.Sleep(time.Duration(retry*5) * time.Second)
return c.Login(ctx, username, password, retry-1)
}
return nil
}
func (c *XuexitongLogin) GetCookieJar() http.CookieJar {
return c.client.CookieJar()
}
func (c *XuexitongLogin) GetCookieString() string {
cookieJar := c.GetCookieJar()
serializableJar := cookieJar.(*cookiejar.PersistCookieJar)
return serializableJar.Serialize()
}
func (c *XuexitongLogin) GetClient() *resty.Client {
return c.client.SetRedirectPolicy(resty.NoRedirectPolicy())
}
@@ -0,0 +1,18 @@
package xuexitong
import (
"context"
"likedream-goframe/internal/utils"
"testing"
)
func TestXuexitongLogin(t *testing.T) {
xuexitongLogin := NewXuexitongLogin(context.Background())
err := xuexitongLogin.Login(context.Background(), "13551503012", "xiaozhi520", 5)
utils.OkOrPanic(err)
client := xuexitongLogin.GetClient()
courseAction := NewXuexitongCourse(client)
list, err := courseAction.PullCourseList(context.Background(), 5)
utils.OkOrPanic(err)
t.Log(list)
}
@@ -0,0 +1,77 @@
package xuexitong
import (
"crypto/md5"
"encoding/hex"
"fmt"
"math/rand"
"strings"
)
const (
APP_VERSION = "6.6.4"
DEVICE_VENDOR = "MI10"
BUILD = "10831_263"
//BUILD = "10903_285"
ANDROID_VERSION = "Android 11"
)
var IMEI = TokenHex(16)
// GetUA 构建并获取 UA
func GetUA(uaType string) string {
switch uaType {
case "mobile":
//return strings.Join([]string{
// fmt.Sprintf("Dalvik/2.1.0 (Linux; U; %s; %s Build/SKQ1.210216.001)", ANDROID_VERSION, DEVICE_VENDOR),
// fmt.Sprintf("(schild:%s)", MobileUASign(DEVICE_VENDOR, "zh_CN", APP_VERSION, BUILD, IMEI)),
// fmt.Sprintf("(device:%s)", DEVICE_VENDOR),
// "Language/zh_CN",
// fmt.Sprintf("com.chaoxing.mobile/ChaoXingStudy_3_%s_android_phone_%s", APP_VERSION, BUILD),
// //APP_VERSION,
// fmt.Sprintf("(@Kalimdor)_%s", IMEI),
//}, " ")
return strings.Join([]string{
fmt.Sprintf("Mozilla/5.0 (Linux; %s; %s Build/OPM1.171019.019; wv)", ANDROID_VERSION, DEVICE_VENDOR),
fmt.Sprintf("AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/71.0.3578.99 Mobile Safari/537.36"),
fmt.Sprintf("(schild:%s)", MobileUASign(DEVICE_VENDOR, "zh_CN", APP_VERSION, BUILD, IMEI)),
fmt.Sprintf("(device:%s)", DEVICE_VENDOR),
"Language/zh_CN",
fmt.Sprintf("com.chaoxing.mobile/ChaoXingStudy_3_%s_android_phone_%s", APP_VERSION, BUILD),
fmt.Sprintf("(@Kalimdor)_%s", IMEI),
}, " ")
case "web":
return "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35"
default:
return ""
}
}
// 用于生成IMEI
func TokenHex(len int) string {
b := make([]byte, 16)
_, err := rand.Read(b)
if err != nil {
panic(err)
}
token := hex.EncodeToString(b)
return token
}
func MobileUASign(model, locale, version, build, imei string) string {
// 拼接字符串,和 Python 的 " ".join 相同
str := strings.Join([]string{
"(schild:ipL$TkeiEmfy1gTXb2XHrdLN0a@7c^vu)",
fmt.Sprintf("(device:%s)", model),
fmt.Sprintf("Language/%s", locale),
fmt.Sprintf("com.chaoxing.mobile/ChaoXingStudy_3_%s_android_phone_%s", version, build),
fmt.Sprintf("(@Kalimdor)_%s", imei),
}, " ")
// 计算 md5
hash := md5.Sum([]byte(str))
// 转换为小写 hex 字符串
return fmt.Sprintf("%x", hash)
}
+5
View File
@@ -0,0 +1,5 @@
package cst
const (
BasePointCpdaily = 1
)
+47
View File
@@ -0,0 +1,47 @@
package cst
import "time"
const (
ConfigOcrServerUrl = "ocr.url"
ConfigEnvMode = "env.mode"
ConfigDatabaseType = "database.type"
ConfigDatabaseDsn = "database.dsn"
ConfigDatabaseDsn2 = "database.dsn2"
ConfigServerPort = "server.port"
ConfigEmailConfirmBaseUrl = "server.emailConfirmBaseUrl"
ConfigEmailResetPasswordUrl = "server.emailResetPasswordUrl"
ConfigBalanceMigrateUrl = "server.balanceMigrateUrl"
ConfigAuthorizationKey = "server.authorization"
ConfigJwtKey = "server.jwt"
ConfigRuoliCaptchaBaseUrl = "ruoliCaptcha.baseUrl"
ConfigS3AccessKey = "s3.accessKey"
ConfigS3SecretKey = "s3.secretKey"
ConfigS3BaseUrl = "s3.baseUrl"
ConfigS3Bucket = "s3.bucket"
ConfigCpdailyAppVersion = "cpdaily.appVersion"
ConfigCpdailySystemVersion = "cpdaily.systemVersion"
ConfigCpdailyCalVersion = "cpdaily.calVersion"
ConfigRedisUrl = "redis.url"
ConfigTaskConcurrency = "task.concurrency"
// Email配置常量
ConfigEmailSMTPHost = "email.smtpHost"
ConfigEmailSMTPPort = "email.smtpPort"
ConfigEmailSMTPUsername = "email.smtpUsername"
ConfigEmailSMTPPassword = "email.smtpPassword"
ConfigEmailFromEmail = "email.fromEmail"
ConfigEmailFromName = "email.fromName"
)
const (
// 应用程序常量
AppName = "若梦系统"
AppCopyright = "© 2025 若梦系统. 保留所有权利."
)
var (
TimeZoneShangHai, _ = time.LoadLocation("Asia/Shanghai")
)
@@ -3,6 +3,8 @@ package cst
const (
RedisUserInfo = "userinfo:"
RedisVerifyCode = "verifycode:"
RedisResetPassword = "resetpassword:"
RedisBalanceMigrate = "balancemigrate:" // 积分转移token
RedisCpUserLogin = "cpuserlogin:"
RedisCpUserAuthorize = "cpuser:authorize:"
)
@@ -10,6 +12,8 @@ const (
var (
RedisUserInfoExpire = int64(86400)
RedisVerifyCodeExpire = int64(86400)
RedisResetPasswordExpire = int64(3600) // 重置密码链接1小时有效
RedisBalanceMigrateExpire = int64(3600) // 积分转移链接1小时有效
RedisCpUserLoginExpire = int64(180)
RedisCpUserAuthorizeExpire = int64(1800)
)
+13
View File
@@ -0,0 +1,13 @@
package cst
const (
TaskCpdaily = "task:cpdaily"
TaskEmail = "task:email"
TaskResetDaily = "task:reset:daily"
TaskCpdailyId = "cpdaily:task:schedule:%d"
TaskQueueCpdaily = "queue:cpdaily"
TaskQueueEmail = "queue:email"
TaskQueueDefault = "default"
)
@@ -2,17 +2,18 @@ package db
import (
"context"
"github.com/gogf/gf/v2/os/gctx"
"github.com/shopspring/decimal"
"likedream-goframe/internal/cst"
"likedream-goframe/internal/common/cst"
"likedream-goframe/internal/ent/sysmenu"
"likedream-goframe/internal/ent/sysrole"
"likedream-goframe/internal/ent/sysuser"
"likedream-goframe/internal/utils"
"github.com/gogf/gf/v2/os/gctx"
"github.com/shopspring/decimal"
)
func CheckHasData() bool {
count, err := Global.SysUser.Query().Count(context.Background())
count, err := Global.Debug().SysUser.Query().Count(context.Background())
utils.OkOrPanic(err, func(err error) error {
return err
})
@@ -35,7 +36,7 @@ func GenerateData() {
// 生成用户
func generateUser() {
ctx := gctx.New()
Global.SysUser.Create().
Global.Debug().SysUser.Create().
SetUsername("admin").
SetPassword(utils.PasswordBcryptHash("123456")).
SetEmail("admin@qq.com").
@@ -49,15 +50,15 @@ func generateUser() {
// 生成角色
func generateRoles() {
ctx := gctx.New()
Global.SysRole.Create().SetName("管理员").SetLabel(cst.KeyRoleAdmin).SetDescription("超级管理员角色").SetOrder(1).ExecX(ctx)
Global.SysRole.Create().SetName("代理").SetLabel(cst.KeyRoleAgent).SetDescription("代理角色").SetOrder(2).ExecX(ctx)
Global.SysRole.Create().SetName("普通用户").SetLabel(cst.KeyRoleUser).SetDescription("普通用户角色").SetOrder(3).ExecX(ctx)
Global.Debug().SysRole.Create().SetName("管理员").SetLabel(cst.KeyRoleAdmin).SetDescription("超级管理员角色").SetOrder(1).ExecX(ctx)
Global.Debug().SysRole.Create().SetName("代理").SetLabel(cst.KeyRoleAgent).SetDescription("代理角色").SetOrder(2).ExecX(ctx)
Global.Debug().SysRole.Create().SetName("普通用户").SetLabel(cst.KeyRoleUser).SetDescription("普通用户角色").SetOrder(3).ExecX(ctx)
}
// 生成菜单
func generateMenus() {
ctx := gctx.New()
sysM := Global.SysMenu.Create().
sysM := Global.Debug().SysMenu.Create().
SetName("系统管理").
SetLabel("system").
SetType(sysmenu.TypeGroup).
@@ -65,7 +66,7 @@ func generateMenus() {
SetRoute("/system").
SetOrder(1).
SaveX(ctx)
userM := Global.SysMenu.Create().
userM := Global.Debug().SysMenu.Create().
SetName("用户管理").
SetLabel("user").
SetType(sysmenu.TypeMenu).
@@ -76,7 +77,7 @@ func generateMenus() {
SetParent(sysM).
SaveX(ctx)
// 新增 编辑 删除按钮
Global.SysMenu.Create().
Global.Debug().SysMenu.Create().
SetName("新增").
SetLabel("add").
SetType(sysmenu.TypeButton).
@@ -84,7 +85,7 @@ func generateMenus() {
SetOrder(1).
SetParent(userM).
SaveX(ctx)
Global.SysMenu.Create().
Global.Debug().SysMenu.Create().
SetName("编辑").
SetLabel("edit").
SetType(sysmenu.TypeButton).
@@ -93,7 +94,7 @@ func generateMenus() {
SetParent(userM).
SaveX(ctx)
// 删除按钮
Global.SysMenu.Create().
Global.Debug().SysMenu.Create().
SetName("删除").
SetLabel("delete").
SetType(sysmenu.TypeButton).
@@ -102,7 +103,7 @@ func generateMenus() {
SetParent(userM).
SaveX(ctx)
// 列表
Global.SysMenu.Create().
Global.Debug().SysMenu.Create().
SetName("列表").
SetLabel("list").
SetType(sysmenu.TypeButton).
@@ -110,7 +111,7 @@ func generateMenus() {
SetOrder(4).
SetParent(userM).
SaveX(ctx)
roleM := Global.SysMenu.Create().
roleM := Global.Debug().SysMenu.Create().
SetName("角色管理").
SetLabel("role").
SetType(sysmenu.TypeMenu).
@@ -121,7 +122,7 @@ func generateMenus() {
SetParent(sysM).
SaveX(ctx)
// 新增 编辑 删除按钮
Global.SysMenu.Create().
Global.Debug().SysMenu.Create().
SetName("新增").
SetLabel("add").
SetType(sysmenu.TypeButton).
@@ -129,7 +130,7 @@ func generateMenus() {
SetOrder(1).
SetParent(roleM).
SaveX(ctx)
Global.SysMenu.Create().
Global.Debug().SysMenu.Create().
SetName("编辑").
SetLabel("edit").
SetType(sysmenu.TypeButton).
@@ -138,7 +139,7 @@ func generateMenus() {
SetParent(roleM).
SaveX(ctx)
// 删除按钮
Global.SysMenu.Create().
Global.Debug().SysMenu.Create().
SetName("删除").
SetLabel("delete").
SetType(sysmenu.TypeButton).
@@ -146,7 +147,7 @@ func generateMenus() {
SetOrder(3).
SetParent(roleM).
SaveX(ctx)
Global.SysMenu.Create().
Global.Debug().SysMenu.Create().
SetName("列表").
SetLabel("list").
SetType(sysmenu.TypeButton).
@@ -154,7 +155,7 @@ func generateMenus() {
SetOrder(4).
SetParent(roleM).
SaveX(ctx)
menuM := Global.SysMenu.Create().
menuM := Global.Debug().SysMenu.Create().
SetName("菜单管理").
SetLabel("menu").
SetType(sysmenu.TypeMenu).
@@ -165,7 +166,7 @@ func generateMenus() {
SetParent(sysM).
SaveX(ctx)
// 新增 编辑 删除按钮
Global.SysMenu.Create().
Global.Debug().SysMenu.Create().
SetName("新增").
SetLabel("add").
SetType(sysmenu.TypeButton).
@@ -173,7 +174,7 @@ func generateMenus() {
SetOrder(1).
SetParent(menuM).
SaveX(ctx)
Global.SysMenu.Create().
Global.Debug().SysMenu.Create().
SetName("编辑").
SetLabel("edit").
SetType(sysmenu.TypeButton).
@@ -182,7 +183,7 @@ func generateMenus() {
SetParent(menuM).
SaveX(ctx)
// 删除按钮
Global.SysMenu.Create().
Global.Debug().SysMenu.Create().
SetName("删除").
SetLabel("delete").
SetType(sysmenu.TypeButton).
@@ -190,7 +191,7 @@ func generateMenus() {
SetOrder(3).
SetParent(menuM).
SaveX(ctx)
Global.SysMenu.Create().
Global.Debug().SysMenu.Create().
SetName("列表").
SetLabel("list").
SetType(sysmenu.TypeButton).
@@ -203,14 +204,14 @@ func generateMenus() {
// 关联角色
func relationRoles() {
ctx := gctx.New()
admin := Global.SysUser.Query().Where(sysuser.UsernameEQ("admin")).OnlyX(ctx)
role := Global.SysRole.Query().Where(sysrole.LabelEQ(cst.KeyRoleAdmin)).AllX(ctx)
Global.SysUser.UpdateOne(admin).AddRoles(role...).ExecX(ctx)
admin := Global.Debug().SysUser.Query().Where(sysuser.UsernameEQ("admin")).OnlyX(ctx)
role := Global.Debug().SysRole.Query().Where(sysrole.LabelEQ(cst.KeyRoleAdmin)).AllX(ctx)
Global.Debug().SysUser.UpdateOne(admin).AddRoles(role...).ExecX(ctx)
}
// 关联菜单
func relationMenus() {
ctx := gctx.New()
adminRole := Global.SysRole.Query().Where(sysrole.LabelEQ(cst.KeyRoleAdmin)).OnlyX(ctx)
Global.SysRole.UpdateOne(adminRole).AddMenus(Global.SysMenu.Query().AllX(ctx)...).ExecX(ctx)
adminRole := Global.Debug().SysRole.Query().Where(sysrole.LabelEQ(cst.KeyRoleAdmin)).OnlyX(ctx)
Global.Debug().SysRole.UpdateOne(adminRole).AddMenus(Global.Debug().SysMenu.Query().AllX(ctx)...).ExecX(ctx)
}
+50
View File
@@ -0,0 +1,50 @@
package db
import (
"context"
"likedream-goframe/internal/common/cst"
"likedream-goframe/internal/ent"
"likedream-goframe/internal/framework/logger"
"likedream-goframe/internal/utils"
_ "github.com/go-sql-driver/mysql"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"go.uber.org/zap"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
var Global *ent.Client
var GlobalGorm *gorm.DB
func InitDB() {
dbType, err := g.Cfg().Get(gctx.New(), cst.ConfigDatabaseType)
utils.OkOrPanic(err)
dbDsn, err := g.Cfg().Get(gctx.New(), cst.ConfigDatabaseDsn)
utils.OkOrPanic(err)
client, err := ent.Open(dbType.String(), dbDsn.String())
utils.OkOrPanic(err)
// 自动迁移
if err := client.Debug().Schema.Create(context.Background()); err != nil {
logger.Logger.Fatal("failed creating schema resources: %v", zap.Error(err))
}
Global = client
dbDsn2, err := g.Cfg().Get(gctx.New(), cst.ConfigDatabaseDsn2)
utils.OkOrPanic(err)
GlobalGorm, err = gorm.Open(postgres.Open(dbDsn2.String()), &gorm.Config{})
if err != nil {
logger.Logger.Fatal("连接pg数据库失败: %v", zap.Error(err))
}
// 可选:配置连接池
sqlDB, err := GlobalGorm.DB()
if err != nil {
logger.Logger.Fatal("获取数据库实例失败: %v", zap.Error(err))
}
// 设置连接池参数
sqlDB.SetMaxIdleConns(10) // 设置空闲连接池中连接的最大数量
sqlDB.SetMaxOpenConns(100) // 设置打开数据库连接的最大数量
sqlDB.SetConnMaxLifetime(0) // 设置连接可复用的最大时间(0表示永久)
}
+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
}
+1 -1
View File
@@ -23,7 +23,7 @@ func (a AgentCtrlV1) List(ctx context.Context, req *v1.AgentListReq) (res *utils
// Add 添加下级代理
func (a AgentCtrlV1) Add(ctx context.Context, req *v1.AgentAddReq) (res *utils.Response[any], err error) {
defer utils.Pass(&err)
return service.Global.Agent.Add(ctx, req), nil
panic("implement me")
}
// Ban 禁用代理
+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/recognizer/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 {
+13
View File
@@ -0,0 +1,13 @@
package music
import (
"context"
v1 "likedream-goframe/internal/api/v1"
"likedream-goframe/internal/application/music"
"likedream-goframe/internal/utils"
)
type IMusicCtrlV1 interface {
Search(ctx context.Context, req *v1.SearchMusicReq) (res *utils.Response[[]music.MusicSearchResult], err error)
Download(ctx context.Context, req *v1.DownloadMusicReq) (res *utils.Response[any], err error)
}
+28
View File
@@ -0,0 +1,28 @@
package music
import (
"context"
v1 "likedream-goframe/internal/api/v1"
"likedream-goframe/internal/application/music"
"likedream-goframe/internal/utils"
)
type MusicCtrlV1 struct {
}
func NewMusicCtrlV1() IMusicCtrlV1 {
return &MusicCtrlV1{}
}
func (c *MusicCtrlV1) Search(ctx context.Context, req *v1.SearchMusicReq) (res *utils.Response[[]music.MusicSearchResult], err error) {
defer utils.Pass(&err)
return utils.SuccessWithData(music.MusicDownloader.Search(ctx, req.Keyword)), nil
}
func (c *MusicCtrlV1) Download(ctx context.Context, req *v1.DownloadMusicReq) (res *utils.Response[any], err error) {
defer utils.Pass(&err)
// 获取音频下载地址
downloadUrl := music.MusicDownloader.Download(ctx, req.Path)
return utils.SuccessWithData[any](downloadUrl), nil
}
@@ -25,4 +25,7 @@ type IUserInfoV1 interface {
InviteUserList(ctx context.Context, req *v1.CommonPageReq) (*utils.Response[[]*v1.UserInviteRes], error)
// 生成邀请码
GenerateInviteCode(ctx context.Context, req *v1.CommonPostReq) (*utils.Response[any], error)
RequestBalanceMigrate(ctx context.Context, req *v1.RequestBalanceMigrateReq) (*utils.Response[any], error)
BalanceMigrate(ctx context.Context, req *v1.BalanceMigrateReq) (*utils.Response[any], error)
}
@@ -13,4 +13,8 @@ type IUserLoginV1 interface {
Login(ctx context.Context, req *v1.UserLoginReq) (*utils.Response[any], error)
Register(ctx context.Context, req *v1.UserRegisterReq) (*utils.Response[any], error)
Confirm(ctx context.Context, req *v1.UserConfirmReq) (*utils.Response[any], error)
ResendVerification(ctx context.Context, req *v1.ResendVerificationReq) (*utils.Response[any], error)
ForgotPassword(ctx context.Context, req *v1.ForgotPasswordReq) (*utils.Response[any], error)
ResetPassword(ctx context.Context, req *v1.ForgetResetPasswordReq) (*utils.Response[any], error)
GetResetPasswordInfo(ctx context.Context, req *v1.ResetPasswordInfoReq) (*utils.Response[any], error)
}
@@ -4,8 +4,12 @@ import (
"context"
v1 "likedream-goframe/internal/api/v1"
"likedream-goframe/internal/ent"
"likedream-goframe/internal/framework/captcha"
"likedream-goframe/internal/framework/redis"
"likedream-goframe/internal/service"
"likedream-goframe/internal/utils"
"github.com/bytedance/sonic"
)
type UserInfoV1 struct {
@@ -60,3 +64,34 @@ func (c *UserInfoV1) GenerateInviteCode(ctx context.Context, req *v1.CommonPostR
defer utils.Pass(&err)
return service.Global.UserInfo.GenerateInviteCode(ctx, req), nil
}
func (c *UserInfoV1) RequestBalanceMigrate(ctx context.Context, req *v1.RequestBalanceMigrateReq) (res *utils.Response[any], err error) {
defer utils.Pass(&err)
client := redis.GetClient()
dotsStr := client.GetDel(ctx, req.CaptchaKey).Val()
if dotsStr == "" {
return utils.Fail(10003, "验证码错误"), nil
}
var dots captcha.ConfirmData
err = sonic.Unmarshal([]byte(dotsStr), &dots)
utils.OkOrPanic(err)
if !captcha.VerifyCaptcha(dots, req.Dots) {
return utils.Fail(10003, "验证码错误"), nil
}
return service.Global.UserInfo.RequestBalanceMigrate(ctx, req), nil
}
func (c *UserInfoV1) BalanceMigrate(ctx context.Context, req *v1.BalanceMigrateReq) (res *utils.Response[any], err error) {
defer utils.Pass(&err)
client := redis.GetClient()
dotsStr := client.GetDel(ctx, req.CaptchaKey).Val()
if dotsStr == "" {
return utils.Fail(10003, "验证码错误"), nil
}
var dots captcha.ConfirmData
err = sonic.Unmarshal([]byte(dotsStr), &dots)
utils.OkOrPanic(err)
if !captcha.VerifyCaptcha(dots, req.Dots) {
return utils.Fail(10003, "验证码错误"), nil
}
return service.Global.UserInfo.BalanceMigrate(ctx, req), nil
}
+54 -1
View File
@@ -9,6 +9,8 @@ import (
"likedream-goframe/internal/service"
"likedream-goframe/internal/utils"
"time"
"github.com/bytedance/sonic"
)
type UserLoginV1 struct {
@@ -39,7 +41,7 @@ func (c *UserLoginV1) Login(ctx context.Context, req *v1.UserLoginReq) (res *uti
return utils.Fail(10003, "验证码错误"), nil
}
var dots captcha.ConfirmData
err = json.Unmarshal([]byte(dotsStr), &dots)
err = sonic.Unmarshal([]byte(dotsStr), &dots)
utils.OkOrPanic(err)
if !captcha.VerifyCaptcha(dots, req.Dots) {
return utils.Fail(10003, "验证码错误"), nil
@@ -49,9 +51,60 @@ func (c *UserLoginV1) Login(ctx context.Context, req *v1.UserLoginReq) (res *uti
func (c *UserLoginV1) Register(ctx context.Context, req *v1.UserRegisterReq) (res *utils.Response[any], err error) {
defer utils.Pass(&err)
client := redis.GetClient()
dotsStr := client.GetDel(ctx, req.CaptchaKey).Val()
if dotsStr == "" {
return utils.Fail(10003, "验证码错误"), nil
}
var dots captcha.ConfirmData
err = sonic.Unmarshal([]byte(dotsStr), &dots)
utils.OkOrPanic(err)
if !captcha.VerifyCaptcha(dots, req.Dots) {
return utils.Fail(10003, "验证码错误"), nil
}
return service.Global.UserLogin.Register(ctx, req), nil
}
func (c *UserLoginV1) Confirm(ctx context.Context, req *v1.UserConfirmReq) (*utils.Response[any], error) {
return service.Global.UserLogin.Confirm(ctx, req), nil
}
func (c *UserLoginV1) ResendVerification(ctx context.Context, req *v1.ResendVerificationReq) (res *utils.Response[any], err error) {
defer utils.Pass(&err)
client := redis.GetClient()
dotsStr := client.GetDel(ctx, req.CaptchaKey).Val()
if dotsStr == "" {
return utils.Fail(10003, "验证码错误"), nil
}
var dots captcha.ConfirmData
err = sonic.Unmarshal([]byte(dotsStr), &dots)
utils.OkOrPanic(err)
if !captcha.VerifyCaptcha(dots, req.Dots) {
return utils.Fail(10003, "验证码错误"), nil
}
return service.Global.UserLogin.ResendVerification(ctx, req), nil
}
func (c *UserLoginV1) ForgotPassword(ctx context.Context, req *v1.ForgotPasswordReq) (res *utils.Response[any], err error) {
defer utils.Pass(&err)
client := redis.GetClient()
dotsStr := client.GetDel(ctx, req.CaptchaKey).Val()
if dotsStr == "" {
return utils.Fail(10003, "验证码错误"), nil
}
var dots captcha.ConfirmData
err = sonic.Unmarshal([]byte(dotsStr), &dots)
utils.OkOrPanic(err)
if !captcha.VerifyCaptcha(dots, req.Dots) {
return utils.Fail(10003, "验证码错误"), nil
}
return service.Global.UserLogin.ForgotPassword(ctx, req), nil
}
func (c *UserLoginV1) ResetPassword(ctx context.Context, req *v1.ForgetResetPasswordReq) (*utils.Response[any], error) {
return service.Global.UserLogin.ResetPassword(ctx, req), nil
}
func (c *UserLoginV1) GetResetPasswordInfo(ctx context.Context, req *v1.ResetPasswordInfoReq) (*utils.Response[any], error) {
return service.Global.UserLogin.GetResetPasswordInfo(ctx, req), nil
}
-44
View File
@@ -1,44 +0,0 @@
package cst
import "time"
const (
ConfigOcrServerUrl = "ocr.url"
ConfigEnvMode = "env.mode"
ConfigDatabaseType = "database.type"
ConfigDatabaseDsn = "database.dsn"
ConfigServerPort = "server.port"
ConfigEmailConfirmBaseUrl = "server.emailConfirmBaseUrl"
ConfigAuthorizationKey = "server.authorization"
ConfigJwtKey = "server.jwt"
ConfigRuoliCaptchaBaseUrl = "ruoliCaptcha.baseUrl"
ConfigS3AccessKey = "s3.accessKey"
ConfigS3SecretKey = "s3.secretKey"
ConfigS3BaseUrl = "s3.baseUrl"
ConfigS3Bucket = "s3.bucket"
ConfigCpdailyAppVersion = "cpdaily.appVersion"
ConfigCpdailySystemVersion = "cpdaily.systemVersion"
ConfigCpdailyCalVersion = "cpdaily.calVersion"
ConfigRedisUrl = "redis.url"
ConfigTaskConcurrency = "task.concurrency"
// Email配置常量
ConfigEmailSMTPHost = "email.smtpHost"
ConfigEmailSMTPPort = "email.smtpPort"
ConfigEmailSMTPUsername = "email.smtpUsername"
ConfigEmailSMTPPassword = "email.smtpPassword"
ConfigEmailFromEmail = "email.fromEmail"
ConfigEmailFromName = "email.fromName"
)
const (
// 应用程序常量
AppName = "今日校园系统"
AppCopyright = "© 2024 今日校园系统. 保留所有权利."
)
var (
TimeZoneShangHai, _ = time.LoadLocation("Asia/Shanghai")
)
-9
View File
@@ -1,9 +0,0 @@
package cst
const (
TaskCpdaily = "task:cpdaily"
TaskEmail = "task:email"
TaskQueueCpdaily = "queue:cpdaily"
TaskQueueEmail = "queue:email"
)
-30
View File
@@ -1,30 +0,0 @@
package db
import (
"context"
"likedream-goframe/internal/cst"
"likedream-goframe/internal/ent"
"likedream-goframe/internal/framework/logger"
"likedream-goframe/internal/utils"
_ "github.com/go-sql-driver/mysql"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"go.uber.org/zap"
)
var Global *ent.Client
func InitDB() {
dbType, err := g.Cfg().Get(gctx.New(), cst.ConfigDatabaseType)
utils.OkOrPanic(err)
dbDsn, err := g.Cfg().Get(gctx.New(), cst.ConfigDatabaseDsn)
utils.OkOrPanic(err)
client, err := ent.Open(dbType.String(), dbDsn.String())
utils.OkOrPanic(err)
// 自动迁移
if err := client.Schema.Create(context.Background()); err != nil {
logger.Logger.Fatal("failed creating schema resources: %v", zap.Error(err))
}
Global = client
}
+8 -4
View File
@@ -575,7 +575,8 @@ func (c *CpSchoolClient) QueryCpusers(_m *CpSchool) *CpUserQuery {
// Hooks returns the client hooks.
func (c *CpSchoolClient) Hooks() []Hook {
return c.hooks.CpSchool
hooks := c.hooks.CpSchool
return append(hooks[:len(hooks):len(hooks)], cpschool.Hooks[:]...)
}
// Interceptors returns the client interceptors.
@@ -765,7 +766,8 @@ func (c *CpTaskClient) QueryCpTaskLogs(_m *CpTask) *CpTaskLogQuery {
// Hooks returns the client hooks.
func (c *CpTaskClient) Hooks() []Hook {
return c.hooks.CpTask
hooks := c.hooks.CpTask
return append(hooks[:len(hooks):len(hooks)], cptask.Hooks[:]...)
}
// Interceptors returns the client interceptors.
@@ -955,7 +957,8 @@ func (c *CpTaskLogClient) QueryCpUser(_m *CpTaskLog) *CpUserQuery {
// Hooks returns the client hooks.
func (c *CpTaskLogClient) Hooks() []Hook {
return c.hooks.CpTaskLog
hooks := c.hooks.CpTaskLog
return append(hooks[:len(hooks):len(hooks)], cptasklog.Hooks[:]...)
}
// Interceptors returns the client interceptors.
@@ -1164,7 +1167,8 @@ func (c *CpUserClient) QuerySchool(_m *CpUser) *CpSchoolQuery {
// Hooks returns the client hooks.
func (c *CpUserClient) Hooks() []Hook {
return c.hooks.CpUser
hooks := c.hooks.CpUser
return append(hooks[:len(hooks):len(hooks)], cpuser.Hooks[:]...)
}
// Interceptors returns the client interceptors.
+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
}
+25
View File
@@ -5,6 +5,7 @@ package ent
import (
"fmt"
"likedream-goframe/internal/ent/cpschool"
"likedream-goframe/internal/framework/ent2"
"strings"
"entgo.io/ent"
@@ -16,6 +17,10 @@ type CpSchool struct {
config `json:"-"`
// ID of the ent.
ID string `json:"id,omitempty"`
// CreateTime holds the value of the "create_time" field.
CreateTime *ent2.CustomTime `json:"createTime"`
// UpdateTime holds the value of the "update_time" field.
UpdateTime *ent2.CustomTime `json:"updateTime"`
// Name holds the value of the "name" field.
Name string `json:"name,omitempty"`
// NamePinyin holds the value of the "name_pinyin" field.
@@ -52,6 +57,8 @@ func (*CpSchool) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case cpschool.FieldCreateTime, cpschool.FieldUpdateTime:
values[i] = new(ent2.CustomTime)
case cpschool.FieldID, cpschool.FieldName, cpschool.FieldNamePinyin, cpschool.FieldIconImg:
values[i] = new(sql.NullString)
default:
@@ -75,6 +82,18 @@ func (_m *CpSchool) assignValues(columns []string, values []any) error {
} else if value.Valid {
_m.ID = value.String
}
case cpschool.FieldCreateTime:
if value, ok := values[i].(*ent2.CustomTime); !ok {
return fmt.Errorf("unexpected type %T for field create_time", values[i])
} else if value != nil {
_m.CreateTime = value
}
case cpschool.FieldUpdateTime:
if value, ok := values[i].(*ent2.CustomTime); !ok {
return fmt.Errorf("unexpected type %T for field update_time", values[i])
} else if value != nil {
_m.UpdateTime = value
}
case cpschool.FieldName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field name", values[i])
@@ -134,6 +153,12 @@ func (_m *CpSchool) String() string {
var builder strings.Builder
builder.WriteString("CpSchool(")
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
builder.WriteString("create_time=")
builder.WriteString(fmt.Sprintf("%v", _m.CreateTime))
builder.WriteString(", ")
builder.WriteString("update_time=")
builder.WriteString(fmt.Sprintf("%v", _m.UpdateTime))
builder.WriteString(", ")
builder.WriteString("name=")
builder.WriteString(_m.Name)
builder.WriteString(", ")
+32
View File
@@ -3,6 +3,9 @@
package cpschool
import (
"likedream-goframe/internal/framework/ent2"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
)
@@ -12,6 +15,10 @@ const (
Label = "cp_school"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldCreateTime holds the string denoting the create_time field in the database.
FieldCreateTime = "create_time"
// FieldUpdateTime holds the string denoting the update_time field in the database.
FieldUpdateTime = "update_time"
// FieldName holds the string denoting the name field in the database.
FieldName = "name"
// FieldNamePinyin holds the string denoting the name_pinyin field in the database.
@@ -34,6 +41,8 @@ const (
// Columns holds all SQL columns for cpschool fields.
var Columns = []string{
FieldID,
FieldCreateTime,
FieldUpdateTime,
FieldName,
FieldNamePinyin,
FieldIconImg,
@@ -49,6 +58,19 @@ func ValidColumn(column string) bool {
return false
}
// Note that the variables below are initialized by the runtime
// package on the initialization of the application. Therefore,
// it should be imported in the main as follows:
//
// import _ "likedream-goframe/internal/ent/runtime"
var (
Hooks [1]ent.Hook
// DefaultCreateTime holds the default value on creation for the "create_time" field.
DefaultCreateTime func() *ent2.CustomTime
// DefaultUpdateTime holds the default value on creation for the "update_time" field.
DefaultUpdateTime func() *ent2.CustomTime
)
// OrderOption defines the ordering options for the CpSchool queries.
type OrderOption func(*sql.Selector)
@@ -57,6 +79,16 @@ func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}
// ByCreateTime orders the results by the create_time field.
func ByCreateTime(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreateTime, opts...).ToFunc()
}
// ByUpdateTime orders the results by the update_time field.
func ByUpdateTime(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdateTime, opts...).ToFunc()
}
// ByName orders the results by the name field.
func ByName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldName, opts...).ToFunc()
+151
View File
@@ -5,6 +5,7 @@ package cpschool
import (
"likedream-goframe/internal/ent/internal"
"likedream-goframe/internal/ent/predicate"
"likedream-goframe/internal/framework/ent2"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
@@ -65,6 +66,16 @@ func IDContainsFold(id string) predicate.CpSchool {
return predicate.CpSchool(sql.FieldContainsFold(FieldID, id))
}
// CreateTime applies equality check predicate on the "create_time" field. It's identical to CreateTimeEQ.
func CreateTime(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldEQ(FieldCreateTime, v))
}
// UpdateTime applies equality check predicate on the "update_time" field. It's identical to UpdateTimeEQ.
func UpdateTime(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldEQ(FieldUpdateTime, v))
}
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
func Name(v string) predicate.CpSchool {
return predicate.CpSchool(sql.FieldEQ(FieldName, v))
@@ -80,6 +91,146 @@ func IconImg(v string) predicate.CpSchool {
return predicate.CpSchool(sql.FieldEQ(FieldIconImg, v))
}
// CreateTimeEQ applies the EQ predicate on the "create_time" field.
func CreateTimeEQ(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldEQ(FieldCreateTime, v))
}
// CreateTimeNEQ applies the NEQ predicate on the "create_time" field.
func CreateTimeNEQ(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldNEQ(FieldCreateTime, v))
}
// CreateTimeIn applies the In predicate on the "create_time" field.
func CreateTimeIn(vs ...*ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldIn(FieldCreateTime, vs...))
}
// CreateTimeNotIn applies the NotIn predicate on the "create_time" field.
func CreateTimeNotIn(vs ...*ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldNotIn(FieldCreateTime, vs...))
}
// CreateTimeGT applies the GT predicate on the "create_time" field.
func CreateTimeGT(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldGT(FieldCreateTime, v))
}
// CreateTimeGTE applies the GTE predicate on the "create_time" field.
func CreateTimeGTE(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldGTE(FieldCreateTime, v))
}
// CreateTimeLT applies the LT predicate on the "create_time" field.
func CreateTimeLT(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldLT(FieldCreateTime, v))
}
// CreateTimeLTE applies the LTE predicate on the "create_time" field.
func CreateTimeLTE(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldLTE(FieldCreateTime, v))
}
// CreateTimeContains applies the Contains predicate on the "create_time" field.
func CreateTimeContains(v *ent2.CustomTime) predicate.CpSchool {
vc := v.String()
return predicate.CpSchool(sql.FieldContains(FieldCreateTime, vc))
}
// CreateTimeHasPrefix applies the HasPrefix predicate on the "create_time" field.
func CreateTimeHasPrefix(v *ent2.CustomTime) predicate.CpSchool {
vc := v.String()
return predicate.CpSchool(sql.FieldHasPrefix(FieldCreateTime, vc))
}
// CreateTimeHasSuffix applies the HasSuffix predicate on the "create_time" field.
func CreateTimeHasSuffix(v *ent2.CustomTime) predicate.CpSchool {
vc := v.String()
return predicate.CpSchool(sql.FieldHasSuffix(FieldCreateTime, vc))
}
// CreateTimeEqualFold applies the EqualFold predicate on the "create_time" field.
func CreateTimeEqualFold(v *ent2.CustomTime) predicate.CpSchool {
vc := v.String()
return predicate.CpSchool(sql.FieldEqualFold(FieldCreateTime, vc))
}
// CreateTimeContainsFold applies the ContainsFold predicate on the "create_time" field.
func CreateTimeContainsFold(v *ent2.CustomTime) predicate.CpSchool {
vc := v.String()
return predicate.CpSchool(sql.FieldContainsFold(FieldCreateTime, vc))
}
// UpdateTimeEQ applies the EQ predicate on the "update_time" field.
func UpdateTimeEQ(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldEQ(FieldUpdateTime, v))
}
// UpdateTimeNEQ applies the NEQ predicate on the "update_time" field.
func UpdateTimeNEQ(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldNEQ(FieldUpdateTime, v))
}
// UpdateTimeIn applies the In predicate on the "update_time" field.
func UpdateTimeIn(vs ...*ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldIn(FieldUpdateTime, vs...))
}
// UpdateTimeNotIn applies the NotIn predicate on the "update_time" field.
func UpdateTimeNotIn(vs ...*ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldNotIn(FieldUpdateTime, vs...))
}
// UpdateTimeGT applies the GT predicate on the "update_time" field.
func UpdateTimeGT(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldGT(FieldUpdateTime, v))
}
// UpdateTimeGTE applies the GTE predicate on the "update_time" field.
func UpdateTimeGTE(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldGTE(FieldUpdateTime, v))
}
// UpdateTimeLT applies the LT predicate on the "update_time" field.
func UpdateTimeLT(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldLT(FieldUpdateTime, v))
}
// UpdateTimeLTE applies the LTE predicate on the "update_time" field.
func UpdateTimeLTE(v *ent2.CustomTime) predicate.CpSchool {
return predicate.CpSchool(sql.FieldLTE(FieldUpdateTime, v))
}
// UpdateTimeContains applies the Contains predicate on the "update_time" field.
func UpdateTimeContains(v *ent2.CustomTime) predicate.CpSchool {
vc := v.String()
return predicate.CpSchool(sql.FieldContains(FieldUpdateTime, vc))
}
// UpdateTimeHasPrefix applies the HasPrefix predicate on the "update_time" field.
func UpdateTimeHasPrefix(v *ent2.CustomTime) predicate.CpSchool {
vc := v.String()
return predicate.CpSchool(sql.FieldHasPrefix(FieldUpdateTime, vc))
}
// UpdateTimeHasSuffix applies the HasSuffix predicate on the "update_time" field.
func UpdateTimeHasSuffix(v *ent2.CustomTime) predicate.CpSchool {
vc := v.String()
return predicate.CpSchool(sql.FieldHasSuffix(FieldUpdateTime, vc))
}
// UpdateTimeEqualFold applies the EqualFold predicate on the "update_time" field.
func UpdateTimeEqualFold(v *ent2.CustomTime) predicate.CpSchool {
vc := v.String()
return predicate.CpSchool(sql.FieldEqualFold(FieldUpdateTime, vc))
}
// UpdateTimeContainsFold applies the ContainsFold predicate on the "update_time" field.
func UpdateTimeContainsFold(v *ent2.CustomTime) predicate.CpSchool {
vc := v.String()
return predicate.CpSchool(sql.FieldContainsFold(FieldUpdateTime, vc))
}
// NameEQ applies the EQ predicate on the "name" field.
func NameEQ(v string) predicate.CpSchool {
return predicate.CpSchool(sql.FieldEQ(FieldName, v))
+99 -3
View File
@@ -8,6 +8,7 @@ import (
"fmt"
"likedream-goframe/internal/ent/cpschool"
"likedream-goframe/internal/ent/cpuser"
"likedream-goframe/internal/framework/ent2"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql"
@@ -23,6 +24,18 @@ type CpSchoolCreate struct {
conflict []sql.ConflictOption
}
// SetCreateTime sets the "create_time" field.
func (_c *CpSchoolCreate) SetCreateTime(v *ent2.CustomTime) *CpSchoolCreate {
_c.mutation.SetCreateTime(v)
return _c
}
// SetUpdateTime sets the "update_time" field.
func (_c *CpSchoolCreate) SetUpdateTime(v *ent2.CustomTime) *CpSchoolCreate {
_c.mutation.SetUpdateTime(v)
return _c
}
// SetName sets the "name" field.
func (_c *CpSchoolCreate) SetName(v string) *CpSchoolCreate {
_c.mutation.SetName(v)
@@ -77,6 +90,9 @@ func (_c *CpSchoolCreate) Mutation() *CpSchoolMutation {
// Save creates the CpSchool in the database.
func (_c *CpSchoolCreate) Save(ctx context.Context) (*CpSchool, error) {
if err := _c.defaults(); err != nil {
return nil, err
}
return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks)
}
@@ -102,8 +118,33 @@ func (_c *CpSchoolCreate) ExecX(ctx context.Context) {
}
}
// defaults sets the default values of the builder before save.
func (_c *CpSchoolCreate) defaults() error {
if _, ok := _c.mutation.CreateTime(); !ok {
if cpschool.DefaultCreateTime == nil {
return fmt.Errorf("ent: uninitialized cpschool.DefaultCreateTime (forgotten import ent/runtime?)")
}
v := cpschool.DefaultCreateTime()
_c.mutation.SetCreateTime(v)
}
if _, ok := _c.mutation.UpdateTime(); !ok {
if cpschool.DefaultUpdateTime == nil {
return fmt.Errorf("ent: uninitialized cpschool.DefaultUpdateTime (forgotten import ent/runtime?)")
}
v := cpschool.DefaultUpdateTime()
_c.mutation.SetUpdateTime(v)
}
return nil
}
// check runs all checks and user-defined validators on the builder.
func (_c *CpSchoolCreate) check() error {
if _, ok := _c.mutation.CreateTime(); !ok {
return &ValidationError{Name: "create_time", err: errors.New(`ent: missing required field "CpSchool.create_time"`)}
}
if _, ok := _c.mutation.UpdateTime(); !ok {
return &ValidationError{Name: "update_time", err: errors.New(`ent: missing required field "CpSchool.update_time"`)}
}
if _, ok := _c.mutation.Name(); !ok {
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "CpSchool.name"`)}
}
@@ -147,6 +188,14 @@ func (_c *CpSchoolCreate) createSpec() (*CpSchool, *sqlgraph.CreateSpec) {
_node.ID = id
_spec.ID.Value = id
}
if value, ok := _c.mutation.CreateTime(); ok {
_spec.SetField(cpschool.FieldCreateTime, field.TypeString, value)
_node.CreateTime = value
}
if value, ok := _c.mutation.UpdateTime(); ok {
_spec.SetField(cpschool.FieldUpdateTime, field.TypeString, value)
_node.UpdateTime = value
}
if value, ok := _c.mutation.Name(); ok {
_spec.SetField(cpschool.FieldName, field.TypeString, value)
_node.Name = value
@@ -183,7 +232,7 @@ func (_c *CpSchoolCreate) createSpec() (*CpSchool, *sqlgraph.CreateSpec) {
// of the `INSERT` statement. For example:
//
// client.CpSchool.Create().
// SetName(v).
// SetCreateTime(v).
// OnConflict(
// // Update the row with the new values
// // the was proposed for insertion.
@@ -192,7 +241,7 @@ func (_c *CpSchoolCreate) createSpec() (*CpSchool, *sqlgraph.CreateSpec) {
// // Override some of the fields with custom
// // update values.
// Update(func(u *ent.CpSchoolUpsert) {
// SetName(v+v).
// SetCreateTime(v+v).
// }).
// Exec(ctx)
func (_c *CpSchoolCreate) OnConflict(opts ...sql.ConflictOption) *CpSchoolUpsertOne {
@@ -228,6 +277,18 @@ type (
}
)
// SetUpdateTime sets the "update_time" field.
func (u *CpSchoolUpsert) SetUpdateTime(v *ent2.CustomTime) *CpSchoolUpsert {
u.Set(cpschool.FieldUpdateTime, v)
return u
}
// UpdateUpdateTime sets the "update_time" field to the value that was provided on create.
func (u *CpSchoolUpsert) UpdateUpdateTime() *CpSchoolUpsert {
u.SetExcluded(cpschool.FieldUpdateTime)
return u
}
// SetName sets the "name" field.
func (u *CpSchoolUpsert) SetName(v string) *CpSchoolUpsert {
u.Set(cpschool.FieldName, v)
@@ -287,6 +348,9 @@ func (u *CpSchoolUpsertOne) UpdateNewValues() *CpSchoolUpsertOne {
if _, exists := u.create.mutation.ID(); exists {
s.SetIgnore(cpschool.FieldID)
}
if _, exists := u.create.mutation.CreateTime(); exists {
s.SetIgnore(cpschool.FieldCreateTime)
}
}))
return u
}
@@ -318,6 +382,20 @@ func (u *CpSchoolUpsertOne) Update(set func(*CpSchoolUpsert)) *CpSchoolUpsertOne
return u
}
// SetUpdateTime sets the "update_time" field.
func (u *CpSchoolUpsertOne) SetUpdateTime(v *ent2.CustomTime) *CpSchoolUpsertOne {
return u.Update(func(s *CpSchoolUpsert) {
s.SetUpdateTime(v)
})
}
// UpdateUpdateTime sets the "update_time" field to the value that was provided on create.
func (u *CpSchoolUpsertOne) UpdateUpdateTime() *CpSchoolUpsertOne {
return u.Update(func(s *CpSchoolUpsert) {
s.UpdateUpdateTime()
})
}
// SetName sets the "name" field.
func (u *CpSchoolUpsertOne) SetName(v string) *CpSchoolUpsertOne {
return u.Update(func(s *CpSchoolUpsert) {
@@ -424,6 +502,7 @@ func (_c *CpSchoolCreateBulk) Save(ctx context.Context) ([]*CpSchool, error) {
for i := range _c.builders {
func(i int, root context.Context) {
builder := _c.builders[i]
builder.defaults()
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*CpSchoolMutation)
if !ok {
@@ -502,7 +581,7 @@ func (_c *CpSchoolCreateBulk) ExecX(ctx context.Context) {
// // Override some of the fields with custom
// // update values.
// Update(func(u *ent.CpSchoolUpsert) {
// SetName(v+v).
// SetCreateTime(v+v).
// }).
// Exec(ctx)
func (_c *CpSchoolCreateBulk) OnConflict(opts ...sql.ConflictOption) *CpSchoolUpsertBulk {
@@ -549,6 +628,9 @@ func (u *CpSchoolUpsertBulk) UpdateNewValues() *CpSchoolUpsertBulk {
if _, exists := b.mutation.ID(); exists {
s.SetIgnore(cpschool.FieldID)
}
if _, exists := b.mutation.CreateTime(); exists {
s.SetIgnore(cpschool.FieldCreateTime)
}
}
}))
return u
@@ -581,6 +663,20 @@ func (u *CpSchoolUpsertBulk) Update(set func(*CpSchoolUpsert)) *CpSchoolUpsertBu
return u
}
// SetUpdateTime sets the "update_time" field.
func (u *CpSchoolUpsertBulk) SetUpdateTime(v *ent2.CustomTime) *CpSchoolUpsertBulk {
return u.Update(func(s *CpSchoolUpsert) {
s.SetUpdateTime(v)
})
}
// UpdateUpdateTime sets the "update_time" field to the value that was provided on create.
func (u *CpSchoolUpsertBulk) UpdateUpdateTime() *CpSchoolUpsertBulk {
return u.Update(func(s *CpSchoolUpsert) {
s.UpdateUpdateTime()
})
}
// SetName sets the "name" field.
func (u *CpSchoolUpsertBulk) SetName(v string) *CpSchoolUpsertBulk {
return u.Update(func(s *CpSchoolUpsert) {
+4 -4
View File
@@ -307,12 +307,12 @@ func (_q *CpSchoolQuery) WithCpusers(opts ...func(*CpUserQuery)) *CpSchoolQuery
// Example:
//
// var v []struct {
// Name string `json:"name,omitempty"`
// CreateTime *ent2.CustomTime `json:"createTime"`
// Count int `json:"count,omitempty"`
// }
//
// client.CpSchool.Query().
// GroupBy(cpschool.FieldName).
// GroupBy(cpschool.FieldCreateTime).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (_q *CpSchoolQuery) GroupBy(field string, fields ...string) *CpSchoolGroupBy {
@@ -330,11 +330,11 @@ func (_q *CpSchoolQuery) GroupBy(field string, fields ...string) *CpSchoolGroupB
// Example:
//
// var v []struct {
// Name string `json:"name,omitempty"`
// CreateTime *ent2.CustomTime `json:"createTime"`
// }
//
// client.CpSchool.Query().
// Select(cpschool.FieldName).
// Select(cpschool.FieldCreateTime).
// Scan(ctx, &v)
func (_q *CpSchoolQuery) Select(fields ...string) *CpSchoolSelect {
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
+19
View File
@@ -10,6 +10,7 @@ import (
"likedream-goframe/internal/ent/cpuser"
"likedream-goframe/internal/ent/internal"
"likedream-goframe/internal/ent/predicate"
"likedream-goframe/internal/framework/ent2"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
@@ -30,6 +31,12 @@ func (_u *CpSchoolUpdate) Where(ps ...predicate.CpSchool) *CpSchoolUpdate {
return _u
}
// SetUpdateTime sets the "update_time" field.
func (_u *CpSchoolUpdate) SetUpdateTime(v *ent2.CustomTime) *CpSchoolUpdate {
_u.mutation.SetUpdateTime(v)
return _u
}
// SetName sets the "name" field.
func (_u *CpSchoolUpdate) SetName(v string) *CpSchoolUpdate {
_u.mutation.SetName(v)
@@ -161,6 +168,9 @@ func (_u *CpSchoolUpdate) sqlSave(ctx context.Context) (_node int, err error) {
}
}
}
if value, ok := _u.mutation.UpdateTime(); ok {
_spec.SetField(cpschool.FieldUpdateTime, field.TypeString, value)
}
if value, ok := _u.mutation.Name(); ok {
_spec.SetField(cpschool.FieldName, field.TypeString, value)
}
@@ -245,6 +255,12 @@ type CpSchoolUpdateOne struct {
modifiers []func(*sql.UpdateBuilder)
}
// SetUpdateTime sets the "update_time" field.
func (_u *CpSchoolUpdateOne) SetUpdateTime(v *ent2.CustomTime) *CpSchoolUpdateOne {
_u.mutation.SetUpdateTime(v)
return _u
}
// SetName sets the "name" field.
func (_u *CpSchoolUpdateOne) SetName(v string) *CpSchoolUpdateOne {
_u.mutation.SetName(v)
@@ -406,6 +422,9 @@ func (_u *CpSchoolUpdateOne) sqlSave(ctx context.Context) (_node *CpSchool, err
}
}
}
if value, ok := _u.mutation.UpdateTime(); ok {
_spec.SetField(cpschool.FieldUpdateTime, field.TypeString, value)
}
if value, ok := _u.mutation.Name(); ok {
_spec.SetField(cpschool.FieldName, field.TypeString, value)
}
+25
View File
@@ -7,6 +7,7 @@ import (
"likedream-goframe/internal/ent/cptask"
"likedream-goframe/internal/ent/cpuser"
"likedream-goframe/internal/ent/sysuser"
"likedream-goframe/internal/framework/ent2"
"strings"
"entgo.io/ent"
@@ -18,6 +19,10 @@ type CpTask struct {
config `json:"-"`
// ID of the ent.
ID int64 `json:"id,omitempty"`
// CreateTime holds the value of the "create_time" field.
CreateTime *ent2.CustomTime `json:"createTime"`
// UpdateTime holds the value of the "update_time" field.
UpdateTime *ent2.CustomTime `json:"updateTime"`
// CpUserID holds the value of the "cp_user_id" field.
CpUserID int64 `json:"cp_user_id,omitempty"`
// UserID holds the value of the "user_id" field.
@@ -100,6 +105,8 @@ func (*CpTask) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case cptask.FieldCreateTime, cptask.FieldUpdateTime:
values[i] = new(ent2.CustomTime)
case cptask.FieldID, cptask.FieldCpUserID, cptask.FieldUserID, cptask.FieldFrequency, cptask.FieldSuccessCount, cptask.FieldExecuteHour, cptask.FieldExecuteMinute, cptask.FieldNextExecuteTime:
values[i] = new(sql.NullInt64)
case cptask.FieldTaskType, cptask.FieldTitle, cptask.FieldTaskStatus, cptask.FieldFormData, cptask.FieldStep, cptask.FieldNotificationType:
@@ -125,6 +132,18 @@ func (_m *CpTask) assignValues(columns []string, values []any) error {
return fmt.Errorf("unexpected type %T for field id", value)
}
_m.ID = int64(value.Int64)
case cptask.FieldCreateTime:
if value, ok := values[i].(*ent2.CustomTime); !ok {
return fmt.Errorf("unexpected type %T for field create_time", values[i])
} else if value != nil {
_m.CreateTime = value
}
case cptask.FieldUpdateTime:
if value, ok := values[i].(*ent2.CustomTime); !ok {
return fmt.Errorf("unexpected type %T for field update_time", values[i])
} else if value != nil {
_m.UpdateTime = value
}
case cptask.FieldCpUserID:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field cp_user_id", values[i])
@@ -257,6 +276,12 @@ func (_m *CpTask) String() string {
var builder strings.Builder
builder.WriteString("CpTask(")
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
builder.WriteString("create_time=")
builder.WriteString(fmt.Sprintf("%v", _m.CreateTime))
builder.WriteString(", ")
builder.WriteString("update_time=")
builder.WriteString(fmt.Sprintf("%v", _m.UpdateTime))
builder.WriteString(", ")
builder.WriteString("cp_user_id=")
builder.WriteString(fmt.Sprintf("%v", _m.CpUserID))
builder.WriteString(", ")
+30 -1
View File
@@ -4,7 +4,9 @@ package cptask
import (
"fmt"
"likedream-goframe/internal/framework/ent2"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
)
@@ -14,6 +16,10 @@ const (
Label = "cp_task"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldCreateTime holds the string denoting the create_time field in the database.
FieldCreateTime = "create_time"
// FieldUpdateTime holds the string denoting the update_time field in the database.
FieldUpdateTime = "update_time"
// FieldCpUserID holds the string denoting the cp_user_id field in the database.
FieldCpUserID = "cp_user_id"
// FieldUserID holds the string denoting the user_id field in the database.
@@ -74,6 +80,8 @@ const (
// Columns holds all SQL columns for cptask fields.
var Columns = []string{
FieldID,
FieldCreateTime,
FieldUpdateTime,
FieldCpUserID,
FieldUserID,
FieldTaskType,
@@ -99,7 +107,17 @@ func ValidColumn(column string) bool {
return false
}
// Note that the variables below are initialized by the runtime
// package on the initialization of the application. Therefore,
// it should be imported in the main as follows:
//
// import _ "likedream-goframe/internal/ent/runtime"
var (
Hooks [1]ent.Hook
// DefaultCreateTime holds the default value on creation for the "create_time" field.
DefaultCreateTime func() *ent2.CustomTime
// DefaultUpdateTime holds the default value on creation for the "update_time" field.
DefaultUpdateTime func() *ent2.CustomTime
// TitleValidator is a validator for the "title" field. It is called by the builders before save.
TitleValidator func(string) error
// DefaultFrequency holds the default value on creation for the "frequency" field.
@@ -142,6 +160,7 @@ const (
TaskStatusDone TaskStatus = "done"
TaskStatusFail TaskStatus = "fail"
TaskStatusPause TaskStatus = "pause"
TaskStatusQueue TaskStatus = "queue"
TaskStatusUnknown TaskStatus = "unknown"
)
@@ -152,7 +171,7 @@ func (ts TaskStatus) String() string {
// TaskStatusValidator is a validator for the "task_status" field enum values. It is called by the builders before save.
func TaskStatusValidator(ts TaskStatus) error {
switch ts {
case TaskStatusNotStart, TaskStatusDoing, TaskStatusDone, TaskStatusFail, TaskStatusPause, TaskStatusUnknown:
case TaskStatusNotStart, TaskStatusDoing, TaskStatusDone, TaskStatusFail, TaskStatusPause, TaskStatusQueue, TaskStatusUnknown:
return nil
default:
return fmt.Errorf("cptask: invalid enum value for task_status field: %q", ts)
@@ -215,6 +234,16 @@ func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}
// ByCreateTime orders the results by the create_time field.
func ByCreateTime(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreateTime, opts...).ToFunc()
}
// ByUpdateTime orders the results by the update_time field.
func ByUpdateTime(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdateTime, opts...).ToFunc()
}
// ByCpUserID orders the results by the cp_user_id field.
func ByCpUserID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCpUserID, opts...).ToFunc()
+151
View File
@@ -5,6 +5,7 @@ package cptask
import (
"likedream-goframe/internal/ent/internal"
"likedream-goframe/internal/ent/predicate"
"likedream-goframe/internal/framework/ent2"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
@@ -55,6 +56,16 @@ func IDLTE(id int64) predicate.CpTask {
return predicate.CpTask(sql.FieldLTE(FieldID, id))
}
// CreateTime applies equality check predicate on the "create_time" field. It's identical to CreateTimeEQ.
func CreateTime(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldEQ(FieldCreateTime, v))
}
// UpdateTime applies equality check predicate on the "update_time" field. It's identical to UpdateTimeEQ.
func UpdateTime(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldEQ(FieldUpdateTime, v))
}
// CpUserID applies equality check predicate on the "cp_user_id" field. It's identical to CpUserIDEQ.
func CpUserID(v int64) predicate.CpTask {
return predicate.CpTask(sql.FieldEQ(FieldCpUserID, v))
@@ -100,6 +111,146 @@ func NextExecuteTime(v int64) predicate.CpTask {
return predicate.CpTask(sql.FieldEQ(FieldNextExecuteTime, v))
}
// CreateTimeEQ applies the EQ predicate on the "create_time" field.
func CreateTimeEQ(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldEQ(FieldCreateTime, v))
}
// CreateTimeNEQ applies the NEQ predicate on the "create_time" field.
func CreateTimeNEQ(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldNEQ(FieldCreateTime, v))
}
// CreateTimeIn applies the In predicate on the "create_time" field.
func CreateTimeIn(vs ...*ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldIn(FieldCreateTime, vs...))
}
// CreateTimeNotIn applies the NotIn predicate on the "create_time" field.
func CreateTimeNotIn(vs ...*ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldNotIn(FieldCreateTime, vs...))
}
// CreateTimeGT applies the GT predicate on the "create_time" field.
func CreateTimeGT(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldGT(FieldCreateTime, v))
}
// CreateTimeGTE applies the GTE predicate on the "create_time" field.
func CreateTimeGTE(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldGTE(FieldCreateTime, v))
}
// CreateTimeLT applies the LT predicate on the "create_time" field.
func CreateTimeLT(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldLT(FieldCreateTime, v))
}
// CreateTimeLTE applies the LTE predicate on the "create_time" field.
func CreateTimeLTE(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldLTE(FieldCreateTime, v))
}
// CreateTimeContains applies the Contains predicate on the "create_time" field.
func CreateTimeContains(v *ent2.CustomTime) predicate.CpTask {
vc := v.String()
return predicate.CpTask(sql.FieldContains(FieldCreateTime, vc))
}
// CreateTimeHasPrefix applies the HasPrefix predicate on the "create_time" field.
func CreateTimeHasPrefix(v *ent2.CustomTime) predicate.CpTask {
vc := v.String()
return predicate.CpTask(sql.FieldHasPrefix(FieldCreateTime, vc))
}
// CreateTimeHasSuffix applies the HasSuffix predicate on the "create_time" field.
func CreateTimeHasSuffix(v *ent2.CustomTime) predicate.CpTask {
vc := v.String()
return predicate.CpTask(sql.FieldHasSuffix(FieldCreateTime, vc))
}
// CreateTimeEqualFold applies the EqualFold predicate on the "create_time" field.
func CreateTimeEqualFold(v *ent2.CustomTime) predicate.CpTask {
vc := v.String()
return predicate.CpTask(sql.FieldEqualFold(FieldCreateTime, vc))
}
// CreateTimeContainsFold applies the ContainsFold predicate on the "create_time" field.
func CreateTimeContainsFold(v *ent2.CustomTime) predicate.CpTask {
vc := v.String()
return predicate.CpTask(sql.FieldContainsFold(FieldCreateTime, vc))
}
// UpdateTimeEQ applies the EQ predicate on the "update_time" field.
func UpdateTimeEQ(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldEQ(FieldUpdateTime, v))
}
// UpdateTimeNEQ applies the NEQ predicate on the "update_time" field.
func UpdateTimeNEQ(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldNEQ(FieldUpdateTime, v))
}
// UpdateTimeIn applies the In predicate on the "update_time" field.
func UpdateTimeIn(vs ...*ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldIn(FieldUpdateTime, vs...))
}
// UpdateTimeNotIn applies the NotIn predicate on the "update_time" field.
func UpdateTimeNotIn(vs ...*ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldNotIn(FieldUpdateTime, vs...))
}
// UpdateTimeGT applies the GT predicate on the "update_time" field.
func UpdateTimeGT(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldGT(FieldUpdateTime, v))
}
// UpdateTimeGTE applies the GTE predicate on the "update_time" field.
func UpdateTimeGTE(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldGTE(FieldUpdateTime, v))
}
// UpdateTimeLT applies the LT predicate on the "update_time" field.
func UpdateTimeLT(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldLT(FieldUpdateTime, v))
}
// UpdateTimeLTE applies the LTE predicate on the "update_time" field.
func UpdateTimeLTE(v *ent2.CustomTime) predicate.CpTask {
return predicate.CpTask(sql.FieldLTE(FieldUpdateTime, v))
}
// UpdateTimeContains applies the Contains predicate on the "update_time" field.
func UpdateTimeContains(v *ent2.CustomTime) predicate.CpTask {
vc := v.String()
return predicate.CpTask(sql.FieldContains(FieldUpdateTime, vc))
}
// UpdateTimeHasPrefix applies the HasPrefix predicate on the "update_time" field.
func UpdateTimeHasPrefix(v *ent2.CustomTime) predicate.CpTask {
vc := v.String()
return predicate.CpTask(sql.FieldHasPrefix(FieldUpdateTime, vc))
}
// UpdateTimeHasSuffix applies the HasSuffix predicate on the "update_time" field.
func UpdateTimeHasSuffix(v *ent2.CustomTime) predicate.CpTask {
vc := v.String()
return predicate.CpTask(sql.FieldHasSuffix(FieldUpdateTime, vc))
}
// UpdateTimeEqualFold applies the EqualFold predicate on the "update_time" field.
func UpdateTimeEqualFold(v *ent2.CustomTime) predicate.CpTask {
vc := v.String()
return predicate.CpTask(sql.FieldEqualFold(FieldUpdateTime, vc))
}
// UpdateTimeContainsFold applies the ContainsFold predicate on the "update_time" field.
func UpdateTimeContainsFold(v *ent2.CustomTime) predicate.CpTask {
vc := v.String()
return predicate.CpTask(sql.FieldContainsFold(FieldUpdateTime, vc))
}
// CpUserIDEQ applies the EQ predicate on the "cp_user_id" field.
func CpUserIDEQ(v int64) predicate.CpTask {
return predicate.CpTask(sql.FieldEQ(FieldCpUserID, v))
+101 -5
View File
@@ -10,6 +10,7 @@ import (
"likedream-goframe/internal/ent/cptasklog"
"likedream-goframe/internal/ent/cpuser"
"likedream-goframe/internal/ent/sysuser"
"likedream-goframe/internal/framework/ent2"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
@@ -24,6 +25,18 @@ type CpTaskCreate struct {
conflict []sql.ConflictOption
}
// SetCreateTime sets the "create_time" field.
func (_c *CpTaskCreate) SetCreateTime(v *ent2.CustomTime) *CpTaskCreate {
_c.mutation.SetCreateTime(v)
return _c
}
// SetUpdateTime sets the "update_time" field.
func (_c *CpTaskCreate) SetUpdateTime(v *ent2.CustomTime) *CpTaskCreate {
_c.mutation.SetUpdateTime(v)
return _c
}
// SetCpUserID sets the "cp_user_id" field.
func (_c *CpTaskCreate) SetCpUserID(v int64) *CpTaskCreate {
_c.mutation.SetCpUserID(v)
@@ -188,7 +201,9 @@ func (_c *CpTaskCreate) Mutation() *CpTaskMutation {
// Save creates the CpTask in the database.
func (_c *CpTaskCreate) Save(ctx context.Context) (*CpTask, error) {
_c.defaults()
if err := _c.defaults(); err != nil {
return nil, err
}
return withHooks(ctx, _c.sqlSave, _c.mutation, _c.hooks)
}
@@ -215,7 +230,21 @@ func (_c *CpTaskCreate) ExecX(ctx context.Context) {
}
// defaults sets the default values of the builder before save.
func (_c *CpTaskCreate) defaults() {
func (_c *CpTaskCreate) defaults() error {
if _, ok := _c.mutation.CreateTime(); !ok {
if cptask.DefaultCreateTime == nil {
return fmt.Errorf("ent: uninitialized cptask.DefaultCreateTime (forgotten import ent/runtime?)")
}
v := cptask.DefaultCreateTime()
_c.mutation.SetCreateTime(v)
}
if _, ok := _c.mutation.UpdateTime(); !ok {
if cptask.DefaultUpdateTime == nil {
return fmt.Errorf("ent: uninitialized cptask.DefaultUpdateTime (forgotten import ent/runtime?)")
}
v := cptask.DefaultUpdateTime()
_c.mutation.SetUpdateTime(v)
}
if _, ok := _c.mutation.Frequency(); !ok {
v := cptask.DefaultFrequency
_c.mutation.SetFrequency(v)
@@ -224,10 +253,17 @@ func (_c *CpTaskCreate) defaults() {
v := cptask.DefaultSuccessCount
_c.mutation.SetSuccessCount(v)
}
return nil
}
// check runs all checks and user-defined validators on the builder.
func (_c *CpTaskCreate) check() error {
if _, ok := _c.mutation.CreateTime(); !ok {
return &ValidationError{Name: "create_time", err: errors.New(`ent: missing required field "CpTask.create_time"`)}
}
if _, ok := _c.mutation.UpdateTime(); !ok {
return &ValidationError{Name: "update_time", err: errors.New(`ent: missing required field "CpTask.update_time"`)}
}
if _, ok := _c.mutation.CpUserID(); !ok {
return &ValidationError{Name: "cp_user_id", err: errors.New(`ent: missing required field "CpTask.cp_user_id"`)}
}
@@ -314,6 +350,14 @@ func (_c *CpTaskCreate) createSpec() (*CpTask, *sqlgraph.CreateSpec) {
)
_spec.Schema = _c.schemaConfig.CpTask
_spec.OnConflict = _c.conflict
if value, ok := _c.mutation.CreateTime(); ok {
_spec.SetField(cptask.FieldCreateTime, field.TypeString, value)
_node.CreateTime = value
}
if value, ok := _c.mutation.UpdateTime(); ok {
_spec.SetField(cptask.FieldUpdateTime, field.TypeString, value)
_node.UpdateTime = value
}
if value, ok := _c.mutation.TaskType(); ok {
_spec.SetField(cptask.FieldTaskType, field.TypeEnum, value)
_node.TaskType = value
@@ -418,7 +462,7 @@ func (_c *CpTaskCreate) createSpec() (*CpTask, *sqlgraph.CreateSpec) {
// of the `INSERT` statement. For example:
//
// client.CpTask.Create().
// SetCpUserID(v).
// SetCreateTime(v).
// OnConflict(
// // Update the row with the new values
// // the was proposed for insertion.
@@ -427,7 +471,7 @@ func (_c *CpTaskCreate) createSpec() (*CpTask, *sqlgraph.CreateSpec) {
// // Override some of the fields with custom
// // update values.
// Update(func(u *ent.CpTaskUpsert) {
// SetCpUserID(v+v).
// SetCreateTime(v+v).
// }).
// Exec(ctx)
func (_c *CpTaskCreate) OnConflict(opts ...sql.ConflictOption) *CpTaskUpsertOne {
@@ -463,6 +507,18 @@ type (
}
)
// SetUpdateTime sets the "update_time" field.
func (u *CpTaskUpsert) SetUpdateTime(v *ent2.CustomTime) *CpTaskUpsert {
u.Set(cptask.FieldUpdateTime, v)
return u
}
// UpdateUpdateTime sets the "update_time" field to the value that was provided on create.
func (u *CpTaskUpsert) UpdateUpdateTime() *CpTaskUpsert {
u.SetExcluded(cptask.FieldUpdateTime)
return u
}
// SetCpUserID sets the "cp_user_id" field.
func (u *CpTaskUpsert) SetCpUserID(v int64) *CpTaskUpsert {
u.Set(cptask.FieldCpUserID, v)
@@ -683,6 +739,11 @@ func (u *CpTaskUpsert) ClearNextExecuteTime() *CpTaskUpsert {
// Exec(ctx)
func (u *CpTaskUpsertOne) UpdateNewValues() *CpTaskUpsertOne {
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
if _, exists := u.create.mutation.CreateTime(); exists {
s.SetIgnore(cptask.FieldCreateTime)
}
}))
return u
}
@@ -713,6 +774,20 @@ func (u *CpTaskUpsertOne) Update(set func(*CpTaskUpsert)) *CpTaskUpsertOne {
return u
}
// SetUpdateTime sets the "update_time" field.
func (u *CpTaskUpsertOne) SetUpdateTime(v *ent2.CustomTime) *CpTaskUpsertOne {
return u.Update(func(s *CpTaskUpsert) {
s.SetUpdateTime(v)
})
}
// UpdateUpdateTime sets the "update_time" field to the value that was provided on create.
func (u *CpTaskUpsertOne) UpdateUpdateTime() *CpTaskUpsertOne {
return u.Update(func(s *CpTaskUpsert) {
s.UpdateUpdateTime()
})
}
// SetCpUserID sets the "cp_user_id" field.
func (u *CpTaskUpsertOne) SetCpUserID(v int64) *CpTaskUpsertOne {
return u.Update(func(s *CpTaskUpsert) {
@@ -1093,7 +1168,7 @@ func (_c *CpTaskCreateBulk) ExecX(ctx context.Context) {
// // Override some of the fields with custom
// // update values.
// Update(func(u *ent.CpTaskUpsert) {
// SetCpUserID(v+v).
// SetCreateTime(v+v).
// }).
// Exec(ctx)
func (_c *CpTaskCreateBulk) OnConflict(opts ...sql.ConflictOption) *CpTaskUpsertBulk {
@@ -1132,6 +1207,13 @@ type CpTaskUpsertBulk struct {
// Exec(ctx)
func (u *CpTaskUpsertBulk) UpdateNewValues() *CpTaskUpsertBulk {
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
for _, b := range u.create.builders {
if _, exists := b.mutation.CreateTime(); exists {
s.SetIgnore(cptask.FieldCreateTime)
}
}
}))
return u
}
@@ -1162,6 +1244,20 @@ func (u *CpTaskUpsertBulk) Update(set func(*CpTaskUpsert)) *CpTaskUpsertBulk {
return u
}
// SetUpdateTime sets the "update_time" field.
func (u *CpTaskUpsertBulk) SetUpdateTime(v *ent2.CustomTime) *CpTaskUpsertBulk {
return u.Update(func(s *CpTaskUpsert) {
s.SetUpdateTime(v)
})
}
// UpdateUpdateTime sets the "update_time" field to the value that was provided on create.
func (u *CpTaskUpsertBulk) UpdateUpdateTime() *CpTaskUpsertBulk {
return u.Update(func(s *CpTaskUpsert) {
s.UpdateUpdateTime()
})
}
// SetCpUserID sets the "cp_user_id" field.
func (u *CpTaskUpsertBulk) SetCpUserID(v int64) *CpTaskUpsertBulk {
return u.Update(func(s *CpTaskUpsert) {
+4 -4
View File
@@ -385,12 +385,12 @@ func (_q *CpTaskQuery) WithCpTaskLogs(opts ...func(*CpTaskLogQuery)) *CpTaskQuer
// Example:
//
// var v []struct {
// CpUserID int64 `json:"cp_user_id,omitempty"`
// CreateTime *ent2.CustomTime `json:"createTime"`
// Count int `json:"count,omitempty"`
// }
//
// client.CpTask.Query().
// GroupBy(cptask.FieldCpUserID).
// GroupBy(cptask.FieldCreateTime).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (_q *CpTaskQuery) GroupBy(field string, fields ...string) *CpTaskGroupBy {
@@ -408,11 +408,11 @@ func (_q *CpTaskQuery) GroupBy(field string, fields ...string) *CpTaskGroupBy {
// Example:
//
// var v []struct {
// CpUserID int64 `json:"cp_user_id,omitempty"`
// CreateTime *ent2.CustomTime `json:"createTime"`
// }
//
// client.CpTask.Query().
// Select(cptask.FieldCpUserID).
// Select(cptask.FieldCreateTime).
// Scan(ctx, &v)
func (_q *CpTaskQuery) Select(fields ...string) *CpTaskSelect {
_q.ctx.Fields = append(_q.ctx.Fields, fields...)
+19
View File
@@ -12,6 +12,7 @@ import (
"likedream-goframe/internal/ent/internal"
"likedream-goframe/internal/ent/predicate"
"likedream-goframe/internal/ent/sysuser"
"likedream-goframe/internal/framework/ent2"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
@@ -32,6 +33,12 @@ func (_u *CpTaskUpdate) Where(ps ...predicate.CpTask) *CpTaskUpdate {
return _u
}
// SetUpdateTime sets the "update_time" field.
func (_u *CpTaskUpdate) SetUpdateTime(v *ent2.CustomTime) *CpTaskUpdate {
_u.mutation.SetUpdateTime(v)
return _u
}
// SetCpUserID sets the "cp_user_id" field.
func (_u *CpTaskUpdate) SetCpUserID(v int64) *CpTaskUpdate {
_u.mutation.SetCpUserID(v)
@@ -423,6 +430,9 @@ func (_u *CpTaskUpdate) sqlSave(ctx context.Context) (_node int, err error) {
}
}
}
if value, ok := _u.mutation.UpdateTime(); ok {
_spec.SetField(cptask.FieldUpdateTime, field.TypeString, value)
}
if value, ok := _u.mutation.TaskType(); ok {
_spec.SetField(cptask.FieldTaskType, field.TypeEnum, value)
}
@@ -617,6 +627,12 @@ type CpTaskUpdateOne struct {
modifiers []func(*sql.UpdateBuilder)
}
// SetUpdateTime sets the "update_time" field.
func (_u *CpTaskUpdateOne) SetUpdateTime(v *ent2.CustomTime) *CpTaskUpdateOne {
_u.mutation.SetUpdateTime(v)
return _u
}
// SetCpUserID sets the "cp_user_id" field.
func (_u *CpTaskUpdateOne) SetCpUserID(v int64) *CpTaskUpdateOne {
_u.mutation.SetCpUserID(v)
@@ -1038,6 +1054,9 @@ func (_u *CpTaskUpdateOne) sqlSave(ctx context.Context) (_node *CpTask, err erro
}
}
}
if value, ok := _u.mutation.UpdateTime(); ok {
_spec.SetField(cptask.FieldUpdateTime, field.TypeString, value)
}
if value, ok := _u.mutation.TaskType(); ok {
_spec.SetField(cptask.FieldTaskType, field.TypeEnum, value)
}
+25
View File
@@ -8,6 +8,7 @@ import (
"likedream-goframe/internal/ent/cptasklog"
"likedream-goframe/internal/ent/cpuser"
"likedream-goframe/internal/ent/sysuser"
"likedream-goframe/internal/framework/ent2"
"strings"
"entgo.io/ent"
@@ -19,6 +20,10 @@ type CpTaskLog struct {
config `json:"-"`
// ID of the ent.
ID int64 `json:"id,omitempty"`
// CreateTime holds the value of the "create_time" field.
CreateTime *ent2.CustomTime `json:"createTime"`
// UpdateTime holds the value of the "update_time" field.
UpdateTime *ent2.CustomTime `json:"updateTime"`
// CpTaskID holds the value of the "cp_task_id" field.
CpTaskID int64 `json:"cp_task_id,omitempty"`
// SystemUserID holds the value of the "system_user_id" field.
@@ -88,6 +93,8 @@ func (*CpTaskLog) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case cptasklog.FieldCreateTime, cptasklog.FieldUpdateTime:
values[i] = new(ent2.CustomTime)
case cptasklog.FieldIsSuccess:
values[i] = new(sql.NullBool)
case cptasklog.FieldID, cptasklog.FieldCpTaskID, cptasklog.FieldSystemUserID, cptasklog.FieldCpUserID:
@@ -115,6 +122,18 @@ func (_m *CpTaskLog) assignValues(columns []string, values []any) error {
return fmt.Errorf("unexpected type %T for field id", value)
}
_m.ID = int64(value.Int64)
case cptasklog.FieldCreateTime:
if value, ok := values[i].(*ent2.CustomTime); !ok {
return fmt.Errorf("unexpected type %T for field create_time", values[i])
} else if value != nil {
_m.CreateTime = value
}
case cptasklog.FieldUpdateTime:
if value, ok := values[i].(*ent2.CustomTime); !ok {
return fmt.Errorf("unexpected type %T for field update_time", values[i])
} else if value != nil {
_m.UpdateTime = value
}
case cptasklog.FieldCpTaskID:
if value, ok := values[i].(*sql.NullInt64); !ok {
return fmt.Errorf("unexpected type %T for field cp_task_id", values[i])
@@ -202,6 +221,12 @@ func (_m *CpTaskLog) String() string {
var builder strings.Builder
builder.WriteString("CpTaskLog(")
builder.WriteString(fmt.Sprintf("id=%v, ", _m.ID))
builder.WriteString("create_time=")
builder.WriteString(fmt.Sprintf("%v", _m.CreateTime))
builder.WriteString(", ")
builder.WriteString("update_time=")
builder.WriteString(fmt.Sprintf("%v", _m.UpdateTime))
builder.WriteString(", ")
builder.WriteString("cp_task_id=")
builder.WriteString(fmt.Sprintf("%v", _m.CpTaskID))
builder.WriteString(", ")
+32
View File
@@ -3,6 +3,9 @@
package cptasklog
import (
"likedream-goframe/internal/framework/ent2"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
)
@@ -12,6 +15,10 @@ const (
Label = "cp_task_log"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldCreateTime holds the string denoting the create_time field in the database.
FieldCreateTime = "create_time"
// FieldUpdateTime holds the string denoting the update_time field in the database.
FieldUpdateTime = "update_time"
// FieldCpTaskID holds the string denoting the cp_task_id field in the database.
FieldCpTaskID = "cp_task_id"
// FieldSystemUserID holds the string denoting the system_user_id field in the database.
@@ -58,6 +65,8 @@ const (
// Columns holds all SQL columns for cptasklog fields.
var Columns = []string{
FieldID,
FieldCreateTime,
FieldUpdateTime,
FieldCpTaskID,
FieldSystemUserID,
FieldCpUserID,
@@ -76,6 +85,19 @@ func ValidColumn(column string) bool {
return false
}
// Note that the variables below are initialized by the runtime
// package on the initialization of the application. Therefore,
// it should be imported in the main as follows:
//
// import _ "likedream-goframe/internal/ent/runtime"
var (
Hooks [1]ent.Hook
// DefaultCreateTime holds the default value on creation for the "create_time" field.
DefaultCreateTime func() *ent2.CustomTime
// DefaultUpdateTime holds the default value on creation for the "update_time" field.
DefaultUpdateTime func() *ent2.CustomTime
)
// OrderOption defines the ordering options for the CpTaskLog queries.
type OrderOption func(*sql.Selector)
@@ -84,6 +106,16 @@ func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}
// ByCreateTime orders the results by the create_time field.
func ByCreateTime(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreateTime, opts...).ToFunc()
}
// ByUpdateTime orders the results by the update_time field.
func ByUpdateTime(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdateTime, opts...).ToFunc()
}
// ByCpTaskID orders the results by the cp_task_id field.
func ByCpTaskID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCpTaskID, opts...).ToFunc()
+151
View File
@@ -5,6 +5,7 @@ package cptasklog
import (
"likedream-goframe/internal/ent/internal"
"likedream-goframe/internal/ent/predicate"
"likedream-goframe/internal/framework/ent2"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
@@ -55,6 +56,16 @@ func IDLTE(id int64) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldLTE(FieldID, id))
}
// CreateTime applies equality check predicate on the "create_time" field. It's identical to CreateTimeEQ.
func CreateTime(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldEQ(FieldCreateTime, v))
}
// UpdateTime applies equality check predicate on the "update_time" field. It's identical to UpdateTimeEQ.
func UpdateTime(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldEQ(FieldUpdateTime, v))
}
// CpTaskID applies equality check predicate on the "cp_task_id" field. It's identical to CpTaskIDEQ.
func CpTaskID(v int64) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldEQ(FieldCpTaskID, v))
@@ -85,6 +96,146 @@ func RealName(v string) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldEQ(FieldRealName, v))
}
// CreateTimeEQ applies the EQ predicate on the "create_time" field.
func CreateTimeEQ(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldEQ(FieldCreateTime, v))
}
// CreateTimeNEQ applies the NEQ predicate on the "create_time" field.
func CreateTimeNEQ(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldNEQ(FieldCreateTime, v))
}
// CreateTimeIn applies the In predicate on the "create_time" field.
func CreateTimeIn(vs ...*ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldIn(FieldCreateTime, vs...))
}
// CreateTimeNotIn applies the NotIn predicate on the "create_time" field.
func CreateTimeNotIn(vs ...*ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldNotIn(FieldCreateTime, vs...))
}
// CreateTimeGT applies the GT predicate on the "create_time" field.
func CreateTimeGT(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldGT(FieldCreateTime, v))
}
// CreateTimeGTE applies the GTE predicate on the "create_time" field.
func CreateTimeGTE(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldGTE(FieldCreateTime, v))
}
// CreateTimeLT applies the LT predicate on the "create_time" field.
func CreateTimeLT(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldLT(FieldCreateTime, v))
}
// CreateTimeLTE applies the LTE predicate on the "create_time" field.
func CreateTimeLTE(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldLTE(FieldCreateTime, v))
}
// CreateTimeContains applies the Contains predicate on the "create_time" field.
func CreateTimeContains(v *ent2.CustomTime) predicate.CpTaskLog {
vc := v.String()
return predicate.CpTaskLog(sql.FieldContains(FieldCreateTime, vc))
}
// CreateTimeHasPrefix applies the HasPrefix predicate on the "create_time" field.
func CreateTimeHasPrefix(v *ent2.CustomTime) predicate.CpTaskLog {
vc := v.String()
return predicate.CpTaskLog(sql.FieldHasPrefix(FieldCreateTime, vc))
}
// CreateTimeHasSuffix applies the HasSuffix predicate on the "create_time" field.
func CreateTimeHasSuffix(v *ent2.CustomTime) predicate.CpTaskLog {
vc := v.String()
return predicate.CpTaskLog(sql.FieldHasSuffix(FieldCreateTime, vc))
}
// CreateTimeEqualFold applies the EqualFold predicate on the "create_time" field.
func CreateTimeEqualFold(v *ent2.CustomTime) predicate.CpTaskLog {
vc := v.String()
return predicate.CpTaskLog(sql.FieldEqualFold(FieldCreateTime, vc))
}
// CreateTimeContainsFold applies the ContainsFold predicate on the "create_time" field.
func CreateTimeContainsFold(v *ent2.CustomTime) predicate.CpTaskLog {
vc := v.String()
return predicate.CpTaskLog(sql.FieldContainsFold(FieldCreateTime, vc))
}
// UpdateTimeEQ applies the EQ predicate on the "update_time" field.
func UpdateTimeEQ(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldEQ(FieldUpdateTime, v))
}
// UpdateTimeNEQ applies the NEQ predicate on the "update_time" field.
func UpdateTimeNEQ(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldNEQ(FieldUpdateTime, v))
}
// UpdateTimeIn applies the In predicate on the "update_time" field.
func UpdateTimeIn(vs ...*ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldIn(FieldUpdateTime, vs...))
}
// UpdateTimeNotIn applies the NotIn predicate on the "update_time" field.
func UpdateTimeNotIn(vs ...*ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldNotIn(FieldUpdateTime, vs...))
}
// UpdateTimeGT applies the GT predicate on the "update_time" field.
func UpdateTimeGT(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldGT(FieldUpdateTime, v))
}
// UpdateTimeGTE applies the GTE predicate on the "update_time" field.
func UpdateTimeGTE(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldGTE(FieldUpdateTime, v))
}
// UpdateTimeLT applies the LT predicate on the "update_time" field.
func UpdateTimeLT(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldLT(FieldUpdateTime, v))
}
// UpdateTimeLTE applies the LTE predicate on the "update_time" field.
func UpdateTimeLTE(v *ent2.CustomTime) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldLTE(FieldUpdateTime, v))
}
// UpdateTimeContains applies the Contains predicate on the "update_time" field.
func UpdateTimeContains(v *ent2.CustomTime) predicate.CpTaskLog {
vc := v.String()
return predicate.CpTaskLog(sql.FieldContains(FieldUpdateTime, vc))
}
// UpdateTimeHasPrefix applies the HasPrefix predicate on the "update_time" field.
func UpdateTimeHasPrefix(v *ent2.CustomTime) predicate.CpTaskLog {
vc := v.String()
return predicate.CpTaskLog(sql.FieldHasPrefix(FieldUpdateTime, vc))
}
// UpdateTimeHasSuffix applies the HasSuffix predicate on the "update_time" field.
func UpdateTimeHasSuffix(v *ent2.CustomTime) predicate.CpTaskLog {
vc := v.String()
return predicate.CpTaskLog(sql.FieldHasSuffix(FieldUpdateTime, vc))
}
// UpdateTimeEqualFold applies the EqualFold predicate on the "update_time" field.
func UpdateTimeEqualFold(v *ent2.CustomTime) predicate.CpTaskLog {
vc := v.String()
return predicate.CpTaskLog(sql.FieldEqualFold(FieldUpdateTime, vc))
}
// UpdateTimeContainsFold applies the ContainsFold predicate on the "update_time" field.
func UpdateTimeContainsFold(v *ent2.CustomTime) predicate.CpTaskLog {
vc := v.String()
return predicate.CpTaskLog(sql.FieldContainsFold(FieldUpdateTime, vc))
}
// CpTaskIDEQ applies the EQ predicate on the "cp_task_id" field.
func CpTaskIDEQ(v int64) predicate.CpTaskLog {
return predicate.CpTaskLog(sql.FieldEQ(FieldCpTaskID, v))

Some files were not shown because too many files have changed in this diff Show More