diff --git a/.gitignore b/.gitignore index 10047f6..7e3c22d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ config.yml .idea/ .DS_Store *.db +data/ ui/node_modules/ ui/dist/ diff --git a/db/const.go b/db/const.go index 7e7fdd4..04f126a 100644 --- a/db/const.go +++ b/db/const.go @@ -16,6 +16,13 @@ const ( const ( IndexerTorznabImpl = "torznab" + DataPath = "./data" + ImgPath = DataPath + "/img" +) + +const ( + LanguageEN = "en-US" + LanguageCN = "zh-CN" ) type ResolutionType string diff --git a/db/db.go b/db/db.go index 8239e64..e839308 100644 --- a/db/db.go +++ b/db/db.go @@ -28,8 +28,8 @@ type Client struct { } func Open() (*Client, error) { - os.Mkdir("./db", 0666) - client, err := ent.Open(dialect.SQLite, "file:./db/polaris.db?cache=shared&_fk=1") + os.Mkdir(DataPath, 0777) + client, err := ent.Open(dialect.SQLite, fmt.Sprintf("file:%v/polaris.db?cache=shared&_fk=1", DataPath)) if err != nil { return nil, errors.Wrap(err, "failed opening connection to sqlite") } @@ -72,7 +72,7 @@ func (c *Client) GetLanguage() string { return lang } -func (c *Client) AddWatchlist(storageId int, nameEn string, detail *tmdb.TVDetails, episodes []int, res ResolutionType) (*ent.Series, error) { +func (c *Client) AddWatchlist(storageId int, nameCn, nameEn string, detail *tmdb.TVDetails, episodes []int, res ResolutionType) (*ent.Series, error) { count := c.ent.Series.Query().Where(series.TmdbID(int(detail.ID))).CountX(context.Background()) if count > 0 { return nil, fmt.Errorf("tv series %s already in watchlist", detail.Name) @@ -92,7 +92,7 @@ func (c *Client) AddWatchlist(storageId int, nameEn string, detail *tmdb.TVDetai SetTmdbID(int(detail.ID)). SetStorageID(storageId). SetOverview(detail.Overview). - SetName(detail.Name). + SetNameCn(nameCn). SetNameEn(nameEn). SetOriginalName(detail.OriginalName). SetPosterPath(detail.PosterPath). @@ -320,9 +320,8 @@ func (c *Client) SetDefaultStorageByName(name string) error { return err } - -func (c *Client) SaveHistoryRecord(h ent.History) (*ent.History,error) { - return c.ent.History.Create().SetSeriesID(h.SeriesID).SetEpisodeID(h.EpisodeID).SetDate(time.Now()). +func (c *Client) SaveHistoryRecord(h ent.History) (*ent.History, error) { + return c.ent.History.Create().SetSeriesID(h.SeriesID).SetEpisodeID(h.EpisodeID).SetDate(time.Now()). SetCompleted(h.Completed).SetTargetDir(h.TargetDir).SetSourceTitle(h.SourceTitle).SetSaved(h.Saved).Save(context.TODO()) } @@ -346,22 +345,19 @@ func (c *Client) GetRunningHistories() ent.Histories { return h } - func (c *Client) GetHistory(id int) *ent.History { return c.ent.History.Query().Where(history.ID(id)).FirstX(context.TODO()) } - func (c *Client) DeleteHistory(id int) error { _, err := c.ent.History.Delete().Where(history.ID(id)).Exec(context.Background()) return err } - func (c *Client) GetDownloadDir() string { r, err := c.ent.Settings.Query().Where(settings.Key(SettingDownloadDir)).First(context.TODO()) if err != nil { return "/downloads" } return r.Value -} \ No newline at end of file +} diff --git a/ent/migrate/schema.go b/ent/migrate/schema.go index b0337b6..76cb6e0 100644 --- a/ent/migrate/schema.go +++ b/ent/migrate/schema.go @@ -90,8 +90,8 @@ var ( {Name: "id", Type: field.TypeInt, Increment: true}, {Name: "tmdb_id", Type: field.TypeInt}, {Name: "imdb_id", Type: field.TypeString, Nullable: true}, - {Name: "name", Type: field.TypeString}, - {Name: "name_en", Type: field.TypeString, Nullable: true}, + {Name: "name_cn", Type: field.TypeString}, + {Name: "name_en", Type: field.TypeString}, {Name: "original_name", Type: field.TypeString}, {Name: "overview", Type: field.TypeString}, {Name: "poster_path", Type: field.TypeString, Nullable: true}, diff --git a/ent/mutation.go b/ent/mutation.go index 8362680..5d341f8 100644 --- a/ent/mutation.go +++ b/ent/mutation.go @@ -2974,7 +2974,7 @@ type SeriesMutation struct { tmdb_id *int addtmdb_id *int imdb_id *string - name *string + name_cn *string name_en *string original_name *string overview *string @@ -3196,40 +3196,40 @@ func (m *SeriesMutation) ResetImdbID() { delete(m.clearedFields, series.FieldImdbID) } -// SetName sets the "name" field. -func (m *SeriesMutation) SetName(s string) { - m.name = &s +// SetNameCn sets the "name_cn" field. +func (m *SeriesMutation) SetNameCn(s string) { + m.name_cn = &s } -// Name returns the value of the "name" field in the mutation. -func (m *SeriesMutation) Name() (r string, exists bool) { - v := m.name +// NameCn returns the value of the "name_cn" field in the mutation. +func (m *SeriesMutation) NameCn() (r string, exists bool) { + v := m.name_cn if v == nil { return } return *v, true } -// OldName returns the old "name" field's value of the Series entity. +// OldNameCn returns the old "name_cn" field's value of the Series entity. // If the Series 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 *SeriesMutation) OldName(ctx context.Context) (v string, err error) { +func (m *SeriesMutation) OldNameCn(ctx context.Context) (v string, err error) { if !m.op.Is(OpUpdateOne) { - return v, errors.New("OldName is only allowed on UpdateOne operations") + return v, errors.New("OldNameCn is only allowed on UpdateOne operations") } if m.id == nil || m.oldValue == nil { - return v, errors.New("OldName requires an ID field in the mutation") + return v, errors.New("OldNameCn requires an ID field in the mutation") } oldValue, err := m.oldValue(ctx) if err != nil { - return v, fmt.Errorf("querying old value for OldName: %w", err) + return v, fmt.Errorf("querying old value for OldNameCn: %w", err) } - return oldValue.Name, nil + return oldValue.NameCn, nil } -// ResetName resets all changes to the "name" field. -func (m *SeriesMutation) ResetName() { - m.name = nil +// ResetNameCn resets all changes to the "name_cn" field. +func (m *SeriesMutation) ResetNameCn() { + m.name_cn = nil } // SetNameEn sets the "name_en" field. @@ -3263,22 +3263,9 @@ func (m *SeriesMutation) OldNameEn(ctx context.Context) (v string, err error) { return oldValue.NameEn, nil } -// ClearNameEn clears the value of the "name_en" field. -func (m *SeriesMutation) ClearNameEn() { - m.name_en = nil - m.clearedFields[series.FieldNameEn] = struct{}{} -} - -// NameEnCleared returns if the "name_en" field was cleared in this mutation. -func (m *SeriesMutation) NameEnCleared() bool { - _, ok := m.clearedFields[series.FieldNameEn] - return ok -} - // ResetNameEn resets all changes to the "name_en" field. func (m *SeriesMutation) ResetNameEn() { m.name_en = nil - delete(m.clearedFields, series.FieldNameEn) } // SetOriginalName sets the "original_name" field. @@ -3675,8 +3662,8 @@ func (m *SeriesMutation) Fields() []string { if m.imdb_id != nil { fields = append(fields, series.FieldImdbID) } - if m.name != nil { - fields = append(fields, series.FieldName) + if m.name_cn != nil { + fields = append(fields, series.FieldNameCn) } if m.name_en != nil { fields = append(fields, series.FieldNameEn) @@ -3714,8 +3701,8 @@ func (m *SeriesMutation) Field(name string) (ent.Value, bool) { return m.TmdbID() case series.FieldImdbID: return m.ImdbID() - case series.FieldName: - return m.Name() + case series.FieldNameCn: + return m.NameCn() case series.FieldNameEn: return m.NameEn() case series.FieldOriginalName: @@ -3745,8 +3732,8 @@ func (m *SeriesMutation) OldField(ctx context.Context, name string) (ent.Value, return m.OldTmdbID(ctx) case series.FieldImdbID: return m.OldImdbID(ctx) - case series.FieldName: - return m.OldName(ctx) + case series.FieldNameCn: + return m.OldNameCn(ctx) case series.FieldNameEn: return m.OldNameEn(ctx) case series.FieldOriginalName: @@ -3786,12 +3773,12 @@ func (m *SeriesMutation) SetField(name string, value ent.Value) error { } m.SetImdbID(v) return nil - case series.FieldName: + case series.FieldNameCn: v, ok := value.(string) if !ok { return fmt.Errorf("unexpected type %T for field %s", value, name) } - m.SetName(v) + m.SetNameCn(v) return nil case series.FieldNameEn: v, ok := value.(string) @@ -3909,9 +3896,6 @@ func (m *SeriesMutation) ClearedFields() []string { if m.FieldCleared(series.FieldImdbID) { fields = append(fields, series.FieldImdbID) } - if m.FieldCleared(series.FieldNameEn) { - fields = append(fields, series.FieldNameEn) - } if m.FieldCleared(series.FieldPosterPath) { fields = append(fields, series.FieldPosterPath) } @@ -3935,9 +3919,6 @@ func (m *SeriesMutation) ClearField(name string) error { case series.FieldImdbID: m.ClearImdbID() return nil - case series.FieldNameEn: - m.ClearNameEn() - return nil case series.FieldPosterPath: m.ClearPosterPath() return nil @@ -3958,8 +3939,8 @@ func (m *SeriesMutation) ResetField(name string) error { case series.FieldImdbID: m.ResetImdbID() return nil - case series.FieldName: - m.ResetName() + case series.FieldNameCn: + m.ResetNameCn() return nil case series.FieldNameEn: m.ResetNameEn() diff --git a/ent/schema/series.go b/ent/schema/series.go index 0a3366b..c069ea5 100644 --- a/ent/schema/series.go +++ b/ent/schema/series.go @@ -18,8 +18,8 @@ func (Series) Fields() []ent.Field { return []ent.Field{ field.Int("tmdb_id"), field.String("imdb_id").Optional(), - field.String("name"), - field.String("name_en").Optional(), + field.String("name_cn"), + field.String("name_en"), field.String("original_name"), field.String("overview"), field.String("poster_path").Optional(), diff --git a/ent/series.go b/ent/series.go index cd215ec..03ec556 100644 --- a/ent/series.go +++ b/ent/series.go @@ -21,8 +21,8 @@ type Series struct { TmdbID int `json:"tmdb_id,omitempty"` // ImdbID holds the value of the "imdb_id" field. ImdbID string `json:"imdb_id,omitempty"` - // Name holds the value of the "name" field. - Name string `json:"name,omitempty"` + // NameCn holds the value of the "name_cn" field. + NameCn string `json:"name_cn,omitempty"` // NameEn holds the value of the "name_en" field. NameEn string `json:"name_en,omitempty"` // OriginalName holds the value of the "original_name" field. @@ -70,7 +70,7 @@ func (*Series) scanValues(columns []string) ([]any, error) { switch columns[i] { case series.FieldID, series.FieldTmdbID, series.FieldStorageID: values[i] = new(sql.NullInt64) - case series.FieldImdbID, series.FieldName, series.FieldNameEn, series.FieldOriginalName, series.FieldOverview, series.FieldPosterPath, series.FieldAirDate, series.FieldResolution: + case series.FieldImdbID, series.FieldNameCn, series.FieldNameEn, series.FieldOriginalName, series.FieldOverview, series.FieldPosterPath, series.FieldAirDate, series.FieldResolution: values[i] = new(sql.NullString) case series.FieldCreatedAt: values[i] = new(sql.NullTime) @@ -107,11 +107,11 @@ func (s *Series) assignValues(columns []string, values []any) error { } else if value.Valid { s.ImdbID = value.String } - case series.FieldName: + case series.FieldNameCn: if value, ok := values[i].(*sql.NullString); !ok { - return fmt.Errorf("unexpected type %T for field name", values[i]) + return fmt.Errorf("unexpected type %T for field name_cn", values[i]) } else if value.Valid { - s.Name = value.String + s.NameCn = value.String } case series.FieldNameEn: if value, ok := values[i].(*sql.NullString); !ok { @@ -208,8 +208,8 @@ func (s *Series) String() string { builder.WriteString("imdb_id=") builder.WriteString(s.ImdbID) builder.WriteString(", ") - builder.WriteString("name=") - builder.WriteString(s.Name) + builder.WriteString("name_cn=") + builder.WriteString(s.NameCn) builder.WriteString(", ") builder.WriteString("name_en=") builder.WriteString(s.NameEn) diff --git a/ent/series/series.go b/ent/series/series.go index ff90d1d..6797d38 100644 --- a/ent/series/series.go +++ b/ent/series/series.go @@ -18,8 +18,8 @@ const ( FieldTmdbID = "tmdb_id" // FieldImdbID holds the string denoting the imdb_id field in the database. FieldImdbID = "imdb_id" - // FieldName holds the string denoting the name field in the database. - FieldName = "name" + // FieldNameCn holds the string denoting the name_cn field in the database. + FieldNameCn = "name_cn" // FieldNameEn holds the string denoting the name_en field in the database. FieldNameEn = "name_en" // FieldOriginalName holds the string denoting the original_name field in the database. @@ -54,7 +54,7 @@ var Columns = []string{ FieldID, FieldTmdbID, FieldImdbID, - FieldName, + FieldNameCn, FieldNameEn, FieldOriginalName, FieldOverview, @@ -102,9 +102,9 @@ func ByImdbID(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldImdbID, opts...).ToFunc() } -// ByName orders the results by the name field. -func ByName(opts ...sql.OrderTermOption) OrderOption { - return sql.OrderByField(FieldName, opts...).ToFunc() +// ByNameCn orders the results by the name_cn field. +func ByNameCn(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldNameCn, opts...).ToFunc() } // ByNameEn orders the results by the name_en field. diff --git a/ent/series/where.go b/ent/series/where.go index 969b40f..ef14a67 100644 --- a/ent/series/where.go +++ b/ent/series/where.go @@ -65,9 +65,9 @@ func ImdbID(v string) predicate.Series { return predicate.Series(sql.FieldEQ(FieldImdbID, v)) } -// Name applies equality check predicate on the "name" field. It's identical to NameEQ. -func Name(v string) predicate.Series { - return predicate.Series(sql.FieldEQ(FieldName, v)) +// NameCn applies equality check predicate on the "name_cn" field. It's identical to NameCnEQ. +func NameCn(v string) predicate.Series { + return predicate.Series(sql.FieldEQ(FieldNameCn, v)) } // NameEn applies equality check predicate on the "name_en" field. It's identical to NameEnEQ. @@ -225,69 +225,69 @@ func ImdbIDContainsFold(v string) predicate.Series { return predicate.Series(sql.FieldContainsFold(FieldImdbID, v)) } -// NameEQ applies the EQ predicate on the "name" field. -func NameEQ(v string) predicate.Series { - return predicate.Series(sql.FieldEQ(FieldName, v)) +// NameCnEQ applies the EQ predicate on the "name_cn" field. +func NameCnEQ(v string) predicate.Series { + return predicate.Series(sql.FieldEQ(FieldNameCn, v)) } -// NameNEQ applies the NEQ predicate on the "name" field. -func NameNEQ(v string) predicate.Series { - return predicate.Series(sql.FieldNEQ(FieldName, v)) +// NameCnNEQ applies the NEQ predicate on the "name_cn" field. +func NameCnNEQ(v string) predicate.Series { + return predicate.Series(sql.FieldNEQ(FieldNameCn, v)) } -// NameIn applies the In predicate on the "name" field. -func NameIn(vs ...string) predicate.Series { - return predicate.Series(sql.FieldIn(FieldName, vs...)) +// NameCnIn applies the In predicate on the "name_cn" field. +func NameCnIn(vs ...string) predicate.Series { + return predicate.Series(sql.FieldIn(FieldNameCn, vs...)) } -// NameNotIn applies the NotIn predicate on the "name" field. -func NameNotIn(vs ...string) predicate.Series { - return predicate.Series(sql.FieldNotIn(FieldName, vs...)) +// NameCnNotIn applies the NotIn predicate on the "name_cn" field. +func NameCnNotIn(vs ...string) predicate.Series { + return predicate.Series(sql.FieldNotIn(FieldNameCn, vs...)) } -// NameGT applies the GT predicate on the "name" field. -func NameGT(v string) predicate.Series { - return predicate.Series(sql.FieldGT(FieldName, v)) +// NameCnGT applies the GT predicate on the "name_cn" field. +func NameCnGT(v string) predicate.Series { + return predicate.Series(sql.FieldGT(FieldNameCn, v)) } -// NameGTE applies the GTE predicate on the "name" field. -func NameGTE(v string) predicate.Series { - return predicate.Series(sql.FieldGTE(FieldName, v)) +// NameCnGTE applies the GTE predicate on the "name_cn" field. +func NameCnGTE(v string) predicate.Series { + return predicate.Series(sql.FieldGTE(FieldNameCn, v)) } -// NameLT applies the LT predicate on the "name" field. -func NameLT(v string) predicate.Series { - return predicate.Series(sql.FieldLT(FieldName, v)) +// NameCnLT applies the LT predicate on the "name_cn" field. +func NameCnLT(v string) predicate.Series { + return predicate.Series(sql.FieldLT(FieldNameCn, v)) } -// NameLTE applies the LTE predicate on the "name" field. -func NameLTE(v string) predicate.Series { - return predicate.Series(sql.FieldLTE(FieldName, v)) +// NameCnLTE applies the LTE predicate on the "name_cn" field. +func NameCnLTE(v string) predicate.Series { + return predicate.Series(sql.FieldLTE(FieldNameCn, v)) } -// NameContains applies the Contains predicate on the "name" field. -func NameContains(v string) predicate.Series { - return predicate.Series(sql.FieldContains(FieldName, v)) +// NameCnContains applies the Contains predicate on the "name_cn" field. +func NameCnContains(v string) predicate.Series { + return predicate.Series(sql.FieldContains(FieldNameCn, v)) } -// NameHasPrefix applies the HasPrefix predicate on the "name" field. -func NameHasPrefix(v string) predicate.Series { - return predicate.Series(sql.FieldHasPrefix(FieldName, v)) +// NameCnHasPrefix applies the HasPrefix predicate on the "name_cn" field. +func NameCnHasPrefix(v string) predicate.Series { + return predicate.Series(sql.FieldHasPrefix(FieldNameCn, v)) } -// NameHasSuffix applies the HasSuffix predicate on the "name" field. -func NameHasSuffix(v string) predicate.Series { - return predicate.Series(sql.FieldHasSuffix(FieldName, v)) +// NameCnHasSuffix applies the HasSuffix predicate on the "name_cn" field. +func NameCnHasSuffix(v string) predicate.Series { + return predicate.Series(sql.FieldHasSuffix(FieldNameCn, v)) } -// NameEqualFold applies the EqualFold predicate on the "name" field. -func NameEqualFold(v string) predicate.Series { - return predicate.Series(sql.FieldEqualFold(FieldName, v)) +// NameCnEqualFold applies the EqualFold predicate on the "name_cn" field. +func NameCnEqualFold(v string) predicate.Series { + return predicate.Series(sql.FieldEqualFold(FieldNameCn, v)) } -// NameContainsFold applies the ContainsFold predicate on the "name" field. -func NameContainsFold(v string) predicate.Series { - return predicate.Series(sql.FieldContainsFold(FieldName, v)) +// NameCnContainsFold applies the ContainsFold predicate on the "name_cn" field. +func NameCnContainsFold(v string) predicate.Series { + return predicate.Series(sql.FieldContainsFold(FieldNameCn, v)) } // NameEnEQ applies the EQ predicate on the "name_en" field. @@ -345,16 +345,6 @@ func NameEnHasSuffix(v string) predicate.Series { return predicate.Series(sql.FieldHasSuffix(FieldNameEn, v)) } -// NameEnIsNil applies the IsNil predicate on the "name_en" field. -func NameEnIsNil() predicate.Series { - return predicate.Series(sql.FieldIsNull(FieldNameEn)) -} - -// NameEnNotNil applies the NotNil predicate on the "name_en" field. -func NameEnNotNil() predicate.Series { - return predicate.Series(sql.FieldNotNull(FieldNameEn)) -} - // NameEnEqualFold applies the EqualFold predicate on the "name_en" field. func NameEnEqualFold(v string) predicate.Series { return predicate.Series(sql.FieldEqualFold(FieldNameEn, v)) diff --git a/ent/series_create.go b/ent/series_create.go index 4d564ba..617d51a 100644 --- a/ent/series_create.go +++ b/ent/series_create.go @@ -41,9 +41,9 @@ func (sc *SeriesCreate) SetNillableImdbID(s *string) *SeriesCreate { return sc } -// SetName sets the "name" field. -func (sc *SeriesCreate) SetName(s string) *SeriesCreate { - sc.mutation.SetName(s) +// SetNameCn sets the "name_cn" field. +func (sc *SeriesCreate) SetNameCn(s string) *SeriesCreate { + sc.mutation.SetNameCn(s) return sc } @@ -53,14 +53,6 @@ func (sc *SeriesCreate) SetNameEn(s string) *SeriesCreate { return sc } -// SetNillableNameEn sets the "name_en" field if the given value is not nil. -func (sc *SeriesCreate) SetNillableNameEn(s *string) *SeriesCreate { - if s != nil { - sc.SetNameEn(*s) - } - return sc -} - // SetOriginalName sets the "original_name" field. func (sc *SeriesCreate) SetOriginalName(s string) *SeriesCreate { sc.mutation.SetOriginalName(s) @@ -212,8 +204,11 @@ func (sc *SeriesCreate) check() error { if _, ok := sc.mutation.TmdbID(); !ok { return &ValidationError{Name: "tmdb_id", err: errors.New(`ent: missing required field "Series.tmdb_id"`)} } - if _, ok := sc.mutation.Name(); !ok { - return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Series.name"`)} + if _, ok := sc.mutation.NameCn(); !ok { + return &ValidationError{Name: "name_cn", err: errors.New(`ent: missing required field "Series.name_cn"`)} + } + if _, ok := sc.mutation.NameEn(); !ok { + return &ValidationError{Name: "name_en", err: errors.New(`ent: missing required field "Series.name_en"`)} } if _, ok := sc.mutation.OriginalName(); !ok { return &ValidationError{Name: "original_name", err: errors.New(`ent: missing required field "Series.original_name"`)} @@ -264,9 +259,9 @@ func (sc *SeriesCreate) createSpec() (*Series, *sqlgraph.CreateSpec) { _spec.SetField(series.FieldImdbID, field.TypeString, value) _node.ImdbID = value } - if value, ok := sc.mutation.Name(); ok { - _spec.SetField(series.FieldName, field.TypeString, value) - _node.Name = value + if value, ok := sc.mutation.NameCn(); ok { + _spec.SetField(series.FieldNameCn, field.TypeString, value) + _node.NameCn = value } if value, ok := sc.mutation.NameEn(); ok { _spec.SetField(series.FieldNameEn, field.TypeString, value) diff --git a/ent/series_update.go b/ent/series_update.go index 5bde156..6068d28 100644 --- a/ent/series_update.go +++ b/ent/series_update.go @@ -70,16 +70,16 @@ func (su *SeriesUpdate) ClearImdbID() *SeriesUpdate { return su } -// SetName sets the "name" field. -func (su *SeriesUpdate) SetName(s string) *SeriesUpdate { - su.mutation.SetName(s) +// SetNameCn sets the "name_cn" field. +func (su *SeriesUpdate) SetNameCn(s string) *SeriesUpdate { + su.mutation.SetNameCn(s) return su } -// SetNillableName sets the "name" field if the given value is not nil. -func (su *SeriesUpdate) SetNillableName(s *string) *SeriesUpdate { +// SetNillableNameCn sets the "name_cn" field if the given value is not nil. +func (su *SeriesUpdate) SetNillableNameCn(s *string) *SeriesUpdate { if s != nil { - su.SetName(*s) + su.SetNameCn(*s) } return su } @@ -98,12 +98,6 @@ func (su *SeriesUpdate) SetNillableNameEn(s *string) *SeriesUpdate { return su } -// ClearNameEn clears the value of the "name_en" field. -func (su *SeriesUpdate) ClearNameEn() *SeriesUpdate { - su.mutation.ClearNameEn() - return su -} - // SetOriginalName sets the "original_name" field. func (su *SeriesUpdate) SetOriginalName(s string) *SeriesUpdate { su.mutation.SetOriginalName(s) @@ -310,15 +304,12 @@ func (su *SeriesUpdate) sqlSave(ctx context.Context) (n int, err error) { if su.mutation.ImdbIDCleared() { _spec.ClearField(series.FieldImdbID, field.TypeString) } - if value, ok := su.mutation.Name(); ok { - _spec.SetField(series.FieldName, field.TypeString, value) + if value, ok := su.mutation.NameCn(); ok { + _spec.SetField(series.FieldNameCn, field.TypeString, value) } if value, ok := su.mutation.NameEn(); ok { _spec.SetField(series.FieldNameEn, field.TypeString, value) } - if su.mutation.NameEnCleared() { - _spec.ClearField(series.FieldNameEn, field.TypeString) - } if value, ok := su.mutation.OriginalName(); ok { _spec.SetField(series.FieldOriginalName, field.TypeString, value) } @@ -455,16 +446,16 @@ func (suo *SeriesUpdateOne) ClearImdbID() *SeriesUpdateOne { return suo } -// SetName sets the "name" field. -func (suo *SeriesUpdateOne) SetName(s string) *SeriesUpdateOne { - suo.mutation.SetName(s) +// SetNameCn sets the "name_cn" field. +func (suo *SeriesUpdateOne) SetNameCn(s string) *SeriesUpdateOne { + suo.mutation.SetNameCn(s) return suo } -// SetNillableName sets the "name" field if the given value is not nil. -func (suo *SeriesUpdateOne) SetNillableName(s *string) *SeriesUpdateOne { +// SetNillableNameCn sets the "name_cn" field if the given value is not nil. +func (suo *SeriesUpdateOne) SetNillableNameCn(s *string) *SeriesUpdateOne { if s != nil { - suo.SetName(*s) + suo.SetNameCn(*s) } return suo } @@ -483,12 +474,6 @@ func (suo *SeriesUpdateOne) SetNillableNameEn(s *string) *SeriesUpdateOne { return suo } -// ClearNameEn clears the value of the "name_en" field. -func (suo *SeriesUpdateOne) ClearNameEn() *SeriesUpdateOne { - suo.mutation.ClearNameEn() - return suo -} - // SetOriginalName sets the "original_name" field. func (suo *SeriesUpdateOne) SetOriginalName(s string) *SeriesUpdateOne { suo.mutation.SetOriginalName(s) @@ -725,15 +710,12 @@ func (suo *SeriesUpdateOne) sqlSave(ctx context.Context) (_node *Series, err err if suo.mutation.ImdbIDCleared() { _spec.ClearField(series.FieldImdbID, field.TypeString) } - if value, ok := suo.mutation.Name(); ok { - _spec.SetField(series.FieldName, field.TypeString, value) + if value, ok := suo.mutation.NameCn(); ok { + _spec.SetField(series.FieldNameCn, field.TypeString, value) } if value, ok := suo.mutation.NameEn(); ok { _spec.SetField(series.FieldNameEn, field.TypeString, value) } - if suo.mutation.NameEnCleared() { - _spec.ClearField(series.FieldNameEn, field.TypeString) - } if value, ok := suo.mutation.OriginalName(); ok { _spec.SetField(series.FieldOriginalName, field.TypeString, value) } diff --git a/go.sum b/go.sum index 5d6d98a..65ae838 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,8 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= @@ -100,6 +102,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -123,6 +127,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= @@ -169,6 +175,8 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -180,6 +188,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/server/server.go b/server/server.go index a7a64f3..ab80069 100644 --- a/server/server.go +++ b/server/server.go @@ -1,6 +1,7 @@ package server import ( + "net/http" "polaris/db" "polaris/log" "polaris/pkg/tmdb" @@ -42,6 +43,7 @@ func (s *Server) Serve() error { api := s.r.Group("/api/v1") api.Use(s.authModdleware) + api.StaticFS("/img", http.Dir(db.ImgPath)) setting := api.Group("/setting") { diff --git a/server/watchlist.go b/server/watchlist.go index a9b8eb2..d94bc1a 100644 --- a/server/watchlist.go +++ b/server/watchlist.go @@ -1,11 +1,17 @@ package server import ( + "fmt" + "io" + "net/http" + "os" + "path/filepath" "polaris/db" "polaris/ent" "polaris/log" "strconv" + tmdb "github.com/cyruzin/golang-tmdb" "github.com/gin-gonic/gin" "github.com/pkg/errors" ) @@ -38,13 +44,21 @@ func (s *Server) AddWatchlist(c *gin.Context) (interface{}, error) { if err := c.ShouldBindJSON(&in); err != nil { return nil, errors.Wrap(err, "bind query") } - detail, err := s.MustTMDB().GetTvDetails(in.TmdbID, s.language) + detailCn, err := s.MustTMDB().GetTvDetails(in.TmdbID, db.LanguageCN) if err != nil { return nil, errors.Wrap(err, "get tv detail") } - log.Infof("find detail for tv id %d: %v", in.TmdbID, detail) - detailEn, _ := s.MustTMDB().GetTvDetails(in.TmdbID, "en-US") + var nameCn = detailCn.Name + + detailEn, _ := s.MustTMDB().GetTvDetails(in.TmdbID, db.LanguageEN) var nameEn = detailEn.Name + var detail *tmdb.TVDetails + if s.language == "" || s.language ==db.LanguageCN { + detail = detailCn + } else { + detail = detailEn + } + log.Infof("find detail for tv id %d: %v", in.TmdbID, detail) var epIds []int for _, season := range detail.Seasons { @@ -69,15 +83,45 @@ func (s *Server) AddWatchlist(c *gin.Context) (interface{}, error) { epIds = append(epIds, epid) } } - _, err = s.db.AddWatchlist(in.StorageID, nameEn, detail, epIds, db.R1080p) + r, err := s.db.AddWatchlist(in.StorageID, nameCn, nameEn, detail, epIds, db.R1080p) if err != nil { return nil, errors.Wrap(err, "add to list") } + go func () { + if err := s.downloadPoster(detail.PosterPath, r.ID); err != nil { + log.Errorf("download poster error: %v", err) + } + }() log.Infof("add tv %s to watchlist success", detail.Name) return nil, nil } +func (s *Server) downloadPoster(path string, seriesId int) error{ + var tmdbImgBaseUrl = "https://image.tmdb.org/t/p/w500/" + url := tmdbImgBaseUrl + path + log.Infof("try to download poster: %v", url) + var resp, err = http.Get(url) + if err != nil { + return errors.Wrap(err, "http get") + } + targetDir := fmt.Sprintf("%v/%d", db.ImgPath, seriesId) + os.MkdirAll(targetDir, 0777) + ext := filepath.Ext(path) + targetFile := filepath.Join(targetDir, "poster"+ ext) + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrap(err, "new file") + } + defer f.Close() + _, err = io.Copy(f, resp.Body) + if err != nil { + return errors.Wrap(err, "copy http response") + } + log.Infof("poster successfully downlaoded: %v", targetFile) + return nil +} + func (s *Server) GetWatchlist(c *gin.Context) (interface{}, error) { list := s.db.GetWatchlist() return list, nil diff --git a/ui/lib/main.dart b/ui/lib/main.dart index 95b8b90..49d2c7b 100644 --- a/ui/lib/main.dart +++ b/ui/lib/main.dart @@ -12,14 +12,11 @@ import 'package:ui/tv_details.dart'; import 'package:ui/weclome.dart'; void main() { - runApp(MyApp()); + runApp(const MyApp()); } class MyApp extends StatelessWidget { - final GlobalKey _rootNavigatorKey = - GlobalKey(); - - MyApp({super.key}); + const MyApp({super.key}); // This widget is the root of your application. @override diff --git a/ui/lib/providers/APIs.dart b/ui/lib/providers/APIs.dart index f266d2e..dd1f855 100644 --- a/ui/lib/providers/APIs.dart +++ b/ui/lib/providers/APIs.dart @@ -21,6 +21,7 @@ class APIs { static final loginUrl = "$_baseUrl/api/login"; static final loginSettingUrl = "$_baseUrl/api/v1/setting/auth"; static final activityUrl = "$_baseUrl/api/v1/activity/"; + static final imagesUrl = "$_baseUrl/api/v1/img"; static const tmdbImgBaseUrl = "https://image.tmdb.org/t/p/w500/"; diff --git a/ui/lib/providers/series_details.dart b/ui/lib/providers/series_details.dart index eca56d7..c5411bf 100644 --- a/ui/lib/providers/series_details.dart +++ b/ui/lib/providers/series_details.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:dio/dio.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:ui/providers/APIs.dart'; import 'package:ui/providers/server_response.dart'; @@ -74,7 +73,7 @@ class SeriesDetails { SeriesDetails.fromJson(Map json) { id = json['id']; tmdbId = json['tmdb_id']; - name = json['name']; + name = json['name_cn']; originalName = json['original_name']; overview = json['overview']; path = json['path']; diff --git a/ui/lib/providers/welcome_data.dart b/ui/lib/providers/welcome_data.dart index ce3e34c..0047f10 100644 --- a/ui/lib/providers/welcome_data.dart +++ b/ui/lib/providers/welcome_data.dart @@ -133,7 +133,7 @@ class TvSeries { TvSeries.fromJson(Map json) { id = json['id']; tmdbId = json['tmdb_id']; - name = json['name']; + name = json['name_cn']; originalName = json['original_name']; overview = json['overview']; path = json['path']; diff --git a/ui/lib/tv_details.dart b/ui/lib/tv_details.dart index b729526..3fe73ee 100644 --- a/ui/lib/tv_details.dart +++ b/ui/lib/tv_details.dart @@ -110,7 +110,7 @@ class _TvDetailsPageState extends ConsumerState { width: 150, height: 200, child: Image.network( - APIs.tmdbImgBaseUrl + details!.posterPath!, + "${APIs.imagesUrl}/${details.id}/poster.jpg", fit: BoxFit.contain, ), ), diff --git a/ui/lib/weclome.dart b/ui/lib/weclome.dart index ed9ce2c..072e6f5 100644 --- a/ui/lib/weclome.dart +++ b/ui/lib/weclome.dart @@ -36,7 +36,7 @@ class WelcomePage extends ConsumerWidget { children: [ Flexible( child: Image.network( - APIs.tmdbImgBaseUrl + item.posterPath!, + "${APIs.imagesUrl}/${item.id}/poster.jpg" , fit: BoxFit.contain, ), ), diff --git a/ui/web/index.html b/ui/web/index.html index 30c5389..3567ab6 100644 --- a/ui/web/index.html +++ b/ui/web/index.html @@ -23,13 +23,13 @@ - + - ui + Polaris