diff --git a/db/notification.go b/db/notification.go new file mode 100644 index 0000000..7bf8f62 --- /dev/null +++ b/db/notification.go @@ -0,0 +1,95 @@ +package db + +import ( + "context" + "encoding/json" + "polaris/ent" + "polaris/ent/notificationclient" + "polaris/pkg/notifier" + "strings" + + "github.com/pkg/errors" +) + +func (c *Client) GetAllNotificationClients2() ([]*ent.NotificationClient, error) { + return c.ent.NotificationClient.Query().All(context.TODO()) +} + +func (c *Client) GetAllNotificationClients() ([]*NotificationClient, error) { + all, err := c.ent.NotificationClient.Query().All(context.TODO()) + if err != nil { + return nil, errors.Wrap(err, "query db") + } + var all1 []*NotificationClient + for _, item := range all { + cl, err := toNotificationClient(item) + if err != nil { + return nil, errors.Wrap(err, "convert") + } + all1 = append(all1, cl) + } + return all1, nil +} + +func (c *Client) AddNotificationClient(name, service string, setting string, enabled bool) error { + // data, err := json.Marshal(setting) + // if err != nil { + // return errors.Wrap(err, "json") + // } + service = strings.ToLower(service) + count, err := c.ent.NotificationClient.Query().Where(notificationclient.Name(name)).Count(context.Background()) + if err == nil && count > 0 { + //update exist one + return c.ent.NotificationClient.Update().Where(notificationclient.Name(name)).SetService(service). + SetSettings(setting).SetEnabled(enabled).Exec(context.Background()) + } + + return c.ent.NotificationClient.Create().SetName(name).SetService(service). + SetSettings(setting).SetEnabled(enabled).Exec(context.Background()) +} + +func (c *Client) DeleteNotificationClient(id int) error { + _, err := c.ent.NotificationClient.Delete().Where(notificationclient.ID(id)).Exec(context.Background()) + return err +} + +func (c *Client) GetNotificationClient(id int) (*NotificationClient, error) { + noti, err := c.ent.NotificationClient.Query().Where(notificationclient.ID(id)).First(context.Background()) + if err != nil { + return nil, errors.Wrap(err, "query") + } + + return toNotificationClient(noti) +} + +func toNotificationClient(cl *ent.NotificationClient) (*NotificationClient, error) { + var settings interface{} + switch cl.Service { + case "pushover": + settings = notifier.PushoverConfig{} + case "dingtalk": + settings = notifier.DingTalkConfig{} + case "telegram": + settings = notifier.TelegramConfig{} + } + err := json.Unmarshal([]byte(cl.Settings), &settings) + if err != nil { + return nil, errors.Wrap(err, "json") + } + return &NotificationClient{ + ID: cl.ID, + Name: cl.Name, + Service: cl.Service, + Enabled: cl.Enabled, + Settings: settings, + }, nil + +} + +type NotificationClient struct { + ID int `json:"id"` + Name string `json:"name"` + Service string `json:"service"` + Enabled bool `json:"enabled"` + Settings interface{} `json:"settings"` +} diff --git a/ent/client.go b/ent/client.go index a81ed9d..2134b0a 100644 --- a/ent/client.go +++ b/ent/client.go @@ -16,6 +16,7 @@ import ( "polaris/ent/history" "polaris/ent/indexers" "polaris/ent/media" + "polaris/ent/notificationclient" "polaris/ent/settings" "polaris/ent/storage" @@ -40,6 +41,8 @@ type Client struct { Indexers *IndexersClient // Media is the client for interacting with the Media builders. Media *MediaClient + // NotificationClient is the client for interacting with the NotificationClient builders. + NotificationClient *NotificationClientClient // Settings is the client for interacting with the Settings builders. Settings *SettingsClient // Storage is the client for interacting with the Storage builders. @@ -60,6 +63,7 @@ func (c *Client) init() { c.History = NewHistoryClient(c.config) c.Indexers = NewIndexersClient(c.config) c.Media = NewMediaClient(c.config) + c.NotificationClient = NewNotificationClientClient(c.config) c.Settings = NewSettingsClient(c.config) c.Storage = NewStorageClient(c.config) } @@ -152,15 +156,16 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { cfg := c.config cfg.driver = tx return &Tx{ - ctx: ctx, - config: cfg, - DownloadClients: NewDownloadClientsClient(cfg), - Episode: NewEpisodeClient(cfg), - History: NewHistoryClient(cfg), - Indexers: NewIndexersClient(cfg), - Media: NewMediaClient(cfg), - Settings: NewSettingsClient(cfg), - Storage: NewStorageClient(cfg), + ctx: ctx, + config: cfg, + DownloadClients: NewDownloadClientsClient(cfg), + Episode: NewEpisodeClient(cfg), + History: NewHistoryClient(cfg), + Indexers: NewIndexersClient(cfg), + Media: NewMediaClient(cfg), + NotificationClient: NewNotificationClientClient(cfg), + Settings: NewSettingsClient(cfg), + Storage: NewStorageClient(cfg), }, nil } @@ -178,15 +183,16 @@ 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, - DownloadClients: NewDownloadClientsClient(cfg), - Episode: NewEpisodeClient(cfg), - History: NewHistoryClient(cfg), - Indexers: NewIndexersClient(cfg), - Media: NewMediaClient(cfg), - Settings: NewSettingsClient(cfg), - Storage: NewStorageClient(cfg), + ctx: ctx, + config: cfg, + DownloadClients: NewDownloadClientsClient(cfg), + Episode: NewEpisodeClient(cfg), + History: NewHistoryClient(cfg), + Indexers: NewIndexersClient(cfg), + Media: NewMediaClient(cfg), + NotificationClient: NewNotificationClientClient(cfg), + Settings: NewSettingsClient(cfg), + Storage: NewStorageClient(cfg), }, nil } @@ -216,8 +222,8 @@ 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.DownloadClients, c.Episode, c.History, c.Indexers, c.Media, c.Settings, - c.Storage, + c.DownloadClients, c.Episode, c.History, c.Indexers, c.Media, + c.NotificationClient, c.Settings, c.Storage, } { n.Use(hooks...) } @@ -227,8 +233,8 @@ 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.DownloadClients, c.Episode, c.History, c.Indexers, c.Media, c.Settings, - c.Storage, + c.DownloadClients, c.Episode, c.History, c.Indexers, c.Media, + c.NotificationClient, c.Settings, c.Storage, } { n.Intercept(interceptors...) } @@ -247,6 +253,8 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { return c.Indexers.mutate(ctx, m) case *MediaMutation: return c.Media.mutate(ctx, m) + case *NotificationClientMutation: + return c.NotificationClient.mutate(ctx, m) case *SettingsMutation: return c.Settings.mutate(ctx, m) case *StorageMutation: @@ -953,6 +961,139 @@ func (c *MediaClient) mutate(ctx context.Context, m *MediaMutation) (Value, erro } } +// NotificationClientClient is a client for the NotificationClient schema. +type NotificationClientClient struct { + config +} + +// NewNotificationClientClient returns a client for the NotificationClient from the given config. +func NewNotificationClientClient(c config) *NotificationClientClient { + return &NotificationClientClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `notificationclient.Hooks(f(g(h())))`. +func (c *NotificationClientClient) Use(hooks ...Hook) { + c.hooks.NotificationClient = append(c.hooks.NotificationClient, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `notificationclient.Intercept(f(g(h())))`. +func (c *NotificationClientClient) Intercept(interceptors ...Interceptor) { + c.inters.NotificationClient = append(c.inters.NotificationClient, interceptors...) +} + +// Create returns a builder for creating a NotificationClient entity. +func (c *NotificationClientClient) Create() *NotificationClientCreate { + mutation := newNotificationClientMutation(c.config, OpCreate) + return &NotificationClientCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of NotificationClient entities. +func (c *NotificationClientClient) CreateBulk(builders ...*NotificationClientCreate) *NotificationClientCreateBulk { + return &NotificationClientCreateBulk{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 *NotificationClientClient) MapCreateBulk(slice any, setFunc func(*NotificationClientCreate, int)) *NotificationClientCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &NotificationClientCreateBulk{err: fmt.Errorf("calling to NotificationClientClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*NotificationClientCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &NotificationClientCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for NotificationClient. +func (c *NotificationClientClient) Update() *NotificationClientUpdate { + mutation := newNotificationClientMutation(c.config, OpUpdate) + return &NotificationClientUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *NotificationClientClient) UpdateOne(nc *NotificationClient) *NotificationClientUpdateOne { + mutation := newNotificationClientMutation(c.config, OpUpdateOne, withNotificationClient(nc)) + return &NotificationClientUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *NotificationClientClient) UpdateOneID(id int) *NotificationClientUpdateOne { + mutation := newNotificationClientMutation(c.config, OpUpdateOne, withNotificationClientID(id)) + return &NotificationClientUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for NotificationClient. +func (c *NotificationClientClient) Delete() *NotificationClientDelete { + mutation := newNotificationClientMutation(c.config, OpDelete) + return &NotificationClientDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *NotificationClientClient) DeleteOne(nc *NotificationClient) *NotificationClientDeleteOne { + return c.DeleteOneID(nc.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *NotificationClientClient) DeleteOneID(id int) *NotificationClientDeleteOne { + builder := c.Delete().Where(notificationclient.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &NotificationClientDeleteOne{builder} +} + +// Query returns a query builder for NotificationClient. +func (c *NotificationClientClient) Query() *NotificationClientQuery { + return &NotificationClientQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeNotificationClient}, + inters: c.Interceptors(), + } +} + +// Get returns a NotificationClient entity by its id. +func (c *NotificationClientClient) Get(ctx context.Context, id int) (*NotificationClient, error) { + return c.Query().Where(notificationclient.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *NotificationClientClient) GetX(ctx context.Context, id int) *NotificationClient { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// Hooks returns the client hooks. +func (c *NotificationClientClient) Hooks() []Hook { + return c.hooks.NotificationClient +} + +// Interceptors returns the client interceptors. +func (c *NotificationClientClient) Interceptors() []Interceptor { + return c.inters.NotificationClient +} + +func (c *NotificationClientClient) mutate(ctx context.Context, m *NotificationClientMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&NotificationClientCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&NotificationClientUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&NotificationClientUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&NotificationClientDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown NotificationClient mutation op: %q", m.Op()) + } +} + // SettingsClient is a client for the Settings schema. type SettingsClient struct { config @@ -1222,10 +1363,11 @@ func (c *StorageClient) mutate(ctx context.Context, m *StorageMutation) (Value, // hooks and interceptors per client, for fast access. type ( hooks struct { - DownloadClients, Episode, History, Indexers, Media, Settings, Storage []ent.Hook + DownloadClients, Episode, History, Indexers, Media, NotificationClient, + Settings, Storage []ent.Hook } inters struct { - DownloadClients, Episode, History, Indexers, Media, Settings, - Storage []ent.Interceptor + DownloadClients, Episode, History, Indexers, Media, NotificationClient, + Settings, Storage []ent.Interceptor } ) diff --git a/ent/ent.go b/ent/ent.go index 26b05ea..a3fa936 100644 --- a/ent/ent.go +++ b/ent/ent.go @@ -11,6 +11,7 @@ import ( "polaris/ent/history" "polaris/ent/indexers" "polaris/ent/media" + "polaris/ent/notificationclient" "polaris/ent/settings" "polaris/ent/storage" "reflect" @@ -79,13 +80,14 @@ var ( func checkColumn(table, column string) error { initCheck.Do(func() { columnCheck = sql.NewColumnCheck(map[string]func(string) bool{ - downloadclients.Table: downloadclients.ValidColumn, - episode.Table: episode.ValidColumn, - history.Table: history.ValidColumn, - indexers.Table: indexers.ValidColumn, - media.Table: media.ValidColumn, - settings.Table: settings.ValidColumn, - storage.Table: storage.ValidColumn, + downloadclients.Table: downloadclients.ValidColumn, + episode.Table: episode.ValidColumn, + history.Table: history.ValidColumn, + indexers.Table: indexers.ValidColumn, + media.Table: media.ValidColumn, + notificationclient.Table: notificationclient.ValidColumn, + settings.Table: settings.ValidColumn, + storage.Table: storage.ValidColumn, }) }) return columnCheck(table, column) diff --git a/ent/hook/hook.go b/ent/hook/hook.go index 8b5ad13..40f95df 100644 --- a/ent/hook/hook.go +++ b/ent/hook/hook.go @@ -68,6 +68,18 @@ func (f MediaFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.MediaMutation", m) } +// The NotificationClientFunc type is an adapter to allow the use of ordinary +// function as NotificationClient mutator. +type NotificationClientFunc func(context.Context, *ent.NotificationClientMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f NotificationClientFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.NotificationClientMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.NotificationClientMutation", m) +} + // The SettingsFunc type is an adapter to allow the use of ordinary // function as Settings mutator. type SettingsFunc func(context.Context, *ent.SettingsMutation) (ent.Value, error) diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index 622b3a7..32bc204 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -110,6 +110,20 @@ var ( Columns: MediaColumns, PrimaryKey: []*schema.Column{MediaColumns[0]}, } + // NotificationClientsColumns holds the columns for the "notification_clients" table. + NotificationClientsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "name", Type: field.TypeString}, + {Name: "service", Type: field.TypeString}, + {Name: "settings", Type: field.TypeString}, + {Name: "enabled", Type: field.TypeBool, Default: true}, + } + // NotificationClientsTable holds the schema information for the "notification_clients" table. + NotificationClientsTable = &schema.Table{ + Name: "notification_clients", + Columns: NotificationClientsColumns, + PrimaryKey: []*schema.Column{NotificationClientsColumns[0]}, + } // SettingsColumns holds the columns for the "settings" table. SettingsColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, @@ -144,6 +158,7 @@ var ( HistoriesTable, IndexersTable, MediaTable, + NotificationClientsTable, SettingsTable, StoragesTable, } diff --git a/ent/mutation.go b/ent/mutation.go index 70c7437..1c11422 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -11,6 +11,7 @@ import ( "polaris/ent/history" "polaris/ent/indexers" "polaris/ent/media" + "polaris/ent/notificationclient" "polaris/ent/predicate" "polaris/ent/settings" "polaris/ent/storage" @@ -30,13 +31,14 @@ const ( OpUpdateOne = ent.OpUpdateOne // Node types. - TypeDownloadClients = "DownloadClients" - TypeEpisode = "Episode" - TypeHistory = "History" - TypeIndexers = "Indexers" - TypeMedia = "Media" - TypeSettings = "Settings" - TypeStorage = "Storage" + TypeDownloadClients = "DownloadClients" + TypeEpisode = "Episode" + TypeHistory = "History" + TypeIndexers = "Indexers" + TypeMedia = "Media" + TypeNotificationClient = "NotificationClient" + TypeSettings = "Settings" + TypeStorage = "Storage" ) // DownloadClientsMutation represents an operation that mutates the DownloadClients nodes in the graph. @@ -4342,6 +4344,494 @@ func (m *MediaMutation) ResetEdge(name string) error { return fmt.Errorf("unknown Media edge %s", name) } +// NotificationClientMutation represents an operation that mutates the NotificationClient nodes in the graph. +type NotificationClientMutation struct { + config + op Op + typ string + id *int + name *string + service *string + settings *string + enabled *bool + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*NotificationClient, error) + predicates []predicate.NotificationClient +} + +var _ ent.Mutation = (*NotificationClientMutation)(nil) + +// notificationclientOption allows management of the mutation configuration using functional options. +type notificationclientOption func(*NotificationClientMutation) + +// newNotificationClientMutation creates new mutation for the NotificationClient entity. +func newNotificationClientMutation(c config, op Op, opts ...notificationclientOption) *NotificationClientMutation { + m := &NotificationClientMutation{ + config: c, + op: op, + typ: TypeNotificationClient, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withNotificationClientID sets the ID field of the mutation. +func withNotificationClientID(id int) notificationclientOption { + return func(m *NotificationClientMutation) { + var ( + err error + once sync.Once + value *NotificationClient + ) + m.oldValue = func(ctx context.Context) (*NotificationClient, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().NotificationClient.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withNotificationClient sets the old NotificationClient of the mutation. +func withNotificationClient(node *NotificationClient) notificationclientOption { + return func(m *NotificationClientMutation) { + m.oldValue = func(context.Context) (*NotificationClient, 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 NotificationClientMutation) 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 NotificationClientMutation) 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 *NotificationClientMutation) 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 *NotificationClientMutation) 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().NotificationClient.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetName sets the "name" field. +func (m *NotificationClientMutation) SetName(s string) { + m.name = &s +} + +// Name returns the value of the "name" field in the mutation. +func (m *NotificationClientMutation) Name() (r string, exists bool) { + v := m.name + if v == nil { + return + } + return *v, true +} + +// OldName returns the old "name" field's value of the NotificationClient entity. +// If the NotificationClient 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 *NotificationClientMutation) OldName(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldName is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldName requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldName: %w", err) + } + return oldValue.Name, nil +} + +// ResetName resets all changes to the "name" field. +func (m *NotificationClientMutation) ResetName() { + m.name = nil +} + +// SetService sets the "service" field. +func (m *NotificationClientMutation) SetService(s string) { + m.service = &s +} + +// Service returns the value of the "service" field in the mutation. +func (m *NotificationClientMutation) Service() (r string, exists bool) { + v := m.service + if v == nil { + return + } + return *v, true +} + +// OldService returns the old "service" field's value of the NotificationClient entity. +// If the NotificationClient 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 *NotificationClientMutation) OldService(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldService is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldService requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldService: %w", err) + } + return oldValue.Service, nil +} + +// ResetService resets all changes to the "service" field. +func (m *NotificationClientMutation) ResetService() { + m.service = nil +} + +// SetSettings sets the "settings" field. +func (m *NotificationClientMutation) SetSettings(s string) { + m.settings = &s +} + +// Settings returns the value of the "settings" field in the mutation. +func (m *NotificationClientMutation) Settings() (r string, exists bool) { + v := m.settings + if v == nil { + return + } + return *v, true +} + +// OldSettings returns the old "settings" field's value of the NotificationClient entity. +// If the NotificationClient 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 *NotificationClientMutation) OldSettings(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldSettings is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldSettings requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldSettings: %w", err) + } + return oldValue.Settings, nil +} + +// ResetSettings resets all changes to the "settings" field. +func (m *NotificationClientMutation) ResetSettings() { + m.settings = nil +} + +// SetEnabled sets the "enabled" field. +func (m *NotificationClientMutation) SetEnabled(b bool) { + m.enabled = &b +} + +// Enabled returns the value of the "enabled" field in the mutation. +func (m *NotificationClientMutation) Enabled() (r bool, exists bool) { + v := m.enabled + if v == nil { + return + } + return *v, true +} + +// OldEnabled returns the old "enabled" field's value of the NotificationClient entity. +// If the NotificationClient 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 *NotificationClientMutation) OldEnabled(ctx context.Context) (v bool, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldEnabled is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldEnabled requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldEnabled: %w", err) + } + return oldValue.Enabled, nil +} + +// ResetEnabled resets all changes to the "enabled" field. +func (m *NotificationClientMutation) ResetEnabled() { + m.enabled = nil +} + +// Where appends a list predicates to the NotificationClientMutation builder. +func (m *NotificationClientMutation) Where(ps ...predicate.NotificationClient) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the NotificationClientMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *NotificationClientMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.NotificationClient, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *NotificationClientMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *NotificationClientMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (NotificationClient). +func (m *NotificationClientMutation) 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 *NotificationClientMutation) Fields() []string { + fields := make([]string, 0, 4) + if m.name != nil { + fields = append(fields, notificationclient.FieldName) + } + if m.service != nil { + fields = append(fields, notificationclient.FieldService) + } + if m.settings != nil { + fields = append(fields, notificationclient.FieldSettings) + } + if m.enabled != nil { + fields = append(fields, notificationclient.FieldEnabled) + } + 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 *NotificationClientMutation) Field(name string) (ent.Value, bool) { + switch name { + case notificationclient.FieldName: + return m.Name() + case notificationclient.FieldService: + return m.Service() + case notificationclient.FieldSettings: + return m.Settings() + case notificationclient.FieldEnabled: + return m.Enabled() + } + 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 *NotificationClientMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case notificationclient.FieldName: + return m.OldName(ctx) + case notificationclient.FieldService: + return m.OldService(ctx) + case notificationclient.FieldSettings: + return m.OldSettings(ctx) + case notificationclient.FieldEnabled: + return m.OldEnabled(ctx) + } + return nil, fmt.Errorf("unknown NotificationClient 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 *NotificationClientMutation) SetField(name string, value ent.Value) error { + switch name { + case notificationclient.FieldName: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetName(v) + return nil + case notificationclient.FieldService: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetService(v) + return nil + case notificationclient.FieldSettings: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetSettings(v) + return nil + case notificationclient.FieldEnabled: + v, ok := value.(bool) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetEnabled(v) + return nil + } + return fmt.Errorf("unknown NotificationClient field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *NotificationClientMutation) AddedFields() []string { + return nil +} + +// 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 *NotificationClientMutation) AddedField(name string) (ent.Value, bool) { + 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 *NotificationClientMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown NotificationClient numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *NotificationClientMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *NotificationClientMutation) 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 *NotificationClientMutation) ClearField(name string) error { + return fmt.Errorf("unknown NotificationClient 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 *NotificationClientMutation) ResetField(name string) error { + switch name { + case notificationclient.FieldName: + m.ResetName() + return nil + case notificationclient.FieldService: + m.ResetService() + return nil + case notificationclient.FieldSettings: + m.ResetSettings() + return nil + case notificationclient.FieldEnabled: + m.ResetEnabled() + return nil + } + return fmt.Errorf("unknown NotificationClient field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *NotificationClientMutation) 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 *NotificationClientMutation) AddedIDs(name string) []ent.Value { + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *NotificationClientMutation) 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 *NotificationClientMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *NotificationClientMutation) 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 *NotificationClientMutation) 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 *NotificationClientMutation) ClearEdge(name string) error { + return fmt.Errorf("unknown NotificationClient 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 *NotificationClientMutation) ResetEdge(name string) error { + return fmt.Errorf("unknown NotificationClient edge %s", name) +} + // SettingsMutation represents an operation that mutates the Settings nodes in the graph. type SettingsMutation struct { config diff --git a/ent/notificationclient.go b/ent/notificationclient.go new file mode 100644 index 0000000..464bf28 --- /dev/null +++ b/ent/notificationclient.go @@ -0,0 +1,138 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "polaris/ent/notificationclient" + "strings" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" +) + +// NotificationClient is the model entity for the NotificationClient schema. +type NotificationClient struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // Name holds the value of the "name" field. + Name string `json:"name,omitempty"` + // Service holds the value of the "service" field. + Service string `json:"service,omitempty"` + // Settings holds the value of the "settings" field. + Settings string `json:"settings,omitempty"` + // Enabled holds the value of the "enabled" field. + Enabled bool `json:"enabled,omitempty"` + selectValues sql.SelectValues +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*NotificationClient) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case notificationclient.FieldEnabled: + values[i] = new(sql.NullBool) + case notificationclient.FieldID: + values[i] = new(sql.NullInt64) + case notificationclient.FieldName, notificationclient.FieldService, notificationclient.FieldSettings: + values[i] = new(sql.NullString) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the NotificationClient fields. +func (nc *NotificationClient) 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 notificationclient.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + nc.ID = int(value.Int64) + case notificationclient.FieldName: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field name", values[i]) + } else if value.Valid { + nc.Name = value.String + } + case notificationclient.FieldService: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field service", values[i]) + } else if value.Valid { + nc.Service = value.String + } + case notificationclient.FieldSettings: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field settings", values[i]) + } else if value.Valid { + nc.Settings = value.String + } + case notificationclient.FieldEnabled: + if value, ok := values[i].(*sql.NullBool); !ok { + return fmt.Errorf("unexpected type %T for field enabled", values[i]) + } else if value.Valid { + nc.Enabled = value.Bool + } + default: + nc.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the NotificationClient. +// This includes values selected through modifiers, order, etc. +func (nc *NotificationClient) Value(name string) (ent.Value, error) { + return nc.selectValues.Get(name) +} + +// Update returns a builder for updating this NotificationClient. +// Note that you need to call NotificationClient.Unwrap() before calling this method if this NotificationClient +// was returned from a transaction, and the transaction was committed or rolled back. +func (nc *NotificationClient) Update() *NotificationClientUpdateOne { + return NewNotificationClientClient(nc.config).UpdateOne(nc) +} + +// Unwrap unwraps the NotificationClient 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 (nc *NotificationClient) Unwrap() *NotificationClient { + _tx, ok := nc.config.driver.(*txDriver) + if !ok { + panic("ent: NotificationClient is not a transactional entity") + } + nc.config.driver = _tx.drv + return nc +} + +// String implements the fmt.Stringer. +func (nc *NotificationClient) String() string { + var builder strings.Builder + builder.WriteString("NotificationClient(") + builder.WriteString(fmt.Sprintf("id=%v, ", nc.ID)) + builder.WriteString("name=") + builder.WriteString(nc.Name) + builder.WriteString(", ") + builder.WriteString("service=") + builder.WriteString(nc.Service) + builder.WriteString(", ") + builder.WriteString("settings=") + builder.WriteString(nc.Settings) + builder.WriteString(", ") + builder.WriteString("enabled=") + builder.WriteString(fmt.Sprintf("%v", nc.Enabled)) + builder.WriteByte(')') + return builder.String() +} + +// NotificationClients is a parsable slice of NotificationClient. +type NotificationClients []*NotificationClient diff --git a/ent/notificationclient/notificationclient.go b/ent/notificationclient/notificationclient.go new file mode 100644 index 0000000..320b66c --- /dev/null +++ b/ent/notificationclient/notificationclient.go @@ -0,0 +1,76 @@ +// Code generated by ent, DO NOT EDIT. + +package notificationclient + +import ( + "entgo.io/ent/dialect/sql" +) + +const ( + // Label holds the string label denoting the notificationclient type in the database. + Label = "notification_client" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldName holds the string denoting the name field in the database. + FieldName = "name" + // FieldService holds the string denoting the service field in the database. + FieldService = "service" + // FieldSettings holds the string denoting the settings field in the database. + FieldSettings = "settings" + // FieldEnabled holds the string denoting the enabled field in the database. + FieldEnabled = "enabled" + // Table holds the table name of the notificationclient in the database. + Table = "notification_clients" +) + +// Columns holds all SQL columns for notificationclient fields. +var Columns = []string{ + FieldID, + FieldName, + FieldService, + FieldSettings, + FieldEnabled, +} + +// 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 +} + +var ( + // DefaultEnabled holds the default value on creation for the "enabled" field. + DefaultEnabled bool +) + +// OrderOption defines the ordering options for the NotificationClient 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() +} + +// ByName orders the results by the name field. +func ByName(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldName, opts...).ToFunc() +} + +// ByService orders the results by the service field. +func ByService(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldService, opts...).ToFunc() +} + +// BySettings orders the results by the settings field. +func BySettings(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldSettings, opts...).ToFunc() +} + +// ByEnabled orders the results by the enabled field. +func ByEnabled(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldEnabled, opts...).ToFunc() +} diff --git a/ent/notificationclient/where.go b/ent/notificationclient/where.go new file mode 100644 index 0000000..25bec43 --- /dev/null +++ b/ent/notificationclient/where.go @@ -0,0 +1,294 @@ +// Code generated by ent, DO NOT EDIT. + +package notificationclient + +import ( + "polaris/ent/predicate" + + "entgo.io/ent/dialect/sql" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldLTE(FieldID, id)) +} + +// Name applies equality check predicate on the "name" field. It's identical to NameEQ. +func Name(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEQ(FieldName, v)) +} + +// Service applies equality check predicate on the "service" field. It's identical to ServiceEQ. +func Service(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEQ(FieldService, v)) +} + +// Settings applies equality check predicate on the "settings" field. It's identical to SettingsEQ. +func Settings(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEQ(FieldSettings, v)) +} + +// Enabled applies equality check predicate on the "enabled" field. It's identical to EnabledEQ. +func Enabled(v bool) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEQ(FieldEnabled, v)) +} + +// NameEQ applies the EQ predicate on the "name" field. +func NameEQ(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEQ(FieldName, v)) +} + +// NameNEQ applies the NEQ predicate on the "name" field. +func NameNEQ(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldNEQ(FieldName, v)) +} + +// NameIn applies the In predicate on the "name" field. +func NameIn(vs ...string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldIn(FieldName, vs...)) +} + +// NameNotIn applies the NotIn predicate on the "name" field. +func NameNotIn(vs ...string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldNotIn(FieldName, vs...)) +} + +// NameGT applies the GT predicate on the "name" field. +func NameGT(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldGT(FieldName, v)) +} + +// NameGTE applies the GTE predicate on the "name" field. +func NameGTE(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldGTE(FieldName, v)) +} + +// NameLT applies the LT predicate on the "name" field. +func NameLT(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldLT(FieldName, v)) +} + +// NameLTE applies the LTE predicate on the "name" field. +func NameLTE(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldLTE(FieldName, v)) +} + +// NameContains applies the Contains predicate on the "name" field. +func NameContains(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldContains(FieldName, v)) +} + +// NameHasPrefix applies the HasPrefix predicate on the "name" field. +func NameHasPrefix(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldHasPrefix(FieldName, v)) +} + +// NameHasSuffix applies the HasSuffix predicate on the "name" field. +func NameHasSuffix(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldHasSuffix(FieldName, v)) +} + +// NameEqualFold applies the EqualFold predicate on the "name" field. +func NameEqualFold(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEqualFold(FieldName, v)) +} + +// NameContainsFold applies the ContainsFold predicate on the "name" field. +func NameContainsFold(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldContainsFold(FieldName, v)) +} + +// ServiceEQ applies the EQ predicate on the "service" field. +func ServiceEQ(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEQ(FieldService, v)) +} + +// ServiceNEQ applies the NEQ predicate on the "service" field. +func ServiceNEQ(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldNEQ(FieldService, v)) +} + +// ServiceIn applies the In predicate on the "service" field. +func ServiceIn(vs ...string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldIn(FieldService, vs...)) +} + +// ServiceNotIn applies the NotIn predicate on the "service" field. +func ServiceNotIn(vs ...string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldNotIn(FieldService, vs...)) +} + +// ServiceGT applies the GT predicate on the "service" field. +func ServiceGT(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldGT(FieldService, v)) +} + +// ServiceGTE applies the GTE predicate on the "service" field. +func ServiceGTE(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldGTE(FieldService, v)) +} + +// ServiceLT applies the LT predicate on the "service" field. +func ServiceLT(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldLT(FieldService, v)) +} + +// ServiceLTE applies the LTE predicate on the "service" field. +func ServiceLTE(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldLTE(FieldService, v)) +} + +// ServiceContains applies the Contains predicate on the "service" field. +func ServiceContains(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldContains(FieldService, v)) +} + +// ServiceHasPrefix applies the HasPrefix predicate on the "service" field. +func ServiceHasPrefix(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldHasPrefix(FieldService, v)) +} + +// ServiceHasSuffix applies the HasSuffix predicate on the "service" field. +func ServiceHasSuffix(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldHasSuffix(FieldService, v)) +} + +// ServiceEqualFold applies the EqualFold predicate on the "service" field. +func ServiceEqualFold(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEqualFold(FieldService, v)) +} + +// ServiceContainsFold applies the ContainsFold predicate on the "service" field. +func ServiceContainsFold(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldContainsFold(FieldService, v)) +} + +// SettingsEQ applies the EQ predicate on the "settings" field. +func SettingsEQ(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEQ(FieldSettings, v)) +} + +// SettingsNEQ applies the NEQ predicate on the "settings" field. +func SettingsNEQ(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldNEQ(FieldSettings, v)) +} + +// SettingsIn applies the In predicate on the "settings" field. +func SettingsIn(vs ...string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldIn(FieldSettings, vs...)) +} + +// SettingsNotIn applies the NotIn predicate on the "settings" field. +func SettingsNotIn(vs ...string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldNotIn(FieldSettings, vs...)) +} + +// SettingsGT applies the GT predicate on the "settings" field. +func SettingsGT(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldGT(FieldSettings, v)) +} + +// SettingsGTE applies the GTE predicate on the "settings" field. +func SettingsGTE(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldGTE(FieldSettings, v)) +} + +// SettingsLT applies the LT predicate on the "settings" field. +func SettingsLT(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldLT(FieldSettings, v)) +} + +// SettingsLTE applies the LTE predicate on the "settings" field. +func SettingsLTE(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldLTE(FieldSettings, v)) +} + +// SettingsContains applies the Contains predicate on the "settings" field. +func SettingsContains(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldContains(FieldSettings, v)) +} + +// SettingsHasPrefix applies the HasPrefix predicate on the "settings" field. +func SettingsHasPrefix(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldHasPrefix(FieldSettings, v)) +} + +// SettingsHasSuffix applies the HasSuffix predicate on the "settings" field. +func SettingsHasSuffix(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldHasSuffix(FieldSettings, v)) +} + +// SettingsEqualFold applies the EqualFold predicate on the "settings" field. +func SettingsEqualFold(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEqualFold(FieldSettings, v)) +} + +// SettingsContainsFold applies the ContainsFold predicate on the "settings" field. +func SettingsContainsFold(v string) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldContainsFold(FieldSettings, v)) +} + +// EnabledEQ applies the EQ predicate on the "enabled" field. +func EnabledEQ(v bool) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldEQ(FieldEnabled, v)) +} + +// EnabledNEQ applies the NEQ predicate on the "enabled" field. +func EnabledNEQ(v bool) predicate.NotificationClient { + return predicate.NotificationClient(sql.FieldNEQ(FieldEnabled, v)) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.NotificationClient) predicate.NotificationClient { + return predicate.NotificationClient(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.NotificationClient) predicate.NotificationClient { + return predicate.NotificationClient(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.NotificationClient) predicate.NotificationClient { + return predicate.NotificationClient(sql.NotPredicates(p)) +} diff --git a/ent/notificationclient_create.go b/ent/notificationclient_create.go new file mode 100644 index 0000000..70d3a6f --- /dev/null +++ b/ent/notificationclient_create.go @@ -0,0 +1,240 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "polaris/ent/notificationclient" + + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// NotificationClientCreate is the builder for creating a NotificationClient entity. +type NotificationClientCreate struct { + config + mutation *NotificationClientMutation + hooks []Hook +} + +// SetName sets the "name" field. +func (ncc *NotificationClientCreate) SetName(s string) *NotificationClientCreate { + ncc.mutation.SetName(s) + return ncc +} + +// SetService sets the "service" field. +func (ncc *NotificationClientCreate) SetService(s string) *NotificationClientCreate { + ncc.mutation.SetService(s) + return ncc +} + +// SetSettings sets the "settings" field. +func (ncc *NotificationClientCreate) SetSettings(s string) *NotificationClientCreate { + ncc.mutation.SetSettings(s) + return ncc +} + +// SetEnabled sets the "enabled" field. +func (ncc *NotificationClientCreate) SetEnabled(b bool) *NotificationClientCreate { + ncc.mutation.SetEnabled(b) + return ncc +} + +// SetNillableEnabled sets the "enabled" field if the given value is not nil. +func (ncc *NotificationClientCreate) SetNillableEnabled(b *bool) *NotificationClientCreate { + if b != nil { + ncc.SetEnabled(*b) + } + return ncc +} + +// Mutation returns the NotificationClientMutation object of the builder. +func (ncc *NotificationClientCreate) Mutation() *NotificationClientMutation { + return ncc.mutation +} + +// Save creates the NotificationClient in the database. +func (ncc *NotificationClientCreate) Save(ctx context.Context) (*NotificationClient, error) { + ncc.defaults() + return withHooks(ctx, ncc.sqlSave, ncc.mutation, ncc.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (ncc *NotificationClientCreate) SaveX(ctx context.Context) *NotificationClient { + v, err := ncc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (ncc *NotificationClientCreate) Exec(ctx context.Context) error { + _, err := ncc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ncc *NotificationClientCreate) ExecX(ctx context.Context) { + if err := ncc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (ncc *NotificationClientCreate) defaults() { + if _, ok := ncc.mutation.Enabled(); !ok { + v := notificationclient.DefaultEnabled + ncc.mutation.SetEnabled(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (ncc *NotificationClientCreate) check() error { + if _, ok := ncc.mutation.Name(); !ok { + return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "NotificationClient.name"`)} + } + if _, ok := ncc.mutation.Service(); !ok { + return &ValidationError{Name: "service", err: errors.New(`ent: missing required field "NotificationClient.service"`)} + } + if _, ok := ncc.mutation.Settings(); !ok { + return &ValidationError{Name: "settings", err: errors.New(`ent: missing required field "NotificationClient.settings"`)} + } + if _, ok := ncc.mutation.Enabled(); !ok { + return &ValidationError{Name: "enabled", err: errors.New(`ent: missing required field "NotificationClient.enabled"`)} + } + return nil +} + +func (ncc *NotificationClientCreate) sqlSave(ctx context.Context) (*NotificationClient, error) { + if err := ncc.check(); err != nil { + return nil, err + } + _node, _spec := ncc.createSpec() + if err := sqlgraph.CreateNode(ctx, ncc.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) + ncc.mutation.id = &_node.ID + ncc.mutation.done = true + return _node, nil +} + +func (ncc *NotificationClientCreate) createSpec() (*NotificationClient, *sqlgraph.CreateSpec) { + var ( + _node = &NotificationClient{config: ncc.config} + _spec = sqlgraph.NewCreateSpec(notificationclient.Table, sqlgraph.NewFieldSpec(notificationclient.FieldID, field.TypeInt)) + ) + if value, ok := ncc.mutation.Name(); ok { + _spec.SetField(notificationclient.FieldName, field.TypeString, value) + _node.Name = value + } + if value, ok := ncc.mutation.Service(); ok { + _spec.SetField(notificationclient.FieldService, field.TypeString, value) + _node.Service = value + } + if value, ok := ncc.mutation.Settings(); ok { + _spec.SetField(notificationclient.FieldSettings, field.TypeString, value) + _node.Settings = value + } + if value, ok := ncc.mutation.Enabled(); ok { + _spec.SetField(notificationclient.FieldEnabled, field.TypeBool, value) + _node.Enabled = value + } + return _node, _spec +} + +// NotificationClientCreateBulk is the builder for creating many NotificationClient entities in bulk. +type NotificationClientCreateBulk struct { + config + err error + builders []*NotificationClientCreate +} + +// Save creates the NotificationClient entities in the database. +func (nccb *NotificationClientCreateBulk) Save(ctx context.Context) ([]*NotificationClient, error) { + if nccb.err != nil { + return nil, nccb.err + } + specs := make([]*sqlgraph.CreateSpec, len(nccb.builders)) + nodes := make([]*NotificationClient, len(nccb.builders)) + mutators := make([]Mutator, len(nccb.builders)) + for i := range nccb.builders { + func(i int, root context.Context) { + builder := nccb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*NotificationClientMutation) + 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, nccb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, nccb.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, nccb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (nccb *NotificationClientCreateBulk) SaveX(ctx context.Context) []*NotificationClient { + v, err := nccb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (nccb *NotificationClientCreateBulk) Exec(ctx context.Context) error { + _, err := nccb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (nccb *NotificationClientCreateBulk) ExecX(ctx context.Context) { + if err := nccb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/notificationclient_delete.go b/ent/notificationclient_delete.go new file mode 100644 index 0000000..1a28411 --- /dev/null +++ b/ent/notificationclient_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "polaris/ent/notificationclient" + "polaris/ent/predicate" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// NotificationClientDelete is the builder for deleting a NotificationClient entity. +type NotificationClientDelete struct { + config + hooks []Hook + mutation *NotificationClientMutation +} + +// Where appends a list predicates to the NotificationClientDelete builder. +func (ncd *NotificationClientDelete) Where(ps ...predicate.NotificationClient) *NotificationClientDelete { + ncd.mutation.Where(ps...) + return ncd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (ncd *NotificationClientDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, ncd.sqlExec, ncd.mutation, ncd.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (ncd *NotificationClientDelete) ExecX(ctx context.Context) int { + n, err := ncd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (ncd *NotificationClientDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(notificationclient.Table, sqlgraph.NewFieldSpec(notificationclient.FieldID, field.TypeInt)) + if ps := ncd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, ncd.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + ncd.mutation.done = true + return affected, err +} + +// NotificationClientDeleteOne is the builder for deleting a single NotificationClient entity. +type NotificationClientDeleteOne struct { + ncd *NotificationClientDelete +} + +// Where appends a list predicates to the NotificationClientDelete builder. +func (ncdo *NotificationClientDeleteOne) Where(ps ...predicate.NotificationClient) *NotificationClientDeleteOne { + ncdo.ncd.mutation.Where(ps...) + return ncdo +} + +// Exec executes the deletion query. +func (ncdo *NotificationClientDeleteOne) Exec(ctx context.Context) error { + n, err := ncdo.ncd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{notificationclient.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (ncdo *NotificationClientDeleteOne) ExecX(ctx context.Context) { + if err := ncdo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/notificationclient_query.go b/ent/notificationclient_query.go new file mode 100644 index 0000000..7381002 --- /dev/null +++ b/ent/notificationclient_query.go @@ -0,0 +1,526 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "math" + "polaris/ent/notificationclient" + "polaris/ent/predicate" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// NotificationClientQuery is the builder for querying NotificationClient entities. +type NotificationClientQuery struct { + config + ctx *QueryContext + order []notificationclient.OrderOption + inters []Interceptor + predicates []predicate.NotificationClient + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the NotificationClientQuery builder. +func (ncq *NotificationClientQuery) Where(ps ...predicate.NotificationClient) *NotificationClientQuery { + ncq.predicates = append(ncq.predicates, ps...) + return ncq +} + +// Limit the number of records to be returned by this query. +func (ncq *NotificationClientQuery) Limit(limit int) *NotificationClientQuery { + ncq.ctx.Limit = &limit + return ncq +} + +// Offset to start from. +func (ncq *NotificationClientQuery) Offset(offset int) *NotificationClientQuery { + ncq.ctx.Offset = &offset + return ncq +} + +// 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 (ncq *NotificationClientQuery) Unique(unique bool) *NotificationClientQuery { + ncq.ctx.Unique = &unique + return ncq +} + +// Order specifies how the records should be ordered. +func (ncq *NotificationClientQuery) Order(o ...notificationclient.OrderOption) *NotificationClientQuery { + ncq.order = append(ncq.order, o...) + return ncq +} + +// First returns the first NotificationClient entity from the query. +// Returns a *NotFoundError when no NotificationClient was found. +func (ncq *NotificationClientQuery) First(ctx context.Context) (*NotificationClient, error) { + nodes, err := ncq.Limit(1).All(setContextOp(ctx, ncq.ctx, "First")) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{notificationclient.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (ncq *NotificationClientQuery) FirstX(ctx context.Context) *NotificationClient { + node, err := ncq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first NotificationClient ID from the query. +// Returns a *NotFoundError when no NotificationClient ID was found. +func (ncq *NotificationClientQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = ncq.Limit(1).IDs(setContextOp(ctx, ncq.ctx, "FirstID")); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{notificationclient.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (ncq *NotificationClientQuery) FirstIDX(ctx context.Context) int { + id, err := ncq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single NotificationClient entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one NotificationClient entity is found. +// Returns a *NotFoundError when no NotificationClient entities are found. +func (ncq *NotificationClientQuery) Only(ctx context.Context) (*NotificationClient, error) { + nodes, err := ncq.Limit(2).All(setContextOp(ctx, ncq.ctx, "Only")) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{notificationclient.Label} + default: + return nil, &NotSingularError{notificationclient.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (ncq *NotificationClientQuery) OnlyX(ctx context.Context) *NotificationClient { + node, err := ncq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only NotificationClient ID in the query. +// Returns a *NotSingularError when more than one NotificationClient ID is found. +// Returns a *NotFoundError when no entities are found. +func (ncq *NotificationClientQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = ncq.Limit(2).IDs(setContextOp(ctx, ncq.ctx, "OnlyID")); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{notificationclient.Label} + default: + err = &NotSingularError{notificationclient.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (ncq *NotificationClientQuery) OnlyIDX(ctx context.Context) int { + id, err := ncq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of NotificationClients. +func (ncq *NotificationClientQuery) All(ctx context.Context) ([]*NotificationClient, error) { + ctx = setContextOp(ctx, ncq.ctx, "All") + if err := ncq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*NotificationClient, *NotificationClientQuery]() + return withInterceptors[[]*NotificationClient](ctx, ncq, qr, ncq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (ncq *NotificationClientQuery) AllX(ctx context.Context) []*NotificationClient { + nodes, err := ncq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of NotificationClient IDs. +func (ncq *NotificationClientQuery) IDs(ctx context.Context) (ids []int, err error) { + if ncq.ctx.Unique == nil && ncq.path != nil { + ncq.Unique(true) + } + ctx = setContextOp(ctx, ncq.ctx, "IDs") + if err = ncq.Select(notificationclient.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (ncq *NotificationClientQuery) IDsX(ctx context.Context) []int { + ids, err := ncq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (ncq *NotificationClientQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, ncq.ctx, "Count") + if err := ncq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, ncq, querierCount[*NotificationClientQuery](), ncq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (ncq *NotificationClientQuery) CountX(ctx context.Context) int { + count, err := ncq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (ncq *NotificationClientQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, ncq.ctx, "Exist") + switch _, err := ncq.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 (ncq *NotificationClientQuery) ExistX(ctx context.Context) bool { + exist, err := ncq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the NotificationClientQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (ncq *NotificationClientQuery) Clone() *NotificationClientQuery { + if ncq == nil { + return nil + } + return &NotificationClientQuery{ + config: ncq.config, + ctx: ncq.ctx.Clone(), + order: append([]notificationclient.OrderOption{}, ncq.order...), + inters: append([]Interceptor{}, ncq.inters...), + predicates: append([]predicate.NotificationClient{}, ncq.predicates...), + // clone intermediate query. + sql: ncq.sql.Clone(), + path: ncq.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 { +// Name string `json:"name,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.NotificationClient.Query(). +// GroupBy(notificationclient.FieldName). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (ncq *NotificationClientQuery) GroupBy(field string, fields ...string) *NotificationClientGroupBy { + ncq.ctx.Fields = append([]string{field}, fields...) + grbuild := &NotificationClientGroupBy{build: ncq} + grbuild.flds = &ncq.ctx.Fields + grbuild.label = notificationclient.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 { +// Name string `json:"name,omitempty"` +// } +// +// client.NotificationClient.Query(). +// Select(notificationclient.FieldName). +// Scan(ctx, &v) +func (ncq *NotificationClientQuery) Select(fields ...string) *NotificationClientSelect { + ncq.ctx.Fields = append(ncq.ctx.Fields, fields...) + sbuild := &NotificationClientSelect{NotificationClientQuery: ncq} + sbuild.label = notificationclient.Label + sbuild.flds, sbuild.scan = &ncq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a NotificationClientSelect configured with the given aggregations. +func (ncq *NotificationClientQuery) Aggregate(fns ...AggregateFunc) *NotificationClientSelect { + return ncq.Select().Aggregate(fns...) +} + +func (ncq *NotificationClientQuery) prepareQuery(ctx context.Context) error { + for _, inter := range ncq.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, ncq); err != nil { + return err + } + } + } + for _, f := range ncq.ctx.Fields { + if !notificationclient.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if ncq.path != nil { + prev, err := ncq.path(ctx) + if err != nil { + return err + } + ncq.sql = prev + } + return nil +} + +func (ncq *NotificationClientQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*NotificationClient, error) { + var ( + nodes = []*NotificationClient{} + _spec = ncq.querySpec() + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*NotificationClient).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &NotificationClient{config: ncq.config} + nodes = append(nodes, node) + return node.assignValues(columns, values) + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, ncq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + return nodes, nil +} + +func (ncq *NotificationClientQuery) sqlCount(ctx context.Context) (int, error) { + _spec := ncq.querySpec() + _spec.Node.Columns = ncq.ctx.Fields + if len(ncq.ctx.Fields) > 0 { + _spec.Unique = ncq.ctx.Unique != nil && *ncq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, ncq.driver, _spec) +} + +func (ncq *NotificationClientQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(notificationclient.Table, notificationclient.Columns, sqlgraph.NewFieldSpec(notificationclient.FieldID, field.TypeInt)) + _spec.From = ncq.sql + if unique := ncq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if ncq.path != nil { + _spec.Unique = true + } + if fields := ncq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, notificationclient.FieldID) + for i := range fields { + if fields[i] != notificationclient.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := ncq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := ncq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := ncq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := ncq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (ncq *NotificationClientQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(ncq.driver.Dialect()) + t1 := builder.Table(notificationclient.Table) + columns := ncq.ctx.Fields + if len(columns) == 0 { + columns = notificationclient.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if ncq.sql != nil { + selector = ncq.sql + selector.Select(selector.Columns(columns...)...) + } + if ncq.ctx.Unique != nil && *ncq.ctx.Unique { + selector.Distinct() + } + for _, p := range ncq.predicates { + p(selector) + } + for _, p := range ncq.order { + p(selector) + } + if offset := ncq.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 := ncq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// NotificationClientGroupBy is the group-by builder for NotificationClient entities. +type NotificationClientGroupBy struct { + selector + build *NotificationClientQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (ncgb *NotificationClientGroupBy) Aggregate(fns ...AggregateFunc) *NotificationClientGroupBy { + ncgb.fns = append(ncgb.fns, fns...) + return ncgb +} + +// Scan applies the selector query and scans the result into the given value. +func (ncgb *NotificationClientGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, ncgb.build.ctx, "GroupBy") + if err := ncgb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*NotificationClientQuery, *NotificationClientGroupBy](ctx, ncgb.build, ncgb, ncgb.build.inters, v) +} + +func (ncgb *NotificationClientGroupBy) sqlScan(ctx context.Context, root *NotificationClientQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(ncgb.fns)) + for _, fn := range ncgb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*ncgb.flds)+len(ncgb.fns)) + for _, f := range *ncgb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*ncgb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := ncgb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// NotificationClientSelect is the builder for selecting fields of NotificationClient entities. +type NotificationClientSelect struct { + *NotificationClientQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (ncs *NotificationClientSelect) Aggregate(fns ...AggregateFunc) *NotificationClientSelect { + ncs.fns = append(ncs.fns, fns...) + return ncs +} + +// Scan applies the selector query and scans the result into the given value. +func (ncs *NotificationClientSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, ncs.ctx, "Select") + if err := ncs.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*NotificationClientQuery, *NotificationClientSelect](ctx, ncs.NotificationClientQuery, ncs, ncs.inters, v) +} + +func (ncs *NotificationClientSelect) sqlScan(ctx context.Context, root *NotificationClientQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(ncs.fns)) + for _, fn := range ncs.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*ncs.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 := ncs.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/ent/notificationclient_update.go b/ent/notificationclient_update.go new file mode 100644 index 0000000..9ff7dec --- /dev/null +++ b/ent/notificationclient_update.go @@ -0,0 +1,311 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "polaris/ent/notificationclient" + "polaris/ent/predicate" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// NotificationClientUpdate is the builder for updating NotificationClient entities. +type NotificationClientUpdate struct { + config + hooks []Hook + mutation *NotificationClientMutation +} + +// Where appends a list predicates to the NotificationClientUpdate builder. +func (ncu *NotificationClientUpdate) Where(ps ...predicate.NotificationClient) *NotificationClientUpdate { + ncu.mutation.Where(ps...) + return ncu +} + +// SetName sets the "name" field. +func (ncu *NotificationClientUpdate) SetName(s string) *NotificationClientUpdate { + ncu.mutation.SetName(s) + return ncu +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (ncu *NotificationClientUpdate) SetNillableName(s *string) *NotificationClientUpdate { + if s != nil { + ncu.SetName(*s) + } + return ncu +} + +// SetService sets the "service" field. +func (ncu *NotificationClientUpdate) SetService(s string) *NotificationClientUpdate { + ncu.mutation.SetService(s) + return ncu +} + +// SetNillableService sets the "service" field if the given value is not nil. +func (ncu *NotificationClientUpdate) SetNillableService(s *string) *NotificationClientUpdate { + if s != nil { + ncu.SetService(*s) + } + return ncu +} + +// SetSettings sets the "settings" field. +func (ncu *NotificationClientUpdate) SetSettings(s string) *NotificationClientUpdate { + ncu.mutation.SetSettings(s) + return ncu +} + +// SetNillableSettings sets the "settings" field if the given value is not nil. +func (ncu *NotificationClientUpdate) SetNillableSettings(s *string) *NotificationClientUpdate { + if s != nil { + ncu.SetSettings(*s) + } + return ncu +} + +// SetEnabled sets the "enabled" field. +func (ncu *NotificationClientUpdate) SetEnabled(b bool) *NotificationClientUpdate { + ncu.mutation.SetEnabled(b) + return ncu +} + +// SetNillableEnabled sets the "enabled" field if the given value is not nil. +func (ncu *NotificationClientUpdate) SetNillableEnabled(b *bool) *NotificationClientUpdate { + if b != nil { + ncu.SetEnabled(*b) + } + return ncu +} + +// Mutation returns the NotificationClientMutation object of the builder. +func (ncu *NotificationClientUpdate) Mutation() *NotificationClientMutation { + return ncu.mutation +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (ncu *NotificationClientUpdate) Save(ctx context.Context) (int, error) { + return withHooks(ctx, ncu.sqlSave, ncu.mutation, ncu.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (ncu *NotificationClientUpdate) SaveX(ctx context.Context) int { + affected, err := ncu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (ncu *NotificationClientUpdate) Exec(ctx context.Context) error { + _, err := ncu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ncu *NotificationClientUpdate) ExecX(ctx context.Context) { + if err := ncu.Exec(ctx); err != nil { + panic(err) + } +} + +func (ncu *NotificationClientUpdate) sqlSave(ctx context.Context) (n int, err error) { + _spec := sqlgraph.NewUpdateSpec(notificationclient.Table, notificationclient.Columns, sqlgraph.NewFieldSpec(notificationclient.FieldID, field.TypeInt)) + if ps := ncu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := ncu.mutation.Name(); ok { + _spec.SetField(notificationclient.FieldName, field.TypeString, value) + } + if value, ok := ncu.mutation.Service(); ok { + _spec.SetField(notificationclient.FieldService, field.TypeString, value) + } + if value, ok := ncu.mutation.Settings(); ok { + _spec.SetField(notificationclient.FieldSettings, field.TypeString, value) + } + if value, ok := ncu.mutation.Enabled(); ok { + _spec.SetField(notificationclient.FieldEnabled, field.TypeBool, value) + } + if n, err = sqlgraph.UpdateNodes(ctx, ncu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{notificationclient.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + ncu.mutation.done = true + return n, nil +} + +// NotificationClientUpdateOne is the builder for updating a single NotificationClient entity. +type NotificationClientUpdateOne struct { + config + fields []string + hooks []Hook + mutation *NotificationClientMutation +} + +// SetName sets the "name" field. +func (ncuo *NotificationClientUpdateOne) SetName(s string) *NotificationClientUpdateOne { + ncuo.mutation.SetName(s) + return ncuo +} + +// SetNillableName sets the "name" field if the given value is not nil. +func (ncuo *NotificationClientUpdateOne) SetNillableName(s *string) *NotificationClientUpdateOne { + if s != nil { + ncuo.SetName(*s) + } + return ncuo +} + +// SetService sets the "service" field. +func (ncuo *NotificationClientUpdateOne) SetService(s string) *NotificationClientUpdateOne { + ncuo.mutation.SetService(s) + return ncuo +} + +// SetNillableService sets the "service" field if the given value is not nil. +func (ncuo *NotificationClientUpdateOne) SetNillableService(s *string) *NotificationClientUpdateOne { + if s != nil { + ncuo.SetService(*s) + } + return ncuo +} + +// SetSettings sets the "settings" field. +func (ncuo *NotificationClientUpdateOne) SetSettings(s string) *NotificationClientUpdateOne { + ncuo.mutation.SetSettings(s) + return ncuo +} + +// SetNillableSettings sets the "settings" field if the given value is not nil. +func (ncuo *NotificationClientUpdateOne) SetNillableSettings(s *string) *NotificationClientUpdateOne { + if s != nil { + ncuo.SetSettings(*s) + } + return ncuo +} + +// SetEnabled sets the "enabled" field. +func (ncuo *NotificationClientUpdateOne) SetEnabled(b bool) *NotificationClientUpdateOne { + ncuo.mutation.SetEnabled(b) + return ncuo +} + +// SetNillableEnabled sets the "enabled" field if the given value is not nil. +func (ncuo *NotificationClientUpdateOne) SetNillableEnabled(b *bool) *NotificationClientUpdateOne { + if b != nil { + ncuo.SetEnabled(*b) + } + return ncuo +} + +// Mutation returns the NotificationClientMutation object of the builder. +func (ncuo *NotificationClientUpdateOne) Mutation() *NotificationClientMutation { + return ncuo.mutation +} + +// Where appends a list predicates to the NotificationClientUpdate builder. +func (ncuo *NotificationClientUpdateOne) Where(ps ...predicate.NotificationClient) *NotificationClientUpdateOne { + ncuo.mutation.Where(ps...) + return ncuo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (ncuo *NotificationClientUpdateOne) Select(field string, fields ...string) *NotificationClientUpdateOne { + ncuo.fields = append([]string{field}, fields...) + return ncuo +} + +// Save executes the query and returns the updated NotificationClient entity. +func (ncuo *NotificationClientUpdateOne) Save(ctx context.Context) (*NotificationClient, error) { + return withHooks(ctx, ncuo.sqlSave, ncuo.mutation, ncuo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (ncuo *NotificationClientUpdateOne) SaveX(ctx context.Context) *NotificationClient { + node, err := ncuo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (ncuo *NotificationClientUpdateOne) Exec(ctx context.Context) error { + _, err := ncuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ncuo *NotificationClientUpdateOne) ExecX(ctx context.Context) { + if err := ncuo.Exec(ctx); err != nil { + panic(err) + } +} + +func (ncuo *NotificationClientUpdateOne) sqlSave(ctx context.Context) (_node *NotificationClient, err error) { + _spec := sqlgraph.NewUpdateSpec(notificationclient.Table, notificationclient.Columns, sqlgraph.NewFieldSpec(notificationclient.FieldID, field.TypeInt)) + id, ok := ncuo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "NotificationClient.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := ncuo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, notificationclient.FieldID) + for _, f := range fields { + if !notificationclient.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != notificationclient.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := ncuo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := ncuo.mutation.Name(); ok { + _spec.SetField(notificationclient.FieldName, field.TypeString, value) + } + if value, ok := ncuo.mutation.Service(); ok { + _spec.SetField(notificationclient.FieldService, field.TypeString, value) + } + if value, ok := ncuo.mutation.Settings(); ok { + _spec.SetField(notificationclient.FieldSettings, field.TypeString, value) + } + if value, ok := ncuo.mutation.Enabled(); ok { + _spec.SetField(notificationclient.FieldEnabled, field.TypeBool, value) + } + _node = &NotificationClient{config: ncuo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, ncuo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{notificationclient.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + ncuo.mutation.done = true + return _node, nil +} diff --git a/ent/predicate/predicate.go b/ent/predicate/predicate.go index 8a8db0b..859847f 100644 --- a/ent/predicate/predicate.go +++ b/ent/predicate/predicate.go @@ -21,6 +21,9 @@ type Indexers func(*sql.Selector) // Media is the predicate function for media builders. type Media func(*sql.Selector) +// NotificationClient is the predicate function for notificationclient builders. +type NotificationClient func(*sql.Selector) + // Settings is the predicate function for settings builders. type Settings func(*sql.Selector) diff --git a/ent/runtime.go b/ent/runtime.go index 95bd1fc..c989275 100644 --- a/ent/runtime.go +++ b/ent/runtime.go @@ -7,6 +7,7 @@ import ( "polaris/ent/history" "polaris/ent/indexers" "polaris/ent/media" + "polaris/ent/notificationclient" "polaris/ent/schema" "polaris/ent/storage" "time" @@ -74,6 +75,12 @@ func init() { mediaDescDownloadHistoryEpisodes := mediaFields[12].Descriptor() // media.DefaultDownloadHistoryEpisodes holds the default value on creation for the download_history_episodes field. media.DefaultDownloadHistoryEpisodes = mediaDescDownloadHistoryEpisodes.Default.(bool) + notificationclientFields := schema.NotificationClient{}.Fields() + _ = notificationclientFields + // notificationclientDescEnabled is the schema descriptor for enabled field. + notificationclientDescEnabled := notificationclientFields[3].Descriptor() + // notificationclient.DefaultEnabled holds the default value on creation for the enabled field. + notificationclient.DefaultEnabled = notificationclientDescEnabled.Default.(bool) storageFields := schema.Storage{}.Fields() _ = storageFields // storageDescDeleted is the schema descriptor for deleted field. diff --git a/ent/schema/notificationclient.go b/ent/schema/notificationclient.go new file mode 100644 index 0000000..914ea54 --- /dev/null +++ b/ent/schema/notificationclient.go @@ -0,0 +1,26 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/schema/field" +) + +// NotificationClient holds the schema definition for the NotificationClient entity. +type NotificationClient struct { + ent.Schema +} + +// Fields of the NotificationClient. +func (NotificationClient) Fields() []ent.Field { + return []ent.Field{ + field.String("name"), + field.String("service"), + field.String("settings"), + field.Bool("enabled").Default(true), + } +} + +// Edges of the NotificationClient. +func (NotificationClient) Edges() []ent.Edge { + return nil +} diff --git a/ent/tx.go b/ent/tx.go index f038106..bf1d3be 100644 --- a/ent/tx.go +++ b/ent/tx.go @@ -22,6 +22,8 @@ type Tx struct { Indexers *IndexersClient // Media is the client for interacting with the Media builders. Media *MediaClient + // NotificationClient is the client for interacting with the NotificationClient builders. + NotificationClient *NotificationClientClient // Settings is the client for interacting with the Settings builders. Settings *SettingsClient // Storage is the client for interacting with the Storage builders. @@ -162,6 +164,7 @@ func (tx *Tx) init() { tx.History = NewHistoryClient(tx.config) tx.Indexers = NewIndexersClient(tx.config) tx.Media = NewMediaClient(tx.config) + tx.NotificationClient = NewNotificationClientClient(tx.config) tx.Settings = NewSettingsClient(tx.config) tx.Storage = NewStorageClient(tx.config) } diff --git a/go.mod b/go.mod index e8354b9..30a9e25 100644 --- a/go.mod +++ b/go.mod @@ -8,14 +8,28 @@ require ( github.com/mattn/go-sqlite3 v1.14.16 github.com/robfig/cron v1.2.0 go.uber.org/zap v1.27.0 - golang.org/x/net v0.25.0 + golang.org/x/net v0.27.0 ) -require github.com/adrg/strutil v0.3.1 +require ( + github.com/adrg/strutil v0.3.1 + github.com/gin-contrib/zap v1.1.3 + github.com/nikoksr/notify v1.0.0 +) require ( - github.com/gin-contrib/zap v1.1.3 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect + github.com/blinkbean/dingtalk v1.1.3 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect + github.com/gregdel/pushover v1.3.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/technoweenie/multipartstreamer v1.0.1 // indirect + golang.org/x/sync v0.7.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect ) require ( @@ -36,7 +50,7 @@ require ( github.com/go-playground/validator/v10 v10.20.0 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/uuid v1.4.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl/v2 v2.13.0 // indirect @@ -60,12 +74,12 @@ require ( github.com/ugorji/go/codec v1.2.12 // indirect github.com/zclconf/go-cty v1.8.0 // indirect golang.org/x/arch v0.8.0 // indirect - golang.org/x/crypto v0.23.0 - golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 - golang.org/x/mod v0.17.0 // indirect - golang.org/x/sys v0.21.0 + golang.org/x/crypto v0.25.0 + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 + golang.org/x/mod v0.19.0 // indirect + golang.org/x/sys v0.22.0 golang.org/x/text v0.16.0 // indirect - google.golang.org/protobuf v1.34.1 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 598f9ca..85a1bce 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ ariga.io/atlas v0.19.1-0.20240203083654-5948b60a8e43 h1:GwdJbXydHCYPedeeLt4x/lrl ariga.io/atlas v0.19.1-0.20240203083654-5948b60a8e43/go.mod h1:uj3pm+hUTVN/X5yfdBexHlZv+1Xu5u5ZbZx7+CDavNU= entgo.io/ent v0.13.1 h1:uD8QwN1h6SNphdCCzmkMN3feSUzNnVvV/WIkHKMbzOE= entgo.io/ent v0.13.1/go.mod h1:qCEmo+biw3ccBn9OyL4ZK5dfpwg++l1Gxwac5B1206A= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/adrg/strutil v0.3.1 h1:OLvSS7CSJO8lBii4YmBt8jiK9QOtB9CzCzwl4Ic/Fz4= @@ -10,6 +12,8 @@ github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tj github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= +github.com/blinkbean/dingtalk v1.1.3 h1:MbidFZYom7DTFHD/YIs+eaI7kRy52kmWE/sy0xjo6E4= +github.com/blinkbean/dingtalk v1.1.3/go.mod h1:9BaLuGSBqY3vT5hstValh48DbsKO7vaHaJnG9pXwbto= github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= @@ -48,6 +52,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= @@ -60,8 +66,10 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gregdel/pushover v1.3.1 h1:4bMLITOZ15+Zpi6qqoGqOPuVHCwSUvMCgVnN5Xhilfo= +github.com/gregdel/pushover v1.3.1/go.mod h1:EcaO66Nn1StkpEm1iKtBTV3d2A16SoMsVER1PthX7to= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -108,6 +116,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= +github.com/nikoksr/notify v1.0.0 h1:qe9/6FRsWdxBgQgWcpvQ0sv8LRGJZDpRB4TkL2uNdO8= +github.com/nikoksr/notify v1.0.0/go.mod h1:hPaaDt30d6LAA7/5nb0e48Bp/MctDfycCSs8VEgN29I= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= @@ -142,6 +152,7 @@ github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -153,6 +164,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= +github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= @@ -163,8 +176,6 @@ github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA= github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= @@ -173,34 +184,34 @@ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUu golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= @@ -209,6 +220,8 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/notifier/clients.go b/pkg/notifier/clients.go new file mode 100644 index 0000000..019be1a --- /dev/null +++ b/pkg/notifier/clients.go @@ -0,0 +1,70 @@ +package notifier + +import ( + "encoding/json" + + "github.com/nikoksr/notify/service/dingding" + po "github.com/nikoksr/notify/service/pushover" + "github.com/nikoksr/notify/service/telegram" + "github.com/pkg/errors" +) + +type PushoverConfig struct { + UserKey string `json:"user_key"` + GroupKey string `json:"group_key"` + AppToken string `json:"app_token"` +} + +func NewPushoverClient(s string) (NotificationClient, error) { + var cfg PushoverConfig + if err := json.Unmarshal([]byte(s), &cfg); err != nil { + return nil, errors.Wrap(err, "json") + } + + c := po.New(cfg.AppToken) + if cfg.UserKey != "" { + c.AddReceivers(cfg.UserKey) + } + if cfg.GroupKey != "" { + c.AddReceivers(cfg.GroupKey) + } + + return &Notifier{service: c}, nil +} + +type DingTalkConfig struct { + Token string `json:"token"` + Secret string `json:"secret"` +} + +func NewDingTalkClient(s string) (NotificationClient, error) { + var cfg DingTalkConfig + if err := json.Unmarshal([]byte(s), &cfg); err != nil { + return nil, errors.Wrap(err, "json") + } + + svc := dingding.New(&dingding.Config{ + Token: cfg.Token, + Secret: cfg.Secret, + }) + return &Notifier{service: svc}, nil +} + +type TelegramConfig struct { + Token string `json:"token"` + ChatID int64 `json:"chat_id"` +} + +func NewTelegramClient(s string) (NotificationClient, error) { + var cfg TelegramConfig + if err := json.Unmarshal([]byte(s), &cfg); err != nil { + return nil, errors.Wrap(err, "json") + } + + svc, err := telegram.New(cfg.Token) + if err != nil { + panic(err) + } + svc.AddReceivers(cfg.ChatID) + return &Notifier{service: svc}, nil +} diff --git a/pkg/notifier/doc.go b/pkg/notifier/doc.go new file mode 100644 index 0000000..e64d721 --- /dev/null +++ b/pkg/notifier/doc.go @@ -0,0 +1,36 @@ +package notifier + +import ( + "context" + "polaris/pkg/utils" + + "github.com/nikoksr/notify" +) + +type HandlerFunc func(string) (NotificationClient, error) + +type NotificationClient interface { + SendMsg(msg string) error +} + +type Notifier struct { + service notify.Notifier +} + +func (s *Notifier) SendMsg(msg string) error { + notifier := notify.New() + notifier.UseServices(s.service) + return notifier.Send(context.TODO(), "polaris", msg) +} + +var handler = utils.Map[string, HandlerFunc]{} + +func init() { + handler.Store("pushover", NewPushoverClient) + handler.Store("dingtalk", NewDingTalkClient) + handler.Store("telegram", NewTelegramClient) +} + +func Gethandler(name string) (HandlerFunc, bool) { + return handler.Load(name) +} diff --git a/pkg/notifier/message/message.go b/pkg/notifier/message/message.go new file mode 100644 index 0000000..c8cc322 --- /dev/null +++ b/pkg/notifier/message/message.go @@ -0,0 +1,8 @@ +package message + +const ( + BeginDownload = "开始下载:%s" + DownloadComplete = "下载完成:%s" + ProcessingComplete = "文件处理完成:%s" + ProcessingFailed = "文件处理失败:%s" +) \ No newline at end of file diff --git a/pkg/utils/map.go b/pkg/utils/map.go new file mode 100644 index 0000000..9ef051f --- /dev/null +++ b/pkg/utils/map.go @@ -0,0 +1,31 @@ +package utils + +import "sync" + +type Map[K comparable, V any] struct { + m sync.Map +} + +func (m *Map[K, V]) Delete(key K) { m.m.Delete(key) } +func (m *Map[K, V]) Load(key K) (value V, ok bool) { + v, ok := m.m.Load(key) + if !ok { + return value, ok + } + return v.(V), ok +} +func (m *Map[K, V]) LoadAndDelete(key K) (value V, loaded bool) { + v, loaded := m.m.LoadAndDelete(key) + if !loaded { + return value, loaded + } + return v.(V), loaded +} +func (m *Map[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) { + a, loaded := m.m.LoadOrStore(key, value) + return a.(V), loaded +} +func (m *Map[K, V]) Range(f func(key K, value V) bool) { + m.m.Range(func(key, value any) bool { return f(key.(K), value.(V)) }) +} +func (m *Map[K, V]) Store(key K, value V) { m.m.Store(key, value) } diff --git a/server/notify_client.go b/server/notify_client.go new file mode 100644 index 0000000..c6aa468 --- /dev/null +++ b/server/notify_client.go @@ -0,0 +1,75 @@ +package server + +import ( + "polaris/ent" + "polaris/log" + "polaris/pkg/notifier" + "strconv" + + "github.com/gin-gonic/gin" + "github.com/pkg/errors" +) + +func (s *Server) GetAllNotificationClients(c *gin.Context) (interface{}, error) { + return s.db.GetAllNotificationClients() +} + +func (s *Server) GetNotificationClient(c *gin.Context) (interface{}, error) { + ids := c.Param("id") + id, err := strconv.Atoi(ids) + if err != nil { + return nil, errors.Wrap(err, "convert") + } + return s.db.GetNotificationClient(id) +} + +func (s *Server) DeleteNotificationClient(c *gin.Context) (interface{}, error) { + ids := c.Param("id") + id, err := strconv.Atoi(ids) + if err != nil { + return nil, errors.Wrap(err, "convert") + } + return nil, s.db.DeleteNotificationClient(id) +} + +func (s *Server) AddNotificationClient(c *gin.Context) (interface{}, error) { + var in ent.NotificationClient + if err := c.ShouldBindJSON(&in); err != nil { + return nil, errors.Wrap(err, "json") + } + + err := s.db.AddNotificationClient(in.Name, in.Service, in.Settings, in.Enabled) + if err != nil { + return nil, errors.Wrap(err, "save db") + } + return nil, nil +} + +func (s *Server) sendMsg(msg string) { + clients, err := s.db.GetAllNotificationClients2() + if err != nil { + log.Errorf("query notification clients: %v", err) + return + } + for _, cl := range clients { + if !cl.Enabled { + continue + } + handler, ok := notifier.Gethandler(cl.Service) + if !ok { + log.Errorf("no notification implementation of service %s", cl.Service) + continue + } + noCl, err := handler(cl.Settings) + if err != nil { + log.Errorf("handle setting for name %s error: %v", cl.Name, err) + continue + } + err = noCl.SendMsg(msg) + if err != nil { + log.Errorf("send message error: %v", err) + continue + } + log.Debugf("send message to %s success, msg is %s", cl.Name, msg) + } +} \ No newline at end of file diff --git a/server/resources.go b/server/resources.go index 22eb45b..0d6b103 100644 --- a/server/resources.go +++ b/server/resources.go @@ -7,6 +7,7 @@ import ( "polaris/ent/history" "polaris/ent/media" "polaris/log" + "polaris/pkg/notifier/message" "polaris/pkg/torznab" "polaris/pkg/utils" "polaris/server/core" @@ -67,6 +68,8 @@ func (s *Server) downloadSeasonPackage(r1 torznab.Result, seriesId, seasonNum in s.db.SetSeasonAllEpisodeStatus(seriesId, seasonNum, episode.StatusDownloading) s.tasks[history.ID] = &Task{Torrent: torrent} + + s.sendMsg(fmt.Sprintf(message.BeginDownload, r1.Name)) return &r1.Name, nil } @@ -112,6 +115,7 @@ func (s *Server) downloadEpisodeTorrent(r1 torznab.Result, seriesId, seasonNum, s.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading) s.tasks[history.ID] = &Task{Torrent: torrent} + s.sendMsg(fmt.Sprintf(message.BeginDownload, r1.Name)) log.Infof("success add %s to download task", r1.Name) return &r1.Name, nil @@ -293,7 +297,8 @@ func (s *Server) DownloadTorrent(c *gin.Context) (interface{}, error) { s.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading) }() - + + s.sendMsg(fmt.Sprintf(message.BeginDownload, in.Name)) log.Infof("success add %s to download task", in.Name) return in.Name, nil diff --git a/server/scheduler.go b/server/scheduler.go index 762d07f..23adf25 100644 --- a/server/scheduler.go +++ b/server/scheduler.go @@ -1,6 +1,7 @@ package server import ( + "fmt" "path/filepath" "polaris/ent" "polaris/ent/episode" @@ -9,6 +10,7 @@ import ( storage1 "polaris/ent/storage" "polaris/log" "polaris/pkg" + "polaris/pkg/notifier/message" "polaris/pkg/storage" "polaris/pkg/utils" "polaris/server/core" @@ -44,6 +46,7 @@ func (s *Server) checkTasks() { log.Infof("task (%s) percentage done: %d%%", t.Name(), t.Progress()) if t.Progress() == 100 { log.Infof("task is done: %v", t.Name()) + s.sendMsg(fmt.Sprintf(message.DownloadComplete, t.Name())) go func() { if err := s.moveCompletedTask(id); err != nil { log.Infof("post tasks for id %v fail: %v", id, err) @@ -76,7 +79,7 @@ func (s *Server) moveCompletedTask(id int) (err1 error) { } else { s.db.SetSeasonAllEpisodeStatus(r.MediaID, seasonNum, episode.StatusMissing) } - + s.sendMsg(fmt.Sprintf(message.ProcessingFailed, err)) } else { delete(s.tasks, r.ID) s.db.SetHistoryStatus(r.ID, history.StatusSuccess) @@ -85,6 +88,7 @@ func (s *Server) moveCompletedTask(id int) (err1 error) { } else { s.db.SetSeasonAllEpisodeStatus(r.MediaID, seasonNum, episode.StatusDownloaded) } + s.sendMsg(fmt.Sprintf(message.ProcessingComplete, torrent.Name())) torrent.Remove() } @@ -229,9 +233,9 @@ func (s *Server) downloadTvSeries() { } if series.CreatedAt.Sub(t) > 24*time.Hour { //剧集在加入watchlist之前,不去下载 continue - } + } } - + if ep.Status != episode.StatusMissing { //已经下载的不去下载 continue } @@ -252,7 +256,7 @@ func (s *Server) downloadMovie() { allSeries := s.db.GetMediaWatchlist(media.MediaTypeMovie) for _, series := range allSeries { - detail := s.db.GetMediaDetails(series.ID) + detail := s.db.GetMediaDetails(series.ID) if len(detail.Episodes) == 0 { log.Errorf("no related dummy episode: %v", detail.NameEn) continue @@ -317,7 +321,7 @@ func (s *Server) checkAllSeriesNewSeason() { } } -func (s *Server) checkSeiesNewSeason(media *ent.Media) error{ +func (s *Server) checkSeiesNewSeason(media *ent.Media) error { d, err := s.MustTMDB().GetTvDetails(media.TmdbID, s.language) if err != nil { return errors.Wrap(err, "tmdb") @@ -327,29 +331,29 @@ func (s *Server) checkSeiesNewSeason(media *ent.Media) error{ if err != nil { return errors.Wrap(err, "tmdb season") } - + for _, ep := range seasonDetail.Episodes { epDb, err := s.db.GetEpisode(media.ID, ep.SeasonNumber, ep.EpisodeNumber) if err != nil { if ent.IsNotFound(err) { log.Infof("add new episode: %+v", ep) episode := &ent.Episode{ - MediaID: media.ID, - SeasonNumber: ep.SeasonNumber, + MediaID: media.ID, + SeasonNumber: ep.SeasonNumber, EpisodeNumber: ep.EpisodeNumber, - Title: ep.Name, - Overview: ep.Overview, - AirDate: ep.AirDate, - Status: episode.StatusMissing, + Title: ep.Name, + Overview: ep.Overview, + AirDate: ep.AirDate, + Status: episode.StatusMissing, } s.db.SaveEposideDetail2(episode) } - } else {//update episode + } else { //update episode if ep.Name != epDb.Title || ep.Overview != epDb.Overview || ep.AirDate != epDb.AirDate { log.Infof("update new episode: %+v", ep) - s.db.UpdateEpiode2(epDb.ID, ep.Name, ep.Overview, ep.AirDate) + s.db.UpdateEpiode2(epDb.ID, ep.Name, ep.Overview, ep.AirDate) } } } return nil -} \ No newline at end of file +} diff --git a/server/server.go b/server/server.go index 92f2b0c..d5c50bd 100644 --- a/server/server.go +++ b/server/server.go @@ -115,6 +115,13 @@ func (s *Server) Serve() error { storage.POST("/", HttpHandler(s.AddStorage)) storage.DELETE("/:id", HttpHandler(s.DeleteStorage)) } + notifier := api.Group("/notifier") + { + notifier.GET("/all", HttpHandler(s.GetAllNotificationClients)) + notifier.GET("/id/:id", HttpHandler(s.GetNotificationClient)) + notifier.DELETE("/id/:id", HttpHandler(s.DeleteNotificationClient)) + notifier.POST("/add", HttpHandler(s.AddNotificationClient)) + } s.language = s.db.GetLanguage() return s.r.Run(":8080") diff --git a/ui/lib/providers/APIs.dart b/ui/lib/providers/APIs.dart index da7503e..da0c0cd 100644 --- a/ui/lib/providers/APIs.dart +++ b/ui/lib/providers/APIs.dart @@ -33,6 +33,10 @@ class APIs { static final logFilesUrl = "$_baseUrl/api/v1/setting/logfiles"; static final aboutUrl = "$_baseUrl/api/v1/setting/about"; + static final notifierAllUrl = "$_baseUrl/api/v1/notifier/all"; + static final notifierDeleteUrl = "$_baseUrl/api/v1/notifier/id/"; + static final notifierAddUrl = "$_baseUrl/api/v1/notifier/add/"; + static final tmdbImgBaseUrl = "$_baseUrl/api/v1/posters"; static const tmdbApiKey = "tmdb_api_key"; diff --git a/ui/lib/providers/notifier.dart b/ui/lib/providers/notifier.dart new file mode 100644 index 0000000..0378efc --- /dev/null +++ b/ui/lib/providers/notifier.dart @@ -0,0 +1,75 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:ui/providers/APIs.dart'; +import 'package:ui/providers/server_response.dart'; + +final notifiersDataProvider = + AsyncNotifierProvider.autoDispose>( + NotifiersData.new); + +class NotifierData { + int? id; + String? name; + String? service; + Map? settings; + bool? enabled; + + NotifierData({this.id, this.name, this.service, this.enabled, this.settings}); + + factory NotifierData.fromJson(Map json) { + return NotifierData( + id: json["id"], + name: json["name"], + service: json["service"], + enabled: json["enabled"] ?? true, + settings: json["settings"]); + } + + Map toJson() { + final data = {}; + data["name"] = name; + data["service"] = service; + data["enabled"] = enabled; + + data["settings"] = jsonEncode(settings); + return data; + } +} + +class NotifiersData extends AutoDisposeAsyncNotifier> { + @override + FutureOr> build() async { + final dio = APIs.getDio(); + final resp = await dio.get(APIs.notifierAllUrl); + final sp = ServerResponse.fromJson(resp.data); + if (sp.code != 0) { + throw sp.message; + } + + return sp.data == null + ? List.empty() + : (sp.data as List).map((e) => NotifierData.fromJson(e)).toList(); + } + + Future delete(int id) async { + final dio = APIs.getDio(); + final resp = await dio.delete(APIs.notifierDeleteUrl + id.toString()); + final sp = ServerResponse.fromJson(resp.data); + if (sp.code != 0) { + throw sp.message; + } + ref.invalidateSelf(); + } + + Future add(NotifierData n) async { + final dio = APIs.getDio(); + final resp = await dio.post(APIs.notifierAddUrl, data: n.toJson()); + final sp = ServerResponse.fromJson(resp.data); + if (sp.code != 0) { + throw sp.message; + } + ref.invalidateSelf(); + } +} diff --git a/ui/lib/settings.dart b/ui/lib/settings.dart index c31ed65..ae4144e 100644 --- a/ui/lib/settings.dart +++ b/ui/lib/settings.dart @@ -3,6 +3,7 @@ import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:quiver/strings.dart'; import 'package:ui/providers/login.dart'; +import 'package:ui/providers/notifier.dart'; import 'package:ui/providers/settings.dart'; import 'package:ui/utils.dart'; import 'package:ui/widgets/progress_indicator.dart'; @@ -52,14 +53,18 @@ class _SystemSettingsPageState extends ConsumerState { FormBuilderTextField( name: "download_dir", decoration: Commons.requiredTextFieldStyle( - text: "下载路径", icon: const Icon(Icons.folder), helperText: "媒体文件临时下载路径,非最终存储路径"), + text: "下载路径", + icon: const Icon(Icons.folder), + helperText: "媒体文件临时下载路径,非最终存储路径"), // validator: FormBuilderValidators.required(), ), FormBuilderTextField( name: "proxy", decoration: const InputDecoration( - labelText: "代理地址", icon: Icon(Icons.folder), helperText: "后台联网代理地址,留空表示不启用代理"), + labelText: "代理地址", + icon: Icon(Icons.folder), + helperText: "后台联网代理地址,留空表示不启用代理"), ), SizedBox( width: 300, @@ -246,40 +251,137 @@ class _SystemSettingsPageState extends ConsumerState { expandedAlignment: Alignment.centerLeft, childrenPadding: const EdgeInsets.fromLTRB(20, 0, 20, 0), initiallyExpanded: true, - title: const Text("常规设置"), + title: const Text("常规"), children: [tmdbSetting], ), ExpansionTile( expandedAlignment: Alignment.centerLeft, childrenPadding: const EdgeInsets.fromLTRB(20, 0, 20, 0), initiallyExpanded: false, - title: const Text("索引器设置"), + title: const Text("索引器"), children: [indexerSetting], ), ExpansionTile( expandedAlignment: Alignment.centerLeft, childrenPadding: const EdgeInsets.fromLTRB(20, 0, 20, 0), initiallyExpanded: false, - title: const Text("下载器设置"), + title: const Text("下载器"), children: [downloadSetting], ), ExpansionTile( expandedAlignment: Alignment.centerLeft, childrenPadding: const EdgeInsets.fromLTRB(20, 0, 50, 0), initiallyExpanded: false, - title: const Text("存储设置"), + title: const Text("存储"), children: [storageSetting], ), + ExpansionTile( + expandedAlignment: Alignment.centerLeft, + childrenPadding: const EdgeInsets.fromLTRB(20, 0, 50, 0), + initiallyExpanded: false, + title: const Text("通知客户端"), + children: [notifers()], + ), ExpansionTile( childrenPadding: const EdgeInsets.fromLTRB(20, 0, 20, 0), initiallyExpanded: false, - title: const Text("认证设置"), + title: const Text("认证"), children: [authSetting], ), ], ); } + Widget notifers() { + final notifierData = ref.watch(notifiersDataProvider); + return notifierData.when( + data: (v) => Wrap( + children: List.generate(v.length + 1, (i) { + if (i < v.length) { + final client = v[i]; + return SettingsCard( + child: Text("${client.name!} (${client.service})"), + onTap: () => showNotifierDetails(client), + ); + } + return SettingsCard( + onTap: () => showNotifierDetails(NotifierData()), + child: const Icon(Icons.add)); + }), + ), + error: (err, trace) => Text("$err"), + loading: () => const MyProgressIndicator()); + } + + Future showNotifierDetails(NotifierData notifier) { + final _formKey = GlobalKey(); + + var body = FormBuilder( + key: _formKey, + initialValue: { + "name": notifier.name, + "service": notifier.service, + "enabled": notifier.enabled ?? true, + "app_token": + notifier.settings != null ? notifier.settings!["app_token"] : "", + "user_key": + notifier.settings != null ? notifier.settings!["user_key"] : "", + }, + child: Column( + children: [ + FormBuilderDropdown( + name: "service", + decoration: const InputDecoration(labelText: "类型"), + items: const [ + DropdownMenuItem(value: "pushover", child: Text("Pushover")), + ], + ), + FormBuilderTextField( + name: "name", + decoration: Commons.requiredTextFieldStyle(text: "名称"), + autovalidateMode: AutovalidateMode.onUserInteraction, + validator: FormBuilderValidators.required(), + ), + FormBuilderTextField( + name: "app_token", + decoration: Commons.requiredTextFieldStyle(text: "APP密钥"), + autovalidateMode: AutovalidateMode.onUserInteraction, + validator: FormBuilderValidators.required(), + ), + FormBuilderTextField( + name: "user_key", + decoration: Commons.requiredTextFieldStyle(text: "用户密钥"), + autovalidateMode: AutovalidateMode.onUserInteraction, + validator: FormBuilderValidators.required(), + ), + FormBuilderSwitch(name: "enabled", title: const Text("启用")) + ], + ), + ); + onDelete() async { + return ref.read(notifiersDataProvider.notifier).delete(notifier.id!); + } + + onSubmit() async { + if (_formKey.currentState!.saveAndValidate()) { + var values = _formKey.currentState!.value; + return ref.read(notifiersDataProvider.notifier).add(NotifierData( + name: values["name"], + service: values["service"], + enabled: values["enabled"], + settings: { + "app_token": values["app_token"], + "user_key": values["user_key"] + })); + } else { + throw "validation_error"; + } + } + + return showSettingDialog( + "通知客户端", notifier.id != null, body, onSubmit, onDelete); + } + Future showIndexerDetails(Indexer indexer) { final _formKey = GlobalKey(); @@ -564,7 +666,9 @@ class _SystemSettingsPageState extends ConsumerState { "user": values["user"], "password": values["password"], "change_file_hash": - (values["change_file_hash"]??false) as bool ? "true" : "false" + (values["change_file_hash"] ?? false) as bool + ? "true" + : "false" }, )); } else {