From 51c7654b03f7169a2985dcc0ed47b95d1beb0280 Mon Sep 17 00:00:00 2001 From: thotenn Date: Thu, 9 Jul 2026 23:41:41 -0300 Subject: [PATCH] feat(media): deferred image compression subsystem (APP-101) Adds a media post-processing pipeline that compresses images off the upload path, in batches, to save storage: - New media_process_task ent table (media_type discriminator; image now, video later) + inventory client with idempotent Enqueue/ListPending. - CompleteUpload enqueues the primary entity when the global switch and the owner's auto_compress_images opt-in are on and mime/size gates pass. - A configurable cron enqueues a bounded batch onto a dedicated MediaProcessQueue (default 1 worker) that compresses each blob via vips (default) or ffmpeg using EntitySource, then writes the result back as a new version through manager.Update (quota handled by StorageDiff). A context guard prevents the write-back from re-enqueueing itself. - BackendVersion 4.14.1 -> 4.14.2 to fire the migration; new default settings are idempotently backfilled. BusyWorkers/metrics expose the queue in /admin/task; result mode 'version' is the MVP (replace/auto are follow-ups). --- application/application.go | 1 + application/constants/constants.go | 4 +- application/dependency/dependency.go | 47 + assets | 2 +- ent/client.go | 239 +++- ent/ent.go | 34 +- ent/hook/hook.go | 12 + ent/intercept/intercept.go | 30 + ent/internal/schema.go | 2 +- ent/mediaprocesstask.go | 236 ++++ ent/mediaprocesstask/mediaprocesstask.go | 207 ++++ ent/mediaprocesstask/where.go | 590 ++++++++++ ent/mediaprocesstask_create.go | 1325 ++++++++++++++++++++++ ent/mediaprocesstask_delete.go | 88 ++ ent/mediaprocesstask_query.go | 526 +++++++++ ent/mediaprocesstask_update.go | 775 +++++++++++++ ent/migrate/schema.go | 35 + ent/mutation.go | 1222 +++++++++++++++++++- ent/mutationhelper.go | 6 + ent/predicate/predicate.go | 3 + ent/runtime/runtime.go | 24 + ent/schema/mediaprocesstask.go | 67 ++ ent/tx.go | 3 + inventory/mediaprocess.go | 162 +++ inventory/mediaprocess_test.go | 73 ++ inventory/setting.go | 20 + inventory/types/types.go | 14 + pkg/filemanager/manager/mediacompress.go | 506 +++++++++ pkg/filemanager/manager/upload.go | 2 + pkg/queue/task.go | 1 + pkg/setting/provider.go | 20 + pkg/setting/types.go | 16 + service/admin/site.go | 12 + service/admin/task.go | 9 + service/user/response.go | 2 + service/user/setting.go | 6 + 36 files changed, 6238 insertions(+), 83 deletions(-) create mode 100644 ent/mediaprocesstask.go create mode 100644 ent/mediaprocesstask/mediaprocesstask.go create mode 100644 ent/mediaprocesstask/where.go create mode 100644 ent/mediaprocesstask_create.go create mode 100644 ent/mediaprocesstask_delete.go create mode 100644 ent/mediaprocesstask_query.go create mode 100644 ent/mediaprocesstask_update.go create mode 100644 ent/schema/mediaprocesstask.go create mode 100644 inventory/mediaprocess.go create mode 100644 inventory/mediaprocess_test.go create mode 100644 pkg/filemanager/manager/mediacompress.go diff --git a/application/application.go b/application/application.go index 0380872a..b52b2fe8 100644 --- a/application/application.go +++ b/application/application.go @@ -108,6 +108,7 @@ func (s *server) Start() error { s.dep.EntityRecycleQueue(context.Background()).Start() s.dep.IoIntenseQueue(context.Background()).Start() s.dep.RemoteDownloadQueue(context.Background()).Start() + s.dep.MediaProcessQueue(context.Background()).Start() // Start cron jobs c, err := crontab.NewCron(context.Background(), s.dep) diff --git a/application/constants/constants.go b/application/constants/constants.go index 82bf3b48..9df042f4 100644 --- a/application/constants/constants.go +++ b/application/constants/constants.go @@ -5,7 +5,9 @@ package constants // BackendVersion 当前后端版本号 // Bumped to 4.14.1 in this fork to trigger the schema migration that creates the // group⇄storage_policy allowed-set join table and backfills it (see inventory/migration.go). -var BackendVersion = "4.14.1" +// Bumped to 4.14.2 (APP-101) to trigger the migration that creates the +// media_process_task table and seeds the media-compression default settings. +var BackendVersion = "4.14.2" // IsPro 是否为Pro版本 var IsPro = "false" diff --git a/application/dependency/dependency.go b/application/dependency/dependency.go index d9963780..9036d2f4 100644 --- a/application/dependency/dependency.go +++ b/application/dependency/dependency.go @@ -120,6 +120,10 @@ type Dep interface { ThumbQueue(ctx context.Context) queue.Queue // EntityRecycleQueue Get a singleton queue.Queue instance for entity recycle. EntityRecycleQueue(ctx context.Context) queue.Queue + // MediaProcessQueue Get a singleton queue.Queue instance for media post-processing (APP-101). + MediaProcessQueue(ctx context.Context) queue.Queue + // MediaProcessClient Creates a new inventory.MediaProcessClient instance for the media_process_task store. + MediaProcessClient() inventory.MediaProcessClient // MimeDetector Get a singleton fs.MimeDetector instance for MIME type detection. MimeDetector(ctx context.Context) mime.MimeDetector // CredManager Get a singleton credmanager.CredManager instance for credential management. @@ -165,6 +169,7 @@ type dependency struct { groupClient inventory.GroupClient storagePolicyClient inventory.StoragePolicyClient taskClient inventory.TaskClient + mediaProcessClient inventory.MediaProcessClient nodeClient inventory.NodeClient davAccountClient inventory.DavAccountClient directLinkClient inventory.DirectLinkClient @@ -180,6 +185,7 @@ type dependency struct { thumbQueue queue.Queue mediaMetaQueue queue.Queue entityRecycleQueue queue.Queue + mediaProcessQueue queue.Queue slaveQueue queue.Queue remoteDownloadQueue queue.Queue ioIntenseQueueTask queue.Task @@ -746,6 +752,47 @@ func (d *dependency) EntityRecycleQueue(ctx context.Context) queue.Queue { return d.entityRecycleQueue } +func (d *dependency) MediaProcessQueue(ctx context.Context) queue.Queue { + d.mu.Lock() + defer d.mu.Unlock() + + _, reload := ctx.Value(ReloadCtx{}).(bool) + if d.mediaProcessQueue != nil && !reload { + return d.mediaProcessQueue + } + + if d.mediaProcessQueue != nil { + d.mediaProcessQueue.Shutdown() + } + + settings := d.SettingProvider() + queueSetting := settings.Queue(context.Background(), setting.QueueTypeMediaProcess) + // Worker count comes from the dedicated media_compress_worker_num key (default + // 1) to keep compression CPU-bounded — the generic queue worker_num getter has + // an upstream key bug that always yields its fallback. + workerNum := settings.MediaProcess(context.Background()).WorkerNum + + d.mediaProcessQueue = queue.New(d.Logger(), d.TaskClient(), d.TaskRegistry(), d, + queue.WithBackoffFactor(queueSetting.BackoffFactor), + queue.WithMaxRetry(queueSetting.MaxRetry), + queue.WithBackoffMaxDuration(queueSetting.BackoffMaxDuration), + queue.WithRetryDelay(queueSetting.RetryDelay), + queue.WithWorkerCount(workerNum), + queue.WithName("MediaProcessQueue"), + queue.WithMaxTaskExecution(queueSetting.MaxExecution), + queue.WithResumeTaskType(queue.MediaCompressTaskType), + queue.WithTaskPullInterval(10*time.Second), + ) + return d.mediaProcessQueue +} + +func (d *dependency) MediaProcessClient() inventory.MediaProcessClient { + if d.mediaProcessClient != nil { + return d.mediaProcessClient + } + return inventory.NewMediaProcessClient(d.DBClient(), d.ConfigProvider().Database().Type) +} + func (d *dependency) SlaveQueue(ctx context.Context) queue.Queue { d.mu.Lock() defer d.mu.Unlock() diff --git a/assets b/assets index 4107a8f4..74d41bbc 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 4107a8f4fd66e95a26877ee35b86ac6413976d4a +Subproject commit 74d41bbcee74020f3f071340f8cea73152f705c9 diff --git a/ent/client.go b/ent/client.go index 79c4ce8e..82924e3d 100644 --- a/ent/client.go +++ b/ent/client.go @@ -21,6 +21,7 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/file" "github.com/cloudreve/Cloudreve/v4/ent/fsevent" "github.com/cloudreve/Cloudreve/v4/ent/group" + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" "github.com/cloudreve/Cloudreve/v4/ent/metadata" "github.com/cloudreve/Cloudreve/v4/ent/node" "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" @@ -52,6 +53,8 @@ type Client struct { FsEvent *FsEventClient // Group is the client for interacting with the Group builders. Group *GroupClient + // MediaProcessTask is the client for interacting with the MediaProcessTask builders. + MediaProcessTask *MediaProcessTaskClient // Metadata is the client for interacting with the Metadata builders. Metadata *MetadataClient // Node is the client for interacting with the Node builders. @@ -89,6 +92,7 @@ func (c *Client) init() { c.File = NewFileClient(c.config) c.FsEvent = NewFsEventClient(c.config) c.Group = NewGroupClient(c.config) + c.MediaProcessTask = NewMediaProcessTaskClient(c.config) c.Metadata = NewMetadataClient(c.config) c.Node = NewNodeClient(c.config) c.OAuthClient = NewOAuthClientClient(c.config) @@ -189,24 +193,25 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { cfg := c.config cfg.driver = tx return &Tx{ - ctx: ctx, - config: cfg, - DavAccount: NewDavAccountClient(cfg), - DirectLink: NewDirectLinkClient(cfg), - Entity: NewEntityClient(cfg), - File: NewFileClient(cfg), - FsEvent: NewFsEventClient(cfg), - Group: NewGroupClient(cfg), - Metadata: NewMetadataClient(cfg), - Node: NewNodeClient(cfg), - OAuthClient: NewOAuthClientClient(cfg), - OAuthGrant: NewOAuthGrantClient(cfg), - Passkey: NewPasskeyClient(cfg), - Setting: NewSettingClient(cfg), - Share: NewShareClient(cfg), - StoragePolicy: NewStoragePolicyClient(cfg), - Task: NewTaskClient(cfg), - User: NewUserClient(cfg), + ctx: ctx, + config: cfg, + DavAccount: NewDavAccountClient(cfg), + DirectLink: NewDirectLinkClient(cfg), + Entity: NewEntityClient(cfg), + File: NewFileClient(cfg), + FsEvent: NewFsEventClient(cfg), + Group: NewGroupClient(cfg), + MediaProcessTask: NewMediaProcessTaskClient(cfg), + Metadata: NewMetadataClient(cfg), + Node: NewNodeClient(cfg), + OAuthClient: NewOAuthClientClient(cfg), + OAuthGrant: NewOAuthGrantClient(cfg), + Passkey: NewPasskeyClient(cfg), + Setting: NewSettingClient(cfg), + Share: NewShareClient(cfg), + StoragePolicy: NewStoragePolicyClient(cfg), + Task: NewTaskClient(cfg), + User: NewUserClient(cfg), }, nil } @@ -224,24 +229,25 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) cfg := c.config cfg.driver = &txDriver{tx: tx, drv: c.driver} return &Tx{ - ctx: ctx, - config: cfg, - DavAccount: NewDavAccountClient(cfg), - DirectLink: NewDirectLinkClient(cfg), - Entity: NewEntityClient(cfg), - File: NewFileClient(cfg), - FsEvent: NewFsEventClient(cfg), - Group: NewGroupClient(cfg), - Metadata: NewMetadataClient(cfg), - Node: NewNodeClient(cfg), - OAuthClient: NewOAuthClientClient(cfg), - OAuthGrant: NewOAuthGrantClient(cfg), - Passkey: NewPasskeyClient(cfg), - Setting: NewSettingClient(cfg), - Share: NewShareClient(cfg), - StoragePolicy: NewStoragePolicyClient(cfg), - Task: NewTaskClient(cfg), - User: NewUserClient(cfg), + ctx: ctx, + config: cfg, + DavAccount: NewDavAccountClient(cfg), + DirectLink: NewDirectLinkClient(cfg), + Entity: NewEntityClient(cfg), + File: NewFileClient(cfg), + FsEvent: NewFsEventClient(cfg), + Group: NewGroupClient(cfg), + MediaProcessTask: NewMediaProcessTaskClient(cfg), + Metadata: NewMetadataClient(cfg), + Node: NewNodeClient(cfg), + OAuthClient: NewOAuthClientClient(cfg), + OAuthGrant: NewOAuthGrantClient(cfg), + Passkey: NewPasskeyClient(cfg), + Setting: NewSettingClient(cfg), + Share: NewShareClient(cfg), + StoragePolicy: NewStoragePolicyClient(cfg), + Task: NewTaskClient(cfg), + User: NewUserClient(cfg), }, nil } @@ -271,9 +277,9 @@ func (c *Client) Close() error { // In order to add hooks to a specific client, call: `client.Node.Use(...)`. func (c *Client) Use(hooks ...Hook) { for _, n := range []interface{ Use(...Hook) }{ - c.DavAccount, c.DirectLink, c.Entity, c.File, c.FsEvent, c.Group, c.Metadata, - c.Node, c.OAuthClient, c.OAuthGrant, c.Passkey, c.Setting, c.Share, - c.StoragePolicy, c.Task, c.User, + c.DavAccount, c.DirectLink, c.Entity, c.File, c.FsEvent, c.Group, + c.MediaProcessTask, c.Metadata, c.Node, c.OAuthClient, c.OAuthGrant, c.Passkey, + c.Setting, c.Share, c.StoragePolicy, c.Task, c.User, } { n.Use(hooks...) } @@ -283,9 +289,9 @@ func (c *Client) Use(hooks ...Hook) { // In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`. func (c *Client) Intercept(interceptors ...Interceptor) { for _, n := range []interface{ Intercept(...Interceptor) }{ - c.DavAccount, c.DirectLink, c.Entity, c.File, c.FsEvent, c.Group, c.Metadata, - c.Node, c.OAuthClient, c.OAuthGrant, c.Passkey, c.Setting, c.Share, - c.StoragePolicy, c.Task, c.User, + c.DavAccount, c.DirectLink, c.Entity, c.File, c.FsEvent, c.Group, + c.MediaProcessTask, c.Metadata, c.Node, c.OAuthClient, c.OAuthGrant, c.Passkey, + c.Setting, c.Share, c.StoragePolicy, c.Task, c.User, } { n.Intercept(interceptors...) } @@ -306,6 +312,8 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { return c.FsEvent.mutate(ctx, m) case *GroupMutation: return c.Group.mutate(ctx, m) + case *MediaProcessTaskMutation: + return c.MediaProcessTask.mutate(ctx, m) case *MetadataMutation: return c.Metadata.mutate(ctx, m) case *NodeMutation: @@ -1412,6 +1420,141 @@ func (c *GroupClient) mutate(ctx context.Context, m *GroupMutation) (Value, erro } } +// MediaProcessTaskClient is a client for the MediaProcessTask schema. +type MediaProcessTaskClient struct { + config +} + +// NewMediaProcessTaskClient returns a client for the MediaProcessTask from the given config. +func NewMediaProcessTaskClient(c config) *MediaProcessTaskClient { + return &MediaProcessTaskClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `mediaprocesstask.Hooks(f(g(h())))`. +func (c *MediaProcessTaskClient) Use(hooks ...Hook) { + c.hooks.MediaProcessTask = append(c.hooks.MediaProcessTask, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `mediaprocesstask.Intercept(f(g(h())))`. +func (c *MediaProcessTaskClient) Intercept(interceptors ...Interceptor) { + c.inters.MediaProcessTask = append(c.inters.MediaProcessTask, interceptors...) +} + +// Create returns a builder for creating a MediaProcessTask entity. +func (c *MediaProcessTaskClient) Create() *MediaProcessTaskCreate { + mutation := newMediaProcessTaskMutation(c.config, OpCreate) + return &MediaProcessTaskCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of MediaProcessTask entities. +func (c *MediaProcessTaskClient) CreateBulk(builders ...*MediaProcessTaskCreate) *MediaProcessTaskCreateBulk { + return &MediaProcessTaskCreateBulk{config: c.config, builders: builders} +} + +// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates +// a builder and applies setFunc on it. +func (c *MediaProcessTaskClient) MapCreateBulk(slice any, setFunc func(*MediaProcessTaskCreate, int)) *MediaProcessTaskCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &MediaProcessTaskCreateBulk{err: fmt.Errorf("calling to MediaProcessTaskClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*MediaProcessTaskCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &MediaProcessTaskCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for MediaProcessTask. +func (c *MediaProcessTaskClient) Update() *MediaProcessTaskUpdate { + mutation := newMediaProcessTaskMutation(c.config, OpUpdate) + return &MediaProcessTaskUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *MediaProcessTaskClient) UpdateOne(mpt *MediaProcessTask) *MediaProcessTaskUpdateOne { + mutation := newMediaProcessTaskMutation(c.config, OpUpdateOne, withMediaProcessTask(mpt)) + return &MediaProcessTaskUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *MediaProcessTaskClient) UpdateOneID(id int) *MediaProcessTaskUpdateOne { + mutation := newMediaProcessTaskMutation(c.config, OpUpdateOne, withMediaProcessTaskID(id)) + return &MediaProcessTaskUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for MediaProcessTask. +func (c *MediaProcessTaskClient) Delete() *MediaProcessTaskDelete { + mutation := newMediaProcessTaskMutation(c.config, OpDelete) + return &MediaProcessTaskDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *MediaProcessTaskClient) DeleteOne(mpt *MediaProcessTask) *MediaProcessTaskDeleteOne { + return c.DeleteOneID(mpt.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *MediaProcessTaskClient) DeleteOneID(id int) *MediaProcessTaskDeleteOne { + builder := c.Delete().Where(mediaprocesstask.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &MediaProcessTaskDeleteOne{builder} +} + +// Query returns a query builder for MediaProcessTask. +func (c *MediaProcessTaskClient) Query() *MediaProcessTaskQuery { + return &MediaProcessTaskQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeMediaProcessTask}, + inters: c.Interceptors(), + } +} + +// Get returns a MediaProcessTask entity by its id. +func (c *MediaProcessTaskClient) Get(ctx context.Context, id int) (*MediaProcessTask, error) { + return c.Query().Where(mediaprocesstask.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *MediaProcessTaskClient) GetX(ctx context.Context, id int) *MediaProcessTask { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// Hooks returns the client hooks. +func (c *MediaProcessTaskClient) Hooks() []Hook { + hooks := c.hooks.MediaProcessTask + return append(hooks[:len(hooks):len(hooks)], mediaprocesstask.Hooks[:]...) +} + +// Interceptors returns the client interceptors. +func (c *MediaProcessTaskClient) Interceptors() []Interceptor { + inters := c.inters.MediaProcessTask + return append(inters[:len(inters):len(inters)], mediaprocesstask.Interceptors[:]...) +} + +func (c *MediaProcessTaskClient) mutate(ctx context.Context, m *MediaProcessTaskMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&MediaProcessTaskCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&MediaProcessTaskUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&MediaProcessTaskUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&MediaProcessTaskDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown MediaProcessTask mutation op: %q", m.Op()) + } +} + // MetadataClient is a client for the Metadata schema. type MetadataClient struct { config @@ -3133,14 +3276,14 @@ func (c *UserClient) mutate(ctx context.Context, m *UserMutation) (Value, error) // hooks and interceptors per client, for fast access. type ( hooks struct { - DavAccount, DirectLink, Entity, File, FsEvent, Group, Metadata, Node, - OAuthClient, OAuthGrant, Passkey, Setting, Share, StoragePolicy, Task, - User []ent.Hook + DavAccount, DirectLink, Entity, File, FsEvent, Group, MediaProcessTask, + Metadata, Node, OAuthClient, OAuthGrant, Passkey, Setting, Share, + StoragePolicy, Task, User []ent.Hook } inters struct { - DavAccount, DirectLink, Entity, File, FsEvent, Group, Metadata, Node, - OAuthClient, OAuthGrant, Passkey, Setting, Share, StoragePolicy, Task, - User []ent.Interceptor + DavAccount, DirectLink, Entity, File, FsEvent, Group, MediaProcessTask, + Metadata, Node, OAuthClient, OAuthGrant, Passkey, Setting, Share, + StoragePolicy, Task, User []ent.Interceptor } ) diff --git a/ent/ent.go b/ent/ent.go index 3d92b48c..dd74ab38 100644 --- a/ent/ent.go +++ b/ent/ent.go @@ -18,6 +18,7 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/file" "github.com/cloudreve/Cloudreve/v4/ent/fsevent" "github.com/cloudreve/Cloudreve/v4/ent/group" + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" "github.com/cloudreve/Cloudreve/v4/ent/metadata" "github.com/cloudreve/Cloudreve/v4/ent/node" "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" @@ -88,22 +89,23 @@ var ( func checkColumn(table, column string) error { initCheck.Do(func() { columnCheck = sql.NewColumnCheck(map[string]func(string) bool{ - davaccount.Table: davaccount.ValidColumn, - directlink.Table: directlink.ValidColumn, - entity.Table: entity.ValidColumn, - file.Table: file.ValidColumn, - fsevent.Table: fsevent.ValidColumn, - group.Table: group.ValidColumn, - metadata.Table: metadata.ValidColumn, - node.Table: node.ValidColumn, - oauthclient.Table: oauthclient.ValidColumn, - oauthgrant.Table: oauthgrant.ValidColumn, - passkey.Table: passkey.ValidColumn, - setting.Table: setting.ValidColumn, - share.Table: share.ValidColumn, - storagepolicy.Table: storagepolicy.ValidColumn, - task.Table: task.ValidColumn, - user.Table: user.ValidColumn, + davaccount.Table: davaccount.ValidColumn, + directlink.Table: directlink.ValidColumn, + entity.Table: entity.ValidColumn, + file.Table: file.ValidColumn, + fsevent.Table: fsevent.ValidColumn, + group.Table: group.ValidColumn, + mediaprocesstask.Table: mediaprocesstask.ValidColumn, + metadata.Table: metadata.ValidColumn, + node.Table: node.ValidColumn, + oauthclient.Table: oauthclient.ValidColumn, + oauthgrant.Table: oauthgrant.ValidColumn, + passkey.Table: passkey.ValidColumn, + setting.Table: setting.ValidColumn, + share.Table: share.ValidColumn, + storagepolicy.Table: storagepolicy.ValidColumn, + task.Table: task.ValidColumn, + user.Table: user.ValidColumn, }) }) return columnCheck(table, column) diff --git a/ent/hook/hook.go b/ent/hook/hook.go index 2bf7e995..c49b7239 100644 --- a/ent/hook/hook.go +++ b/ent/hook/hook.go @@ -81,6 +81,18 @@ func (f GroupFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.GroupMutation", m) } +// The MediaProcessTaskFunc type is an adapter to allow the use of ordinary +// function as MediaProcessTask mutator. +type MediaProcessTaskFunc func(context.Context, *ent.MediaProcessTaskMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f MediaProcessTaskFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.MediaProcessTaskMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.MediaProcessTaskMutation", m) +} + // The MetadataFunc type is an adapter to allow the use of ordinary // function as Metadata mutator. type MetadataFunc func(context.Context, *ent.MetadataMutation) (ent.Value, error) diff --git a/ent/intercept/intercept.go b/ent/intercept/intercept.go index b2efc35b..49f0ecbf 100644 --- a/ent/intercept/intercept.go +++ b/ent/intercept/intercept.go @@ -14,6 +14,7 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/file" "github.com/cloudreve/Cloudreve/v4/ent/fsevent" "github.com/cloudreve/Cloudreve/v4/ent/group" + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" "github.com/cloudreve/Cloudreve/v4/ent/metadata" "github.com/cloudreve/Cloudreve/v4/ent/node" "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" @@ -245,6 +246,33 @@ func (f TraverseGroup) Traverse(ctx context.Context, q ent.Query) error { return fmt.Errorf("unexpected query type %T. expect *ent.GroupQuery", q) } +// The MediaProcessTaskFunc type is an adapter to allow the use of ordinary function as a Querier. +type MediaProcessTaskFunc func(context.Context, *ent.MediaProcessTaskQuery) (ent.Value, error) + +// Query calls f(ctx, q). +func (f MediaProcessTaskFunc) Query(ctx context.Context, q ent.Query) (ent.Value, error) { + if q, ok := q.(*ent.MediaProcessTaskQuery); ok { + return f(ctx, q) + } + return nil, fmt.Errorf("unexpected query type %T. expect *ent.MediaProcessTaskQuery", q) +} + +// The TraverseMediaProcessTask type is an adapter to allow the use of ordinary function as Traverser. +type TraverseMediaProcessTask func(context.Context, *ent.MediaProcessTaskQuery) error + +// Intercept is a dummy implementation of Intercept that returns the next Querier in the pipeline. +func (f TraverseMediaProcessTask) Intercept(next ent.Querier) ent.Querier { + return next +} + +// Traverse calls f(ctx, q). +func (f TraverseMediaProcessTask) Traverse(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.MediaProcessTaskQuery); ok { + return f(ctx, q) + } + return fmt.Errorf("unexpected query type %T. expect *ent.MediaProcessTaskQuery", q) +} + // The MetadataFunc type is an adapter to allow the use of ordinary function as a Querier. type MetadataFunc func(context.Context, *ent.MetadataQuery) (ent.Value, error) @@ -530,6 +558,8 @@ func NewQuery(q ent.Query) (Query, error) { return &query[*ent.FsEventQuery, predicate.FsEvent, fsevent.OrderOption]{typ: ent.TypeFsEvent, tq: q}, nil case *ent.GroupQuery: return &query[*ent.GroupQuery, predicate.Group, group.OrderOption]{typ: ent.TypeGroup, tq: q}, nil + case *ent.MediaProcessTaskQuery: + return &query[*ent.MediaProcessTaskQuery, predicate.MediaProcessTask, mediaprocesstask.OrderOption]{typ: ent.TypeMediaProcessTask, tq: q}, nil case *ent.MetadataQuery: return &query[*ent.MetadataQuery, predicate.Metadata, metadata.OrderOption]{typ: ent.TypeMetadata, tq: q}, nil case *ent.NodeQuery: diff --git a/ent/internal/schema.go b/ent/internal/schema.go index 97ed5035..07abe47f 100644 --- a/ent/internal/schema.go +++ b/ent/internal/schema.go @@ -6,4 +6,4 @@ // Package internal holds a loadable version of the latest schema. package internal -const Schema = "{\"Schema\":\"github.com/cloudreve/Cloudreve/v4/ent/schema\",\"Package\":\"github.com/cloudreve/Cloudreve/v4/ent\",\"Schemas\":[{\"name\":\"DavAccount\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"owner\",\"type\":\"User\",\"field\":\"owner_id\",\"ref_name\":\"dav_accounts\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"uri\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"options\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.DavAccountProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"DavAccountProps\",\"Ident\":\"types.DavAccountProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"owner_id\",\"password\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"DirectLink\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"direct_links\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"speed\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Entity\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"ref_name\":\"entities\",\"inverse\":true},{\"name\":\"user\",\"type\":\"User\",\"field\":\"created_by\",\"ref_name\":\"entities\",\"unique\":true,\"inverse\":true},{\"name\":\"storage_policy\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_entities\",\"ref_name\":\"entities\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"source\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"reference_count\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":1,\"default_kind\":2,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_entities\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"created_by\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"upload_session_id\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.EntityProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"EntityProps\",\"Ident\":\"types.EntityProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"storage_key\":\"recycle_options\",\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"File\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"owner\",\"type\":\"User\",\"field\":\"owner_id\",\"ref_name\":\"files\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"storage_policies\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_files\",\"ref_name\":\"files\",\"unique\":true,\"inverse\":true},{\"name\":\"parent\",\"type\":\"File\",\"field\":\"file_children\",\"ref\":{\"name\":\"children\",\"type\":\"File\"},\"unique\":true,\"inverse\":true},{\"name\":\"metadata\",\"type\":\"Metadata\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"shares\",\"type\":\"Share\"},{\"name\":\"direct_links\",\"type\":\"DirectLink\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"primary_entity\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_children\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_symbolic\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.FileProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"FileProps\",\"Ident\":\"types.FileProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_files\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_children\",\"name\"]},{\"fields\":[\"file_children\",\"type\",\"updated_at\"]},{\"fields\":[\"file_children\",\"type\",\"created_at\"]},{\"fields\":[\"file_children\",\"type\",\"size\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}]},{\"name\":\"FsEvent\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_fsevent\",\"ref_name\":\"fsevents\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"event\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"subscriber\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_fsevent\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Group\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"users\",\"type\":\"User\"},{\"name\":\"storage_policies\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_id\",\"ref_name\":\"groups\",\"unique\":true,\"inverse\":true},{\"name\":\"storage_policies_allowed\",\"type\":\"StoragePolicy\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_storage\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"speed_limit\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"permissions\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.GroupSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"GroupSetting\",\"Ident\":\"types.GroupSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Metadata\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"metadata\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"value\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_public\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_id\",\"name\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Node\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"storage_policy\",\"type\":\"StoragePolicy\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"node.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"suspended\",\"V\":\"suspended\"}],\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":6,\"Ident\":\"node.Type\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"master\",\"V\":\"master\"},{\"N\":\"slave\",\"V\":\"slave\"}],\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"server\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"slave_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"capabilities\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.NodeSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"NodeSetting\",\"Ident\":\"types.NodeSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"weight\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"OAuthClient\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"grants\",\"type\":\"OAuthGrant\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"guid\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"secret\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"validators\":1,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"homepage_url\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2048,\"optional\":true,\"validators\":1,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"redirect_uris\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"scopes\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.OAuthClientProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"OAuthClientProps\",\"Ident\":\"types.OAuthClientProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_enabled\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":true,\"default_kind\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"OAuthGrant\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"oauth_grants\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"client\",\"type\":\"OAuthClient\",\"field\":\"client_id\",\"ref_name\":\"grants\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"client_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"scopes\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"last_used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}}],\"indexes\":[{\"unique\":true,\"fields\":[\"user_id\",\"client_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Passkey\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"passkey\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credential_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credential\",\"type\":{\"Type\":3,\"Ident\":\"*webauthn.Credential\",\"PkgPath\":\"github.com/go-webauthn/webauthn/webauthn\",\"PkgName\":\"webauthn\",\"Nillable\":true,\"RType\":{\"Name\":\"Credential\",\"Ident\":\"webauthn.Credential\",\"Kind\":22,\"PkgPath\":\"github.com/go-webauthn/webauthn/webauthn\",\"Methods\":{\"Descriptor\":{\"In\":[],\"Out\":[{\"Name\":\"CredentialDescriptor\",\"Ident\":\"protocol.CredentialDescriptor\",\"Kind\":25,\"PkgPath\":\"github.com/go-webauthn/webauthn/protocol\",\"Methods\":null}]},\"Verify\":{\"In\":[{\"Name\":\"Provider\",\"Ident\":\"metadata.Provider\",\"Kind\":20,\"PkgPath\":\"github.com/go-webauthn/webauthn/metadata\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}}],\"indexes\":[{\"unique\":true,\"fields\":[\"user_id\",\"credential_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Setting\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"unique\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"value\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Share\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"ref_name\":\"shares\",\"unique\":true,\"inverse\":true},{\"name\":\"file\",\"type\":\"File\",\"ref_name\":\"shares\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"views\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"expires\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"remain_downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.ShareProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"ShareProps\",\"Ident\":\"types.ShareProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"StoragePolicy\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"groups\",\"type\":\"Group\"},{\"name\":\"files\",\"type\":\"File\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"node\",\"type\":\"Node\",\"field\":\"node_id\",\"ref_name\":\"storage_policy\",\"unique\":true,\"inverse\":true},{\"name\":\"groups_allowed\",\"type\":\"Group\",\"ref_name\":\"storage_policies_allowed\",\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"server\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"bucket_name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_private\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"access_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"secret_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"dir_name_rule\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_name_rule\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.PolicySetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"PolicySetting\",\"Ident\":\"types.PolicySetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{\"file_type\":null,\"native_media_processing\":false,\"s3_path_style\":false,\"token\":\"\"},\"default_kind\":22,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"node_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":11,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Task\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_tasks\",\"ref_name\":\"tasks\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"task.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"queued\",\"V\":\"queued\"},{\"N\":\"processing\",\"V\":\"processing\"},{\"N\":\"suspending\",\"V\":\"suspending\"},{\"N\":\"error\",\"V\":\"error\"},{\"N\":\"canceled\",\"V\":\"canceled\"},{\"N\":\"completed\",\"V\":\"completed\"}],\"default\":true,\"default_value\":\"queued\",\"default_kind\":24,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"public_state\",\"type\":{\"Type\":3,\"Ident\":\"*types.TaskPublicState\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"TaskPublicState\",\"Ident\":\"types.TaskPublicState\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"private_state\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"correlation_id\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"optional\":true,\"immutable\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_tasks\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"User\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"group\",\"type\":\"Group\",\"field\":\"group_users\",\"ref_name\":\"users\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"files\",\"type\":\"File\"},{\"name\":\"dav_accounts\",\"type\":\"DavAccount\"},{\"name\":\"shares\",\"type\":\"Share\"},{\"name\":\"passkey\",\"type\":\"Passkey\"},{\"name\":\"tasks\",\"type\":\"Task\"},{\"name\":\"fsevents\",\"type\":\"FsEvent\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"oauth_grants\",\"type\":\"OAuthGrant\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"email\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":100,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"nick\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":100,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"user.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"inactive\",\"V\":\"inactive\"},{\"N\":\"manual_banned\",\"V\":\"manual_banned\"},{\"N\":\"sys_banned\",\"V\":\"sys_banned\"}],\"default\":true,\"default_value\":\"active\",\"default_kind\":24,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"two_factor_secret\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"avatar\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.UserSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"UserSetting\",\"Ident\":\"types.UserSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"group_users\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]}],\"Features\":[\"intercept\",\"schema/snapshot\",\"sql/upsert\",\"sql/upsert\",\"sql/execquery\"]}" +const Schema = "{\"Schema\":\"github.com/cloudreve/Cloudreve/v4/ent/schema\",\"Package\":\"github.com/cloudreve/Cloudreve/v4/ent\",\"Schemas\":[{\"name\":\"DavAccount\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"owner\",\"type\":\"User\",\"field\":\"owner_id\",\"ref_name\":\"dav_accounts\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"uri\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"options\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.DavAccountProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"DavAccountProps\",\"Ident\":\"types.DavAccountProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"owner_id\",\"password\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"DirectLink\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"direct_links\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"speed\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Entity\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"ref_name\":\"entities\",\"inverse\":true},{\"name\":\"user\",\"type\":\"User\",\"field\":\"created_by\",\"ref_name\":\"entities\",\"unique\":true,\"inverse\":true},{\"name\":\"storage_policy\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_entities\",\"ref_name\":\"entities\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"source\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"reference_count\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":1,\"default_kind\":2,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_entities\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"created_by\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"upload_session_id\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.EntityProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"EntityProps\",\"Ident\":\"types.EntityProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"storage_key\":\"recycle_options\",\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"File\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"owner\",\"type\":\"User\",\"field\":\"owner_id\",\"ref_name\":\"files\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"storage_policies\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_files\",\"ref_name\":\"files\",\"unique\":true,\"inverse\":true},{\"name\":\"parent\",\"type\":\"File\",\"field\":\"file_children\",\"ref\":{\"name\":\"children\",\"type\":\"File\"},\"unique\":true,\"inverse\":true},{\"name\":\"metadata\",\"type\":\"Metadata\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"shares\",\"type\":\"Share\"},{\"name\":\"direct_links\",\"type\":\"DirectLink\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"primary_entity\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_children\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_symbolic\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.FileProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"FileProps\",\"Ident\":\"types.FileProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_files\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_children\",\"name\"]},{\"fields\":[\"file_children\",\"type\",\"updated_at\"]},{\"fields\":[\"file_children\",\"type\",\"created_at\"]},{\"fields\":[\"file_children\",\"type\",\"size\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}]},{\"name\":\"FsEvent\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_fsevent\",\"ref_name\":\"fsevents\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"event\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"subscriber\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_fsevent\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Group\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"users\",\"type\":\"User\"},{\"name\":\"storage_policies\",\"type\":\"StoragePolicy\",\"field\":\"storage_policy_id\",\"ref_name\":\"groups\",\"unique\":true,\"inverse\":true},{\"name\":\"storage_policies_allowed\",\"type\":\"StoragePolicy\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_storage\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"speed_limit\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"permissions\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.GroupSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"GroupSetting\",\"Ident\":\"types.GroupSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage_policy_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"MediaProcessTask\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"media_type\",\"type\":{\"Type\":6,\"Ident\":\"mediaprocesstask.MediaType\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"image\",\"V\":\"image\"},{\"N\":\"video\",\"V\":\"video\"}],\"default\":true,\"default_value\":\"image\",\"default_kind\":24,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"mediaprocesstask.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"pending\",\"V\":\"pending\"},{\"N\":\"processing\",\"V\":\"processing\"},{\"N\":\"done\",\"V\":\"done\"},{\"N\":\"failed\",\"V\":\"failed\"},{\"N\":\"skipped\",\"V\":\"skipped\"}],\"default\":true,\"default_value\":\"pending\",\"default_kind\":24,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"entity_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"owner_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"attempts\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"error\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"result_size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.MediaProcessTaskProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"MediaProcessTaskProps\",\"Ident\":\"types.MediaProcessTaskProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"fields\":[\"status\",\"media_type\"]},{\"fields\":[\"entity_id\",\"status\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Metadata\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"file\",\"type\":\"File\",\"field\":\"file_id\",\"ref_name\":\"metadata\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"value\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_public\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":false,\"default_kind\":1,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}}],\"indexes\":[{\"unique\":true,\"fields\":[\"file_id\",\"name\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Node\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"storage_policy\",\"type\":\"StoragePolicy\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"node.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"suspended\",\"V\":\"suspended\"}],\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":6,\"Ident\":\"node.Type\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"master\",\"V\":\"master\"},{\"N\":\"slave\",\"V\":\"slave\"}],\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"server\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"slave_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"capabilities\",\"type\":{\"Type\":5,\"Ident\":\"*boolset.BooleanSet\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"PkgName\":\"boolset\",\"Nillable\":true,\"RType\":{\"Name\":\"BooleanSet\",\"Ident\":\"boolset.BooleanSet\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/pkg/boolset\",\"Methods\":{\"Enabled\":{\"In\":[{\"Name\":\"int\",\"Ident\":\"int\",\"Kind\":2,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"bool\",\"Ident\":\"bool\",\"Kind\":1,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.NodeSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"NodeSetting\",\"Ident\":\"types.NodeSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"weight\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"OAuthClient\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"grants\",\"type\":\"OAuthGrant\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"guid\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"secret\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":255,\"validators\":1,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"homepage_url\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2048,\"optional\":true,\"validators\":1,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"redirect_uris\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"scopes\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.OAuthClientProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"OAuthClientProps\",\"Ident\":\"types.OAuthClientProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_enabled\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":true,\"default_kind\":1,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"OAuthGrant\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"oauth_grants\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"client\",\"type\":\"OAuthClient\",\"field\":\"client_id\",\"ref_name\":\"grants\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"client_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"scopes\",\"type\":{\"Type\":3,\"Ident\":\"[]string\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":true,\"RType\":{\"Name\":\"\",\"Ident\":\"[]string\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":{}}},\"default\":true,\"default_value\":[],\"default_kind\":23,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"last_used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}}],\"indexes\":[{\"unique\":true,\"fields\":[\"user_id\",\"client_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Passkey\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_id\",\"ref_name\":\"passkey\",\"unique\":true,\"inverse\":true,\"required\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"user_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credential_id\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"credential\",\"type\":{\"Type\":3,\"Ident\":\"*webauthn.Credential\",\"PkgPath\":\"github.com/go-webauthn/webauthn/webauthn\",\"PkgName\":\"webauthn\",\"Nillable\":true,\"RType\":{\"Name\":\"Credential\",\"Ident\":\"webauthn.Credential\",\"Kind\":22,\"PkgPath\":\"github.com/go-webauthn/webauthn/webauthn\",\"Methods\":{\"Descriptor\":{\"In\":[],\"Out\":[{\"Name\":\"CredentialDescriptor\",\"Ident\":\"protocol.CredentialDescriptor\",\"Kind\":25,\"PkgPath\":\"github.com/go-webauthn/webauthn/protocol\",\"Methods\":null}]},\"Verify\":{\"In\":[{\"Name\":\"Provider\",\"Ident\":\"metadata.Provider\",\"Kind\":20,\"PkgPath\":\"github.com/go-webauthn/webauthn/metadata\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"used_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}}],\"indexes\":[{\"unique\":true,\"fields\":[\"user_id\",\"credential_id\"]}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Setting\",\"config\":{\"Table\":\"\"},\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"unique\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"value\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Share\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"ref_name\":\"shares\",\"unique\":true,\"inverse\":true},{\"name\":\"file\",\"type\":\"File\",\"ref_name\":\"shares\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"views\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":2,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"expires\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"remain_downloads\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"props\",\"type\":{\"Type\":3,\"Ident\":\"*types.ShareProps\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"ShareProps\",\"Ident\":\"types.ShareProps\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"StoragePolicy\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"groups\",\"type\":\"Group\"},{\"name\":\"files\",\"type\":\"File\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"node\",\"type\":\"Node\",\"field\":\"node_id\",\"ref_name\":\"storage_policy\",\"unique\":true,\"inverse\":true},{\"name\":\"groups_allowed\",\"type\":\"Group\",\"ref_name\":\"storage_policies_allowed\",\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"server\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"bucket_name\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"is_private\",\"type\":{\"Type\":1,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"access_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"secret_key\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"max_size\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"dir_name_rule\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"file_name_rule\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":9,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.PolicySetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"PolicySetting\",\"Ident\":\"types.PolicySetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{\"file_type\":null,\"native_media_processing\":false,\"s3_path_style\":false,\"token\":\"\"},\"default_kind\":22,\"position\":{\"Index\":10,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"node_id\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":11,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"Task\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"user\",\"type\":\"User\",\"field\":\"user_tasks\",\"ref_name\":\"tasks\",\"unique\":true,\"inverse\":true}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"type\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"task.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"queued\",\"V\":\"queued\"},{\"N\":\"processing\",\"V\":\"processing\"},{\"N\":\"suspending\",\"V\":\"suspending\"},{\"N\":\"error\",\"V\":\"error\"},{\"N\":\"canceled\",\"V\":\"canceled\"},{\"N\":\"completed\",\"V\":\"completed\"}],\"default\":true,\"default_value\":\"queued\",\"default_kind\":24,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"public_state\",\"type\":{\"Type\":3,\"Ident\":\"*types.TaskPublicState\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"TaskPublicState\",\"Ident\":\"types.TaskPublicState\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"private_state\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":2147483647,\"optional\":true,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"correlation_id\",\"type\":{\"Type\":4,\"Ident\":\"uuid.UUID\",\"PkgPath\":\"github.com/gofrs/uuid\",\"PkgName\":\"uuid\",\"Nillable\":false,\"RType\":{\"Name\":\"UUID\",\"Ident\":\"uuid.UUID\",\"Kind\":17,\"PkgPath\":\"github.com/gofrs/uuid\",\"Methods\":{\"Bytes\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}]},\"Format\":{\"In\":[{\"Name\":\"State\",\"Ident\":\"fmt.State\",\"Kind\":20,\"PkgPath\":\"fmt\",\"Methods\":null},{\"Name\":\"int32\",\"Ident\":\"int32\",\"Kind\":5,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"MarshalBinary\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"MarshalText\":{\"In\":[],\"Out\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Scan\":{\"In\":[{\"Name\":\"\",\"Ident\":\"interface {}\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"SetVariant\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"SetVersion\":{\"In\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[]},\"String\":{\"In\":[],\"Out\":[{\"Name\":\"string\",\"Ident\":\"string\",\"Kind\":24,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalBinary\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"UnmarshalText\":{\"In\":[{\"Name\":\"\",\"Ident\":\"[]uint8\",\"Kind\":23,\"PkgPath\":\"\",\"Methods\":null}],\"Out\":[{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Value\":{\"In\":[],\"Out\":[{\"Name\":\"Value\",\"Ident\":\"driver.Value\",\"Kind\":20,\"PkgPath\":\"database/sql/driver\",\"Methods\":null},{\"Name\":\"error\",\"Ident\":\"error\",\"Kind\":20,\"PkgPath\":\"\",\"Methods\":null}]},\"Variant\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]},\"Version\":{\"In\":[],\"Out\":[{\"Name\":\"uint8\",\"Ident\":\"uint8\",\"Kind\":8,\"PkgPath\":\"\",\"Methods\":null}]}}}},\"optional\":true,\"immutable\":true,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"user_tasks\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]},{\"name\":\"User\",\"config\":{\"Table\":\"\"},\"edges\":[{\"name\":\"group\",\"type\":\"Group\",\"field\":\"group_users\",\"ref_name\":\"users\",\"unique\":true,\"inverse\":true,\"required\":true},{\"name\":\"files\",\"type\":\"File\"},{\"name\":\"dav_accounts\",\"type\":\"DavAccount\"},{\"name\":\"shares\",\"type\":\"Share\"},{\"name\":\"passkey\",\"type\":\"Passkey\"},{\"name\":\"tasks\",\"type\":\"Task\"},{\"name\":\"fsevents\",\"type\":\"FsEvent\"},{\"name\":\"entities\",\"type\":\"Entity\"},{\"name\":\"oauth_grants\",\"type\":\"OAuthGrant\"}],\"fields\":[{\"name\":\"created_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"immutable\":true,\"position\":{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"updated_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_kind\":19,\"update_default\":true,\"position\":{\"Index\":1,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"deleted_at\",\"type\":{\"Type\":2,\"Ident\":\"\",\"PkgPath\":\"time\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"nillable\":true,\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":true,\"MixinIndex\":0},\"schema_type\":{\"mysql\":\"datetime\"}},{\"name\":\"email\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":100,\"unique\":true,\"validators\":1,\"position\":{\"Index\":0,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"nick\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"size\":100,\"validators\":1,\"position\":{\"Index\":1,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"password\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":2,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"status\",\"type\":{\"Type\":6,\"Ident\":\"user.Status\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"enums\":[{\"N\":\"active\",\"V\":\"active\"},{\"N\":\"inactive\",\"V\":\"inactive\"},{\"N\":\"manual_banned\",\"V\":\"manual_banned\"},{\"N\":\"sys_banned\",\"V\":\"sys_banned\"}],\"default\":true,\"default_value\":\"active\",\"default_kind\":24,\"position\":{\"Index\":3,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"storage\",\"type\":{\"Type\":13,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"default\":true,\"default_value\":0,\"default_kind\":6,\"position\":{\"Index\":4,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"two_factor_secret\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":5,\"MixedIn\":false,\"MixinIndex\":0},\"sensitive\":true},{\"name\":\"avatar\",\"type\":{\"Type\":7,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"optional\":true,\"position\":{\"Index\":6,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"settings\",\"type\":{\"Type\":3,\"Ident\":\"*types.UserSetting\",\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"PkgName\":\"types\",\"Nillable\":true,\"RType\":{\"Name\":\"UserSetting\",\"Ident\":\"types.UserSetting\",\"Kind\":22,\"PkgPath\":\"github.com/cloudreve/Cloudreve/v4/inventory/types\",\"Methods\":{}}},\"optional\":true,\"default\":true,\"default_value\":{},\"default_kind\":22,\"position\":{\"Index\":7,\"MixedIn\":false,\"MixinIndex\":0}},{\"name\":\"group_users\",\"type\":{\"Type\":12,\"Ident\":\"\",\"PkgPath\":\"\",\"PkgName\":\"\",\"Nillable\":false,\"RType\":null},\"position\":{\"Index\":8,\"MixedIn\":false,\"MixinIndex\":0}}],\"hooks\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}],\"interceptors\":[{\"Index\":0,\"MixedIn\":true,\"MixinIndex\":0}]}],\"Features\":[\"intercept\",\"schema/snapshot\",\"sql/upsert\",\"sql/upsert\",\"sql/execquery\"]}" diff --git a/ent/mediaprocesstask.go b/ent/mediaprocesstask.go new file mode 100644 index 00000000..a38ea432 --- /dev/null +++ b/ent/mediaprocesstask.go @@ -0,0 +1,236 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "encoding/json" + "fmt" + "strings" + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" + "github.com/cloudreve/Cloudreve/v4/inventory/types" +) + +// MediaProcessTask is the model entity for the MediaProcessTask schema. +type MediaProcessTask struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt time.Time `json:"created_at,omitempty"` + // UpdatedAt holds the value of the "updated_at" field. + UpdatedAt time.Time `json:"updated_at,omitempty"` + // DeletedAt holds the value of the "deleted_at" field. + DeletedAt *time.Time `json:"deleted_at,omitempty"` + // MediaType holds the value of the "media_type" field. + MediaType mediaprocesstask.MediaType `json:"media_type,omitempty"` + // Status holds the value of the "status" field. + Status mediaprocesstask.Status `json:"status,omitempty"` + // EntityID holds the value of the "entity_id" field. + EntityID int `json:"entity_id,omitempty"` + // FileID holds the value of the "file_id" field. + FileID int `json:"file_id,omitempty"` + // OwnerID holds the value of the "owner_id" field. + OwnerID int `json:"owner_id,omitempty"` + // Attempts holds the value of the "attempts" field. + Attempts int `json:"attempts,omitempty"` + // Error holds the value of the "error" field. + Error string `json:"error,omitempty"` + // ResultSize holds the value of the "result_size" field. + ResultSize int64 `json:"result_size,omitempty"` + // Props holds the value of the "props" field. + Props *types.MediaProcessTaskProps `json:"props,omitempty"` + selectValues sql.SelectValues +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*MediaProcessTask) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case mediaprocesstask.FieldProps: + values[i] = new([]byte) + case mediaprocesstask.FieldID, mediaprocesstask.FieldEntityID, mediaprocesstask.FieldFileID, mediaprocesstask.FieldOwnerID, mediaprocesstask.FieldAttempts, mediaprocesstask.FieldResultSize: + values[i] = new(sql.NullInt64) + case mediaprocesstask.FieldMediaType, mediaprocesstask.FieldStatus, mediaprocesstask.FieldError: + values[i] = new(sql.NullString) + case mediaprocesstask.FieldCreatedAt, mediaprocesstask.FieldUpdatedAt, mediaprocesstask.FieldDeletedAt: + values[i] = new(sql.NullTime) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the MediaProcessTask fields. +func (mpt *MediaProcessTask) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case mediaprocesstask.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + mpt.ID = int(value.Int64) + case mediaprocesstask.FieldCreatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value.Valid { + mpt.CreatedAt = value.Time + } + case mediaprocesstask.FieldUpdatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field updated_at", values[i]) + } else if value.Valid { + mpt.UpdatedAt = value.Time + } + case mediaprocesstask.FieldDeletedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field deleted_at", values[i]) + } else if value.Valid { + mpt.DeletedAt = new(time.Time) + *mpt.DeletedAt = value.Time + } + case mediaprocesstask.FieldMediaType: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field media_type", values[i]) + } else if value.Valid { + mpt.MediaType = mediaprocesstask.MediaType(value.String) + } + case mediaprocesstask.FieldStatus: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field status", values[i]) + } else if value.Valid { + mpt.Status = mediaprocesstask.Status(value.String) + } + case mediaprocesstask.FieldEntityID: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field entity_id", values[i]) + } else if value.Valid { + mpt.EntityID = int(value.Int64) + } + case mediaprocesstask.FieldFileID: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field file_id", values[i]) + } else if value.Valid { + mpt.FileID = int(value.Int64) + } + case mediaprocesstask.FieldOwnerID: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field owner_id", values[i]) + } else if value.Valid { + mpt.OwnerID = int(value.Int64) + } + case mediaprocesstask.FieldAttempts: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field attempts", values[i]) + } else if value.Valid { + mpt.Attempts = int(value.Int64) + } + case mediaprocesstask.FieldError: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field error", values[i]) + } else if value.Valid { + mpt.Error = value.String + } + case mediaprocesstask.FieldResultSize: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field result_size", values[i]) + } else if value.Valid { + mpt.ResultSize = value.Int64 + } + case mediaprocesstask.FieldProps: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field props", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &mpt.Props); err != nil { + return fmt.Errorf("unmarshal field props: %w", err) + } + } + default: + mpt.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the MediaProcessTask. +// This includes values selected through modifiers, order, etc. +func (mpt *MediaProcessTask) Value(name string) (ent.Value, error) { + return mpt.selectValues.Get(name) +} + +// Update returns a builder for updating this MediaProcessTask. +// Note that you need to call MediaProcessTask.Unwrap() before calling this method if this MediaProcessTask +// was returned from a transaction, and the transaction was committed or rolled back. +func (mpt *MediaProcessTask) Update() *MediaProcessTaskUpdateOne { + return NewMediaProcessTaskClient(mpt.config).UpdateOne(mpt) +} + +// Unwrap unwraps the MediaProcessTask entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (mpt *MediaProcessTask) Unwrap() *MediaProcessTask { + _tx, ok := mpt.config.driver.(*txDriver) + if !ok { + panic("ent: MediaProcessTask is not a transactional entity") + } + mpt.config.driver = _tx.drv + return mpt +} + +// String implements the fmt.Stringer. +func (mpt *MediaProcessTask) String() string { + var builder strings.Builder + builder.WriteString("MediaProcessTask(") + builder.WriteString(fmt.Sprintf("id=%v, ", mpt.ID)) + builder.WriteString("created_at=") + builder.WriteString(mpt.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("updated_at=") + builder.WriteString(mpt.UpdatedAt.Format(time.ANSIC)) + builder.WriteString(", ") + if v := mpt.DeletedAt; v != nil { + builder.WriteString("deleted_at=") + builder.WriteString(v.Format(time.ANSIC)) + } + builder.WriteString(", ") + builder.WriteString("media_type=") + builder.WriteString(fmt.Sprintf("%v", mpt.MediaType)) + builder.WriteString(", ") + builder.WriteString("status=") + builder.WriteString(fmt.Sprintf("%v", mpt.Status)) + builder.WriteString(", ") + builder.WriteString("entity_id=") + builder.WriteString(fmt.Sprintf("%v", mpt.EntityID)) + builder.WriteString(", ") + builder.WriteString("file_id=") + builder.WriteString(fmt.Sprintf("%v", mpt.FileID)) + builder.WriteString(", ") + builder.WriteString("owner_id=") + builder.WriteString(fmt.Sprintf("%v", mpt.OwnerID)) + builder.WriteString(", ") + builder.WriteString("attempts=") + builder.WriteString(fmt.Sprintf("%v", mpt.Attempts)) + builder.WriteString(", ") + builder.WriteString("error=") + builder.WriteString(mpt.Error) + builder.WriteString(", ") + builder.WriteString("result_size=") + builder.WriteString(fmt.Sprintf("%v", mpt.ResultSize)) + builder.WriteString(", ") + builder.WriteString("props=") + builder.WriteString(fmt.Sprintf("%v", mpt.Props)) + builder.WriteByte(')') + return builder.String() +} + +// MediaProcessTasks is a parsable slice of MediaProcessTask. +type MediaProcessTasks []*MediaProcessTask diff --git a/ent/mediaprocesstask/mediaprocesstask.go b/ent/mediaprocesstask/mediaprocesstask.go new file mode 100644 index 00000000..6f8c3c94 --- /dev/null +++ b/ent/mediaprocesstask/mediaprocesstask.go @@ -0,0 +1,207 @@ +// Code generated by ent, DO NOT EDIT. + +package mediaprocesstask + +import ( + "fmt" + "time" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" +) + +const ( + // Label holds the string label denoting the mediaprocesstask type in the database. + Label = "media_process_task" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldUpdatedAt holds the string denoting the updated_at field in the database. + FieldUpdatedAt = "updated_at" + // FieldDeletedAt holds the string denoting the deleted_at field in the database. + FieldDeletedAt = "deleted_at" + // FieldMediaType holds the string denoting the media_type field in the database. + FieldMediaType = "media_type" + // FieldStatus holds the string denoting the status field in the database. + FieldStatus = "status" + // FieldEntityID holds the string denoting the entity_id field in the database. + FieldEntityID = "entity_id" + // FieldFileID holds the string denoting the file_id field in the database. + FieldFileID = "file_id" + // FieldOwnerID holds the string denoting the owner_id field in the database. + FieldOwnerID = "owner_id" + // FieldAttempts holds the string denoting the attempts field in the database. + FieldAttempts = "attempts" + // FieldError holds the string denoting the error field in the database. + FieldError = "error" + // FieldResultSize holds the string denoting the result_size field in the database. + FieldResultSize = "result_size" + // FieldProps holds the string denoting the props field in the database. + FieldProps = "props" + // Table holds the table name of the mediaprocesstask in the database. + Table = "media_process_tasks" +) + +// Columns holds all SQL columns for mediaprocesstask fields. +var Columns = []string{ + FieldID, + FieldCreatedAt, + FieldUpdatedAt, + FieldDeletedAt, + FieldMediaType, + FieldStatus, + FieldEntityID, + FieldFileID, + FieldOwnerID, + FieldAttempts, + FieldError, + FieldResultSize, + FieldProps, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/cloudreve/Cloudreve/v4/ent/runtime" +var ( + Hooks [1]ent.Hook + Interceptors [1]ent.Interceptor + // DefaultCreatedAt holds the default value on creation for the "created_at" field. + DefaultCreatedAt func() time.Time + // DefaultUpdatedAt holds the default value on creation for the "updated_at" field. + DefaultUpdatedAt func() time.Time + // UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field. + UpdateDefaultUpdatedAt func() time.Time + // DefaultAttempts holds the default value on creation for the "attempts" field. + DefaultAttempts int +) + +// MediaType defines the type for the "media_type" enum field. +type MediaType string + +// MediaTypeImage is the default value of the MediaType enum. +const DefaultMediaType = MediaTypeImage + +// MediaType values. +const ( + MediaTypeImage MediaType = "image" + MediaTypeVideo MediaType = "video" +) + +func (mt MediaType) String() string { + return string(mt) +} + +// MediaTypeValidator is a validator for the "media_type" field enum values. It is called by the builders before save. +func MediaTypeValidator(mt MediaType) error { + switch mt { + case MediaTypeImage, MediaTypeVideo: + return nil + default: + return fmt.Errorf("mediaprocesstask: invalid enum value for media_type field: %q", mt) + } +} + +// Status defines the type for the "status" enum field. +type Status string + +// StatusPending is the default value of the Status enum. +const DefaultStatus = StatusPending + +// Status values. +const ( + StatusPending Status = "pending" + StatusProcessing Status = "processing" + StatusDone Status = "done" + StatusFailed Status = "failed" + StatusSkipped Status = "skipped" +) + +func (s Status) String() string { + return string(s) +} + +// StatusValidator is a validator for the "status" field enum values. It is called by the builders before save. +func StatusValidator(s Status) error { + switch s { + case StatusPending, StatusProcessing, StatusDone, StatusFailed, StatusSkipped: + return nil + default: + return fmt.Errorf("mediaprocesstask: invalid enum value for status field: %q", s) + } +} + +// OrderOption defines the ordering options for the MediaProcessTask queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByCreatedAt orders the results by the created_at field. +func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldCreatedAt, opts...).ToFunc() +} + +// ByUpdatedAt orders the results by the updated_at field. +func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc() +} + +// ByDeletedAt orders the results by the deleted_at field. +func ByDeletedAt(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldDeletedAt, opts...).ToFunc() +} + +// ByMediaType orders the results by the media_type field. +func ByMediaType(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldMediaType, opts...).ToFunc() +} + +// ByStatus orders the results by the status field. +func ByStatus(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldStatus, opts...).ToFunc() +} + +// ByEntityID orders the results by the entity_id field. +func ByEntityID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldEntityID, opts...).ToFunc() +} + +// ByFileID orders the results by the file_id field. +func ByFileID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldFileID, opts...).ToFunc() +} + +// ByOwnerID orders the results by the owner_id field. +func ByOwnerID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldOwnerID, opts...).ToFunc() +} + +// ByAttempts orders the results by the attempts field. +func ByAttempts(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldAttempts, opts...).ToFunc() +} + +// ByError orders the results by the error field. +func ByError(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldError, opts...).ToFunc() +} + +// ByResultSize orders the results by the result_size field. +func ByResultSize(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldResultSize, opts...).ToFunc() +} diff --git a/ent/mediaprocesstask/where.go b/ent/mediaprocesstask/where.go new file mode 100644 index 00000000..c11b9d0e --- /dev/null +++ b/ent/mediaprocesstask/where.go @@ -0,0 +1,590 @@ +// Code generated by ent, DO NOT EDIT. + +package mediaprocesstask + +import ( + "time" + + "entgo.io/ent/dialect/sql" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLTE(FieldID, id)) +} + +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldCreatedAt, v)) +} + +// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ. +func UpdatedAt(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// DeletedAt applies equality check predicate on the "deleted_at" field. It's identical to DeletedAtEQ. +func DeletedAt(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldDeletedAt, v)) +} + +// EntityID applies equality check predicate on the "entity_id" field. It's identical to EntityIDEQ. +func EntityID(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldEntityID, v)) +} + +// FileID applies equality check predicate on the "file_id" field. It's identical to FileIDEQ. +func FileID(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldFileID, v)) +} + +// OwnerID applies equality check predicate on the "owner_id" field. It's identical to OwnerIDEQ. +func OwnerID(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldOwnerID, v)) +} + +// Attempts applies equality check predicate on the "attempts" field. It's identical to AttemptsEQ. +func Attempts(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldAttempts, v)) +} + +// Error applies equality check predicate on the "error" field. It's identical to ErrorEQ. +func Error(v string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldError, v)) +} + +// ResultSize applies equality check predicate on the "result_size" field. It's identical to ResultSizeEQ. +func ResultSize(v int64) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldResultSize, v)) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldCreatedAt, v)) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNEQ(FieldCreatedAt, v)) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIn(FieldCreatedAt, vs...)) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotIn(FieldCreatedAt, vs...)) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGT(FieldCreatedAt, v)) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGTE(FieldCreatedAt, v)) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLT(FieldCreatedAt, v)) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLTE(FieldCreatedAt, v)) +} + +// UpdatedAtEQ applies the EQ predicate on the "updated_at" field. +func UpdatedAtEQ(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field. +func UpdatedAtNEQ(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNEQ(FieldUpdatedAt, v)) +} + +// UpdatedAtIn applies the In predicate on the "updated_at" field. +func UpdatedAtIn(vs ...time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field. +func UpdatedAtNotIn(vs ...time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotIn(FieldUpdatedAt, vs...)) +} + +// UpdatedAtGT applies the GT predicate on the "updated_at" field. +func UpdatedAtGT(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGT(FieldUpdatedAt, v)) +} + +// UpdatedAtGTE applies the GTE predicate on the "updated_at" field. +func UpdatedAtGTE(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGTE(FieldUpdatedAt, v)) +} + +// UpdatedAtLT applies the LT predicate on the "updated_at" field. +func UpdatedAtLT(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLT(FieldUpdatedAt, v)) +} + +// UpdatedAtLTE applies the LTE predicate on the "updated_at" field. +func UpdatedAtLTE(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLTE(FieldUpdatedAt, v)) +} + +// DeletedAtEQ applies the EQ predicate on the "deleted_at" field. +func DeletedAtEQ(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldDeletedAt, v)) +} + +// DeletedAtNEQ applies the NEQ predicate on the "deleted_at" field. +func DeletedAtNEQ(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNEQ(FieldDeletedAt, v)) +} + +// DeletedAtIn applies the In predicate on the "deleted_at" field. +func DeletedAtIn(vs ...time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIn(FieldDeletedAt, vs...)) +} + +// DeletedAtNotIn applies the NotIn predicate on the "deleted_at" field. +func DeletedAtNotIn(vs ...time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotIn(FieldDeletedAt, vs...)) +} + +// DeletedAtGT applies the GT predicate on the "deleted_at" field. +func DeletedAtGT(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGT(FieldDeletedAt, v)) +} + +// DeletedAtGTE applies the GTE predicate on the "deleted_at" field. +func DeletedAtGTE(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGTE(FieldDeletedAt, v)) +} + +// DeletedAtLT applies the LT predicate on the "deleted_at" field. +func DeletedAtLT(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLT(FieldDeletedAt, v)) +} + +// DeletedAtLTE applies the LTE predicate on the "deleted_at" field. +func DeletedAtLTE(v time.Time) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLTE(FieldDeletedAt, v)) +} + +// DeletedAtIsNil applies the IsNil predicate on the "deleted_at" field. +func DeletedAtIsNil() predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIsNull(FieldDeletedAt)) +} + +// DeletedAtNotNil applies the NotNil predicate on the "deleted_at" field. +func DeletedAtNotNil() predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotNull(FieldDeletedAt)) +} + +// MediaTypeEQ applies the EQ predicate on the "media_type" field. +func MediaTypeEQ(v MediaType) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldMediaType, v)) +} + +// MediaTypeNEQ applies the NEQ predicate on the "media_type" field. +func MediaTypeNEQ(v MediaType) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNEQ(FieldMediaType, v)) +} + +// MediaTypeIn applies the In predicate on the "media_type" field. +func MediaTypeIn(vs ...MediaType) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIn(FieldMediaType, vs...)) +} + +// MediaTypeNotIn applies the NotIn predicate on the "media_type" field. +func MediaTypeNotIn(vs ...MediaType) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotIn(FieldMediaType, vs...)) +} + +// StatusEQ applies the EQ predicate on the "status" field. +func StatusEQ(v Status) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldStatus, v)) +} + +// StatusNEQ applies the NEQ predicate on the "status" field. +func StatusNEQ(v Status) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNEQ(FieldStatus, v)) +} + +// StatusIn applies the In predicate on the "status" field. +func StatusIn(vs ...Status) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIn(FieldStatus, vs...)) +} + +// StatusNotIn applies the NotIn predicate on the "status" field. +func StatusNotIn(vs ...Status) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotIn(FieldStatus, vs...)) +} + +// EntityIDEQ applies the EQ predicate on the "entity_id" field. +func EntityIDEQ(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldEntityID, v)) +} + +// EntityIDNEQ applies the NEQ predicate on the "entity_id" field. +func EntityIDNEQ(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNEQ(FieldEntityID, v)) +} + +// EntityIDIn applies the In predicate on the "entity_id" field. +func EntityIDIn(vs ...int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIn(FieldEntityID, vs...)) +} + +// EntityIDNotIn applies the NotIn predicate on the "entity_id" field. +func EntityIDNotIn(vs ...int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotIn(FieldEntityID, vs...)) +} + +// EntityIDGT applies the GT predicate on the "entity_id" field. +func EntityIDGT(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGT(FieldEntityID, v)) +} + +// EntityIDGTE applies the GTE predicate on the "entity_id" field. +func EntityIDGTE(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGTE(FieldEntityID, v)) +} + +// EntityIDLT applies the LT predicate on the "entity_id" field. +func EntityIDLT(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLT(FieldEntityID, v)) +} + +// EntityIDLTE applies the LTE predicate on the "entity_id" field. +func EntityIDLTE(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLTE(FieldEntityID, v)) +} + +// FileIDEQ applies the EQ predicate on the "file_id" field. +func FileIDEQ(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldFileID, v)) +} + +// FileIDNEQ applies the NEQ predicate on the "file_id" field. +func FileIDNEQ(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNEQ(FieldFileID, v)) +} + +// FileIDIn applies the In predicate on the "file_id" field. +func FileIDIn(vs ...int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIn(FieldFileID, vs...)) +} + +// FileIDNotIn applies the NotIn predicate on the "file_id" field. +func FileIDNotIn(vs ...int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotIn(FieldFileID, vs...)) +} + +// FileIDGT applies the GT predicate on the "file_id" field. +func FileIDGT(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGT(FieldFileID, v)) +} + +// FileIDGTE applies the GTE predicate on the "file_id" field. +func FileIDGTE(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGTE(FieldFileID, v)) +} + +// FileIDLT applies the LT predicate on the "file_id" field. +func FileIDLT(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLT(FieldFileID, v)) +} + +// FileIDLTE applies the LTE predicate on the "file_id" field. +func FileIDLTE(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLTE(FieldFileID, v)) +} + +// FileIDIsNil applies the IsNil predicate on the "file_id" field. +func FileIDIsNil() predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIsNull(FieldFileID)) +} + +// FileIDNotNil applies the NotNil predicate on the "file_id" field. +func FileIDNotNil() predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotNull(FieldFileID)) +} + +// OwnerIDEQ applies the EQ predicate on the "owner_id" field. +func OwnerIDEQ(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldOwnerID, v)) +} + +// OwnerIDNEQ applies the NEQ predicate on the "owner_id" field. +func OwnerIDNEQ(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNEQ(FieldOwnerID, v)) +} + +// OwnerIDIn applies the In predicate on the "owner_id" field. +func OwnerIDIn(vs ...int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIn(FieldOwnerID, vs...)) +} + +// OwnerIDNotIn applies the NotIn predicate on the "owner_id" field. +func OwnerIDNotIn(vs ...int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotIn(FieldOwnerID, vs...)) +} + +// OwnerIDGT applies the GT predicate on the "owner_id" field. +func OwnerIDGT(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGT(FieldOwnerID, v)) +} + +// OwnerIDGTE applies the GTE predicate on the "owner_id" field. +func OwnerIDGTE(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGTE(FieldOwnerID, v)) +} + +// OwnerIDLT applies the LT predicate on the "owner_id" field. +func OwnerIDLT(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLT(FieldOwnerID, v)) +} + +// OwnerIDLTE applies the LTE predicate on the "owner_id" field. +func OwnerIDLTE(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLTE(FieldOwnerID, v)) +} + +// AttemptsEQ applies the EQ predicate on the "attempts" field. +func AttemptsEQ(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldAttempts, v)) +} + +// AttemptsNEQ applies the NEQ predicate on the "attempts" field. +func AttemptsNEQ(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNEQ(FieldAttempts, v)) +} + +// AttemptsIn applies the In predicate on the "attempts" field. +func AttemptsIn(vs ...int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIn(FieldAttempts, vs...)) +} + +// AttemptsNotIn applies the NotIn predicate on the "attempts" field. +func AttemptsNotIn(vs ...int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotIn(FieldAttempts, vs...)) +} + +// AttemptsGT applies the GT predicate on the "attempts" field. +func AttemptsGT(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGT(FieldAttempts, v)) +} + +// AttemptsGTE applies the GTE predicate on the "attempts" field. +func AttemptsGTE(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGTE(FieldAttempts, v)) +} + +// AttemptsLT applies the LT predicate on the "attempts" field. +func AttemptsLT(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLT(FieldAttempts, v)) +} + +// AttemptsLTE applies the LTE predicate on the "attempts" field. +func AttemptsLTE(v int) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLTE(FieldAttempts, v)) +} + +// ErrorEQ applies the EQ predicate on the "error" field. +func ErrorEQ(v string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldError, v)) +} + +// ErrorNEQ applies the NEQ predicate on the "error" field. +func ErrorNEQ(v string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNEQ(FieldError, v)) +} + +// ErrorIn applies the In predicate on the "error" field. +func ErrorIn(vs ...string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIn(FieldError, vs...)) +} + +// ErrorNotIn applies the NotIn predicate on the "error" field. +func ErrorNotIn(vs ...string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotIn(FieldError, vs...)) +} + +// ErrorGT applies the GT predicate on the "error" field. +func ErrorGT(v string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGT(FieldError, v)) +} + +// ErrorGTE applies the GTE predicate on the "error" field. +func ErrorGTE(v string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGTE(FieldError, v)) +} + +// ErrorLT applies the LT predicate on the "error" field. +func ErrorLT(v string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLT(FieldError, v)) +} + +// ErrorLTE applies the LTE predicate on the "error" field. +func ErrorLTE(v string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLTE(FieldError, v)) +} + +// ErrorContains applies the Contains predicate on the "error" field. +func ErrorContains(v string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldContains(FieldError, v)) +} + +// ErrorHasPrefix applies the HasPrefix predicate on the "error" field. +func ErrorHasPrefix(v string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldHasPrefix(FieldError, v)) +} + +// ErrorHasSuffix applies the HasSuffix predicate on the "error" field. +func ErrorHasSuffix(v string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldHasSuffix(FieldError, v)) +} + +// ErrorIsNil applies the IsNil predicate on the "error" field. +func ErrorIsNil() predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIsNull(FieldError)) +} + +// ErrorNotNil applies the NotNil predicate on the "error" field. +func ErrorNotNil() predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotNull(FieldError)) +} + +// ErrorEqualFold applies the EqualFold predicate on the "error" field. +func ErrorEqualFold(v string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEqualFold(FieldError, v)) +} + +// ErrorContainsFold applies the ContainsFold predicate on the "error" field. +func ErrorContainsFold(v string) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldContainsFold(FieldError, v)) +} + +// ResultSizeEQ applies the EQ predicate on the "result_size" field. +func ResultSizeEQ(v int64) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldEQ(FieldResultSize, v)) +} + +// ResultSizeNEQ applies the NEQ predicate on the "result_size" field. +func ResultSizeNEQ(v int64) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNEQ(FieldResultSize, v)) +} + +// ResultSizeIn applies the In predicate on the "result_size" field. +func ResultSizeIn(vs ...int64) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIn(FieldResultSize, vs...)) +} + +// ResultSizeNotIn applies the NotIn predicate on the "result_size" field. +func ResultSizeNotIn(vs ...int64) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotIn(FieldResultSize, vs...)) +} + +// ResultSizeGT applies the GT predicate on the "result_size" field. +func ResultSizeGT(v int64) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGT(FieldResultSize, v)) +} + +// ResultSizeGTE applies the GTE predicate on the "result_size" field. +func ResultSizeGTE(v int64) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldGTE(FieldResultSize, v)) +} + +// ResultSizeLT applies the LT predicate on the "result_size" field. +func ResultSizeLT(v int64) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLT(FieldResultSize, v)) +} + +// ResultSizeLTE applies the LTE predicate on the "result_size" field. +func ResultSizeLTE(v int64) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldLTE(FieldResultSize, v)) +} + +// ResultSizeIsNil applies the IsNil predicate on the "result_size" field. +func ResultSizeIsNil() predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIsNull(FieldResultSize)) +} + +// ResultSizeNotNil applies the NotNil predicate on the "result_size" field. +func ResultSizeNotNil() predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotNull(FieldResultSize)) +} + +// PropsIsNil applies the IsNil predicate on the "props" field. +func PropsIsNil() predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldIsNull(FieldProps)) +} + +// PropsNotNil applies the NotNil predicate on the "props" field. +func PropsNotNil() predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.FieldNotNull(FieldProps)) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.MediaProcessTask) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.MediaProcessTask) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.MediaProcessTask) predicate.MediaProcessTask { + return predicate.MediaProcessTask(sql.NotPredicates(p)) +} diff --git a/ent/mediaprocesstask_create.go b/ent/mediaprocesstask_create.go new file mode 100644 index 00000000..98a4ecb1 --- /dev/null +++ b/ent/mediaprocesstask_create.go @@ -0,0 +1,1325 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" + "github.com/cloudreve/Cloudreve/v4/inventory/types" +) + +// MediaProcessTaskCreate is the builder for creating a MediaProcessTask entity. +type MediaProcessTaskCreate struct { + config + mutation *MediaProcessTaskMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetCreatedAt sets the "created_at" field. +func (mptc *MediaProcessTaskCreate) SetCreatedAt(t time.Time) *MediaProcessTaskCreate { + mptc.mutation.SetCreatedAt(t) + return mptc +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (mptc *MediaProcessTaskCreate) SetNillableCreatedAt(t *time.Time) *MediaProcessTaskCreate { + if t != nil { + mptc.SetCreatedAt(*t) + } + return mptc +} + +// SetUpdatedAt sets the "updated_at" field. +func (mptc *MediaProcessTaskCreate) SetUpdatedAt(t time.Time) *MediaProcessTaskCreate { + mptc.mutation.SetUpdatedAt(t) + return mptc +} + +// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil. +func (mptc *MediaProcessTaskCreate) SetNillableUpdatedAt(t *time.Time) *MediaProcessTaskCreate { + if t != nil { + mptc.SetUpdatedAt(*t) + } + return mptc +} + +// SetDeletedAt sets the "deleted_at" field. +func (mptc *MediaProcessTaskCreate) SetDeletedAt(t time.Time) *MediaProcessTaskCreate { + mptc.mutation.SetDeletedAt(t) + return mptc +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (mptc *MediaProcessTaskCreate) SetNillableDeletedAt(t *time.Time) *MediaProcessTaskCreate { + if t != nil { + mptc.SetDeletedAt(*t) + } + return mptc +} + +// SetMediaType sets the "media_type" field. +func (mptc *MediaProcessTaskCreate) SetMediaType(mt mediaprocesstask.MediaType) *MediaProcessTaskCreate { + mptc.mutation.SetMediaType(mt) + return mptc +} + +// SetNillableMediaType sets the "media_type" field if the given value is not nil. +func (mptc *MediaProcessTaskCreate) SetNillableMediaType(mt *mediaprocesstask.MediaType) *MediaProcessTaskCreate { + if mt != nil { + mptc.SetMediaType(*mt) + } + return mptc +} + +// SetStatus sets the "status" field. +func (mptc *MediaProcessTaskCreate) SetStatus(m mediaprocesstask.Status) *MediaProcessTaskCreate { + mptc.mutation.SetStatus(m) + return mptc +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (mptc *MediaProcessTaskCreate) SetNillableStatus(m *mediaprocesstask.Status) *MediaProcessTaskCreate { + if m != nil { + mptc.SetStatus(*m) + } + return mptc +} + +// SetEntityID sets the "entity_id" field. +func (mptc *MediaProcessTaskCreate) SetEntityID(i int) *MediaProcessTaskCreate { + mptc.mutation.SetEntityID(i) + return mptc +} + +// SetFileID sets the "file_id" field. +func (mptc *MediaProcessTaskCreate) SetFileID(i int) *MediaProcessTaskCreate { + mptc.mutation.SetFileID(i) + return mptc +} + +// SetNillableFileID sets the "file_id" field if the given value is not nil. +func (mptc *MediaProcessTaskCreate) SetNillableFileID(i *int) *MediaProcessTaskCreate { + if i != nil { + mptc.SetFileID(*i) + } + return mptc +} + +// SetOwnerID sets the "owner_id" field. +func (mptc *MediaProcessTaskCreate) SetOwnerID(i int) *MediaProcessTaskCreate { + mptc.mutation.SetOwnerID(i) + return mptc +} + +// SetAttempts sets the "attempts" field. +func (mptc *MediaProcessTaskCreate) SetAttempts(i int) *MediaProcessTaskCreate { + mptc.mutation.SetAttempts(i) + return mptc +} + +// SetNillableAttempts sets the "attempts" field if the given value is not nil. +func (mptc *MediaProcessTaskCreate) SetNillableAttempts(i *int) *MediaProcessTaskCreate { + if i != nil { + mptc.SetAttempts(*i) + } + return mptc +} + +// SetError sets the "error" field. +func (mptc *MediaProcessTaskCreate) SetError(s string) *MediaProcessTaskCreate { + mptc.mutation.SetError(s) + return mptc +} + +// SetNillableError sets the "error" field if the given value is not nil. +func (mptc *MediaProcessTaskCreate) SetNillableError(s *string) *MediaProcessTaskCreate { + if s != nil { + mptc.SetError(*s) + } + return mptc +} + +// SetResultSize sets the "result_size" field. +func (mptc *MediaProcessTaskCreate) SetResultSize(i int64) *MediaProcessTaskCreate { + mptc.mutation.SetResultSize(i) + return mptc +} + +// SetNillableResultSize sets the "result_size" field if the given value is not nil. +func (mptc *MediaProcessTaskCreate) SetNillableResultSize(i *int64) *MediaProcessTaskCreate { + if i != nil { + mptc.SetResultSize(*i) + } + return mptc +} + +// SetProps sets the "props" field. +func (mptc *MediaProcessTaskCreate) SetProps(tptp *types.MediaProcessTaskProps) *MediaProcessTaskCreate { + mptc.mutation.SetProps(tptp) + return mptc +} + +// Mutation returns the MediaProcessTaskMutation object of the builder. +func (mptc *MediaProcessTaskCreate) Mutation() *MediaProcessTaskMutation { + return mptc.mutation +} + +// Save creates the MediaProcessTask in the database. +func (mptc *MediaProcessTaskCreate) Save(ctx context.Context) (*MediaProcessTask, error) { + if err := mptc.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, mptc.sqlSave, mptc.mutation, mptc.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (mptc *MediaProcessTaskCreate) SaveX(ctx context.Context) *MediaProcessTask { + v, err := mptc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (mptc *MediaProcessTaskCreate) Exec(ctx context.Context) error { + _, err := mptc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (mptc *MediaProcessTaskCreate) ExecX(ctx context.Context) { + if err := mptc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (mptc *MediaProcessTaskCreate) defaults() error { + if _, ok := mptc.mutation.CreatedAt(); !ok { + if mediaprocesstask.DefaultCreatedAt == nil { + return fmt.Errorf("ent: uninitialized mediaprocesstask.DefaultCreatedAt (forgotten import ent/runtime?)") + } + v := mediaprocesstask.DefaultCreatedAt() + mptc.mutation.SetCreatedAt(v) + } + if _, ok := mptc.mutation.UpdatedAt(); !ok { + if mediaprocesstask.DefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized mediaprocesstask.DefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := mediaprocesstask.DefaultUpdatedAt() + mptc.mutation.SetUpdatedAt(v) + } + if _, ok := mptc.mutation.MediaType(); !ok { + v := mediaprocesstask.DefaultMediaType + mptc.mutation.SetMediaType(v) + } + if _, ok := mptc.mutation.Status(); !ok { + v := mediaprocesstask.DefaultStatus + mptc.mutation.SetStatus(v) + } + if _, ok := mptc.mutation.Attempts(); !ok { + v := mediaprocesstask.DefaultAttempts + mptc.mutation.SetAttempts(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (mptc *MediaProcessTaskCreate) check() error { + if _, ok := mptc.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "MediaProcessTask.created_at"`)} + } + if _, ok := mptc.mutation.UpdatedAt(); !ok { + return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "MediaProcessTask.updated_at"`)} + } + if _, ok := mptc.mutation.MediaType(); !ok { + return &ValidationError{Name: "media_type", err: errors.New(`ent: missing required field "MediaProcessTask.media_type"`)} + } + if v, ok := mptc.mutation.MediaType(); ok { + if err := mediaprocesstask.MediaTypeValidator(v); err != nil { + return &ValidationError{Name: "media_type", err: fmt.Errorf(`ent: validator failed for field "MediaProcessTask.media_type": %w`, err)} + } + } + if _, ok := mptc.mutation.Status(); !ok { + return &ValidationError{Name: "status", err: errors.New(`ent: missing required field "MediaProcessTask.status"`)} + } + if v, ok := mptc.mutation.Status(); ok { + if err := mediaprocesstask.StatusValidator(v); err != nil { + return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "MediaProcessTask.status": %w`, err)} + } + } + if _, ok := mptc.mutation.EntityID(); !ok { + return &ValidationError{Name: "entity_id", err: errors.New(`ent: missing required field "MediaProcessTask.entity_id"`)} + } + if _, ok := mptc.mutation.OwnerID(); !ok { + return &ValidationError{Name: "owner_id", err: errors.New(`ent: missing required field "MediaProcessTask.owner_id"`)} + } + if _, ok := mptc.mutation.Attempts(); !ok { + return &ValidationError{Name: "attempts", err: errors.New(`ent: missing required field "MediaProcessTask.attempts"`)} + } + return nil +} + +func (mptc *MediaProcessTaskCreate) sqlSave(ctx context.Context) (*MediaProcessTask, error) { + if err := mptc.check(); err != nil { + return nil, err + } + _node, _spec := mptc.createSpec() + if err := sqlgraph.CreateNode(ctx, mptc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + id := _spec.ID.Value.(int64) + _node.ID = int(id) + mptc.mutation.id = &_node.ID + mptc.mutation.done = true + return _node, nil +} + +func (mptc *MediaProcessTaskCreate) createSpec() (*MediaProcessTask, *sqlgraph.CreateSpec) { + var ( + _node = &MediaProcessTask{config: mptc.config} + _spec = sqlgraph.NewCreateSpec(mediaprocesstask.Table, sqlgraph.NewFieldSpec(mediaprocesstask.FieldID, field.TypeInt)) + ) + + if id, ok := mptc.mutation.ID(); ok { + _node.ID = id + id64 := int64(id) + _spec.ID.Value = id64 + } + + _spec.OnConflict = mptc.conflict + if value, ok := mptc.mutation.CreatedAt(); ok { + _spec.SetField(mediaprocesstask.FieldCreatedAt, field.TypeTime, value) + _node.CreatedAt = value + } + if value, ok := mptc.mutation.UpdatedAt(); ok { + _spec.SetField(mediaprocesstask.FieldUpdatedAt, field.TypeTime, value) + _node.UpdatedAt = value + } + if value, ok := mptc.mutation.DeletedAt(); ok { + _spec.SetField(mediaprocesstask.FieldDeletedAt, field.TypeTime, value) + _node.DeletedAt = &value + } + if value, ok := mptc.mutation.MediaType(); ok { + _spec.SetField(mediaprocesstask.FieldMediaType, field.TypeEnum, value) + _node.MediaType = value + } + if value, ok := mptc.mutation.Status(); ok { + _spec.SetField(mediaprocesstask.FieldStatus, field.TypeEnum, value) + _node.Status = value + } + if value, ok := mptc.mutation.EntityID(); ok { + _spec.SetField(mediaprocesstask.FieldEntityID, field.TypeInt, value) + _node.EntityID = value + } + if value, ok := mptc.mutation.FileID(); ok { + _spec.SetField(mediaprocesstask.FieldFileID, field.TypeInt, value) + _node.FileID = value + } + if value, ok := mptc.mutation.OwnerID(); ok { + _spec.SetField(mediaprocesstask.FieldOwnerID, field.TypeInt, value) + _node.OwnerID = value + } + if value, ok := mptc.mutation.Attempts(); ok { + _spec.SetField(mediaprocesstask.FieldAttempts, field.TypeInt, value) + _node.Attempts = value + } + if value, ok := mptc.mutation.Error(); ok { + _spec.SetField(mediaprocesstask.FieldError, field.TypeString, value) + _node.Error = value + } + if value, ok := mptc.mutation.ResultSize(); ok { + _spec.SetField(mediaprocesstask.FieldResultSize, field.TypeInt64, value) + _node.ResultSize = value + } + if value, ok := mptc.mutation.Props(); ok { + _spec.SetField(mediaprocesstask.FieldProps, field.TypeJSON, value) + _node.Props = value + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.MediaProcessTask.Create(). +// SetCreatedAt(v). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.MediaProcessTaskUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (mptc *MediaProcessTaskCreate) OnConflict(opts ...sql.ConflictOption) *MediaProcessTaskUpsertOne { + mptc.conflict = opts + return &MediaProcessTaskUpsertOne{ + create: mptc, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.MediaProcessTask.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (mptc *MediaProcessTaskCreate) OnConflictColumns(columns ...string) *MediaProcessTaskUpsertOne { + mptc.conflict = append(mptc.conflict, sql.ConflictColumns(columns...)) + return &MediaProcessTaskUpsertOne{ + create: mptc, + } +} + +type ( + // MediaProcessTaskUpsertOne is the builder for "upsert"-ing + // one MediaProcessTask node. + MediaProcessTaskUpsertOne struct { + create *MediaProcessTaskCreate + } + + // MediaProcessTaskUpsert is the "OnConflict" setter. + MediaProcessTaskUpsert struct { + *sql.UpdateSet + } +) + +// SetUpdatedAt sets the "updated_at" field. +func (u *MediaProcessTaskUpsert) SetUpdatedAt(v time.Time) *MediaProcessTaskUpsert { + u.Set(mediaprocesstask.FieldUpdatedAt, v) + return u +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *MediaProcessTaskUpsert) UpdateUpdatedAt() *MediaProcessTaskUpsert { + u.SetExcluded(mediaprocesstask.FieldUpdatedAt) + return u +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *MediaProcessTaskUpsert) SetDeletedAt(v time.Time) *MediaProcessTaskUpsert { + u.Set(mediaprocesstask.FieldDeletedAt, v) + return u +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *MediaProcessTaskUpsert) UpdateDeletedAt() *MediaProcessTaskUpsert { + u.SetExcluded(mediaprocesstask.FieldDeletedAt) + return u +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *MediaProcessTaskUpsert) ClearDeletedAt() *MediaProcessTaskUpsert { + u.SetNull(mediaprocesstask.FieldDeletedAt) + return u +} + +// SetMediaType sets the "media_type" field. +func (u *MediaProcessTaskUpsert) SetMediaType(v mediaprocesstask.MediaType) *MediaProcessTaskUpsert { + u.Set(mediaprocesstask.FieldMediaType, v) + return u +} + +// UpdateMediaType sets the "media_type" field to the value that was provided on create. +func (u *MediaProcessTaskUpsert) UpdateMediaType() *MediaProcessTaskUpsert { + u.SetExcluded(mediaprocesstask.FieldMediaType) + return u +} + +// SetStatus sets the "status" field. +func (u *MediaProcessTaskUpsert) SetStatus(v mediaprocesstask.Status) *MediaProcessTaskUpsert { + u.Set(mediaprocesstask.FieldStatus, v) + return u +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *MediaProcessTaskUpsert) UpdateStatus() *MediaProcessTaskUpsert { + u.SetExcluded(mediaprocesstask.FieldStatus) + return u +} + +// SetEntityID sets the "entity_id" field. +func (u *MediaProcessTaskUpsert) SetEntityID(v int) *MediaProcessTaskUpsert { + u.Set(mediaprocesstask.FieldEntityID, v) + return u +} + +// UpdateEntityID sets the "entity_id" field to the value that was provided on create. +func (u *MediaProcessTaskUpsert) UpdateEntityID() *MediaProcessTaskUpsert { + u.SetExcluded(mediaprocesstask.FieldEntityID) + return u +} + +// AddEntityID adds v to the "entity_id" field. +func (u *MediaProcessTaskUpsert) AddEntityID(v int) *MediaProcessTaskUpsert { + u.Add(mediaprocesstask.FieldEntityID, v) + return u +} + +// SetFileID sets the "file_id" field. +func (u *MediaProcessTaskUpsert) SetFileID(v int) *MediaProcessTaskUpsert { + u.Set(mediaprocesstask.FieldFileID, v) + return u +} + +// UpdateFileID sets the "file_id" field to the value that was provided on create. +func (u *MediaProcessTaskUpsert) UpdateFileID() *MediaProcessTaskUpsert { + u.SetExcluded(mediaprocesstask.FieldFileID) + return u +} + +// AddFileID adds v to the "file_id" field. +func (u *MediaProcessTaskUpsert) AddFileID(v int) *MediaProcessTaskUpsert { + u.Add(mediaprocesstask.FieldFileID, v) + return u +} + +// ClearFileID clears the value of the "file_id" field. +func (u *MediaProcessTaskUpsert) ClearFileID() *MediaProcessTaskUpsert { + u.SetNull(mediaprocesstask.FieldFileID) + return u +} + +// SetOwnerID sets the "owner_id" field. +func (u *MediaProcessTaskUpsert) SetOwnerID(v int) *MediaProcessTaskUpsert { + u.Set(mediaprocesstask.FieldOwnerID, v) + return u +} + +// UpdateOwnerID sets the "owner_id" field to the value that was provided on create. +func (u *MediaProcessTaskUpsert) UpdateOwnerID() *MediaProcessTaskUpsert { + u.SetExcluded(mediaprocesstask.FieldOwnerID) + return u +} + +// AddOwnerID adds v to the "owner_id" field. +func (u *MediaProcessTaskUpsert) AddOwnerID(v int) *MediaProcessTaskUpsert { + u.Add(mediaprocesstask.FieldOwnerID, v) + return u +} + +// SetAttempts sets the "attempts" field. +func (u *MediaProcessTaskUpsert) SetAttempts(v int) *MediaProcessTaskUpsert { + u.Set(mediaprocesstask.FieldAttempts, v) + return u +} + +// UpdateAttempts sets the "attempts" field to the value that was provided on create. +func (u *MediaProcessTaskUpsert) UpdateAttempts() *MediaProcessTaskUpsert { + u.SetExcluded(mediaprocesstask.FieldAttempts) + return u +} + +// AddAttempts adds v to the "attempts" field. +func (u *MediaProcessTaskUpsert) AddAttempts(v int) *MediaProcessTaskUpsert { + u.Add(mediaprocesstask.FieldAttempts, v) + return u +} + +// SetError sets the "error" field. +func (u *MediaProcessTaskUpsert) SetError(v string) *MediaProcessTaskUpsert { + u.Set(mediaprocesstask.FieldError, v) + return u +} + +// UpdateError sets the "error" field to the value that was provided on create. +func (u *MediaProcessTaskUpsert) UpdateError() *MediaProcessTaskUpsert { + u.SetExcluded(mediaprocesstask.FieldError) + return u +} + +// ClearError clears the value of the "error" field. +func (u *MediaProcessTaskUpsert) ClearError() *MediaProcessTaskUpsert { + u.SetNull(mediaprocesstask.FieldError) + return u +} + +// SetResultSize sets the "result_size" field. +func (u *MediaProcessTaskUpsert) SetResultSize(v int64) *MediaProcessTaskUpsert { + u.Set(mediaprocesstask.FieldResultSize, v) + return u +} + +// UpdateResultSize sets the "result_size" field to the value that was provided on create. +func (u *MediaProcessTaskUpsert) UpdateResultSize() *MediaProcessTaskUpsert { + u.SetExcluded(mediaprocesstask.FieldResultSize) + return u +} + +// AddResultSize adds v to the "result_size" field. +func (u *MediaProcessTaskUpsert) AddResultSize(v int64) *MediaProcessTaskUpsert { + u.Add(mediaprocesstask.FieldResultSize, v) + return u +} + +// ClearResultSize clears the value of the "result_size" field. +func (u *MediaProcessTaskUpsert) ClearResultSize() *MediaProcessTaskUpsert { + u.SetNull(mediaprocesstask.FieldResultSize) + return u +} + +// SetProps sets the "props" field. +func (u *MediaProcessTaskUpsert) SetProps(v *types.MediaProcessTaskProps) *MediaProcessTaskUpsert { + u.Set(mediaprocesstask.FieldProps, v) + return u +} + +// UpdateProps sets the "props" field to the value that was provided on create. +func (u *MediaProcessTaskUpsert) UpdateProps() *MediaProcessTaskUpsert { + u.SetExcluded(mediaprocesstask.FieldProps) + return u +} + +// ClearProps clears the value of the "props" field. +func (u *MediaProcessTaskUpsert) ClearProps() *MediaProcessTaskUpsert { + u.SetNull(mediaprocesstask.FieldProps) + return u +} + +// UpdateNewValues updates the mutable fields using the new values that were set on create. +// Using this option is equivalent to using: +// +// client.MediaProcessTask.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *MediaProcessTaskUpsertOne) UpdateNewValues() *MediaProcessTaskUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + if _, exists := u.create.mutation.CreatedAt(); exists { + s.SetIgnore(mediaprocesstask.FieldCreatedAt) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.MediaProcessTask.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *MediaProcessTaskUpsertOne) Ignore() *MediaProcessTaskUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *MediaProcessTaskUpsertOne) DoNothing() *MediaProcessTaskUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the MediaProcessTaskCreate.OnConflict +// documentation for more info. +func (u *MediaProcessTaskUpsertOne) Update(set func(*MediaProcessTaskUpsert)) *MediaProcessTaskUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&MediaProcessTaskUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *MediaProcessTaskUpsertOne) SetUpdatedAt(v time.Time) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertOne) UpdateUpdatedAt() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *MediaProcessTaskUpsertOne) SetDeletedAt(v time.Time) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertOne) UpdateDeletedAt() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *MediaProcessTaskUpsertOne) ClearDeletedAt() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.ClearDeletedAt() + }) +} + +// SetMediaType sets the "media_type" field. +func (u *MediaProcessTaskUpsertOne) SetMediaType(v mediaprocesstask.MediaType) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetMediaType(v) + }) +} + +// UpdateMediaType sets the "media_type" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertOne) UpdateMediaType() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateMediaType() + }) +} + +// SetStatus sets the "status" field. +func (u *MediaProcessTaskUpsertOne) SetStatus(v mediaprocesstask.Status) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetStatus(v) + }) +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertOne) UpdateStatus() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateStatus() + }) +} + +// SetEntityID sets the "entity_id" field. +func (u *MediaProcessTaskUpsertOne) SetEntityID(v int) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetEntityID(v) + }) +} + +// AddEntityID adds v to the "entity_id" field. +func (u *MediaProcessTaskUpsertOne) AddEntityID(v int) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.AddEntityID(v) + }) +} + +// UpdateEntityID sets the "entity_id" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertOne) UpdateEntityID() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateEntityID() + }) +} + +// SetFileID sets the "file_id" field. +func (u *MediaProcessTaskUpsertOne) SetFileID(v int) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetFileID(v) + }) +} + +// AddFileID adds v to the "file_id" field. +func (u *MediaProcessTaskUpsertOne) AddFileID(v int) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.AddFileID(v) + }) +} + +// UpdateFileID sets the "file_id" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertOne) UpdateFileID() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateFileID() + }) +} + +// ClearFileID clears the value of the "file_id" field. +func (u *MediaProcessTaskUpsertOne) ClearFileID() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.ClearFileID() + }) +} + +// SetOwnerID sets the "owner_id" field. +func (u *MediaProcessTaskUpsertOne) SetOwnerID(v int) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetOwnerID(v) + }) +} + +// AddOwnerID adds v to the "owner_id" field. +func (u *MediaProcessTaskUpsertOne) AddOwnerID(v int) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.AddOwnerID(v) + }) +} + +// UpdateOwnerID sets the "owner_id" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertOne) UpdateOwnerID() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateOwnerID() + }) +} + +// SetAttempts sets the "attempts" field. +func (u *MediaProcessTaskUpsertOne) SetAttempts(v int) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetAttempts(v) + }) +} + +// AddAttempts adds v to the "attempts" field. +func (u *MediaProcessTaskUpsertOne) AddAttempts(v int) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.AddAttempts(v) + }) +} + +// UpdateAttempts sets the "attempts" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertOne) UpdateAttempts() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateAttempts() + }) +} + +// SetError sets the "error" field. +func (u *MediaProcessTaskUpsertOne) SetError(v string) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetError(v) + }) +} + +// UpdateError sets the "error" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertOne) UpdateError() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateError() + }) +} + +// ClearError clears the value of the "error" field. +func (u *MediaProcessTaskUpsertOne) ClearError() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.ClearError() + }) +} + +// SetResultSize sets the "result_size" field. +func (u *MediaProcessTaskUpsertOne) SetResultSize(v int64) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetResultSize(v) + }) +} + +// AddResultSize adds v to the "result_size" field. +func (u *MediaProcessTaskUpsertOne) AddResultSize(v int64) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.AddResultSize(v) + }) +} + +// UpdateResultSize sets the "result_size" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertOne) UpdateResultSize() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateResultSize() + }) +} + +// ClearResultSize clears the value of the "result_size" field. +func (u *MediaProcessTaskUpsertOne) ClearResultSize() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.ClearResultSize() + }) +} + +// SetProps sets the "props" field. +func (u *MediaProcessTaskUpsertOne) SetProps(v *types.MediaProcessTaskProps) *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetProps(v) + }) +} + +// UpdateProps sets the "props" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertOne) UpdateProps() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateProps() + }) +} + +// ClearProps clears the value of the "props" field. +func (u *MediaProcessTaskUpsertOne) ClearProps() *MediaProcessTaskUpsertOne { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.ClearProps() + }) +} + +// Exec executes the query. +func (u *MediaProcessTaskUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for MediaProcessTaskCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *MediaProcessTaskUpsertOne) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} + +// Exec executes the UPSERT query and returns the inserted/updated ID. +func (u *MediaProcessTaskUpsertOne) ID(ctx context.Context) (id int, err error) { + node, err := u.create.Save(ctx) + if err != nil { + return id, err + } + return node.ID, nil +} + +// IDX is like ID, but panics if an error occurs. +func (u *MediaProcessTaskUpsertOne) IDX(ctx context.Context) int { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +func (m *MediaProcessTaskCreate) SetRawID(t int) *MediaProcessTaskCreate { + m.mutation.SetRawID(t) + return m +} + +// MediaProcessTaskCreateBulk is the builder for creating many MediaProcessTask entities in bulk. +type MediaProcessTaskCreateBulk struct { + config + err error + builders []*MediaProcessTaskCreate + conflict []sql.ConflictOption +} + +// Save creates the MediaProcessTask entities in the database. +func (mptcb *MediaProcessTaskCreateBulk) Save(ctx context.Context) ([]*MediaProcessTask, error) { + if mptcb.err != nil { + return nil, mptcb.err + } + specs := make([]*sqlgraph.CreateSpec, len(mptcb.builders)) + nodes := make([]*MediaProcessTask, len(mptcb.builders)) + mutators := make([]Mutator, len(mptcb.builders)) + for i := range mptcb.builders { + func(i int, root context.Context) { + builder := mptcb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*MediaProcessTaskMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, mptcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = mptcb.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, mptcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, mptcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (mptcb *MediaProcessTaskCreateBulk) SaveX(ctx context.Context) []*MediaProcessTask { + v, err := mptcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (mptcb *MediaProcessTaskCreateBulk) Exec(ctx context.Context) error { + _, err := mptcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (mptcb *MediaProcessTaskCreateBulk) ExecX(ctx context.Context) { + if err := mptcb.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.MediaProcessTask.CreateBulk(builders...). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.MediaProcessTaskUpsert) { +// SetCreatedAt(v+v). +// }). +// Exec(ctx) +func (mptcb *MediaProcessTaskCreateBulk) OnConflict(opts ...sql.ConflictOption) *MediaProcessTaskUpsertBulk { + mptcb.conflict = opts + return &MediaProcessTaskUpsertBulk{ + create: mptcb, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.MediaProcessTask.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (mptcb *MediaProcessTaskCreateBulk) OnConflictColumns(columns ...string) *MediaProcessTaskUpsertBulk { + mptcb.conflict = append(mptcb.conflict, sql.ConflictColumns(columns...)) + return &MediaProcessTaskUpsertBulk{ + create: mptcb, + } +} + +// MediaProcessTaskUpsertBulk is the builder for "upsert"-ing +// a bulk of MediaProcessTask nodes. +type MediaProcessTaskUpsertBulk struct { + create *MediaProcessTaskCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.MediaProcessTask.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// ). +// Exec(ctx) +func (u *MediaProcessTaskUpsertBulk) UpdateNewValues() *MediaProcessTaskUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + for _, b := range u.create.builders { + if _, exists := b.mutation.CreatedAt(); exists { + s.SetIgnore(mediaprocesstask.FieldCreatedAt) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.MediaProcessTask.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *MediaProcessTaskUpsertBulk) Ignore() *MediaProcessTaskUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *MediaProcessTaskUpsertBulk) DoNothing() *MediaProcessTaskUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the MediaProcessTaskCreateBulk.OnConflict +// documentation for more info. +func (u *MediaProcessTaskUpsertBulk) Update(set func(*MediaProcessTaskUpsert)) *MediaProcessTaskUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&MediaProcessTaskUpsert{UpdateSet: update}) + })) + return u +} + +// SetUpdatedAt sets the "updated_at" field. +func (u *MediaProcessTaskUpsertBulk) SetUpdatedAt(v time.Time) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetUpdatedAt(v) + }) +} + +// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertBulk) UpdateUpdatedAt() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateUpdatedAt() + }) +} + +// SetDeletedAt sets the "deleted_at" field. +func (u *MediaProcessTaskUpsertBulk) SetDeletedAt(v time.Time) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetDeletedAt(v) + }) +} + +// UpdateDeletedAt sets the "deleted_at" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertBulk) UpdateDeletedAt() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateDeletedAt() + }) +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (u *MediaProcessTaskUpsertBulk) ClearDeletedAt() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.ClearDeletedAt() + }) +} + +// SetMediaType sets the "media_type" field. +func (u *MediaProcessTaskUpsertBulk) SetMediaType(v mediaprocesstask.MediaType) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetMediaType(v) + }) +} + +// UpdateMediaType sets the "media_type" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertBulk) UpdateMediaType() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateMediaType() + }) +} + +// SetStatus sets the "status" field. +func (u *MediaProcessTaskUpsertBulk) SetStatus(v mediaprocesstask.Status) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetStatus(v) + }) +} + +// UpdateStatus sets the "status" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertBulk) UpdateStatus() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateStatus() + }) +} + +// SetEntityID sets the "entity_id" field. +func (u *MediaProcessTaskUpsertBulk) SetEntityID(v int) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetEntityID(v) + }) +} + +// AddEntityID adds v to the "entity_id" field. +func (u *MediaProcessTaskUpsertBulk) AddEntityID(v int) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.AddEntityID(v) + }) +} + +// UpdateEntityID sets the "entity_id" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertBulk) UpdateEntityID() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateEntityID() + }) +} + +// SetFileID sets the "file_id" field. +func (u *MediaProcessTaskUpsertBulk) SetFileID(v int) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetFileID(v) + }) +} + +// AddFileID adds v to the "file_id" field. +func (u *MediaProcessTaskUpsertBulk) AddFileID(v int) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.AddFileID(v) + }) +} + +// UpdateFileID sets the "file_id" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertBulk) UpdateFileID() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateFileID() + }) +} + +// ClearFileID clears the value of the "file_id" field. +func (u *MediaProcessTaskUpsertBulk) ClearFileID() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.ClearFileID() + }) +} + +// SetOwnerID sets the "owner_id" field. +func (u *MediaProcessTaskUpsertBulk) SetOwnerID(v int) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetOwnerID(v) + }) +} + +// AddOwnerID adds v to the "owner_id" field. +func (u *MediaProcessTaskUpsertBulk) AddOwnerID(v int) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.AddOwnerID(v) + }) +} + +// UpdateOwnerID sets the "owner_id" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertBulk) UpdateOwnerID() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateOwnerID() + }) +} + +// SetAttempts sets the "attempts" field. +func (u *MediaProcessTaskUpsertBulk) SetAttempts(v int) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetAttempts(v) + }) +} + +// AddAttempts adds v to the "attempts" field. +func (u *MediaProcessTaskUpsertBulk) AddAttempts(v int) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.AddAttempts(v) + }) +} + +// UpdateAttempts sets the "attempts" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertBulk) UpdateAttempts() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateAttempts() + }) +} + +// SetError sets the "error" field. +func (u *MediaProcessTaskUpsertBulk) SetError(v string) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetError(v) + }) +} + +// UpdateError sets the "error" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertBulk) UpdateError() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateError() + }) +} + +// ClearError clears the value of the "error" field. +func (u *MediaProcessTaskUpsertBulk) ClearError() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.ClearError() + }) +} + +// SetResultSize sets the "result_size" field. +func (u *MediaProcessTaskUpsertBulk) SetResultSize(v int64) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetResultSize(v) + }) +} + +// AddResultSize adds v to the "result_size" field. +func (u *MediaProcessTaskUpsertBulk) AddResultSize(v int64) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.AddResultSize(v) + }) +} + +// UpdateResultSize sets the "result_size" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertBulk) UpdateResultSize() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateResultSize() + }) +} + +// ClearResultSize clears the value of the "result_size" field. +func (u *MediaProcessTaskUpsertBulk) ClearResultSize() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.ClearResultSize() + }) +} + +// SetProps sets the "props" field. +func (u *MediaProcessTaskUpsertBulk) SetProps(v *types.MediaProcessTaskProps) *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.SetProps(v) + }) +} + +// UpdateProps sets the "props" field to the value that was provided on create. +func (u *MediaProcessTaskUpsertBulk) UpdateProps() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.UpdateProps() + }) +} + +// ClearProps clears the value of the "props" field. +func (u *MediaProcessTaskUpsertBulk) ClearProps() *MediaProcessTaskUpsertBulk { + return u.Update(func(s *MediaProcessTaskUpsert) { + s.ClearProps() + }) +} + +// Exec executes the query. +func (u *MediaProcessTaskUpsertBulk) Exec(ctx context.Context) error { + if u.create.err != nil { + return u.create.err + } + for i, b := range u.create.builders { + if len(b.conflict) != 0 { + return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the MediaProcessTaskCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for MediaProcessTaskCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *MediaProcessTaskUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/mediaprocesstask_delete.go b/ent/mediaprocesstask_delete.go new file mode 100644 index 00000000..2b728dc9 --- /dev/null +++ b/ent/mediaprocesstask_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" +) + +// MediaProcessTaskDelete is the builder for deleting a MediaProcessTask entity. +type MediaProcessTaskDelete struct { + config + hooks []Hook + mutation *MediaProcessTaskMutation +} + +// Where appends a list predicates to the MediaProcessTaskDelete builder. +func (mptd *MediaProcessTaskDelete) Where(ps ...predicate.MediaProcessTask) *MediaProcessTaskDelete { + mptd.mutation.Where(ps...) + return mptd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (mptd *MediaProcessTaskDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, mptd.sqlExec, mptd.mutation, mptd.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (mptd *MediaProcessTaskDelete) ExecX(ctx context.Context) int { + n, err := mptd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (mptd *MediaProcessTaskDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(mediaprocesstask.Table, sqlgraph.NewFieldSpec(mediaprocesstask.FieldID, field.TypeInt)) + if ps := mptd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, mptd.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + mptd.mutation.done = true + return affected, err +} + +// MediaProcessTaskDeleteOne is the builder for deleting a single MediaProcessTask entity. +type MediaProcessTaskDeleteOne struct { + mptd *MediaProcessTaskDelete +} + +// Where appends a list predicates to the MediaProcessTaskDelete builder. +func (mptdo *MediaProcessTaskDeleteOne) Where(ps ...predicate.MediaProcessTask) *MediaProcessTaskDeleteOne { + mptdo.mptd.mutation.Where(ps...) + return mptdo +} + +// Exec executes the deletion query. +func (mptdo *MediaProcessTaskDeleteOne) Exec(ctx context.Context) error { + n, err := mptdo.mptd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{mediaprocesstask.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (mptdo *MediaProcessTaskDeleteOne) ExecX(ctx context.Context) { + if err := mptdo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/mediaprocesstask_query.go b/ent/mediaprocesstask_query.go new file mode 100644 index 00000000..cb44bfee --- /dev/null +++ b/ent/mediaprocesstask_query.go @@ -0,0 +1,526 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" +) + +// MediaProcessTaskQuery is the builder for querying MediaProcessTask entities. +type MediaProcessTaskQuery struct { + config + ctx *QueryContext + order []mediaprocesstask.OrderOption + inters []Interceptor + predicates []predicate.MediaProcessTask + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the MediaProcessTaskQuery builder. +func (mptq *MediaProcessTaskQuery) Where(ps ...predicate.MediaProcessTask) *MediaProcessTaskQuery { + mptq.predicates = append(mptq.predicates, ps...) + return mptq +} + +// Limit the number of records to be returned by this query. +func (mptq *MediaProcessTaskQuery) Limit(limit int) *MediaProcessTaskQuery { + mptq.ctx.Limit = &limit + return mptq +} + +// Offset to start from. +func (mptq *MediaProcessTaskQuery) Offset(offset int) *MediaProcessTaskQuery { + mptq.ctx.Offset = &offset + return mptq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (mptq *MediaProcessTaskQuery) Unique(unique bool) *MediaProcessTaskQuery { + mptq.ctx.Unique = &unique + return mptq +} + +// Order specifies how the records should be ordered. +func (mptq *MediaProcessTaskQuery) Order(o ...mediaprocesstask.OrderOption) *MediaProcessTaskQuery { + mptq.order = append(mptq.order, o...) + return mptq +} + +// First returns the first MediaProcessTask entity from the query. +// Returns a *NotFoundError when no MediaProcessTask was found. +func (mptq *MediaProcessTaskQuery) First(ctx context.Context) (*MediaProcessTask, error) { + nodes, err := mptq.Limit(1).All(setContextOp(ctx, mptq.ctx, "First")) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{mediaprocesstask.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (mptq *MediaProcessTaskQuery) FirstX(ctx context.Context) *MediaProcessTask { + node, err := mptq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first MediaProcessTask ID from the query. +// Returns a *NotFoundError when no MediaProcessTask ID was found. +func (mptq *MediaProcessTaskQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = mptq.Limit(1).IDs(setContextOp(ctx, mptq.ctx, "FirstID")); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{mediaprocesstask.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (mptq *MediaProcessTaskQuery) FirstIDX(ctx context.Context) int { + id, err := mptq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single MediaProcessTask entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one MediaProcessTask entity is found. +// Returns a *NotFoundError when no MediaProcessTask entities are found. +func (mptq *MediaProcessTaskQuery) Only(ctx context.Context) (*MediaProcessTask, error) { + nodes, err := mptq.Limit(2).All(setContextOp(ctx, mptq.ctx, "Only")) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{mediaprocesstask.Label} + default: + return nil, &NotSingularError{mediaprocesstask.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (mptq *MediaProcessTaskQuery) OnlyX(ctx context.Context) *MediaProcessTask { + node, err := mptq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only MediaProcessTask ID in the query. +// Returns a *NotSingularError when more than one MediaProcessTask ID is found. +// Returns a *NotFoundError when no entities are found. +func (mptq *MediaProcessTaskQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = mptq.Limit(2).IDs(setContextOp(ctx, mptq.ctx, "OnlyID")); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{mediaprocesstask.Label} + default: + err = &NotSingularError{mediaprocesstask.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (mptq *MediaProcessTaskQuery) OnlyIDX(ctx context.Context) int { + id, err := mptq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of MediaProcessTasks. +func (mptq *MediaProcessTaskQuery) All(ctx context.Context) ([]*MediaProcessTask, error) { + ctx = setContextOp(ctx, mptq.ctx, "All") + if err := mptq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*MediaProcessTask, *MediaProcessTaskQuery]() + return withInterceptors[[]*MediaProcessTask](ctx, mptq, qr, mptq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (mptq *MediaProcessTaskQuery) AllX(ctx context.Context) []*MediaProcessTask { + nodes, err := mptq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of MediaProcessTask IDs. +func (mptq *MediaProcessTaskQuery) IDs(ctx context.Context) (ids []int, err error) { + if mptq.ctx.Unique == nil && mptq.path != nil { + mptq.Unique(true) + } + ctx = setContextOp(ctx, mptq.ctx, "IDs") + if err = mptq.Select(mediaprocesstask.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (mptq *MediaProcessTaskQuery) IDsX(ctx context.Context) []int { + ids, err := mptq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (mptq *MediaProcessTaskQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, mptq.ctx, "Count") + if err := mptq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, mptq, querierCount[*MediaProcessTaskQuery](), mptq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (mptq *MediaProcessTaskQuery) CountX(ctx context.Context) int { + count, err := mptq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (mptq *MediaProcessTaskQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, mptq.ctx, "Exist") + switch _, err := mptq.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (mptq *MediaProcessTaskQuery) ExistX(ctx context.Context) bool { + exist, err := mptq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the MediaProcessTaskQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (mptq *MediaProcessTaskQuery) Clone() *MediaProcessTaskQuery { + if mptq == nil { + return nil + } + return &MediaProcessTaskQuery{ + config: mptq.config, + ctx: mptq.ctx.Clone(), + order: append([]mediaprocesstask.OrderOption{}, mptq.order...), + inters: append([]Interceptor{}, mptq.inters...), + predicates: append([]predicate.MediaProcessTask{}, mptq.predicates...), + // clone intermediate query. + sql: mptq.sql.Clone(), + path: mptq.path, + } +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.MediaProcessTask.Query(). +// GroupBy(mediaprocesstask.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (mptq *MediaProcessTaskQuery) GroupBy(field string, fields ...string) *MediaProcessTaskGroupBy { + mptq.ctx.Fields = append([]string{field}, fields...) + grbuild := &MediaProcessTaskGroupBy{build: mptq} + grbuild.flds = &mptq.ctx.Fields + grbuild.label = mediaprocesstask.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// } +// +// client.MediaProcessTask.Query(). +// Select(mediaprocesstask.FieldCreatedAt). +// Scan(ctx, &v) +func (mptq *MediaProcessTaskQuery) Select(fields ...string) *MediaProcessTaskSelect { + mptq.ctx.Fields = append(mptq.ctx.Fields, fields...) + sbuild := &MediaProcessTaskSelect{MediaProcessTaskQuery: mptq} + sbuild.label = mediaprocesstask.Label + sbuild.flds, sbuild.scan = &mptq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a MediaProcessTaskSelect configured with the given aggregations. +func (mptq *MediaProcessTaskQuery) Aggregate(fns ...AggregateFunc) *MediaProcessTaskSelect { + return mptq.Select().Aggregate(fns...) +} + +func (mptq *MediaProcessTaskQuery) prepareQuery(ctx context.Context) error { + for _, inter := range mptq.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, mptq); err != nil { + return err + } + } + } + for _, f := range mptq.ctx.Fields { + if !mediaprocesstask.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if mptq.path != nil { + prev, err := mptq.path(ctx) + if err != nil { + return err + } + mptq.sql = prev + } + return nil +} + +func (mptq *MediaProcessTaskQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*MediaProcessTask, error) { + var ( + nodes = []*MediaProcessTask{} + _spec = mptq.querySpec() + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*MediaProcessTask).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &MediaProcessTask{config: mptq.config} + nodes = append(nodes, node) + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, mptq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + return nodes, nil +} + +func (mptq *MediaProcessTaskQuery) sqlCount(ctx context.Context) (int, error) { + _spec := mptq.querySpec() + _spec.Node.Columns = mptq.ctx.Fields + if len(mptq.ctx.Fields) > 0 { + _spec.Unique = mptq.ctx.Unique != nil && *mptq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, mptq.driver, _spec) +} + +func (mptq *MediaProcessTaskQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(mediaprocesstask.Table, mediaprocesstask.Columns, sqlgraph.NewFieldSpec(mediaprocesstask.FieldID, field.TypeInt)) + _spec.From = mptq.sql + if unique := mptq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if mptq.path != nil { + _spec.Unique = true + } + if fields := mptq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, mediaprocesstask.FieldID) + for i := range fields { + if fields[i] != mediaprocesstask.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := mptq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := mptq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := mptq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := mptq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (mptq *MediaProcessTaskQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(mptq.driver.Dialect()) + t1 := builder.Table(mediaprocesstask.Table) + columns := mptq.ctx.Fields + if len(columns) == 0 { + columns = mediaprocesstask.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if mptq.sql != nil { + selector = mptq.sql + selector.Select(selector.Columns(columns...)...) + } + if mptq.ctx.Unique != nil && *mptq.ctx.Unique { + selector.Distinct() + } + for _, p := range mptq.predicates { + p(selector) + } + for _, p := range mptq.order { + p(selector) + } + if offset := mptq.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := mptq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// MediaProcessTaskGroupBy is the group-by builder for MediaProcessTask entities. +type MediaProcessTaskGroupBy struct { + selector + build *MediaProcessTaskQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (mptgb *MediaProcessTaskGroupBy) Aggregate(fns ...AggregateFunc) *MediaProcessTaskGroupBy { + mptgb.fns = append(mptgb.fns, fns...) + return mptgb +} + +// Scan applies the selector query and scans the result into the given value. +func (mptgb *MediaProcessTaskGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, mptgb.build.ctx, "GroupBy") + if err := mptgb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*MediaProcessTaskQuery, *MediaProcessTaskGroupBy](ctx, mptgb.build, mptgb, mptgb.build.inters, v) +} + +func (mptgb *MediaProcessTaskGroupBy) sqlScan(ctx context.Context, root *MediaProcessTaskQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(mptgb.fns)) + for _, fn := range mptgb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*mptgb.flds)+len(mptgb.fns)) + for _, f := range *mptgb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*mptgb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := mptgb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// MediaProcessTaskSelect is the builder for selecting fields of MediaProcessTask entities. +type MediaProcessTaskSelect struct { + *MediaProcessTaskQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (mpts *MediaProcessTaskSelect) Aggregate(fns ...AggregateFunc) *MediaProcessTaskSelect { + mpts.fns = append(mpts.fns, fns...) + return mpts +} + +// Scan applies the selector query and scans the result into the given value. +func (mpts *MediaProcessTaskSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, mpts.ctx, "Select") + if err := mpts.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*MediaProcessTaskQuery, *MediaProcessTaskSelect](ctx, mpts.MediaProcessTaskQuery, mpts, mpts.inters, v) +} + +func (mpts *MediaProcessTaskSelect) sqlScan(ctx context.Context, root *MediaProcessTaskQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(mpts.fns)) + for _, fn := range mpts.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*mpts.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := mpts.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/mediaprocesstask_update.go b/ent/mediaprocesstask_update.go new file mode 100644 index 00000000..42c33675 --- /dev/null +++ b/ent/mediaprocesstask_update.go @@ -0,0 +1,775 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" + "github.com/cloudreve/Cloudreve/v4/ent/predicate" + "github.com/cloudreve/Cloudreve/v4/inventory/types" +) + +// MediaProcessTaskUpdate is the builder for updating MediaProcessTask entities. +type MediaProcessTaskUpdate struct { + config + hooks []Hook + mutation *MediaProcessTaskMutation +} + +// Where appends a list predicates to the MediaProcessTaskUpdate builder. +func (mptu *MediaProcessTaskUpdate) Where(ps ...predicate.MediaProcessTask) *MediaProcessTaskUpdate { + mptu.mutation.Where(ps...) + return mptu +} + +// SetUpdatedAt sets the "updated_at" field. +func (mptu *MediaProcessTaskUpdate) SetUpdatedAt(t time.Time) *MediaProcessTaskUpdate { + mptu.mutation.SetUpdatedAt(t) + return mptu +} + +// SetDeletedAt sets the "deleted_at" field. +func (mptu *MediaProcessTaskUpdate) SetDeletedAt(t time.Time) *MediaProcessTaskUpdate { + mptu.mutation.SetDeletedAt(t) + return mptu +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (mptu *MediaProcessTaskUpdate) SetNillableDeletedAt(t *time.Time) *MediaProcessTaskUpdate { + if t != nil { + mptu.SetDeletedAt(*t) + } + return mptu +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (mptu *MediaProcessTaskUpdate) ClearDeletedAt() *MediaProcessTaskUpdate { + mptu.mutation.ClearDeletedAt() + return mptu +} + +// SetMediaType sets the "media_type" field. +func (mptu *MediaProcessTaskUpdate) SetMediaType(mt mediaprocesstask.MediaType) *MediaProcessTaskUpdate { + mptu.mutation.SetMediaType(mt) + return mptu +} + +// SetNillableMediaType sets the "media_type" field if the given value is not nil. +func (mptu *MediaProcessTaskUpdate) SetNillableMediaType(mt *mediaprocesstask.MediaType) *MediaProcessTaskUpdate { + if mt != nil { + mptu.SetMediaType(*mt) + } + return mptu +} + +// SetStatus sets the "status" field. +func (mptu *MediaProcessTaskUpdate) SetStatus(m mediaprocesstask.Status) *MediaProcessTaskUpdate { + mptu.mutation.SetStatus(m) + return mptu +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (mptu *MediaProcessTaskUpdate) SetNillableStatus(m *mediaprocesstask.Status) *MediaProcessTaskUpdate { + if m != nil { + mptu.SetStatus(*m) + } + return mptu +} + +// SetEntityID sets the "entity_id" field. +func (mptu *MediaProcessTaskUpdate) SetEntityID(i int) *MediaProcessTaskUpdate { + mptu.mutation.ResetEntityID() + mptu.mutation.SetEntityID(i) + return mptu +} + +// SetNillableEntityID sets the "entity_id" field if the given value is not nil. +func (mptu *MediaProcessTaskUpdate) SetNillableEntityID(i *int) *MediaProcessTaskUpdate { + if i != nil { + mptu.SetEntityID(*i) + } + return mptu +} + +// AddEntityID adds i to the "entity_id" field. +func (mptu *MediaProcessTaskUpdate) AddEntityID(i int) *MediaProcessTaskUpdate { + mptu.mutation.AddEntityID(i) + return mptu +} + +// SetFileID sets the "file_id" field. +func (mptu *MediaProcessTaskUpdate) SetFileID(i int) *MediaProcessTaskUpdate { + mptu.mutation.ResetFileID() + mptu.mutation.SetFileID(i) + return mptu +} + +// SetNillableFileID sets the "file_id" field if the given value is not nil. +func (mptu *MediaProcessTaskUpdate) SetNillableFileID(i *int) *MediaProcessTaskUpdate { + if i != nil { + mptu.SetFileID(*i) + } + return mptu +} + +// AddFileID adds i to the "file_id" field. +func (mptu *MediaProcessTaskUpdate) AddFileID(i int) *MediaProcessTaskUpdate { + mptu.mutation.AddFileID(i) + return mptu +} + +// ClearFileID clears the value of the "file_id" field. +func (mptu *MediaProcessTaskUpdate) ClearFileID() *MediaProcessTaskUpdate { + mptu.mutation.ClearFileID() + return mptu +} + +// SetOwnerID sets the "owner_id" field. +func (mptu *MediaProcessTaskUpdate) SetOwnerID(i int) *MediaProcessTaskUpdate { + mptu.mutation.ResetOwnerID() + mptu.mutation.SetOwnerID(i) + return mptu +} + +// SetNillableOwnerID sets the "owner_id" field if the given value is not nil. +func (mptu *MediaProcessTaskUpdate) SetNillableOwnerID(i *int) *MediaProcessTaskUpdate { + if i != nil { + mptu.SetOwnerID(*i) + } + return mptu +} + +// AddOwnerID adds i to the "owner_id" field. +func (mptu *MediaProcessTaskUpdate) AddOwnerID(i int) *MediaProcessTaskUpdate { + mptu.mutation.AddOwnerID(i) + return mptu +} + +// SetAttempts sets the "attempts" field. +func (mptu *MediaProcessTaskUpdate) SetAttempts(i int) *MediaProcessTaskUpdate { + mptu.mutation.ResetAttempts() + mptu.mutation.SetAttempts(i) + return mptu +} + +// SetNillableAttempts sets the "attempts" field if the given value is not nil. +func (mptu *MediaProcessTaskUpdate) SetNillableAttempts(i *int) *MediaProcessTaskUpdate { + if i != nil { + mptu.SetAttempts(*i) + } + return mptu +} + +// AddAttempts adds i to the "attempts" field. +func (mptu *MediaProcessTaskUpdate) AddAttempts(i int) *MediaProcessTaskUpdate { + mptu.mutation.AddAttempts(i) + return mptu +} + +// SetError sets the "error" field. +func (mptu *MediaProcessTaskUpdate) SetError(s string) *MediaProcessTaskUpdate { + mptu.mutation.SetError(s) + return mptu +} + +// SetNillableError sets the "error" field if the given value is not nil. +func (mptu *MediaProcessTaskUpdate) SetNillableError(s *string) *MediaProcessTaskUpdate { + if s != nil { + mptu.SetError(*s) + } + return mptu +} + +// ClearError clears the value of the "error" field. +func (mptu *MediaProcessTaskUpdate) ClearError() *MediaProcessTaskUpdate { + mptu.mutation.ClearError() + return mptu +} + +// SetResultSize sets the "result_size" field. +func (mptu *MediaProcessTaskUpdate) SetResultSize(i int64) *MediaProcessTaskUpdate { + mptu.mutation.ResetResultSize() + mptu.mutation.SetResultSize(i) + return mptu +} + +// SetNillableResultSize sets the "result_size" field if the given value is not nil. +func (mptu *MediaProcessTaskUpdate) SetNillableResultSize(i *int64) *MediaProcessTaskUpdate { + if i != nil { + mptu.SetResultSize(*i) + } + return mptu +} + +// AddResultSize adds i to the "result_size" field. +func (mptu *MediaProcessTaskUpdate) AddResultSize(i int64) *MediaProcessTaskUpdate { + mptu.mutation.AddResultSize(i) + return mptu +} + +// ClearResultSize clears the value of the "result_size" field. +func (mptu *MediaProcessTaskUpdate) ClearResultSize() *MediaProcessTaskUpdate { + mptu.mutation.ClearResultSize() + return mptu +} + +// SetProps sets the "props" field. +func (mptu *MediaProcessTaskUpdate) SetProps(tptp *types.MediaProcessTaskProps) *MediaProcessTaskUpdate { + mptu.mutation.SetProps(tptp) + return mptu +} + +// ClearProps clears the value of the "props" field. +func (mptu *MediaProcessTaskUpdate) ClearProps() *MediaProcessTaskUpdate { + mptu.mutation.ClearProps() + return mptu +} + +// Mutation returns the MediaProcessTaskMutation object of the builder. +func (mptu *MediaProcessTaskUpdate) Mutation() *MediaProcessTaskMutation { + return mptu.mutation +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (mptu *MediaProcessTaskUpdate) Save(ctx context.Context) (int, error) { + if err := mptu.defaults(); err != nil { + return 0, err + } + return withHooks(ctx, mptu.sqlSave, mptu.mutation, mptu.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (mptu *MediaProcessTaskUpdate) SaveX(ctx context.Context) int { + affected, err := mptu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (mptu *MediaProcessTaskUpdate) Exec(ctx context.Context) error { + _, err := mptu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (mptu *MediaProcessTaskUpdate) ExecX(ctx context.Context) { + if err := mptu.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (mptu *MediaProcessTaskUpdate) defaults() error { + if _, ok := mptu.mutation.UpdatedAt(); !ok { + if mediaprocesstask.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized mediaprocesstask.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := mediaprocesstask.UpdateDefaultUpdatedAt() + mptu.mutation.SetUpdatedAt(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (mptu *MediaProcessTaskUpdate) check() error { + if v, ok := mptu.mutation.MediaType(); ok { + if err := mediaprocesstask.MediaTypeValidator(v); err != nil { + return &ValidationError{Name: "media_type", err: fmt.Errorf(`ent: validator failed for field "MediaProcessTask.media_type": %w`, err)} + } + } + if v, ok := mptu.mutation.Status(); ok { + if err := mediaprocesstask.StatusValidator(v); err != nil { + return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "MediaProcessTask.status": %w`, err)} + } + } + return nil +} + +func (mptu *MediaProcessTaskUpdate) sqlSave(ctx context.Context) (n int, err error) { + if err := mptu.check(); err != nil { + return n, err + } + _spec := sqlgraph.NewUpdateSpec(mediaprocesstask.Table, mediaprocesstask.Columns, sqlgraph.NewFieldSpec(mediaprocesstask.FieldID, field.TypeInt)) + if ps := mptu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := mptu.mutation.UpdatedAt(); ok { + _spec.SetField(mediaprocesstask.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := mptu.mutation.DeletedAt(); ok { + _spec.SetField(mediaprocesstask.FieldDeletedAt, field.TypeTime, value) + } + if mptu.mutation.DeletedAtCleared() { + _spec.ClearField(mediaprocesstask.FieldDeletedAt, field.TypeTime) + } + if value, ok := mptu.mutation.MediaType(); ok { + _spec.SetField(mediaprocesstask.FieldMediaType, field.TypeEnum, value) + } + if value, ok := mptu.mutation.Status(); ok { + _spec.SetField(mediaprocesstask.FieldStatus, field.TypeEnum, value) + } + if value, ok := mptu.mutation.EntityID(); ok { + _spec.SetField(mediaprocesstask.FieldEntityID, field.TypeInt, value) + } + if value, ok := mptu.mutation.AddedEntityID(); ok { + _spec.AddField(mediaprocesstask.FieldEntityID, field.TypeInt, value) + } + if value, ok := mptu.mutation.FileID(); ok { + _spec.SetField(mediaprocesstask.FieldFileID, field.TypeInt, value) + } + if value, ok := mptu.mutation.AddedFileID(); ok { + _spec.AddField(mediaprocesstask.FieldFileID, field.TypeInt, value) + } + if mptu.mutation.FileIDCleared() { + _spec.ClearField(mediaprocesstask.FieldFileID, field.TypeInt) + } + if value, ok := mptu.mutation.OwnerID(); ok { + _spec.SetField(mediaprocesstask.FieldOwnerID, field.TypeInt, value) + } + if value, ok := mptu.mutation.AddedOwnerID(); ok { + _spec.AddField(mediaprocesstask.FieldOwnerID, field.TypeInt, value) + } + if value, ok := mptu.mutation.Attempts(); ok { + _spec.SetField(mediaprocesstask.FieldAttempts, field.TypeInt, value) + } + if value, ok := mptu.mutation.AddedAttempts(); ok { + _spec.AddField(mediaprocesstask.FieldAttempts, field.TypeInt, value) + } + if value, ok := mptu.mutation.Error(); ok { + _spec.SetField(mediaprocesstask.FieldError, field.TypeString, value) + } + if mptu.mutation.ErrorCleared() { + _spec.ClearField(mediaprocesstask.FieldError, field.TypeString) + } + if value, ok := mptu.mutation.ResultSize(); ok { + _spec.SetField(mediaprocesstask.FieldResultSize, field.TypeInt64, value) + } + if value, ok := mptu.mutation.AddedResultSize(); ok { + _spec.AddField(mediaprocesstask.FieldResultSize, field.TypeInt64, value) + } + if mptu.mutation.ResultSizeCleared() { + _spec.ClearField(mediaprocesstask.FieldResultSize, field.TypeInt64) + } + if value, ok := mptu.mutation.Props(); ok { + _spec.SetField(mediaprocesstask.FieldProps, field.TypeJSON, value) + } + if mptu.mutation.PropsCleared() { + _spec.ClearField(mediaprocesstask.FieldProps, field.TypeJSON) + } + if n, err = sqlgraph.UpdateNodes(ctx, mptu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{mediaprocesstask.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + mptu.mutation.done = true + return n, nil +} + +// MediaProcessTaskUpdateOne is the builder for updating a single MediaProcessTask entity. +type MediaProcessTaskUpdateOne struct { + config + fields []string + hooks []Hook + mutation *MediaProcessTaskMutation +} + +// SetUpdatedAt sets the "updated_at" field. +func (mptuo *MediaProcessTaskUpdateOne) SetUpdatedAt(t time.Time) *MediaProcessTaskUpdateOne { + mptuo.mutation.SetUpdatedAt(t) + return mptuo +} + +// SetDeletedAt sets the "deleted_at" field. +func (mptuo *MediaProcessTaskUpdateOne) SetDeletedAt(t time.Time) *MediaProcessTaskUpdateOne { + mptuo.mutation.SetDeletedAt(t) + return mptuo +} + +// SetNillableDeletedAt sets the "deleted_at" field if the given value is not nil. +func (mptuo *MediaProcessTaskUpdateOne) SetNillableDeletedAt(t *time.Time) *MediaProcessTaskUpdateOne { + if t != nil { + mptuo.SetDeletedAt(*t) + } + return mptuo +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (mptuo *MediaProcessTaskUpdateOne) ClearDeletedAt() *MediaProcessTaskUpdateOne { + mptuo.mutation.ClearDeletedAt() + return mptuo +} + +// SetMediaType sets the "media_type" field. +func (mptuo *MediaProcessTaskUpdateOne) SetMediaType(mt mediaprocesstask.MediaType) *MediaProcessTaskUpdateOne { + mptuo.mutation.SetMediaType(mt) + return mptuo +} + +// SetNillableMediaType sets the "media_type" field if the given value is not nil. +func (mptuo *MediaProcessTaskUpdateOne) SetNillableMediaType(mt *mediaprocesstask.MediaType) *MediaProcessTaskUpdateOne { + if mt != nil { + mptuo.SetMediaType(*mt) + } + return mptuo +} + +// SetStatus sets the "status" field. +func (mptuo *MediaProcessTaskUpdateOne) SetStatus(m mediaprocesstask.Status) *MediaProcessTaskUpdateOne { + mptuo.mutation.SetStatus(m) + return mptuo +} + +// SetNillableStatus sets the "status" field if the given value is not nil. +func (mptuo *MediaProcessTaskUpdateOne) SetNillableStatus(m *mediaprocesstask.Status) *MediaProcessTaskUpdateOne { + if m != nil { + mptuo.SetStatus(*m) + } + return mptuo +} + +// SetEntityID sets the "entity_id" field. +func (mptuo *MediaProcessTaskUpdateOne) SetEntityID(i int) *MediaProcessTaskUpdateOne { + mptuo.mutation.ResetEntityID() + mptuo.mutation.SetEntityID(i) + return mptuo +} + +// SetNillableEntityID sets the "entity_id" field if the given value is not nil. +func (mptuo *MediaProcessTaskUpdateOne) SetNillableEntityID(i *int) *MediaProcessTaskUpdateOne { + if i != nil { + mptuo.SetEntityID(*i) + } + return mptuo +} + +// AddEntityID adds i to the "entity_id" field. +func (mptuo *MediaProcessTaskUpdateOne) AddEntityID(i int) *MediaProcessTaskUpdateOne { + mptuo.mutation.AddEntityID(i) + return mptuo +} + +// SetFileID sets the "file_id" field. +func (mptuo *MediaProcessTaskUpdateOne) SetFileID(i int) *MediaProcessTaskUpdateOne { + mptuo.mutation.ResetFileID() + mptuo.mutation.SetFileID(i) + return mptuo +} + +// SetNillableFileID sets the "file_id" field if the given value is not nil. +func (mptuo *MediaProcessTaskUpdateOne) SetNillableFileID(i *int) *MediaProcessTaskUpdateOne { + if i != nil { + mptuo.SetFileID(*i) + } + return mptuo +} + +// AddFileID adds i to the "file_id" field. +func (mptuo *MediaProcessTaskUpdateOne) AddFileID(i int) *MediaProcessTaskUpdateOne { + mptuo.mutation.AddFileID(i) + return mptuo +} + +// ClearFileID clears the value of the "file_id" field. +func (mptuo *MediaProcessTaskUpdateOne) ClearFileID() *MediaProcessTaskUpdateOne { + mptuo.mutation.ClearFileID() + return mptuo +} + +// SetOwnerID sets the "owner_id" field. +func (mptuo *MediaProcessTaskUpdateOne) SetOwnerID(i int) *MediaProcessTaskUpdateOne { + mptuo.mutation.ResetOwnerID() + mptuo.mutation.SetOwnerID(i) + return mptuo +} + +// SetNillableOwnerID sets the "owner_id" field if the given value is not nil. +func (mptuo *MediaProcessTaskUpdateOne) SetNillableOwnerID(i *int) *MediaProcessTaskUpdateOne { + if i != nil { + mptuo.SetOwnerID(*i) + } + return mptuo +} + +// AddOwnerID adds i to the "owner_id" field. +func (mptuo *MediaProcessTaskUpdateOne) AddOwnerID(i int) *MediaProcessTaskUpdateOne { + mptuo.mutation.AddOwnerID(i) + return mptuo +} + +// SetAttempts sets the "attempts" field. +func (mptuo *MediaProcessTaskUpdateOne) SetAttempts(i int) *MediaProcessTaskUpdateOne { + mptuo.mutation.ResetAttempts() + mptuo.mutation.SetAttempts(i) + return mptuo +} + +// SetNillableAttempts sets the "attempts" field if the given value is not nil. +func (mptuo *MediaProcessTaskUpdateOne) SetNillableAttempts(i *int) *MediaProcessTaskUpdateOne { + if i != nil { + mptuo.SetAttempts(*i) + } + return mptuo +} + +// AddAttempts adds i to the "attempts" field. +func (mptuo *MediaProcessTaskUpdateOne) AddAttempts(i int) *MediaProcessTaskUpdateOne { + mptuo.mutation.AddAttempts(i) + return mptuo +} + +// SetError sets the "error" field. +func (mptuo *MediaProcessTaskUpdateOne) SetError(s string) *MediaProcessTaskUpdateOne { + mptuo.mutation.SetError(s) + return mptuo +} + +// SetNillableError sets the "error" field if the given value is not nil. +func (mptuo *MediaProcessTaskUpdateOne) SetNillableError(s *string) *MediaProcessTaskUpdateOne { + if s != nil { + mptuo.SetError(*s) + } + return mptuo +} + +// ClearError clears the value of the "error" field. +func (mptuo *MediaProcessTaskUpdateOne) ClearError() *MediaProcessTaskUpdateOne { + mptuo.mutation.ClearError() + return mptuo +} + +// SetResultSize sets the "result_size" field. +func (mptuo *MediaProcessTaskUpdateOne) SetResultSize(i int64) *MediaProcessTaskUpdateOne { + mptuo.mutation.ResetResultSize() + mptuo.mutation.SetResultSize(i) + return mptuo +} + +// SetNillableResultSize sets the "result_size" field if the given value is not nil. +func (mptuo *MediaProcessTaskUpdateOne) SetNillableResultSize(i *int64) *MediaProcessTaskUpdateOne { + if i != nil { + mptuo.SetResultSize(*i) + } + return mptuo +} + +// AddResultSize adds i to the "result_size" field. +func (mptuo *MediaProcessTaskUpdateOne) AddResultSize(i int64) *MediaProcessTaskUpdateOne { + mptuo.mutation.AddResultSize(i) + return mptuo +} + +// ClearResultSize clears the value of the "result_size" field. +func (mptuo *MediaProcessTaskUpdateOne) ClearResultSize() *MediaProcessTaskUpdateOne { + mptuo.mutation.ClearResultSize() + return mptuo +} + +// SetProps sets the "props" field. +func (mptuo *MediaProcessTaskUpdateOne) SetProps(tptp *types.MediaProcessTaskProps) *MediaProcessTaskUpdateOne { + mptuo.mutation.SetProps(tptp) + return mptuo +} + +// ClearProps clears the value of the "props" field. +func (mptuo *MediaProcessTaskUpdateOne) ClearProps() *MediaProcessTaskUpdateOne { + mptuo.mutation.ClearProps() + return mptuo +} + +// Mutation returns the MediaProcessTaskMutation object of the builder. +func (mptuo *MediaProcessTaskUpdateOne) Mutation() *MediaProcessTaskMutation { + return mptuo.mutation +} + +// Where appends a list predicates to the MediaProcessTaskUpdate builder. +func (mptuo *MediaProcessTaskUpdateOne) Where(ps ...predicate.MediaProcessTask) *MediaProcessTaskUpdateOne { + mptuo.mutation.Where(ps...) + return mptuo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (mptuo *MediaProcessTaskUpdateOne) Select(field string, fields ...string) *MediaProcessTaskUpdateOne { + mptuo.fields = append([]string{field}, fields...) + return mptuo +} + +// Save executes the query and returns the updated MediaProcessTask entity. +func (mptuo *MediaProcessTaskUpdateOne) Save(ctx context.Context) (*MediaProcessTask, error) { + if err := mptuo.defaults(); err != nil { + return nil, err + } + return withHooks(ctx, mptuo.sqlSave, mptuo.mutation, mptuo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (mptuo *MediaProcessTaskUpdateOne) SaveX(ctx context.Context) *MediaProcessTask { + node, err := mptuo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (mptuo *MediaProcessTaskUpdateOne) Exec(ctx context.Context) error { + _, err := mptuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (mptuo *MediaProcessTaskUpdateOne) ExecX(ctx context.Context) { + if err := mptuo.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (mptuo *MediaProcessTaskUpdateOne) defaults() error { + if _, ok := mptuo.mutation.UpdatedAt(); !ok { + if mediaprocesstask.UpdateDefaultUpdatedAt == nil { + return fmt.Errorf("ent: uninitialized mediaprocesstask.UpdateDefaultUpdatedAt (forgotten import ent/runtime?)") + } + v := mediaprocesstask.UpdateDefaultUpdatedAt() + mptuo.mutation.SetUpdatedAt(v) + } + return nil +} + +// check runs all checks and user-defined validators on the builder. +func (mptuo *MediaProcessTaskUpdateOne) check() error { + if v, ok := mptuo.mutation.MediaType(); ok { + if err := mediaprocesstask.MediaTypeValidator(v); err != nil { + return &ValidationError{Name: "media_type", err: fmt.Errorf(`ent: validator failed for field "MediaProcessTask.media_type": %w`, err)} + } + } + if v, ok := mptuo.mutation.Status(); ok { + if err := mediaprocesstask.StatusValidator(v); err != nil { + return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "MediaProcessTask.status": %w`, err)} + } + } + return nil +} + +func (mptuo *MediaProcessTaskUpdateOne) sqlSave(ctx context.Context) (_node *MediaProcessTask, err error) { + if err := mptuo.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(mediaprocesstask.Table, mediaprocesstask.Columns, sqlgraph.NewFieldSpec(mediaprocesstask.FieldID, field.TypeInt)) + id, ok := mptuo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "MediaProcessTask.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := mptuo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, mediaprocesstask.FieldID) + for _, f := range fields { + if !mediaprocesstask.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != mediaprocesstask.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := mptuo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := mptuo.mutation.UpdatedAt(); ok { + _spec.SetField(mediaprocesstask.FieldUpdatedAt, field.TypeTime, value) + } + if value, ok := mptuo.mutation.DeletedAt(); ok { + _spec.SetField(mediaprocesstask.FieldDeletedAt, field.TypeTime, value) + } + if mptuo.mutation.DeletedAtCleared() { + _spec.ClearField(mediaprocesstask.FieldDeletedAt, field.TypeTime) + } + if value, ok := mptuo.mutation.MediaType(); ok { + _spec.SetField(mediaprocesstask.FieldMediaType, field.TypeEnum, value) + } + if value, ok := mptuo.mutation.Status(); ok { + _spec.SetField(mediaprocesstask.FieldStatus, field.TypeEnum, value) + } + if value, ok := mptuo.mutation.EntityID(); ok { + _spec.SetField(mediaprocesstask.FieldEntityID, field.TypeInt, value) + } + if value, ok := mptuo.mutation.AddedEntityID(); ok { + _spec.AddField(mediaprocesstask.FieldEntityID, field.TypeInt, value) + } + if value, ok := mptuo.mutation.FileID(); ok { + _spec.SetField(mediaprocesstask.FieldFileID, field.TypeInt, value) + } + if value, ok := mptuo.mutation.AddedFileID(); ok { + _spec.AddField(mediaprocesstask.FieldFileID, field.TypeInt, value) + } + if mptuo.mutation.FileIDCleared() { + _spec.ClearField(mediaprocesstask.FieldFileID, field.TypeInt) + } + if value, ok := mptuo.mutation.OwnerID(); ok { + _spec.SetField(mediaprocesstask.FieldOwnerID, field.TypeInt, value) + } + if value, ok := mptuo.mutation.AddedOwnerID(); ok { + _spec.AddField(mediaprocesstask.FieldOwnerID, field.TypeInt, value) + } + if value, ok := mptuo.mutation.Attempts(); ok { + _spec.SetField(mediaprocesstask.FieldAttempts, field.TypeInt, value) + } + if value, ok := mptuo.mutation.AddedAttempts(); ok { + _spec.AddField(mediaprocesstask.FieldAttempts, field.TypeInt, value) + } + if value, ok := mptuo.mutation.Error(); ok { + _spec.SetField(mediaprocesstask.FieldError, field.TypeString, value) + } + if mptuo.mutation.ErrorCleared() { + _spec.ClearField(mediaprocesstask.FieldError, field.TypeString) + } + if value, ok := mptuo.mutation.ResultSize(); ok { + _spec.SetField(mediaprocesstask.FieldResultSize, field.TypeInt64, value) + } + if value, ok := mptuo.mutation.AddedResultSize(); ok { + _spec.AddField(mediaprocesstask.FieldResultSize, field.TypeInt64, value) + } + if mptuo.mutation.ResultSizeCleared() { + _spec.ClearField(mediaprocesstask.FieldResultSize, field.TypeInt64) + } + if value, ok := mptuo.mutation.Props(); ok { + _spec.SetField(mediaprocesstask.FieldProps, field.TypeJSON, value) + } + if mptuo.mutation.PropsCleared() { + _spec.ClearField(mediaprocesstask.FieldProps, field.TypeJSON) + } + _node = &MediaProcessTask{config: mptuo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, mptuo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{mediaprocesstask.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + mptuo.mutation.done = true + return _node, nil +} diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index 8d3ab5ca..ab5eabf0 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -216,6 +216,40 @@ var ( }, }, } + // MediaProcessTasksColumns holds the columns for the "media_process_tasks" table. + MediaProcessTasksColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "created_at", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "updated_at", Type: field.TypeTime, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "deleted_at", Type: field.TypeTime, Nullable: true, SchemaType: map[string]string{"mysql": "datetime"}}, + {Name: "media_type", Type: field.TypeEnum, Enums: []string{"image", "video"}, Default: "image"}, + {Name: "status", Type: field.TypeEnum, Enums: []string{"pending", "processing", "done", "failed", "skipped"}, Default: "pending"}, + {Name: "entity_id", Type: field.TypeInt}, + {Name: "file_id", Type: field.TypeInt, Nullable: true}, + {Name: "owner_id", Type: field.TypeInt}, + {Name: "attempts", Type: field.TypeInt, Default: 0}, + {Name: "error", Type: field.TypeString, Nullable: true, Size: 2147483647}, + {Name: "result_size", Type: field.TypeInt64, Nullable: true}, + {Name: "props", Type: field.TypeJSON, Nullable: true}, + } + // MediaProcessTasksTable holds the schema information for the "media_process_tasks" table. + MediaProcessTasksTable = &schema.Table{ + Name: "media_process_tasks", + Columns: MediaProcessTasksColumns, + PrimaryKey: []*schema.Column{MediaProcessTasksColumns[0]}, + Indexes: []*schema.Index{ + { + Name: "mediaprocesstask_status_media_type", + Unique: false, + Columns: []*schema.Column{MediaProcessTasksColumns[5], MediaProcessTasksColumns[4]}, + }, + { + Name: "mediaprocesstask_entity_id_status", + Unique: false, + Columns: []*schema.Column{MediaProcessTasksColumns[6], MediaProcessTasksColumns[5]}, + }, + }, + } // MetadataColumns holds the columns for the "metadata" table. MetadataColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, @@ -559,6 +593,7 @@ var ( FilesTable, FsEventsTable, GroupsTable, + MediaProcessTasksTable, MetadataTable, NodesTable, OauthClientsTable, diff --git a/ent/mutation.go b/ent/mutation.go index 8125d95a..f84eab8d 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -17,6 +17,7 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/file" "github.com/cloudreve/Cloudreve/v4/ent/fsevent" "github.com/cloudreve/Cloudreve/v4/ent/group" + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" "github.com/cloudreve/Cloudreve/v4/ent/metadata" "github.com/cloudreve/Cloudreve/v4/ent/node" "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" @@ -43,22 +44,23 @@ const ( OpUpdateOne = ent.OpUpdateOne // Node types. - TypeDavAccount = "DavAccount" - TypeDirectLink = "DirectLink" - TypeEntity = "Entity" - TypeFile = "File" - TypeFsEvent = "FsEvent" - TypeGroup = "Group" - TypeMetadata = "Metadata" - TypeNode = "Node" - TypeOAuthClient = "OAuthClient" - TypeOAuthGrant = "OAuthGrant" - TypePasskey = "Passkey" - TypeSetting = "Setting" - TypeShare = "Share" - TypeStoragePolicy = "StoragePolicy" - TypeTask = "Task" - TypeUser = "User" + TypeDavAccount = "DavAccount" + TypeDirectLink = "DirectLink" + TypeEntity = "Entity" + TypeFile = "File" + TypeFsEvent = "FsEvent" + TypeGroup = "Group" + TypeMediaProcessTask = "MediaProcessTask" + TypeMetadata = "Metadata" + TypeNode = "Node" + TypeOAuthClient = "OAuthClient" + TypeOAuthGrant = "OAuthGrant" + TypePasskey = "Passkey" + TypeSetting = "Setting" + TypeShare = "Share" + TypeStoragePolicy = "StoragePolicy" + TypeTask = "Task" + TypeUser = "User" ) // DavAccountMutation represents an operation that mutates the DavAccount nodes in the graph. @@ -6476,6 +6478,1194 @@ func (m *GroupMutation) ResetEdge(name string) error { return fmt.Errorf("unknown Group edge %s", name) } +// MediaProcessTaskMutation represents an operation that mutates the MediaProcessTask nodes in the graph. +type MediaProcessTaskMutation struct { + config + op Op + typ string + id *int + created_at *time.Time + updated_at *time.Time + deleted_at *time.Time + media_type *mediaprocesstask.MediaType + status *mediaprocesstask.Status + entity_id *int + addentity_id *int + file_id *int + addfile_id *int + owner_id *int + addowner_id *int + attempts *int + addattempts *int + error *string + result_size *int64 + addresult_size *int64 + props **types.MediaProcessTaskProps + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*MediaProcessTask, error) + predicates []predicate.MediaProcessTask +} + +var _ ent.Mutation = (*MediaProcessTaskMutation)(nil) + +// mediaprocesstaskOption allows management of the mutation configuration using functional options. +type mediaprocesstaskOption func(*MediaProcessTaskMutation) + +// newMediaProcessTaskMutation creates new mutation for the MediaProcessTask entity. +func newMediaProcessTaskMutation(c config, op Op, opts ...mediaprocesstaskOption) *MediaProcessTaskMutation { + m := &MediaProcessTaskMutation{ + config: c, + op: op, + typ: TypeMediaProcessTask, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withMediaProcessTaskID sets the ID field of the mutation. +func withMediaProcessTaskID(id int) mediaprocesstaskOption { + return func(m *MediaProcessTaskMutation) { + var ( + err error + once sync.Once + value *MediaProcessTask + ) + m.oldValue = func(ctx context.Context) (*MediaProcessTask, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().MediaProcessTask.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withMediaProcessTask sets the old MediaProcessTask of the mutation. +func withMediaProcessTask(node *MediaProcessTask) mediaprocesstaskOption { + return func(m *MediaProcessTaskMutation) { + m.oldValue = func(context.Context) (*MediaProcessTask, 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 MediaProcessTaskMutation) 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 MediaProcessTaskMutation) 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 *MediaProcessTaskMutation) ID() (id int, 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 *MediaProcessTaskMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().MediaProcessTask.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 *MediaProcessTaskMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *MediaProcessTaskMutation) 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 MediaProcessTask entity. +// If the MediaProcessTask 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 *MediaProcessTaskMutation) 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 *MediaProcessTaskMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetUpdatedAt sets the "updated_at" field. +func (m *MediaProcessTaskMutation) SetUpdatedAt(t time.Time) { + m.updated_at = &t +} + +// UpdatedAt returns the value of the "updated_at" field in the mutation. +func (m *MediaProcessTaskMutation) 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 MediaProcessTask entity. +// If the MediaProcessTask 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 *MediaProcessTaskMutation) 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 *MediaProcessTaskMutation) ResetUpdatedAt() { + m.updated_at = nil +} + +// SetDeletedAt sets the "deleted_at" field. +func (m *MediaProcessTaskMutation) SetDeletedAt(t time.Time) { + m.deleted_at = &t +} + +// DeletedAt returns the value of the "deleted_at" field in the mutation. +func (m *MediaProcessTaskMutation) DeletedAt() (r time.Time, exists bool) { + v := m.deleted_at + if v == nil { + return + } + return *v, true +} + +// OldDeletedAt returns the old "deleted_at" field's value of the MediaProcessTask entity. +// If the MediaProcessTask 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 *MediaProcessTaskMutation) OldDeletedAt(ctx context.Context) (v *time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDeletedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDeletedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDeletedAt: %w", err) + } + return oldValue.DeletedAt, nil +} + +// ClearDeletedAt clears the value of the "deleted_at" field. +func (m *MediaProcessTaskMutation) ClearDeletedAt() { + m.deleted_at = nil + m.clearedFields[mediaprocesstask.FieldDeletedAt] = struct{}{} +} + +// DeletedAtCleared returns if the "deleted_at" field was cleared in this mutation. +func (m *MediaProcessTaskMutation) DeletedAtCleared() bool { + _, ok := m.clearedFields[mediaprocesstask.FieldDeletedAt] + return ok +} + +// ResetDeletedAt resets all changes to the "deleted_at" field. +func (m *MediaProcessTaskMutation) ResetDeletedAt() { + m.deleted_at = nil + delete(m.clearedFields, mediaprocesstask.FieldDeletedAt) +} + +// SetMediaType sets the "media_type" field. +func (m *MediaProcessTaskMutation) SetMediaType(mt mediaprocesstask.MediaType) { + m.media_type = &mt +} + +// MediaType returns the value of the "media_type" field in the mutation. +func (m *MediaProcessTaskMutation) MediaType() (r mediaprocesstask.MediaType, exists bool) { + v := m.media_type + if v == nil { + return + } + return *v, true +} + +// OldMediaType returns the old "media_type" field's value of the MediaProcessTask entity. +// If the MediaProcessTask 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 *MediaProcessTaskMutation) OldMediaType(ctx context.Context) (v mediaprocesstask.MediaType, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldMediaType is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldMediaType requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldMediaType: %w", err) + } + return oldValue.MediaType, nil +} + +// ResetMediaType resets all changes to the "media_type" field. +func (m *MediaProcessTaskMutation) ResetMediaType() { + m.media_type = nil +} + +// SetStatus sets the "status" field. +func (m *MediaProcessTaskMutation) SetStatus(value mediaprocesstask.Status) { + m.status = &value +} + +// Status returns the value of the "status" field in the mutation. +func (m *MediaProcessTaskMutation) Status() (r mediaprocesstask.Status, exists bool) { + v := m.status + if v == nil { + return + } + return *v, true +} + +// OldStatus returns the old "status" field's value of the MediaProcessTask entity. +// If the MediaProcessTask 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 *MediaProcessTaskMutation) OldStatus(ctx context.Context) (v mediaprocesstask.Status, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldStatus is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldStatus requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldStatus: %w", err) + } + return oldValue.Status, nil +} + +// ResetStatus resets all changes to the "status" field. +func (m *MediaProcessTaskMutation) ResetStatus() { + m.status = nil +} + +// SetEntityID sets the "entity_id" field. +func (m *MediaProcessTaskMutation) SetEntityID(i int) { + m.entity_id = &i + m.addentity_id = nil +} + +// EntityID returns the value of the "entity_id" field in the mutation. +func (m *MediaProcessTaskMutation) EntityID() (r int, exists bool) { + v := m.entity_id + if v == nil { + return + } + return *v, true +} + +// OldEntityID returns the old "entity_id" field's value of the MediaProcessTask entity. +// If the MediaProcessTask 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 *MediaProcessTaskMutation) OldEntityID(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldEntityID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldEntityID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldEntityID: %w", err) + } + return oldValue.EntityID, nil +} + +// AddEntityID adds i to the "entity_id" field. +func (m *MediaProcessTaskMutation) AddEntityID(i int) { + if m.addentity_id != nil { + *m.addentity_id += i + } else { + m.addentity_id = &i + } +} + +// AddedEntityID returns the value that was added to the "entity_id" field in this mutation. +func (m *MediaProcessTaskMutation) AddedEntityID() (r int, exists bool) { + v := m.addentity_id + if v == nil { + return + } + return *v, true +} + +// ResetEntityID resets all changes to the "entity_id" field. +func (m *MediaProcessTaskMutation) ResetEntityID() { + m.entity_id = nil + m.addentity_id = nil +} + +// SetFileID sets the "file_id" field. +func (m *MediaProcessTaskMutation) SetFileID(i int) { + m.file_id = &i + m.addfile_id = nil +} + +// FileID returns the value of the "file_id" field in the mutation. +func (m *MediaProcessTaskMutation) FileID() (r int, exists bool) { + v := m.file_id + if v == nil { + return + } + return *v, true +} + +// OldFileID returns the old "file_id" field's value of the MediaProcessTask entity. +// If the MediaProcessTask 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 *MediaProcessTaskMutation) OldFileID(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldFileID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldFileID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldFileID: %w", err) + } + return oldValue.FileID, nil +} + +// AddFileID adds i to the "file_id" field. +func (m *MediaProcessTaskMutation) AddFileID(i int) { + if m.addfile_id != nil { + *m.addfile_id += i + } else { + m.addfile_id = &i + } +} + +// AddedFileID returns the value that was added to the "file_id" field in this mutation. +func (m *MediaProcessTaskMutation) AddedFileID() (r int, exists bool) { + v := m.addfile_id + if v == nil { + return + } + return *v, true +} + +// ClearFileID clears the value of the "file_id" field. +func (m *MediaProcessTaskMutation) ClearFileID() { + m.file_id = nil + m.addfile_id = nil + m.clearedFields[mediaprocesstask.FieldFileID] = struct{}{} +} + +// FileIDCleared returns if the "file_id" field was cleared in this mutation. +func (m *MediaProcessTaskMutation) FileIDCleared() bool { + _, ok := m.clearedFields[mediaprocesstask.FieldFileID] + return ok +} + +// ResetFileID resets all changes to the "file_id" field. +func (m *MediaProcessTaskMutation) ResetFileID() { + m.file_id = nil + m.addfile_id = nil + delete(m.clearedFields, mediaprocesstask.FieldFileID) +} + +// SetOwnerID sets the "owner_id" field. +func (m *MediaProcessTaskMutation) SetOwnerID(i int) { + m.owner_id = &i + m.addowner_id = nil +} + +// OwnerID returns the value of the "owner_id" field in the mutation. +func (m *MediaProcessTaskMutation) OwnerID() (r int, exists bool) { + v := m.owner_id + if v == nil { + return + } + return *v, true +} + +// OldOwnerID returns the old "owner_id" field's value of the MediaProcessTask entity. +// If the MediaProcessTask 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 *MediaProcessTaskMutation) OldOwnerID(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldOwnerID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldOwnerID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldOwnerID: %w", err) + } + return oldValue.OwnerID, nil +} + +// AddOwnerID adds i to the "owner_id" field. +func (m *MediaProcessTaskMutation) AddOwnerID(i int) { + if m.addowner_id != nil { + *m.addowner_id += i + } else { + m.addowner_id = &i + } +} + +// AddedOwnerID returns the value that was added to the "owner_id" field in this mutation. +func (m *MediaProcessTaskMutation) AddedOwnerID() (r int, exists bool) { + v := m.addowner_id + if v == nil { + return + } + return *v, true +} + +// ResetOwnerID resets all changes to the "owner_id" field. +func (m *MediaProcessTaskMutation) ResetOwnerID() { + m.owner_id = nil + m.addowner_id = nil +} + +// SetAttempts sets the "attempts" field. +func (m *MediaProcessTaskMutation) SetAttempts(i int) { + m.attempts = &i + m.addattempts = nil +} + +// Attempts returns the value of the "attempts" field in the mutation. +func (m *MediaProcessTaskMutation) Attempts() (r int, exists bool) { + v := m.attempts + if v == nil { + return + } + return *v, true +} + +// OldAttempts returns the old "attempts" field's value of the MediaProcessTask entity. +// If the MediaProcessTask 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 *MediaProcessTaskMutation) OldAttempts(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldAttempts is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldAttempts requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldAttempts: %w", err) + } + return oldValue.Attempts, nil +} + +// AddAttempts adds i to the "attempts" field. +func (m *MediaProcessTaskMutation) AddAttempts(i int) { + if m.addattempts != nil { + *m.addattempts += i + } else { + m.addattempts = &i + } +} + +// AddedAttempts returns the value that was added to the "attempts" field in this mutation. +func (m *MediaProcessTaskMutation) AddedAttempts() (r int, exists bool) { + v := m.addattempts + if v == nil { + return + } + return *v, true +} + +// ResetAttempts resets all changes to the "attempts" field. +func (m *MediaProcessTaskMutation) ResetAttempts() { + m.attempts = nil + m.addattempts = nil +} + +// SetError sets the "error" field. +func (m *MediaProcessTaskMutation) SetError(s string) { + m.error = &s +} + +// Error returns the value of the "error" field in the mutation. +func (m *MediaProcessTaskMutation) Error() (r string, exists bool) { + v := m.error + if v == nil { + return + } + return *v, true +} + +// OldError returns the old "error" field's value of the MediaProcessTask entity. +// If the MediaProcessTask 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 *MediaProcessTaskMutation) OldError(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldError is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldError requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldError: %w", err) + } + return oldValue.Error, nil +} + +// ClearError clears the value of the "error" field. +func (m *MediaProcessTaskMutation) ClearError() { + m.error = nil + m.clearedFields[mediaprocesstask.FieldError] = struct{}{} +} + +// ErrorCleared returns if the "error" field was cleared in this mutation. +func (m *MediaProcessTaskMutation) ErrorCleared() bool { + _, ok := m.clearedFields[mediaprocesstask.FieldError] + return ok +} + +// ResetError resets all changes to the "error" field. +func (m *MediaProcessTaskMutation) ResetError() { + m.error = nil + delete(m.clearedFields, mediaprocesstask.FieldError) +} + +// SetResultSize sets the "result_size" field. +func (m *MediaProcessTaskMutation) SetResultSize(i int64) { + m.result_size = &i + m.addresult_size = nil +} + +// ResultSize returns the value of the "result_size" field in the mutation. +func (m *MediaProcessTaskMutation) ResultSize() (r int64, exists bool) { + v := m.result_size + if v == nil { + return + } + return *v, true +} + +// OldResultSize returns the old "result_size" field's value of the MediaProcessTask entity. +// If the MediaProcessTask 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 *MediaProcessTaskMutation) OldResultSize(ctx context.Context) (v int64, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldResultSize is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldResultSize requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldResultSize: %w", err) + } + return oldValue.ResultSize, nil +} + +// AddResultSize adds i to the "result_size" field. +func (m *MediaProcessTaskMutation) AddResultSize(i int64) { + if m.addresult_size != nil { + *m.addresult_size += i + } else { + m.addresult_size = &i + } +} + +// AddedResultSize returns the value that was added to the "result_size" field in this mutation. +func (m *MediaProcessTaskMutation) AddedResultSize() (r int64, exists bool) { + v := m.addresult_size + if v == nil { + return + } + return *v, true +} + +// ClearResultSize clears the value of the "result_size" field. +func (m *MediaProcessTaskMutation) ClearResultSize() { + m.result_size = nil + m.addresult_size = nil + m.clearedFields[mediaprocesstask.FieldResultSize] = struct{}{} +} + +// ResultSizeCleared returns if the "result_size" field was cleared in this mutation. +func (m *MediaProcessTaskMutation) ResultSizeCleared() bool { + _, ok := m.clearedFields[mediaprocesstask.FieldResultSize] + return ok +} + +// ResetResultSize resets all changes to the "result_size" field. +func (m *MediaProcessTaskMutation) ResetResultSize() { + m.result_size = nil + m.addresult_size = nil + delete(m.clearedFields, mediaprocesstask.FieldResultSize) +} + +// SetProps sets the "props" field. +func (m *MediaProcessTaskMutation) SetProps(tptp *types.MediaProcessTaskProps) { + m.props = &tptp +} + +// Props returns the value of the "props" field in the mutation. +func (m *MediaProcessTaskMutation) Props() (r *types.MediaProcessTaskProps, exists bool) { + v := m.props + if v == nil { + return + } + return *v, true +} + +// OldProps returns the old "props" field's value of the MediaProcessTask entity. +// If the MediaProcessTask 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 *MediaProcessTaskMutation) OldProps(ctx context.Context) (v *types.MediaProcessTaskProps, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldProps is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldProps requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldProps: %w", err) + } + return oldValue.Props, nil +} + +// ClearProps clears the value of the "props" field. +func (m *MediaProcessTaskMutation) ClearProps() { + m.props = nil + m.clearedFields[mediaprocesstask.FieldProps] = struct{}{} +} + +// PropsCleared returns if the "props" field was cleared in this mutation. +func (m *MediaProcessTaskMutation) PropsCleared() bool { + _, ok := m.clearedFields[mediaprocesstask.FieldProps] + return ok +} + +// ResetProps resets all changes to the "props" field. +func (m *MediaProcessTaskMutation) ResetProps() { + m.props = nil + delete(m.clearedFields, mediaprocesstask.FieldProps) +} + +// Where appends a list predicates to the MediaProcessTaskMutation builder. +func (m *MediaProcessTaskMutation) Where(ps ...predicate.MediaProcessTask) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the MediaProcessTaskMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *MediaProcessTaskMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.MediaProcessTask, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *MediaProcessTaskMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *MediaProcessTaskMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (MediaProcessTask). +func (m *MediaProcessTaskMutation) 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 *MediaProcessTaskMutation) Fields() []string { + fields := make([]string, 0, 12) + if m.created_at != nil { + fields = append(fields, mediaprocesstask.FieldCreatedAt) + } + if m.updated_at != nil { + fields = append(fields, mediaprocesstask.FieldUpdatedAt) + } + if m.deleted_at != nil { + fields = append(fields, mediaprocesstask.FieldDeletedAt) + } + if m.media_type != nil { + fields = append(fields, mediaprocesstask.FieldMediaType) + } + if m.status != nil { + fields = append(fields, mediaprocesstask.FieldStatus) + } + if m.entity_id != nil { + fields = append(fields, mediaprocesstask.FieldEntityID) + } + if m.file_id != nil { + fields = append(fields, mediaprocesstask.FieldFileID) + } + if m.owner_id != nil { + fields = append(fields, mediaprocesstask.FieldOwnerID) + } + if m.attempts != nil { + fields = append(fields, mediaprocesstask.FieldAttempts) + } + if m.error != nil { + fields = append(fields, mediaprocesstask.FieldError) + } + if m.result_size != nil { + fields = append(fields, mediaprocesstask.FieldResultSize) + } + if m.props != nil { + fields = append(fields, mediaprocesstask.FieldProps) + } + 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 *MediaProcessTaskMutation) Field(name string) (ent.Value, bool) { + switch name { + case mediaprocesstask.FieldCreatedAt: + return m.CreatedAt() + case mediaprocesstask.FieldUpdatedAt: + return m.UpdatedAt() + case mediaprocesstask.FieldDeletedAt: + return m.DeletedAt() + case mediaprocesstask.FieldMediaType: + return m.MediaType() + case mediaprocesstask.FieldStatus: + return m.Status() + case mediaprocesstask.FieldEntityID: + return m.EntityID() + case mediaprocesstask.FieldFileID: + return m.FileID() + case mediaprocesstask.FieldOwnerID: + return m.OwnerID() + case mediaprocesstask.FieldAttempts: + return m.Attempts() + case mediaprocesstask.FieldError: + return m.Error() + case mediaprocesstask.FieldResultSize: + return m.ResultSize() + case mediaprocesstask.FieldProps: + return m.Props() + } + 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 *MediaProcessTaskMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case mediaprocesstask.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case mediaprocesstask.FieldUpdatedAt: + return m.OldUpdatedAt(ctx) + case mediaprocesstask.FieldDeletedAt: + return m.OldDeletedAt(ctx) + case mediaprocesstask.FieldMediaType: + return m.OldMediaType(ctx) + case mediaprocesstask.FieldStatus: + return m.OldStatus(ctx) + case mediaprocesstask.FieldEntityID: + return m.OldEntityID(ctx) + case mediaprocesstask.FieldFileID: + return m.OldFileID(ctx) + case mediaprocesstask.FieldOwnerID: + return m.OldOwnerID(ctx) + case mediaprocesstask.FieldAttempts: + return m.OldAttempts(ctx) + case mediaprocesstask.FieldError: + return m.OldError(ctx) + case mediaprocesstask.FieldResultSize: + return m.OldResultSize(ctx) + case mediaprocesstask.FieldProps: + return m.OldProps(ctx) + } + return nil, fmt.Errorf("unknown MediaProcessTask 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 *MediaProcessTaskMutation) SetField(name string, value ent.Value) error { + switch name { + case mediaprocesstask.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 mediaprocesstask.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 mediaprocesstask.FieldDeletedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDeletedAt(v) + return nil + case mediaprocesstask.FieldMediaType: + v, ok := value.(mediaprocesstask.MediaType) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetMediaType(v) + return nil + case mediaprocesstask.FieldStatus: + v, ok := value.(mediaprocesstask.Status) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetStatus(v) + return nil + case mediaprocesstask.FieldEntityID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetEntityID(v) + return nil + case mediaprocesstask.FieldFileID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetFileID(v) + return nil + case mediaprocesstask.FieldOwnerID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetOwnerID(v) + return nil + case mediaprocesstask.FieldAttempts: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetAttempts(v) + return nil + case mediaprocesstask.FieldError: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetError(v) + return nil + case mediaprocesstask.FieldResultSize: + v, ok := value.(int64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetResultSize(v) + return nil + case mediaprocesstask.FieldProps: + v, ok := value.(*types.MediaProcessTaskProps) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetProps(v) + return nil + } + return fmt.Errorf("unknown MediaProcessTask field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *MediaProcessTaskMutation) AddedFields() []string { + var fields []string + if m.addentity_id != nil { + fields = append(fields, mediaprocesstask.FieldEntityID) + } + if m.addfile_id != nil { + fields = append(fields, mediaprocesstask.FieldFileID) + } + if m.addowner_id != nil { + fields = append(fields, mediaprocesstask.FieldOwnerID) + } + if m.addattempts != nil { + fields = append(fields, mediaprocesstask.FieldAttempts) + } + if m.addresult_size != nil { + fields = append(fields, mediaprocesstask.FieldResultSize) + } + 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 *MediaProcessTaskMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case mediaprocesstask.FieldEntityID: + return m.AddedEntityID() + case mediaprocesstask.FieldFileID: + return m.AddedFileID() + case mediaprocesstask.FieldOwnerID: + return m.AddedOwnerID() + case mediaprocesstask.FieldAttempts: + return m.AddedAttempts() + case mediaprocesstask.FieldResultSize: + return m.AddedResultSize() + } + 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 *MediaProcessTaskMutation) AddField(name string, value ent.Value) error { + switch name { + case mediaprocesstask.FieldEntityID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddEntityID(v) + return nil + case mediaprocesstask.FieldFileID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddFileID(v) + return nil + case mediaprocesstask.FieldOwnerID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddOwnerID(v) + return nil + case mediaprocesstask.FieldAttempts: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddAttempts(v) + return nil + case mediaprocesstask.FieldResultSize: + v, ok := value.(int64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddResultSize(v) + return nil + } + return fmt.Errorf("unknown MediaProcessTask numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *MediaProcessTaskMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(mediaprocesstask.FieldDeletedAt) { + fields = append(fields, mediaprocesstask.FieldDeletedAt) + } + if m.FieldCleared(mediaprocesstask.FieldFileID) { + fields = append(fields, mediaprocesstask.FieldFileID) + } + if m.FieldCleared(mediaprocesstask.FieldError) { + fields = append(fields, mediaprocesstask.FieldError) + } + if m.FieldCleared(mediaprocesstask.FieldResultSize) { + fields = append(fields, mediaprocesstask.FieldResultSize) + } + if m.FieldCleared(mediaprocesstask.FieldProps) { + fields = append(fields, mediaprocesstask.FieldProps) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *MediaProcessTaskMutation) 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 *MediaProcessTaskMutation) ClearField(name string) error { + switch name { + case mediaprocesstask.FieldDeletedAt: + m.ClearDeletedAt() + return nil + case mediaprocesstask.FieldFileID: + m.ClearFileID() + return nil + case mediaprocesstask.FieldError: + m.ClearError() + return nil + case mediaprocesstask.FieldResultSize: + m.ClearResultSize() + return nil + case mediaprocesstask.FieldProps: + m.ClearProps() + return nil + } + return fmt.Errorf("unknown MediaProcessTask 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 *MediaProcessTaskMutation) ResetField(name string) error { + switch name { + case mediaprocesstask.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case mediaprocesstask.FieldUpdatedAt: + m.ResetUpdatedAt() + return nil + case mediaprocesstask.FieldDeletedAt: + m.ResetDeletedAt() + return nil + case mediaprocesstask.FieldMediaType: + m.ResetMediaType() + return nil + case mediaprocesstask.FieldStatus: + m.ResetStatus() + return nil + case mediaprocesstask.FieldEntityID: + m.ResetEntityID() + return nil + case mediaprocesstask.FieldFileID: + m.ResetFileID() + return nil + case mediaprocesstask.FieldOwnerID: + m.ResetOwnerID() + return nil + case mediaprocesstask.FieldAttempts: + m.ResetAttempts() + return nil + case mediaprocesstask.FieldError: + m.ResetError() + return nil + case mediaprocesstask.FieldResultSize: + m.ResetResultSize() + return nil + case mediaprocesstask.FieldProps: + m.ResetProps() + return nil + } + return fmt.Errorf("unknown MediaProcessTask field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *MediaProcessTaskMutation) 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 *MediaProcessTaskMutation) AddedIDs(name string) []ent.Value { + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *MediaProcessTaskMutation) 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 *MediaProcessTaskMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *MediaProcessTaskMutation) 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 *MediaProcessTaskMutation) 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 *MediaProcessTaskMutation) ClearEdge(name string) error { + return fmt.Errorf("unknown MediaProcessTask 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 *MediaProcessTaskMutation) ResetEdge(name string) error { + return fmt.Errorf("unknown MediaProcessTask edge %s", name) +} + // MetadataMutation represents an operation that mutates the Metadata nodes in the graph. type MetadataMutation struct { config diff --git a/ent/mutationhelper.go b/ent/mutationhelper.go index 2361bddf..8548bc1f 100644 --- a/ent/mutationhelper.go +++ b/ent/mutationhelper.go @@ -40,6 +40,12 @@ func (m *GroupMutation) SetRawID(t int) { // SetUpdatedAt sets the "updated_at" field. +func (m *MediaProcessTaskMutation) SetRawID(t int) { + m.id = &t +} + +// SetUpdatedAt sets the "updated_at" field. + func (m *MetadataMutation) SetRawID(t int) { m.id = &t } diff --git a/ent/predicate/predicate.go b/ent/predicate/predicate.go index d258dac0..e9ba684a 100644 --- a/ent/predicate/predicate.go +++ b/ent/predicate/predicate.go @@ -24,6 +24,9 @@ type FsEvent func(*sql.Selector) // Group is the predicate function for group builders. type Group func(*sql.Selector) +// MediaProcessTask is the predicate function for mediaprocesstask builders. +type MediaProcessTask func(*sql.Selector) + // Metadata is the predicate function for metadata builders. type Metadata func(*sql.Selector) diff --git a/ent/runtime/runtime.go b/ent/runtime/runtime.go index 40303c99..b52556ba 100644 --- a/ent/runtime/runtime.go +++ b/ent/runtime/runtime.go @@ -11,6 +11,7 @@ import ( "github.com/cloudreve/Cloudreve/v4/ent/file" "github.com/cloudreve/Cloudreve/v4/ent/fsevent" "github.com/cloudreve/Cloudreve/v4/ent/group" + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" "github.com/cloudreve/Cloudreve/v4/ent/metadata" "github.com/cloudreve/Cloudreve/v4/ent/node" "github.com/cloudreve/Cloudreve/v4/ent/oauthclient" @@ -152,6 +153,29 @@ func init() { groupDescSettings := groupFields[4].Descriptor() // group.DefaultSettings holds the default value on creation for the settings field. group.DefaultSettings = groupDescSettings.Default.(*types.GroupSetting) + mediaprocesstaskMixin := schema.MediaProcessTask{}.Mixin() + mediaprocesstaskMixinHooks0 := mediaprocesstaskMixin[0].Hooks() + mediaprocesstask.Hooks[0] = mediaprocesstaskMixinHooks0[0] + mediaprocesstaskMixinInters0 := mediaprocesstaskMixin[0].Interceptors() + mediaprocesstask.Interceptors[0] = mediaprocesstaskMixinInters0[0] + mediaprocesstaskMixinFields0 := mediaprocesstaskMixin[0].Fields() + _ = mediaprocesstaskMixinFields0 + mediaprocesstaskFields := schema.MediaProcessTask{}.Fields() + _ = mediaprocesstaskFields + // mediaprocesstaskDescCreatedAt is the schema descriptor for created_at field. + mediaprocesstaskDescCreatedAt := mediaprocesstaskMixinFields0[0].Descriptor() + // mediaprocesstask.DefaultCreatedAt holds the default value on creation for the created_at field. + mediaprocesstask.DefaultCreatedAt = mediaprocesstaskDescCreatedAt.Default.(func() time.Time) + // mediaprocesstaskDescUpdatedAt is the schema descriptor for updated_at field. + mediaprocesstaskDescUpdatedAt := mediaprocesstaskMixinFields0[1].Descriptor() + // mediaprocesstask.DefaultUpdatedAt holds the default value on creation for the updated_at field. + mediaprocesstask.DefaultUpdatedAt = mediaprocesstaskDescUpdatedAt.Default.(func() time.Time) + // mediaprocesstask.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field. + mediaprocesstask.UpdateDefaultUpdatedAt = mediaprocesstaskDescUpdatedAt.UpdateDefault.(func() time.Time) + // mediaprocesstaskDescAttempts is the schema descriptor for attempts field. + mediaprocesstaskDescAttempts := mediaprocesstaskFields[5].Descriptor() + // mediaprocesstask.DefaultAttempts holds the default value on creation for the attempts field. + mediaprocesstask.DefaultAttempts = mediaprocesstaskDescAttempts.Default.(int) metadataMixin := schema.Metadata{}.Mixin() metadataMixinHooks0 := metadataMixin[0].Hooks() metadata.Hooks[0] = metadataMixinHooks0[0] diff --git a/ent/schema/mediaprocesstask.go b/ent/schema/mediaprocesstask.go new file mode 100644 index 00000000..0cd23a9a --- /dev/null +++ b/ent/schema/mediaprocesstask.go @@ -0,0 +1,67 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/schema/field" + "entgo.io/ent/schema/index" + "github.com/cloudreve/Cloudreve/v4/inventory/types" +) + +// MediaProcessTask holds the schema definition for the MediaProcessTask entity. +// +// It is a deferred media post-processing work item (APP-101): one row per blob +// pending compression. The table is shared between image and video work via the +// media_type discriminator (video is a follow-up ticket). +// +// The references to entity/file/owner are stored as plain int columns (no ent +// FK edges) on purpose: entities are hard-deleted during recycle +// (inventory/file.go), so a hard FK constraint would break that path. The task +// resolves them through the existing inventory clients and self-heals (skips) +// when the referenced blob is gone. +type MediaProcessTask struct { + ent.Schema +} + +// Fields of the MediaProcessTask. +func (MediaProcessTask) Fields() []ent.Field { + return []ent.Field{ + field.Enum("media_type"). + Values("image", "video"). + Default("image"), + field.Enum("status"). + Values("pending", "processing", "done", "failed", "skipped"). + Default("pending"), + // entity_id is the physical blob to process (required). + field.Int("entity_id"), + // file_id is the logical file, for navigation/write-back (optional: the + // file may be gone by processing time). + field.Int("file_id").Optional(), + // owner_id is the user that owns the blob, for quota accounting (required). + field.Int("owner_id"), + field.Int("attempts").Default(0), + field.Text("error").Optional(), + field.Int64("result_size").Optional(), + field.JSON("props", &types.MediaProcessTaskProps{}).Optional(), + } +} + +// Edges of the MediaProcessTask. +func (MediaProcessTask) Edges() []ent.Edge { + return nil +} + +// Indexes of the MediaProcessTask. +func (MediaProcessTask) Indexes() []ent.Index { + return []ent.Index{ + // Batch pickup: ListPending filters by (status, media_type). + index.Fields("status", "media_type"), + // Idempotency guard: "is there an active row for this entity?". + index.Fields("entity_id", "status"), + } +} + +func (MediaProcessTask) Mixin() []ent.Mixin { + return []ent.Mixin{ + CommonMixin{}, + } +} diff --git a/ent/tx.go b/ent/tx.go index 9d71651a..cb6537a3 100644 --- a/ent/tx.go +++ b/ent/tx.go @@ -26,6 +26,8 @@ type Tx struct { FsEvent *FsEventClient // Group is the client for interacting with the Group builders. Group *GroupClient + // MediaProcessTask is the client for interacting with the MediaProcessTask builders. + MediaProcessTask *MediaProcessTaskClient // Metadata is the client for interacting with the Metadata builders. Metadata *MetadataClient // Node is the client for interacting with the Node builders. @@ -183,6 +185,7 @@ func (tx *Tx) init() { tx.File = NewFileClient(tx.config) tx.FsEvent = NewFsEventClient(tx.config) tx.Group = NewGroupClient(tx.config) + tx.MediaProcessTask = NewMediaProcessTaskClient(tx.config) tx.Metadata = NewMetadataClient(tx.config) tx.Node = NewNodeClient(tx.config) tx.OAuthClient = NewOAuthClientClient(tx.config) diff --git a/inventory/mediaprocess.go b/inventory/mediaprocess.go new file mode 100644 index 00000000..e20aaae6 --- /dev/null +++ b/inventory/mediaprocess.go @@ -0,0 +1,162 @@ +package inventory + +import ( + "context" + "fmt" + + "github.com/cloudreve/Cloudreve/v4/ent" + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" + "github.com/cloudreve/Cloudreve/v4/inventory/types" + "github.com/cloudreve/Cloudreve/v4/pkg/conf" +) + +// MediaProcessClient is the data-access layer for the media_process_task table +// (APP-101): the queue of blobs pending deferred post-processing (compression). +type MediaProcessClient interface { + TxOperator + // Enqueue registers a blob as pending for the given media type. It is + // idempotent: if an active (pending/processing) row already exists for the + // entity, it returns that row instead of creating a duplicate. + Enqueue(ctx context.Context, args *MediaProcessEnqueueArgs) (*ent.MediaProcessTask, error) + // HasActive reports whether an active (pending/processing) row exists for the + // given entity id. + HasActive(ctx context.Context, entityID int) (bool, error) + // ListPending returns up to limit pending rows of the given media type, + // oldest first. + ListPending(ctx context.Context, mediaType mediaprocesstask.MediaType, limit int) ([]*ent.MediaProcessTask, error) + // GetByID returns a row by its id. + GetByID(ctx context.Context, id int) (*ent.MediaProcessTask, error) + // SetStatus transitions a row to the given status, bumping attempts and + // persisting error/result_size/props when supplied. + SetStatus(ctx context.Context, id int, args *MediaProcessStatusArgs) (*ent.MediaProcessTask, error) +} + +type ( + MediaProcessEnqueueArgs struct { + EntityID int + FileID int + OwnerID int + MediaType mediaprocesstask.MediaType + Props *types.MediaProcessTaskProps + } + + MediaProcessStatusArgs struct { + Status mediaprocesstask.Status + BumpAttempts bool + Error string + ResultSize int64 + Props *types.MediaProcessTaskProps + } +) + +func NewMediaProcessClient(client *ent.Client, dbType conf.DBType) MediaProcessClient { + return &mediaProcessClient{client: client, maxSQlParam: sqlParamLimit(dbType)} +} + +type mediaProcessClient struct { + maxSQlParam int + client *ent.Client +} + +func (c *mediaProcessClient) SetClient(newClient *ent.Client) TxOperator { + return &mediaProcessClient{client: newClient, maxSQlParam: c.maxSQlParam} +} + +func (c *mediaProcessClient) GetClient() *ent.Client { + return c.client +} + +func (c *mediaProcessClient) HasActive(ctx context.Context, entityID int) (bool, error) { + return c.client.MediaProcessTask.Query(). + Where( + mediaprocesstask.EntityID(entityID), + mediaprocesstask.StatusIn(mediaprocesstask.StatusPending, mediaprocesstask.StatusProcessing), + ). + Exist(ctx) +} + +func (c *mediaProcessClient) Enqueue(ctx context.Context, args *MediaProcessEnqueueArgs) (*ent.MediaProcessTask, error) { + mediaType := args.MediaType + if mediaType == "" { + mediaType = mediaprocesstask.MediaTypeImage + } + + // Idempotency: reuse an existing active row for this entity. + existing, err := c.client.MediaProcessTask.Query(). + Where( + mediaprocesstask.EntityID(args.EntityID), + mediaprocesstask.StatusIn(mediaprocesstask.StatusPending, mediaprocesstask.StatusProcessing), + ). + First(ctx) + if err == nil { + return existing, nil + } + if !ent.IsNotFound(err) { + return nil, fmt.Errorf("failed to query active media process task: %w", err) + } + + stm := c.client.MediaProcessTask.Create(). + SetEntityID(args.EntityID). + SetOwnerID(args.OwnerID). + SetMediaType(mediaType). + SetStatus(mediaprocesstask.StatusPending) + if args.FileID != 0 { + stm.SetFileID(args.FileID) + } + if args.Props != nil { + stm.SetProps(args.Props) + } + + created, err := stm.Save(ctx) + if err != nil { + return nil, fmt.Errorf("failed to enqueue media process task: %w", err) + } + + return created, nil +} + +func (c *mediaProcessClient) ListPending(ctx context.Context, mediaType mediaprocesstask.MediaType, limit int) ([]*ent.MediaProcessTask, error) { + if limit <= 0 { + limit = 50 + } + if mediaType == "" { + mediaType = mediaprocesstask.MediaTypeImage + } + + return c.client.MediaProcessTask.Query(). + Where( + mediaprocesstask.StatusEQ(mediaprocesstask.StatusPending), + mediaprocesstask.MediaTypeEQ(mediaType), + ). + Order(ent.Asc(mediaprocesstask.FieldID)). + Limit(limit). + All(ctx) +} + +func (c *mediaProcessClient) GetByID(ctx context.Context, id int) (*ent.MediaProcessTask, error) { + return c.client.MediaProcessTask.Get(ctx, id) +} + +func (c *mediaProcessClient) SetStatus(ctx context.Context, id int, args *MediaProcessStatusArgs) (*ent.MediaProcessTask, error) { + stm := c.client.MediaProcessTask.UpdateOneID(id). + SetStatus(args.Status) + if args.BumpAttempts { + stm.AddAttempts(1) + } + if args.Error != "" { + stm.SetError(args.Error) + } + if args.ResultSize > 0 { + stm.SetResultSize(args.ResultSize) + } + if args.Props != nil { + stm.SetProps(args.Props) + } + + updated, err := stm.Save(ctx) + if err != nil { + return nil, fmt.Errorf("failed to update media process task status: %w", err) + } + + return updated, nil +} diff --git a/inventory/mediaprocess_test.go b/inventory/mediaprocess_test.go new file mode 100644 index 00000000..2d628383 --- /dev/null +++ b/inventory/mediaprocess_test.go @@ -0,0 +1,73 @@ +package inventory + +import ( + "context" + "testing" + + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestMediaProcessEnqueueIdempotent covers APP-101: Enqueue is idempotent per +// active entity, ListPending filters by status+media_type, and SetStatus(done) +// clears the active guard so a fresh Enqueue is allowed again. +func TestMediaProcessEnqueueIdempotent(t *testing.T) { + ctx := context.Background() + client := newTestClient(t) + c := NewMediaProcessClient(client, "sqlite") + + // First enqueue creates a pending row. + row1, err := c.Enqueue(ctx, &MediaProcessEnqueueArgs{ + EntityID: 101, FileID: 11, OwnerID: 1, MediaType: mediaprocesstask.MediaTypeImage, + }) + require.NoError(t, err) + assert.Equal(t, mediaprocesstask.StatusPending, row1.Status) + assert.Equal(t, 101, row1.EntityID) + + // Second enqueue for the same entity returns the same row (no duplicate). + row2, err := c.Enqueue(ctx, &MediaProcessEnqueueArgs{ + EntityID: 101, FileID: 11, OwnerID: 1, MediaType: mediaprocesstask.MediaTypeImage, + }) + require.NoError(t, err) + assert.Equal(t, row1.ID, row2.ID, "duplicate enqueue must reuse the active row") + + active, err := c.HasActive(ctx, 101) + require.NoError(t, err) + assert.True(t, active) + + // A different entity is a separate row. + _, err = c.Enqueue(ctx, &MediaProcessEnqueueArgs{ + EntityID: 202, FileID: 22, OwnerID: 1, MediaType: mediaprocesstask.MediaTypeImage, + }) + require.NoError(t, err) + + // ListPending returns both pending image rows. + pending, err := c.ListPending(ctx, mediaprocesstask.MediaTypeImage, 50) + require.NoError(t, err) + assert.Len(t, pending, 2) + + // Video pending is empty (discriminator filter). + vids, err := c.ListPending(ctx, mediaprocesstask.MediaTypeVideo, 50) + require.NoError(t, err) + assert.Len(t, vids, 0) + + // Marking entity 101 done clears the active guard and drops it from pending. + _, err = c.SetStatus(ctx, row1.ID, &MediaProcessStatusArgs{Status: mediaprocesstask.StatusDone, ResultSize: 1234}) + require.NoError(t, err) + + active, err = c.HasActive(ctx, 101) + require.NoError(t, err) + assert.False(t, active, "done row must not count as active") + + pending, err = c.ListPending(ctx, mediaprocesstask.MediaTypeImage, 50) + require.NoError(t, err) + assert.Len(t, pending, 1, "only the still-pending entity remains") + + // After done, a new enqueue for the same entity is allowed (re-upload case). + row3, err := c.Enqueue(ctx, &MediaProcessEnqueueArgs{ + EntityID: 101, FileID: 11, OwnerID: 1, MediaType: mediaprocesstask.MediaTypeImage, + }) + require.NoError(t, err) + assert.NotEqual(t, row1.ID, row3.ID, "a new pending row is created after the previous one is done") +} diff --git a/inventory/setting.go b/inventory/setting.go index 78ce9de9..2f432668 100644 --- a/inventory/setting.go +++ b/inventory/setting.go @@ -625,6 +625,26 @@ var DefaultSettings = map[string]string{ "queue_remote_download_backoff_max_duration": "600", "queue_remote_download_max_retry": "5", "queue_remote_download_retry_delay": "0", + // APP-101 — media post-processing (image compression) queue tuning + cron. + "queue_media_process_max_execution": "3600", + "queue_media_process_backoff_factor": "2", + "queue_media_process_backoff_max_duration": "60", + "queue_media_process_max_retry": "3", + "queue_media_process_retry_delay": "5", + "cron_media_process": "@every 1h", + // Master switch + compression parameters. Engine defaults to vips (better for + // stills; present in the deploy image alongside ffmpeg). Worker count uses a + // dedicated key (the generic queue worker_num getter has an upstream key bug), + // default 1 to keep CPU usage bounded. + "media_compress_image_enabled": "0", + "media_compress_engine": "vips", + "media_compress_worker_num": "1", + "media_compress_batch_size": "50", + "media_compress_image_quality": "80", + "media_compress_image_format": "keep", + "media_compress_image_args": "", + "media_compress_result_mode": "version", + "media_compress_min_size": "204800", // 200 KB "entity_url_default_ttl": "3600", "entity_url_cache_margin": "600", "media_meta": "1", diff --git a/inventory/types/types.go b/inventory/types/types.go index 8af1614c..2d8f2f7a 100644 --- a/inventory/types/types.go +++ b/inventory/types/types.go @@ -17,6 +17,20 @@ type ( DisableViewSync bool `json:"disable_view_sync,omitempty"` FsViewMap map[string]ExplorerView `json:"fs_view_map,omitempty"` ShareLinksInProfile ShareLinksInProfileLevel `json:"share_links_in_profile,omitempty"` + // AutoCompressImages opts this user's uploaded images into the deferred + // media post-processing (compression) pipeline (APP-101). Default off. + AutoCompressImages bool `json:"auto_compress_images,omitempty"` + } + + // MediaProcessTaskProps is the JSON payload of a media_process_task row + // (APP-101). Signature is the idempotency fingerprint (engine+quality+format + // +original size) so a blob is not recompressed with the same parameters. + MediaProcessTaskProps struct { + Engine string `json:"engine,omitempty"` + Quality int `json:"quality,omitempty"` + Format string `json:"format,omitempty"` + OriginalSize int64 `json:"original_size,omitempty"` + Signature string `json:"signature,omitempty"` } ShareLinksInProfileLevel string diff --git a/pkg/filemanager/manager/mediacompress.go b/pkg/filemanager/manager/mediacompress.go new file mode 100644 index 00000000..5d91b557 --- /dev/null +++ b/pkg/filemanager/manager/mediacompress.go @@ -0,0 +1,506 @@ +package manager + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + + "github.com/cloudreve/Cloudreve/v4/application/dependency" + "github.com/cloudreve/Cloudreve/v4/ent" + "github.com/cloudreve/Cloudreve/v4/ent/mediaprocesstask" + "github.com/cloudreve/Cloudreve/v4/ent/task" + "github.com/cloudreve/Cloudreve/v4/inventory" + "github.com/cloudreve/Cloudreve/v4/inventory/types" + "github.com/cloudreve/Cloudreve/v4/pkg/crontab" + "github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs" + "github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs/dbfs" + "github.com/cloudreve/Cloudreve/v4/pkg/logging" + "github.com/cloudreve/Cloudreve/v4/pkg/queue" + "github.com/cloudreve/Cloudreve/v4/pkg/setting" + "github.com/cloudreve/Cloudreve/v4/pkg/util" + "github.com/gofrs/uuid" +) + +// skipMediaProcessEnqueueKey marks a context as originating from the media +// compression write-back, so CompleteUpload does not re-enqueue a compression +// task for the freshly written (already compressed) version — which would loop. +type skipMediaProcessEnqueueKey struct{} + +func withSkipMediaProcessEnqueue(ctx context.Context) context.Context { + return context.WithValue(ctx, skipMediaProcessEnqueueKey{}, true) +} + +func shouldSkipMediaProcessEnqueue(ctx context.Context) bool { + v, _ := ctx.Value(skipMediaProcessEnqueueKey{}).(bool) + return v +} + +const mediaCompressTempFolder = "media_compress" + +type ( + // MediaCompressTask is the queue task that compresses a single blob recorded + // in the media_process_task table (APP-101). One task == one image. + MediaCompressTask struct { + *queue.DBTask + + l logging.Logger + state *MediaCompressTaskState + } + + MediaCompressTaskState struct { + // RowID is the media_process_task row id this task processes. + RowID int `json:"row_id"` + } +) + +func init() { + queue.RegisterResumableTaskFactory(queue.MediaCompressTaskType, NewMediaCompressTaskFromModel) + + // Cron: enqueue a bounded batch of pending images onto the dedicated + // MediaProcessQueue. Mirrors pkg/filemanager/manager/recycle.go. + crontab.Register(setting.CronTypeMediaProcess, func(ctx context.Context) { + dep := dependency.FromContext(ctx) + l := dep.Logger() + + mp := dep.SettingProvider().MediaProcess(ctx) + if !mp.ImageEnabled { + return + } + + rows, err := dep.MediaProcessClient().ListPending(ctx, mediaprocesstask.MediaTypeImage, mp.BatchSize) + if err != nil { + l.Error("Failed to list pending media process tasks: %s", err) + return + } + if len(rows) == 0 { + return + } + + q := dep.MediaProcessQueue(ctx) + uc := dep.UserClient() + enqueued := 0 + for _, row := range rows { + // The task must carry an owner (DBTask.Owner() is dereferenced when the + // queue persists the task); attribute it to the blob's owner. + owner, err := uc.GetByID(ctx, row.OwnerID) + if err != nil { + l.Error("Failed to load owner %d for media compress row %d: %s", row.OwnerID, row.ID, err) + continue + } + t, err := NewMediaCompressTask(ctx, row.ID, owner) + if err != nil { + l.Error("Failed to create media compress task for row %d: %s", row.ID, err) + continue + } + if err := q.QueueTask(ctx, t); err != nil { + l.Error("Failed to queue media compress task for row %d: %s", row.ID, err) + continue + } + enqueued++ + } + l.Info("Enqueued %d media compress task(s) from cron.", enqueued) + }) +} + +func NewMediaCompressTask(ctx context.Context, rowID int, owner *ent.User) (queue.Task, error) { + state := &MediaCompressTaskState{RowID: rowID} + stateBytes, err := json.Marshal(state) + if err != nil { + return nil, fmt.Errorf("failed to marshal state: %w", err) + } + + return &MediaCompressTask{ + DBTask: &queue.DBTask{ + // DirectOwner must be non-nil: the queue dereferences Owner().ID when + // persisting the task (pkg/queue/task.go). + DirectOwner: owner, + Task: &ent.Task{ + Type: queue.MediaCompressTaskType, + CorrelationID: logging.CorrelationID(ctx), + PrivateState: string(stateBytes), + PublicState: &types.TaskPublicState{}, + }, + }, + }, nil +} + +func NewMediaCompressTaskFromModel(t *ent.Task) queue.Task { + return &MediaCompressTask{ + DBTask: &queue.DBTask{ + Task: t, + }, + } +} + +func (m *MediaCompressTask) Do(ctx context.Context) (task.Status, error) { + dep := dependency.FromContext(ctx) + m.l = dep.Logger() + + state := &MediaCompressTaskState{} + if err := json.Unmarshal([]byte(m.State()), state); err != nil { + return task.StatusError, fmt.Errorf("failed to unmarshal state: %w", err) + } + m.state = state + + mpClient := dep.MediaProcessClient() + row, err := mpClient.GetByID(ctx, state.RowID) + if err != nil { + // Row gone (e.g. cleaned up): nothing to do. + m.l.Warning("Media process task row %d not found, skipping: %s", state.RowID, err) + return task.StatusCompleted, nil + } + + // Idempotency: only act on a pending row. + if row.Status != mediaprocesstask.StatusPending { + return task.StatusCompleted, nil + } + + settings := dep.SettingProvider().MediaProcess(ctx) + if !settings.ImageEnabled { + _, _ = mpClient.SetStatus(ctx, row.ID, &inventory.MediaProcessStatusArgs{Status: mediaprocesstask.StatusSkipped}) + return task.StatusCompleted, nil + } + + // Only the write-back "version" mode is implemented in the MVP; replace/auto + // are follow-ups (see ticket §7.1). Any other value falls back to version. + if _, err := mpClient.SetStatus(ctx, row.ID, &inventory.MediaProcessStatusArgs{ + Status: mediaprocesstask.StatusProcessing, + BumpAttempts: true, + }); err != nil { + return task.StatusError, fmt.Errorf("failed to mark processing: %w", err) + } + + if err := m.compress(ctx, dep, settings, row); err != nil { + // Persist the error; the queue backoff will retry up to MaxRetry, after + // which the row stays "processing" — a follow-up sweep can requeue it. + _, _ = mpClient.SetStatus(ctx, row.ID, &inventory.MediaProcessStatusArgs{ + Status: mediaprocesstask.StatusFailed, + Error: err.Error(), + }) + return task.StatusError, err + } + + return task.StatusCompleted, nil +} + +// compress runs the full pipeline for one row: read → compress → write-back as a +// new version → mark done. Returns nil on success or a documented skip. +func (m *MediaCompressTask) compress(ctx context.Context, dep dependency.Dep, settings *setting.MediaProcessSetting, row *ent.MediaProcessTask) error { + mpClient := dep.MediaProcessClient() + + owner, err := dep.UserClient().GetByID(ctx, row.OwnerID) + if err != nil { + return fmt.Errorf("failed to load owner %d: %w", row.OwnerID, err) + } + + fm := NewFileManager(dep, owner) + defer fm.Recycle() + + es, err := fm.GetEntitySource(ctx, row.EntityID) + if err != nil { + // Blob gone (recycled/deleted): self-heal by skipping. + m.l.Warning("Entity %d unavailable, skipping media compress: %s", row.EntityID, err) + _, _ = mpClient.SetStatus(ctx, row.ID, &inventory.MediaProcessStatusArgs{Status: mediaprocesstask.StatusSkipped, Error: err.Error()}) + return nil + } + defer es.Close() + + originalSize := es.Entity().Size() + if originalSize < settings.MinSize { + _, _ = mpClient.SetStatus(ctx, row.ID, &inventory.MediaProcessStatusArgs{Status: mediaprocesstask.StatusSkipped}) + return nil + } + + // Resolve the logical file for the write-back URI + name/ext. + file, err := fm.TraverseFile(ctx, row.FileID) + if err != nil { + m.l.Warning("File %d unavailable, skipping media compress: %s", row.FileID, err) + _, _ = mpClient.SetStatus(ctx, row.ID, &inventory.MediaProcessStatusArgs{Status: mediaprocesstask.StatusSkipped, Error: err.Error()}) + return nil + } + sourceExt := strings.ToLower(strings.TrimPrefix(filepath.Ext(file.Name()), ".")) + + // Idempotency signature: engine + quality + format + original size. + signature := fmt.Sprintf("%s|q%d|%s|%d", settings.Engine, settings.Quality, settings.Format, originalSize) + if row.Props != nil && row.Props.Signature == signature { + _, _ = mpClient.SetStatus(ctx, row.ID, &inventory.MediaProcessStatusArgs{Status: mediaprocesstask.StatusSkipped}) + return nil + } + + // Materialize a local input path (download if the blob is remote/encrypted). + tempDir := filepath.Join(util.DataPath(dep.SettingProvider().TempPath(ctx)), mediaCompressTempFolder) + if err := util.CreatNestedFolder(tempDir); err != nil { + return fmt.Errorf("failed to create temp folder: %w", err) + } + inputPath, cleanupInput, err := materializeLocalInput(ctx, es, tempDir, sourceExt) + if err != nil { + return fmt.Errorf("failed to materialize input: %w", err) + } + defer cleanupInput() + + // Compress. + outputPath, targetExt, err := compressImage(ctx, settings, dep.SettingProvider(), inputPath, sourceExt, tempDir) + if err != nil { + if err == errUnsupportedFormat { + m.l.Info("Unsupported image format %q for row %d, skipping.", sourceExt, row.ID) + _, _ = mpClient.SetStatus(ctx, row.ID, &inventory.MediaProcessStatusArgs{Status: mediaprocesstask.StatusSkipped}) + return nil + } + return err + } + defer os.Remove(outputPath) + + outInfo, err := os.Stat(outputPath) + if err != nil { + return fmt.Errorf("failed to stat compressed output: %w", err) + } + resultSize := outInfo.Size() + + // No gain (or larger): keep the original, mark done with the signature so it + // is not retried with the same parameters. + if resultSize == 0 || resultSize >= originalSize { + m.l.Info("Compression yielded no gain for row %d (%d -> %d), keeping original.", row.ID, originalSize, resultSize) + _, _ = mpClient.SetStatus(ctx, row.ID, &inventory.MediaProcessStatusArgs{ + Status: mediaprocesstask.StatusDone, + ResultSize: originalSize, + Props: &types.MediaProcessTaskProps{ + Engine: settings.Engine, Quality: settings.Quality, Format: settings.Format, + OriginalSize: originalSize, Signature: signature, + }, + }) + return nil + } + + // Write-back as a new version via manager.Update. This reuses the whole upload + // path (any driver, incl. remote) and applies the quota StorageDiff + // automatically. The context guard prevents CompleteUpload from re-enqueuing. + outFile, err := os.Open(outputPath) + if err != nil { + return fmt.Errorf("failed to open compressed output: %w", err) + } + defer outFile.Close() + + req := &fs.UploadRequest{ + Props: &fs.UploadProps{ + Uri: file.Uri(false), + Size: resultSize, + }, + File: outFile, + Seeker: outFile, + Mode: fs.ModeOverwrite, + } + + writeCtx := withSkipMediaProcessEnqueue(dbfs.WithBypassOwnerCheck(ctx)) + if _, err := fm.Update(writeCtx, req, fs.WithEntityType(types.EntityTypeVersion)); err != nil { + return fmt.Errorf("failed to write back compressed version: %w", err) + } + + _, err = mpClient.SetStatus(ctx, row.ID, &inventory.MediaProcessStatusArgs{ + Status: mediaprocesstask.StatusDone, + ResultSize: resultSize, + Props: &types.MediaProcessTaskProps{ + Engine: settings.Engine, Quality: settings.Quality, Format: settings.Format, + OriginalSize: originalSize, Signature: signature, + }, + }) + if err != nil { + return fmt.Errorf("failed to mark done: %w", err) + } + + m.l.Info("Compressed row %d: %s %d -> %d bytes (target .%s).", row.ID, sourceExt, originalSize, resultSize, targetExt) + return nil +} + +// materializeLocalInput returns a local filesystem path for the entity bytes. If +// the source is a local, unencrypted blob it uses its path directly (no cleanup); +// otherwise it streams the source into a temp file (cleaned up by the returned fn). +func materializeLocalInput(ctx context.Context, es entitySourceReader, tempDir, ext string) (string, func(), error) { + if es.IsLocal() && !es.Entity().Encrypted() { + return es.LocalPath(ctx), func() {}, nil + } + + name := fmt.Sprintf("in_%s.%s", uuid.Must(uuid.NewV4()).String(), ext) + tempInput := filepath.Join(tempDir, name) + f, err := util.CreatNestedFile(tempInput) + if err != nil { + return "", func() {}, fmt.Errorf("failed to create temp input: %w", err) + } + if _, err := io.Copy(f, es); err != nil { + f.Close() + os.Remove(tempInput) + return "", func() {}, fmt.Errorf("failed to download entity: %w", err) + } + f.Close() + + return tempInput, func() { os.Remove(tempInput) }, nil +} + +var errUnsupportedFormat = fmt.Errorf("unsupported image format") + +// compressImage runs the configured engine on a local input file and returns the +// compressed output path + its extension. Engine default is vips (better for +// stills); ffmpeg is the alternative. +func compressImage(ctx context.Context, mp *setting.MediaProcessSetting, settings setting.Provider, inputPath, sourceExt, tempDir string) (string, string, error) { + targetExt := normalizeFormat(mp.Format, sourceExt) + if targetExt == "" { + return "", "", errUnsupportedFormat + } + + outputPath := filepath.Join(tempDir, fmt.Sprintf("out_%s.%s", uuid.Must(uuid.NewV4()).String(), targetExt)) + + var ( + bin string + args []string + ) + switch strings.ToLower(mp.Engine) { + case "ffmpeg": + bin = settings.FFMpegPath(ctx) + a, err := ffmpegCompressArgs(inputPath, outputPath, targetExt, mp.Quality) + if err != nil { + return "", "", err + } + args = a + default: // vips + bin = settings.VipsPath(ctx) + args = []string{"copy", inputPath, vipsOutputSpec(outputPath, targetExt, mp.Quality)} + } + + if extra := strings.TrimSpace(mp.ExtraArgs); extra != "" { + args = append(args, strings.Fields(extra)...) + } + + cmd := exec.CommandContext(ctx, bin, args...) + var stdErr bytes.Buffer + cmd.Stderr = &stdErr + if err := cmd.Run(); err != nil { + os.Remove(outputPath) + return "", "", fmt.Errorf("failed to invoke %s: %w, output: %s", bin, err, stdErr.String()) + } + + return outputPath, targetExt, nil +} + +// normalizeFormat resolves the target extension from the format setting. "keep" +// preserves the source extension (only for compressible raster types). An empty +// return means the source is not compressible with this configuration. +func normalizeFormat(format, sourceExt string) string { + f := strings.ToLower(strings.TrimSpace(format)) + if f == "" || f == "keep" { + f = sourceExt + } + switch f { + case "jpg", "jpeg": + return "jpg" + case "webp": + return "webp" + case "png": + return "png" + default: + return "" + } +} + +// vipsOutputSpec builds the vips output filename with save options that trigger +// re-encoding at the requested quality. +func vipsOutputSpec(outputPath, targetExt string, quality int) string { + switch targetExt { + case "jpg", "webp": + return fmt.Sprintf("%s[Q=%d]", outputPath, quality) + case "png": + return fmt.Sprintf("%s[compression=9]", outputPath) + default: + return outputPath + } +} + +// ffmpegCompressArgs maps the quality (1..100, higher = better) onto ffmpeg's +// per-codec quality flag. +func ffmpegCompressArgs(inputPath, outputPath, targetExt string, quality int) ([]string, error) { + base := []string{"-y", "-i", inputPath} + switch targetExt { + case "jpg": + // mjpeg qscale: 2 (best) .. 31 (worst). + q := 31 - int(float64(quality)/100.0*29.0) + if q < 2 { + q = 2 + } + if q > 31 { + q = 31 + } + return append(base, "-q:v", strconv.Itoa(q), outputPath), nil + case "webp": + return append(base, "-quality", strconv.Itoa(quality), outputPath), nil + case "png": + return append(base, "-compression_level", "100", outputPath), nil + default: + return nil, errUnsupportedFormat + } +} + +// entitySourceReader is the subset of entitysource.EntitySource the compression +// pipeline consumes (kept local to avoid widening the import surface). +type entitySourceReader interface { + io.Reader + IsLocal() bool + LocalPath(ctx context.Context) string + Entity() fs.Entity +} + +// enqueueMediaProcessIfEligible registers the just-uploaded primary entity as a +// pending image-compression row, when the global switch + the owner's opt-in + +// mime/size gates all pass (APP-101). Called from CompleteUpload on the master. +// It is a no-op on the compression write-back path (context guard) so it never +// loops on its own output. +func (m *manager) enqueueMediaProcessIfEligible(ctx context.Context, session *fs.UploadSession, file fs.File) { + if m.stateless || file == nil || m.user == nil || m.user.Settings == nil { + return + } + if shouldSkipMediaProcessEnqueue(ctx) { + return + } + + mp := m.settings.MediaProcess(ctx) + if !mp.ImageEnabled || !m.user.Settings.AutoCompressImages { + return + } + + mimeType := "" + if session != nil && session.Props != nil { + mimeType = session.Props.MimeType + } + if mimeType == "" { + mimeType = m.dep.MimeDetector(ctx).TypeByName(file.Name()) + } + if !strings.HasPrefix(strings.ToLower(mimeType), "image/") { + return + } + + entity := file.PrimaryEntity() + if entity == nil || entity.Size() < mp.MinSize { + return + } + + mpClient := m.dep.MediaProcessClient() + if active, err := mpClient.HasActive(ctx, entity.ID()); err != nil { + m.l.Warning("media process: active-row check failed for entity %d: %s", entity.ID(), err) + return + } else if active { + return + } + + if _, err := mpClient.Enqueue(ctx, &inventory.MediaProcessEnqueueArgs{ + EntityID: entity.ID(), + FileID: file.ID(), + OwnerID: m.user.ID, + MediaType: mediaprocesstask.MediaTypeImage, + }); err != nil { + m.l.Warning("media process: failed to enqueue pending row for entity %d: %s", entity.ID(), err) + } +} diff --git a/pkg/filemanager/manager/upload.go b/pkg/filemanager/manager/upload.go index a4792676..47f4ec0c 100644 --- a/pkg/filemanager/manager/upload.go +++ b/pkg/filemanager/manager/upload.go @@ -318,6 +318,8 @@ func (m *manager) CompleteUpload(ctx context.Context, session *fs.UploadSession) } m.onNewEntityUploaded(ctx, session, d, ownerId) + // APP-101: register the new image for deferred compression when eligible. + m.enqueueMediaProcessIfEligible(ctx, session, file) // Remove upload session _ = m.kv.Delete(UploadSessionCachePrefix, session.Props.UploadSessionID) return file, nil diff --git a/pkg/queue/task.go b/pkg/queue/task.go index 0a2d9fc9..db38536c 100644 --- a/pkg/queue/task.go +++ b/pkg/queue/task.go @@ -104,6 +104,7 @@ const ( RelocateTaskType = "relocate" RemoteDownloadTaskType = "remote_download" ImportTaskType = "import" + MediaCompressTaskType = "media_compress" FullTextIndexTaskType = "full_text_index" FullTextCopyTaskType = "full_text_copy" diff --git a/pkg/setting/provider.go b/pkg/setting/provider.go index e9816c45..46121f08 100644 --- a/pkg/setting/provider.go +++ b/pkg/setting/provider.go @@ -156,6 +156,8 @@ type ( MusicCoverThumbExts(ctx context.Context) []string // Cron returns the crontab settings. Cron(ctx context.Context, t CronType) string + // MediaProcess returns the media post-processing (image compression) settings. + MediaProcess(ctx context.Context) *MediaProcessSetting // Theme returns the theme settings. Theme(ctx context.Context) *Theme // Logo returns the logo settings. @@ -439,6 +441,24 @@ func (s *settingProvider) Cron(ctx context.Context, t CronType) string { return s.getString(ctx, "cron_"+string(t), "@hourly") } +func (s *settingProvider) MediaProcess(ctx context.Context) *MediaProcessSetting { + workerNum := s.getInt(ctx, "media_compress_worker_num", 1) + if workerNum <= 0 { + workerNum = 1 + } + return &MediaProcessSetting{ + ImageEnabled: s.getBoolean(ctx, "media_compress_image_enabled", false), + Engine: s.getString(ctx, "media_compress_engine", "vips"), + WorkerNum: workerNum, + BatchSize: s.getInt(ctx, "media_compress_batch_size", 50), + Quality: s.getInt(ctx, "media_compress_image_quality", 80), + Format: s.getString(ctx, "media_compress_image_format", "keep"), + ExtraArgs: s.getString(ctx, "media_compress_image_args", ""), + ResultMode: s.getString(ctx, "media_compress_result_mode", "version"), + MinSize: s.getInt64(ctx, "media_compress_min_size", 204800), + } +} + func (s *settingProvider) BuiltinThumbGeneratorEnabled(ctx context.Context) bool { return s.getBoolean(ctx, "thumb_builtin_enabled", true) } diff --git a/pkg/setting/types.go b/pkg/setting/types.go index 7c9b975e..cdc290ac 100644 --- a/pkg/setting/types.go +++ b/pkg/setting/types.go @@ -89,6 +89,20 @@ type ( MaxRetry int RetryDelay time.Duration } + + // MediaProcessSetting carries the media post-processing (image compression) + // parameters (APP-101), all editable from the admin panel. + MediaProcessSetting struct { + ImageEnabled bool // master switch for image compression + Engine string // "vips" | "ffmpeg" + WorkerNum int // compression concurrency (dedicated key; default 1) + BatchSize int // max rows the cron enqueues per run + Quality int // 1..100 + Format string // "keep" | "webp" | "jpeg" | "png" + ExtraArgs string // extra engine flags + ResultMode string // "version" | "replace" | "auto" + MinSize int64 // skip blobs smaller than this (bytes) + } ) type ThumbEncode struct { @@ -103,6 +117,7 @@ var ( QueueTypeEntityRecycle = QueueType("recycle") QueueTypeSlave = QueueType("slave") QueueTypeRemoteDownload = QueueType("remote_download") + QueueTypeMediaProcess = QueueType("media_process") ) type CronType string @@ -111,6 +126,7 @@ var ( CronTypeEntityCollect = CronType("entity_collect") CronTypeTrashBinCollect = CronType("trash_bin_collect") CronTypeOauthCredRefresh = CronType("oauth_cred_refresh") + CronTypeMediaProcess = CronType("media_process") ) type Theme struct { diff --git a/service/admin/site.go b/service/admin/site.go index 20498fa1..7dedfc72 100644 --- a/service/admin/site.go +++ b/service/admin/site.go @@ -262,6 +262,12 @@ var ( "queue_remote_download_backoff_max_duration": remoteDownloadQueuePostProcessor, "queue_remote_download_max_retry": remoteDownloadQueuePostProcessor, "queue_remote_download_retry_delay": remoteDownloadQueuePostProcessor, + "media_compress_worker_num": mediaProcessQueuePostProcessor, + "queue_media_process_max_execution": mediaProcessQueuePostProcessor, + "queue_media_process_backoff_factor": mediaProcessQueuePostProcessor, + "queue_media_process_backoff_max_duration": mediaProcessQueuePostProcessor, + "queue_media_process_max_retry": mediaProcessQueuePostProcessor, + "queue_media_process_retry_delay": mediaProcessQueuePostProcessor, "secret_key": secretKeyPostProcessor, "fts_meilisearch_embed_config": meilisearchPostProcessor, "fts_meilisearch_endpoint": meilisearchPostProcessor, @@ -413,6 +419,12 @@ func thumbQueuePostProcessor(ctx context.Context, settings map[string]string) er return nil } +func mediaProcessQueuePostProcessor(ctx context.Context, settings map[string]string) error { + dep := dependency.FromContext(ctx) + dep.MediaProcessQueue(context.WithValue(ctx, dependency.ReloadCtx{}, true)).Start() + return nil +} + func secretKeyPostProcessor(ctx context.Context, settings map[string]string) error { dep := dependency.FromContext(ctx) dep.KV().Delete(manager.EntityUrlCacheKeyPrefix) diff --git a/service/admin/task.go b/service/admin/task.go index c6811bcb..c77cf50c 100644 --- a/service/admin/task.go +++ b/service/admin/task.go @@ -27,6 +27,7 @@ func GetQueueMetrics(c *gin.Context) ([]QueueMetric, error) { ioIntense := dep.IoIntenseQueue(c) remoteDownload := dep.RemoteDownloadQueue(c) thumb := dep.ThumbQueue(c) + mediaProcess := dep.MediaProcessQueue(c) res = append(res, QueueMetric{ Name: setting.QueueTypeMediaMeta, @@ -68,6 +69,14 @@ func GetQueueMetrics(c *gin.Context) ([]QueueMetric, error) { SubmittedTasks: thumb.SubmittedTasks(), SuspendingTasks: thumb.SuspendingTasks(), }) + res = append(res, QueueMetric{ + Name: setting.QueueTypeMediaProcess, + BusyWorkers: mediaProcess.BusyWorkers(), + SuccessTasks: mediaProcess.SuccessTasks(), + FailureTasks: mediaProcess.FailureTasks(), + SubmittedTasks: mediaProcess.SubmittedTasks(), + SuspendingTasks: mediaProcess.SuspendingTasks(), + }) return res, nil } diff --git a/service/user/response.go b/service/user/response.go index ac063a0d..7c61a9f0 100644 --- a/service/user/response.go +++ b/service/user/response.go @@ -32,6 +32,7 @@ type UserSettings struct { Passkeys []Passkey `json:"passkeys,omitempty"` DisableViewSync bool `json:"disable_view_sync"` ShareLinksInProfile string `json:"share_links_in_profile"` + AutoCompressImages bool `json:"auto_compress_images"` OAuthGrants []OauthGrant `json:"oauth_grants,omitempty"` } @@ -47,6 +48,7 @@ func BuildUserSettings(u *ent.User, passkeys []*ent.Passkey, parser *uaparser.Pa }), DisableViewSync: u.Settings.DisableViewSync, ShareLinksInProfile: string(u.Settings.ShareLinksInProfile), + AutoCompressImages: u.Settings.AutoCompressImages, OAuthGrants: lo.Map(grants, func(item *ent.OAuthGrant, index int) OauthGrant { return BuildOauthGrant(item) }), diff --git a/service/user/setting.go b/service/user/setting.go index 58d821c9..d3e41334 100644 --- a/service/user/setting.go +++ b/service/user/setting.go @@ -230,6 +230,7 @@ type ( TwoFACode *string `json:"two_fa_code" binding:"omitempty"` DisableViewSync *bool `json:"disable_view_sync" binding:"omitempty"` ShareLinksInProfile *string `json:"share_links_in_profile" binding:"omitempty"` + AutoCompressImages *bool `json:"auto_compress_images" binding:"omitempty"` } PatchUserSettingParamsCtx struct{} ) @@ -276,6 +277,11 @@ func (s *PatchUserSetting) Patch(c *gin.Context) error { saveSetting = true } + if s.AutoCompressImages != nil { + u.Settings.AutoCompressImages = *s.AutoCompressImages + saveSetting = true + } + if s.ShareLinksInProfile != nil { u.Settings.ShareLinksInProfile = types.ShareLinksInProfileLevel(*s.ShareLinksInProfile) saveSetting = true