Too many changes to mention.
Now atleast partially works
This commit is contained in:
parent
0e17c2c44c
commit
da7e541666
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
TorrentFilter
|
||||
vendor
|
||||
|
236
main.go
236
main.go
@ -2,69 +2,253 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"timmy.narnian.us/git/timmy/scene"
|
||||
|
||||
"github.com/alexflint/go-arg"
|
||||
"github.com/lordwelch/transmission"
|
||||
)
|
||||
|
||||
var (
|
||||
current_torrents SeriesTorrent
|
||||
unselectedDir string
|
||||
CurrentTorrents map[string]SeriesTorrent
|
||||
unselectedDir string
|
||||
Transmission *transmission.Client
|
||||
mutex = new(sync.Mutex)
|
||||
|
||||
args struct {
|
||||
RES string `arg:"help:Resolution preference [480/720/1080]"`
|
||||
RELEASE []string `arg:"-r,help:Release group preference order."`
|
||||
NRELEASE []string `arg:"-R,help:Release groups to use only as a lost resort."`
|
||||
TAGS []string `arg:"-t,help:Tags to prefer -t internal would choose an internal over another. Whichever file with the most tags is chosen. Release Group takes priority"`
|
||||
Series []string `arg:"required,positional,help:TV series to download torrent file for"`
|
||||
NEW bool `arg:"-n,help:Only modify new torrents"`
|
||||
PATH string `arg:"-P,required,help:Path to torrent files"`
|
||||
}
|
||||
)
|
||||
|
||||
func main() {
|
||||
var (
|
||||
torrentName string
|
||||
torrentPath string
|
||||
args struct {
|
||||
RES string `arg:"help:Resolution preference [480/720/1080]"`
|
||||
RELEASE []string `arg:"-r,help:Release group preference order."`
|
||||
TAGS []string `arg:"-t, help:Tags to prefer -t internal would choose an internal over another"`
|
||||
Series []string `arg:"required,positional,help:TV series to download"`
|
||||
NEW bool `arg:"-n,help:Only modify new torrents"`
|
||||
PATH string `arg:"-P,help:Path to torrent files"`
|
||||
}
|
||||
stdC = make(chan *SceneVideoTorrent)
|
||||
)
|
||||
initialize()
|
||||
go stdinLoop(stdC)
|
||||
|
||||
arg.MustParse(&args)
|
||||
if len(args.PATH) < 1 {
|
||||
args.PATH, _ = os.Getwd()
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Minute * 15):
|
||||
download()
|
||||
|
||||
case current := <-stdC:
|
||||
mutex.Lock()
|
||||
addtorrent(CurrentTorrents[current.Title], current)
|
||||
mutex.Unlock()
|
||||
}
|
||||
}
|
||||
unselectedDir = filepath.Clean(args.PATH + "/unselected/")
|
||||
}
|
||||
|
||||
func stdinLoop(C chan *SceneVideoTorrent) {
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
url := strings.TrimSpace(scanner.Text())
|
||||
torrentName = filepath.Base(url)
|
||||
torrentPath = filepath.Join(unselectedDir, torrentName)
|
||||
torrentName := filepath.Base(url)
|
||||
torrentPath := filepath.Join(unselectedDir, torrentName)
|
||||
_, err := os.Stat(torrentPath)
|
||||
if !os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
cmd := exec.Command("wget", url, "-q", "-O", torrentPath)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
fmt.Println()
|
||||
|
||||
err = cmd.Run()
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("url failed: ", url)
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
process(torrentPath)
|
||||
current := process(torrentPath)
|
||||
for _, title := range args.Series {
|
||||
if current.Title == title {
|
||||
C <- current
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func download() {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
hash := removeLinks()
|
||||
removeDownloads(hash)
|
||||
|
||||
for _, s := range CurrentTorrents {
|
||||
for _, se := range s {
|
||||
for _, ep := range se {
|
||||
fmt.Println("symlink", ep.Ep[0].Title, ep.Ep[0].Season, ep.Ep[0].Episode)
|
||||
os.Symlink(ep.Ep[0].Meta.FilePath, filepath.Join(filepath.Join(ep.Ep[0].Meta.FilePath, "../../"), filepath.Base(ep.Ep[0].Meta.FilePath)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func addtorrent(St SeriesTorrent, torrent *SceneVideoTorrent) {
|
||||
_, ok := St[torrent.Season]
|
||||
if !ok {
|
||||
St[torrent.Season] = make(SeasonTorrent, 20)
|
||||
}
|
||||
Ep := St[torrent.Season][torrent.Episode]
|
||||
if Ep == nil {
|
||||
RES, _ := strconv.Atoi(args.RES)
|
||||
St[torrent.Season][torrent.Episode] = &EpisodeTorrent{
|
||||
Tags: make(map[string]int),
|
||||
Release: make(map[string]int),
|
||||
Res: scene.Res(RES),
|
||||
}
|
||||
|
||||
for i, v := range args.RELEASE {
|
||||
if i+1 == 0 {
|
||||
panic("You do not exist in a world that I know of")
|
||||
}
|
||||
St[torrent.Season][torrent.Episode].Release[v] = i + 1
|
||||
}
|
||||
for i, v := range args.NRELEASE {
|
||||
if i+1 == 0 {
|
||||
panic("You do not exist in a world that I know of")
|
||||
}
|
||||
St[torrent.Season][torrent.Episode].Release[v] = i + 1000000
|
||||
}
|
||||
for i, v := range args.TAGS {
|
||||
if i+1 == 0 {
|
||||
panic("You do not exist in a world that I know of")
|
||||
}
|
||||
St[torrent.Season][torrent.Episode].Tags[v] = i + 1
|
||||
}
|
||||
}
|
||||
St[torrent.Season][torrent.Episode].Add(torrent)
|
||||
}
|
||||
|
||||
// Get hashes of torrents that were previously selected then remove the link to them
|
||||
func removeLinks() (hash []string) {
|
||||
selectedDir := filepath.Join(unselectedDir, "../")
|
||||
selectedFolder, _ := os.Open(selectedDir)
|
||||
//fmt.Println("selected dir", selectedDir)
|
||||
defer selectedFolder.Close()
|
||||
|
||||
selectedNames, _ := selectedFolder.Readdirnames(0)
|
||||
for _, lnk := range selectedNames {
|
||||
target, err := os.Readlink(filepath.Join(selectedDir, lnk))
|
||||
//fmt.Println(target)
|
||||
//fmt.Println(err)
|
||||
|
||||
if err == nil {
|
||||
if filepath.Base(filepath.Dir(target)) == "unselected" {
|
||||
hash = append(hash, process(target).Meta.Hash)
|
||||
|
||||
os.Remove(filepath.Join(selectedDir, lnk))
|
||||
}
|
||||
}
|
||||
}
|
||||
selectedNames, _ = selectedFolder.Readdirnames(0)
|
||||
fmt.Println(selectedNames)
|
||||
return
|
||||
}
|
||||
|
||||
func removeDownloads(hash []string) {
|
||||
tmap, err := Transmission.GetTorrentMap()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
thash := make([]string, len(hash))
|
||||
// Removes torrents from transmission that are not selected this time
|
||||
for _, CHash := range hash {
|
||||
v, ok := tmap[CHash]
|
||||
if ok {
|
||||
current := scene.Parse(v.Name)
|
||||
if CurrentTorrents[current.Title][current.Season][current.Episode].Ep[0].Meta.Hash != CHash {
|
||||
thash = append(thash, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
Transmission.RemoveTorrents(false, thash...)
|
||||
}
|
||||
|
||||
func initialize() {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
||||
args.PATH, _ = os.Getwd()
|
||||
args.RES = "-1"
|
||||
arg.MustParse(&args)
|
||||
|
||||
CurrentTorrents = make(map[string]SeriesTorrent, len(args.Series))
|
||||
for _, title := range args.Series {
|
||||
fmt.Println(title)
|
||||
CurrentTorrents[title] = make(SeriesTorrent, 10)
|
||||
}
|
||||
|
||||
unselectedDir, _ = filepath.Abs(filepath.Join(args.PATH, "unselected/"))
|
||||
|
||||
//fmt.Println("unselected dir:", unselectedDir)
|
||||
// Load all downloaded torrents
|
||||
unselectedFolder, _ := os.Open(unselectedDir)
|
||||
defer unselectedFolder.Close()
|
||||
unselectedNames, _ := unselectedFolder.Readdirnames(0)
|
||||
sort.Strings(unselectedNames)
|
||||
for _, name := range unselectedNames {
|
||||
current := process(filepath.Join(unselectedDir, name))
|
||||
for _, title := range args.Series {
|
||||
if current.Title == title {
|
||||
addtorrent(CurrentTorrents[title], current)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Transmission, err = transmission.New(transmission.Config{
|
||||
Address: "http://timmy:9091/transmission/rpc",
|
||||
HTTPClient: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
download()
|
||||
}
|
||||
|
||||
func process(torrentFile string) *SceneVideoTorrent {
|
||||
var (
|
||||
mt *MetaTorrent = new(MetaTorrent)
|
||||
vt *SceneVideoTorrent = new(SceneVideoTorrent)
|
||||
mt = new(MetaTorrent)
|
||||
vt = new(SceneVideoTorrent)
|
||||
)
|
||||
|
||||
f, _ := os.OpenFile(torrentFile, os.O_RDONLY, 755)
|
||||
defer f.Close()
|
||||
mt.ReadFile(f)
|
||||
vt.Torrent = NewTorrent(*mt)
|
||||
vt.Parse(strings.TrimSuffix(vt.Name, path.Ext(vt.Name)))
|
||||
fmt.Printf("%v\n", *vt)
|
||||
vt.Parse(strings.TrimSuffix(vt.Name, filepath.Ext(vt.Name)))
|
||||
//fmt.Println(vt.Original)
|
||||
fmt.Println(vt.Title)
|
||||
return vt
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
172
type.go
172
type.go
@ -1,27 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"timmy.narnian.us/git/timmy/scene"
|
||||
|
||||
"github.com/lordwelch/SceneParse"
|
||||
"github.com/zeebo/bencode"
|
||||
)
|
||||
|
||||
type MetaTorrent struct {
|
||||
Path string
|
||||
Hash string `bencode:"-"`
|
||||
FilePath string `bencode:"-"`
|
||||
Path string `bencode:"path"`
|
||||
Announce string `bencode:"announce"`
|
||||
Announcelist [][]string `bencode:"announce-list"`
|
||||
Comment string `bencode:"comment"`
|
||||
CreatedBy string `bencode:"created by"`
|
||||
Announcelist [][]string `bencode:"announce-list,omitempty"`
|
||||
Comment string `bencode:"comment,omitempty"`
|
||||
CreatedBy string `bencode:"created by,omitempty"`
|
||||
Info struct {
|
||||
Name string `bencode:"name"`
|
||||
Piece_length int64 `bencode:"piece length"`
|
||||
Length int64 `bencode:"length"`
|
||||
Files []struct {
|
||||
Name string `bencode:"name"`
|
||||
PieceLength int64 `bencode:"piece length"`
|
||||
Length int64 `bencode:"length,omitempty"`
|
||||
Pieces string `bencode:"pieces"`
|
||||
Files []struct {
|
||||
Length int64 `bencode:"length"`
|
||||
Path []string `bencode:"path"`
|
||||
} `bencode:"files"`
|
||||
} `bencode:"files,omitempty"`
|
||||
} `bencode:"info"`
|
||||
}
|
||||
|
||||
@ -35,22 +42,44 @@ type Torrent struct {
|
||||
|
||||
type SceneVideoTorrent struct {
|
||||
Torrent
|
||||
Scene.Scene
|
||||
scene.Scene
|
||||
}
|
||||
|
||||
type EpisodeTorrent struct {
|
||||
Episode []SceneVideoTorrent
|
||||
Release string
|
||||
Ep []*SceneVideoTorrent
|
||||
Tags map[string]int
|
||||
Res scene.Res
|
||||
Release map[string]int
|
||||
}
|
||||
type SeasonTorrent map[string]*EpisodeTorrent
|
||||
type SeriesTorrent map[string]SeasonTorrent
|
||||
|
||||
type SeriesTorrent []EpisodeTorrent
|
||||
func OrderedBy(fns ...func(int, int) bool) func(int, int) bool {
|
||||
return func(i, j int) bool {
|
||||
// Try all but the last comparison.
|
||||
for _, less := range fns {
|
||||
switch {
|
||||
case less(i, j):
|
||||
// i < j, so we have a decision.
|
||||
return true
|
||||
case less(j, i):
|
||||
// i > j, so we have a decision.
|
||||
return false
|
||||
}
|
||||
// i == j; try the next comparison.
|
||||
}
|
||||
// All comparisons to here said "equal", so just return whatever
|
||||
// the final comparison reports.
|
||||
return fns[len(fns)-1](i, j)
|
||||
}
|
||||
}
|
||||
|
||||
func NewTorrent(mt MetaTorrent) (T Torrent) {
|
||||
if mt.Info.Length == 0 {
|
||||
for i, path := range mt.Info.Files {
|
||||
for _, path := range mt.Info.Files {
|
||||
for _, file := range path.Path {
|
||||
if file[len(file)-3:] == "mkv" || file[len(file)-3:] == "mp4" {
|
||||
T.Size = mt.Info.Files[i].Length
|
||||
T.Size = path.Length
|
||||
T.Name = file
|
||||
}
|
||||
}
|
||||
@ -65,14 +94,113 @@ func NewTorrent(mt MetaTorrent) (T Torrent) {
|
||||
return T
|
||||
}
|
||||
|
||||
func (Mt *MetaTorrent) ReadFile(r io.Reader) error {
|
||||
return bencode.NewDecoder(r).Decode(Mt)
|
||||
func (Mt *MetaTorrent) ReadFile(r *os.File) error {
|
||||
err := bencode.NewDecoder(r).Decode(Mt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
str, _ := bencode.EncodeString(Mt.Info)
|
||||
Mt.Hash = fmt.Sprintf("%x", sha1.Sum([]byte(str)))
|
||||
Mt.FilePath, err = filepath.Abs(r.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (Vt SceneVideoTorrent) String() string {
|
||||
return fmt.Sprint(Vt.Scene)
|
||||
return Vt.Torrent.Meta.FilePath
|
||||
}
|
||||
|
||||
func (s SeriesTorrent) Title() string {
|
||||
return s[0].Episode[0].Title
|
||||
func (Et *EpisodeTorrent) ByRelease(i, j int) bool {
|
||||
var (
|
||||
ii int
|
||||
ij int
|
||||
ret bool
|
||||
)
|
||||
ii = Et.Release[Et.Ep[i].Release]
|
||||
ij = Et.Release[Et.Ep[j].Release]
|
||||
if ii == 0 {
|
||||
ii = 999999
|
||||
}
|
||||
if ij == 0 {
|
||||
ij = 999999
|
||||
}
|
||||
if ii == ij {
|
||||
ret = Et.Ep[i].Release > Et.Ep[j].Release
|
||||
//fmt.Println(Et.Ep[i].Release, ">", Et.Ep[j].Release, "=", ret, Et)
|
||||
} else {
|
||||
ret = ii < ij
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (Et *EpisodeTorrent) ByTag(i, j int) bool {
|
||||
var (
|
||||
ii int
|
||||
ij int
|
||||
ret bool
|
||||
)
|
||||
for k := range Et.Ep[i].Tags {
|
||||
if Et.Tags[k] > 0 {
|
||||
ii++
|
||||
}
|
||||
}
|
||||
for k := range Et.Ep[j].Tags {
|
||||
if Et.Tags[k] > 0 {
|
||||
ij++
|
||||
}
|
||||
}
|
||||
|
||||
if ii == ij {
|
||||
ret = len(Et.Ep[i].Tags) < len(Et.Ep[j].Tags)
|
||||
//fmt.Println(len(Et.Ep[i].Tags), "<", len(Et.Ep[j].Tags), "=", ret)
|
||||
} else {
|
||||
ret = ii > ij
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (Et *EpisodeTorrent) ByRes(i, j int) bool {
|
||||
var ret bool
|
||||
ret = Et.Ep[i].Resolution > Et.Ep[j].Resolution
|
||||
//fmt.Println(Et.Ep[i].Resolution, ">", Et.Ep[j].Resolution, "=", ret)
|
||||
|
||||
if Et.Res == Et.Ep[i].Resolution && Et.Ep[i].Resolution != Et.Ep[j].Resolution {
|
||||
ret = true
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (Et *EpisodeTorrent) Len() int {
|
||||
return len(Et.Ep)
|
||||
}
|
||||
|
||||
func (Et *EpisodeTorrent) Swap(i, j int) {
|
||||
Et.Ep[i], Et.Ep[j] = Et.Ep[j], Et.Ep[i]
|
||||
//fmt.Println(Et.Ep)
|
||||
}
|
||||
|
||||
func (Et *EpisodeTorrent) Less(i, j int) bool {
|
||||
return OrderedBy(Et.ByRelease, Et.ByRes, Et.ByTag)(i, j)
|
||||
}
|
||||
|
||||
func (Et *EpisodeTorrent) Add(Vt *SceneVideoTorrent) {
|
||||
Et.Ep = append(Et.Ep, Vt)
|
||||
sort.Stable(Et)
|
||||
}
|
||||
|
||||
func (St SeriesTorrent) SearchHash(hash string) *SceneVideoTorrent {
|
||||
for _, v := range St {
|
||||
for _, v2 := range v {
|
||||
for _, v3 := range v2.Ep {
|
||||
if v3.Meta.Hash == hash {
|
||||
return v3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return &SceneVideoTorrent{}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user