mirror of
https://github.com/simon-ding/polaris.git
synced 2026-06-09 19:47:47 +08:00
feat: save hash instead of link, and refactor torrent download
This commit is contained in:
10
db/db.go
10
db/db.go
@@ -462,18 +462,10 @@ func (c *Client) SetDefaultStorageByName(name string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) SaveHistoryRecord(h ent.History) (*ent.History, error) {
|
func (c *Client) SaveHistoryRecord(h ent.History) (*ent.History, error) {
|
||||||
if h.Link != "" {
|
|
||||||
r, err := utils.Link2Magnet(h.Link)
|
|
||||||
if err != nil {
|
|
||||||
log.Warnf("convert link to magnet error, link %v, error: %v", h.Link, err)
|
|
||||||
} else {
|
|
||||||
h.Link = r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c.ent.History.Create().SetMediaID(h.MediaID).SetEpisodeID(h.EpisodeID).SetDate(time.Now()).
|
return c.ent.History.Create().SetMediaID(h.MediaID).SetEpisodeID(h.EpisodeID).SetDate(time.Now()).
|
||||||
SetStatus(h.Status).SetTargetDir(h.TargetDir).SetSourceTitle(h.SourceTitle).SetIndexerID(h.IndexerID).
|
SetStatus(h.Status).SetTargetDir(h.TargetDir).SetSourceTitle(h.SourceTitle).SetIndexerID(h.IndexerID).
|
||||||
SetDownloadClientID(h.DownloadClientID).SetSize(h.Size).SetSaved(h.Saved).SetSeasonNum(h.SeasonNum).
|
SetDownloadClientID(h.DownloadClientID).SetSize(h.Size).SetSaved(h.Saved).SetSeasonNum(h.SeasonNum).
|
||||||
SetEpisodeNums(h.EpisodeNums).SetLink(h.Link).Save(context.TODO())
|
SetEpisodeNums(h.EpisodeNums).SetHash(h.Hash).SetLink(h.Link).Save(context.TODO())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) SetHistoryStatus(id int, status history.Status) error {
|
func (c *Client) SetHistoryStatus(id int, status history.Status) error {
|
||||||
|
|||||||
@@ -38,8 +38,10 @@ type History struct {
|
|||||||
DownloadClientID int `json:"download_client_id,omitempty"`
|
DownloadClientID int `json:"download_client_id,omitempty"`
|
||||||
// IndexerID holds the value of the "indexer_id" field.
|
// IndexerID holds the value of the "indexer_id" field.
|
||||||
IndexerID int `json:"indexer_id,omitempty"`
|
IndexerID int `json:"indexer_id,omitempty"`
|
||||||
// Link holds the value of the "link" field.
|
// deprecated, use hash instead
|
||||||
Link string `json:"link,omitempty"`
|
Link string `json:"link,omitempty"`
|
||||||
|
// torrent hash
|
||||||
|
Hash string `json:"hash,omitempty"`
|
||||||
// Status holds the value of the "status" field.
|
// Status holds the value of the "status" field.
|
||||||
Status history.Status `json:"status,omitempty"`
|
Status history.Status `json:"status,omitempty"`
|
||||||
// deprecated
|
// deprecated
|
||||||
@@ -56,7 +58,7 @@ func (*History) scanValues(columns []string) ([]any, error) {
|
|||||||
values[i] = new([]byte)
|
values[i] = new([]byte)
|
||||||
case history.FieldID, history.FieldMediaID, history.FieldEpisodeID, history.FieldSeasonNum, history.FieldSize, history.FieldDownloadClientID, history.FieldIndexerID:
|
case history.FieldID, history.FieldMediaID, history.FieldEpisodeID, history.FieldSeasonNum, history.FieldSize, history.FieldDownloadClientID, history.FieldIndexerID:
|
||||||
values[i] = new(sql.NullInt64)
|
values[i] = new(sql.NullInt64)
|
||||||
case history.FieldSourceTitle, history.FieldTargetDir, history.FieldLink, history.FieldStatus, history.FieldSaved:
|
case history.FieldSourceTitle, history.FieldTargetDir, history.FieldLink, history.FieldHash, history.FieldStatus, history.FieldSaved:
|
||||||
values[i] = new(sql.NullString)
|
values[i] = new(sql.NullString)
|
||||||
case history.FieldDate:
|
case history.FieldDate:
|
||||||
values[i] = new(sql.NullTime)
|
values[i] = new(sql.NullTime)
|
||||||
@@ -149,6 +151,12 @@ func (h *History) assignValues(columns []string, values []any) error {
|
|||||||
} else if value.Valid {
|
} else if value.Valid {
|
||||||
h.Link = value.String
|
h.Link = value.String
|
||||||
}
|
}
|
||||||
|
case history.FieldHash:
|
||||||
|
if value, ok := values[i].(*sql.NullString); !ok {
|
||||||
|
return fmt.Errorf("unexpected type %T for field hash", values[i])
|
||||||
|
} else if value.Valid {
|
||||||
|
h.Hash = value.String
|
||||||
|
}
|
||||||
case history.FieldStatus:
|
case history.FieldStatus:
|
||||||
if value, ok := values[i].(*sql.NullString); !ok {
|
if value, ok := values[i].(*sql.NullString); !ok {
|
||||||
return fmt.Errorf("unexpected type %T for field status", values[i])
|
return fmt.Errorf("unexpected type %T for field status", values[i])
|
||||||
@@ -230,6 +238,9 @@ func (h *History) String() string {
|
|||||||
builder.WriteString("link=")
|
builder.WriteString("link=")
|
||||||
builder.WriteString(h.Link)
|
builder.WriteString(h.Link)
|
||||||
builder.WriteString(", ")
|
builder.WriteString(", ")
|
||||||
|
builder.WriteString("hash=")
|
||||||
|
builder.WriteString(h.Hash)
|
||||||
|
builder.WriteString(", ")
|
||||||
builder.WriteString("status=")
|
builder.WriteString("status=")
|
||||||
builder.WriteString(fmt.Sprintf("%v", h.Status))
|
builder.WriteString(fmt.Sprintf("%v", h.Status))
|
||||||
builder.WriteString(", ")
|
builder.WriteString(", ")
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ const (
|
|||||||
FieldIndexerID = "indexer_id"
|
FieldIndexerID = "indexer_id"
|
||||||
// FieldLink holds the string denoting the link field in the database.
|
// FieldLink holds the string denoting the link field in the database.
|
||||||
FieldLink = "link"
|
FieldLink = "link"
|
||||||
|
// FieldHash holds the string denoting the hash field in the database.
|
||||||
|
FieldHash = "hash"
|
||||||
// FieldStatus holds the string denoting the status field in the database.
|
// FieldStatus holds the string denoting the status field in the database.
|
||||||
FieldStatus = "status"
|
FieldStatus = "status"
|
||||||
// FieldSaved holds the string denoting the saved field in the database.
|
// FieldSaved holds the string denoting the saved field in the database.
|
||||||
@@ -57,6 +59,7 @@ var Columns = []string{
|
|||||||
FieldDownloadClientID,
|
FieldDownloadClientID,
|
||||||
FieldIndexerID,
|
FieldIndexerID,
|
||||||
FieldLink,
|
FieldLink,
|
||||||
|
FieldHash,
|
||||||
FieldStatus,
|
FieldStatus,
|
||||||
FieldSaved,
|
FieldSaved,
|
||||||
}
|
}
|
||||||
@@ -160,6 +163,11 @@ func ByLink(opts ...sql.OrderTermOption) OrderOption {
|
|||||||
return sql.OrderByField(FieldLink, opts...).ToFunc()
|
return sql.OrderByField(FieldLink, opts...).ToFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ByHash orders the results by the hash field.
|
||||||
|
func ByHash(opts ...sql.OrderTermOption) OrderOption {
|
||||||
|
return sql.OrderByField(FieldHash, opts...).ToFunc()
|
||||||
|
}
|
||||||
|
|
||||||
// ByStatus orders the results by the status field.
|
// ByStatus orders the results by the status field.
|
||||||
func ByStatus(opts ...sql.OrderTermOption) OrderOption {
|
func ByStatus(opts ...sql.OrderTermOption) OrderOption {
|
||||||
return sql.OrderByField(FieldStatus, opts...).ToFunc()
|
return sql.OrderByField(FieldStatus, opts...).ToFunc()
|
||||||
|
|||||||
@@ -104,6 +104,11 @@ func Link(v string) predicate.History {
|
|||||||
return predicate.History(sql.FieldEQ(FieldLink, v))
|
return predicate.History(sql.FieldEQ(FieldLink, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hash applies equality check predicate on the "hash" field. It's identical to HashEQ.
|
||||||
|
func Hash(v string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldEQ(FieldHash, v))
|
||||||
|
}
|
||||||
|
|
||||||
// Saved applies equality check predicate on the "saved" field. It's identical to SavedEQ.
|
// Saved applies equality check predicate on the "saved" field. It's identical to SavedEQ.
|
||||||
func Saved(v string) predicate.History {
|
func Saved(v string) predicate.History {
|
||||||
return predicate.History(sql.FieldEQ(FieldSaved, v))
|
return predicate.History(sql.FieldEQ(FieldSaved, v))
|
||||||
@@ -644,6 +649,81 @@ func LinkContainsFold(v string) predicate.History {
|
|||||||
return predicate.History(sql.FieldContainsFold(FieldLink, v))
|
return predicate.History(sql.FieldContainsFold(FieldLink, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HashEQ applies the EQ predicate on the "hash" field.
|
||||||
|
func HashEQ(v string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldEQ(FieldHash, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashNEQ applies the NEQ predicate on the "hash" field.
|
||||||
|
func HashNEQ(v string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldNEQ(FieldHash, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashIn applies the In predicate on the "hash" field.
|
||||||
|
func HashIn(vs ...string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldIn(FieldHash, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashNotIn applies the NotIn predicate on the "hash" field.
|
||||||
|
func HashNotIn(vs ...string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldNotIn(FieldHash, vs...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashGT applies the GT predicate on the "hash" field.
|
||||||
|
func HashGT(v string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldGT(FieldHash, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashGTE applies the GTE predicate on the "hash" field.
|
||||||
|
func HashGTE(v string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldGTE(FieldHash, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashLT applies the LT predicate on the "hash" field.
|
||||||
|
func HashLT(v string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldLT(FieldHash, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashLTE applies the LTE predicate on the "hash" field.
|
||||||
|
func HashLTE(v string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldLTE(FieldHash, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashContains applies the Contains predicate on the "hash" field.
|
||||||
|
func HashContains(v string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldContains(FieldHash, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashHasPrefix applies the HasPrefix predicate on the "hash" field.
|
||||||
|
func HashHasPrefix(v string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldHasPrefix(FieldHash, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashHasSuffix applies the HasSuffix predicate on the "hash" field.
|
||||||
|
func HashHasSuffix(v string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldHasSuffix(FieldHash, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashIsNil applies the IsNil predicate on the "hash" field.
|
||||||
|
func HashIsNil() predicate.History {
|
||||||
|
return predicate.History(sql.FieldIsNull(FieldHash))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashNotNil applies the NotNil predicate on the "hash" field.
|
||||||
|
func HashNotNil() predicate.History {
|
||||||
|
return predicate.History(sql.FieldNotNull(FieldHash))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashEqualFold applies the EqualFold predicate on the "hash" field.
|
||||||
|
func HashEqualFold(v string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldEqualFold(FieldHash, v))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashContainsFold applies the ContainsFold predicate on the "hash" field.
|
||||||
|
func HashContainsFold(v string) predicate.History {
|
||||||
|
return predicate.History(sql.FieldContainsFold(FieldHash, v))
|
||||||
|
}
|
||||||
|
|
||||||
// StatusEQ applies the EQ predicate on the "status" field.
|
// StatusEQ applies the EQ predicate on the "status" field.
|
||||||
func StatusEQ(v Status) predicate.History {
|
func StatusEQ(v Status) predicate.History {
|
||||||
return predicate.History(sql.FieldEQ(FieldStatus, v))
|
return predicate.History(sql.FieldEQ(FieldStatus, v))
|
||||||
|
|||||||
@@ -134,6 +134,20 @@ func (hc *HistoryCreate) SetNillableLink(s *string) *HistoryCreate {
|
|||||||
return hc
|
return hc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetHash sets the "hash" field.
|
||||||
|
func (hc *HistoryCreate) SetHash(s string) *HistoryCreate {
|
||||||
|
hc.mutation.SetHash(s)
|
||||||
|
return hc
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableHash sets the "hash" field if the given value is not nil.
|
||||||
|
func (hc *HistoryCreate) SetNillableHash(s *string) *HistoryCreate {
|
||||||
|
if s != nil {
|
||||||
|
hc.SetHash(*s)
|
||||||
|
}
|
||||||
|
return hc
|
||||||
|
}
|
||||||
|
|
||||||
// SetStatus sets the "status" field.
|
// SetStatus sets the "status" field.
|
||||||
func (hc *HistoryCreate) SetStatus(h history.Status) *HistoryCreate {
|
func (hc *HistoryCreate) SetStatus(h history.Status) *HistoryCreate {
|
||||||
hc.mutation.SetStatus(h)
|
hc.mutation.SetStatus(h)
|
||||||
@@ -290,6 +304,10 @@ func (hc *HistoryCreate) createSpec() (*History, *sqlgraph.CreateSpec) {
|
|||||||
_spec.SetField(history.FieldLink, field.TypeString, value)
|
_spec.SetField(history.FieldLink, field.TypeString, value)
|
||||||
_node.Link = value
|
_node.Link = value
|
||||||
}
|
}
|
||||||
|
if value, ok := hc.mutation.Hash(); ok {
|
||||||
|
_spec.SetField(history.FieldHash, field.TypeString, value)
|
||||||
|
_node.Hash = value
|
||||||
|
}
|
||||||
if value, ok := hc.mutation.Status(); ok {
|
if value, ok := hc.mutation.Status(); ok {
|
||||||
_spec.SetField(history.FieldStatus, field.TypeEnum, value)
|
_spec.SetField(history.FieldStatus, field.TypeEnum, value)
|
||||||
_node.Status = value
|
_node.Status = value
|
||||||
|
|||||||
@@ -259,6 +259,26 @@ func (hu *HistoryUpdate) ClearLink() *HistoryUpdate {
|
|||||||
return hu
|
return hu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetHash sets the "hash" field.
|
||||||
|
func (hu *HistoryUpdate) SetHash(s string) *HistoryUpdate {
|
||||||
|
hu.mutation.SetHash(s)
|
||||||
|
return hu
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableHash sets the "hash" field if the given value is not nil.
|
||||||
|
func (hu *HistoryUpdate) SetNillableHash(s *string) *HistoryUpdate {
|
||||||
|
if s != nil {
|
||||||
|
hu.SetHash(*s)
|
||||||
|
}
|
||||||
|
return hu
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearHash clears the value of the "hash" field.
|
||||||
|
func (hu *HistoryUpdate) ClearHash() *HistoryUpdate {
|
||||||
|
hu.mutation.ClearHash()
|
||||||
|
return hu
|
||||||
|
}
|
||||||
|
|
||||||
// SetStatus sets the "status" field.
|
// SetStatus sets the "status" field.
|
||||||
func (hu *HistoryUpdate) SetStatus(h history.Status) *HistoryUpdate {
|
func (hu *HistoryUpdate) SetStatus(h history.Status) *HistoryUpdate {
|
||||||
hu.mutation.SetStatus(h)
|
hu.mutation.SetStatus(h)
|
||||||
@@ -421,6 +441,12 @@ func (hu *HistoryUpdate) sqlSave(ctx context.Context) (n int, err error) {
|
|||||||
if hu.mutation.LinkCleared() {
|
if hu.mutation.LinkCleared() {
|
||||||
_spec.ClearField(history.FieldLink, field.TypeString)
|
_spec.ClearField(history.FieldLink, field.TypeString)
|
||||||
}
|
}
|
||||||
|
if value, ok := hu.mutation.Hash(); ok {
|
||||||
|
_spec.SetField(history.FieldHash, field.TypeString, value)
|
||||||
|
}
|
||||||
|
if hu.mutation.HashCleared() {
|
||||||
|
_spec.ClearField(history.FieldHash, field.TypeString)
|
||||||
|
}
|
||||||
if value, ok := hu.mutation.Status(); ok {
|
if value, ok := hu.mutation.Status(); ok {
|
||||||
_spec.SetField(history.FieldStatus, field.TypeEnum, value)
|
_spec.SetField(history.FieldStatus, field.TypeEnum, value)
|
||||||
}
|
}
|
||||||
@@ -680,6 +706,26 @@ func (huo *HistoryUpdateOne) ClearLink() *HistoryUpdateOne {
|
|||||||
return huo
|
return huo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetHash sets the "hash" field.
|
||||||
|
func (huo *HistoryUpdateOne) SetHash(s string) *HistoryUpdateOne {
|
||||||
|
huo.mutation.SetHash(s)
|
||||||
|
return huo
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNillableHash sets the "hash" field if the given value is not nil.
|
||||||
|
func (huo *HistoryUpdateOne) SetNillableHash(s *string) *HistoryUpdateOne {
|
||||||
|
if s != nil {
|
||||||
|
huo.SetHash(*s)
|
||||||
|
}
|
||||||
|
return huo
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearHash clears the value of the "hash" field.
|
||||||
|
func (huo *HistoryUpdateOne) ClearHash() *HistoryUpdateOne {
|
||||||
|
huo.mutation.ClearHash()
|
||||||
|
return huo
|
||||||
|
}
|
||||||
|
|
||||||
// SetStatus sets the "status" field.
|
// SetStatus sets the "status" field.
|
||||||
func (huo *HistoryUpdateOne) SetStatus(h history.Status) *HistoryUpdateOne {
|
func (huo *HistoryUpdateOne) SetStatus(h history.Status) *HistoryUpdateOne {
|
||||||
huo.mutation.SetStatus(h)
|
huo.mutation.SetStatus(h)
|
||||||
@@ -872,6 +918,12 @@ func (huo *HistoryUpdateOne) sqlSave(ctx context.Context) (_node *History, err e
|
|||||||
if huo.mutation.LinkCleared() {
|
if huo.mutation.LinkCleared() {
|
||||||
_spec.ClearField(history.FieldLink, field.TypeString)
|
_spec.ClearField(history.FieldLink, field.TypeString)
|
||||||
}
|
}
|
||||||
|
if value, ok := huo.mutation.Hash(); ok {
|
||||||
|
_spec.SetField(history.FieldHash, field.TypeString, value)
|
||||||
|
}
|
||||||
|
if huo.mutation.HashCleared() {
|
||||||
|
_spec.ClearField(history.FieldHash, field.TypeString)
|
||||||
|
}
|
||||||
if value, ok := huo.mutation.Status(); ok {
|
if value, ok := huo.mutation.Status(); ok {
|
||||||
_spec.SetField(history.FieldStatus, field.TypeEnum, value)
|
_spec.SetField(history.FieldStatus, field.TypeEnum, value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ var (
|
|||||||
{Name: "download_client_id", Type: field.TypeInt, Nullable: true},
|
{Name: "download_client_id", Type: field.TypeInt, Nullable: true},
|
||||||
{Name: "indexer_id", Type: field.TypeInt, Nullable: true},
|
{Name: "indexer_id", Type: field.TypeInt, Nullable: true},
|
||||||
{Name: "link", Type: field.TypeString, Nullable: true},
|
{Name: "link", Type: field.TypeString, Nullable: true},
|
||||||
|
{Name: "hash", Type: field.TypeString, Nullable: true},
|
||||||
{Name: "status", Type: field.TypeEnum, Enums: []string{"running", "success", "fail", "uploading", "seeding"}},
|
{Name: "status", Type: field.TypeEnum, Enums: []string{"running", "success", "fail", "uploading", "seeding"}},
|
||||||
{Name: "saved", Type: field.TypeString, Nullable: true},
|
{Name: "saved", Type: field.TypeString, Nullable: true},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2350,6 +2350,7 @@ type HistoryMutation struct {
|
|||||||
indexer_id *int
|
indexer_id *int
|
||||||
addindexer_id *int
|
addindexer_id *int
|
||||||
link *string
|
link *string
|
||||||
|
hash *string
|
||||||
status *history.Status
|
status *history.Status
|
||||||
saved *string
|
saved *string
|
||||||
clearedFields map[string]struct{}
|
clearedFields map[string]struct{}
|
||||||
@@ -3070,6 +3071,55 @@ func (m *HistoryMutation) ResetLink() {
|
|||||||
delete(m.clearedFields, history.FieldLink)
|
delete(m.clearedFields, history.FieldLink)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetHash sets the "hash" field.
|
||||||
|
func (m *HistoryMutation) SetHash(s string) {
|
||||||
|
m.hash = &s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash returns the value of the "hash" field in the mutation.
|
||||||
|
func (m *HistoryMutation) Hash() (r string, exists bool) {
|
||||||
|
v := m.hash
|
||||||
|
if v == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return *v, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// OldHash returns the old "hash" field's value of the History entity.
|
||||||
|
// If the History object wasn't provided to the builder, the object is fetched from the database.
|
||||||
|
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
|
||||||
|
func (m *HistoryMutation) OldHash(ctx context.Context) (v string, err error) {
|
||||||
|
if !m.op.Is(OpUpdateOne) {
|
||||||
|
return v, errors.New("OldHash is only allowed on UpdateOne operations")
|
||||||
|
}
|
||||||
|
if m.id == nil || m.oldValue == nil {
|
||||||
|
return v, errors.New("OldHash requires an ID field in the mutation")
|
||||||
|
}
|
||||||
|
oldValue, err := m.oldValue(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return v, fmt.Errorf("querying old value for OldHash: %w", err)
|
||||||
|
}
|
||||||
|
return oldValue.Hash, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearHash clears the value of the "hash" field.
|
||||||
|
func (m *HistoryMutation) ClearHash() {
|
||||||
|
m.hash = nil
|
||||||
|
m.clearedFields[history.FieldHash] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashCleared returns if the "hash" field was cleared in this mutation.
|
||||||
|
func (m *HistoryMutation) HashCleared() bool {
|
||||||
|
_, ok := m.clearedFields[history.FieldHash]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetHash resets all changes to the "hash" field.
|
||||||
|
func (m *HistoryMutation) ResetHash() {
|
||||||
|
m.hash = nil
|
||||||
|
delete(m.clearedFields, history.FieldHash)
|
||||||
|
}
|
||||||
|
|
||||||
// SetStatus sets the "status" field.
|
// SetStatus sets the "status" field.
|
||||||
func (m *HistoryMutation) SetStatus(h history.Status) {
|
func (m *HistoryMutation) SetStatus(h history.Status) {
|
||||||
m.status = &h
|
m.status = &h
|
||||||
@@ -3189,7 +3239,7 @@ func (m *HistoryMutation) 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 *HistoryMutation) Fields() []string {
|
func (m *HistoryMutation) Fields() []string {
|
||||||
fields := make([]string, 0, 13)
|
fields := make([]string, 0, 14)
|
||||||
if m.media_id != nil {
|
if m.media_id != nil {
|
||||||
fields = append(fields, history.FieldMediaID)
|
fields = append(fields, history.FieldMediaID)
|
||||||
}
|
}
|
||||||
@@ -3223,6 +3273,9 @@ func (m *HistoryMutation) Fields() []string {
|
|||||||
if m.link != nil {
|
if m.link != nil {
|
||||||
fields = append(fields, history.FieldLink)
|
fields = append(fields, history.FieldLink)
|
||||||
}
|
}
|
||||||
|
if m.hash != nil {
|
||||||
|
fields = append(fields, history.FieldHash)
|
||||||
|
}
|
||||||
if m.status != nil {
|
if m.status != nil {
|
||||||
fields = append(fields, history.FieldStatus)
|
fields = append(fields, history.FieldStatus)
|
||||||
}
|
}
|
||||||
@@ -3259,6 +3312,8 @@ func (m *HistoryMutation) Field(name string) (ent.Value, bool) {
|
|||||||
return m.IndexerID()
|
return m.IndexerID()
|
||||||
case history.FieldLink:
|
case history.FieldLink:
|
||||||
return m.Link()
|
return m.Link()
|
||||||
|
case history.FieldHash:
|
||||||
|
return m.Hash()
|
||||||
case history.FieldStatus:
|
case history.FieldStatus:
|
||||||
return m.Status()
|
return m.Status()
|
||||||
case history.FieldSaved:
|
case history.FieldSaved:
|
||||||
@@ -3294,6 +3349,8 @@ func (m *HistoryMutation) OldField(ctx context.Context, name string) (ent.Value,
|
|||||||
return m.OldIndexerID(ctx)
|
return m.OldIndexerID(ctx)
|
||||||
case history.FieldLink:
|
case history.FieldLink:
|
||||||
return m.OldLink(ctx)
|
return m.OldLink(ctx)
|
||||||
|
case history.FieldHash:
|
||||||
|
return m.OldHash(ctx)
|
||||||
case history.FieldStatus:
|
case history.FieldStatus:
|
||||||
return m.OldStatus(ctx)
|
return m.OldStatus(ctx)
|
||||||
case history.FieldSaved:
|
case history.FieldSaved:
|
||||||
@@ -3384,6 +3441,13 @@ func (m *HistoryMutation) SetField(name string, value ent.Value) error {
|
|||||||
}
|
}
|
||||||
m.SetLink(v)
|
m.SetLink(v)
|
||||||
return nil
|
return nil
|
||||||
|
case history.FieldHash:
|
||||||
|
v, ok := value.(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
||||||
|
}
|
||||||
|
m.SetHash(v)
|
||||||
|
return nil
|
||||||
case history.FieldStatus:
|
case history.FieldStatus:
|
||||||
v, ok := value.(history.Status)
|
v, ok := value.(history.Status)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -3521,6 +3585,9 @@ func (m *HistoryMutation) ClearedFields() []string {
|
|||||||
if m.FieldCleared(history.FieldLink) {
|
if m.FieldCleared(history.FieldLink) {
|
||||||
fields = append(fields, history.FieldLink)
|
fields = append(fields, history.FieldLink)
|
||||||
}
|
}
|
||||||
|
if m.FieldCleared(history.FieldHash) {
|
||||||
|
fields = append(fields, history.FieldHash)
|
||||||
|
}
|
||||||
if m.FieldCleared(history.FieldSaved) {
|
if m.FieldCleared(history.FieldSaved) {
|
||||||
fields = append(fields, history.FieldSaved)
|
fields = append(fields, history.FieldSaved)
|
||||||
}
|
}
|
||||||
@@ -3556,6 +3623,9 @@ func (m *HistoryMutation) ClearField(name string) error {
|
|||||||
case history.FieldLink:
|
case history.FieldLink:
|
||||||
m.ClearLink()
|
m.ClearLink()
|
||||||
return nil
|
return nil
|
||||||
|
case history.FieldHash:
|
||||||
|
m.ClearHash()
|
||||||
|
return nil
|
||||||
case history.FieldSaved:
|
case history.FieldSaved:
|
||||||
m.ClearSaved()
|
m.ClearSaved()
|
||||||
return nil
|
return nil
|
||||||
@@ -3600,6 +3670,9 @@ func (m *HistoryMutation) ResetField(name string) error {
|
|||||||
case history.FieldLink:
|
case history.FieldLink:
|
||||||
m.ResetLink()
|
m.ResetLink()
|
||||||
return nil
|
return nil
|
||||||
|
case history.FieldHash:
|
||||||
|
m.ResetHash()
|
||||||
|
return nil
|
||||||
case history.FieldStatus:
|
case history.FieldStatus:
|
||||||
m.ResetStatus()
|
m.ResetStatus()
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ func (History) Fields() []ent.Field {
|
|||||||
field.Int("size").Default(0),
|
field.Int("size").Default(0),
|
||||||
field.Int("download_client_id").Optional(),
|
field.Int("download_client_id").Optional(),
|
||||||
field.Int("indexer_id").Optional(),
|
field.Int("indexer_id").Optional(),
|
||||||
field.String("link").Optional(), //should be magnet link
|
field.String("link").Optional().Comment("deprecated, use hash instead"), //should be magnet link
|
||||||
|
field.String("hash").Optional().Comment("torrent hash"),
|
||||||
field.Enum("status").Values("running", "success", "fail", "uploading", "seeding"),
|
field.Enum("status").Values("running", "success", "fail", "uploading", "seeding"),
|
||||||
field.String("saved").Optional().Comment("deprecated"), //deprecated
|
field.String("saved").Optional().Comment("deprecated"), //deprecated
|
||||||
}
|
}
|
||||||
|
|||||||
8
go.sum
8
go.sum
@@ -216,6 +216,8 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V
|
|||||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
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 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
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.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
@@ -249,6 +251,8 @@ github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt
|
|||||||
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
|
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
|
||||||
github.com/nikoksr/notify v1.0.0 h1:qe9/6FRsWdxBgQgWcpvQ0sv8LRGJZDpRB4TkL2uNdO8=
|
github.com/nikoksr/notify v1.0.0 h1:qe9/6FRsWdxBgQgWcpvQ0sv8LRGJZDpRB4TkL2uNdO8=
|
||||||
github.com/nikoksr/notify v1.0.0/go.mod h1:hPaaDt30d6LAA7/5nb0e48Bp/MctDfycCSs8VEgN29I=
|
github.com/nikoksr/notify v1.0.0/go.mod h1:hPaaDt30d6LAA7/5nb0e48Bp/MctDfycCSs8VEgN29I=
|
||||||
|
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||||
|
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
@@ -306,6 +310,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/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 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
||||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
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 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||||
@@ -447,6 +453,8 @@ golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3
|
|||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||||
|
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golift.io/starr v1.0.0 h1:IDSaSL+ZYxdLT/Lg//dg/iwZ39LHO3D5CmbLCOgSXbI=
|
golift.io/starr v1.0.0 h1:IDSaSL+ZYxdLT/Lg//dg/iwZ39LHO3D5CmbLCOgSXbI=
|
||||||
|
|||||||
@@ -18,5 +18,5 @@ type Torrent interface {
|
|||||||
|
|
||||||
type Downloader interface {
|
type Downloader interface {
|
||||||
GetAll() ([]Torrent, error)
|
GetAll() ([]Torrent, error)
|
||||||
Download(link, dir string) (Torrent, error)
|
Download(link, hash, dir string) (Torrent, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,49 +61,45 @@ func (c *Client) GetAll() ([]pkg.Torrent, error) {
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Download(link, dir string) (pkg.Torrent, error) {
|
func (c *Client) Download(link, hash, dir string) (pkg.Torrent, error) {
|
||||||
err := c.c.DownloadLinks([]string{link}, qbt.DownloadOptions{Savepath: &dir, Category: &c.category})
|
err := c.c.DownloadLinks([]string{link}, qbt.DownloadOptions{Savepath: &dir, Category: &c.category})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "qbt download")
|
return nil, errors.Wrap(err, "qbt download")
|
||||||
}
|
}
|
||||||
magnet, err := utils.Link2Magnet(link)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Errorf("converting link to magnet error, link: %v, error: %v", link, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
hash, err := utils.MagnetHash(magnet)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "get hash")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Torrent{hash: hash, c: c.c}, nil
|
return &Torrent{hash: hash, c: c.c}, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTorrent(info Info, link string) (*Torrent, error) {
|
func NewTorrentHash(info Info, hash string) (*Torrent, error) {
|
||||||
c, err := NewClient(info.URL, info.User, info.Password)
|
c, err := NewClient(info.URL, info.User, info.Password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
magnet, err := utils.Link2Magnet(link)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Errorf("converting link to magnet error, link: %v, error: %v", link, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
hash, err := utils.MagnetHash(magnet)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
t := &Torrent{
|
t := &Torrent{
|
||||||
c: c.c,
|
c: c.c,
|
||||||
hash: hash,
|
hash: hash,
|
||||||
}
|
}
|
||||||
if !t.Exists() {
|
if !t.Exists() {
|
||||||
return nil, errors.Errorf("torrent not exist: %v", magnet)
|
return nil, errors.Errorf("torrent not exist: %v", hash)
|
||||||
}
|
}
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewTorrent(info Info, link string) (*Torrent, error) {
|
||||||
|
magnet, err := utils.Link2Magnet(link)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("converting link to magnet error, link: %v, error: %v", link, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hash, err := utils.MagnetHash(magnet)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewTorrentHash(info, hash)
|
||||||
|
}
|
||||||
|
|
||||||
type Torrent struct {
|
type Torrent struct {
|
||||||
c *qbt.Client
|
c *qbt.Client
|
||||||
hash string
|
hash string
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ func (c *Client) GetAll() ([]pkg.Torrent, error) {
|
|||||||
return torrents, nil
|
return torrents, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Download(link, dir string) (pkg.Torrent, error) {
|
func (c *Client) Download(link, hash, dir string) (pkg.Torrent, error) {
|
||||||
|
|
||||||
t, err := c.c.TorrentAdd(context.TODO(), transmissionrpc.TorrentAddPayload{
|
t, err := c.c.TorrentAdd(context.TODO(), transmissionrpc.TorrentAddPayload{
|
||||||
Filename: &link,
|
Filename: &link,
|
||||||
@@ -74,16 +74,6 @@ func (c *Client) Download(link, dir string) (pkg.Torrent, error) {
|
|||||||
}
|
}
|
||||||
log.Debugf("get torrent info: %+v", t)
|
log.Debugf("get torrent info: %+v", t)
|
||||||
|
|
||||||
magnet, err := utils.Link2Magnet(link)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Errorf("converting link to magnet error, link: %v, error: %v", link, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
hash, err := utils.MagnetHash(magnet)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "get hash")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Torrent{
|
return &Torrent{
|
||||||
hash: hash,
|
hash: hash,
|
||||||
c: c.c,
|
c: c.c,
|
||||||
@@ -91,33 +81,38 @@ func (c *Client) Download(link, dir string) (pkg.Torrent, error) {
|
|||||||
}, err
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTorrent(cfg Config, link string) (*Torrent, error) {
|
func NewTorrentHash(cfg Config, hash string) (*Torrent, error) {
|
||||||
c, err := NewClient(cfg)
|
c, err := NewClient(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
magnet, err := utils.Link2Magnet(link)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Errorf("converting link to magnet error, link: %v, error: %v", link, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
hash, err := utils.MagnetHash(magnet)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
t := &Torrent{
|
t := &Torrent{
|
||||||
c: c.c,
|
c: c.c,
|
||||||
hash: hash,
|
hash: hash,
|
||||||
//cfg: cfg,
|
//cfg: cfg,
|
||||||
}
|
}
|
||||||
if !t.Exists() {
|
if !t.Exists() {
|
||||||
return nil, errors.Errorf("torrent not exist: %v", magnet)
|
return nil, errors.Errorf("torrent not exist: %v", hash)
|
||||||
}
|
}
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewTorrent(cfg Config, link string) (*Torrent, error) {
|
||||||
|
|
||||||
|
magnet, err := utils.Link2Magnet(link)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("converting link to magnet error, link: %v, error: %v", link, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hash, err := utils.MagnetHash(magnet)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewTorrentHash(cfg, hash)
|
||||||
|
}
|
||||||
|
|
||||||
type Torrent struct {
|
type Torrent struct {
|
||||||
//t *transmissionrpc.Torrent
|
//t *transmissionrpc.Torrent
|
||||||
c *transmissionrpc.Client
|
c *transmissionrpc.Client
|
||||||
|
|||||||
@@ -222,6 +222,33 @@ func isWSL() bool {
|
|||||||
return strings.Contains(strings.ToLower(string(releaseData)), "microsoft")
|
return strings.Contains(strings.ToLower(string(releaseData)), "microsoft")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Link2Hash(link string) (string, error) {
|
||||||
|
if strings.HasPrefix(strings.ToLower(link), "magnet:") {
|
||||||
|
return MagnetHash(link)
|
||||||
|
}
|
||||||
|
client := &http.Client{
|
||||||
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
|
return http.ErrUseLastResponse //do not follow redirects
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Get(link)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "get link")
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode >= 300 && resp.StatusCode < 400 {
|
||||||
|
//redirects
|
||||||
|
tourl := resp.Header.Get("Location")
|
||||||
|
return Link2Hash(tourl)
|
||||||
|
}
|
||||||
|
info, err := metainfo.Load(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "parse response")
|
||||||
|
}
|
||||||
|
return info.HashInfoBytes().AsString(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func Link2Magnet(link string) (string, error) {
|
func Link2Magnet(link string) (string, error) {
|
||||||
if strings.HasPrefix(strings.ToLower(link), "magnet:") {
|
if strings.HasPrefix(strings.ToLower(link), "magnet:") {
|
||||||
return link, nil
|
return link, nil
|
||||||
|
|||||||
@@ -59,27 +59,55 @@ func (c *Client) reloadTasks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if dl.Implementation == downloadclients.ImplementationTransmission {
|
if dl.Implementation == downloadclients.ImplementationTransmission {
|
||||||
to, err := transmission.NewTorrent(transmission.Config{
|
if t.Hash != "" { //优先使用hash
|
||||||
URL: dl.URL,
|
to, err := transmission.NewTorrentHash(transmission.Config{
|
||||||
User: dl.User,
|
URL: dl.URL,
|
||||||
Password: dl.Password,
|
User: dl.User,
|
||||||
}, t.Link)
|
Password: dl.Password,
|
||||||
if err != nil {
|
}, t.Hash)
|
||||||
log.Warnf("get task error: %v", err)
|
if err != nil {
|
||||||
continue
|
log.Warnf("get task error: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c.tasks[t.ID] = &Task{Torrent: to}
|
||||||
|
} else if t.Link != "" {
|
||||||
|
to, err := transmission.NewTorrent(transmission.Config{
|
||||||
|
URL: dl.URL,
|
||||||
|
User: dl.User,
|
||||||
|
Password: dl.Password,
|
||||||
|
}, t.Link)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("get task error: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c.tasks[t.ID] = &Task{Torrent: to}
|
||||||
}
|
}
|
||||||
c.tasks[t.ID] = &Task{Torrent: to}
|
|
||||||
} else if dl.Implementation == downloadclients.ImplementationQbittorrent {
|
} else if dl.Implementation == downloadclients.ImplementationQbittorrent {
|
||||||
to, err := qbittorrent.NewTorrent(qbittorrent.Info{
|
if t.Hash != "" {
|
||||||
URL: dl.URL,
|
to, err := qbittorrent.NewTorrentHash(qbittorrent.Info{
|
||||||
User: dl.User,
|
URL: dl.URL,
|
||||||
Password: dl.Password,
|
User: dl.User,
|
||||||
}, t.Link)
|
Password: dl.Password,
|
||||||
if err != nil {
|
}, t.Hash)
|
||||||
log.Warnf("get task error: %v", err)
|
if err != nil {
|
||||||
continue
|
log.Warnf("get task error: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c.tasks[t.ID] = &Task{Torrent: to}
|
||||||
|
|
||||||
|
} else if t.Link != "" {
|
||||||
|
to, err := qbittorrent.NewTorrent(qbittorrent.Info{
|
||||||
|
URL: dl.URL,
|
||||||
|
User: dl.User,
|
||||||
|
Password: dl.Password,
|
||||||
|
}, t.Link)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("get task error: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c.tasks[t.ID] = &Task{Torrent: to}
|
||||||
|
|
||||||
}
|
}
|
||||||
c.tasks[t.ID] = &Task{Torrent: to}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"polaris/ent"
|
"polaris/ent"
|
||||||
"polaris/ent/episode"
|
"polaris/ent/episode"
|
||||||
"polaris/ent/history"
|
"polaris/ent/history"
|
||||||
|
"polaris/ent/media"
|
||||||
"polaris/log"
|
"polaris/log"
|
||||||
"polaris/pkg/metadata"
|
"polaris/pkg/metadata"
|
||||||
"polaris/pkg/notifier/message"
|
"polaris/pkg/notifier/message"
|
||||||
@@ -16,95 +17,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) DownloadEpisodeTorrent(r1 torznab.Result, seriesId, seasonNum int, episodeNums ...int) (*string, error) {
|
func (c *Client) DownloadEpisodeTorrent(r1 torznab.Result, seriesId, seasonNum int, episodeNums ...int) (*string, error) {
|
||||||
trc, dlc, err := c.GetDownloadClient()
|
|
||||||
|
series, err := c.db.GetMedia(seriesId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "connect transmission")
|
|
||||||
}
|
|
||||||
series := c.db.GetMediaDetails(seriesId)
|
|
||||||
if series == nil {
|
|
||||||
return nil, fmt.Errorf("no tv series of id %v", seriesId)
|
return nil, fmt.Errorf("no tv series of id %v", seriesId)
|
||||||
}
|
}
|
||||||
|
|
||||||
//check space available
|
return c.downloadTorrent(series, r1, seasonNum, episodeNums...)
|
||||||
downloadDir := c.db.GetDownloadDir()
|
|
||||||
size := utils.AvailableSpace(downloadDir)
|
|
||||||
if size < uint64(r1.Size) {
|
|
||||||
log.Errorf("space available %v, space needed %v", size, r1.Size)
|
|
||||||
return nil, errors.New("no enough space")
|
|
||||||
}
|
|
||||||
|
|
||||||
// magnet, err := utils.Link2Magnet(r1.Link)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, errors.Errorf("converting link to magnet error, link: %v, error: %v", r1.Link, err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
dir := fmt.Sprintf("%s/Season %02d/", series.TargetDir, seasonNum)
|
|
||||||
|
|
||||||
if len(episodeNums) > 0 {
|
|
||||||
for _, epNum := range episodeNums {
|
|
||||||
var ep *ent.Episode
|
|
||||||
for _, e := range series.Episodes {
|
|
||||||
if e.SeasonNumber == seasonNum && e.EpisodeNumber == epNum {
|
|
||||||
ep = e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ep == nil {
|
|
||||||
return nil, errors.Errorf("no episode of season %d episode %d", seasonNum, epNum)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ep.Status == episode.StatusMissing {
|
|
||||||
c.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} else { //season package download
|
|
||||||
c.db.SetSeasonAllEpisodeStatus(seriesId, seasonNum, episode.StatusDownloading)
|
|
||||||
|
|
||||||
}
|
|
||||||
history, err := c.db.SaveHistoryRecord(ent.History{
|
|
||||||
MediaID: seriesId,
|
|
||||||
EpisodeNums: episodeNums,
|
|
||||||
SeasonNum: seasonNum,
|
|
||||||
SourceTitle: r1.Name,
|
|
||||||
TargetDir: dir,
|
|
||||||
Status: history.StatusRunning,
|
|
||||||
Size: int(r1.Size),
|
|
||||||
//Saved: torrent.Save(),
|
|
||||||
Link: r1.Link,
|
|
||||||
DownloadClientID: dlc.ID,
|
|
||||||
IndexerID: r1.IndexerId,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "save record")
|
|
||||||
}
|
|
||||||
|
|
||||||
torrent, err := trc.Download(r1.Link, downloadDir)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "downloading")
|
|
||||||
}
|
|
||||||
torrent.Start()
|
|
||||||
|
|
||||||
c.tasks[history.ID] = &Task{Torrent: torrent}
|
|
||||||
name := r1.Name
|
|
||||||
|
|
||||||
if len(episodeNums) > 0 {
|
|
||||||
buff := &bytes.Buffer{}
|
|
||||||
for i, ep := range episodeNums {
|
|
||||||
if i != 0 {
|
|
||||||
buff.WriteString(",")
|
|
||||||
|
|
||||||
}
|
|
||||||
buff.WriteString(fmt.Sprint(ep))
|
|
||||||
}
|
|
||||||
name = fmt.Sprintf("第%s集 (%s)", buff.String(), name)
|
|
||||||
} else {
|
|
||||||
name = fmt.Sprintf("全集 (%s)", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.sendMsg(fmt.Sprintf(message.BeginDownload, name))
|
|
||||||
|
|
||||||
log.Infof("success add %s to download task", r1.Name)
|
|
||||||
return &r1.Name, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -192,53 +111,95 @@ lo:
|
|||||||
return torrentNames, nil
|
return torrentNames, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) DownloadMovie(m *ent.Media, link, name string, size int64, indexerID int) (*string, error) {
|
func (c *Client) DownloadMovie(m *ent.Media, r1 torznab.Result) (*string, error) {
|
||||||
|
return c.downloadTorrent(m, r1, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) downloadTorrent(m *ent.Media, r1 torznab.Result, seasonNum int, episodeNums ...int) (*string, error) {
|
||||||
trc, dlc, err := c.GetDownloadClient()
|
trc, dlc, err := c.GetDownloadClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "connect transmission")
|
return nil, errors.Wrap(err, "connect transmission")
|
||||||
}
|
}
|
||||||
// magnet, err := utils.Link2Magnet(link)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, errors.Errorf("converting link to magnet error, link: %v, error: %v", link, err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
torrent, err := trc.Download(link, c.db.GetDownloadDir())
|
//check space available
|
||||||
|
downloadDir := c.db.GetDownloadDir()
|
||||||
|
size := utils.AvailableSpace(downloadDir)
|
||||||
|
if size < uint64(r1.Size) {
|
||||||
|
log.Errorf("space available %v, space needed %v", size, r1.Size)
|
||||||
|
return nil, errors.New("no enough space")
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = r1.Name
|
||||||
|
var targetDir = m.TargetDir
|
||||||
|
if m.MediaType == media.MediaTypeTv { //tv download
|
||||||
|
targetDir = fmt.Sprintf("%s/Season %02d/", m.TargetDir, seasonNum)
|
||||||
|
|
||||||
|
if len(episodeNums) > 0 {
|
||||||
|
for _, epNum := range episodeNums {
|
||||||
|
ep, err := c.db.GetEpisode(m.ID, seasonNum, epNum)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("no episode of season %d episode %d", seasonNum, epNum)
|
||||||
|
|
||||||
|
}
|
||||||
|
if ep.Status == episode.StatusMissing {
|
||||||
|
c.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buff := &bytes.Buffer{}
|
||||||
|
for i, ep := range episodeNums {
|
||||||
|
if i != 0 {
|
||||||
|
buff.WriteString(",")
|
||||||
|
|
||||||
|
}
|
||||||
|
buff.WriteString(fmt.Sprint(ep))
|
||||||
|
}
|
||||||
|
name = fmt.Sprintf("第%s集 (%s)", buff.String(), name)
|
||||||
|
|
||||||
|
} else { //season package download
|
||||||
|
name = fmt.Sprintf("全集 (%s)", name)
|
||||||
|
c.db.SetSeasonAllEpisodeStatus(m.ID, seasonNum, episode.StatusDownloading)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ep, _ := c.db.GetMovieDummyEpisode(m.ID)
|
||||||
|
if ep.Status == episode.StatusMissing {
|
||||||
|
c.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
hash, err := utils.Link2Hash(r1.Link)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "get hash")
|
||||||
|
}
|
||||||
|
history, err := c.db.SaveHistoryRecord(ent.History{
|
||||||
|
MediaID: m.ID,
|
||||||
|
EpisodeNums: episodeNums,
|
||||||
|
SeasonNum: seasonNum,
|
||||||
|
SourceTitle: r1.Name,
|
||||||
|
TargetDir: targetDir,
|
||||||
|
Status: history.StatusRunning,
|
||||||
|
Size: int(r1.Size),
|
||||||
|
//Saved: torrent.Save(),
|
||||||
|
Link: r1.Link,
|
||||||
|
Hash: hash,
|
||||||
|
DownloadClientID: dlc.ID,
|
||||||
|
IndexerID: r1.IndexerId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "save record")
|
||||||
|
}
|
||||||
|
|
||||||
|
torrent, err := trc.Download(r1.Link, hash, downloadDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "downloading")
|
return nil, errors.Wrap(err, "downloading")
|
||||||
}
|
}
|
||||||
torrent.Start()
|
torrent.Start()
|
||||||
|
|
||||||
if name == "" {
|
c.tasks[history.ID] = &Task{Torrent: torrent}
|
||||||
name = m.OriginalName
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
ep, _ := c.db.GetMovieDummyEpisode(m.ID)
|
|
||||||
history, err := c.db.SaveHistoryRecord(ent.History{
|
|
||||||
MediaID: m.ID,
|
|
||||||
EpisodeID: ep.ID,
|
|
||||||
SourceTitle: name,
|
|
||||||
TargetDir: m.TargetDir,
|
|
||||||
Status: history.StatusRunning,
|
|
||||||
Size: int(size),
|
|
||||||
//Saved: torrent.Save(),
|
|
||||||
Link: link,
|
|
||||||
DownloadClientID: dlc.ID,
|
|
||||||
IndexerID: indexerID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("save history error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.tasks[history.ID] = &Task{Torrent: torrent}
|
|
||||||
|
|
||||||
if ep.Status == episode.StatusMissing {
|
|
||||||
c.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
|
||||||
}
|
|
||||||
|
|
||||||
}()
|
|
||||||
|
|
||||||
c.sendMsg(fmt.Sprintf(message.BeginDownload, name))
|
c.sendMsg(fmt.Sprintf(message.BeginDownload, name))
|
||||||
log.Infof("success add %s to download task", name)
|
|
||||||
return &name, nil
|
|
||||||
|
|
||||||
|
log.Infof("success add %s to download task", r1.Name)
|
||||||
|
|
||||||
|
return &r1.Name, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -459,18 +459,15 @@ func (c *Client) DownloadMovieByID(id int) (string, error) {
|
|||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if name, err := c.downloadMovieSingleEpisode(ep, detail.TargetDir); err != nil {
|
if name, err := c.downloadMovieSingleEpisode(detail.Media, ep); err != nil {
|
||||||
return "", errors.Wrap(err, "download movie")
|
return "", errors.Wrap(err, "download movie")
|
||||||
} else {
|
} else {
|
||||||
return name, nil
|
return name, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) downloadMovieSingleEpisode(ep *ent.Episode, targetDir string) (string, error) {
|
func (c *Client) downloadMovieSingleEpisode(m *ent.Media, ep *ent.Episode) (string, error) {
|
||||||
trc, dlc, err := c.GetDownloadClient()
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrap(err, "connect transmission")
|
|
||||||
}
|
|
||||||
qiangban := c.db.GetSetting(db.SettingAllowQiangban)
|
qiangban := c.db.GetSetting(db.SettingAllowQiangban)
|
||||||
allowQiangban := false
|
allowQiangban := false
|
||||||
if qiangban == "true" {
|
if qiangban == "true" {
|
||||||
@@ -484,43 +481,16 @@ func (c *Client) downloadMovieSingleEpisode(ep *ent.Episode, targetDir string) (
|
|||||||
FilterQiangban: !allowQiangban,
|
FilterQiangban: !allowQiangban,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
return "", errors.Wrap(err, "search movie")
|
return "", errors.Wrap(err, "search movie")
|
||||||
}
|
}
|
||||||
r1 := res[0]
|
r1 := res[0]
|
||||||
log.Infof("begin download torrent resource: %v", r1.Name)
|
log.Infof("begin download torrent resource: %v", r1.Name)
|
||||||
|
|
||||||
magnet, err := utils.Link2Magnet(r1.Link)
|
s, err := c.downloadTorrent(m, r1, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Errorf("converting link to magnet error, link: %v, error: %v", r1.Link, err)
|
return "", err
|
||||||
}
|
}
|
||||||
|
return *s, nil
|
||||||
torrent, err := trc.Download(magnet, c.db.GetDownloadDir())
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrap(err, "downloading")
|
|
||||||
}
|
|
||||||
torrent.Start()
|
|
||||||
|
|
||||||
history, err := c.db.SaveHistoryRecord(ent.History{
|
|
||||||
MediaID: ep.MediaID,
|
|
||||||
EpisodeID: ep.ID,
|
|
||||||
SourceTitle: r1.Name,
|
|
||||||
TargetDir: targetDir,
|
|
||||||
Status: history.StatusRunning,
|
|
||||||
Size: int(r1.Size),
|
|
||||||
//Saved: torrent.Save(),
|
|
||||||
Link: magnet,
|
|
||||||
DownloadClientID: dlc.ID,
|
|
||||||
IndexerID: r1.IndexerId,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("save history error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.tasks[history.ID] = &Task{Torrent: torrent}
|
|
||||||
|
|
||||||
c.db.SetEpisodeStatus(ep.ID, episode.StatusDownloading)
|
|
||||||
return r1.Name, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) checkAllSeriesNewSeason() error {
|
func (c *Client) checkAllSeriesNewSeason() error {
|
||||||
|
|||||||
@@ -164,7 +164,13 @@ func (s *Server) DownloadTorrent(c *gin.Context) (interface{}, error) {
|
|||||||
return s.core.DownloadEpisodeTorrent(res, in.MediaID, in.Season, in.Episode)
|
return s.core.DownloadEpisodeTorrent(res, in.MediaID, in.Season, in.Episode)
|
||||||
} else {
|
} else {
|
||||||
//movie
|
//movie
|
||||||
return s.core.DownloadMovie(m, in.Link, in.Name, in.Size, in.IndexerId)
|
name := in.Name
|
||||||
|
if name == "" {
|
||||||
|
name = m.OriginalName
|
||||||
|
}
|
||||||
|
|
||||||
|
res := torznab.Result{Name: name, Link: in.Link, Size: in.Size, IndexerId: in.IndexerId}
|
||||||
|
return s.core.DownloadMovie(m, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user