diff --git a/db/const.go b/db/const.go index 02f346d..15ba9f7 100644 --- a/db/const.go +++ b/db/const.go @@ -3,4 +3,10 @@ package db const ( SettingTmdbApiKey = "tmdb_api_key" SettingLanguage = "language" + SettingJacketUrl = "jacket_url" + SettingJacketApiKey = "jacket_api_key" +) + +const ( + IndexerTorznabImpl = "torznab" ) \ No newline at end of file diff --git a/db/db.go b/db/db.go index d2e0e9a..6e1d8c6 100644 --- a/db/db.go +++ b/db/db.go @@ -2,10 +2,14 @@ package db import ( "context" + "encoding/json" "polaris/ent" + "polaris/ent/downloadclients" + "polaris/ent/indexers" "polaris/ent/settings" "polaris/log" + "entgo.io/ent/dialect" tmdb "github.com/cyruzin/golang-tmdb" _ "github.com/mattn/go-sqlite3" "github.com/pkg/errors" @@ -16,7 +20,7 @@ type Client struct { } func Open() (*Client, error) { - client, err := ent.Open("sqlite3", "file:polaris.db?cache=shared&_fk=1") + client, err := ent.Open(dialect.SQLite, "file:polaris.db?cache=shared&_fk=1") if err != nil { return nil, errors.Wrap(err, "failed opening connection to sqlite") } @@ -61,11 +65,11 @@ func (c *Client) GetLanguage() string { func (c *Client) AddWatchlist(path string, detail *tmdb.TVDetails) error { _, err := c.ent.Series.Create(). - SetTmdbID(int(detail.ID)). - SetPath(path). - SetOverview(detail.Overview). - SetTitle(detail.Name). - SetOriginalName(detail.OriginalName). + SetTmdbID(int(detail.ID)). + SetPath(path). + SetOverview(detail.Overview). + SetTitle(detail.Name). + SetOriginalName(detail.OriginalName). Save(context.TODO()) return err } @@ -78,3 +82,64 @@ func (c *Client) GetWatchlist() []*ent.Series { } return list } + +func (c *Client) SaveEposideDetail(tmdbId int, d *tmdb.TVEpisodeDetails) error { + _, err := c.ent.Epidodes.Create(). + SetAirDate(d.AirDate). + SetSeasonNumber(d.SeasonNumber). + SetEpisodeNumber(d.EpisodeNumber). + SetSeriesID(tmdbId). + SetOverview(d.Overview). + SetTitle(d.Name).Save(context.TODO()) + + return err +} + +type TorznabSetting struct { + URL string `json:"url"` + ApiKey string `json:"api_key"` +} + +func (c *Client) SaveTorznabInfo(name string, setting TorznabSetting) error { + data, err := json.Marshal(setting) + if err != nil { + return errors.Wrap(err, "marshal json") + } + _, err = c.ent.Indexers.Create(). + SetName(name).SetImplementation(IndexerTorznabImpl).SetPriority(1).SetSettings(string(data)).Save(context.TODO()) + if err != nil { + return errors.Wrap(err, "save db") + } + return nil +} + +func (c *Client) GetAllTorznabInfo() map[string]TorznabSetting { + res := c.ent.Indexers.Query().Where(indexers.Implementation(IndexerTorznabImpl)).AllX(context.TODO()) + var m = make(map[string]TorznabSetting, len(res)) + for _, r := range res { + var ss TorznabSetting + err := json.Unmarshal([]byte(r.Settings), &ss) + if err != nil { + log.Errorf("unmarshal torznab %s error: %v", r.Name, err) + continue + } + m[r.Name] = ss + } + return m +} + +func (c *Client) SaveTransmission(name, url, user, password string) error { + _, err := c.ent.DownloadClients.Create().SetEnable(true).SetImplementation("transmission"). + SetName(name).SetURL(url).SetUser(user).SetPassword(password).Save(context.TODO()) + + return err +} + +func (c *Client) GetTransmission() *ent.DownloadClients { + dc, err := c.ent.DownloadClients.Query().Where(downloadclients.Implementation("transmission")).First(context.TODO()) + if err != nil { + log.Errorf("no transmission client found: %v", err) + return nil + } + return dc +} diff --git a/ent/client.go b/ent/client.go index 426958e..e5b16ed 100644 --- a/ent/client.go +++ b/ent/client.go @@ -13,6 +13,7 @@ import ( "polaris/ent/downloadclients" "polaris/ent/epidodes" + "polaris/ent/history" "polaris/ent/indexers" "polaris/ent/series" "polaris/ent/settings" @@ -31,6 +32,8 @@ type Client struct { DownloadClients *DownloadClientsClient // Epidodes is the client for interacting with the Epidodes builders. Epidodes *EpidodesClient + // History is the client for interacting with the History builders. + History *HistoryClient // Indexers is the client for interacting with the Indexers builders. Indexers *IndexersClient // Series is the client for interacting with the Series builders. @@ -50,6 +53,7 @@ func (c *Client) init() { c.Schema = migrate.NewSchema(c.driver) c.DownloadClients = NewDownloadClientsClient(c.config) c.Epidodes = NewEpidodesClient(c.config) + c.History = NewHistoryClient(c.config) c.Indexers = NewIndexersClient(c.config) c.Series = NewSeriesClient(c.config) c.Settings = NewSettingsClient(c.config) @@ -147,6 +151,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { config: cfg, DownloadClients: NewDownloadClientsClient(cfg), Epidodes: NewEpidodesClient(cfg), + History: NewHistoryClient(cfg), Indexers: NewIndexersClient(cfg), Series: NewSeriesClient(cfg), Settings: NewSettingsClient(cfg), @@ -171,6 +176,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) config: cfg, DownloadClients: NewDownloadClientsClient(cfg), Epidodes: NewEpidodesClient(cfg), + History: NewHistoryClient(cfg), Indexers: NewIndexersClient(cfg), Series: NewSeriesClient(cfg), Settings: NewSettingsClient(cfg), @@ -202,21 +208,21 @@ func (c *Client) Close() error { // Use adds the mutation hooks to all the entity clients. // In order to add hooks to a specific client, call: `client.Node.Use(...)`. func (c *Client) Use(hooks ...Hook) { - c.DownloadClients.Use(hooks...) - c.Epidodes.Use(hooks...) - c.Indexers.Use(hooks...) - c.Series.Use(hooks...) - c.Settings.Use(hooks...) + for _, n := range []interface{ Use(...Hook) }{ + c.DownloadClients, c.Epidodes, c.History, c.Indexers, c.Series, c.Settings, + } { + n.Use(hooks...) + } } // Intercept adds the query interceptors to all the entity clients. // In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`. func (c *Client) Intercept(interceptors ...Interceptor) { - c.DownloadClients.Intercept(interceptors...) - c.Epidodes.Intercept(interceptors...) - c.Indexers.Intercept(interceptors...) - c.Series.Intercept(interceptors...) - c.Settings.Intercept(interceptors...) + for _, n := range []interface{ Intercept(...Interceptor) }{ + c.DownloadClients, c.Epidodes, c.History, c.Indexers, c.Series, c.Settings, + } { + n.Intercept(interceptors...) + } } // Mutate implements the ent.Mutator interface. @@ -226,6 +232,8 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { return c.DownloadClients.mutate(ctx, m) case *EpidodesMutation: return c.Epidodes.mutate(ctx, m) + case *HistoryMutation: + return c.History.mutate(ctx, m) case *IndexersMutation: return c.Indexers.mutate(ctx, m) case *SeriesMutation: @@ -503,6 +511,139 @@ func (c *EpidodesClient) mutate(ctx context.Context, m *EpidodesMutation) (Value } } +// HistoryClient is a client for the History schema. +type HistoryClient struct { + config +} + +// NewHistoryClient returns a client for the History from the given config. +func NewHistoryClient(c config) *HistoryClient { + return &HistoryClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `history.Hooks(f(g(h())))`. +func (c *HistoryClient) Use(hooks ...Hook) { + c.hooks.History = append(c.hooks.History, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `history.Intercept(f(g(h())))`. +func (c *HistoryClient) Intercept(interceptors ...Interceptor) { + c.inters.History = append(c.inters.History, interceptors...) +} + +// Create returns a builder for creating a History entity. +func (c *HistoryClient) Create() *HistoryCreate { + mutation := newHistoryMutation(c.config, OpCreate) + return &HistoryCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of History entities. +func (c *HistoryClient) CreateBulk(builders ...*HistoryCreate) *HistoryCreateBulk { + return &HistoryCreateBulk{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 *HistoryClient) MapCreateBulk(slice any, setFunc func(*HistoryCreate, int)) *HistoryCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &HistoryCreateBulk{err: fmt.Errorf("calling to HistoryClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*HistoryCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &HistoryCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for History. +func (c *HistoryClient) Update() *HistoryUpdate { + mutation := newHistoryMutation(c.config, OpUpdate) + return &HistoryUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *HistoryClient) UpdateOne(h *History) *HistoryUpdateOne { + mutation := newHistoryMutation(c.config, OpUpdateOne, withHistory(h)) + return &HistoryUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *HistoryClient) UpdateOneID(id int) *HistoryUpdateOne { + mutation := newHistoryMutation(c.config, OpUpdateOne, withHistoryID(id)) + return &HistoryUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for History. +func (c *HistoryClient) Delete() *HistoryDelete { + mutation := newHistoryMutation(c.config, OpDelete) + return &HistoryDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *HistoryClient) DeleteOne(h *History) *HistoryDeleteOne { + return c.DeleteOneID(h.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *HistoryClient) DeleteOneID(id int) *HistoryDeleteOne { + builder := c.Delete().Where(history.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &HistoryDeleteOne{builder} +} + +// Query returns a query builder for History. +func (c *HistoryClient) Query() *HistoryQuery { + return &HistoryQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeHistory}, + inters: c.Interceptors(), + } +} + +// Get returns a History entity by its id. +func (c *HistoryClient) Get(ctx context.Context, id int) (*History, error) { + return c.Query().Where(history.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *HistoryClient) GetX(ctx context.Context, id int) *History { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// Hooks returns the client hooks. +func (c *HistoryClient) Hooks() []Hook { + return c.hooks.History +} + +// Interceptors returns the client interceptors. +func (c *HistoryClient) Interceptors() []Interceptor { + return c.inters.History +} + +func (c *HistoryClient) mutate(ctx context.Context, m *HistoryMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&HistoryCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&HistoryUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&HistoryUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&HistoryDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown History mutation op: %q", m.Op()) + } +} + // IndexersClient is a client for the Indexers schema. type IndexersClient struct { config @@ -905,9 +1046,9 @@ func (c *SettingsClient) mutate(ctx context.Context, m *SettingsMutation) (Value // hooks and interceptors per client, for fast access. type ( hooks struct { - DownloadClients, Epidodes, Indexers, Series, Settings []ent.Hook + DownloadClients, Epidodes, History, Indexers, Series, Settings []ent.Hook } inters struct { - DownloadClients, Epidodes, Indexers, Series, Settings []ent.Interceptor + DownloadClients, Epidodes, History, Indexers, Series, Settings []ent.Interceptor } ) diff --git a/ent/downloadclients.go b/ent/downloadclients.go index 41890aa..d60d6d5 100644 --- a/ent/downloadclients.go +++ b/ent/downloadclients.go @@ -22,6 +22,12 @@ type DownloadClients struct { Name string `json:"name,omitempty"` // Implementation holds the value of the "implementation" field. Implementation string `json:"implementation,omitempty"` + // URL holds the value of the "url" field. + URL string `json:"url,omitempty"` + // User holds the value of the "user" field. + User string `json:"user,omitempty"` + // Password holds the value of the "password" field. + Password string `json:"password,omitempty"` // Settings holds the value of the "settings" field. Settings string `json:"settings,omitempty"` // Priority holds the value of the "priority" field. @@ -44,7 +50,7 @@ func (*DownloadClients) scanValues(columns []string) ([]any, error) { values[i] = new(sql.NullBool) case downloadclients.FieldID: values[i] = new(sql.NullInt64) - case downloadclients.FieldName, downloadclients.FieldImplementation, downloadclients.FieldSettings, downloadclients.FieldPriority, downloadclients.FieldTags: + case downloadclients.FieldName, downloadclients.FieldImplementation, downloadclients.FieldURL, downloadclients.FieldUser, downloadclients.FieldPassword, downloadclients.FieldSettings, downloadclients.FieldPriority, downloadclients.FieldTags: values[i] = new(sql.NullString) default: values[i] = new(sql.UnknownType) @@ -85,6 +91,24 @@ func (dc *DownloadClients) assignValues(columns []string, values []any) error { } else if value.Valid { dc.Implementation = value.String } + case downloadclients.FieldURL: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field url", values[i]) + } else if value.Valid { + dc.URL = value.String + } + case downloadclients.FieldUser: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field user", values[i]) + } else if value.Valid { + dc.User = value.String + } + case downloadclients.FieldPassword: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field password", values[i]) + } else if value.Valid { + dc.Password = value.String + } case downloadclients.FieldSettings: if value, ok := values[i].(*sql.NullString); !ok { return fmt.Errorf("unexpected type %T for field settings", values[i]) @@ -160,6 +184,15 @@ func (dc *DownloadClients) String() string { builder.WriteString("implementation=") builder.WriteString(dc.Implementation) builder.WriteString(", ") + builder.WriteString("url=") + builder.WriteString(dc.URL) + builder.WriteString(", ") + builder.WriteString("user=") + builder.WriteString(dc.User) + builder.WriteString(", ") + builder.WriteString("password=") + builder.WriteString(dc.Password) + builder.WriteString(", ") builder.WriteString("settings=") builder.WriteString(dc.Settings) builder.WriteString(", ") diff --git a/ent/downloadclients/downloadclients.go b/ent/downloadclients/downloadclients.go index 82be9b7..f83c5ba 100644 --- a/ent/downloadclients/downloadclients.go +++ b/ent/downloadclients/downloadclients.go @@ -17,6 +17,12 @@ const ( FieldName = "name" // FieldImplementation holds the string denoting the implementation field in the database. FieldImplementation = "implementation" + // FieldURL holds the string denoting the url field in the database. + FieldURL = "url" + // FieldUser holds the string denoting the user field in the database. + FieldUser = "user" + // FieldPassword holds the string denoting the password field in the database. + FieldPassword = "password" // FieldSettings holds the string denoting the settings field in the database. FieldSettings = "settings" // FieldPriority holds the string denoting the priority field in the database. @@ -37,6 +43,9 @@ var Columns = []string{ FieldEnable, FieldName, FieldImplementation, + FieldURL, + FieldUser, + FieldPassword, FieldSettings, FieldPriority, FieldRemoveCompletedDownloads, @@ -54,6 +63,23 @@ func ValidColumn(column string) bool { return false } +var ( + // DefaultUser holds the default value on creation for the "user" field. + DefaultUser string + // DefaultPassword holds the default value on creation for the "password" field. + DefaultPassword string + // DefaultSettings holds the default value on creation for the "settings" field. + DefaultSettings string + // DefaultPriority holds the default value on creation for the "priority" field. + DefaultPriority string + // DefaultRemoveCompletedDownloads holds the default value on creation for the "remove_completed_downloads" field. + DefaultRemoveCompletedDownloads bool + // DefaultRemoveFailedDownloads holds the default value on creation for the "remove_failed_downloads" field. + DefaultRemoveFailedDownloads bool + // DefaultTags holds the default value on creation for the "tags" field. + DefaultTags string +) + // OrderOption defines the ordering options for the DownloadClients queries. type OrderOption func(*sql.Selector) @@ -77,6 +103,21 @@ func ByImplementation(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldImplementation, opts...).ToFunc() } +// ByURL orders the results by the url field. +func ByURL(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldURL, opts...).ToFunc() +} + +// ByUser orders the results by the user field. +func ByUser(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldUser, opts...).ToFunc() +} + +// ByPassword orders the results by the password field. +func ByPassword(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldPassword, opts...).ToFunc() +} + // BySettings orders the results by the settings field. func BySettings(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldSettings, opts...).ToFunc() diff --git a/ent/downloadclients/where.go b/ent/downloadclients/where.go index 16e0c40..38fa7f0 100644 --- a/ent/downloadclients/where.go +++ b/ent/downloadclients/where.go @@ -68,6 +68,21 @@ func Implementation(v string) predicate.DownloadClients { return predicate.DownloadClients(sql.FieldEQ(FieldImplementation, v)) } +// URL applies equality check predicate on the "url" field. It's identical to URLEQ. +func URL(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldEQ(FieldURL, v)) +} + +// User applies equality check predicate on the "user" field. It's identical to UserEQ. +func User(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldEQ(FieldUser, v)) +} + +// Password applies equality check predicate on the "password" field. It's identical to PasswordEQ. +func Password(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldEQ(FieldPassword, v)) +} + // Settings applies equality check predicate on the "settings" field. It's identical to SettingsEQ. func Settings(v string) predicate.DownloadClients { return predicate.DownloadClients(sql.FieldEQ(FieldSettings, v)) @@ -233,6 +248,201 @@ func ImplementationContainsFold(v string) predicate.DownloadClients { return predicate.DownloadClients(sql.FieldContainsFold(FieldImplementation, v)) } +// URLEQ applies the EQ predicate on the "url" field. +func URLEQ(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldEQ(FieldURL, v)) +} + +// URLNEQ applies the NEQ predicate on the "url" field. +func URLNEQ(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldNEQ(FieldURL, v)) +} + +// URLIn applies the In predicate on the "url" field. +func URLIn(vs ...string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldIn(FieldURL, vs...)) +} + +// URLNotIn applies the NotIn predicate on the "url" field. +func URLNotIn(vs ...string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldNotIn(FieldURL, vs...)) +} + +// URLGT applies the GT predicate on the "url" field. +func URLGT(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldGT(FieldURL, v)) +} + +// URLGTE applies the GTE predicate on the "url" field. +func URLGTE(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldGTE(FieldURL, v)) +} + +// URLLT applies the LT predicate on the "url" field. +func URLLT(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldLT(FieldURL, v)) +} + +// URLLTE applies the LTE predicate on the "url" field. +func URLLTE(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldLTE(FieldURL, v)) +} + +// URLContains applies the Contains predicate on the "url" field. +func URLContains(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldContains(FieldURL, v)) +} + +// URLHasPrefix applies the HasPrefix predicate on the "url" field. +func URLHasPrefix(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldHasPrefix(FieldURL, v)) +} + +// URLHasSuffix applies the HasSuffix predicate on the "url" field. +func URLHasSuffix(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldHasSuffix(FieldURL, v)) +} + +// URLEqualFold applies the EqualFold predicate on the "url" field. +func URLEqualFold(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldEqualFold(FieldURL, v)) +} + +// URLContainsFold applies the ContainsFold predicate on the "url" field. +func URLContainsFold(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldContainsFold(FieldURL, v)) +} + +// UserEQ applies the EQ predicate on the "user" field. +func UserEQ(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldEQ(FieldUser, v)) +} + +// UserNEQ applies the NEQ predicate on the "user" field. +func UserNEQ(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldNEQ(FieldUser, v)) +} + +// UserIn applies the In predicate on the "user" field. +func UserIn(vs ...string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldIn(FieldUser, vs...)) +} + +// UserNotIn applies the NotIn predicate on the "user" field. +func UserNotIn(vs ...string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldNotIn(FieldUser, vs...)) +} + +// UserGT applies the GT predicate on the "user" field. +func UserGT(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldGT(FieldUser, v)) +} + +// UserGTE applies the GTE predicate on the "user" field. +func UserGTE(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldGTE(FieldUser, v)) +} + +// UserLT applies the LT predicate on the "user" field. +func UserLT(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldLT(FieldUser, v)) +} + +// UserLTE applies the LTE predicate on the "user" field. +func UserLTE(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldLTE(FieldUser, v)) +} + +// UserContains applies the Contains predicate on the "user" field. +func UserContains(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldContains(FieldUser, v)) +} + +// UserHasPrefix applies the HasPrefix predicate on the "user" field. +func UserHasPrefix(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldHasPrefix(FieldUser, v)) +} + +// UserHasSuffix applies the HasSuffix predicate on the "user" field. +func UserHasSuffix(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldHasSuffix(FieldUser, v)) +} + +// UserEqualFold applies the EqualFold predicate on the "user" field. +func UserEqualFold(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldEqualFold(FieldUser, v)) +} + +// UserContainsFold applies the ContainsFold predicate on the "user" field. +func UserContainsFold(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldContainsFold(FieldUser, v)) +} + +// PasswordEQ applies the EQ predicate on the "password" field. +func PasswordEQ(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldEQ(FieldPassword, v)) +} + +// PasswordNEQ applies the NEQ predicate on the "password" field. +func PasswordNEQ(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldNEQ(FieldPassword, v)) +} + +// PasswordIn applies the In predicate on the "password" field. +func PasswordIn(vs ...string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldIn(FieldPassword, vs...)) +} + +// PasswordNotIn applies the NotIn predicate on the "password" field. +func PasswordNotIn(vs ...string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldNotIn(FieldPassword, vs...)) +} + +// PasswordGT applies the GT predicate on the "password" field. +func PasswordGT(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldGT(FieldPassword, v)) +} + +// PasswordGTE applies the GTE predicate on the "password" field. +func PasswordGTE(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldGTE(FieldPassword, v)) +} + +// PasswordLT applies the LT predicate on the "password" field. +func PasswordLT(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldLT(FieldPassword, v)) +} + +// PasswordLTE applies the LTE predicate on the "password" field. +func PasswordLTE(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldLTE(FieldPassword, v)) +} + +// PasswordContains applies the Contains predicate on the "password" field. +func PasswordContains(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldContains(FieldPassword, v)) +} + +// PasswordHasPrefix applies the HasPrefix predicate on the "password" field. +func PasswordHasPrefix(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldHasPrefix(FieldPassword, v)) +} + +// PasswordHasSuffix applies the HasSuffix predicate on the "password" field. +func PasswordHasSuffix(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldHasSuffix(FieldPassword, v)) +} + +// PasswordEqualFold applies the EqualFold predicate on the "password" field. +func PasswordEqualFold(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldEqualFold(FieldPassword, v)) +} + +// PasswordContainsFold applies the ContainsFold predicate on the "password" field. +func PasswordContainsFold(v string) predicate.DownloadClients { + return predicate.DownloadClients(sql.FieldContainsFold(FieldPassword, v)) +} + // SettingsEQ applies the EQ predicate on the "settings" field. func SettingsEQ(v string) predicate.DownloadClients { return predicate.DownloadClients(sql.FieldEQ(FieldSettings, v)) diff --git a/ent/downloadclients_create.go b/ent/downloadclients_create.go index 1aa4f08..41dd099 100644 --- a/ent/downloadclients_create.go +++ b/ent/downloadclients_create.go @@ -37,36 +37,110 @@ func (dcc *DownloadClientsCreate) SetImplementation(s string) *DownloadClientsCr return dcc } +// SetURL sets the "url" field. +func (dcc *DownloadClientsCreate) SetURL(s string) *DownloadClientsCreate { + dcc.mutation.SetURL(s) + return dcc +} + +// SetUser sets the "user" field. +func (dcc *DownloadClientsCreate) SetUser(s string) *DownloadClientsCreate { + dcc.mutation.SetUser(s) + return dcc +} + +// SetNillableUser sets the "user" field if the given value is not nil. +func (dcc *DownloadClientsCreate) SetNillableUser(s *string) *DownloadClientsCreate { + if s != nil { + dcc.SetUser(*s) + } + return dcc +} + +// SetPassword sets the "password" field. +func (dcc *DownloadClientsCreate) SetPassword(s string) *DownloadClientsCreate { + dcc.mutation.SetPassword(s) + return dcc +} + +// SetNillablePassword sets the "password" field if the given value is not nil. +func (dcc *DownloadClientsCreate) SetNillablePassword(s *string) *DownloadClientsCreate { + if s != nil { + dcc.SetPassword(*s) + } + return dcc +} + // SetSettings sets the "settings" field. func (dcc *DownloadClientsCreate) SetSettings(s string) *DownloadClientsCreate { dcc.mutation.SetSettings(s) return dcc } +// SetNillableSettings sets the "settings" field if the given value is not nil. +func (dcc *DownloadClientsCreate) SetNillableSettings(s *string) *DownloadClientsCreate { + if s != nil { + dcc.SetSettings(*s) + } + return dcc +} + // SetPriority sets the "priority" field. func (dcc *DownloadClientsCreate) SetPriority(s string) *DownloadClientsCreate { dcc.mutation.SetPriority(s) return dcc } +// SetNillablePriority sets the "priority" field if the given value is not nil. +func (dcc *DownloadClientsCreate) SetNillablePriority(s *string) *DownloadClientsCreate { + if s != nil { + dcc.SetPriority(*s) + } + return dcc +} + // SetRemoveCompletedDownloads sets the "remove_completed_downloads" field. func (dcc *DownloadClientsCreate) SetRemoveCompletedDownloads(b bool) *DownloadClientsCreate { dcc.mutation.SetRemoveCompletedDownloads(b) return dcc } +// SetNillableRemoveCompletedDownloads sets the "remove_completed_downloads" field if the given value is not nil. +func (dcc *DownloadClientsCreate) SetNillableRemoveCompletedDownloads(b *bool) *DownloadClientsCreate { + if b != nil { + dcc.SetRemoveCompletedDownloads(*b) + } + return dcc +} + // SetRemoveFailedDownloads sets the "remove_failed_downloads" field. func (dcc *DownloadClientsCreate) SetRemoveFailedDownloads(b bool) *DownloadClientsCreate { dcc.mutation.SetRemoveFailedDownloads(b) return dcc } +// SetNillableRemoveFailedDownloads sets the "remove_failed_downloads" field if the given value is not nil. +func (dcc *DownloadClientsCreate) SetNillableRemoveFailedDownloads(b *bool) *DownloadClientsCreate { + if b != nil { + dcc.SetRemoveFailedDownloads(*b) + } + return dcc +} + // SetTags sets the "tags" field. func (dcc *DownloadClientsCreate) SetTags(s string) *DownloadClientsCreate { dcc.mutation.SetTags(s) return dcc } +// SetNillableTags sets the "tags" field if the given value is not nil. +func (dcc *DownloadClientsCreate) SetNillableTags(s *string) *DownloadClientsCreate { + if s != nil { + dcc.SetTags(*s) + } + return dcc +} + // Mutation returns the DownloadClientsMutation object of the builder. func (dcc *DownloadClientsCreate) Mutation() *DownloadClientsMutation { return dcc.mutation @@ -74,6 +148,7 @@ func (dcc *DownloadClientsCreate) Mutation() *DownloadClientsMutation { // Save creates the DownloadClients in the database. func (dcc *DownloadClientsCreate) Save(ctx context.Context) (*DownloadClients, error) { + dcc.defaults() return withHooks(ctx, dcc.sqlSave, dcc.mutation, dcc.hooks) } @@ -99,6 +174,38 @@ func (dcc *DownloadClientsCreate) ExecX(ctx context.Context) { } } +// defaults sets the default values of the builder before save. +func (dcc *DownloadClientsCreate) defaults() { + if _, ok := dcc.mutation.User(); !ok { + v := downloadclients.DefaultUser + dcc.mutation.SetUser(v) + } + if _, ok := dcc.mutation.Password(); !ok { + v := downloadclients.DefaultPassword + dcc.mutation.SetPassword(v) + } + if _, ok := dcc.mutation.Settings(); !ok { + v := downloadclients.DefaultSettings + dcc.mutation.SetSettings(v) + } + if _, ok := dcc.mutation.Priority(); !ok { + v := downloadclients.DefaultPriority + dcc.mutation.SetPriority(v) + } + if _, ok := dcc.mutation.RemoveCompletedDownloads(); !ok { + v := downloadclients.DefaultRemoveCompletedDownloads + dcc.mutation.SetRemoveCompletedDownloads(v) + } + if _, ok := dcc.mutation.RemoveFailedDownloads(); !ok { + v := downloadclients.DefaultRemoveFailedDownloads + dcc.mutation.SetRemoveFailedDownloads(v) + } + if _, ok := dcc.mutation.Tags(); !ok { + v := downloadclients.DefaultTags + dcc.mutation.SetTags(v) + } +} + // check runs all checks and user-defined validators on the builder. func (dcc *DownloadClientsCreate) check() error { if _, ok := dcc.mutation.Enable(); !ok { @@ -110,6 +217,15 @@ func (dcc *DownloadClientsCreate) check() error { if _, ok := dcc.mutation.Implementation(); !ok { return &ValidationError{Name: "implementation", err: errors.New(`ent: missing required field "DownloadClients.implementation"`)} } + if _, ok := dcc.mutation.URL(); !ok { + return &ValidationError{Name: "url", err: errors.New(`ent: missing required field "DownloadClients.url"`)} + } + if _, ok := dcc.mutation.User(); !ok { + return &ValidationError{Name: "user", err: errors.New(`ent: missing required field "DownloadClients.user"`)} + } + if _, ok := dcc.mutation.Password(); !ok { + return &ValidationError{Name: "password", err: errors.New(`ent: missing required field "DownloadClients.password"`)} + } if _, ok := dcc.mutation.Settings(); !ok { return &ValidationError{Name: "settings", err: errors.New(`ent: missing required field "DownloadClients.settings"`)} } @@ -163,6 +279,18 @@ func (dcc *DownloadClientsCreate) createSpec() (*DownloadClients, *sqlgraph.Crea _spec.SetField(downloadclients.FieldImplementation, field.TypeString, value) _node.Implementation = value } + if value, ok := dcc.mutation.URL(); ok { + _spec.SetField(downloadclients.FieldURL, field.TypeString, value) + _node.URL = value + } + if value, ok := dcc.mutation.User(); ok { + _spec.SetField(downloadclients.FieldUser, field.TypeString, value) + _node.User = value + } + if value, ok := dcc.mutation.Password(); ok { + _spec.SetField(downloadclients.FieldPassword, field.TypeString, value) + _node.Password = value + } if value, ok := dcc.mutation.Settings(); ok { _spec.SetField(downloadclients.FieldSettings, field.TypeString, value) _node.Settings = value @@ -204,6 +332,7 @@ func (dccb *DownloadClientsCreateBulk) Save(ctx context.Context) ([]*DownloadCli for i := range dccb.builders { func(i int, root context.Context) { builder := dccb.builders[i] + builder.defaults() var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { mutation, ok := m.(*DownloadClientsMutation) if !ok { diff --git a/ent/downloadclients_update.go b/ent/downloadclients_update.go index 6251e43..113507f 100644 --- a/ent/downloadclients_update.go +++ b/ent/downloadclients_update.go @@ -69,6 +69,48 @@ func (dcu *DownloadClientsUpdate) SetNillableImplementation(s *string) *Download return dcu } +// SetURL sets the "url" field. +func (dcu *DownloadClientsUpdate) SetURL(s string) *DownloadClientsUpdate { + dcu.mutation.SetURL(s) + return dcu +} + +// SetNillableURL sets the "url" field if the given value is not nil. +func (dcu *DownloadClientsUpdate) SetNillableURL(s *string) *DownloadClientsUpdate { + if s != nil { + dcu.SetURL(*s) + } + return dcu +} + +// SetUser sets the "user" field. +func (dcu *DownloadClientsUpdate) SetUser(s string) *DownloadClientsUpdate { + dcu.mutation.SetUser(s) + return dcu +} + +// SetNillableUser sets the "user" field if the given value is not nil. +func (dcu *DownloadClientsUpdate) SetNillableUser(s *string) *DownloadClientsUpdate { + if s != nil { + dcu.SetUser(*s) + } + return dcu +} + +// SetPassword sets the "password" field. +func (dcu *DownloadClientsUpdate) SetPassword(s string) *DownloadClientsUpdate { + dcu.mutation.SetPassword(s) + return dcu +} + +// SetNillablePassword sets the "password" field if the given value is not nil. +func (dcu *DownloadClientsUpdate) SetNillablePassword(s *string) *DownloadClientsUpdate { + if s != nil { + dcu.SetPassword(*s) + } + return dcu +} + // SetSettings sets the "settings" field. func (dcu *DownloadClientsUpdate) SetSettings(s string) *DownloadClientsUpdate { dcu.mutation.SetSettings(s) @@ -189,6 +231,15 @@ func (dcu *DownloadClientsUpdate) sqlSave(ctx context.Context) (n int, err error if value, ok := dcu.mutation.Implementation(); ok { _spec.SetField(downloadclients.FieldImplementation, field.TypeString, value) } + if value, ok := dcu.mutation.URL(); ok { + _spec.SetField(downloadclients.FieldURL, field.TypeString, value) + } + if value, ok := dcu.mutation.User(); ok { + _spec.SetField(downloadclients.FieldUser, field.TypeString, value) + } + if value, ok := dcu.mutation.Password(); ok { + _spec.SetField(downloadclients.FieldPassword, field.TypeString, value) + } if value, ok := dcu.mutation.Settings(); ok { _spec.SetField(downloadclients.FieldSettings, field.TypeString, value) } @@ -266,6 +317,48 @@ func (dcuo *DownloadClientsUpdateOne) SetNillableImplementation(s *string) *Down return dcuo } +// SetURL sets the "url" field. +func (dcuo *DownloadClientsUpdateOne) SetURL(s string) *DownloadClientsUpdateOne { + dcuo.mutation.SetURL(s) + return dcuo +} + +// SetNillableURL sets the "url" field if the given value is not nil. +func (dcuo *DownloadClientsUpdateOne) SetNillableURL(s *string) *DownloadClientsUpdateOne { + if s != nil { + dcuo.SetURL(*s) + } + return dcuo +} + +// SetUser sets the "user" field. +func (dcuo *DownloadClientsUpdateOne) SetUser(s string) *DownloadClientsUpdateOne { + dcuo.mutation.SetUser(s) + return dcuo +} + +// SetNillableUser sets the "user" field if the given value is not nil. +func (dcuo *DownloadClientsUpdateOne) SetNillableUser(s *string) *DownloadClientsUpdateOne { + if s != nil { + dcuo.SetUser(*s) + } + return dcuo +} + +// SetPassword sets the "password" field. +func (dcuo *DownloadClientsUpdateOne) SetPassword(s string) *DownloadClientsUpdateOne { + dcuo.mutation.SetPassword(s) + return dcuo +} + +// SetNillablePassword sets the "password" field if the given value is not nil. +func (dcuo *DownloadClientsUpdateOne) SetNillablePassword(s *string) *DownloadClientsUpdateOne { + if s != nil { + dcuo.SetPassword(*s) + } + return dcuo +} + // SetSettings sets the "settings" field. func (dcuo *DownloadClientsUpdateOne) SetSettings(s string) *DownloadClientsUpdateOne { dcuo.mutation.SetSettings(s) @@ -416,6 +509,15 @@ func (dcuo *DownloadClientsUpdateOne) sqlSave(ctx context.Context) (_node *Downl if value, ok := dcuo.mutation.Implementation(); ok { _spec.SetField(downloadclients.FieldImplementation, field.TypeString, value) } + if value, ok := dcuo.mutation.URL(); ok { + _spec.SetField(downloadclients.FieldURL, field.TypeString, value) + } + if value, ok := dcuo.mutation.User(); ok { + _spec.SetField(downloadclients.FieldUser, field.TypeString, value) + } + if value, ok := dcuo.mutation.Password(); ok { + _spec.SetField(downloadclients.FieldPassword, field.TypeString, value) + } if value, ok := dcuo.mutation.Settings(); ok { _spec.SetField(downloadclients.FieldSettings, field.TypeString, value) } diff --git a/ent/ent.go b/ent/ent.go index 3c68ebe..09c9cfb 100644 --- a/ent/ent.go +++ b/ent/ent.go @@ -8,6 +8,7 @@ import ( "fmt" "polaris/ent/downloadclients" "polaris/ent/epidodes" + "polaris/ent/history" "polaris/ent/indexers" "polaris/ent/series" "polaris/ent/settings" @@ -79,6 +80,7 @@ func checkColumn(table, column string) error { columnCheck = sql.NewColumnCheck(map[string]func(string) bool{ downloadclients.Table: downloadclients.ValidColumn, epidodes.Table: epidodes.ValidColumn, + history.Table: history.ValidColumn, indexers.Table: indexers.ValidColumn, series.Table: series.ValidColumn, settings.Table: settings.ValidColumn, diff --git a/ent/epidodes.go b/ent/epidodes.go index ad39e1c..68a5316 100644 --- a/ent/epidodes.go +++ b/ent/epidodes.go @@ -6,7 +6,6 @@ import ( "fmt" "polaris/ent/epidodes" "strings" - "time" "entgo.io/ent" "entgo.io/ent/dialect/sql" @@ -28,7 +27,7 @@ type Epidodes struct { // Overview holds the value of the "overview" field. Overview string `json:"overview,omitempty"` // AirDate holds the value of the "air_date" field. - AirDate time.Time `json:"air_date,omitempty"` + AirDate string `json:"air_date,omitempty"` selectValues sql.SelectValues } @@ -39,10 +38,8 @@ func (*Epidodes) scanValues(columns []string) ([]any, error) { switch columns[i] { case epidodes.FieldID, epidodes.FieldSeriesID, epidodes.FieldSeasonNumber, epidodes.FieldEpisodeNumber: values[i] = new(sql.NullInt64) - case epidodes.FieldTitle, epidodes.FieldOverview: + case epidodes.FieldTitle, epidodes.FieldOverview, epidodes.FieldAirDate: values[i] = new(sql.NullString) - case epidodes.FieldAirDate: - values[i] = new(sql.NullTime) default: values[i] = new(sql.UnknownType) } @@ -95,10 +92,10 @@ func (e *Epidodes) assignValues(columns []string, values []any) error { e.Overview = value.String } case epidodes.FieldAirDate: - if value, ok := values[i].(*sql.NullTime); !ok { + if value, ok := values[i].(*sql.NullString); !ok { return fmt.Errorf("unexpected type %T for field air_date", values[i]) } else if value.Valid { - e.AirDate = value.Time + e.AirDate = value.String } default: e.selectValues.Set(columns[i], values[i]) @@ -152,7 +149,7 @@ func (e *Epidodes) String() string { builder.WriteString(e.Overview) builder.WriteString(", ") builder.WriteString("air_date=") - builder.WriteString(e.AirDate.Format(time.ANSIC)) + builder.WriteString(e.AirDate) builder.WriteByte(')') return builder.String() } diff --git a/ent/epidodes/where.go b/ent/epidodes/where.go index 549abab..cc1f8e2 100644 --- a/ent/epidodes/where.go +++ b/ent/epidodes/where.go @@ -4,7 +4,6 @@ package epidodes import ( "polaris/ent/predicate" - "time" "entgo.io/ent/dialect/sql" ) @@ -80,7 +79,7 @@ func Overview(v string) predicate.Epidodes { } // AirDate applies equality check predicate on the "air_date" field. It's identical to AirDateEQ. -func AirDate(v time.Time) predicate.Epidodes { +func AirDate(v string) predicate.Epidodes { return predicate.Epidodes(sql.FieldEQ(FieldAirDate, v)) } @@ -335,45 +334,70 @@ func OverviewContainsFold(v string) predicate.Epidodes { } // AirDateEQ applies the EQ predicate on the "air_date" field. -func AirDateEQ(v time.Time) predicate.Epidodes { +func AirDateEQ(v string) predicate.Epidodes { return predicate.Epidodes(sql.FieldEQ(FieldAirDate, v)) } // AirDateNEQ applies the NEQ predicate on the "air_date" field. -func AirDateNEQ(v time.Time) predicate.Epidodes { +func AirDateNEQ(v string) predicate.Epidodes { return predicate.Epidodes(sql.FieldNEQ(FieldAirDate, v)) } // AirDateIn applies the In predicate on the "air_date" field. -func AirDateIn(vs ...time.Time) predicate.Epidodes { +func AirDateIn(vs ...string) predicate.Epidodes { return predicate.Epidodes(sql.FieldIn(FieldAirDate, vs...)) } // AirDateNotIn applies the NotIn predicate on the "air_date" field. -func AirDateNotIn(vs ...time.Time) predicate.Epidodes { +func AirDateNotIn(vs ...string) predicate.Epidodes { return predicate.Epidodes(sql.FieldNotIn(FieldAirDate, vs...)) } // AirDateGT applies the GT predicate on the "air_date" field. -func AirDateGT(v time.Time) predicate.Epidodes { +func AirDateGT(v string) predicate.Epidodes { return predicate.Epidodes(sql.FieldGT(FieldAirDate, v)) } // AirDateGTE applies the GTE predicate on the "air_date" field. -func AirDateGTE(v time.Time) predicate.Epidodes { +func AirDateGTE(v string) predicate.Epidodes { return predicate.Epidodes(sql.FieldGTE(FieldAirDate, v)) } // AirDateLT applies the LT predicate on the "air_date" field. -func AirDateLT(v time.Time) predicate.Epidodes { +func AirDateLT(v string) predicate.Epidodes { return predicate.Epidodes(sql.FieldLT(FieldAirDate, v)) } // AirDateLTE applies the LTE predicate on the "air_date" field. -func AirDateLTE(v time.Time) predicate.Epidodes { +func AirDateLTE(v string) predicate.Epidodes { return predicate.Epidodes(sql.FieldLTE(FieldAirDate, v)) } +// AirDateContains applies the Contains predicate on the "air_date" field. +func AirDateContains(v string) predicate.Epidodes { + return predicate.Epidodes(sql.FieldContains(FieldAirDate, v)) +} + +// AirDateHasPrefix applies the HasPrefix predicate on the "air_date" field. +func AirDateHasPrefix(v string) predicate.Epidodes { + return predicate.Epidodes(sql.FieldHasPrefix(FieldAirDate, v)) +} + +// AirDateHasSuffix applies the HasSuffix predicate on the "air_date" field. +func AirDateHasSuffix(v string) predicate.Epidodes { + return predicate.Epidodes(sql.FieldHasSuffix(FieldAirDate, v)) +} + +// AirDateEqualFold applies the EqualFold predicate on the "air_date" field. +func AirDateEqualFold(v string) predicate.Epidodes { + return predicate.Epidodes(sql.FieldEqualFold(FieldAirDate, v)) +} + +// AirDateContainsFold applies the ContainsFold predicate on the "air_date" field. +func AirDateContainsFold(v string) predicate.Epidodes { + return predicate.Epidodes(sql.FieldContainsFold(FieldAirDate, v)) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.Epidodes) predicate.Epidodes { return predicate.Epidodes(sql.AndPredicates(predicates...)) diff --git a/ent/epidodes_create.go b/ent/epidodes_create.go index bd48992..db3361e 100644 --- a/ent/epidodes_create.go +++ b/ent/epidodes_create.go @@ -7,7 +7,6 @@ import ( "errors" "fmt" "polaris/ent/epidodes" - "time" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" @@ -51,8 +50,8 @@ func (ec *EpidodesCreate) SetOverview(s string) *EpidodesCreate { } // SetAirDate sets the "air_date" field. -func (ec *EpidodesCreate) SetAirDate(t time.Time) *EpidodesCreate { - ec.mutation.SetAirDate(t) +func (ec *EpidodesCreate) SetAirDate(s string) *EpidodesCreate { + ec.mutation.SetAirDate(s) return ec } @@ -155,7 +154,7 @@ func (ec *EpidodesCreate) createSpec() (*Epidodes, *sqlgraph.CreateSpec) { _node.Overview = value } if value, ok := ec.mutation.AirDate(); ok { - _spec.SetField(epidodes.FieldAirDate, field.TypeTime, value) + _spec.SetField(epidodes.FieldAirDate, field.TypeString, value) _node.AirDate = value } return _node, _spec diff --git a/ent/epidodes_update.go b/ent/epidodes_update.go index 09b8b60..b17f864 100644 --- a/ent/epidodes_update.go +++ b/ent/epidodes_update.go @@ -8,7 +8,6 @@ import ( "fmt" "polaris/ent/epidodes" "polaris/ent/predicate" - "time" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" @@ -120,15 +119,15 @@ func (eu *EpidodesUpdate) SetNillableOverview(s *string) *EpidodesUpdate { } // SetAirDate sets the "air_date" field. -func (eu *EpidodesUpdate) SetAirDate(t time.Time) *EpidodesUpdate { - eu.mutation.SetAirDate(t) +func (eu *EpidodesUpdate) SetAirDate(s string) *EpidodesUpdate { + eu.mutation.SetAirDate(s) return eu } // SetNillableAirDate sets the "air_date" field if the given value is not nil. -func (eu *EpidodesUpdate) SetNillableAirDate(t *time.Time) *EpidodesUpdate { - if t != nil { - eu.SetAirDate(*t) +func (eu *EpidodesUpdate) SetNillableAirDate(s *string) *EpidodesUpdate { + if s != nil { + eu.SetAirDate(*s) } return eu } @@ -199,7 +198,7 @@ func (eu *EpidodesUpdate) sqlSave(ctx context.Context) (n int, err error) { _spec.SetField(epidodes.FieldOverview, field.TypeString, value) } if value, ok := eu.mutation.AirDate(); ok { - _spec.SetField(epidodes.FieldAirDate, field.TypeTime, value) + _spec.SetField(epidodes.FieldAirDate, field.TypeString, value) } if n, err = sqlgraph.UpdateNodes(ctx, eu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { @@ -313,15 +312,15 @@ func (euo *EpidodesUpdateOne) SetNillableOverview(s *string) *EpidodesUpdateOne } // SetAirDate sets the "air_date" field. -func (euo *EpidodesUpdateOne) SetAirDate(t time.Time) *EpidodesUpdateOne { - euo.mutation.SetAirDate(t) +func (euo *EpidodesUpdateOne) SetAirDate(s string) *EpidodesUpdateOne { + euo.mutation.SetAirDate(s) return euo } // SetNillableAirDate sets the "air_date" field if the given value is not nil. -func (euo *EpidodesUpdateOne) SetNillableAirDate(t *time.Time) *EpidodesUpdateOne { - if t != nil { - euo.SetAirDate(*t) +func (euo *EpidodesUpdateOne) SetNillableAirDate(s *string) *EpidodesUpdateOne { + if s != nil { + euo.SetAirDate(*s) } return euo } @@ -422,7 +421,7 @@ func (euo *EpidodesUpdateOne) sqlSave(ctx context.Context) (_node *Epidodes, err _spec.SetField(epidodes.FieldOverview, field.TypeString, value) } if value, ok := euo.mutation.AirDate(); ok { - _spec.SetField(epidodes.FieldAirDate, field.TypeTime, value) + _spec.SetField(epidodes.FieldAirDate, field.TypeString, value) } _node = &Epidodes{config: euo.config} _spec.Assign = _node.assignValues diff --git a/ent/hook/hook.go b/ent/hook/hook.go index bceefc3..23fae07 100644 --- a/ent/hook/hook.go +++ b/ent/hook/hook.go @@ -32,6 +32,18 @@ func (f EpidodesFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, er return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.EpidodesMutation", m) } +// The HistoryFunc type is an adapter to allow the use of ordinary +// function as History mutator. +type HistoryFunc func(context.Context, *ent.HistoryMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f HistoryFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.HistoryMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.HistoryMutation", m) +} + // The IndexersFunc type is an adapter to allow the use of ordinary // function as Indexers mutator. type IndexersFunc func(context.Context, *ent.IndexersMutation) (ent.Value, error) diff --git a/ent/indexers/indexers.go b/ent/indexers/indexers.go index ef4dbfe..9794efb 100644 --- a/ent/indexers/indexers.go +++ b/ent/indexers/indexers.go @@ -45,6 +45,11 @@ func ValidColumn(column string) bool { return false } +var ( + // DefaultEnableRss holds the default value on creation for the "enable_rss" field. + DefaultEnableRss bool +) + // OrderOption defines the ordering options for the Indexers queries. type OrderOption func(*sql.Selector) diff --git a/ent/indexers_create.go b/ent/indexers_create.go index 7720bd8..6b99f8b 100644 --- a/ent/indexers_create.go +++ b/ent/indexers_create.go @@ -43,6 +43,14 @@ func (ic *IndexersCreate) SetEnableRss(b bool) *IndexersCreate { return ic } +// SetNillableEnableRss sets the "enable_rss" field if the given value is not nil. +func (ic *IndexersCreate) SetNillableEnableRss(b *bool) *IndexersCreate { + if b != nil { + ic.SetEnableRss(*b) + } + return ic +} + // SetPriority sets the "priority" field. func (ic *IndexersCreate) SetPriority(i int) *IndexersCreate { ic.mutation.SetPriority(i) @@ -56,6 +64,7 @@ func (ic *IndexersCreate) Mutation() *IndexersMutation { // Save creates the Indexers in the database. func (ic *IndexersCreate) Save(ctx context.Context) (*Indexers, error) { + ic.defaults() return withHooks(ctx, ic.sqlSave, ic.mutation, ic.hooks) } @@ -81,6 +90,14 @@ func (ic *IndexersCreate) ExecX(ctx context.Context) { } } +// defaults sets the default values of the builder before save. +func (ic *IndexersCreate) defaults() { + if _, ok := ic.mutation.EnableRss(); !ok { + v := indexers.DefaultEnableRss + ic.mutation.SetEnableRss(v) + } +} + // check runs all checks and user-defined validators on the builder. func (ic *IndexersCreate) check() error { if _, ok := ic.mutation.Name(); !ok { @@ -165,6 +182,7 @@ func (icb *IndexersCreateBulk) Save(ctx context.Context) ([]*Indexers, error) { for i := range icb.builders { func(i int, root context.Context) { builder := icb.builders[i] + builder.defaults() var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { mutation, ok := m.(*IndexersMutation) if !ok { diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index f017c27..9a271b6 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -14,11 +14,14 @@ var ( {Name: "enable", Type: field.TypeBool}, {Name: "name", Type: field.TypeString}, {Name: "implementation", Type: field.TypeString}, - {Name: "settings", Type: field.TypeString}, - {Name: "priority", Type: field.TypeString}, - {Name: "remove_completed_downloads", Type: field.TypeBool}, - {Name: "remove_failed_downloads", Type: field.TypeBool}, - {Name: "tags", Type: field.TypeString}, + {Name: "url", Type: field.TypeString}, + {Name: "user", Type: field.TypeString, Default: ""}, + {Name: "password", Type: field.TypeString, Default: ""}, + {Name: "settings", Type: field.TypeString, Default: ""}, + {Name: "priority", Type: field.TypeString, Default: ""}, + {Name: "remove_completed_downloads", Type: field.TypeBool, Default: true}, + {Name: "remove_failed_downloads", Type: field.TypeBool, Default: true}, + {Name: "tags", Type: field.TypeString, Default: ""}, } // DownloadClientsTable holds the schema information for the "download_clients" table. DownloadClientsTable = &schema.Table{ @@ -34,7 +37,7 @@ var ( {Name: "episode_number", Type: field.TypeInt}, {Name: "title", Type: field.TypeString}, {Name: "overview", Type: field.TypeString}, - {Name: "air_date", Type: field.TypeTime}, + {Name: "air_date", Type: field.TypeString}, } // EpidodesTable holds the schema information for the "epidodes" table. EpidodesTable = &schema.Table{ @@ -42,13 +45,27 @@ var ( Columns: EpidodesColumns, PrimaryKey: []*schema.Column{EpidodesColumns[0]}, } + // HistoriesColumns holds the columns for the "histories" table. + HistoriesColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "series_id", Type: field.TypeInt}, + {Name: "episode_id", Type: field.TypeInt}, + {Name: "source_title", Type: field.TypeString}, + {Name: "date", Type: field.TypeTime}, + } + // HistoriesTable holds the schema information for the "histories" table. + HistoriesTable = &schema.Table{ + Name: "histories", + Columns: HistoriesColumns, + PrimaryKey: []*schema.Column{HistoriesColumns[0]}, + } // IndexersColumns holds the columns for the "indexers" table. IndexersColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, {Name: "name", Type: field.TypeString}, {Name: "implementation", Type: field.TypeString}, {Name: "settings", Type: field.TypeString}, - {Name: "enable_rss", Type: field.TypeBool}, + {Name: "enable_rss", Type: field.TypeBool, Default: true}, {Name: "priority", Type: field.TypeInt}, } // IndexersTable holds the schema information for the "indexers" table. @@ -89,6 +106,7 @@ var ( Tables = []*schema.Table{ DownloadClientsTable, EpidodesTable, + HistoriesTable, IndexersTable, SeriesTable, SettingsTable, diff --git a/ent/mutation.go b/ent/mutation.go index 40fd834..e17d771 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -8,6 +8,7 @@ import ( "fmt" "polaris/ent/downloadclients" "polaris/ent/epidodes" + "polaris/ent/history" "polaris/ent/indexers" "polaris/ent/predicate" "polaris/ent/series" @@ -30,6 +31,7 @@ const ( // Node types. TypeDownloadClients = "DownloadClients" TypeEpidodes = "Epidodes" + TypeHistory = "History" TypeIndexers = "Indexers" TypeSeries = "Series" TypeSettings = "Settings" @@ -44,6 +46,9 @@ type DownloadClientsMutation struct { enable *bool name *string implementation *string + url *string + user *string + password *string settings *string priority *string remove_completed_downloads *bool @@ -261,6 +266,114 @@ func (m *DownloadClientsMutation) ResetImplementation() { m.implementation = nil } +// SetURL sets the "url" field. +func (m *DownloadClientsMutation) SetURL(s string) { + m.url = &s +} + +// URL returns the value of the "url" field in the mutation. +func (m *DownloadClientsMutation) URL() (r string, exists bool) { + v := m.url + if v == nil { + return + } + return *v, true +} + +// OldURL returns the old "url" field's value of the DownloadClients entity. +// If the DownloadClients 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 *DownloadClientsMutation) OldURL(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldURL is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldURL requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldURL: %w", err) + } + return oldValue.URL, nil +} + +// ResetURL resets all changes to the "url" field. +func (m *DownloadClientsMutation) ResetURL() { + m.url = nil +} + +// SetUser sets the "user" field. +func (m *DownloadClientsMutation) SetUser(s string) { + m.user = &s +} + +// User returns the value of the "user" field in the mutation. +func (m *DownloadClientsMutation) User() (r string, exists bool) { + v := m.user + if v == nil { + return + } + return *v, true +} + +// OldUser returns the old "user" field's value of the DownloadClients entity. +// If the DownloadClients 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 *DownloadClientsMutation) OldUser(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUser is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUser requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUser: %w", err) + } + return oldValue.User, nil +} + +// ResetUser resets all changes to the "user" field. +func (m *DownloadClientsMutation) ResetUser() { + m.user = nil +} + +// SetPassword sets the "password" field. +func (m *DownloadClientsMutation) SetPassword(s string) { + m.password = &s +} + +// Password returns the value of the "password" field in the mutation. +func (m *DownloadClientsMutation) Password() (r string, exists bool) { + v := m.password + if v == nil { + return + } + return *v, true +} + +// OldPassword returns the old "password" field's value of the DownloadClients entity. +// If the DownloadClients 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 *DownloadClientsMutation) OldPassword(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldPassword is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldPassword requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldPassword: %w", err) + } + return oldValue.Password, nil +} + +// ResetPassword resets all changes to the "password" field. +func (m *DownloadClientsMutation) ResetPassword() { + m.password = nil +} + // SetSettings sets the "settings" field. func (m *DownloadClientsMutation) SetSettings(s string) { m.settings = &s @@ -475,7 +588,7 @@ func (m *DownloadClientsMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *DownloadClientsMutation) Fields() []string { - fields := make([]string, 0, 8) + fields := make([]string, 0, 11) if m.enable != nil { fields = append(fields, downloadclients.FieldEnable) } @@ -485,6 +598,15 @@ func (m *DownloadClientsMutation) Fields() []string { if m.implementation != nil { fields = append(fields, downloadclients.FieldImplementation) } + if m.url != nil { + fields = append(fields, downloadclients.FieldURL) + } + if m.user != nil { + fields = append(fields, downloadclients.FieldUser) + } + if m.password != nil { + fields = append(fields, downloadclients.FieldPassword) + } if m.settings != nil { fields = append(fields, downloadclients.FieldSettings) } @@ -514,6 +636,12 @@ func (m *DownloadClientsMutation) Field(name string) (ent.Value, bool) { return m.Name() case downloadclients.FieldImplementation: return m.Implementation() + case downloadclients.FieldURL: + return m.URL() + case downloadclients.FieldUser: + return m.User() + case downloadclients.FieldPassword: + return m.Password() case downloadclients.FieldSettings: return m.Settings() case downloadclients.FieldPriority: @@ -539,6 +667,12 @@ func (m *DownloadClientsMutation) OldField(ctx context.Context, name string) (en return m.OldName(ctx) case downloadclients.FieldImplementation: return m.OldImplementation(ctx) + case downloadclients.FieldURL: + return m.OldURL(ctx) + case downloadclients.FieldUser: + return m.OldUser(ctx) + case downloadclients.FieldPassword: + return m.OldPassword(ctx) case downloadclients.FieldSettings: return m.OldSettings(ctx) case downloadclients.FieldPriority: @@ -579,6 +713,27 @@ func (m *DownloadClientsMutation) SetField(name string, value ent.Value) error { } m.SetImplementation(v) return nil + case downloadclients.FieldURL: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetURL(v) + return nil + case downloadclients.FieldUser: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUser(v) + return nil + case downloadclients.FieldPassword: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetPassword(v) + return nil case downloadclients.FieldSettings: v, ok := value.(string) if !ok { @@ -672,6 +827,15 @@ func (m *DownloadClientsMutation) ResetField(name string) error { case downloadclients.FieldImplementation: m.ResetImplementation() return nil + case downloadclients.FieldURL: + m.ResetURL() + return nil + case downloadclients.FieldUser: + m.ResetUser() + return nil + case downloadclients.FieldPassword: + m.ResetPassword() + return nil case downloadclients.FieldSettings: m.ResetSettings() return nil @@ -753,7 +917,7 @@ type EpidodesMutation struct { addepisode_number *int title *string overview *string - air_date *time.Time + air_date *string clearedFields map[string]struct{} done bool oldValue func(context.Context) (*Epidodes, error) @@ -1099,12 +1263,12 @@ func (m *EpidodesMutation) ResetOverview() { } // SetAirDate sets the "air_date" field. -func (m *EpidodesMutation) SetAirDate(t time.Time) { - m.air_date = &t +func (m *EpidodesMutation) SetAirDate(s string) { + m.air_date = &s } // AirDate returns the value of the "air_date" field in the mutation. -func (m *EpidodesMutation) AirDate() (r time.Time, exists bool) { +func (m *EpidodesMutation) AirDate() (r string, exists bool) { v := m.air_date if v == nil { return @@ -1115,7 +1279,7 @@ func (m *EpidodesMutation) AirDate() (r time.Time, exists bool) { // OldAirDate returns the old "air_date" field's value of the Epidodes entity. // If the Epidodes 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 *EpidodesMutation) OldAirDate(ctx context.Context) (v time.Time, err error) { +func (m *EpidodesMutation) OldAirDate(ctx context.Context) (v string, err error) { if !m.op.Is(OpUpdateOne) { return v, errors.New("OldAirDate is only allowed on UpdateOne operations") } @@ -1273,7 +1437,7 @@ func (m *EpidodesMutation) SetField(name string, value ent.Value) error { m.SetOverview(v) return nil case epidodes.FieldAirDate: - v, ok := value.(time.Time) + v, ok := value.(string) if !ok { return fmt.Errorf("unexpected type %T for field %s", value, name) } @@ -1437,6 +1601,563 @@ func (m *EpidodesMutation) ResetEdge(name string) error { return fmt.Errorf("unknown Epidodes edge %s", name) } +// HistoryMutation represents an operation that mutates the History nodes in the graph. +type HistoryMutation struct { + config + op Op + typ string + id *int + series_id *int + addseries_id *int + episode_id *int + addepisode_id *int + source_title *string + date *time.Time + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*History, error) + predicates []predicate.History +} + +var _ ent.Mutation = (*HistoryMutation)(nil) + +// historyOption allows management of the mutation configuration using functional options. +type historyOption func(*HistoryMutation) + +// newHistoryMutation creates new mutation for the History entity. +func newHistoryMutation(c config, op Op, opts ...historyOption) *HistoryMutation { + m := &HistoryMutation{ + config: c, + op: op, + typ: TypeHistory, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withHistoryID sets the ID field of the mutation. +func withHistoryID(id int) historyOption { + return func(m *HistoryMutation) { + var ( + err error + once sync.Once + value *History + ) + m.oldValue = func(ctx context.Context) (*History, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().History.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withHistory sets the old History of the mutation. +func withHistory(node *History) historyOption { + return func(m *HistoryMutation) { + m.oldValue = func(context.Context) (*History, 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 HistoryMutation) 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 HistoryMutation) 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 *HistoryMutation) 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 *HistoryMutation) 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().History.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetSeriesID sets the "series_id" field. +func (m *HistoryMutation) SetSeriesID(i int) { + m.series_id = &i + m.addseries_id = nil +} + +// SeriesID returns the value of the "series_id" field in the mutation. +func (m *HistoryMutation) SeriesID() (r int, exists bool) { + v := m.series_id + if v == nil { + return + } + return *v, true +} + +// OldSeriesID returns the old "series_id" field's value of the History entity. +// If the History 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 *HistoryMutation) OldSeriesID(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldSeriesID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldSeriesID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldSeriesID: %w", err) + } + return oldValue.SeriesID, nil +} + +// AddSeriesID adds i to the "series_id" field. +func (m *HistoryMutation) AddSeriesID(i int) { + if m.addseries_id != nil { + *m.addseries_id += i + } else { + m.addseries_id = &i + } +} + +// AddedSeriesID returns the value that was added to the "series_id" field in this mutation. +func (m *HistoryMutation) AddedSeriesID() (r int, exists bool) { + v := m.addseries_id + if v == nil { + return + } + return *v, true +} + +// ResetSeriesID resets all changes to the "series_id" field. +func (m *HistoryMutation) ResetSeriesID() { + m.series_id = nil + m.addseries_id = nil +} + +// SetEpisodeID sets the "episode_id" field. +func (m *HistoryMutation) SetEpisodeID(i int) { + m.episode_id = &i + m.addepisode_id = nil +} + +// EpisodeID returns the value of the "episode_id" field in the mutation. +func (m *HistoryMutation) EpisodeID() (r int, exists bool) { + v := m.episode_id + if v == nil { + return + } + return *v, true +} + +// OldEpisodeID returns the old "episode_id" field's value of the History entity. +// If the History 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 *HistoryMutation) OldEpisodeID(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldEpisodeID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldEpisodeID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldEpisodeID: %w", err) + } + return oldValue.EpisodeID, nil +} + +// AddEpisodeID adds i to the "episode_id" field. +func (m *HistoryMutation) AddEpisodeID(i int) { + if m.addepisode_id != nil { + *m.addepisode_id += i + } else { + m.addepisode_id = &i + } +} + +// AddedEpisodeID returns the value that was added to the "episode_id" field in this mutation. +func (m *HistoryMutation) AddedEpisodeID() (r int, exists bool) { + v := m.addepisode_id + if v == nil { + return + } + return *v, true +} + +// ResetEpisodeID resets all changes to the "episode_id" field. +func (m *HistoryMutation) ResetEpisodeID() { + m.episode_id = nil + m.addepisode_id = nil +} + +// SetSourceTitle sets the "source_title" field. +func (m *HistoryMutation) SetSourceTitle(s string) { + m.source_title = &s +} + +// SourceTitle returns the value of the "source_title" field in the mutation. +func (m *HistoryMutation) SourceTitle() (r string, exists bool) { + v := m.source_title + if v == nil { + return + } + return *v, true +} + +// OldSourceTitle returns the old "source_title" field's value of the History entity. +// If the History 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 *HistoryMutation) OldSourceTitle(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldSourceTitle is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldSourceTitle requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldSourceTitle: %w", err) + } + return oldValue.SourceTitle, nil +} + +// ResetSourceTitle resets all changes to the "source_title" field. +func (m *HistoryMutation) ResetSourceTitle() { + m.source_title = nil +} + +// SetDate sets the "date" field. +func (m *HistoryMutation) SetDate(t time.Time) { + m.date = &t +} + +// Date returns the value of the "date" field in the mutation. +func (m *HistoryMutation) Date() (r time.Time, exists bool) { + v := m.date + if v == nil { + return + } + return *v, true +} + +// OldDate returns the old "date" field's value of the History entity. +// If the History 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 *HistoryMutation) OldDate(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDate is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDate requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDate: %w", err) + } + return oldValue.Date, nil +} + +// ResetDate resets all changes to the "date" field. +func (m *HistoryMutation) ResetDate() { + m.date = nil +} + +// Where appends a list predicates to the HistoryMutation builder. +func (m *HistoryMutation) Where(ps ...predicate.History) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the HistoryMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *HistoryMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.History, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *HistoryMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *HistoryMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (History). +func (m *HistoryMutation) 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 *HistoryMutation) Fields() []string { + fields := make([]string, 0, 4) + if m.series_id != nil { + fields = append(fields, history.FieldSeriesID) + } + if m.episode_id != nil { + fields = append(fields, history.FieldEpisodeID) + } + if m.source_title != nil { + fields = append(fields, history.FieldSourceTitle) + } + if m.date != nil { + fields = append(fields, history.FieldDate) + } + 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 *HistoryMutation) Field(name string) (ent.Value, bool) { + switch name { + case history.FieldSeriesID: + return m.SeriesID() + case history.FieldEpisodeID: + return m.EpisodeID() + case history.FieldSourceTitle: + return m.SourceTitle() + case history.FieldDate: + return m.Date() + } + 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 *HistoryMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case history.FieldSeriesID: + return m.OldSeriesID(ctx) + case history.FieldEpisodeID: + return m.OldEpisodeID(ctx) + case history.FieldSourceTitle: + return m.OldSourceTitle(ctx) + case history.FieldDate: + return m.OldDate(ctx) + } + return nil, fmt.Errorf("unknown History 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 *HistoryMutation) SetField(name string, value ent.Value) error { + switch name { + case history.FieldSeriesID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetSeriesID(v) + return nil + case history.FieldEpisodeID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetEpisodeID(v) + return nil + case history.FieldSourceTitle: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetSourceTitle(v) + return nil + case history.FieldDate: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDate(v) + return nil + } + return fmt.Errorf("unknown History field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *HistoryMutation) AddedFields() []string { + var fields []string + if m.addseries_id != nil { + fields = append(fields, history.FieldSeriesID) + } + if m.addepisode_id != nil { + fields = append(fields, history.FieldEpisodeID) + } + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *HistoryMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case history.FieldSeriesID: + return m.AddedSeriesID() + case history.FieldEpisodeID: + return m.AddedEpisodeID() + } + 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 *HistoryMutation) AddField(name string, value ent.Value) error { + switch name { + case history.FieldSeriesID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddSeriesID(v) + return nil + case history.FieldEpisodeID: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddEpisodeID(v) + return nil + } + return fmt.Errorf("unknown History numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *HistoryMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *HistoryMutation) 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 *HistoryMutation) ClearField(name string) error { + return fmt.Errorf("unknown History 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 *HistoryMutation) ResetField(name string) error { + switch name { + case history.FieldSeriesID: + m.ResetSeriesID() + return nil + case history.FieldEpisodeID: + m.ResetEpisodeID() + return nil + case history.FieldSourceTitle: + m.ResetSourceTitle() + return nil + case history.FieldDate: + m.ResetDate() + return nil + } + return fmt.Errorf("unknown History field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *HistoryMutation) 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 *HistoryMutation) AddedIDs(name string) []ent.Value { + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *HistoryMutation) 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 *HistoryMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *HistoryMutation) 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 *HistoryMutation) 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 *HistoryMutation) ClearEdge(name string) error { + return fmt.Errorf("unknown History 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 *HistoryMutation) ResetEdge(name string) error { + return fmt.Errorf("unknown History edge %s", name) +} + // IndexersMutation represents an operation that mutates the Indexers nodes in the graph. type IndexersMutation struct { config diff --git a/ent/predicate/predicate.go b/ent/predicate/predicate.go index a60537b..4b3a9df 100644 --- a/ent/predicate/predicate.go +++ b/ent/predicate/predicate.go @@ -12,6 +12,9 @@ type DownloadClients func(*sql.Selector) // Epidodes is the predicate function for epidodes builders. type Epidodes func(*sql.Selector) +// History is the predicate function for history builders. +type History func(*sql.Selector) + // Indexers is the predicate function for indexers builders. type Indexers func(*sql.Selector) diff --git a/ent/runtime.go b/ent/runtime.go index 793d053..6c80c48 100644 --- a/ent/runtime.go +++ b/ent/runtime.go @@ -2,8 +2,50 @@ package ent +import ( + "polaris/ent/downloadclients" + "polaris/ent/indexers" + "polaris/ent/schema" +) + // The init function reads all schema descriptors with runtime code // (default values, validators, hooks and policies) and stitches it // to their package variables. func init() { + downloadclientsFields := schema.DownloadClients{}.Fields() + _ = downloadclientsFields + // downloadclientsDescUser is the schema descriptor for user field. + downloadclientsDescUser := downloadclientsFields[4].Descriptor() + // downloadclients.DefaultUser holds the default value on creation for the user field. + downloadclients.DefaultUser = downloadclientsDescUser.Default.(string) + // downloadclientsDescPassword is the schema descriptor for password field. + downloadclientsDescPassword := downloadclientsFields[5].Descriptor() + // downloadclients.DefaultPassword holds the default value on creation for the password field. + downloadclients.DefaultPassword = downloadclientsDescPassword.Default.(string) + // downloadclientsDescSettings is the schema descriptor for settings field. + downloadclientsDescSettings := downloadclientsFields[6].Descriptor() + // downloadclients.DefaultSettings holds the default value on creation for the settings field. + downloadclients.DefaultSettings = downloadclientsDescSettings.Default.(string) + // downloadclientsDescPriority is the schema descriptor for priority field. + downloadclientsDescPriority := downloadclientsFields[7].Descriptor() + // downloadclients.DefaultPriority holds the default value on creation for the priority field. + downloadclients.DefaultPriority = downloadclientsDescPriority.Default.(string) + // downloadclientsDescRemoveCompletedDownloads is the schema descriptor for remove_completed_downloads field. + downloadclientsDescRemoveCompletedDownloads := downloadclientsFields[8].Descriptor() + // downloadclients.DefaultRemoveCompletedDownloads holds the default value on creation for the remove_completed_downloads field. + downloadclients.DefaultRemoveCompletedDownloads = downloadclientsDescRemoveCompletedDownloads.Default.(bool) + // downloadclientsDescRemoveFailedDownloads is the schema descriptor for remove_failed_downloads field. + downloadclientsDescRemoveFailedDownloads := downloadclientsFields[9].Descriptor() + // downloadclients.DefaultRemoveFailedDownloads holds the default value on creation for the remove_failed_downloads field. + downloadclients.DefaultRemoveFailedDownloads = downloadclientsDescRemoveFailedDownloads.Default.(bool) + // downloadclientsDescTags is the schema descriptor for tags field. + downloadclientsDescTags := downloadclientsFields[10].Descriptor() + // downloadclients.DefaultTags holds the default value on creation for the tags field. + downloadclients.DefaultTags = downloadclientsDescTags.Default.(string) + indexersFields := schema.Indexers{}.Fields() + _ = indexersFields + // indexersDescEnableRss is the schema descriptor for enable_rss field. + indexersDescEnableRss := indexersFields[3].Descriptor() + // indexers.DefaultEnableRss holds the default value on creation for the enable_rss field. + indexers.DefaultEnableRss = indexersDescEnableRss.Default.(bool) } diff --git a/ent/schema/downloadclients.go b/ent/schema/downloadclients.go index 385ca86..3ee1fa7 100644 --- a/ent/schema/downloadclients.go +++ b/ent/schema/downloadclients.go @@ -16,11 +16,14 @@ func (DownloadClients) Fields() []ent.Field { field.Bool("enable"), field.String("name"), field.String("implementation"), - field.String("settings"), - field.String("priority"), - field.Bool("remove_completed_downloads"), - field.Bool("remove_failed_downloads"), - field.String("tags"), + field.String("url"), + field.String("user").Default(""), + field.String("password").Default(""), + field.String("settings").Default(""), + field.String("priority").Default(""), + field.Bool("remove_completed_downloads").Default(true), + field.Bool("remove_failed_downloads").Default(true), + field.String("tags").Default(""), } } diff --git a/ent/schema/epidodes.go b/ent/schema/epidodes.go index bc34ad8..ab2f663 100644 --- a/ent/schema/epidodes.go +++ b/ent/schema/epidodes.go @@ -18,7 +18,7 @@ func (Epidodes) Fields() []ent.Field { field.Int("episode_number"), field.String("title"), field.String("overview"), - field.Time("air_date"), + field.String("air_date"), } } diff --git a/ent/schema/indexers.go b/ent/schema/indexers.go index 76ba35c..826851e 100644 --- a/ent/schema/indexers.go +++ b/ent/schema/indexers.go @@ -16,7 +16,7 @@ func (Indexers) Fields() []ent.Field { field.String("name"), field.String("implementation"), field.String("settings"), - field.Bool("enable_rss"), + field.Bool("enable_rss").Default(true), field.Int("priority"), } } diff --git a/ent/tx.go b/ent/tx.go index f5e68a8..f34beb1 100644 --- a/ent/tx.go +++ b/ent/tx.go @@ -16,6 +16,8 @@ type Tx struct { DownloadClients *DownloadClientsClient // Epidodes is the client for interacting with the Epidodes builders. Epidodes *EpidodesClient + // History is the client for interacting with the History builders. + History *HistoryClient // Indexers is the client for interacting with the Indexers builders. Indexers *IndexersClient // Series is the client for interacting with the Series builders. @@ -155,6 +157,7 @@ func (tx *Tx) Client() *Client { func (tx *Tx) init() { tx.DownloadClients = NewDownloadClientsClient(tx.config) tx.Epidodes = NewEpidodesClient(tx.config) + tx.History = NewHistoryClient(tx.config) tx.Indexers = NewIndexersClient(tx.config) tx.Series = NewSeriesClient(tx.config) tx.Settings = NewSettingsClient(tx.config) diff --git a/go.mod b/go.mod index a317c2d..699cd75 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,9 @@ go 1.22.4 require ( entgo.io/ent v0.13.1 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 ) require ( @@ -26,8 +28,10 @@ require ( 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/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl/v2 v2.13.0 // indirect + github.com/hekmon/cunits/v2 v2.1.0 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -47,9 +51,8 @@ require ( github.com/zclconf/go-cty v1.8.0 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/crypto v0.23.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.25.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect google.golang.org/protobuf v1.34.1 // indirect @@ -60,6 +63,7 @@ require ( require ( github.com/cyruzin/golang-tmdb v1.6.3 github.com/gin-gonic/gin v1.10.0 + github.com/hekmon/transmissionrpc v1.1.0 github.com/json-iterator/go v1.1.12 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect diff --git a/go.sum b/go.sum index 2eae9ad..6ccb0e0 100644 --- a/go.sum +++ b/go.sum @@ -54,10 +54,18 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN 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/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +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= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl/v2 v2.13.0 h1:0Apadu1w6M11dyGFxWnmhhcMjkbAiKCv7G1r/2QgCNc= github.com/hashicorp/hcl/v2 v2.13.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0= +github.com/hekmon/cunits/v2 v2.0.2/go.mod h1:9r1TycXYXaTmEWlAIfFV8JT+Xo59U96yUJAYHxzii2M= +github.com/hekmon/cunits/v2 v2.1.0 h1:k6wIjc4PlacNOHwKEMBgWV2/c8jyD4eRMs5mR1BBhI0= +github.com/hekmon/cunits/v2 v2.1.0/go.mod h1:9r1TycXYXaTmEWlAIfFV8JT+Xo59U96yUJAYHxzii2M= +github.com/hekmon/transmissionrpc v1.1.0 h1:58xY27x2JYxaMlIj7ycKnxqgCm3IjvTxfB7cHPLxOfs= +github.com/hekmon/transmissionrpc v1.1.0/go.mod h1:qkwhsyD/MQSlWvOE1AC92xajwEveAuGsOvTuOBZEuHc= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -101,6 +109,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= +github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= @@ -155,8 +165,8 @@ 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-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +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/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= diff --git a/pkg/downloader/torrent.go b/pkg/downloader/torrent.go deleted file mode 100644 index a67c307..0000000 --- a/pkg/downloader/torrent.go +++ /dev/null @@ -1,25 +0,0 @@ -package downloader - -import ( - "github.com/anacrolix/torrent" - "github.com/pkg/errors" -) - - - -func DownloadByMagnet(magnet string, dir string) (*torrent.Torrent, error) { - c, err := torrent.NewClient(nil) - if err != nil { - return nil, errors.Wrap(err, "new torrent") - } - defer c.Close() - t, err := c.AddMagnet(magnet) - if err != nil { - return nil, errors.Wrap(err, "add torrent") - } - - <-t.GotInfo() - t.DownloadAll() - c.WaitAll() - return t, nil -} \ No newline at end of file diff --git a/pkg/tmdb/tmdb.go b/pkg/tmdb/tmdb.go index 89d8ebf..486f2a9 100644 --- a/pkg/tmdb/tmdb.go +++ b/pkg/tmdb/tmdb.go @@ -36,6 +36,11 @@ func (c *Client) SearchTvShow(query string, lang string) (*tmdb.SearchTVShows, e return r, nil } +func (c *Client) GetEposideDetail(id, seasonNumber, eposideNumber int, language string) (*tmdb.TVEpisodeDetails, error) { + d, err := c.tmdbClient.GetTVEpisodeDetails(id, seasonNumber, eposideNumber, withLangOption(language)) + return d, err +} + func wrapLanguage(lang string) string { if lang == "" { lang = "zh-CN" diff --git a/pkg/transmission/transmission.go b/pkg/transmission/transmission.go new file mode 100644 index 0000000..3fa0ecf --- /dev/null +++ b/pkg/transmission/transmission.go @@ -0,0 +1,28 @@ +package transmission + +import ( + "net/url" + "github.com/hekmon/transmissionrpc" + "github.com/pkg/errors" +) + +func NewClient(url1, user, password string) (*Client, error) { + u, err := url.Parse(url1) + if err != nil { + return nil, errors.Wrap(err, "parse url") + } + tbt, err := transmissionrpc.New(u.Hostname(), user, password, nil) + if err != nil { + return nil, errors.Wrap(err, "connect transmission") + } + return &Client{c: tbt}, nil +} + +type Client struct { + c *transmissionrpc.Client +} + +func (c *Client) Download(magnet string) (*transmissionrpc.Torrent, error) { + t, err := c.c.TorrentAdd(&transmissionrpc.TorrentAddPayload{Filename: &magnet}) + return t, err +} diff --git a/server/resources.go b/server/resources.go index 1bfcd70..7dcb421 100644 --- a/server/resources.go +++ b/server/resources.go @@ -4,8 +4,8 @@ import ( "fmt" "polaris/db" "polaris/log" - "polaris/pkg/downloader" "polaris/pkg/torznab" + "polaris/pkg/transmission" "github.com/gin-gonic/gin" "github.com/pkg/errors" @@ -49,9 +49,9 @@ func (s *Server) AddTorznabInfo(c *gin.Context) (interface{}, error) { } type searchAndDownloadIn struct { - Title string `json:"title"` - Season int `json:"season"` - Episode int `json:"episode"` + Title string `json:"title"` + Season int `json:"season"` + Episode int `json:"episode"` } func (s *Server) SearchAndDownload(c *gin.Context) (interface{}, error) { @@ -59,13 +59,43 @@ func (s *Server) SearchAndDownload(c *gin.Context) (interface{}, error) { if err := c.ShouldBindJSON(&in); err != nil { return nil, errors.Wrap(err, "bind json") } + tr := s.db.GetTransmission() + trc, err := transmission.NewClient(tr.URL, tr.User, tr.Password) + if err != nil { + return nil, errors.Wrap(err, "connect transmission") + } + res := s.searchTvWithTorznab(in.Title, in.Season, in.Episode) r1 := res[0] - t, err := downloader.DownloadByMagnet(r1.Magnet, "~") + log.Infof("found resource to download: %v", r1) + torrent, err := trc.Download(r1.Magnet) if err != nil { - return nil, errors.Wrap(err, "download torrent") + return nil, errors.Wrap(err, "downloading") } - s.tasks[r1.Name] = t + s.tasks[r1.Name] = torrent + // t, err := downloader.DownloadByMagnet(r1.Magnet, "~") + // if err != nil { + // return nil, errors.Wrap(err, "download torrent") + // } log.Errorf("success add %s to download task", r1.Name) return nil, nil -} \ No newline at end of file +} + +type downloadClientIn struct { + Name string `json:"name"` + URL string `json:"url"` + User string `json:"user"` + Password string `json:"password"` + Implementation string `json:"implementation"` +} + +func (s *Server) AddDownloadClient(c *gin.Context) (interface{}, error) { + var in downloadClientIn + if err := c.ShouldBindJSON(&in); err != nil { + return nil, errors.Wrap(err, "bind json") + } + if err := s.db.SaveTransmission(in.Name, in.URL, in.User, in.Password); err != nil { + return nil, errors.Wrap(err, "save transmission") + } + return nil, nil +} diff --git a/server/server.go b/server/server.go index 21f377a..0ba9ceb 100644 --- a/server/server.go +++ b/server/server.go @@ -5,6 +5,9 @@ import ( "polaris/log" "polaris/pkg/tmdb" + "github.com/hekmon/transmissionrpc" + "github.com/robfig/cron" + "github.com/gin-gonic/gin" "github.com/pkg/errors" ) @@ -12,18 +15,34 @@ import ( func NewServer(db *db.Client) *Server { r := gin.Default() return &Server{ - r: r, - db: db, + r: r, + db: db, + cron: cron.New(), + tasks: make(map[string]*transmissionrpc.Torrent), } } type Server struct { - r *gin.Engine - db *db.Client + r *gin.Engine + db *db.Client + cron *cron.Cron language string + tasks map[string]*transmissionrpc.Torrent +} + +func (s *Server) scheduler() { + s.cron.AddFunc("@every 1m", s.checkTasks) +} + +func (s *Server) checkTasks() { + for name, t := range s.tasks { + log.Infof("task %s percentage done: %f", name, *t.PercentDone) + } } func (s *Server) Serve() error { + s.scheduler() + api := s.r.Group("/api/v1") setting := api.Group("/setting") @@ -38,12 +57,21 @@ func (s *Server) Serve() error { tv.POST("/watchlist", HttpHandler(s.AddWatchlist)) tv.GET("/watchlist", HttpHandler(s.GetWatchlist)) } + indexer := api.Group("/indexer") + { + indexer.POST("/add", HttpHandler(s.AddTorznabInfo)) + indexer.POST("/download", HttpHandler(s.SearchAndDownload)) + } + + downloader := api.Group("/downloader") + { + downloader.POST("/add", HttpHandler(s.AddDownloadClient)) + } s.language = s.db.GetLanguage() return s.r.Run(":8080") } - func (s *Server) TMDB() (*tmdb.Client, error) { api := s.db.GetSetting(db.SettingTmdbApiKey) if api == "" { @@ -59,4 +87,3 @@ func (s *Server) MustTMDB() *tmdb.Client { } return t } - diff --git a/server/watchlist.go b/server/watchlist.go index 5e6ed85..0efc4db 100644 --- a/server/watchlist.go +++ b/server/watchlist.go @@ -42,6 +42,21 @@ func (s *Server) AddWatchlist(c *gin.Context) (interface{}, error) { if err := s.db.AddWatchlist(in.RootFolder, detail); err != nil { return nil, errors.Wrap(err, "add to list") } + + for _, season := range detail.Seasons { + seasonId := season.SeasonNumber + for i := 1; i <= season.EpisodeCount; i++ { + ep, err := s.MustTMDB().GetEposideDetail(int(detail.ID), seasonId, i, s.language) + if err != nil { + log.Errorf("get eposide detail: %v", err) + return nil, errors.Wrap(err, "get eposide detail") + } + err = s.db.SaveEposideDetail(int(detail.ID), ep) + if err != nil { + return nil, errors.Wrap(err, "save episode") + } + } + } log.Infof("add tv %s to watchlist success", detail.Name) return nil, nil }