mirror of
https://github.com/simon-ding/polaris.git
synced 2026-06-25 18:25:05 +08:00
feat: change method to monitor episodes
This commit is contained in:
@@ -31,6 +31,8 @@ type Episode struct {
|
||||
AirDate string `json:"air_date,omitempty"`
|
||||
// Status holds the value of the "status" field.
|
||||
Status episode.Status `json:"status,omitempty"`
|
||||
// Monitored holds the value of the "monitored" field.
|
||||
Monitored bool `json:"monitored"`
|
||||
// Edges holds the relations/edges for other nodes in the graph.
|
||||
// The values are being populated by the EpisodeQuery when eager-loading is set.
|
||||
Edges EpisodeEdges `json:"edges"`
|
||||
@@ -62,6 +64,8 @@ func (*Episode) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case episode.FieldMonitored:
|
||||
values[i] = new(sql.NullBool)
|
||||
case episode.FieldID, episode.FieldMediaID, episode.FieldSeasonNumber, episode.FieldEpisodeNumber:
|
||||
values[i] = new(sql.NullInt64)
|
||||
case episode.FieldTitle, episode.FieldOverview, episode.FieldAirDate, episode.FieldStatus:
|
||||
@@ -129,6 +133,12 @@ func (e *Episode) assignValues(columns []string, values []any) error {
|
||||
} else if value.Valid {
|
||||
e.Status = episode.Status(value.String)
|
||||
}
|
||||
case episode.FieldMonitored:
|
||||
if value, ok := values[i].(*sql.NullBool); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field monitored", values[i])
|
||||
} else if value.Valid {
|
||||
e.Monitored = value.Bool
|
||||
}
|
||||
default:
|
||||
e.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
@@ -190,6 +200,9 @@ func (e *Episode) String() string {
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("status=")
|
||||
builder.WriteString(fmt.Sprintf("%v", e.Status))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("monitored=")
|
||||
builder.WriteString(fmt.Sprintf("%v", e.Monitored))
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ const (
|
||||
FieldAirDate = "air_date"
|
||||
// FieldStatus holds the string denoting the status field in the database.
|
||||
FieldStatus = "status"
|
||||
// FieldMonitored holds the string denoting the monitored field in the database.
|
||||
FieldMonitored = "monitored"
|
||||
// EdgeMedia holds the string denoting the media edge name in mutations.
|
||||
EdgeMedia = "media"
|
||||
// Table holds the table name of the episode in the database.
|
||||
@@ -51,6 +53,7 @@ var Columns = []string{
|
||||
FieldOverview,
|
||||
FieldAirDate,
|
||||
FieldStatus,
|
||||
FieldMonitored,
|
||||
}
|
||||
|
||||
// ValidColumn reports if the column name is valid (part of the table columns).
|
||||
@@ -63,6 +66,11 @@ func ValidColumn(column string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
// DefaultMonitored holds the default value on creation for the "monitored" field.
|
||||
DefaultMonitored bool
|
||||
)
|
||||
|
||||
// Status defines the type for the "status" enum field.
|
||||
type Status string
|
||||
|
||||
@@ -133,6 +141,11 @@ func ByStatus(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldStatus, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByMonitored orders the results by the monitored field.
|
||||
func ByMonitored(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldMonitored, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// ByMediaField orders the results by media field.
|
||||
func ByMediaField(field string, opts ...sql.OrderTermOption) OrderOption {
|
||||
return func(s *sql.Selector) {
|
||||
|
||||
@@ -84,6 +84,11 @@ func AirDate(v string) predicate.Episode {
|
||||
return predicate.Episode(sql.FieldEQ(FieldAirDate, v))
|
||||
}
|
||||
|
||||
// Monitored applies equality check predicate on the "monitored" field. It's identical to MonitoredEQ.
|
||||
func Monitored(v bool) predicate.Episode {
|
||||
return predicate.Episode(sql.FieldEQ(FieldMonitored, v))
|
||||
}
|
||||
|
||||
// MediaIDEQ applies the EQ predicate on the "media_id" field.
|
||||
func MediaIDEQ(v int) predicate.Episode {
|
||||
return predicate.Episode(sql.FieldEQ(FieldMediaID, v))
|
||||
@@ -409,6 +414,16 @@ func StatusNotIn(vs ...Status) predicate.Episode {
|
||||
return predicate.Episode(sql.FieldNotIn(FieldStatus, vs...))
|
||||
}
|
||||
|
||||
// MonitoredEQ applies the EQ predicate on the "monitored" field.
|
||||
func MonitoredEQ(v bool) predicate.Episode {
|
||||
return predicate.Episode(sql.FieldEQ(FieldMonitored, v))
|
||||
}
|
||||
|
||||
// MonitoredNEQ applies the NEQ predicate on the "monitored" field.
|
||||
func MonitoredNEQ(v bool) predicate.Episode {
|
||||
return predicate.Episode(sql.FieldNEQ(FieldMonitored, v))
|
||||
}
|
||||
|
||||
// HasMedia applies the HasEdge predicate on the "media" edge.
|
||||
func HasMedia() predicate.Episode {
|
||||
return predicate.Episode(func(s *sql.Selector) {
|
||||
|
||||
@@ -78,6 +78,20 @@ func (ec *EpisodeCreate) SetNillableStatus(e *episode.Status) *EpisodeCreate {
|
||||
return ec
|
||||
}
|
||||
|
||||
// SetMonitored sets the "monitored" field.
|
||||
func (ec *EpisodeCreate) SetMonitored(b bool) *EpisodeCreate {
|
||||
ec.mutation.SetMonitored(b)
|
||||
return ec
|
||||
}
|
||||
|
||||
// SetNillableMonitored sets the "monitored" field if the given value is not nil.
|
||||
func (ec *EpisodeCreate) SetNillableMonitored(b *bool) *EpisodeCreate {
|
||||
if b != nil {
|
||||
ec.SetMonitored(*b)
|
||||
}
|
||||
return ec
|
||||
}
|
||||
|
||||
// SetMedia sets the "media" edge to the Media entity.
|
||||
func (ec *EpisodeCreate) SetMedia(m *Media) *EpisodeCreate {
|
||||
return ec.SetMediaID(m.ID)
|
||||
@@ -122,6 +136,10 @@ func (ec *EpisodeCreate) defaults() {
|
||||
v := episode.DefaultStatus
|
||||
ec.mutation.SetStatus(v)
|
||||
}
|
||||
if _, ok := ec.mutation.Monitored(); !ok {
|
||||
v := episode.DefaultMonitored
|
||||
ec.mutation.SetMonitored(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
@@ -149,6 +167,9 @@ func (ec *EpisodeCreate) check() error {
|
||||
return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "Episode.status": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := ec.mutation.Monitored(); !ok {
|
||||
return &ValidationError{Name: "monitored", err: errors.New(`ent: missing required field "Episode.monitored"`)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -199,6 +220,10 @@ func (ec *EpisodeCreate) createSpec() (*Episode, *sqlgraph.CreateSpec) {
|
||||
_spec.SetField(episode.FieldStatus, field.TypeEnum, value)
|
||||
_node.Status = value
|
||||
}
|
||||
if value, ok := ec.mutation.Monitored(); ok {
|
||||
_spec.SetField(episode.FieldMonitored, field.TypeBool, value)
|
||||
_node.Monitored = value
|
||||
}
|
||||
if nodes := ec.mutation.MediaIDs(); len(nodes) > 0 {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
|
||||
@@ -146,6 +146,20 @@ func (eu *EpisodeUpdate) SetNillableStatus(e *episode.Status) *EpisodeUpdate {
|
||||
return eu
|
||||
}
|
||||
|
||||
// SetMonitored sets the "monitored" field.
|
||||
func (eu *EpisodeUpdate) SetMonitored(b bool) *EpisodeUpdate {
|
||||
eu.mutation.SetMonitored(b)
|
||||
return eu
|
||||
}
|
||||
|
||||
// SetNillableMonitored sets the "monitored" field if the given value is not nil.
|
||||
func (eu *EpisodeUpdate) SetNillableMonitored(b *bool) *EpisodeUpdate {
|
||||
if b != nil {
|
||||
eu.SetMonitored(*b)
|
||||
}
|
||||
return eu
|
||||
}
|
||||
|
||||
// SetMedia sets the "media" edge to the Media entity.
|
||||
func (eu *EpisodeUpdate) SetMedia(m *Media) *EpisodeUpdate {
|
||||
return eu.SetMediaID(m.ID)
|
||||
@@ -235,6 +249,9 @@ func (eu *EpisodeUpdate) sqlSave(ctx context.Context) (n int, err error) {
|
||||
if value, ok := eu.mutation.Status(); ok {
|
||||
_spec.SetField(episode.FieldStatus, field.TypeEnum, value)
|
||||
}
|
||||
if value, ok := eu.mutation.Monitored(); ok {
|
||||
_spec.SetField(episode.FieldMonitored, field.TypeBool, value)
|
||||
}
|
||||
if eu.mutation.MediaCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
@@ -402,6 +419,20 @@ func (euo *EpisodeUpdateOne) SetNillableStatus(e *episode.Status) *EpisodeUpdate
|
||||
return euo
|
||||
}
|
||||
|
||||
// SetMonitored sets the "monitored" field.
|
||||
func (euo *EpisodeUpdateOne) SetMonitored(b bool) *EpisodeUpdateOne {
|
||||
euo.mutation.SetMonitored(b)
|
||||
return euo
|
||||
}
|
||||
|
||||
// SetNillableMonitored sets the "monitored" field if the given value is not nil.
|
||||
func (euo *EpisodeUpdateOne) SetNillableMonitored(b *bool) *EpisodeUpdateOne {
|
||||
if b != nil {
|
||||
euo.SetMonitored(*b)
|
||||
}
|
||||
return euo
|
||||
}
|
||||
|
||||
// SetMedia sets the "media" edge to the Media entity.
|
||||
func (euo *EpisodeUpdateOne) SetMedia(m *Media) *EpisodeUpdateOne {
|
||||
return euo.SetMediaID(m.ID)
|
||||
@@ -521,6 +552,9 @@ func (euo *EpisodeUpdateOne) sqlSave(ctx context.Context) (_node *Episode, err e
|
||||
if value, ok := euo.mutation.Status(); ok {
|
||||
_spec.SetField(episode.FieldStatus, field.TypeEnum, value)
|
||||
}
|
||||
if value, ok := euo.mutation.Monitored(); ok {
|
||||
_spec.SetField(episode.FieldMonitored, field.TypeBool, value)
|
||||
}
|
||||
if euo.mutation.MediaCleared() {
|
||||
edge := &sqlgraph.EdgeSpec{
|
||||
Rel: sqlgraph.M2O,
|
||||
|
||||
@@ -38,6 +38,7 @@ var (
|
||||
{Name: "overview", Type: field.TypeString},
|
||||
{Name: "air_date", Type: field.TypeString},
|
||||
{Name: "status", Type: field.TypeEnum, Enums: []string{"missing", "downloading", "downloaded"}, Default: "missing"},
|
||||
{Name: "monitored", Type: field.TypeBool, Default: false},
|
||||
{Name: "media_id", Type: field.TypeInt, Nullable: true},
|
||||
}
|
||||
// EpisodesTable holds the schema information for the "episodes" table.
|
||||
@@ -48,7 +49,7 @@ var (
|
||||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "episodes_media_episodes",
|
||||
Columns: []*schema.Column{EpisodesColumns[7]},
|
||||
Columns: []*schema.Column{EpisodesColumns[8]},
|
||||
RefColumns: []*schema.Column{MediaColumns[0]},
|
||||
OnDelete: schema.SetNull,
|
||||
},
|
||||
|
||||
@@ -921,6 +921,7 @@ type EpisodeMutation struct {
|
||||
overview *string
|
||||
air_date *string
|
||||
status *episode.Status
|
||||
monitored *bool
|
||||
clearedFields map[string]struct{}
|
||||
media *int
|
||||
clearedmedia bool
|
||||
@@ -1332,6 +1333,42 @@ func (m *EpisodeMutation) ResetStatus() {
|
||||
m.status = nil
|
||||
}
|
||||
|
||||
// SetMonitored sets the "monitored" field.
|
||||
func (m *EpisodeMutation) SetMonitored(b bool) {
|
||||
m.monitored = &b
|
||||
}
|
||||
|
||||
// Monitored returns the value of the "monitored" field in the mutation.
|
||||
func (m *EpisodeMutation) Monitored() (r bool, exists bool) {
|
||||
v := m.monitored
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
return *v, true
|
||||
}
|
||||
|
||||
// OldMonitored returns the old "monitored" 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) OldMonitored(ctx context.Context) (v bool, err error) {
|
||||
if !m.op.Is(OpUpdateOne) {
|
||||
return v, errors.New("OldMonitored is only allowed on UpdateOne operations")
|
||||
}
|
||||
if m.id == nil || m.oldValue == nil {
|
||||
return v, errors.New("OldMonitored requires an ID field in the mutation")
|
||||
}
|
||||
oldValue, err := m.oldValue(ctx)
|
||||
if err != nil {
|
||||
return v, fmt.Errorf("querying old value for OldMonitored: %w", err)
|
||||
}
|
||||
return oldValue.Monitored, nil
|
||||
}
|
||||
|
||||
// ResetMonitored resets all changes to the "monitored" field.
|
||||
func (m *EpisodeMutation) ResetMonitored() {
|
||||
m.monitored = nil
|
||||
}
|
||||
|
||||
// ClearMedia clears the "media" edge to the Media entity.
|
||||
func (m *EpisodeMutation) ClearMedia() {
|
||||
m.clearedmedia = true
|
||||
@@ -1393,7 +1430,7 @@ func (m *EpisodeMutation) Type() string {
|
||||
// order to get all numeric fields that were incremented/decremented, call
|
||||
// AddedFields().
|
||||
func (m *EpisodeMutation) Fields() []string {
|
||||
fields := make([]string, 0, 7)
|
||||
fields := make([]string, 0, 8)
|
||||
if m.media != nil {
|
||||
fields = append(fields, episode.FieldMediaID)
|
||||
}
|
||||
@@ -1415,6 +1452,9 @@ func (m *EpisodeMutation) Fields() []string {
|
||||
if m.status != nil {
|
||||
fields = append(fields, episode.FieldStatus)
|
||||
}
|
||||
if m.monitored != nil {
|
||||
fields = append(fields, episode.FieldMonitored)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
@@ -1437,6 +1477,8 @@ func (m *EpisodeMutation) Field(name string) (ent.Value, bool) {
|
||||
return m.AirDate()
|
||||
case episode.FieldStatus:
|
||||
return m.Status()
|
||||
case episode.FieldMonitored:
|
||||
return m.Monitored()
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
@@ -1460,6 +1502,8 @@ func (m *EpisodeMutation) OldField(ctx context.Context, name string) (ent.Value,
|
||||
return m.OldAirDate(ctx)
|
||||
case episode.FieldStatus:
|
||||
return m.OldStatus(ctx)
|
||||
case episode.FieldMonitored:
|
||||
return m.OldMonitored(ctx)
|
||||
}
|
||||
return nil, fmt.Errorf("unknown Episode field %s", name)
|
||||
}
|
||||
@@ -1518,6 +1562,13 @@ func (m *EpisodeMutation) SetField(name string, value ent.Value) error {
|
||||
}
|
||||
m.SetStatus(v)
|
||||
return nil
|
||||
case episode.FieldMonitored:
|
||||
v, ok := value.(bool)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
||||
}
|
||||
m.SetMonitored(v)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown Episode field %s", name)
|
||||
}
|
||||
@@ -1624,6 +1675,9 @@ func (m *EpisodeMutation) ResetField(name string) error {
|
||||
case episode.FieldStatus:
|
||||
m.ResetStatus()
|
||||
return nil
|
||||
case episode.FieldMonitored:
|
||||
m.ResetMonitored()
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unknown Episode field %s", name)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ package ent
|
||||
|
||||
import (
|
||||
"polaris/ent/downloadclients"
|
||||
"polaris/ent/episode"
|
||||
"polaris/ent/history"
|
||||
"polaris/ent/indexers"
|
||||
"polaris/ent/media"
|
||||
@@ -49,6 +50,10 @@ func init() {
|
||||
downloadclients.DefaultTags = downloadclientsDescTags.Default.(string)
|
||||
episodeFields := schema.Episode{}.Fields()
|
||||
_ = episodeFields
|
||||
// episodeDescMonitored is the schema descriptor for monitored field.
|
||||
episodeDescMonitored := episodeFields[7].Descriptor()
|
||||
// episode.DefaultMonitored holds the default value on creation for the monitored field.
|
||||
episode.DefaultMonitored = episodeDescMonitored.Default.(bool)
|
||||
historyFields := schema.History{}.Fields()
|
||||
_ = historyFields
|
||||
// historyDescSize is the schema descriptor for size field.
|
||||
|
||||
@@ -21,7 +21,7 @@ func (Episode) Fields() []ent.Field {
|
||||
field.String("overview"),
|
||||
field.String("air_date"),
|
||||
field.Enum("status").Values("missing", "downloading", "downloaded").Default("missing"),
|
||||
field.Bool("monitored").Default(true).StructTag("json:\"monitored\""), //whether this episode is monitored
|
||||
field.Bool("monitored").Default(false).StructTag("json:\"monitored\""), //whether this episode is monitored
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ func (c *Client) DownloadEpisodeTorrent(r1 torznab.Result, seriesId, seasonNum,
|
||||
}
|
||||
func (c *Client) SearchAndDownload(seriesId, seasonNum, episodeNum int) (*string, error) {
|
||||
|
||||
res, err := SearchEpisode(c.db, seriesId, seasonNum, episodeNum, true)
|
||||
res, err := SearchTvSeries(c.db, seriesId, seasonNum, []int{episodeNum}, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"polaris/pkg"
|
||||
"polaris/pkg/notifier/message"
|
||||
"polaris/pkg/utils"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -217,16 +216,9 @@ func (c *Client) downloadTvSeries() {
|
||||
for _, series := range allSeries {
|
||||
tvDetail := c.db.GetMediaDetails(series.ID)
|
||||
for _, ep := range tvDetail.Episodes {
|
||||
if !series.DownloadHistoryEpisodes { //设置不下载历史已播出剧集,只下载将来剧集
|
||||
t, err := time.Parse("2006-01-02", ep.AirDate)
|
||||
if err != nil {
|
||||
log.Error("air date not known, skip: %v", ep.Title)
|
||||
if !ep.Monitored { //未监控的剧集不去下载
|
||||
continue
|
||||
}
|
||||
if series.CreatedAt.Sub(t) > 24*time.Hour { //剧集在加入watchlist之前,不去下载
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if ep.Status != episode.StatusMissing { //已经下载的不去下载
|
||||
continue
|
||||
@@ -338,6 +330,7 @@ func (c *Client) checkSeiesNewSeason(media *ent.Media) error {
|
||||
Overview: ep.Overview,
|
||||
AirDate: ep.AirDate,
|
||||
Status: episode.StatusMissing,
|
||||
Monitored: true,
|
||||
}
|
||||
c.db.SaveEposideDetail2(episode)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"polaris/pkg/metadata"
|
||||
"polaris/pkg/torznab"
|
||||
"polaris/pkg/utils"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -15,30 +16,12 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func SearchSeasonPackage(db1 *db.Client, seriesId, seasonNum int, checkResolution bool) ([]torznab.Result, error) {
|
||||
return SearchEpisode(db1, seriesId, seasonNum, -1, checkResolution)
|
||||
}
|
||||
|
||||
func isNumberedSeries(detail *db.MediaDetails) bool {
|
||||
hasSeason2 := false
|
||||
season2HasEpisode1 := false
|
||||
for _, ep := range detail.Episodes {
|
||||
if ep.SeasonNumber == 2 {
|
||||
hasSeason2 = true
|
||||
if ep.EpisodeNumber == 1 {
|
||||
season2HasEpisode1 = true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return hasSeason2 && !season2HasEpisode1 //only one 1st episode
|
||||
}
|
||||
|
||||
func SearchEpisode(db1 *db.Client, seriesId, seasonNum, episodeNum int, checkResolution bool) ([]torznab.Result, error) {
|
||||
func SearchTvSeries(db1 *db.Client, seriesId, seasonNum int, episodes []int, checkResolution bool) ([]torznab.Result, error) {
|
||||
series := db1.GetMediaDetails(seriesId)
|
||||
if series == nil {
|
||||
return nil, fmt.Errorf("no tv series of id %v", seriesId)
|
||||
}
|
||||
slices.Contains(episodes, 1)
|
||||
|
||||
res := searchWithTorznab(db1, series.NameEn)
|
||||
resCn := searchWithTorznab(db1, series.NameCn)
|
||||
@@ -56,14 +39,14 @@ func SearchEpisode(db1 *db.Client, seriesId, seasonNum, episodeNum int, checkRes
|
||||
continue
|
||||
}
|
||||
}
|
||||
if isNumberedSeries(series) && episodeNum == -1 {
|
||||
if isNumberedSeries(series) && len(episodes) == 0 {
|
||||
//should not want season
|
||||
continue
|
||||
}
|
||||
|
||||
if episodeNum != -1 && meta.Episode != episodeNum { //not season pack, episode number equals
|
||||
if len(episodes) > 0 && slices.Contains(episodes, meta.Episode) { //not season pack, episode number equals
|
||||
continue
|
||||
}else if episodeNum == -1 && !meta.IsSeasonPack { //want season pack, but not season pack
|
||||
}else if len(episodes) == 0 && !meta.IsSeasonPack { //want season pack, but not season pack
|
||||
continue
|
||||
}
|
||||
if checkResolution && meta.Resolution != series.Resolution.String() {
|
||||
@@ -82,6 +65,21 @@ func SearchEpisode(db1 *db.Client, seriesId, seasonNum, episodeNum int, checkRes
|
||||
|
||||
}
|
||||
|
||||
func isNumberedSeries(detail *db.MediaDetails) bool {
|
||||
hasSeason2 := false
|
||||
season2HasEpisode1 := false
|
||||
for _, ep := range detail.Episodes {
|
||||
if ep.SeasonNumber == 2 {
|
||||
hasSeason2 = true
|
||||
if ep.EpisodeNumber == 1 {
|
||||
season2HasEpisode1 = true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return hasSeason2 && !season2HasEpisode1 //only one 1st episode
|
||||
}
|
||||
|
||||
func SearchMovie(db1 *db.Client, movieId int, checkResolution bool) ([]torznab.Result, error) {
|
||||
movieDetail := db1.GetMediaDetails(movieId)
|
||||
if movieDetail == nil {
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
func (s *Server) searchAndDownloadSeasonPackage(seriesId, seasonNum int) (*string, error) {
|
||||
|
||||
res, err := core.SearchSeasonPackage(s.db, seriesId, seasonNum, true)
|
||||
res, err := core.SearchTvSeries(s.db, seriesId, seasonNum, nil, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -46,13 +46,13 @@ func (s *Server) SearchAvailableTorrents(c *gin.Context) (interface{}, error) {
|
||||
if in.Episode == 0 {
|
||||
//search season package
|
||||
log.Infof("search series season package S%02d", in.Season)
|
||||
res, err = core.SearchSeasonPackage(s.db, in.ID, in.Season, false)
|
||||
res, err = core.SearchTvSeries(s.db, in.ID, in.Season, nil, false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "search season package")
|
||||
}
|
||||
} else {
|
||||
log.Infof("search series episode S%02dE%02d", in.Season, in.Episode)
|
||||
res, err = core.SearchEpisode(s.db, in.ID, in.Season, in.Episode, false)
|
||||
res, err = core.SearchTvSeries(s.db, in.ID, in.Season, []int{in.Episode}, false)
|
||||
if err != nil {
|
||||
if err.Error() == "no resource found" {
|
||||
return []string{}, nil
|
||||
|
||||
@@ -102,12 +102,29 @@ func (s *Server) AddTv2Watchlist(c *gin.Context) (interface{}, error) {
|
||||
continue
|
||||
}
|
||||
for _, ep := range se.Episodes {
|
||||
shouldMonitor := false
|
||||
//如果设置下载往期剧集,则监控所有剧集。如果没有则监控未上映的剧集,考虑时差等问题留24h余量
|
||||
if in.DownloadHistoryEpisodes {
|
||||
shouldMonitor = true
|
||||
} else {
|
||||
t, err := time.Parse("2006-01-02", ep.AirDate)
|
||||
if err != nil {
|
||||
log.Error("air date not known, will not monitor: %v", ep.AirDate)
|
||||
|
||||
} else {
|
||||
if time.Since(t) < 24*time.Hour { //monitor episode air 24h before now
|
||||
shouldMonitor = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
epid, err := s.db.SaveEposideDetail(&ent.Episode{
|
||||
SeasonNumber: seasonId,
|
||||
EpisodeNumber: ep.EpisodeNumber,
|
||||
Title: ep.Name,
|
||||
Overview: ep.Overview,
|
||||
AirDate: ep.AirDate,
|
||||
Monitored: shouldMonitor,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("save episode info error: %v", err)
|
||||
@@ -176,6 +193,7 @@ func (s *Server) AddMovie2Watchlist(c *gin.Context) (interface{}, error) {
|
||||
Title: "dummy episode for movies",
|
||||
Overview: "dummy episode for movies",
|
||||
AirDate: detail.ReleaseDate,
|
||||
Monitored: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "add dummy episode")
|
||||
@@ -271,31 +289,13 @@ func (s *Server) GetTvWatchlist(c *gin.Context) (interface{}, error) {
|
||||
details := s.db.GetMediaDetails(item.ID)
|
||||
|
||||
for _, ep := range details.Episodes {
|
||||
monitored := false
|
||||
if ep.SeasonNumber == 0 {
|
||||
continue
|
||||
}
|
||||
if item.DownloadHistoryEpisodes {
|
||||
monitored = true
|
||||
} else {
|
||||
t, err := time.Parse("2006-01-02", ep.AirDate)
|
||||
if err != nil { //airdate not exist, maybe airdate not set yet
|
||||
monitored = true
|
||||
} else {
|
||||
if item.CreatedAt.Sub(t) > 24*time.Hour { //剧集在加入watchlist之前,不去下载
|
||||
continue
|
||||
}
|
||||
monitored = true
|
||||
}
|
||||
}
|
||||
if monitored {
|
||||
if ep.Monitored {
|
||||
ms.MonitoredNum++
|
||||
}
|
||||
if ep.Status == episode.StatusDownloaded {
|
||||
ms.DownloadedNum++
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
res[i] = ms
|
||||
}
|
||||
return res, nil
|
||||
|
||||
Reference in New Issue
Block a user