171 lines
3.3 KiB
Go
171 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/schollz/progressbar/v3"
|
|
)
|
|
|
|
// The skeleton for now
|
|
|
|
var link string
|
|
|
|
func terminate() {
|
|
flag.Usage()
|
|
os.Exit(1)
|
|
}
|
|
|
|
func check(f func() error) {
|
|
if err := f(); err != nil {
|
|
fmt.Fprintf(os.Stderr, "ERR > %v\n", err)
|
|
}
|
|
}
|
|
|
|
func generateRequest(link, method string, body io.Reader) *http.Request {
|
|
req, _ := http.NewRequest(method, link, body)
|
|
|
|
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0")
|
|
req.Header.Set("Connection", "keep-alive")
|
|
|
|
return req
|
|
}
|
|
|
|
func executeRequest(req *http.Request) *http.Response {
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
println(err)
|
|
}
|
|
|
|
return resp
|
|
}
|
|
|
|
func writeResponseToFile(resp *http.Response, filename string) {
|
|
f, _ := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0644)
|
|
defer f.Close()
|
|
|
|
var filesize int64
|
|
if _, ok := resp.Header["Content-Length"]; ok {
|
|
filesize = resp.ContentLength
|
|
} else {
|
|
filesize = -1
|
|
}
|
|
|
|
bar := progressbar.DefaultBytes(
|
|
filesize,
|
|
filename,
|
|
)
|
|
|
|
io.Copy(io.MultiWriter(f, bar), resp.Body)
|
|
}
|
|
|
|
func parseFilenameFromContentDisposition(s string) string {
|
|
regex := regexp.MustCompile(`".*?"`)
|
|
|
|
// Ugly but it works
|
|
filename := regex.FindString(s)
|
|
filename = filename[1 : len(filename)-1]
|
|
|
|
return filename
|
|
}
|
|
|
|
func Pixeldrain(path string) error {
|
|
// TODO: Implement more URL forms
|
|
split := strings.Split(path, "/")
|
|
id := split[2]
|
|
|
|
contentURL := fmt.Sprintf("https://pixeldrain.com/api/file/%s?download", id)
|
|
|
|
req := generateRequest(contentURL, "GET", nil)
|
|
resp := executeRequest(req)
|
|
|
|
filename := parseFilenameFromContentDisposition(resp.Header["Content-Disposition"][0])
|
|
|
|
writeResponseToFile(resp, filename)
|
|
|
|
return nil
|
|
}
|
|
|
|
func WeTransfer(path string) error {
|
|
// TODO: Support we.tl
|
|
|
|
split := strings.Split(path, "/")
|
|
|
|
// Some checks
|
|
if split[1] != "downloads" {
|
|
return fmt.Errorf("WeTransfer parser: Unsupported URL")
|
|
}
|
|
|
|
baseID := split[2]
|
|
secHash := split[3]
|
|
|
|
contentURL := fmt.Sprintf("https://wetransfer.com/api/v4/transfers/%s/download", baseID)
|
|
payload := []byte(fmt.Sprintf(`{"security_hash":"%s","intent":"entire_transfer"}`, secHash))
|
|
|
|
req := generateRequest(contentURL, "POST", bytes.NewBuffer(payload))
|
|
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
|
|
|
|
resp := executeRequest(req)
|
|
body, err := io.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
regex := regexp.MustCompile(`"https://.*?"`)
|
|
directLink := regex.FindString(string(body))
|
|
|
|
req = generateRequest(directLink[1:len(directLink)-1], "GET", nil)
|
|
resp = executeRequest(req)
|
|
|
|
filename := parseFilenameFromContentDisposition(resp.Header["Content-Disposition"][0])
|
|
|
|
writeResponseToFile(resp, filename)
|
|
|
|
return nil
|
|
}
|
|
|
|
func extractURL(link string) error {
|
|
parsed, err := url.Parse(link)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
hostname := parsed.Hostname()
|
|
path := parsed.Path
|
|
|
|
switch hostname {
|
|
case "pixeldrain.com":
|
|
Pixeldrain(path)
|
|
case "wetransfer.com":
|
|
WeTransfer(path)
|
|
default:
|
|
return fmt.Errorf("Error: Unimplemented URL")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
var help = flag.Bool("help", false, "Show help")
|
|
|
|
if *help {
|
|
terminate()
|
|
}
|
|
|
|
flag.StringVar(&link, "url", "", "The URL to fetch the file from")
|
|
flag.Parse()
|
|
|
|
if len(link) < 1 {
|
|
fmt.Println("Error: Invalid URL?")
|
|
terminate()
|
|
}
|
|
|
|
_ = extractURL(link)
|
|
}
|