Too many changes to mention.

Now atleast partially works
This commit is contained in:
lordwelch 2018-01-06 18:31:50 -07:00
parent 0e17c2c44c
commit da7e541666
25 changed files with 361 additions and 48 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
TorrentFilter
vendor

236
main.go
View File

@ -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
}

172
type.go
View File

@ -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{}
}