diff --git a/dataType/bool.go b/dataType/bool.go index 902c555..89ff61d 100644 --- a/dataType/bool.go +++ b/dataType/bool.go @@ -130,3 +130,7 @@ func (b *Bool) GobDecode(data []byte) error { b.bool = data[0] != 0 return nil } + +func (b Bool) ToPtr() *Bool { + return &b +} diff --git a/dataType/date.go b/dataType/date.go index 094f0d4..a2703e7 100644 --- a/dataType/date.go +++ b/dataType/date.go @@ -1,7 +1,6 @@ package dataType import ( - "database/sql" "database/sql/driver" "strings" "time" @@ -13,6 +12,16 @@ import ( "helay.net/go/utils/v3/tools" ) +var timeFormat = formatter.FormatRule[time.Time]{ + FormatType: "output_date", + InputRules: []string{ + "timestamp", + "2006-01-02", + "2006-01-02 15", + "2006-01-02 15:04", + }, +} + type CustomDate struct { time.Time } @@ -23,10 +32,15 @@ func (c CustomDate) String() string { } // noinspection all -func (c *CustomDate) Scan(value interface{}) (err error) { - nullTime := &sql.NullTime{} - err = nullTime.Scan(value) - c.Time = nullTime.Time +func (c *CustomDate) Scan(value any) (err error) { + if value == nil { + return nil + } + t, err := timeFormat.Format(value) + if err != nil { + return err + } + c.Time = t return } @@ -70,8 +84,7 @@ func (c *CustomDate) UnmarshalJSON(b []byte) (err error) { //*this = CustomTime{} return nil } - tf := formatter.FormatRule[time.Time]{FormatType: "output_date"} - _t, err := tf.Format(s) + _t, err := timeFormat.Format(s) if err != nil { return err } @@ -98,9 +111,14 @@ func (c CustomTime) String() string { // noinspection all func (c *CustomTime) Scan(value interface{}) (err error) { - nullTime := &sql.NullTime{} - err = nullTime.Scan(value) - c.Time = nullTime.Time + if value == nil { + return nil + } + t, err := timeFormat.Format(value) + if err != nil { + return err + } + c.Time = t return } @@ -155,6 +173,20 @@ func (c *CustomTime) UnmarshalJSON(b []byte) (err error) { return err } +// UnmarshalParam 从 query string 参数解析 +func (c *CustomTime) UnmarshalParam(param string) error { + if param == "" { + return nil + } + tf := formatter.FormatRule[time.Time]{FormatType: "output_date"} + _t, err := tf.Format(param) + if err != nil { + return err + } + c.Time = _t + return nil +} + // noinspection all func (c CustomTime) ToPtr() *CustomTime { return &c diff --git a/dataType/int.go b/dataType/int.go index 99d5b7b..2e57a3b 100644 --- a/dataType/int.go +++ b/dataType/int.go @@ -47,6 +47,42 @@ func (Byte) GormDBDataType(db *gorm.DB, field *schema.Field) string { return "int" } +func (b Byte) ToInt() int { + return int(b) +} + +func (b Byte) ToInt64() int64 { + return int64(b) +} + +func (b Byte) ToUint64() uint64 { + return uint64(b) +} + +func (b Byte) ToFloat64() float64 { + return float64(b) +} + +func (b Byte) ToString() string { + return fmt.Sprintf("%d", b) +} + +func (b Byte) ToBool() bool { + return b != 0 +} + +func (b Byte) ToInt32() int32 { + return int32(b) +} + +func (b Byte) ToInt16() int16 { + return int16(b) +} + +func (b Byte) ToByte() byte { + return byte(b) +} + type Uint64 struct { uint64 } diff --git a/dataType/json_map.go b/dataType/json_map.go index 0842a86..679aa89 100644 --- a/dataType/json_map.go +++ b/dataType/json_map.go @@ -5,6 +5,7 @@ import ( "context" "database/sql/driver" "encoding/json" + "errors" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -13,48 +14,36 @@ import ( // JSONMap defined JSON data type, need to implements driver.Valuer, sql.Scanner interface // noinspection all -type JSONMap map[string]any +type JSONMap struct { + data map[string]any +} + +func NewJSONMap(data map[string]any) JSONMap { + return JSONMap{data: data} +} // Value return json value, implement driver.Valuer interface // noinspection all func (m JSONMap) Value() (driver.Value, error) { - return DriverValueWithJson(m) + return DriverValueWithJson(m.data) } // Scan scan value into Jsonb, implements sql.Scanner interface // noinspection all func (m *JSONMap) Scan(val any) error { - return DriverScanWithJson(val, m) // 这里暂时先用这个版本 - //if val == nil { - // *m = make(JSONMap) - // return nil - //} - //var ba []byte - //switch v := val.(type) { - //case []byte: - // ba = v - //case string: - // ba = []byte(v) - //default: - // return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", val)) - //} - //t := map[string]any{} - //rd := bytes.NewReader(ba) - //decoder := json.NewDecoder(rd) - //decoder.UseNumber() - //err := decoder.Decode(&t) - //*m = t - //return err + if m == nil { + return errors.New("JSONMap is nil") + } + return DriverScanWithJson(val, &m.data) // 这里暂时先用这个版本 } // MarshalJSON to output non base64 encoded []byte // noinspection all func (m JSONMap) MarshalJSON() ([]byte, error) { - if m == nil { + if m.data == nil { return []byte("null"), nil } - t := (map[string]any)(m) - return json.Marshal(t) + return json.Marshal(m.data) } // UnmarshalJSON to deserialize []byte @@ -64,10 +53,7 @@ func (m *JSONMap) UnmarshalJSON(b []byte) error { rd := bytes.NewReader(b) decoder := json.NewDecoder(rd) decoder.UseNumber() - t := map[string]any{} - err := decoder.Decode(&t) - *m = t - return err + return decoder.Decode(&m.data) } // GormDataType gorm common data type @@ -83,7 +69,37 @@ func (JSONMap) GormDBDataType(db *gorm.DB, field *schema.Field) string { } // noinspection all -func (jm JSONMap) GormValue(_ context.Context, db *gorm.DB) clause.Expr { - data, _ := jm.MarshalJSON() +func (m JSONMap) GormValue(_ context.Context, db *gorm.DB) clause.Expr { + data, _ := m.MarshalJSON() return MapGormValue(string(data), db) } + +func (m *JSONMap) Add(k string, v any) { + if m == nil { + return + } + if m.data == nil { + m.data = make(map[string]any) + } + m.data[k] = v +} + +func (m *JSONMap) Get(k string) (any, bool) { + if m == nil || m.data == nil { + return nil, false + } + v, ok := m.data[k] + return v, ok +} + +func (m *JSONMap) Remove(k string) { + if m == nil || m.data == nil { + return + } + + delete(m.data, k) +} + +func (m *JSONMap) ToMap() map[string]any { + return m.data +} diff --git a/db/localredis/unimplemented.go b/db/localredis/unimplemented.go index 5cfa71a..8501710 100644 --- a/db/localredis/unimplemented.go +++ b/db/localredis/unimplemented.go @@ -2721,13 +2721,13 @@ func (l *LocalCache) VInfo(ctx context.Context, key string) *redis.MapStringInte // VLinks // noinspection all -func (l *LocalCache) VLinks(ctx context.Context, key, element string) *redis.StringSliceCmd { +func (l *LocalCache) VLinks(ctx context.Context, key string, element string) *redis.StringSliceSliceCmd { return nil } // VLinksWithScores // noinspection all -func (l *LocalCache) VLinksWithScores(ctx context.Context, key, element string) *redis.VectorScoreSliceCmd { +func (l *LocalCache) VLinksWithScores(ctx context.Context, key, element string) *redis.VectorScoreSliceSliceCmd { return nil } @@ -2994,3 +2994,147 @@ func (l *LocalCache) SetIFDNEGet(ctx context.Context, key string, value interfac func (l *LocalCache) VRange(ctx context.Context, key string, start string, end string, count int64) *redis.StringSliceCmd { return nil } + +func (l *LocalCache) ReplicaOf(ctx context.Context, host string, port string) *redis.StatusCmd { + return nil +} + +func (l *LocalCache) XCfgSet(ctx context.Context, a *redis.XCfgSetArgs) *redis.StatusCmd { + return nil +} +func (l *LocalCache) VSimWithArgsWithAttribs(ctx context.Context, key string, val redis.Vector, args *redis.VSimArgs) *redis.VectorAttribSliceCmd { + return nil +} +func (l *LocalCache) VSimWithArgsWithScoresWithAttribs(ctx context.Context, key string, val redis.Vector, args *redis.VSimArgs) *redis.VectorScoreAttribSliceCmd { + return nil +} + +func (l *LocalCache) VIsMember(ctx context.Context, key string, element string) *redis.BoolCmd { + return nil +} + +func (l *LocalCache) ARSet(ctx context.Context, key string, index uint64, values ...string) *redis.IntCmd { + return nil +} +func (l *LocalCache) ARGet(ctx context.Context, key string, index uint64) *redis.StringCmd { + return nil +} +func (l *LocalCache) ARGetRange(ctx context.Context, key string, start uint64, end uint64) *redis.SliceCmd { + return nil +} + +func (l *LocalCache) ARMGet(ctx context.Context, key string, indexes ...uint64) *redis.SliceCmd { + return nil +} +func (l *LocalCache) ARMSet(ctx context.Context, key string, members ...redis.AREntry) *redis.IntCmd { + return nil +} +func (l *LocalCache) ARInsert(ctx context.Context, key string, values ...string) *redis.UintCmd { + return nil +} + +func (l *LocalCache) ARDel(ctx context.Context, key string, indexes ...uint64) *redis.IntCmd { + return nil +} +func (l *LocalCache) ARDelRange(ctx context.Context, key string, ranges ...redis.ARRange) *redis.UintCmd { + return nil +} +func (l *LocalCache) ARLen(ctx context.Context, key string) *redis.UintCmd { + return nil +} + +func (l *LocalCache) ARCount(ctx context.Context, key string) *redis.UintCmd { + return nil +} +func (l *LocalCache) ARNext(ctx context.Context, key string) *redis.UintCmd { + return nil +} +func (l *LocalCache) ARSeek(ctx context.Context, key string, index uint64) *redis.IntCmd { + return nil +} + +func (l *LocalCache) ARInfo(ctx context.Context, key string) *redis.MapStringInterfaceCmd { + return nil +} +func (l *LocalCache) ARInfoFull(ctx context.Context, key string) *redis.MapStringInterfaceCmd { + return nil +} +func (l *LocalCache) ARScan(ctx context.Context, key string, start uint64, end uint64, args *redis.ARScanArgs) *redis.AREntrySliceCmd { + return nil +} + +func (l *LocalCache) AROpSum(ctx context.Context, key string, start, end uint64) *redis.StringCmd { + return nil +} + +func (l *LocalCache) AROpMin(ctx context.Context, key string, start, end uint64) *redis.StringCmd { + return nil +} + +func (l *LocalCache) AROpMax(ctx context.Context, key string, start, end uint64) *redis.StringCmd { + return nil +} + +func (l *LocalCache) AROpAnd(ctx context.Context, key string, start, end uint64) *redis.IntCmd { + return nil +} + +func (l *LocalCache) AROpOr(ctx context.Context, key string, start, end uint64) *redis.IntCmd { + return nil +} + +func (l *LocalCache) AROpXor(ctx context.Context, key string, start, end uint64) *redis.IntCmd { + return nil +} + +func (l *LocalCache) AROpMatch(ctx context.Context, key string, start, end uint64, value string) *redis.IntCmd { + return nil +} + +func (l *LocalCache) AROpUsed(ctx context.Context, key string, start, end uint64) *redis.IntCmd { + return nil +} + +func (l *LocalCache) ARGrep(ctx context.Context, key string, start, end string, args *redis.ARGrepArgs) *redis.UintSliceCmd { + return nil +} + +func (l *LocalCache) ARGrepWithValues(ctx context.Context, key string, start, end string, args *redis.ARGrepArgs) *redis.AREntrySliceCmd { + return nil +} + +func (l *LocalCache) ARRing(ctx context.Context, key string, size uint64, values ...string) *redis.UintCmd { + return nil +} + +func (l *LocalCache) ARLastItems(ctx context.Context, key string, count uint64, rev bool) *redis.SliceCmd { + return nil +} + +func (l *LocalCache) GetToBuffer(ctx context.Context, key string, buf []byte) *redis.ZeroCopyStringCmd { + return nil +} + +func (l *LocalCache) IncrEXInt(ctx context.Context, key string, args redis.IncrEXIntArgs) *redis.IncrEXIntCmd { + return nil +} + +func (l *LocalCache) IncrEXFloat(ctx context.Context, key string, args redis.IncrEXFloatArgs) *redis.IncrEXFloatCmd { + return nil +} + +func (l *LocalCache) SetFromBuffer(ctx context.Context, key string, buf []byte) *redis.StatusCmd { + return nil +} + +func (l *LocalCache) XNack(ctx context.Context, a *redis.XNackArgs) *redis.IntCmd { + return nil +} + +func (l *LocalCache) XAutoClaimWithDeleted(ctx context.Context, a *redis.XAutoClaimArgs) *redis.XAutoClaimWithDeletedCmd { + return nil +} + +func (l *LocalCache) JSONSetWithArgs(ctx context.Context, key, path string, value interface{}, options *redis.JSONSetArgsOptions) *redis.StatusCmd { + return nil +} diff --git a/go.mod b/go.mod index 6f686c6..cf9983d 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,14 @@ module helay.net/go/utils/v3 -go 1.25.0 +go 1.26 require ( - github.com/IBM/sarama v1.48.0 + github.com/IBM/sarama v1.50.3 github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de github.com/cespare/xxhash/v2 v2.3.0 github.com/colinmarc/hdfs/v2 v2.4.0 github.com/dchest/captcha v1.1.0 - github.com/elastic/go-elasticsearch/v8 v8.19.5 + github.com/elastic/go-elasticsearch/v8 v8.19.6 github.com/gin-gonic/gin v1.12.0 github.com/go-playground/form/v4 v4.3.0 github.com/go-sql-driver/mysql v1.10.0 @@ -21,65 +21,65 @@ require ( github.com/gorilla/handlers v1.5.2 github.com/gorilla/schema v1.4.1 github.com/helays/gomail/v2 v2.0.3 - github.com/jackc/pgx/v5 v5.9.2 - github.com/jlaffaye/ftp v0.2.0 + github.com/jackc/pgx/v5 v5.10.0 + github.com/jlaffaye/ftp v0.2.1 github.com/malfunkt/iprange v0.9.0 - github.com/minio/minio-go/v7 v7.1.0 + github.com/minio/minio-go/v7 v7.2.0 github.com/nacos-group/nacos-sdk-go/v2 v2.3.5 github.com/natefinch/lumberjack v2.0.0+incompatible github.com/pkg/errors v0.9.1 github.com/pkg/sftp v1.13.10 - github.com/quic-go/quic-go v0.59.0 + github.com/quic-go/quic-go v0.60.0 github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 - github.com/redis/go-redis/v9 v9.19.0 + github.com/redis/go-redis/v9 v9.21.0 github.com/robfig/cron/v3 v3.0.1 github.com/sony/sonyflake/v2 v2.2.0 github.com/tjfoc/gmsm v1.4.1 github.com/vmihailenco/msgpack/v5 v5.4.1 github.com/xdg-go/scram v1.2.0 github.com/xuri/excelize/v2 v2.10.1 - go.etcd.io/etcd/client/v3 v3.6.10 + go.etcd.io/etcd/client/v3 v3.6.12 go.uber.org/zap v1.28.0 go4.org/netipx v0.0.0-20231129151722-fdeea329fbba - golang.org/x/crypto v0.50.0 - golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f - golang.org/x/net v0.53.0 - golang.org/x/text v0.36.0 - gopkg.in/ini.v1 v1.67.1 + golang.org/x/crypto v0.53.0 + golang.org/x/exp v0.0.0-20260611194520-c48552f49976 + golang.org/x/net v0.56.0 + golang.org/x/text v0.38.0 + gopkg.in/ini.v1 v1.67.3 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/mysql v1.6.0 gorm.io/driver/postgres v1.6.0 gorm.io/driver/sqlite v1.6.0 - gorm.io/gorm v1.31.1 + gorm.io/gorm v1.31.2 ) require ( filippo.io/edwards25519 v1.2.0 // indirect - github.com/alibabacloud-go/alibabacloud-gateway-pop v0.1.3 // indirect + github.com/alibabacloud-go/alibabacloud-gateway-pop v0.1.4 // indirect github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect github.com/alibabacloud-go/darabonba-array v0.1.0 // indirect github.com/alibabacloud-go/darabonba-encode-util v0.0.2 // indirect github.com/alibabacloud-go/darabonba-map v0.0.2 // indirect - github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.15 // indirect + github.com/alibabacloud-go/darabonba-openapi/v2 v2.2.2 // indirect github.com/alibabacloud-go/darabonba-signature-util v0.0.7 // indirect github.com/alibabacloud-go/darabonba-string v1.0.2 // indirect github.com/alibabacloud-go/debug v1.0.1 // indirect github.com/alibabacloud-go/endpoint-util v1.1.1 // indirect github.com/alibabacloud-go/kms-20160120/v3 v3.4.0 // indirect github.com/alibabacloud-go/openapi-util v0.1.2 // indirect - github.com/alibabacloud-go/tea v1.4.0 // indirect + github.com/alibabacloud-go/tea v1.5.2 // indirect github.com/alibabacloud-go/tea-utils/v2 v2.0.9 // indirect github.com/alibabacloud-go/tea-xml v1.1.3 // indirect github.com/aliyun/alibaba-cloud-sdk-go v1.63.107 // indirect github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.5.1 // indirect github.com/aliyun/alibabacloud-dkms-transfer-go-sdk v0.1.9 // indirect github.com/aliyun/aliyun-secretsmanager-client-go v1.1.5 // indirect - github.com/aliyun/credentials-go v1.4.11 // indirect + github.com/aliyun/credentials-go v1.4.12 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/buger/jsonparser v1.1.1 // indirect + github.com/buger/jsonparser v1.2.0 // indirect github.com/bytedance/gopkg v0.1.4 // indirect - github.com/bytedance/sonic v1.15.1 // indirect + github.com/bytedance/sonic v1.15.2 // indirect github.com/bytedance/sonic/loader v0.5.1 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/cloudwego/base64x v0.1.7 // indirect @@ -87,27 +87,23 @@ require ( github.com/coreos/go-systemd/v22 v22.7.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set v1.8.0 // indirect - github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/eapache/go-resiliency v1.7.0 // indirect - github.com/eapache/queue v1.1.0 // indirect github.com/elastic/elastic-transport-go/v8 v8.11.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/felixge/httpsnoop v1.1.0 // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect github.com/gin-contrib/sse v1.1.1 // indirect - github.com/go-ini/ini v1.67.0 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.30.2 // indirect + github.com/go-playground/validator/v10 v10.30.3 // indirect github.com/goccy/go-yaml v1.19.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/mock v1.7.0-rc.1 // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect @@ -122,13 +118,13 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.18.5 // indirect + github.com/klauspost/compress v1.18.6 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/klauspost/crc32 v1.3.0 // indirect github.com/kr/fs v0.1.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-isatty v0.0.22 // indirect - github.com/mattn/go-sqlite3 v1.14.44 // indirect + github.com/mattn/go-sqlite3 v1.14.47 // indirect github.com/minio/crc64nvme v1.1.1 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -136,16 +132,16 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect github.com/orcaman/concurrent-map v1.0.0 // indirect - github.com/pelletier/go-toml/v2 v2.3.0 // indirect + github.com/pelletier/go-toml/v2 v2.4.2 // indirect github.com/philhofer/fwd v1.2.0 // indirect - github.com/pierrec/lz4/v4 v4.1.26 // indirect + github.com/pierrec/lz4/v4 v4.1.27 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.23.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/common v0.69.0 // indirect github.com/prometheus/procfs v0.20.1 // indirect github.com/quic-go/qpack v0.6.0 // indirect - github.com/richardlehane/mscfb v1.0.6 // indirect + github.com/richardlehane/mscfb v1.0.7 // indirect github.com/richardlehane/msoleps v1.0.6 // indirect github.com/rs/xid v1.6.0 // indirect github.com/tiendc/go-deepcopy v1.7.2 // indirect @@ -158,25 +154,23 @@ require ( github.com/xuri/efp v0.0.1 // indirect github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect github.com/zeebo/xxh3 v1.1.0 // indirect - go.etcd.io/etcd/api/v3 v3.6.10 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.6.10 // indirect - go.mongodb.org/mongo-driver/v2 v2.6.0 // indirect + go.etcd.io/etcd/api/v3 v3.6.12 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.6.12 // indirect + go.mongodb.org/mongo-driver/v2 v2.7.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/otel v1.43.0 // indirect - go.opentelemetry.io/otel/metric v1.43.0 // indirect - go.opentelemetry.io/otel/trace v1.43.0 // indirect + go.opentelemetry.io/otel v1.44.0 // indirect + go.opentelemetry.io/otel/metric v1.44.0 // indirect + go.opentelemetry.io/otel/trace v1.44.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/arch v0.26.0 // indirect - golang.org/x/sync v0.20.0 // indirect - golang.org/x/sys v0.43.0 // indirect - golang.org/x/time v0.14.0 // indirect - google.golang.org/genproto v0.0.0-20260226221140-a57be14db171 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260427160629-7cedc36a6bc4 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260427160629-7cedc36a6bc4 // indirect - google.golang.org/grpc v1.80.0 // indirect + golang.org/x/arch v0.28.0 // indirect + golang.org/x/sync v0.21.0 // indirect + golang.org/x/sys v0.46.0 // indirect + golang.org/x/time v0.15.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260622175928-b703f567277d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260622175928-b703f567277d // indirect + google.golang.org/grpc v1.81.1 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect diff --git a/net/email/email.go b/net/email/email.go index 84e7ffa..920fa58 100644 --- a/net/email/email.go +++ b/net/email/email.go @@ -10,15 +10,35 @@ import ( ) type EmailSender struct { - SmtpSenderMail string `json:"smtp_sender_mail" yaml:"smtp_sender_mail"` - SmtpSenderAlias string `json:"smtp_sender_alias" yaml:"smtp_sender_alias"` - SmtpSenderTo []string `json:"smtp_sender_to" yaml:"smtp_sender_to"` - SmtpSenderAddr string `json:"smtp_sender_addr" yaml:"smtp_sender_addr"` - SmtpSenderPort int `json:"smtp_sender_port" yaml:"smtp_sender_port"` - Account string `json:"account" yaml:"account"` - Password string `json:"password" yaml:"password"` - Proxy cfg_proxy.Proxy `json:"proxy" yaml:"proxy"` - TLS *cfg_tls.TLS `json:"tls" yaml:"tls"` + SmtpSenderMail string `json:"smtp_sender_mail" yaml:"smtp_sender_mail"` + SmtpSenderAlias string `json:"smtp_sender_alias" yaml:"smtp_sender_alias"` + EnableExternalTo bool `json:"enable_external_to" yaml:"enable_external_to"` // 是否启用外部邮件接收人,可用在调用层,是否决定重写 SmtpSenderTo + SmtpSenderTo []string `json:"smtp_sender_to" yaml:"smtp_sender_to"` + SmtpSenderAddr string `json:"smtp_sender_addr" yaml:"smtp_sender_addr"` + SmtpSenderPort int `json:"smtp_sender_port" yaml:"smtp_sender_port"` + Account string `json:"account" yaml:"account"` + Password string `json:"password" yaml:"password"` + + Proxy cfg_proxy.Proxy `json:"proxy" yaml:"proxy"` + TLS *cfg_tls.TLS `json:"tls" yaml:"tls"` +} + +func (e *EmailSender) Clone(dst []string) *EmailSender { + out := &EmailSender{ + SmtpSenderMail: e.SmtpSenderMail, + SmtpSenderAlias: e.SmtpSenderAlias, + SmtpSenderTo: e.SmtpSenderTo, + SmtpSenderPort: e.SmtpSenderPort, + SmtpSenderAddr: e.SmtpSenderAddr, + Account: e.Account, + Password: e.Password, + Proxy: e.Proxy, + TLS: e.TLS, + } + if len(dst)> 0 { + out.SmtpSenderTo = dst + } + return out } func (e *EmailSender) NewDialer() (*gomail.Dialer, error) { diff --git a/rule-engine/formatter/format.rule.date.go b/rule-engine/formatter/format.rule.date.go index 8875d16..774843a 100644 --- a/rule-engine/formatter/format.rule.date.go +++ b/rule-engine/formatter/format.rule.date.go @@ -51,10 +51,11 @@ func (f FormatRule[T]) dateObjectFormat(_src any) (any, error) { t time.Time err error ok bool - src = tools.Any2string(_src) + src string ) // 首先尝试使用 https://github.com/araddon/dateparse 库 if t, ok = _src.(time.Time); !ok { + src = tools.Any2string(_src) t, err = dateparse.ParseLocal(src) } if err == nil { diff --git a/safe/types.go b/safe/types.go index 34a002f..392661d 100644 --- a/safe/types.go +++ b/safe/types.go @@ -1,6 +1,7 @@ package safe import ( + "fmt" "time" "unsafe" @@ -28,6 +29,11 @@ type OnExpired[K comparable] func(key []K) // 过期回调 type Hasher[K comparable] interface { Hash(K) uint64 } +type GenericStringHasher[T fmt.Stringer] struct{} + +func (h GenericStringHasher[T]) Hash(k T) uint64 { + return xxhash.Sum64String(k.String()) +} // IntegerHasher 整数哈希器 type IntegerHasher[T constraints.Integer] struct{} diff --git a/tools/array.go b/tools/array.go index 87e44cd..f3a8f46 100644 --- a/tools/array.go +++ b/tools/array.go @@ -373,6 +373,16 @@ func AnySlice2StrSlice(slice []any) []string { return out } +// ToStrings 将实现了 fmt.Stringer 接口的元素切片转换为字符串切片 +// slice: 任意实现了 String() string 的元素类型切片 +func ToStrings[T fmt.Stringer](slice []T) []string { + out := make([]string, len(slice)) + for i, v := range slice { + out[i] = v.String() + } + return out +} + // AnySlice2Str 将任意切片转成字符串 func AnySlice2Str(slice []any, _sep ...string) string { var builder strings.Builder