Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
7319122e
Commit
7319122e
authored
Feb 06, 2026
by
LLLLLLiulei
Browse files
merge upstream/main
parents
029994a8
4809fa4f
Changes
89
Show whitespace changes
Inline
Side-by-side
backend/ent/intercept/intercept.go
View file @
7319122e
...
...
@@ -13,6 +13,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent/announcement"
"github.com/Wei-Shaw/sub2api/ent/announcementread"
"github.com/Wei-Shaw/sub2api/ent/apikey"
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/predicate"
"github.com/Wei-Shaw/sub2api/ent/promocode"
...
...
@@ -220,6 +221,33 @@ func (f TraverseAnnouncementRead) Traverse(ctx context.Context, q ent.Query) err
return
fmt
.
Errorf
(
"unexpected query type %T. expect *ent.AnnouncementReadQuery"
,
q
)
}
// The ErrorPassthroughRuleFunc type is an adapter to allow the use of ordinary function as a Querier.
type
ErrorPassthroughRuleFunc
func
(
context
.
Context
,
*
ent
.
ErrorPassthroughRuleQuery
)
(
ent
.
Value
,
error
)
// Query calls f(ctx, q).
func
(
f
ErrorPassthroughRuleFunc
)
Query
(
ctx
context
.
Context
,
q
ent
.
Query
)
(
ent
.
Value
,
error
)
{
if
q
,
ok
:=
q
.
(
*
ent
.
ErrorPassthroughRuleQuery
);
ok
{
return
f
(
ctx
,
q
)
}
return
nil
,
fmt
.
Errorf
(
"unexpected query type %T. expect *ent.ErrorPassthroughRuleQuery"
,
q
)
}
// The TraverseErrorPassthroughRule type is an adapter to allow the use of ordinary function as Traverser.
type
TraverseErrorPassthroughRule
func
(
context
.
Context
,
*
ent
.
ErrorPassthroughRuleQuery
)
error
// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline.
func
(
f
TraverseErrorPassthroughRule
)
Intercept
(
next
ent
.
Querier
)
ent
.
Querier
{
return
next
}
// Traverse calls f(ctx, q).
func
(
f
TraverseErrorPassthroughRule
)
Traverse
(
ctx
context
.
Context
,
q
ent
.
Query
)
error
{
if
q
,
ok
:=
q
.
(
*
ent
.
ErrorPassthroughRuleQuery
);
ok
{
return
f
(
ctx
,
q
)
}
return
fmt
.
Errorf
(
"unexpected query type %T. expect *ent.ErrorPassthroughRuleQuery"
,
q
)
}
// The GroupFunc type is an adapter to allow the use of ordinary function as a Querier.
type
GroupFunc
func
(
context
.
Context
,
*
ent
.
GroupQuery
)
(
ent
.
Value
,
error
)
...
...
@@ -584,6 +612,8 @@ func NewQuery(q ent.Query) (Query, error) {
return
&
query
[
*
ent
.
AnnouncementQuery
,
predicate
.
Announcement
,
announcement
.
OrderOption
]{
typ
:
ent
.
TypeAnnouncement
,
tq
:
q
},
nil
case
*
ent
.
AnnouncementReadQuery
:
return
&
query
[
*
ent
.
AnnouncementReadQuery
,
predicate
.
AnnouncementRead
,
announcementread
.
OrderOption
]{
typ
:
ent
.
TypeAnnouncementRead
,
tq
:
q
},
nil
case
*
ent
.
ErrorPassthroughRuleQuery
:
return
&
query
[
*
ent
.
ErrorPassthroughRuleQuery
,
predicate
.
ErrorPassthroughRule
,
errorpassthroughrule
.
OrderOption
]{
typ
:
ent
.
TypeErrorPassthroughRule
,
tq
:
q
},
nil
case
*
ent
.
GroupQuery
:
return
&
query
[
*
ent
.
GroupQuery
,
predicate
.
Group
,
group
.
OrderOption
]{
typ
:
ent
.
TypeGroup
,
tq
:
q
},
nil
case
*
ent
.
PromoCodeQuery
:
...
...
backend/ent/migrate/schema.go
View file @
7319122e
...
...
@@ -309,6 +309,42 @@ var (
},
},
}
// ErrorPassthroughRulesColumns holds the columns for the "error_passthrough_rules" table.
ErrorPassthroughRulesColumns
=
[]
*
schema
.
Column
{
{
Name
:
"id"
,
Type
:
field
.
TypeInt64
,
Increment
:
true
},
{
Name
:
"created_at"
,
Type
:
field
.
TypeTime
,
SchemaType
:
map
[
string
]
string
{
"postgres"
:
"timestamptz"
}},
{
Name
:
"updated_at"
,
Type
:
field
.
TypeTime
,
SchemaType
:
map
[
string
]
string
{
"postgres"
:
"timestamptz"
}},
{
Name
:
"name"
,
Type
:
field
.
TypeString
,
Size
:
100
},
{
Name
:
"enabled"
,
Type
:
field
.
TypeBool
,
Default
:
true
},
{
Name
:
"priority"
,
Type
:
field
.
TypeInt
,
Default
:
0
},
{
Name
:
"error_codes"
,
Type
:
field
.
TypeJSON
,
Nullable
:
true
,
SchemaType
:
map
[
string
]
string
{
"postgres"
:
"jsonb"
}},
{
Name
:
"keywords"
,
Type
:
field
.
TypeJSON
,
Nullable
:
true
,
SchemaType
:
map
[
string
]
string
{
"postgres"
:
"jsonb"
}},
{
Name
:
"match_mode"
,
Type
:
field
.
TypeString
,
Size
:
10
,
Default
:
"any"
},
{
Name
:
"platforms"
,
Type
:
field
.
TypeJSON
,
Nullable
:
true
,
SchemaType
:
map
[
string
]
string
{
"postgres"
:
"jsonb"
}},
{
Name
:
"passthrough_code"
,
Type
:
field
.
TypeBool
,
Default
:
true
},
{
Name
:
"response_code"
,
Type
:
field
.
TypeInt
,
Nullable
:
true
},
{
Name
:
"passthrough_body"
,
Type
:
field
.
TypeBool
,
Default
:
true
},
{
Name
:
"custom_message"
,
Type
:
field
.
TypeString
,
Nullable
:
true
,
Size
:
2147483647
},
{
Name
:
"description"
,
Type
:
field
.
TypeString
,
Nullable
:
true
,
Size
:
2147483647
},
}
// ErrorPassthroughRulesTable holds the schema information for the "error_passthrough_rules" table.
ErrorPassthroughRulesTable
=
&
schema
.
Table
{
Name
:
"error_passthrough_rules"
,
Columns
:
ErrorPassthroughRulesColumns
,
PrimaryKey
:
[]
*
schema
.
Column
{
ErrorPassthroughRulesColumns
[
0
]},
Indexes
:
[]
*
schema
.
Index
{
{
Name
:
"errorpassthroughrule_enabled"
,
Unique
:
false
,
Columns
:
[]
*
schema
.
Column
{
ErrorPassthroughRulesColumns
[
4
]},
},
{
Name
:
"errorpassthroughrule_priority"
,
Unique
:
false
,
Columns
:
[]
*
schema
.
Column
{
ErrorPassthroughRulesColumns
[
5
]},
},
},
}
// GroupsColumns holds the columns for the "groups" table.
GroupsColumns
=
[]
*
schema
.
Column
{
{
Name
:
"id"
,
Type
:
field
.
TypeInt64
,
Increment
:
true
},
...
...
@@ -950,6 +986,7 @@ var (
AccountGroupsTable
,
AnnouncementsTable
,
AnnouncementReadsTable
,
ErrorPassthroughRulesTable
,
GroupsTable
,
PromoCodesTable
,
PromoCodeUsagesTable
,
...
...
@@ -989,6 +1026,9 @@ func init() {
AnnouncementReadsTable
.
Annotation
=
&
entsql
.
Annotation
{
Table
:
"announcement_reads"
,
}
ErrorPassthroughRulesTable
.
Annotation
=
&
entsql
.
Annotation
{
Table
:
"error_passthrough_rules"
,
}
GroupsTable
.
Annotation
=
&
entsql
.
Annotation
{
Table
:
"groups"
,
}
...
...
backend/ent/mutation.go
View file @
7319122e
...
...
@@ -17,6 +17,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent/announcement"
"github.com/Wei-Shaw/sub2api/ent/announcementread"
"github.com/Wei-Shaw/sub2api/ent/apikey"
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/predicate"
"github.com/Wei-Shaw/sub2api/ent/promocode"
...
...
@@ -48,6 +49,7 @@ const (
TypeAccountGroup = "AccountGroup"
TypeAnnouncement = "Announcement"
TypeAnnouncementRead = "AnnouncementRead"
TypeErrorPassthroughRule = "ErrorPassthroughRule"
TypeGroup = "Group"
TypePromoCode = "PromoCode"
TypePromoCodeUsage = "PromoCodeUsage"
...
...
@@ -5750,6 +5752,1272 @@ func (m *AnnouncementReadMutation) ResetEdge(name string) error {
return fmt.Errorf("unknown AnnouncementRead edge %s", name)
}
// ErrorPassthroughRuleMutation represents an operation that mutates the ErrorPassthroughRule nodes in the graph.
type ErrorPassthroughRuleMutation struct {
config
op Op
typ string
id *int64
created_at *time.Time
updated_at *time.Time
name *string
enabled *bool
priority *int
addpriority *int
error_codes *[]int
appenderror_codes []int
keywords *[]string
appendkeywords []string
match_mode *string
platforms *[]string
appendplatforms []string
passthrough_code *bool
response_code *int
addresponse_code *int
passthrough_body *bool
custom_message *string
description *string
clearedFields map[string]struct{}
done bool
oldValue func(context.Context) (*ErrorPassthroughRule, error)
predicates []predicate.ErrorPassthroughRule
}
var _ ent.Mutation = (*ErrorPassthroughRuleMutation)(nil)
// errorpassthroughruleOption allows management of the mutation configuration using functional options.
type errorpassthroughruleOption func(*ErrorPassthroughRuleMutation)
// newErrorPassthroughRuleMutation creates new mutation for the ErrorPassthroughRule entity.
func newErrorPassthroughRuleMutation(c config, op Op, opts ...errorpassthroughruleOption) *ErrorPassthroughRuleMutation {
m := &ErrorPassthroughRuleMutation{
config: c,
op: op,
typ: TypeErrorPassthroughRule,
clearedFields: make(map[string]struct{}),
}
for _, opt := range opts {
opt(m)
}
return m
}
// withErrorPassthroughRuleID sets the ID field of the mutation.
func withErrorPassthroughRuleID(id int64) errorpassthroughruleOption {
return func(m *ErrorPassthroughRuleMutation) {
var (
err error
once sync.Once
value *ErrorPassthroughRule
)
m.oldValue = func(ctx context.Context) (*ErrorPassthroughRule, error) {
once.Do(func() {
if m.done {
err = errors.New("querying old values post mutation is not allowed")
} else {
value, err = m.Client().ErrorPassthroughRule.Get(ctx, id)
}
})
return value, err
}
m.id = &id
}
}
// withErrorPassthroughRule sets the old ErrorPassthroughRule of the mutation.
func withErrorPassthroughRule(node *ErrorPassthroughRule) errorpassthroughruleOption {
return func(m *ErrorPassthroughRuleMutation) {
m.oldValue = func(context.Context) (*ErrorPassthroughRule, error) {
return node, nil
}
m.id = &node.ID
}
}
// Client returns a new `ent.Client` from the mutation. If the mutation was
// executed in a transaction (ent.Tx), a transactional client is returned.
func (m ErrorPassthroughRuleMutation) Client() *Client {
client := &Client{config: m.config}
client.init()
return client
}
// Tx returns an `ent.Tx` for mutations that were executed in transactions;
// it returns an error otherwise.
func (m ErrorPassthroughRuleMutation) Tx() (*Tx, error) {
if _, ok := m.driver.(*txDriver); !ok {
return nil, errors.New("ent: mutation is not running in a transaction")
}
tx := &Tx{config: m.config}
tx.init()
return tx, nil
}
// ID returns the ID value in the mutation. Note that the ID is only available
// if it was provided to the builder or after it was returned from the database.
func (m *ErrorPassthroughRuleMutation) ID() (id int64, exists bool) {
if m.id == nil {
return
}
return *m.id, true
}
// IDs queries the database and returns the entity ids that match the mutation's predicate.
// That means, if the mutation is applied within a transaction with an isolation level such
// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated
// or updated by the mutation.
func (m *ErrorPassthroughRuleMutation) IDs(ctx context.Context) ([]int64, error) {
switch {
case m.op.Is(OpUpdateOne | OpDeleteOne):
id, exists := m.ID()
if exists {
return []int64{id}, nil
}
fallthrough
case m.op.Is(OpUpdate | OpDelete):
return m.Client().ErrorPassthroughRule.Query().Where(m.predicates...).IDs(ctx)
default:
return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op)
}
}
// SetCreatedAt sets the "created_at" field.
func (m *ErrorPassthroughRuleMutation) SetCreatedAt(t time.Time) {
m.created_at = &t
}
// CreatedAt returns the value of the "created_at" field in the mutation.
func (m *ErrorPassthroughRuleMutation) CreatedAt() (r time.Time, exists bool) {
v := m.created_at
if v == nil {
return
}
return *v, true
}
// OldCreatedAt returns the old "created_at" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldCreatedAt requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err)
}
return oldValue.CreatedAt, nil
}
// ResetCreatedAt resets all changes to the "created_at" field.
func (m *ErrorPassthroughRuleMutation) ResetCreatedAt() {
m.created_at = nil
}
// SetUpdatedAt sets the "updated_at" field.
func (m *ErrorPassthroughRuleMutation) SetUpdatedAt(t time.Time) {
m.updated_at = &t
}
// UpdatedAt returns the value of the "updated_at" field in the mutation.
func (m *ErrorPassthroughRuleMutation) UpdatedAt() (r time.Time, exists bool) {
v := m.updated_at
if v == nil {
return
}
return *v, true
}
// OldUpdatedAt returns the old "updated_at" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldUpdatedAt(ctx context.Context) (v time.Time, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldUpdatedAt is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldUpdatedAt requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldUpdatedAt: %w", err)
}
return oldValue.UpdatedAt, nil
}
// ResetUpdatedAt resets all changes to the "updated_at" field.
func (m *ErrorPassthroughRuleMutation) ResetUpdatedAt() {
m.updated_at = nil
}
// SetName sets the "name" field.
func (m *ErrorPassthroughRuleMutation) SetName(s string) {
m.name = &s
}
// Name returns the value of the "name" field in the mutation.
func (m *ErrorPassthroughRuleMutation) Name() (r string, exists bool) {
v := m.name
if v == nil {
return
}
return *v, true
}
// OldName returns the old "name" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldName(ctx context.Context) (v string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldName is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldName requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldName: %w", err)
}
return oldValue.Name, nil
}
// ResetName resets all changes to the "name" field.
func (m *ErrorPassthroughRuleMutation) ResetName() {
m.name = nil
}
// SetEnabled sets the "enabled" field.
func (m *ErrorPassthroughRuleMutation) SetEnabled(b bool) {
m.enabled = &b
}
// Enabled returns the value of the "enabled" field in the mutation.
func (m *ErrorPassthroughRuleMutation) Enabled() (r bool, exists bool) {
v := m.enabled
if v == nil {
return
}
return *v, true
}
// OldEnabled returns the old "enabled" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldEnabled(ctx context.Context) (v bool, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldEnabled is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldEnabled requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldEnabled: %w", err)
}
return oldValue.Enabled, nil
}
// ResetEnabled resets all changes to the "enabled" field.
func (m *ErrorPassthroughRuleMutation) ResetEnabled() {
m.enabled = nil
}
// SetPriority sets the "priority" field.
func (m *ErrorPassthroughRuleMutation) SetPriority(i int) {
m.priority = &i
m.addpriority = nil
}
// Priority returns the value of the "priority" field in the mutation.
func (m *ErrorPassthroughRuleMutation) Priority() (r int, exists bool) {
v := m.priority
if v == nil {
return
}
return *v, true
}
// OldPriority returns the old "priority" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldPriority(ctx context.Context) (v int, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldPriority is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldPriority requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldPriority: %w", err)
}
return oldValue.Priority, nil
}
// AddPriority adds i to the "priority" field.
func (m *ErrorPassthroughRuleMutation) AddPriority(i int) {
if m.addpriority != nil {
*m.addpriority += i
} else {
m.addpriority = &i
}
}
// AddedPriority returns the value that was added to the "priority" field in this mutation.
func (m *ErrorPassthroughRuleMutation) AddedPriority() (r int, exists bool) {
v := m.addpriority
if v == nil {
return
}
return *v, true
}
// ResetPriority resets all changes to the "priority" field.
func (m *ErrorPassthroughRuleMutation) ResetPriority() {
m.priority = nil
m.addpriority = nil
}
// SetErrorCodes sets the "error_codes" field.
func (m *ErrorPassthroughRuleMutation) SetErrorCodes(i []int) {
m.error_codes = &i
m.appenderror_codes = nil
}
// ErrorCodes returns the value of the "error_codes" field in the mutation.
func (m *ErrorPassthroughRuleMutation) ErrorCodes() (r []int, exists bool) {
v := m.error_codes
if v == nil {
return
}
return *v, true
}
// OldErrorCodes returns the old "error_codes" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldErrorCodes(ctx context.Context) (v []int, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldErrorCodes is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldErrorCodes requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldErrorCodes: %w", err)
}
return oldValue.ErrorCodes, nil
}
// AppendErrorCodes adds i to the "error_codes" field.
func (m *ErrorPassthroughRuleMutation) AppendErrorCodes(i []int) {
m.appenderror_codes = append(m.appenderror_codes, i...)
}
// AppendedErrorCodes returns the list of values that were appended to the "error_codes" field in this mutation.
func (m *ErrorPassthroughRuleMutation) AppendedErrorCodes() ([]int, bool) {
if len(m.appenderror_codes) == 0 {
return nil, false
}
return m.appenderror_codes, true
}
// ClearErrorCodes clears the value of the "error_codes" field.
func (m *ErrorPassthroughRuleMutation) ClearErrorCodes() {
m.error_codes = nil
m.appenderror_codes = nil
m.clearedFields[errorpassthroughrule.FieldErrorCodes] = struct{}{}
}
// ErrorCodesCleared returns if the "error_codes" field was cleared in this mutation.
func (m *ErrorPassthroughRuleMutation) ErrorCodesCleared() bool {
_, ok := m.clearedFields[errorpassthroughrule.FieldErrorCodes]
return ok
}
// ResetErrorCodes resets all changes to the "error_codes" field.
func (m *ErrorPassthroughRuleMutation) ResetErrorCodes() {
m.error_codes = nil
m.appenderror_codes = nil
delete(m.clearedFields, errorpassthroughrule.FieldErrorCodes)
}
// SetKeywords sets the "keywords" field.
func (m *ErrorPassthroughRuleMutation) SetKeywords(s []string) {
m.keywords = &s
m.appendkeywords = nil
}
// Keywords returns the value of the "keywords" field in the mutation.
func (m *ErrorPassthroughRuleMutation) Keywords() (r []string, exists bool) {
v := m.keywords
if v == nil {
return
}
return *v, true
}
// OldKeywords returns the old "keywords" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldKeywords(ctx context.Context) (v []string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldKeywords is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldKeywords requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldKeywords: %w", err)
}
return oldValue.Keywords, nil
}
// AppendKeywords adds s to the "keywords" field.
func (m *ErrorPassthroughRuleMutation) AppendKeywords(s []string) {
m.appendkeywords = append(m.appendkeywords, s...)
}
// AppendedKeywords returns the list of values that were appended to the "keywords" field in this mutation.
func (m *ErrorPassthroughRuleMutation) AppendedKeywords() ([]string, bool) {
if len(m.appendkeywords) == 0 {
return nil, false
}
return m.appendkeywords, true
}
// ClearKeywords clears the value of the "keywords" field.
func (m *ErrorPassthroughRuleMutation) ClearKeywords() {
m.keywords = nil
m.appendkeywords = nil
m.clearedFields[errorpassthroughrule.FieldKeywords] = struct{}{}
}
// KeywordsCleared returns if the "keywords" field was cleared in this mutation.
func (m *ErrorPassthroughRuleMutation) KeywordsCleared() bool {
_, ok := m.clearedFields[errorpassthroughrule.FieldKeywords]
return ok
}
// ResetKeywords resets all changes to the "keywords" field.
func (m *ErrorPassthroughRuleMutation) ResetKeywords() {
m.keywords = nil
m.appendkeywords = nil
delete(m.clearedFields, errorpassthroughrule.FieldKeywords)
}
// SetMatchMode sets the "match_mode" field.
func (m *ErrorPassthroughRuleMutation) SetMatchMode(s string) {
m.match_mode = &s
}
// MatchMode returns the value of the "match_mode" field in the mutation.
func (m *ErrorPassthroughRuleMutation) MatchMode() (r string, exists bool) {
v := m.match_mode
if v == nil {
return
}
return *v, true
}
// OldMatchMode returns the old "match_mode" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldMatchMode(ctx context.Context) (v string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldMatchMode is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldMatchMode requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldMatchMode: %w", err)
}
return oldValue.MatchMode, nil
}
// ResetMatchMode resets all changes to the "match_mode" field.
func (m *ErrorPassthroughRuleMutation) ResetMatchMode() {
m.match_mode = nil
}
// SetPlatforms sets the "platforms" field.
func (m *ErrorPassthroughRuleMutation) SetPlatforms(s []string) {
m.platforms = &s
m.appendplatforms = nil
}
// Platforms returns the value of the "platforms" field in the mutation.
func (m *ErrorPassthroughRuleMutation) Platforms() (r []string, exists bool) {
v := m.platforms
if v == nil {
return
}
return *v, true
}
// OldPlatforms returns the old "platforms" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldPlatforms(ctx context.Context) (v []string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldPlatforms is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldPlatforms requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldPlatforms: %w", err)
}
return oldValue.Platforms, nil
}
// AppendPlatforms adds s to the "platforms" field.
func (m *ErrorPassthroughRuleMutation) AppendPlatforms(s []string) {
m.appendplatforms = append(m.appendplatforms, s...)
}
// AppendedPlatforms returns the list of values that were appended to the "platforms" field in this mutation.
func (m *ErrorPassthroughRuleMutation) AppendedPlatforms() ([]string, bool) {
if len(m.appendplatforms) == 0 {
return nil, false
}
return m.appendplatforms, true
}
// ClearPlatforms clears the value of the "platforms" field.
func (m *ErrorPassthroughRuleMutation) ClearPlatforms() {
m.platforms = nil
m.appendplatforms = nil
m.clearedFields[errorpassthroughrule.FieldPlatforms] = struct{}{}
}
// PlatformsCleared returns if the "platforms" field was cleared in this mutation.
func (m *ErrorPassthroughRuleMutation) PlatformsCleared() bool {
_, ok := m.clearedFields[errorpassthroughrule.FieldPlatforms]
return ok
}
// ResetPlatforms resets all changes to the "platforms" field.
func (m *ErrorPassthroughRuleMutation) ResetPlatforms() {
m.platforms = nil
m.appendplatforms = nil
delete(m.clearedFields, errorpassthroughrule.FieldPlatforms)
}
// SetPassthroughCode sets the "passthrough_code" field.
func (m *ErrorPassthroughRuleMutation) SetPassthroughCode(b bool) {
m.passthrough_code = &b
}
// PassthroughCode returns the value of the "passthrough_code" field in the mutation.
func (m *ErrorPassthroughRuleMutation) PassthroughCode() (r bool, exists bool) {
v := m.passthrough_code
if v == nil {
return
}
return *v, true
}
// OldPassthroughCode returns the old "passthrough_code" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldPassthroughCode(ctx context.Context) (v bool, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldPassthroughCode is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldPassthroughCode requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldPassthroughCode: %w", err)
}
return oldValue.PassthroughCode, nil
}
// ResetPassthroughCode resets all changes to the "passthrough_code" field.
func (m *ErrorPassthroughRuleMutation) ResetPassthroughCode() {
m.passthrough_code = nil
}
// SetResponseCode sets the "response_code" field.
func (m *ErrorPassthroughRuleMutation) SetResponseCode(i int) {
m.response_code = &i
m.addresponse_code = nil
}
// ResponseCode returns the value of the "response_code" field in the mutation.
func (m *ErrorPassthroughRuleMutation) ResponseCode() (r int, exists bool) {
v := m.response_code
if v == nil {
return
}
return *v, true
}
// OldResponseCode returns the old "response_code" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldResponseCode(ctx context.Context) (v *int, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldResponseCode is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldResponseCode requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldResponseCode: %w", err)
}
return oldValue.ResponseCode, nil
}
// AddResponseCode adds i to the "response_code" field.
func (m *ErrorPassthroughRuleMutation) AddResponseCode(i int) {
if m.addresponse_code != nil {
*m.addresponse_code += i
} else {
m.addresponse_code = &i
}
}
// AddedResponseCode returns the value that was added to the "response_code" field in this mutation.
func (m *ErrorPassthroughRuleMutation) AddedResponseCode() (r int, exists bool) {
v := m.addresponse_code
if v == nil {
return
}
return *v, true
}
// ClearResponseCode clears the value of the "response_code" field.
func (m *ErrorPassthroughRuleMutation) ClearResponseCode() {
m.response_code = nil
m.addresponse_code = nil
m.clearedFields[errorpassthroughrule.FieldResponseCode] = struct{}{}
}
// ResponseCodeCleared returns if the "response_code" field was cleared in this mutation.
func (m *ErrorPassthroughRuleMutation) ResponseCodeCleared() bool {
_, ok := m.clearedFields[errorpassthroughrule.FieldResponseCode]
return ok
}
// ResetResponseCode resets all changes to the "response_code" field.
func (m *ErrorPassthroughRuleMutation) ResetResponseCode() {
m.response_code = nil
m.addresponse_code = nil
delete(m.clearedFields, errorpassthroughrule.FieldResponseCode)
}
// SetPassthroughBody sets the "passthrough_body" field.
func (m *ErrorPassthroughRuleMutation) SetPassthroughBody(b bool) {
m.passthrough_body = &b
}
// PassthroughBody returns the value of the "passthrough_body" field in the mutation.
func (m *ErrorPassthroughRuleMutation) PassthroughBody() (r bool, exists bool) {
v := m.passthrough_body
if v == nil {
return
}
return *v, true
}
// OldPassthroughBody returns the old "passthrough_body" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldPassthroughBody(ctx context.Context) (v bool, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldPassthroughBody is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldPassthroughBody requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldPassthroughBody: %w", err)
}
return oldValue.PassthroughBody, nil
}
// ResetPassthroughBody resets all changes to the "passthrough_body" field.
func (m *ErrorPassthroughRuleMutation) ResetPassthroughBody() {
m.passthrough_body = nil
}
// SetCustomMessage sets the "custom_message" field.
func (m *ErrorPassthroughRuleMutation) SetCustomMessage(s string) {
m.custom_message = &s
}
// CustomMessage returns the value of the "custom_message" field in the mutation.
func (m *ErrorPassthroughRuleMutation) CustomMessage() (r string, exists bool) {
v := m.custom_message
if v == nil {
return
}
return *v, true
}
// OldCustomMessage returns the old "custom_message" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldCustomMessage(ctx context.Context) (v *string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldCustomMessage is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldCustomMessage requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldCustomMessage: %w", err)
}
return oldValue.CustomMessage, nil
}
// ClearCustomMessage clears the value of the "custom_message" field.
func (m *ErrorPassthroughRuleMutation) ClearCustomMessage() {
m.custom_message = nil
m.clearedFields[errorpassthroughrule.FieldCustomMessage] = struct{}{}
}
// CustomMessageCleared returns if the "custom_message" field was cleared in this mutation.
func (m *ErrorPassthroughRuleMutation) CustomMessageCleared() bool {
_, ok := m.clearedFields[errorpassthroughrule.FieldCustomMessage]
return ok
}
// ResetCustomMessage resets all changes to the "custom_message" field.
func (m *ErrorPassthroughRuleMutation) ResetCustomMessage() {
m.custom_message = nil
delete(m.clearedFields, errorpassthroughrule.FieldCustomMessage)
}
// SetDescription sets the "description" field.
func (m *ErrorPassthroughRuleMutation) SetDescription(s string) {
m.description = &s
}
// Description returns the value of the "description" field in the mutation.
func (m *ErrorPassthroughRuleMutation) Description() (r string, exists bool) {
v := m.description
if v == nil {
return
}
return *v, true
}
// OldDescription returns the old "description" field's value of the ErrorPassthroughRule entity.
// If the ErrorPassthroughRule object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *ErrorPassthroughRuleMutation) OldDescription(ctx context.Context) (v *string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldDescription is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldDescription requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldDescription: %w", err)
}
return oldValue.Description, nil
}
// ClearDescription clears the value of the "description" field.
func (m *ErrorPassthroughRuleMutation) ClearDescription() {
m.description = nil
m.clearedFields[errorpassthroughrule.FieldDescription] = struct{}{}
}
// DescriptionCleared returns if the "description" field was cleared in this mutation.
func (m *ErrorPassthroughRuleMutation) DescriptionCleared() bool {
_, ok := m.clearedFields[errorpassthroughrule.FieldDescription]
return ok
}
// ResetDescription resets all changes to the "description" field.
func (m *ErrorPassthroughRuleMutation) ResetDescription() {
m.description = nil
delete(m.clearedFields, errorpassthroughrule.FieldDescription)
}
// Where appends a list predicates to the ErrorPassthroughRuleMutation builder.
func (m *ErrorPassthroughRuleMutation) Where(ps ...predicate.ErrorPassthroughRule) {
m.predicates = append(m.predicates, ps...)
}
// WhereP appends storage-level predicates to the ErrorPassthroughRuleMutation builder. Using this method,
// users can use type-assertion to append predicates that do not depend on any generated package.
func (m *ErrorPassthroughRuleMutation) WhereP(ps ...func(*sql.Selector)) {
p := make([]predicate.ErrorPassthroughRule, len(ps))
for i := range ps {
p[i] = ps[i]
}
m.Where(p...)
}
// Op returns the operation name.
func (m *ErrorPassthroughRuleMutation) Op() Op {
return m.op
}
// SetOp allows setting the mutation operation.
func (m *ErrorPassthroughRuleMutation) SetOp(op Op) {
m.op = op
}
// Type returns the node type of this mutation (ErrorPassthroughRule).
func (m *ErrorPassthroughRuleMutation) Type() string {
return m.typ
}
// Fields returns all fields that were changed during this mutation. Note that in
// order to get all numeric fields that were incremented/decremented, call
// AddedFields().
func (m *ErrorPassthroughRuleMutation) Fields() []string {
fields := make([]string, 0, 14)
if m.created_at != nil {
fields = append(fields, errorpassthroughrule.FieldCreatedAt)
}
if m.updated_at != nil {
fields = append(fields, errorpassthroughrule.FieldUpdatedAt)
}
if m.name != nil {
fields = append(fields, errorpassthroughrule.FieldName)
}
if m.enabled != nil {
fields = append(fields, errorpassthroughrule.FieldEnabled)
}
if m.priority != nil {
fields = append(fields, errorpassthroughrule.FieldPriority)
}
if m.error_codes != nil {
fields = append(fields, errorpassthroughrule.FieldErrorCodes)
}
if m.keywords != nil {
fields = append(fields, errorpassthroughrule.FieldKeywords)
}
if m.match_mode != nil {
fields = append(fields, errorpassthroughrule.FieldMatchMode)
}
if m.platforms != nil {
fields = append(fields, errorpassthroughrule.FieldPlatforms)
}
if m.passthrough_code != nil {
fields = append(fields, errorpassthroughrule.FieldPassthroughCode)
}
if m.response_code != nil {
fields = append(fields, errorpassthroughrule.FieldResponseCode)
}
if m.passthrough_body != nil {
fields = append(fields, errorpassthroughrule.FieldPassthroughBody)
}
if m.custom_message != nil {
fields = append(fields, errorpassthroughrule.FieldCustomMessage)
}
if m.description != nil {
fields = append(fields, errorpassthroughrule.FieldDescription)
}
return fields
}
// Field returns the value of a field with the given name. The second boolean
// return value indicates that this field was not set, or was not defined in the
// schema.
func (m *ErrorPassthroughRuleMutation) Field(name string) (ent.Value, bool) {
switch name {
case errorpassthroughrule.FieldCreatedAt:
return m.CreatedAt()
case errorpassthroughrule.FieldUpdatedAt:
return m.UpdatedAt()
case errorpassthroughrule.FieldName:
return m.Name()
case errorpassthroughrule.FieldEnabled:
return m.Enabled()
case errorpassthroughrule.FieldPriority:
return m.Priority()
case errorpassthroughrule.FieldErrorCodes:
return m.ErrorCodes()
case errorpassthroughrule.FieldKeywords:
return m.Keywords()
case errorpassthroughrule.FieldMatchMode:
return m.MatchMode()
case errorpassthroughrule.FieldPlatforms:
return m.Platforms()
case errorpassthroughrule.FieldPassthroughCode:
return m.PassthroughCode()
case errorpassthroughrule.FieldResponseCode:
return m.ResponseCode()
case errorpassthroughrule.FieldPassthroughBody:
return m.PassthroughBody()
case errorpassthroughrule.FieldCustomMessage:
return m.CustomMessage()
case errorpassthroughrule.FieldDescription:
return m.Description()
}
return nil, false
}
// OldField returns the old value of the field from the database. An error is
// returned if the mutation operation is not UpdateOne, or the query to the
// database failed.
func (m *ErrorPassthroughRuleMutation) OldField(ctx context.Context, name string) (ent.Value, error) {
switch name {
case errorpassthroughrule.FieldCreatedAt:
return m.OldCreatedAt(ctx)
case errorpassthroughrule.FieldUpdatedAt:
return m.OldUpdatedAt(ctx)
case errorpassthroughrule.FieldName:
return m.OldName(ctx)
case errorpassthroughrule.FieldEnabled:
return m.OldEnabled(ctx)
case errorpassthroughrule.FieldPriority:
return m.OldPriority(ctx)
case errorpassthroughrule.FieldErrorCodes:
return m.OldErrorCodes(ctx)
case errorpassthroughrule.FieldKeywords:
return m.OldKeywords(ctx)
case errorpassthroughrule.FieldMatchMode:
return m.OldMatchMode(ctx)
case errorpassthroughrule.FieldPlatforms:
return m.OldPlatforms(ctx)
case errorpassthroughrule.FieldPassthroughCode:
return m.OldPassthroughCode(ctx)
case errorpassthroughrule.FieldResponseCode:
return m.OldResponseCode(ctx)
case errorpassthroughrule.FieldPassthroughBody:
return m.OldPassthroughBody(ctx)
case errorpassthroughrule.FieldCustomMessage:
return m.OldCustomMessage(ctx)
case errorpassthroughrule.FieldDescription:
return m.OldDescription(ctx)
}
return nil, fmt.Errorf("unknown ErrorPassthroughRule field %s", name)
}
// SetField sets the value of a field with the given name. It returns an error if
// the field is not defined in the schema, or if the type mismatched the field
// type.
func (m *ErrorPassthroughRuleMutation) SetField(name string, value ent.Value) error {
switch name {
case errorpassthroughrule.FieldCreatedAt:
v, ok := value.(time.Time)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetCreatedAt(v)
return nil
case errorpassthroughrule.FieldUpdatedAt:
v, ok := value.(time.Time)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetUpdatedAt(v)
return nil
case errorpassthroughrule.FieldName:
v, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetName(v)
return nil
case errorpassthroughrule.FieldEnabled:
v, ok := value.(bool)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetEnabled(v)
return nil
case errorpassthroughrule.FieldPriority:
v, ok := value.(int)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetPriority(v)
return nil
case errorpassthroughrule.FieldErrorCodes:
v, ok := value.([]int)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetErrorCodes(v)
return nil
case errorpassthroughrule.FieldKeywords:
v, ok := value.([]string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetKeywords(v)
return nil
case errorpassthroughrule.FieldMatchMode:
v, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetMatchMode(v)
return nil
case errorpassthroughrule.FieldPlatforms:
v, ok := value.([]string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetPlatforms(v)
return nil
case errorpassthroughrule.FieldPassthroughCode:
v, ok := value.(bool)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetPassthroughCode(v)
return nil
case errorpassthroughrule.FieldResponseCode:
v, ok := value.(int)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetResponseCode(v)
return nil
case errorpassthroughrule.FieldPassthroughBody:
v, ok := value.(bool)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetPassthroughBody(v)
return nil
case errorpassthroughrule.FieldCustomMessage:
v, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetCustomMessage(v)
return nil
case errorpassthroughrule.FieldDescription:
v, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetDescription(v)
return nil
}
return fmt.Errorf("unknown ErrorPassthroughRule field %s", name)
}
// AddedFields returns all numeric fields that were incremented/decremented during
// this mutation.
func (m *ErrorPassthroughRuleMutation) AddedFields() []string {
var fields []string
if m.addpriority != nil {
fields = append(fields, errorpassthroughrule.FieldPriority)
}
if m.addresponse_code != nil {
fields = append(fields, errorpassthroughrule.FieldResponseCode)
}
return fields
}
// AddedField returns the numeric value that was incremented/decremented on a field
// with the given name. The second boolean return value indicates that this field
// was not set, or was not defined in the schema.
func (m *ErrorPassthroughRuleMutation) AddedField(name string) (ent.Value, bool) {
switch name {
case errorpassthroughrule.FieldPriority:
return m.AddedPriority()
case errorpassthroughrule.FieldResponseCode:
return m.AddedResponseCode()
}
return nil, false
}
// AddField adds the value to the field with the given name. It returns an error if
// the field is not defined in the schema, or if the type mismatched the field
// type.
func (m *ErrorPassthroughRuleMutation) AddField(name string, value ent.Value) error {
switch name {
case errorpassthroughrule.FieldPriority:
v, ok := value.(int)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.AddPriority(v)
return nil
case errorpassthroughrule.FieldResponseCode:
v, ok := value.(int)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.AddResponseCode(v)
return nil
}
return fmt.Errorf("unknown ErrorPassthroughRule numeric field %s", name)
}
// ClearedFields returns all nullable fields that were cleared during this
// mutation.
func (m *ErrorPassthroughRuleMutation) ClearedFields() []string {
var fields []string
if m.FieldCleared(errorpassthroughrule.FieldErrorCodes) {
fields = append(fields, errorpassthroughrule.FieldErrorCodes)
}
if m.FieldCleared(errorpassthroughrule.FieldKeywords) {
fields = append(fields, errorpassthroughrule.FieldKeywords)
}
if m.FieldCleared(errorpassthroughrule.FieldPlatforms) {
fields = append(fields, errorpassthroughrule.FieldPlatforms)
}
if m.FieldCleared(errorpassthroughrule.FieldResponseCode) {
fields = append(fields, errorpassthroughrule.FieldResponseCode)
}
if m.FieldCleared(errorpassthroughrule.FieldCustomMessage) {
fields = append(fields, errorpassthroughrule.FieldCustomMessage)
}
if m.FieldCleared(errorpassthroughrule.FieldDescription) {
fields = append(fields, errorpassthroughrule.FieldDescription)
}
return fields
}
// FieldCleared returns a boolean indicating if a field with the given name was
// cleared in this mutation.
func (m *ErrorPassthroughRuleMutation) FieldCleared(name string) bool {
_, ok := m.clearedFields[name]
return ok
}
// ClearField clears the value of the field with the given name. It returns an
// error if the field is not defined in the schema.
func (m *ErrorPassthroughRuleMutation) ClearField(name string) error {
switch name {
case errorpassthroughrule.FieldErrorCodes:
m.ClearErrorCodes()
return nil
case errorpassthroughrule.FieldKeywords:
m.ClearKeywords()
return nil
case errorpassthroughrule.FieldPlatforms:
m.ClearPlatforms()
return nil
case errorpassthroughrule.FieldResponseCode:
m.ClearResponseCode()
return nil
case errorpassthroughrule.FieldCustomMessage:
m.ClearCustomMessage()
return nil
case errorpassthroughrule.FieldDescription:
m.ClearDescription()
return nil
}
return fmt.Errorf("unknown ErrorPassthroughRule nullable field %s", name)
}
// ResetField resets all changes in the mutation for the field with the given name.
// It returns an error if the field is not defined in the schema.
func (m *ErrorPassthroughRuleMutation) ResetField(name string) error {
switch name {
case errorpassthroughrule.FieldCreatedAt:
m.ResetCreatedAt()
return nil
case errorpassthroughrule.FieldUpdatedAt:
m.ResetUpdatedAt()
return nil
case errorpassthroughrule.FieldName:
m.ResetName()
return nil
case errorpassthroughrule.FieldEnabled:
m.ResetEnabled()
return nil
case errorpassthroughrule.FieldPriority:
m.ResetPriority()
return nil
case errorpassthroughrule.FieldErrorCodes:
m.ResetErrorCodes()
return nil
case errorpassthroughrule.FieldKeywords:
m.ResetKeywords()
return nil
case errorpassthroughrule.FieldMatchMode:
m.ResetMatchMode()
return nil
case errorpassthroughrule.FieldPlatforms:
m.ResetPlatforms()
return nil
case errorpassthroughrule.FieldPassthroughCode:
m.ResetPassthroughCode()
return nil
case errorpassthroughrule.FieldResponseCode:
m.ResetResponseCode()
return nil
case errorpassthroughrule.FieldPassthroughBody:
m.ResetPassthroughBody()
return nil
case errorpassthroughrule.FieldCustomMessage:
m.ResetCustomMessage()
return nil
case errorpassthroughrule.FieldDescription:
m.ResetDescription()
return nil
}
return fmt.Errorf("unknown ErrorPassthroughRule field %s", name)
}
// AddedEdges returns all edge names that were set/added in this mutation.
func (m *ErrorPassthroughRuleMutation) AddedEdges() []string {
edges := make([]string, 0, 0)
return edges
}
// AddedIDs returns all IDs (to other nodes) that were added for the given edge
// name in this mutation.
func (m *ErrorPassthroughRuleMutation) AddedIDs(name string) []ent.Value {
return nil
}
// RemovedEdges returns all edge names that were removed in this mutation.
func (m *ErrorPassthroughRuleMutation) RemovedEdges() []string {
edges := make([]string, 0, 0)
return edges
}
// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with
// the given name in this mutation.
func (m *ErrorPassthroughRuleMutation) RemovedIDs(name string) []ent.Value {
return nil
}
// ClearedEdges returns all edge names that were cleared in this mutation.
func (m *ErrorPassthroughRuleMutation) ClearedEdges() []string {
edges := make([]string, 0, 0)
return edges
}
// EdgeCleared returns a boolean which indicates if the edge with the given name
// was cleared in this mutation.
func (m *ErrorPassthroughRuleMutation) EdgeCleared(name string) bool {
return false
}
// ClearEdge clears the value of the edge with the given name. It returns an error
// if that edge is not defined in the schema.
func (m *ErrorPassthroughRuleMutation) ClearEdge(name string) error {
return fmt.Errorf("unknown ErrorPassthroughRule unique edge %s", name)
}
// ResetEdge resets all changes to the edge with the given name in this mutation.
// It returns an error if the edge is not defined in the schema.
func (m *ErrorPassthroughRuleMutation) ResetEdge(name string) error {
return fmt.Errorf("unknown ErrorPassthroughRule edge %s", name)
}
// GroupMutation represents an operation that mutates the Group nodes in the graph.
type GroupMutation struct {
config
...
...
backend/ent/predicate/predicate.go
View file @
7319122e
...
...
@@ -21,6 +21,9 @@ type Announcement func(*sql.Selector)
// AnnouncementRead is the predicate function for announcementread builders.
type
AnnouncementRead
func
(
*
sql
.
Selector
)
// ErrorPassthroughRule is the predicate function for errorpassthroughrule builders.
type
ErrorPassthroughRule
func
(
*
sql
.
Selector
)
// Group is the predicate function for group builders.
type
Group
func
(
*
sql
.
Selector
)
...
...
backend/ent/runtime/runtime.go
View file @
7319122e
...
...
@@ -10,6 +10,7 @@ import (
"github.com/Wei-Shaw/sub2api/ent/announcement"
"github.com/Wei-Shaw/sub2api/ent/announcementread"
"github.com/Wei-Shaw/sub2api/ent/apikey"
"github.com/Wei-Shaw/sub2api/ent/errorpassthroughrule"
"github.com/Wei-Shaw/sub2api/ent/group"
"github.com/Wei-Shaw/sub2api/ent/promocode"
"github.com/Wei-Shaw/sub2api/ent/promocodeusage"
...
...
@@ -270,6 +271,61 @@ func init() {
announcementreadDescCreatedAt
:=
announcementreadFields
[
3
]
.
Descriptor
()
// announcementread.DefaultCreatedAt holds the default value on creation for the created_at field.
announcementread
.
DefaultCreatedAt
=
announcementreadDescCreatedAt
.
Default
.
(
func
()
time
.
Time
)
errorpassthroughruleMixin
:=
schema
.
ErrorPassthroughRule
{}
.
Mixin
()
errorpassthroughruleMixinFields0
:=
errorpassthroughruleMixin
[
0
]
.
Fields
()
_
=
errorpassthroughruleMixinFields0
errorpassthroughruleFields
:=
schema
.
ErrorPassthroughRule
{}
.
Fields
()
_
=
errorpassthroughruleFields
// errorpassthroughruleDescCreatedAt is the schema descriptor for created_at field.
errorpassthroughruleDescCreatedAt
:=
errorpassthroughruleMixinFields0
[
0
]
.
Descriptor
()
// errorpassthroughrule.DefaultCreatedAt holds the default value on creation for the created_at field.
errorpassthroughrule
.
DefaultCreatedAt
=
errorpassthroughruleDescCreatedAt
.
Default
.
(
func
()
time
.
Time
)
// errorpassthroughruleDescUpdatedAt is the schema descriptor for updated_at field.
errorpassthroughruleDescUpdatedAt
:=
errorpassthroughruleMixinFields0
[
1
]
.
Descriptor
()
// errorpassthroughrule.DefaultUpdatedAt holds the default value on creation for the updated_at field.
errorpassthroughrule
.
DefaultUpdatedAt
=
errorpassthroughruleDescUpdatedAt
.
Default
.
(
func
()
time
.
Time
)
// errorpassthroughrule.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
errorpassthroughrule
.
UpdateDefaultUpdatedAt
=
errorpassthroughruleDescUpdatedAt
.
UpdateDefault
.
(
func
()
time
.
Time
)
// errorpassthroughruleDescName is the schema descriptor for name field.
errorpassthroughruleDescName
:=
errorpassthroughruleFields
[
0
]
.
Descriptor
()
// errorpassthroughrule.NameValidator is a validator for the "name" field. It is called by the builders before save.
errorpassthroughrule
.
NameValidator
=
func
()
func
(
string
)
error
{
validators
:=
errorpassthroughruleDescName
.
Validators
fns
:=
[
...
]
func
(
string
)
error
{
validators
[
0
]
.
(
func
(
string
)
error
),
validators
[
1
]
.
(
func
(
string
)
error
),
}
return
func
(
name
string
)
error
{
for
_
,
fn
:=
range
fns
{
if
err
:=
fn
(
name
);
err
!=
nil
{
return
err
}
}
return
nil
}
}()
// errorpassthroughruleDescEnabled is the schema descriptor for enabled field.
errorpassthroughruleDescEnabled
:=
errorpassthroughruleFields
[
1
]
.
Descriptor
()
// errorpassthroughrule.DefaultEnabled holds the default value on creation for the enabled field.
errorpassthroughrule
.
DefaultEnabled
=
errorpassthroughruleDescEnabled
.
Default
.
(
bool
)
// errorpassthroughruleDescPriority is the schema descriptor for priority field.
errorpassthroughruleDescPriority
:=
errorpassthroughruleFields
[
2
]
.
Descriptor
()
// errorpassthroughrule.DefaultPriority holds the default value on creation for the priority field.
errorpassthroughrule
.
DefaultPriority
=
errorpassthroughruleDescPriority
.
Default
.
(
int
)
// errorpassthroughruleDescMatchMode is the schema descriptor for match_mode field.
errorpassthroughruleDescMatchMode
:=
errorpassthroughruleFields
[
5
]
.
Descriptor
()
// errorpassthroughrule.DefaultMatchMode holds the default value on creation for the match_mode field.
errorpassthroughrule
.
DefaultMatchMode
=
errorpassthroughruleDescMatchMode
.
Default
.
(
string
)
// errorpassthroughrule.MatchModeValidator is a validator for the "match_mode" field. It is called by the builders before save.
errorpassthroughrule
.
MatchModeValidator
=
errorpassthroughruleDescMatchMode
.
Validators
[
0
]
.
(
func
(
string
)
error
)
// errorpassthroughruleDescPassthroughCode is the schema descriptor for passthrough_code field.
errorpassthroughruleDescPassthroughCode
:=
errorpassthroughruleFields
[
7
]
.
Descriptor
()
// errorpassthroughrule.DefaultPassthroughCode holds the default value on creation for the passthrough_code field.
errorpassthroughrule
.
DefaultPassthroughCode
=
errorpassthroughruleDescPassthroughCode
.
Default
.
(
bool
)
// errorpassthroughruleDescPassthroughBody is the schema descriptor for passthrough_body field.
errorpassthroughruleDescPassthroughBody
:=
errorpassthroughruleFields
[
9
]
.
Descriptor
()
// errorpassthroughrule.DefaultPassthroughBody holds the default value on creation for the passthrough_body field.
errorpassthroughrule
.
DefaultPassthroughBody
=
errorpassthroughruleDescPassthroughBody
.
Default
.
(
bool
)
groupMixin
:=
schema
.
Group
{}
.
Mixin
()
groupMixinHooks1
:=
groupMixin
[
1
]
.
Hooks
()
group
.
Hooks
[
0
]
=
groupMixinHooks1
[
0
]
...
...
backend/ent/schema/error_passthrough_rule.go
0 → 100644
View file @
7319122e
// Package schema 定义 Ent ORM 的数据库 schema。
package
schema
import
(
"github.com/Wei-Shaw/sub2api/ent/schema/mixins"
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// ErrorPassthroughRule 定义全局错误透传规则的 schema。
//
// 错误透传规则用于控制上游错误如何返回给客户端:
// - 匹配条件:错误码 + 关键词组合
// - 响应行为:透传原始信息 或 自定义错误信息
// - 响应状态码:可指定返回给客户端的状态码
// - 平台范围:规则适用的平台(Anthropic、OpenAI、Gemini、Antigravity)
type
ErrorPassthroughRule
struct
{
ent
.
Schema
}
// Annotations 返回 schema 的注解配置。
func
(
ErrorPassthroughRule
)
Annotations
()
[]
schema
.
Annotation
{
return
[]
schema
.
Annotation
{
entsql
.
Annotation
{
Table
:
"error_passthrough_rules"
},
}
}
// Mixin 返回该 schema 使用的混入组件。
func
(
ErrorPassthroughRule
)
Mixin
()
[]
ent
.
Mixin
{
return
[]
ent
.
Mixin
{
mixins
.
TimeMixin
{},
}
}
// Fields 定义错误透传规则实体的所有字段。
func
(
ErrorPassthroughRule
)
Fields
()
[]
ent
.
Field
{
return
[]
ent
.
Field
{
// name: 规则名称,用于在界面中标识规则
field
.
String
(
"name"
)
.
MaxLen
(
100
)
.
NotEmpty
(),
// enabled: 是否启用该规则
field
.
Bool
(
"enabled"
)
.
Default
(
true
),
// priority: 规则优先级,数值越小优先级越高
// 匹配时按优先级顺序检查,命中第一个匹配的规则
field
.
Int
(
"priority"
)
.
Default
(
0
),
// error_codes: 匹配的错误码列表(OR关系)
// 例如:[422, 400] 表示匹配 422 或 400 错误码
field
.
JSON
(
"error_codes"
,
[]
int
{})
.
Optional
()
.
SchemaType
(
map
[
string
]
string
{
dialect
.
Postgres
:
"jsonb"
}),
// keywords: 匹配的关键词列表(OR关系)
// 例如:["context limit", "model not supported"]
// 关键词匹配不区分大小写
field
.
JSON
(
"keywords"
,
[]
string
{})
.
Optional
()
.
SchemaType
(
map
[
string
]
string
{
dialect
.
Postgres
:
"jsonb"
}),
// match_mode: 匹配模式
// - "any": 错误码匹配 OR 关键词匹配(任一条件满足即可)
// - "all": 错误码匹配 AND 关键词匹配(所有条件都必须满足)
field
.
String
(
"match_mode"
)
.
MaxLen
(
10
)
.
Default
(
"any"
),
// platforms: 适用平台列表
// 例如:["anthropic", "openai", "gemini", "antigravity"]
// 空列表表示适用于所有平台
field
.
JSON
(
"platforms"
,
[]
string
{})
.
Optional
()
.
SchemaType
(
map
[
string
]
string
{
dialect
.
Postgres
:
"jsonb"
}),
// passthrough_code: 是否透传上游原始状态码
// true: 使用上游返回的状态码
// false: 使用 response_code 指定的状态码
field
.
Bool
(
"passthrough_code"
)
.
Default
(
true
),
// response_code: 自定义响应状态码
// 当 passthrough_code=false 时使用此状态码
field
.
Int
(
"response_code"
)
.
Optional
()
.
Nillable
(),
// passthrough_body: 是否透传上游原始错误信息
// true: 使用上游返回的错误信息
// false: 使用 custom_message 指定的错误信息
field
.
Bool
(
"passthrough_body"
)
.
Default
(
true
),
// custom_message: 自定义错误信息
// 当 passthrough_body=false 时使用此错误信息
field
.
Text
(
"custom_message"
)
.
Optional
()
.
Nillable
(),
// description: 规则描述,用于说明规则的用途
field
.
Text
(
"description"
)
.
Optional
()
.
Nillable
(),
}
}
// Indexes 定义数据库索引,优化查询性能。
func
(
ErrorPassthroughRule
)
Indexes
()
[]
ent
.
Index
{
return
[]
ent
.
Index
{
index
.
Fields
(
"enabled"
),
// 筛选启用的规则
index
.
Fields
(
"priority"
),
// 按优先级排序
}
}
backend/ent/tx.go
View file @
7319122e
...
...
@@ -24,6 +24,8 @@ type Tx struct {
Announcement
*
AnnouncementClient
// AnnouncementRead is the client for interacting with the AnnouncementRead builders.
AnnouncementRead
*
AnnouncementReadClient
// ErrorPassthroughRule is the client for interacting with the ErrorPassthroughRule builders.
ErrorPassthroughRule
*
ErrorPassthroughRuleClient
// Group is the client for interacting with the Group builders.
Group
*
GroupClient
// PromoCode is the client for interacting with the PromoCode builders.
...
...
@@ -186,6 +188,7 @@ func (tx *Tx) init() {
tx
.
AccountGroup
=
NewAccountGroupClient
(
tx
.
config
)
tx
.
Announcement
=
NewAnnouncementClient
(
tx
.
config
)
tx
.
AnnouncementRead
=
NewAnnouncementReadClient
(
tx
.
config
)
tx
.
ErrorPassthroughRule
=
NewErrorPassthroughRuleClient
(
tx
.
config
)
tx
.
Group
=
NewGroupClient
(
tx
.
config
)
tx
.
PromoCode
=
NewPromoCodeClient
(
tx
.
config
)
tx
.
PromoCodeUsage
=
NewPromoCodeUsageClient
(
tx
.
config
)
...
...
backend/go.mod
View file @
7319122e
module github.com/Wei-Shaw/sub2api
go 1.25.
6
go 1.25.
7
require (
entgo.io/ent v0.14.5
...
...
backend/internal/handler/admin/error_passthrough_handler.go
0 → 100644
View file @
7319122e
package
admin
import
(
"strconv"
"github.com/Wei-Shaw/sub2api/internal/model"
"github.com/Wei-Shaw/sub2api/internal/pkg/response"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/gin-gonic/gin"
)
// ErrorPassthroughHandler 处理错误透传规则的 HTTP 请求
type
ErrorPassthroughHandler
struct
{
service
*
service
.
ErrorPassthroughService
}
// NewErrorPassthroughHandler 创建错误透传规则处理器
func
NewErrorPassthroughHandler
(
service
*
service
.
ErrorPassthroughService
)
*
ErrorPassthroughHandler
{
return
&
ErrorPassthroughHandler
{
service
:
service
}
}
// CreateErrorPassthroughRuleRequest 创建规则请求
type
CreateErrorPassthroughRuleRequest
struct
{
Name
string
`json:"name" binding:"required"`
Enabled
*
bool
`json:"enabled"`
Priority
int
`json:"priority"`
ErrorCodes
[]
int
`json:"error_codes"`
Keywords
[]
string
`json:"keywords"`
MatchMode
string
`json:"match_mode"`
Platforms
[]
string
`json:"platforms"`
PassthroughCode
*
bool
`json:"passthrough_code"`
ResponseCode
*
int
`json:"response_code"`
PassthroughBody
*
bool
`json:"passthrough_body"`
CustomMessage
*
string
`json:"custom_message"`
Description
*
string
`json:"description"`
}
// UpdateErrorPassthroughRuleRequest 更新规则请求(部分更新,所有字段可选)
type
UpdateErrorPassthroughRuleRequest
struct
{
Name
*
string
`json:"name"`
Enabled
*
bool
`json:"enabled"`
Priority
*
int
`json:"priority"`
ErrorCodes
[]
int
`json:"error_codes"`
Keywords
[]
string
`json:"keywords"`
MatchMode
*
string
`json:"match_mode"`
Platforms
[]
string
`json:"platforms"`
PassthroughCode
*
bool
`json:"passthrough_code"`
ResponseCode
*
int
`json:"response_code"`
PassthroughBody
*
bool
`json:"passthrough_body"`
CustomMessage
*
string
`json:"custom_message"`
Description
*
string
`json:"description"`
}
// List 获取所有规则
// GET /api/v1/admin/error-passthrough-rules
func
(
h
*
ErrorPassthroughHandler
)
List
(
c
*
gin
.
Context
)
{
rules
,
err
:=
h
.
service
.
List
(
c
.
Request
.
Context
())
if
err
!=
nil
{
response
.
ErrorFrom
(
c
,
err
)
return
}
response
.
Success
(
c
,
rules
)
}
// GetByID 根据 ID 获取规则
// GET /api/v1/admin/error-passthrough-rules/:id
func
(
h
*
ErrorPassthroughHandler
)
GetByID
(
c
*
gin
.
Context
)
{
id
,
err
:=
strconv
.
ParseInt
(
c
.
Param
(
"id"
),
10
,
64
)
if
err
!=
nil
{
response
.
BadRequest
(
c
,
"Invalid rule ID"
)
return
}
rule
,
err
:=
h
.
service
.
GetByID
(
c
.
Request
.
Context
(),
id
)
if
err
!=
nil
{
response
.
ErrorFrom
(
c
,
err
)
return
}
if
rule
==
nil
{
response
.
NotFound
(
c
,
"Rule not found"
)
return
}
response
.
Success
(
c
,
rule
)
}
// Create 创建规则
// POST /api/v1/admin/error-passthrough-rules
func
(
h
*
ErrorPassthroughHandler
)
Create
(
c
*
gin
.
Context
)
{
var
req
CreateErrorPassthroughRuleRequest
if
err
:=
c
.
ShouldBindJSON
(
&
req
);
err
!=
nil
{
response
.
BadRequest
(
c
,
"Invalid request: "
+
err
.
Error
())
return
}
rule
:=
&
model
.
ErrorPassthroughRule
{
Name
:
req
.
Name
,
Priority
:
req
.
Priority
,
ErrorCodes
:
req
.
ErrorCodes
,
Keywords
:
req
.
Keywords
,
Platforms
:
req
.
Platforms
,
}
// 设置默认值
if
req
.
Enabled
!=
nil
{
rule
.
Enabled
=
*
req
.
Enabled
}
else
{
rule
.
Enabled
=
true
}
if
req
.
MatchMode
!=
""
{
rule
.
MatchMode
=
req
.
MatchMode
}
else
{
rule
.
MatchMode
=
model
.
MatchModeAny
}
if
req
.
PassthroughCode
!=
nil
{
rule
.
PassthroughCode
=
*
req
.
PassthroughCode
}
else
{
rule
.
PassthroughCode
=
true
}
if
req
.
PassthroughBody
!=
nil
{
rule
.
PassthroughBody
=
*
req
.
PassthroughBody
}
else
{
rule
.
PassthroughBody
=
true
}
rule
.
ResponseCode
=
req
.
ResponseCode
rule
.
CustomMessage
=
req
.
CustomMessage
rule
.
Description
=
req
.
Description
// 确保切片不为 nil
if
rule
.
ErrorCodes
==
nil
{
rule
.
ErrorCodes
=
[]
int
{}
}
if
rule
.
Keywords
==
nil
{
rule
.
Keywords
=
[]
string
{}
}
if
rule
.
Platforms
==
nil
{
rule
.
Platforms
=
[]
string
{}
}
created
,
err
:=
h
.
service
.
Create
(
c
.
Request
.
Context
(),
rule
)
if
err
!=
nil
{
if
_
,
ok
:=
err
.
(
*
model
.
ValidationError
);
ok
{
response
.
BadRequest
(
c
,
err
.
Error
())
return
}
response
.
ErrorFrom
(
c
,
err
)
return
}
response
.
Success
(
c
,
created
)
}
// Update 更新规则(支持部分更新)
// PUT /api/v1/admin/error-passthrough-rules/:id
func
(
h
*
ErrorPassthroughHandler
)
Update
(
c
*
gin
.
Context
)
{
id
,
err
:=
strconv
.
ParseInt
(
c
.
Param
(
"id"
),
10
,
64
)
if
err
!=
nil
{
response
.
BadRequest
(
c
,
"Invalid rule ID"
)
return
}
var
req
UpdateErrorPassthroughRuleRequest
if
err
:=
c
.
ShouldBindJSON
(
&
req
);
err
!=
nil
{
response
.
BadRequest
(
c
,
"Invalid request: "
+
err
.
Error
())
return
}
// 先获取现有规则
existing
,
err
:=
h
.
service
.
GetByID
(
c
.
Request
.
Context
(),
id
)
if
err
!=
nil
{
response
.
ErrorFrom
(
c
,
err
)
return
}
if
existing
==
nil
{
response
.
NotFound
(
c
,
"Rule not found"
)
return
}
// 部分更新:只更新请求中提供的字段
rule
:=
&
model
.
ErrorPassthroughRule
{
ID
:
id
,
Name
:
existing
.
Name
,
Enabled
:
existing
.
Enabled
,
Priority
:
existing
.
Priority
,
ErrorCodes
:
existing
.
ErrorCodes
,
Keywords
:
existing
.
Keywords
,
MatchMode
:
existing
.
MatchMode
,
Platforms
:
existing
.
Platforms
,
PassthroughCode
:
existing
.
PassthroughCode
,
ResponseCode
:
existing
.
ResponseCode
,
PassthroughBody
:
existing
.
PassthroughBody
,
CustomMessage
:
existing
.
CustomMessage
,
Description
:
existing
.
Description
,
}
// 应用请求中提供的更新
if
req
.
Name
!=
nil
{
rule
.
Name
=
*
req
.
Name
}
if
req
.
Enabled
!=
nil
{
rule
.
Enabled
=
*
req
.
Enabled
}
if
req
.
Priority
!=
nil
{
rule
.
Priority
=
*
req
.
Priority
}
if
req
.
ErrorCodes
!=
nil
{
rule
.
ErrorCodes
=
req
.
ErrorCodes
}
if
req
.
Keywords
!=
nil
{
rule
.
Keywords
=
req
.
Keywords
}
if
req
.
MatchMode
!=
nil
{
rule
.
MatchMode
=
*
req
.
MatchMode
}
if
req
.
Platforms
!=
nil
{
rule
.
Platforms
=
req
.
Platforms
}
if
req
.
PassthroughCode
!=
nil
{
rule
.
PassthroughCode
=
*
req
.
PassthroughCode
}
if
req
.
ResponseCode
!=
nil
{
rule
.
ResponseCode
=
req
.
ResponseCode
}
if
req
.
PassthroughBody
!=
nil
{
rule
.
PassthroughBody
=
*
req
.
PassthroughBody
}
if
req
.
CustomMessage
!=
nil
{
rule
.
CustomMessage
=
req
.
CustomMessage
}
if
req
.
Description
!=
nil
{
rule
.
Description
=
req
.
Description
}
// 确保切片不为 nil
if
rule
.
ErrorCodes
==
nil
{
rule
.
ErrorCodes
=
[]
int
{}
}
if
rule
.
Keywords
==
nil
{
rule
.
Keywords
=
[]
string
{}
}
if
rule
.
Platforms
==
nil
{
rule
.
Platforms
=
[]
string
{}
}
updated
,
err
:=
h
.
service
.
Update
(
c
.
Request
.
Context
(),
rule
)
if
err
!=
nil
{
if
_
,
ok
:=
err
.
(
*
model
.
ValidationError
);
ok
{
response
.
BadRequest
(
c
,
err
.
Error
())
return
}
response
.
ErrorFrom
(
c
,
err
)
return
}
response
.
Success
(
c
,
updated
)
}
// Delete 删除规则
// DELETE /api/v1/admin/error-passthrough-rules/:id
func
(
h
*
ErrorPassthroughHandler
)
Delete
(
c
*
gin
.
Context
)
{
id
,
err
:=
strconv
.
ParseInt
(
c
.
Param
(
"id"
),
10
,
64
)
if
err
!=
nil
{
response
.
BadRequest
(
c
,
"Invalid rule ID"
)
return
}
if
err
:=
h
.
service
.
Delete
(
c
.
Request
.
Context
(),
id
);
err
!=
nil
{
response
.
ErrorFrom
(
c
,
err
)
return
}
response
.
Success
(
c
,
gin
.
H
{
"message"
:
"Rule deleted successfully"
})
}
backend/internal/handler/admin/user_handler.go
View file @
7319122e
...
...
@@ -45,6 +45,9 @@ type UpdateUserRequest struct {
Concurrency
*
int
`json:"concurrency"`
Status
string
`json:"status" binding:"omitempty,oneof=active disabled"`
AllowedGroups
*
[]
int64
`json:"allowed_groups"`
// GroupRates 用户专属分组倍率配置
// map[groupID]*rate,nil 表示删除该分组的专属倍率
GroupRates
map
[
int64
]
*
float64
`json:"group_rates"`
}
// UpdateBalanceRequest represents balance update request
...
...
@@ -183,6 +186,7 @@ func (h *UserHandler) Update(c *gin.Context) {
Concurrency
:
req
.
Concurrency
,
Status
:
req
.
Status
,
AllowedGroups
:
req
.
AllowedGroups
,
GroupRates
:
req
.
GroupRates
,
})
if
err
!=
nil
{
response
.
ErrorFrom
(
c
,
err
)
...
...
backend/internal/handler/api_key_handler.go
View file @
7319122e
...
...
@@ -243,3 +243,21 @@ func (h *APIKeyHandler) GetAvailableGroups(c *gin.Context) {
}
response
.
Success
(
c
,
out
)
}
// GetUserGroupRates 获取当前用户的专属分组倍率配置
// GET /api/v1/groups/rates
func
(
h
*
APIKeyHandler
)
GetUserGroupRates
(
c
*
gin
.
Context
)
{
subject
,
ok
:=
middleware2
.
GetAuthSubjectFromContext
(
c
)
if
!
ok
{
response
.
Unauthorized
(
c
,
"User not authenticated"
)
return
}
rates
,
err
:=
h
.
apiKeyService
.
GetUserGroupRates
(
c
.
Request
.
Context
(),
subject
.
UserID
)
if
err
!=
nil
{
response
.
ErrorFrom
(
c
,
err
)
return
}
response
.
Success
(
c
,
rates
)
}
backend/internal/handler/dto/mappers.go
View file @
7319122e
...
...
@@ -60,6 +60,7 @@ func UserFromServiceAdmin(u *service.User) *AdminUser {
return
&
AdminUser
{
User
:
*
base
,
Notes
:
u
.
Notes
,
GroupRates
:
u
.
GroupRates
,
}
}
...
...
backend/internal/handler/dto/types.go
View file @
7319122e
...
...
@@ -29,6 +29,9 @@ type AdminUser struct {
User
Notes
string
`json:"notes"`
// GroupRates 用户专属分组倍率配置
// map[groupID]rateMultiplier
GroupRates
map
[
int64
]
float64
`json:"group_rates,omitempty"`
}
type
APIKey
struct
{
...
...
backend/internal/handler/gateway_handler.go
View file @
7319122e
...
...
@@ -33,6 +33,7 @@ type GatewayHandler struct {
billingCacheService
*
service
.
BillingCacheService
usageService
*
service
.
UsageService
apiKeyService
*
service
.
APIKeyService
errorPassthroughService
*
service
.
ErrorPassthroughService
concurrencyHelper
*
ConcurrencyHelper
maxAccountSwitches
int
maxAccountSwitchesGemini
int
...
...
@@ -48,6 +49,7 @@ func NewGatewayHandler(
billingCacheService
*
service
.
BillingCacheService
,
usageService
*
service
.
UsageService
,
apiKeyService
*
service
.
APIKeyService
,
errorPassthroughService
*
service
.
ErrorPassthroughService
,
cfg
*
config
.
Config
,
)
*
GatewayHandler
{
pingInterval
:=
time
.
Duration
(
0
)
...
...
@@ -70,6 +72,7 @@ func NewGatewayHandler(
billingCacheService
:
billingCacheService
,
usageService
:
usageService
,
apiKeyService
:
apiKeyService
,
errorPassthroughService
:
errorPassthroughService
,
concurrencyHelper
:
NewConcurrencyHelper
(
concurrencyService
,
SSEPingFormatClaude
,
pingInterval
),
maxAccountSwitches
:
maxAccountSwitches
,
maxAccountSwitchesGemini
:
maxAccountSwitchesGemini
,
...
...
@@ -201,7 +204,7 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
maxAccountSwitches
:=
h
.
maxAccountSwitchesGemini
switchCount
:=
0
failedAccountIDs
:=
make
(
map
[
int64
]
struct
{})
lastFailover
Status
:=
0
var
lastFailover
Err
*
service
.
UpstreamFailoverError
for
{
selection
,
err
:=
h
.
gatewayService
.
SelectAccountWithLoadAwareness
(
c
.
Request
.
Context
(),
apiKey
.
GroupID
,
sessionKey
,
reqModel
,
failedAccountIDs
,
""
)
// Gemini 不使用会话限制
...
...
@@ -210,7 +213,11 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
h
.
handleStreamingAwareError
(
c
,
http
.
StatusServiceUnavailable
,
"api_error"
,
"No available accounts: "
+
err
.
Error
(),
streamStarted
)
return
}
h
.
handleFailoverExhausted
(
c
,
lastFailoverStatus
,
streamStarted
)
if
lastFailoverErr
!=
nil
{
h
.
handleFailoverExhausted
(
c
,
lastFailoverErr
,
service
.
PlatformGemini
,
streamStarted
)
}
else
{
h
.
handleFailoverExhaustedSimple
(
c
,
502
,
streamStarted
)
}
return
}
account
:=
selection
.
Account
...
...
@@ -301,9 +308,9 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
var
failoverErr
*
service
.
UpstreamFailoverError
if
errors
.
As
(
err
,
&
failoverErr
)
{
failedAccountIDs
[
account
.
ID
]
=
struct
{}{}
lastFailover
Status
=
failoverErr
.
StatusCode
lastFailover
Err
=
failoverErr
if
switchCount
>=
maxAccountSwitches
{
h
.
handleFailoverExhausted
(
c
,
lastF
ailover
Status
,
streamStarted
)
h
.
handleFailoverExhausted
(
c
,
f
ailover
Err
,
service
.
PlatformGemini
,
streamStarted
)
return
}
switchCount
++
...
...
@@ -352,7 +359,7 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
maxAccountSwitches
:=
h
.
maxAccountSwitches
switchCount
:=
0
failedAccountIDs
:=
make
(
map
[
int64
]
struct
{})
lastFailover
Status
:=
0
var
lastFailover
Err
*
service
.
UpstreamFailoverError
retryWithFallback
:=
false
for
{
...
...
@@ -363,7 +370,11 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
h
.
handleStreamingAwareError
(
c
,
http
.
StatusServiceUnavailable
,
"api_error"
,
"No available accounts: "
+
err
.
Error
(),
streamStarted
)
return
}
h
.
handleFailoverExhausted
(
c
,
lastFailoverStatus
,
streamStarted
)
if
lastFailoverErr
!=
nil
{
h
.
handleFailoverExhausted
(
c
,
lastFailoverErr
,
platform
,
streamStarted
)
}
else
{
h
.
handleFailoverExhaustedSimple
(
c
,
502
,
streamStarted
)
}
return
}
account
:=
selection
.
Account
...
...
@@ -487,9 +498,9 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
var
failoverErr
*
service
.
UpstreamFailoverError
if
errors
.
As
(
err
,
&
failoverErr
)
{
failedAccountIDs
[
account
.
ID
]
=
struct
{}{}
lastFailover
Status
=
failoverErr
.
StatusCode
lastFailover
Err
=
failoverErr
if
switchCount
>=
maxAccountSwitches
{
h
.
handleFailoverExhausted
(
c
,
lastF
ailover
Status
,
streamStarted
)
h
.
handleFailoverExhausted
(
c
,
f
ailover
Err
,
account
.
Platform
,
streamStarted
)
return
}
switchCount
++
...
...
@@ -755,7 +766,37 @@ func (h *GatewayHandler) handleConcurrencyError(c *gin.Context, err error, slotT
fmt
.
Sprintf
(
"Concurrency limit exceeded for %s, please retry later"
,
slotType
),
streamStarted
)
}
func
(
h
*
GatewayHandler
)
handleFailoverExhausted
(
c
*
gin
.
Context
,
statusCode
int
,
streamStarted
bool
)
{
func
(
h
*
GatewayHandler
)
handleFailoverExhausted
(
c
*
gin
.
Context
,
failoverErr
*
service
.
UpstreamFailoverError
,
platform
string
,
streamStarted
bool
)
{
statusCode
:=
failoverErr
.
StatusCode
responseBody
:=
failoverErr
.
ResponseBody
// 先检查透传规则
if
h
.
errorPassthroughService
!=
nil
&&
len
(
responseBody
)
>
0
{
if
rule
:=
h
.
errorPassthroughService
.
MatchRule
(
platform
,
statusCode
,
responseBody
);
rule
!=
nil
{
// 确定响应状态码
respCode
:=
statusCode
if
!
rule
.
PassthroughCode
&&
rule
.
ResponseCode
!=
nil
{
respCode
=
*
rule
.
ResponseCode
}
// 确定响应消息
msg
:=
service
.
ExtractUpstreamErrorMessage
(
responseBody
)
if
!
rule
.
PassthroughBody
&&
rule
.
CustomMessage
!=
nil
{
msg
=
*
rule
.
CustomMessage
}
h
.
handleStreamingAwareError
(
c
,
respCode
,
"upstream_error"
,
msg
,
streamStarted
)
return
}
}
// 使用默认的错误映射
status
,
errType
,
errMsg
:=
h
.
mapUpstreamError
(
statusCode
)
h
.
handleStreamingAwareError
(
c
,
status
,
errType
,
errMsg
,
streamStarted
)
}
// handleFailoverExhaustedSimple 简化版本,用于没有响应体的情况
func
(
h
*
GatewayHandler
)
handleFailoverExhaustedSimple
(
c
*
gin
.
Context
,
statusCode
int
,
streamStarted
bool
)
{
status
,
errType
,
errMsg
:=
h
.
mapUpstreamError
(
statusCode
)
h
.
handleStreamingAwareError
(
c
,
status
,
errType
,
errMsg
,
streamStarted
)
}
...
...
backend/internal/handler/gemini_v1beta_handler.go
View file @
7319122e
...
...
@@ -253,7 +253,7 @@ func (h *GatewayHandler) GeminiV1BetaModels(c *gin.Context) {
maxAccountSwitches
:=
h
.
maxAccountSwitchesGemini
switchCount
:=
0
failedAccountIDs
:=
make
(
map
[
int64
]
struct
{})
lastFailover
Status
:=
0
var
lastFailover
Err
*
service
.
UpstreamFailoverError
for
{
selection
,
err
:=
h
.
gatewayService
.
SelectAccountWithLoadAwareness
(
c
.
Request
.
Context
(),
apiKey
.
GroupID
,
sessionKey
,
modelName
,
failedAccountIDs
,
""
)
// Gemini 不使用会话限制
...
...
@@ -262,7 +262,7 @@ func (h *GatewayHandler) GeminiV1BetaModels(c *gin.Context) {
googleError
(
c
,
http
.
StatusServiceUnavailable
,
"No available Gemini accounts: "
+
err
.
Error
())
return
}
handleGeminiFailoverExhausted
(
c
,
lastFailover
Status
)
h
.
handleGeminiFailoverExhausted
(
c
,
lastFailover
Err
)
return
}
account
:=
selection
.
Account
...
...
@@ -353,11 +353,11 @@ func (h *GatewayHandler) GeminiV1BetaModels(c *gin.Context) {
if
errors
.
As
(
err
,
&
failoverErr
)
{
failedAccountIDs
[
account
.
ID
]
=
struct
{}{}
if
switchCount
>=
maxAccountSwitches
{
lastFailover
Status
=
failoverErr
.
StatusCode
handleGeminiFailoverExhausted
(
c
,
lastFailover
Status
)
lastFailover
Err
=
failoverErr
h
.
handleGeminiFailoverExhausted
(
c
,
lastFailover
Err
)
return
}
lastFailover
Status
=
failoverErr
.
StatusCode
lastFailover
Err
=
failoverErr
switchCount
++
log
.
Printf
(
"Gemini account %d: upstream error %d, switching account %d/%d"
,
account
.
ID
,
failoverErr
.
StatusCode
,
switchCount
,
maxAccountSwitches
)
continue
...
...
@@ -414,7 +414,36 @@ func parseGeminiModelAction(rest string) (model string, action string, err error
return
""
,
""
,
&
pathParseError
{
"invalid model action path"
}
}
func
handleGeminiFailoverExhausted
(
c
*
gin
.
Context
,
statusCode
int
)
{
func
(
h
*
GatewayHandler
)
handleGeminiFailoverExhausted
(
c
*
gin
.
Context
,
failoverErr
*
service
.
UpstreamFailoverError
)
{
if
failoverErr
==
nil
{
googleError
(
c
,
http
.
StatusBadGateway
,
"Upstream request failed"
)
return
}
statusCode
:=
failoverErr
.
StatusCode
responseBody
:=
failoverErr
.
ResponseBody
// 先检查透传规则
if
h
.
errorPassthroughService
!=
nil
&&
len
(
responseBody
)
>
0
{
if
rule
:=
h
.
errorPassthroughService
.
MatchRule
(
service
.
PlatformGemini
,
statusCode
,
responseBody
);
rule
!=
nil
{
// 确定响应状态码
respCode
:=
statusCode
if
!
rule
.
PassthroughCode
&&
rule
.
ResponseCode
!=
nil
{
respCode
=
*
rule
.
ResponseCode
}
// 确定响应消息
msg
:=
service
.
ExtractUpstreamErrorMessage
(
responseBody
)
if
!
rule
.
PassthroughBody
&&
rule
.
CustomMessage
!=
nil
{
msg
=
*
rule
.
CustomMessage
}
googleError
(
c
,
respCode
,
msg
)
return
}
}
// 使用默认的错误映射
status
,
message
:=
mapGeminiUpstreamError
(
statusCode
)
googleError
(
c
,
status
,
message
)
}
...
...
backend/internal/handler/handler.go
View file @
7319122e
...
...
@@ -24,6 +24,7 @@ type AdminHandlers struct {
Subscription
*
admin
.
SubscriptionHandler
Usage
*
admin
.
UsageHandler
UserAttribute
*
admin
.
UserAttributeHandler
ErrorPassthrough
*
admin
.
ErrorPassthroughHandler
}
// Handlers contains all HTTP handlers
...
...
backend/internal/handler/openai_gateway_handler.go
View file @
7319122e
...
...
@@ -25,6 +25,7 @@ type OpenAIGatewayHandler struct {
gatewayService
*
service
.
OpenAIGatewayService
billingCacheService
*
service
.
BillingCacheService
apiKeyService
*
service
.
APIKeyService
errorPassthroughService
*
service
.
ErrorPassthroughService
concurrencyHelper
*
ConcurrencyHelper
maxAccountSwitches
int
}
...
...
@@ -35,6 +36,7 @@ func NewOpenAIGatewayHandler(
concurrencyService
*
service
.
ConcurrencyService
,
billingCacheService
*
service
.
BillingCacheService
,
apiKeyService
*
service
.
APIKeyService
,
errorPassthroughService
*
service
.
ErrorPassthroughService
,
cfg
*
config
.
Config
,
)
*
OpenAIGatewayHandler
{
pingInterval
:=
time
.
Duration
(
0
)
...
...
@@ -49,6 +51,7 @@ func NewOpenAIGatewayHandler(
gatewayService
:
gatewayService
,
billingCacheService
:
billingCacheService
,
apiKeyService
:
apiKeyService
,
errorPassthroughService
:
errorPassthroughService
,
concurrencyHelper
:
NewConcurrencyHelper
(
concurrencyService
,
SSEPingFormatComment
,
pingInterval
),
maxAccountSwitches
:
maxAccountSwitches
,
}
...
...
@@ -201,7 +204,7 @@ func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
maxAccountSwitches
:=
h
.
maxAccountSwitches
switchCount
:=
0
failedAccountIDs
:=
make
(
map
[
int64
]
struct
{})
lastFailover
Status
:=
0
var
lastFailover
Err
*
service
.
UpstreamFailoverError
for
{
// Select account supporting the requested model
...
...
@@ -213,7 +216,11 @@ func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
h
.
handleStreamingAwareError
(
c
,
http
.
StatusServiceUnavailable
,
"api_error"
,
"No available accounts: "
+
err
.
Error
(),
streamStarted
)
return
}
h
.
handleFailoverExhausted
(
c
,
lastFailoverStatus
,
streamStarted
)
if
lastFailoverErr
!=
nil
{
h
.
handleFailoverExhausted
(
c
,
lastFailoverErr
,
streamStarted
)
}
else
{
h
.
handleFailoverExhaustedSimple
(
c
,
502
,
streamStarted
)
}
return
}
account
:=
selection
.
Account
...
...
@@ -278,12 +285,11 @@ func (h *OpenAIGatewayHandler) Responses(c *gin.Context) {
var
failoverErr
*
service
.
UpstreamFailoverError
if
errors
.
As
(
err
,
&
failoverErr
)
{
failedAccountIDs
[
account
.
ID
]
=
struct
{}{}
lastFailoverErr
=
failoverErr
if
switchCount
>=
maxAccountSwitches
{
lastFailoverStatus
=
failoverErr
.
StatusCode
h
.
handleFailoverExhausted
(
c
,
lastFailoverStatus
,
streamStarted
)
h
.
handleFailoverExhausted
(
c
,
failoverErr
,
streamStarted
)
return
}
lastFailoverStatus
=
failoverErr
.
StatusCode
switchCount
++
log
.
Printf
(
"Account %d: upstream error %d, switching account %d/%d"
,
account
.
ID
,
failoverErr
.
StatusCode
,
switchCount
,
maxAccountSwitches
)
continue
...
...
@@ -324,7 +330,37 @@ func (h *OpenAIGatewayHandler) handleConcurrencyError(c *gin.Context, err error,
fmt
.
Sprintf
(
"Concurrency limit exceeded for %s, please retry later"
,
slotType
),
streamStarted
)
}
func
(
h
*
OpenAIGatewayHandler
)
handleFailoverExhausted
(
c
*
gin
.
Context
,
statusCode
int
,
streamStarted
bool
)
{
func
(
h
*
OpenAIGatewayHandler
)
handleFailoverExhausted
(
c
*
gin
.
Context
,
failoverErr
*
service
.
UpstreamFailoverError
,
streamStarted
bool
)
{
statusCode
:=
failoverErr
.
StatusCode
responseBody
:=
failoverErr
.
ResponseBody
// 先检查透传规则
if
h
.
errorPassthroughService
!=
nil
&&
len
(
responseBody
)
>
0
{
if
rule
:=
h
.
errorPassthroughService
.
MatchRule
(
"openai"
,
statusCode
,
responseBody
);
rule
!=
nil
{
// 确定响应状态码
respCode
:=
statusCode
if
!
rule
.
PassthroughCode
&&
rule
.
ResponseCode
!=
nil
{
respCode
=
*
rule
.
ResponseCode
}
// 确定响应消息
msg
:=
service
.
ExtractUpstreamErrorMessage
(
responseBody
)
if
!
rule
.
PassthroughBody
&&
rule
.
CustomMessage
!=
nil
{
msg
=
*
rule
.
CustomMessage
}
h
.
handleStreamingAwareError
(
c
,
respCode
,
"upstream_error"
,
msg
,
streamStarted
)
return
}
}
// 使用默认的错误映射
status
,
errType
,
errMsg
:=
h
.
mapUpstreamError
(
statusCode
)
h
.
handleStreamingAwareError
(
c
,
status
,
errType
,
errMsg
,
streamStarted
)
}
// handleFailoverExhaustedSimple 简化版本,用于没有响应体的情况
func
(
h
*
OpenAIGatewayHandler
)
handleFailoverExhaustedSimple
(
c
*
gin
.
Context
,
statusCode
int
,
streamStarted
bool
)
{
status
,
errType
,
errMsg
:=
h
.
mapUpstreamError
(
statusCode
)
h
.
handleStreamingAwareError
(
c
,
status
,
errType
,
errMsg
,
streamStarted
)
}
...
...
backend/internal/handler/wire.go
View file @
7319122e
...
...
@@ -27,6 +27,7 @@ func ProvideAdminHandlers(
subscriptionHandler
*
admin
.
SubscriptionHandler
,
usageHandler
*
admin
.
UsageHandler
,
userAttributeHandler
*
admin
.
UserAttributeHandler
,
errorPassthroughHandler
*
admin
.
ErrorPassthroughHandler
,
)
*
AdminHandlers
{
return
&
AdminHandlers
{
Dashboard
:
dashboardHandler
,
...
...
@@ -47,6 +48,7 @@ func ProvideAdminHandlers(
Subscription
:
subscriptionHandler
,
Usage
:
usageHandler
,
UserAttribute
:
userAttributeHandler
,
ErrorPassthrough
:
errorPassthroughHandler
,
}
}
...
...
@@ -125,6 +127,7 @@ var ProviderSet = wire.NewSet(
admin
.
NewSubscriptionHandler
,
admin
.
NewUsageHandler
,
admin
.
NewUserAttributeHandler
,
admin
.
NewErrorPassthroughHandler
,
// AdminHandlers and Handlers constructors
ProvideAdminHandlers
,
...
...
backend/internal/model/error_passthrough_rule.go
0 → 100644
View file @
7319122e
// Package model 定义服务层使用的数据模型。
package
model
import
"time"
// ErrorPassthroughRule 全局错误透传规则
// 用于控制上游错误如何返回给客户端
type
ErrorPassthroughRule
struct
{
ID
int64
`json:"id"`
Name
string
`json:"name"`
// 规则名称
Enabled
bool
`json:"enabled"`
// 是否启用
Priority
int
`json:"priority"`
// 优先级(数字越小优先级越高)
ErrorCodes
[]
int
`json:"error_codes"`
// 匹配的错误码列表(OR关系)
Keywords
[]
string
`json:"keywords"`
// 匹配的关键词列表(OR关系)
MatchMode
string
`json:"match_mode"`
// "any"(任一条件) 或 "all"(所有条件)
Platforms
[]
string
`json:"platforms"`
// 适用平台列表
PassthroughCode
bool
`json:"passthrough_code"`
// 是否透传原始状态码
ResponseCode
*
int
`json:"response_code"`
// 自定义状态码(passthrough_code=false 时使用)
PassthroughBody
bool
`json:"passthrough_body"`
// 是否透传原始错误信息
CustomMessage
*
string
`json:"custom_message"`
// 自定义错误信息(passthrough_body=false 时使用)
Description
*
string
`json:"description"`
// 规则描述
CreatedAt
time
.
Time
`json:"created_at"`
UpdatedAt
time
.
Time
`json:"updated_at"`
}
// MatchModeAny 表示任一条件匹配即可
const
MatchModeAny
=
"any"
// MatchModeAll 表示所有条件都必须匹配
const
MatchModeAll
=
"all"
// 支持的平台常量
const
(
PlatformAnthropic
=
"anthropic"
PlatformOpenAI
=
"openai"
PlatformGemini
=
"gemini"
PlatformAntigravity
=
"antigravity"
)
// AllPlatforms 返回所有支持的平台列表
func
AllPlatforms
()
[]
string
{
return
[]
string
{
PlatformAnthropic
,
PlatformOpenAI
,
PlatformGemini
,
PlatformAntigravity
}
}
// Validate 验证规则配置的有效性
func
(
r
*
ErrorPassthroughRule
)
Validate
()
error
{
if
r
.
Name
==
""
{
return
&
ValidationError
{
Field
:
"name"
,
Message
:
"name is required"
}
}
if
r
.
MatchMode
!=
MatchModeAny
&&
r
.
MatchMode
!=
MatchModeAll
{
return
&
ValidationError
{
Field
:
"match_mode"
,
Message
:
"match_mode must be 'any' or 'all'"
}
}
// 至少需要配置一个匹配条件(错误码或关键词)
if
len
(
r
.
ErrorCodes
)
==
0
&&
len
(
r
.
Keywords
)
==
0
{
return
&
ValidationError
{
Field
:
"conditions"
,
Message
:
"at least one error_code or keyword is required"
}
}
if
!
r
.
PassthroughCode
&&
(
r
.
ResponseCode
==
nil
||
*
r
.
ResponseCode
<=
0
)
{
return
&
ValidationError
{
Field
:
"response_code"
,
Message
:
"response_code is required when passthrough_code is false"
}
}
if
!
r
.
PassthroughBody
&&
(
r
.
CustomMessage
==
nil
||
*
r
.
CustomMessage
==
""
)
{
return
&
ValidationError
{
Field
:
"custom_message"
,
Message
:
"custom_message is required when passthrough_body is false"
}
}
return
nil
}
// ValidationError 表示验证错误
type
ValidationError
struct
{
Field
string
Message
string
}
func
(
e
*
ValidationError
)
Error
()
string
{
return
e
.
Field
+
": "
+
e
.
Message
}
backend/internal/pkg/claude/constants.go
View file @
7319122e
...
...
@@ -71,6 +71,12 @@ var DefaultModels = []Model{
DisplayName
:
"Claude Opus 4.5"
,
CreatedAt
:
"2025-11-01T00:00:00Z"
,
},
{
ID
:
"claude-opus-4-6"
,
Type
:
"model"
,
DisplayName
:
"Claude Opus 4.6"
,
CreatedAt
:
"2026-02-06T00:00:00Z"
,
},
{
ID
:
"claude-sonnet-4-5-20250929"
,
Type
:
"model"
,
...
...
Prev
1
2
3
4
5
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment