some more
This commit is contained in:
parent
e4586cd5f3
commit
c5ceea00fb
121
main.go
121
main.go
|
@ -2,7 +2,9 @@ package main
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
|
@ -148,6 +150,121 @@ func main() {
|
|||
fmt.Fprintf(os.Stderr, "Failed to get index: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
url := urls[i]
|
||||
fmt.Println(url)
|
||||
unparsedUrl := urls[i]
|
||||
fmt.Println(unparsedUrl)
|
||||
parsedUrl, err := url.Parse(unparsedUrl)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to parse url: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
domain := submission.Domain
|
||||
if domain == "" {
|
||||
domain = parsedUrl.Hostname()
|
||||
}
|
||||
path := parsedUrl.EscapedPath()
|
||||
pathExtless, pathExt := SplitExt(path)
|
||||
urls = make([]string, 1)
|
||||
urls[0] = unparsedUrl
|
||||
if domain == "imgur.com" || strings.HasSuffix(domain, ".imgur.com") {
|
||||
parsedUrl.Host = "i.imgur.com"
|
||||
if strings.HasPrefix(path, "/a/") || strings.HasPrefix(path, "/gallery/") {
|
||||
albumId := strings.SplitN(path, "/", 4)[2]
|
||||
imgurImages, err := GetImgurAlbum(client, albumId)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to get imgur album: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
urls = nil
|
||||
for _, i := range imgurImages {
|
||||
urls = append(urls, "https://i.imgur.com/"+i.Hash+i.Ext)
|
||||
}
|
||||
} else {
|
||||
if pathExt == ".gifv" {
|
||||
parsedUrl.RawPath = pathExtless + ".mp4"
|
||||
}
|
||||
urls[0] = parsedUrl.String()
|
||||
}
|
||||
} else if domain == "gfycat.com" {
|
||||
gfyMp4, err := GetGfycat(client, pathExtless)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to get gfycat video: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if gfyMp4 != "" {
|
||||
urls[0] = gfyMp4
|
||||
}
|
||||
} else if submission.IsRedditMediaDomain && submission.Preview != nil {
|
||||
preview := submission.Preview.Images[0]
|
||||
if pathExt == ".gif" {
|
||||
if preview.Variants.Mp4 != nil {
|
||||
urls[0] = preview.Variants.Mp4.Url
|
||||
} else if preview.Variants.Gif != nil {
|
||||
urls[0] = preview.Variants.Gif.Url
|
||||
}
|
||||
} else if submission.IsVideo {
|
||||
urls[0] = preview.Source.Url
|
||||
}
|
||||
}
|
||||
i, err = InteractivelyAskIndex(stdin, urls)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to get index: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
unparsedUrl = urls[i]
|
||||
fmt.Println(unparsedUrl)
|
||||
response, err := client.Get(unparsedUrl)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to get response: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
ext, err := GetExtension(response.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Warning: Failed to get file extension: %s\n", err)
|
||||
} else {
|
||||
filename = filename + ext
|
||||
}
|
||||
fmt.Printf("Downloading to %s\n", filename)
|
||||
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0o664)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to open file for writing: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
writer := bufio.NewWriter(file)
|
||||
defer writer.Flush()
|
||||
reader := bufio.NewReader(response.Body)
|
||||
contentLengthString := ""
|
||||
if response.ContentLength >= 0 {
|
||||
contentLengthString = FormatBytes(float64(response.ContentLength))
|
||||
}
|
||||
lastOutputLength := 0
|
||||
bytesDownloaded := 0
|
||||
toWrite := make([]byte, 1024*1024)
|
||||
for {
|
||||
output := fmt.Sprintf("%s downloaded", FormatBytes(float64(bytesDownloaded)))
|
||||
if response.ContentLength >= 0 {
|
||||
output = fmt.Sprintf("%s out of %s downloaded (%.2f%%)", FormatBytes(float64(bytesDownloaded)), contentLengthString, float64(bytesDownloaded)/float64(response.ContentLength)*100.0)
|
||||
}
|
||||
fmt.Print(output)
|
||||
for i := 0; i < lastOutputLength-len(output); i++ {
|
||||
fmt.Print(" ")
|
||||
}
|
||||
lastOutputLength = len(output)
|
||||
fmt.Print("\r")
|
||||
n, err := reader.Read(toWrite)
|
||||
if n == 0 && errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to read response: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
_, err = writer.Write(toWrite[:n])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to write response: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
bytesDownloaded += n
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
|
22
structs.go
22
structs.go
|
@ -61,17 +61,18 @@ type Submission struct {
|
|||
} `json:"s"`
|
||||
} `json:"media_metadata"`
|
||||
IsRedditMediaDomain bool `json:"is_reddit_media_domain"`
|
||||
Preview struct {
|
||||
Preview *struct {
|
||||
Images []struct {
|
||||
Variants struct {
|
||||
Mp4 *PreviewSource `json:"mp4"`
|
||||
Gif *PreviewSource `json:"gif"`
|
||||
} `json:"variants"`
|
||||
Source *PreviewSource `json:"source"`
|
||||
} `json:"images"`
|
||||
Source *PreviewSource `json:"source"`
|
||||
} `json:"preview"`
|
||||
IsSelf bool `json:"is_self"`
|
||||
Title string `json:"title"`
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
type SubmissionResponseItem struct {
|
||||
|
@ -81,3 +82,20 @@ type SubmissionResponseItem struct {
|
|||
} `json:"children"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type ImgurImage struct {
|
||||
Hash string `json:"hash"`
|
||||
Ext string `json:"ext"`
|
||||
}
|
||||
|
||||
type ImgurResponse struct {
|
||||
Data struct {
|
||||
Images []ImgurImage `json:"images"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type GfycatResponse struct {
|
||||
GfyItem struct {
|
||||
Mp4Url string `json:"mp4Url"`
|
||||
} `json:"gfyItem"`
|
||||
}
|
||||
|
|
94
utils.go
94
utils.go
|
@ -7,6 +7,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -172,3 +173,96 @@ func InteractivelyAskIndex(stdin *bufio.Reader, items []string) (int, error) {
|
|||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func SplitExt(str string) (string, string) {
|
||||
if str == "" {
|
||||
return "", ""
|
||||
}
|
||||
s := strings.Split(str[1:], ".")
|
||||
if len(s) < 2 {
|
||||
return str, ""
|
||||
}
|
||||
return str[:1] + strings.Join(s[:len(s)-1], "."), "." + s[len(s)-1]
|
||||
}
|
||||
|
||||
func GetImgurAlbum(client *http.Client, albumId string) ([]ImgurImage, error) {
|
||||
response, err := client.Get("https://imgur.com/ajaxalbums/getimages/" + albumId + "/hit.json?all=true")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to get response: %s", err)
|
||||
}
|
||||
contents, err := io.ReadAll(response.Body)
|
||||
response.Body.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to read response body: %s", err)
|
||||
}
|
||||
if response.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("Response returned status code %d, body: %s", response.StatusCode, contents)
|
||||
}
|
||||
var imgurResponse *ImgurResponse
|
||||
err = json.Unmarshal(contents, &imgurResponse)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse response: %s", err)
|
||||
}
|
||||
return imgurResponse.Data.Images, nil
|
||||
}
|
||||
|
||||
func GetGfycat(client *http.Client, gfyId string) (string, error) {
|
||||
response, err := client.Get("https://api.gfycat.com/v1/gfycats/" + gfyId)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to get response: %s", err)
|
||||
}
|
||||
contents, err := io.ReadAll(response.Body)
|
||||
response.Body.Close()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to read response body: %s", err)
|
||||
}
|
||||
if response.StatusCode != 200 {
|
||||
return "", fmt.Errorf("Response returned status code %d, body: %s", response.StatusCode, contents)
|
||||
}
|
||||
var gfycatResponse *GfycatResponse
|
||||
err = json.Unmarshal(contents, &gfycatResponse)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to parse response: %s", err)
|
||||
}
|
||||
return gfycatResponse.GfyItem.Mp4Url, nil
|
||||
}
|
||||
|
||||
func FormatBytes(size float64) string {
|
||||
label := ""
|
||||
if size >= 1024 {
|
||||
size /= 1024
|
||||
label = "K"
|
||||
}
|
||||
if size >= 1024 {
|
||||
size /= 1024
|
||||
label = "M"
|
||||
}
|
||||
if size >= 1024 {
|
||||
size /= 1024
|
||||
label = "G"
|
||||
}
|
||||
if size >= 1024 {
|
||||
size /= 1024
|
||||
label = "T"
|
||||
}
|
||||
return fmt.Sprintf("%.2f %sB", size, label)
|
||||
}
|
||||
|
||||
func GetExtension(mimeType string) (string, error) {
|
||||
if mimeType == "" {
|
||||
return "", nil
|
||||
}
|
||||
mediaType, _, err := mime.ParseMediaType(mimeType)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to parse media type of %s: %s", mimeType, err)
|
||||
}
|
||||
exts, err := mime.ExtensionsByType(mediaType)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to find file extensions of %s: %s", mediaType, err)
|
||||
}
|
||||
if len(exts) < 1 {
|
||||
return "", nil
|
||||
}
|
||||
fmt.Println(exts)
|
||||
return exts[0], nil
|
||||
}
|
||||
|
|
Reference in New Issue