mirror of
https://github.com/simon-ding/polaris.git
synced 2026-06-09 03:27:39 +08:00
feat: code refactor and support season pack write .plexmatch file
This commit is contained in:
8
db/db.go
8
db/db.go
@@ -571,3 +571,11 @@ func (c *Client) EditMediaMetadata(in EditMediaData) error {
|
|||||||
return c.ent.Media.Update().Where(media.ID(in.ID)).SetResolution(in.Resolution).SetTargetDir(in.TargetDir).SetLimiter(in.Limiter).
|
return c.ent.Media.Update().Where(media.ID(in.ID)).SetResolution(in.Resolution).SetTargetDir(in.TargetDir).SetLimiter(in.Limiter).
|
||||||
Exec(context.Background())
|
Exec(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) UpdateEpisodeTargetFile(id int, filename string) error {
|
||||||
|
return c.ent.Episode.Update().Where(episode.ID(id)).SetTargetFile(filename).Exec(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetSeasonEpisodes(mediaId, seasonNum int) ([]*ent.Episode, error) {
|
||||||
|
return c.ent.Episode.Query().Where(episode.MediaID(mediaId), episode.SeasonNumber(seasonNum)).All(context.Background())
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ type Episode struct {
|
|||||||
Status episode.Status `json:"status,omitempty"`
|
Status episode.Status `json:"status,omitempty"`
|
||||||
// Monitored holds the value of the "monitored" field.
|
// Monitored holds the value of the "monitored" field.
|
||||||
Monitored bool `json:"monitored"`
|
Monitored bool `json:"monitored"`
|
||||||
|
// TargetFile holds the value of the "target_file" field.
|
||||||
|
TargetFile string `json:"target_file,omitempty"`
|
||||||
// Edges holds the relations/edges for other nodes in the graph.
|
// Edges holds the relations/edges for other nodes in the graph.
|
||||||
// The values are being populated by the EpisodeQuery when eager-loading is set.
|
// The values are being populated by the EpisodeQuery when eager-loading is set.
|
||||||
Edges EpisodeEdges `json:"edges"`
|
Edges EpisodeEdges `json:"edges"`
|
||||||
@@ -68,7 +70,7 @@ func (*Episode) scanValues(columns []string) ([]any, error) {
|
|||||||
values[i] = new(sql.NullBool)
|
values[i] = new(sql.NullBool)
|
||||||
case episode.FieldID, episode.FieldMediaID, episode.FieldSeasonNumber, episode.FieldEpisodeNumber:
|
case episode.FieldID, episode.FieldMediaID, episode.FieldSeasonNumber, episode.FieldEpisodeNumber:
|
||||||
values[i] = new(sql.NullInt64)
|
values[i] = new(sql.NullInt64)
|
||||||
case episode.FieldTitle, episode.FieldOverview, episode.FieldAirDate, episode.FieldStatus:
|
case episode.FieldTitle, episode.FieldOverview, episode.FieldAirDate, episode.FieldStatus, episode.FieldTargetFile:
|
||||||
values[i] = new(sql.NullString)
|
values[i] = new(sql.NullString)
|
||||||
default:
|
default:
|
||||||
values[i] = new(sql.UnknownType)
|
values[i] = new(sql.UnknownType)
|
||||||
@@ -139,6 +141,12 @@ func (e *Episode) assignValues(columns []string, values []any) error {
|
|||||||
} else if value.Valid {
|
} else if value.Valid {
|
||||||
e.Monitored = value.Bool
|
e.Monitored = value.Bool
|
||||||
}
|
}
|
||||||
|
case episode.FieldTargetFile:
|
||||||
|
if value, ok := values[i].(*sql.NullString); !ok {
|
||||||
|
return fmt.Errorf("unexpected type %T for field target_file", values[i])
|
||||||
|
} else if value.Valid {
|
||||||
|
e.TargetFile = value.String
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
e.selectValues.Set(columns[i], values[i])
|
e.selectValues.Set(columns[i], values[i])
|
||||||
}
|
}
|
||||||
@@ -203,6 +211,9 @@ func (e *Episode) String() string {
|
|||||||
builder.WriteString(", ")
|
builder.WriteString(", ")
|
||||||
builder.WriteString("monitored=")
|
builder.WriteString("monitored=")
|
||||||
builder.WriteString(fmt.Sprintf("%v", e.Monitored))
|
builder.WriteString(fmt.Sprintf("%v", e.Monitored))
|
||||||
|
builder.WriteString(", ")
|
||||||
|
builder.WriteString("target_file=")
|
||||||
|
builder.WriteString(e.TargetFile)
|
||||||
builder.WriteByte(')')
|
builder.WriteByte(')')
|
||||||
return builder.String()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ const (
|
|||||||
FieldStatus = "status"
|
FieldStatus = "status"
|
||||||
// FieldMonitored holds the string denoting the monitored field in the database.
|
// FieldMonitored holds the string denoting the monitored field in the database.
|
||||||
FieldMonitored = "monitored"
|
FieldMonitored = "monitored"
|
||||||
|
// FieldTargetFile holds the string denoting the target_file field in the database.
|
||||||
|
FieldTargetFile = "target_file"
|
||||||
// EdgeMedia holds the string denoting the media edge name in mutations.
|
// EdgeMedia holds the string denoting the media edge name in mutations.
|
||||||
EdgeMedia = "media"
|
EdgeMedia = "media"
|
||||||
// Table holds the table name of the episode in the database.
|
// Table holds the table name of the episode in the database.
|
||||||
@@ -54,6 +56,7 @@ var Columns = []string{
|
|||||||
FieldAirDate,
|
FieldAirDate,
|
||||||
FieldStatus,
|
FieldStatus,
|
||||||
FieldMonitored,
|
FieldMonitored,
|
||||||
|
FieldTargetFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidColumn reports if the column name is valid (part of the table columns).
|
// ValidColumn reports if the column name is valid (part of the table columns).
|
||||||
@@ -146,6 +149,11 @@ func ByMonitored(opts ...sql.OrderTermOption) OrderOption {
|
|||||||
return sql.OrderByField(FieldMonitored, opts...).ToFunc()
|
return sql.OrderByField(FieldMonitored, opts...).ToFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ByTargetFile orders the results by the target_file field.
|
||||||
|
func ByTargetFile(opts ...sql.OrderTermOption) OrderOption {
|
||||||
|
return sql.OrderByField(FieldTargetFile, opts...).ToFunc()
|
||||||
|
}
|
||||||
|
|
||||||
// ByMediaField orders the results by media field.
|
// ByMediaField orders the results by media field.
|
||||||
func ByMediaField(field string, opts ...sql.OrderTermOption) OrderOption {
|
func ByMediaField(field string, opts ...sql.OrderTermOption) OrderOption {
|
||||||
return func(s *sql.Selector) {
|
return func(s *sql.Selector) {
|
||||||
|
|||||||
@@ -89,6 +89,11 @@ func Monitored(v bool) predicate.Episode {
|
|||||||
return predicate.Episode(sql.FieldEQ(FieldMonitored, v))
|
return predicate.Episode(sql.FieldEQ(FieldMonitored, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TargetFile applies equality check predicate on the "target_file" field. It's identical to TargetFileEQ.
|
||||||
|
func TargetFile(v string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldEQ(FieldTargetFile, v))
|
||||||
|
}
|
||||||
|
|
||||||
// MediaIDEQ applies the EQ predicate on the "media_id" field.
|
// MediaIDEQ applies the EQ predicate on the "media_id" field.
|
||||||
func MediaIDEQ(v int) predicate.Episode {
|
func MediaIDEQ(v int) predicate.Episode {
|
||||||
return predicate.Episode(sql.FieldEQ(FieldMediaID, v))
|
return predicate.Episode(sql.FieldEQ(FieldMediaID, v))
|
||||||
@@ -424,6 +429,81 @@ func MonitoredNEQ(v bool) predicate.Episode {
|
|||||||
return predicate.Episode(sql.FieldNEQ(FieldMonitored, v))
|
return predicate.Episode(sql.FieldNEQ(FieldMonitored, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TargetFileEQ applies the EQ predicate on the "target_file" field.
|
||||||
|
func TargetFileEQ(v string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldEQ(FieldTargetFile, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileNEQ applies the NEQ predicate on the "target_file" field.
|
||||||
|
func TargetFileNEQ(v string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldNEQ(FieldTargetFile, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileIn applies the In predicate on the "target_file" field.
|
||||||
|
func TargetFileIn(vs ...string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldIn(FieldTargetFile, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileNotIn applies the NotIn predicate on the "target_file" field.
|
||||||
|
func TargetFileNotIn(vs ...string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldNotIn(FieldTargetFile, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileGT applies the GT predicate on the "target_file" field.
|
||||||
|
func TargetFileGT(v string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldGT(FieldTargetFile, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileGTE applies the GTE predicate on the "target_file" field.
|
||||||
|
func TargetFileGTE(v string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldGTE(FieldTargetFile, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileLT applies the LT predicate on the "target_file" field.
|
||||||
|
func TargetFileLT(v string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldLT(FieldTargetFile, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileLTE applies the LTE predicate on the "target_file" field.
|
||||||
|
func TargetFileLTE(v string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldLTE(FieldTargetFile, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileContains applies the Contains predicate on the "target_file" field.
|
||||||
|
func TargetFileContains(v string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldContains(FieldTargetFile, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileHasPrefix applies the HasPrefix predicate on the "target_file" field.
|
||||||
|
func TargetFileHasPrefix(v string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldHasPrefix(FieldTargetFile, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileHasSuffix applies the HasSuffix predicate on the "target_file" field.
|
||||||
|
func TargetFileHasSuffix(v string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldHasSuffix(FieldTargetFile, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileIsNil applies the IsNil predicate on the "target_file" field.
|
||||||
|
func TargetFileIsNil() predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldIsNull(FieldTargetFile))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileNotNil applies the NotNil predicate on the "target_file" field.
|
||||||
|
func TargetFileNotNil() predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldNotNull(FieldTargetFile))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileEqualFold applies the EqualFold predicate on the "target_file" field.
|
||||||
|
func TargetFileEqualFold(v string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldEqualFold(FieldTargetFile, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileContainsFold applies the ContainsFold predicate on the "target_file" field.
|
||||||
|
func TargetFileContainsFold(v string) predicate.Episode {
|
||||||
|
return predicate.Episode(sql.FieldContainsFold(FieldTargetFile, v))
|
||||||
|
}
|
||||||
|
|
||||||
// HasMedia applies the HasEdge predicate on the "media" edge.
|
// HasMedia applies the HasEdge predicate on the "media" edge.
|
||||||
func HasMedia() predicate.Episode {
|
func HasMedia() predicate.Episode {
|
||||||
return predicate.Episode(func(s *sql.Selector) {
|
return predicate.Episode(func(s *sql.Selector) {
|
||||||
|
|||||||
@@ -92,6 +92,20 @@ func (ec *EpisodeCreate) SetNillableMonitored(b *bool) *EpisodeCreate {
|
|||||||
return ec
|
return ec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTargetFile sets the "target_file" field.
|
||||||
|
func (ec *EpisodeCreate) SetTargetFile(s string) *EpisodeCreate {
|
||||||
|
ec.mutation.SetTargetFile(s)
|
||||||
|
return ec
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableTargetFile sets the "target_file" field if the given value is not nil.
|
||||||
|
func (ec *EpisodeCreate) SetNillableTargetFile(s *string) *EpisodeCreate {
|
||||||
|
if s != nil {
|
||||||
|
ec.SetTargetFile(*s)
|
||||||
|
}
|
||||||
|
return ec
|
||||||
|
}
|
||||||
|
|
||||||
// SetMedia sets the "media" edge to the Media entity.
|
// SetMedia sets the "media" edge to the Media entity.
|
||||||
func (ec *EpisodeCreate) SetMedia(m *Media) *EpisodeCreate {
|
func (ec *EpisodeCreate) SetMedia(m *Media) *EpisodeCreate {
|
||||||
return ec.SetMediaID(m.ID)
|
return ec.SetMediaID(m.ID)
|
||||||
@@ -224,6 +238,10 @@ func (ec *EpisodeCreate) createSpec() (*Episode, *sqlgraph.CreateSpec) {
|
|||||||
_spec.SetField(episode.FieldMonitored, field.TypeBool, value)
|
_spec.SetField(episode.FieldMonitored, field.TypeBool, value)
|
||||||
_node.Monitored = value
|
_node.Monitored = value
|
||||||
}
|
}
|
||||||
|
if value, ok := ec.mutation.TargetFile(); ok {
|
||||||
|
_spec.SetField(episode.FieldTargetFile, field.TypeString, value)
|
||||||
|
_node.TargetFile = value
|
||||||
|
}
|
||||||
if nodes := ec.mutation.MediaIDs(); len(nodes) > 0 {
|
if nodes := ec.mutation.MediaIDs(); len(nodes) > 0 {
|
||||||
edge := &sqlgraph.EdgeSpec{
|
edge := &sqlgraph.EdgeSpec{
|
||||||
Rel: sqlgraph.M2O,
|
Rel: sqlgraph.M2O,
|
||||||
|
|||||||
@@ -160,6 +160,26 @@ func (eu *EpisodeUpdate) SetNillableMonitored(b *bool) *EpisodeUpdate {
|
|||||||
return eu
|
return eu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTargetFile sets the "target_file" field.
|
||||||
|
func (eu *EpisodeUpdate) SetTargetFile(s string) *EpisodeUpdate {
|
||||||
|
eu.mutation.SetTargetFile(s)
|
||||||
|
return eu
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableTargetFile sets the "target_file" field if the given value is not nil.
|
||||||
|
func (eu *EpisodeUpdate) SetNillableTargetFile(s *string) *EpisodeUpdate {
|
||||||
|
if s != nil {
|
||||||
|
eu.SetTargetFile(*s)
|
||||||
|
}
|
||||||
|
return eu
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearTargetFile clears the value of the "target_file" field.
|
||||||
|
func (eu *EpisodeUpdate) ClearTargetFile() *EpisodeUpdate {
|
||||||
|
eu.mutation.ClearTargetFile()
|
||||||
|
return eu
|
||||||
|
}
|
||||||
|
|
||||||
// SetMedia sets the "media" edge to the Media entity.
|
// SetMedia sets the "media" edge to the Media entity.
|
||||||
func (eu *EpisodeUpdate) SetMedia(m *Media) *EpisodeUpdate {
|
func (eu *EpisodeUpdate) SetMedia(m *Media) *EpisodeUpdate {
|
||||||
return eu.SetMediaID(m.ID)
|
return eu.SetMediaID(m.ID)
|
||||||
@@ -252,6 +272,12 @@ func (eu *EpisodeUpdate) sqlSave(ctx context.Context) (n int, err error) {
|
|||||||
if value, ok := eu.mutation.Monitored(); ok {
|
if value, ok := eu.mutation.Monitored(); ok {
|
||||||
_spec.SetField(episode.FieldMonitored, field.TypeBool, value)
|
_spec.SetField(episode.FieldMonitored, field.TypeBool, value)
|
||||||
}
|
}
|
||||||
|
if value, ok := eu.mutation.TargetFile(); ok {
|
||||||
|
_spec.SetField(episode.FieldTargetFile, field.TypeString, value)
|
||||||
|
}
|
||||||
|
if eu.mutation.TargetFileCleared() {
|
||||||
|
_spec.ClearField(episode.FieldTargetFile, field.TypeString)
|
||||||
|
}
|
||||||
if eu.mutation.MediaCleared() {
|
if eu.mutation.MediaCleared() {
|
||||||
edge := &sqlgraph.EdgeSpec{
|
edge := &sqlgraph.EdgeSpec{
|
||||||
Rel: sqlgraph.M2O,
|
Rel: sqlgraph.M2O,
|
||||||
@@ -433,6 +459,26 @@ func (euo *EpisodeUpdateOne) SetNillableMonitored(b *bool) *EpisodeUpdateOne {
|
|||||||
return euo
|
return euo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTargetFile sets the "target_file" field.
|
||||||
|
func (euo *EpisodeUpdateOne) SetTargetFile(s string) *EpisodeUpdateOne {
|
||||||
|
euo.mutation.SetTargetFile(s)
|
||||||
|
return euo
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableTargetFile sets the "target_file" field if the given value is not nil.
|
||||||
|
func (euo *EpisodeUpdateOne) SetNillableTargetFile(s *string) *EpisodeUpdateOne {
|
||||||
|
if s != nil {
|
||||||
|
euo.SetTargetFile(*s)
|
||||||
|
}
|
||||||
|
return euo
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearTargetFile clears the value of the "target_file" field.
|
||||||
|
func (euo *EpisodeUpdateOne) ClearTargetFile() *EpisodeUpdateOne {
|
||||||
|
euo.mutation.ClearTargetFile()
|
||||||
|
return euo
|
||||||
|
}
|
||||||
|
|
||||||
// SetMedia sets the "media" edge to the Media entity.
|
// SetMedia sets the "media" edge to the Media entity.
|
||||||
func (euo *EpisodeUpdateOne) SetMedia(m *Media) *EpisodeUpdateOne {
|
func (euo *EpisodeUpdateOne) SetMedia(m *Media) *EpisodeUpdateOne {
|
||||||
return euo.SetMediaID(m.ID)
|
return euo.SetMediaID(m.ID)
|
||||||
@@ -555,6 +601,12 @@ func (euo *EpisodeUpdateOne) sqlSave(ctx context.Context) (_node *Episode, err e
|
|||||||
if value, ok := euo.mutation.Monitored(); ok {
|
if value, ok := euo.mutation.Monitored(); ok {
|
||||||
_spec.SetField(episode.FieldMonitored, field.TypeBool, value)
|
_spec.SetField(episode.FieldMonitored, field.TypeBool, value)
|
||||||
}
|
}
|
||||||
|
if value, ok := euo.mutation.TargetFile(); ok {
|
||||||
|
_spec.SetField(episode.FieldTargetFile, field.TypeString, value)
|
||||||
|
}
|
||||||
|
if euo.mutation.TargetFileCleared() {
|
||||||
|
_spec.ClearField(episode.FieldTargetFile, field.TypeString)
|
||||||
|
}
|
||||||
if euo.mutation.MediaCleared() {
|
if euo.mutation.MediaCleared() {
|
||||||
edge := &sqlgraph.EdgeSpec{
|
edge := &sqlgraph.EdgeSpec{
|
||||||
Rel: sqlgraph.M2O,
|
Rel: sqlgraph.M2O,
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ var (
|
|||||||
{Name: "air_date", Type: field.TypeString},
|
{Name: "air_date", Type: field.TypeString},
|
||||||
{Name: "status", Type: field.TypeEnum, Enums: []string{"missing", "downloading", "downloaded"}, Default: "missing"},
|
{Name: "status", Type: field.TypeEnum, Enums: []string{"missing", "downloading", "downloaded"}, Default: "missing"},
|
||||||
{Name: "monitored", Type: field.TypeBool, Default: false},
|
{Name: "monitored", Type: field.TypeBool, Default: false},
|
||||||
|
{Name: "target_file", Type: field.TypeString, Nullable: true},
|
||||||
{Name: "media_id", Type: field.TypeInt, Nullable: true},
|
{Name: "media_id", Type: field.TypeInt, Nullable: true},
|
||||||
}
|
}
|
||||||
// EpisodesTable holds the schema information for the "episodes" table.
|
// EpisodesTable holds the schema information for the "episodes" table.
|
||||||
@@ -49,7 +50,7 @@ var (
|
|||||||
ForeignKeys: []*schema.ForeignKey{
|
ForeignKeys: []*schema.ForeignKey{
|
||||||
{
|
{
|
||||||
Symbol: "episodes_media_episodes",
|
Symbol: "episodes_media_episodes",
|
||||||
Columns: []*schema.Column{EpisodesColumns[8]},
|
Columns: []*schema.Column{EpisodesColumns[9]},
|
||||||
RefColumns: []*schema.Column{MediaColumns[0]},
|
RefColumns: []*schema.Column{MediaColumns[0]},
|
||||||
OnDelete: schema.SetNull,
|
OnDelete: schema.SetNull,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -923,6 +923,7 @@ type EpisodeMutation struct {
|
|||||||
air_date *string
|
air_date *string
|
||||||
status *episode.Status
|
status *episode.Status
|
||||||
monitored *bool
|
monitored *bool
|
||||||
|
target_file *string
|
||||||
clearedFields map[string]struct{}
|
clearedFields map[string]struct{}
|
||||||
media *int
|
media *int
|
||||||
clearedmedia bool
|
clearedmedia bool
|
||||||
@@ -1370,6 +1371,55 @@ func (m *EpisodeMutation) ResetMonitored() {
|
|||||||
m.monitored = nil
|
m.monitored = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTargetFile sets the "target_file" field.
|
||||||
|
func (m *EpisodeMutation) SetTargetFile(s string) {
|
||||||
|
m.target_file = &s
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFile returns the value of the "target_file" field in the mutation.
|
||||||
|
func (m *EpisodeMutation) TargetFile() (r string, exists bool) {
|
||||||
|
v := m.target_file
|
||||||
|
if v == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return *v, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// OldTargetFile returns the old "target_file" field's value of the Episode entity.
|
||||||
|
// If the Episode 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 *EpisodeMutation) OldTargetFile(ctx context.Context) (v string, err error) {
|
||||||
|
if !m.op.Is(OpUpdateOne) {
|
||||||
|
return v, errors.New("OldTargetFile is only allowed on UpdateOne operations")
|
||||||
|
}
|
||||||
|
if m.id == nil || m.oldValue == nil {
|
||||||
|
return v, errors.New("OldTargetFile requires an ID field in the mutation")
|
||||||
|
}
|
||||||
|
oldValue, err := m.oldValue(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return v, fmt.Errorf("querying old value for OldTargetFile: %w", err)
|
||||||
|
}
|
||||||
|
return oldValue.TargetFile, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearTargetFile clears the value of the "target_file" field.
|
||||||
|
func (m *EpisodeMutation) ClearTargetFile() {
|
||||||
|
m.target_file = nil
|
||||||
|
m.clearedFields[episode.FieldTargetFile] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetFileCleared returns if the "target_file" field was cleared in this mutation.
|
||||||
|
func (m *EpisodeMutation) TargetFileCleared() bool {
|
||||||
|
_, ok := m.clearedFields[episode.FieldTargetFile]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetTargetFile resets all changes to the "target_file" field.
|
||||||
|
func (m *EpisodeMutation) ResetTargetFile() {
|
||||||
|
m.target_file = nil
|
||||||
|
delete(m.clearedFields, episode.FieldTargetFile)
|
||||||
|
}
|
||||||
|
|
||||||
// ClearMedia clears the "media" edge to the Media entity.
|
// ClearMedia clears the "media" edge to the Media entity.
|
||||||
func (m *EpisodeMutation) ClearMedia() {
|
func (m *EpisodeMutation) ClearMedia() {
|
||||||
m.clearedmedia = true
|
m.clearedmedia = true
|
||||||
@@ -1431,7 +1481,7 @@ func (m *EpisodeMutation) Type() string {
|
|||||||
// order to get all numeric fields that were incremented/decremented, call
|
// order to get all numeric fields that were incremented/decremented, call
|
||||||
// AddedFields().
|
// AddedFields().
|
||||||
func (m *EpisodeMutation) Fields() []string {
|
func (m *EpisodeMutation) Fields() []string {
|
||||||
fields := make([]string, 0, 8)
|
fields := make([]string, 0, 9)
|
||||||
if m.media != nil {
|
if m.media != nil {
|
||||||
fields = append(fields, episode.FieldMediaID)
|
fields = append(fields, episode.FieldMediaID)
|
||||||
}
|
}
|
||||||
@@ -1456,6 +1506,9 @@ func (m *EpisodeMutation) Fields() []string {
|
|||||||
if m.monitored != nil {
|
if m.monitored != nil {
|
||||||
fields = append(fields, episode.FieldMonitored)
|
fields = append(fields, episode.FieldMonitored)
|
||||||
}
|
}
|
||||||
|
if m.target_file != nil {
|
||||||
|
fields = append(fields, episode.FieldTargetFile)
|
||||||
|
}
|
||||||
return fields
|
return fields
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1480,6 +1533,8 @@ func (m *EpisodeMutation) Field(name string) (ent.Value, bool) {
|
|||||||
return m.Status()
|
return m.Status()
|
||||||
case episode.FieldMonitored:
|
case episode.FieldMonitored:
|
||||||
return m.Monitored()
|
return m.Monitored()
|
||||||
|
case episode.FieldTargetFile:
|
||||||
|
return m.TargetFile()
|
||||||
}
|
}
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
@@ -1505,6 +1560,8 @@ func (m *EpisodeMutation) OldField(ctx context.Context, name string) (ent.Value,
|
|||||||
return m.OldStatus(ctx)
|
return m.OldStatus(ctx)
|
||||||
case episode.FieldMonitored:
|
case episode.FieldMonitored:
|
||||||
return m.OldMonitored(ctx)
|
return m.OldMonitored(ctx)
|
||||||
|
case episode.FieldTargetFile:
|
||||||
|
return m.OldTargetFile(ctx)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("unknown Episode field %s", name)
|
return nil, fmt.Errorf("unknown Episode field %s", name)
|
||||||
}
|
}
|
||||||
@@ -1570,6 +1627,13 @@ func (m *EpisodeMutation) SetField(name string, value ent.Value) error {
|
|||||||
}
|
}
|
||||||
m.SetMonitored(v)
|
m.SetMonitored(v)
|
||||||
return nil
|
return nil
|
||||||
|
case episode.FieldTargetFile:
|
||||||
|
v, ok := value.(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
||||||
|
}
|
||||||
|
m.SetTargetFile(v)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("unknown Episode field %s", name)
|
return fmt.Errorf("unknown Episode field %s", name)
|
||||||
}
|
}
|
||||||
@@ -1630,6 +1694,9 @@ func (m *EpisodeMutation) ClearedFields() []string {
|
|||||||
if m.FieldCleared(episode.FieldMediaID) {
|
if m.FieldCleared(episode.FieldMediaID) {
|
||||||
fields = append(fields, episode.FieldMediaID)
|
fields = append(fields, episode.FieldMediaID)
|
||||||
}
|
}
|
||||||
|
if m.FieldCleared(episode.FieldTargetFile) {
|
||||||
|
fields = append(fields, episode.FieldTargetFile)
|
||||||
|
}
|
||||||
return fields
|
return fields
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1647,6 +1714,9 @@ func (m *EpisodeMutation) ClearField(name string) error {
|
|||||||
case episode.FieldMediaID:
|
case episode.FieldMediaID:
|
||||||
m.ClearMediaID()
|
m.ClearMediaID()
|
||||||
return nil
|
return nil
|
||||||
|
case episode.FieldTargetFile:
|
||||||
|
m.ClearTargetFile()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("unknown Episode nullable field %s", name)
|
return fmt.Errorf("unknown Episode nullable field %s", name)
|
||||||
}
|
}
|
||||||
@@ -1679,6 +1749,9 @@ func (m *EpisodeMutation) ResetField(name string) error {
|
|||||||
case episode.FieldMonitored:
|
case episode.FieldMonitored:
|
||||||
m.ResetMonitored()
|
m.ResetMonitored()
|
||||||
return nil
|
return nil
|
||||||
|
case episode.FieldTargetFile:
|
||||||
|
m.ResetTargetFile()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("unknown Episode field %s", name)
|
return fmt.Errorf("unknown Episode field %s", name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,16 +22,17 @@ func (Episode) Fields() []ent.Field {
|
|||||||
field.String("air_date"),
|
field.String("air_date"),
|
||||||
field.Enum("status").Values("missing", "downloading", "downloaded").Default("missing"),
|
field.Enum("status").Values("missing", "downloading", "downloaded").Default("missing"),
|
||||||
field.Bool("monitored").Default(false).StructTag("json:\"monitored\""), //whether this episode is monitored
|
field.Bool("monitored").Default(false).StructTag("json:\"monitored\""), //whether this episode is monitored
|
||||||
|
field.String("target_file").Optional(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Edges of the Episode.
|
// Edges of the Episode.
|
||||||
func (Episode) Edges() []ent.Edge {
|
func (Episode) Edges() []ent.Edge {
|
||||||
return []ent.Edge{
|
return []ent.Edge{
|
||||||
edge.From("media", Media.Type).
|
edge.From("media", Media.Type).
|
||||||
Ref("episodes").
|
Ref("episodes").
|
||||||
Unique().
|
Unique().
|
||||||
Field("media_id"),
|
Field("media_id"),
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,24 +3,30 @@ package core
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"polaris/db"
|
"polaris/db"
|
||||||
"polaris/ent/media"
|
"polaris/ent/media"
|
||||||
storage1 "polaris/ent/storage"
|
storage1 "polaris/ent/storage"
|
||||||
"polaris/log"
|
"polaris/log"
|
||||||
|
"polaris/pkg/metadata"
|
||||||
"polaris/pkg/notifier"
|
"polaris/pkg/notifier"
|
||||||
"polaris/pkg/storage"
|
"polaris/pkg/storage"
|
||||||
|
"polaris/pkg/utils"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) writePlexmatch(seriesId int, episodeId int, targetDir, name string) error {
|
func (c *Client) writePlexmatch(historyId int) error {
|
||||||
|
|
||||||
if !c.plexmatchEnabled() {
|
if !c.plexmatchEnabled() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
series, err := c.db.GetMedia(seriesId)
|
|
||||||
|
his := c.db.GetHistory(historyId)
|
||||||
|
|
||||||
|
series, err := c.db.GetMedia(his.MediaID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -47,24 +53,44 @@ func (c *Client) writePlexmatch(seriesId int, episodeId int, targetDir, name str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//season plexmatch file
|
|
||||||
ep, err := c.db.GetEpisodeByID(episodeId)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "query episode")
|
|
||||||
}
|
|
||||||
buff := bytes.Buffer{}
|
buff := bytes.Buffer{}
|
||||||
seasonPlex := filepath.Join(targetDir, ".plexmatch")
|
seasonPlex := filepath.Join(his.TargetDir, ".plexmatch")
|
||||||
data, err := st.ReadFile(seasonPlex)
|
data, err := st.ReadFile(seasonPlex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Infof("read season plexmatch: %v", err)
|
log.Infof("read season plexmatch: %v", err)
|
||||||
} else {
|
} else {
|
||||||
buff.Write(data)
|
buff.Write(data)
|
||||||
}
|
}
|
||||||
if strings.Contains(buff.String(), name) {
|
|
||||||
log.Debugf("already write plex episode line: %v", name)
|
if his.EpisodeID > 0 {
|
||||||
return nil
|
//single episode download
|
||||||
|
ep, err := c.db.GetEpisodeByID(his.EpisodeID)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "query episode")
|
||||||
|
}
|
||||||
|
if strings.Contains(buff.String(), ep.TargetFile) {
|
||||||
|
log.Debugf("already write plex episode line: %v", ep.TargetFile)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
buff.WriteString(fmt.Sprintf("\nep: %d: %s\n", ep.EpisodeNumber, ep.TargetFile))
|
||||||
|
} else {
|
||||||
|
seasonNum, err := utils.SeasonId(his.TargetDir)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "no season id")
|
||||||
|
}
|
||||||
|
allEpisodes, err := c.db.GetSeasonEpisodes(his.MediaID, seasonNum)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "query season episode")
|
||||||
|
}
|
||||||
|
for _, ep := range allEpisodes {
|
||||||
|
if strings.Contains(buff.String(), ep.TargetFile) {
|
||||||
|
log.Debugf("already write plex episode line: %v", ep.TargetFile)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
buff.WriteString(fmt.Sprintf("\nep: %d: %s\n", ep.EpisodeNumber, ep.TargetFile))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
buff.WriteString(fmt.Sprintf("\nep: %d: %s\n", ep.EpisodeNumber, name))
|
|
||||||
log.Infof("write season plexmatch file content: %s", buff.String())
|
log.Infof("write season plexmatch file content: %s", buff.String())
|
||||||
return st.WriteFile(seasonPlex, buff.Bytes())
|
return st.WriteFile(seasonPlex, buff.Bytes())
|
||||||
}
|
}
|
||||||
@@ -128,3 +154,63 @@ func (c *Client) sendMsg(msg string) {
|
|||||||
log.Debugf("send message to %s success, msg is %s", cl.Name, msg)
|
log.Debugf("send message to %s success, msg is %s", cl.Name, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) findEpisodeFilesPreMoving(historyId int) error {
|
||||||
|
his := c.db.GetHistory(historyId)
|
||||||
|
|
||||||
|
isSingleEpisode := his.EpisodeID > 0
|
||||||
|
downloadDir := c.db.GetDownloadDir()
|
||||||
|
task := c.tasks[historyId]
|
||||||
|
target := filepath.Join(downloadDir, task.Name())
|
||||||
|
fi, err := os.Stat(target)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "read dir %v", target)
|
||||||
|
}
|
||||||
|
if isSingleEpisode {
|
||||||
|
if fi.IsDir() {
|
||||||
|
//download single episode in dir
|
||||||
|
//TODO
|
||||||
|
} else {
|
||||||
|
//is file
|
||||||
|
if err := c.db.UpdateEpisodeTargetFile(his.EpisodeID, fi.Name()); err != nil {
|
||||||
|
log.Errorf("writing downloaded file name to db error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if fi.IsDir() {
|
||||||
|
return fmt.Errorf("not season pack downloaded")
|
||||||
|
}
|
||||||
|
seasonNum, err := utils.SeasonId(his.TargetDir)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "no season id")
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err := os.ReadDir(target)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, f := range files {
|
||||||
|
if f.IsDir() { //want media file
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
excludedExt := []string{".txt", ".srt", ".ass", ".sub"}
|
||||||
|
ext := filepath.Ext(f.Name())
|
||||||
|
if slices.Contains(excludedExt, strings.ToLower(ext)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
meta := metadata.ParseTv(f.Name())
|
||||||
|
if meta.Episode > 0 {
|
||||||
|
//episode exists
|
||||||
|
ep, err := c.db.GetEpisode(his.MediaID, seasonNum, meta.Episode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := c.db.UpdateEpisodeTargetFile(ep.ID, f.Name()); err != nil {
|
||||||
|
return errors.Wrap(err, "update episode file")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -61,15 +61,25 @@ func (c *Client) checkTasks() {
|
|||||||
}
|
}
|
||||||
log.Infof("task is done: %v", t.Name())
|
log.Infof("task is done: %v", t.Name())
|
||||||
c.sendMsg(fmt.Sprintf(message.DownloadComplete, t.Name()))
|
c.sendMsg(fmt.Sprintf(message.DownloadComplete, t.Name()))
|
||||||
go func() {
|
|
||||||
if err := c.moveCompletedTask(id); err != nil {
|
go c.postTaskProcessing(id)
|
||||||
log.Infof("post tasks for id %v fail: %v", id, err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) postTaskProcessing(id int) {
|
||||||
|
if err := c.findEpisodeFilesPreMoving(id); err != nil {
|
||||||
|
log.Errorf("finding all episode file error: %v", err)
|
||||||
|
} else {
|
||||||
|
if err := c.writePlexmatch(id); err != nil {
|
||||||
|
log.Errorf("write plexmatch file error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := c.moveCompletedTask(id); err != nil {
|
||||||
|
log.Infof("post tasks for id %v fail: %v", id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) moveCompletedTask(id int) (err1 error) {
|
func (c *Client) moveCompletedTask(id int) (err1 error) {
|
||||||
torrent := c.tasks[id]
|
torrent := c.tasks[id]
|
||||||
r := c.db.GetHistory(id)
|
r := c.db.GetHistory(id)
|
||||||
@@ -119,11 +129,6 @@ func (c *Client) moveCompletedTask(id int) (err1 error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// .plexmatch file
|
|
||||||
if err := c.writePlexmatch(r.MediaID, r.EpisodeID, r.TargetDir, torrentName); err != nil {
|
|
||||||
log.Errorf("create .plexmatch file error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
//如果种子是路径,则会把路径展开,只移动文件,类似 move dir/* dir2/, 如果种子是文件,则会直接移动文件,类似 move file dir/
|
//如果种子是路径,则会把路径展开,只移动文件,类似 move dir/* dir2/, 如果种子是文件,则会直接移动文件,类似 move file dir/
|
||||||
if err := stImpl.Copy(filepath.Join(c.db.GetDownloadDir(), torrentName), r.TargetDir); err != nil {
|
if err := stImpl.Copy(filepath.Join(c.db.GetDownloadDir(), torrentName), r.TargetDir); err != nil {
|
||||||
return errors.Wrap(err, "move file")
|
return errors.Wrap(err, "move file")
|
||||||
|
|||||||
Reference in New Issue
Block a user