Created
November 6, 2013 00:06
-
-
Save kidoman/7328620 to your computer and use it in GitHub Desktop.
A snatcher of sorts :)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"flag" | |
"fmt" | |
"io/ioutil" | |
"log" | |
"net/http" | |
"os" | |
"os/exec" | |
"path" | |
"regexp" | |
"time" | |
) | |
const ( | |
urlFmt = "http://embeds.uploadcrazy.net/ucc.php?file=ts%v%02v" | |
rexp = "http://[a-z0-9]+\\.uploadcrazy.net.+&e=[0-9]+" | |
maxTries = 5 | |
waitTime = 10 | |
) | |
var ( | |
re = regexp.MustCompile(rexp) | |
) | |
var ( | |
folder = flag.String("folder", ".", "where to put the downloaded files") | |
show = flag.String("show", "ts", "show short string") | |
season = flag.Int("s", 1, "season") | |
estart = flag.Int("es", 1, "which episode to start downloading") | |
eend = flag.Int("ee", 1, "which episode to end downloading") | |
) | |
func main() { | |
flag.Parse() | |
if *estart > *eend { | |
log.Fatal("End episode has to be > start episode") | |
} | |
for _, e := range listEpisodes() { | |
if e.done() { | |
log.Printf("Skipping episode %v as it is already done (file %v)", e, e.outputFilename()) | |
continue | |
} | |
if err := e.download(); err != nil { | |
log.Fatalf("Could not download episode %v", e) | |
} | |
} | |
} | |
func listEpisodes() []episode { | |
es := make([]episode, 0) | |
for i := *estart; i <= *eend; i++ { | |
es = append(es, episode(i)) | |
} | |
return es | |
} | |
type episode int | |
func (e episode) String() string { | |
return fmt.Sprintf("%v", int(e)) | |
} | |
func (e episode) done() bool { | |
o := e.outputFilename() | |
fp := path.Join(*folder, o) | |
if _, err := os.Stat(fp); os.IsNotExist(err) { | |
return false | |
} | |
return true | |
} | |
func (e episode) download() error { | |
tries := 0 | |
var durl string | |
for { | |
var err error | |
durl, err = e.downloadUrl() | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Printf("Validating url %q", durl) | |
if validateDownloadUrl(durl) { | |
log.Printf("Validated %q successfully", durl) | |
break | |
} | |
log.Printf("Could not validate %q", durl) | |
tries++ | |
if tries > maxTries { | |
log.Printf("Failed at getting a valid download URL for episode %v", e) | |
return nil | |
} | |
} | |
o := e.outputFilename() | |
cmd := exec.Command("axel", "-o", o, "-a", durl) | |
cmd.Dir = *folder | |
cmd.Stdout = os.Stdout | |
cmd.Stderr = os.Stderr | |
log.Printf("About to start downloading %q", durl) | |
err := cmd.Run() | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Printf("Completed downloading from %q", durl) | |
return nil | |
} | |
func validateDownloadUrl(url string) bool { | |
res := make(chan bool) | |
go func() { | |
resp, err := http.Head(url) | |
if err != nil { | |
res <- false | |
} | |
if resp.StatusCode != 200 { | |
res <- false | |
} | |
res <- true | |
}() | |
timeout := time.After(waitTime * time.Second) | |
select { | |
case result := <-res: | |
return result | |
case <-timeout: | |
return false | |
} | |
} | |
func (e episode) outputFilename() string { | |
return fmt.Sprintf("%v.s%02ve%02v.mp4", *show, *season, e) | |
} | |
func (e episode) downloadUrl() (string, error) { | |
url := e.url() | |
log.Printf("Scrapping page %q", url) | |
res, err := http.Get(url) | |
if err != nil { | |
log.Fatal(err) | |
} | |
defer res.Body.Close() | |
if res.StatusCode != 200 { | |
return "", fmt.Errorf("Invalid intermediate page (%v), cannot scrap", url) | |
} | |
body, err := ioutil.ReadAll(res.Body) | |
if err != nil { | |
log.Fatal(err) | |
} | |
durl := re.Find(body) | |
if durl == nil { | |
return "", errors.New("Cannot find download url") | |
} | |
log.Printf("Found url %q for episode %v", durl, e) | |
return string(durl), nil | |
} | |
func (e episode) url() string { | |
return fmt.Sprintf(urlFmt, *season, e) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment