package main import ( "bufio" "encoding/json" "errors" "fmt" "io" "mime" "net/http" "strconv" "strings" ) var mimeOverride map[string]string // a jpeg file can have a jpe extension and i personally don't like it // https://github.com/LonamiWebs/Telethon/blob/2e1be01ad4f6462de2e9e1f96a33537e51f44980/telethon/utils.py#L33 func LoadMimetypes() { mimeOverride = make(map[string]string) mimeOverride["image/png"] = ".png" mimeOverride["image/jpeg"] = ".jpeg" mimeOverride["image/webp"] = ".webp" mimeOverride["image/gif"] = ".gif" mimeOverride["image/bmp"] = ".bmp" mimeOverride["image/x-tga"] = ".tga" mimeOverride["image/tiff"] = ".tiff" mimeOverride["image/vnd.adobe.photoshop"] = ".psd" mimeOverride["video/mp4"] = ".mp4" mimeOverride["video/quicktime"] = ".mov" mimeOverride["video/avi"] = ".avi" mimeOverride["audio/mpeg"] = ".mp3" mimeOverride["audio/m4a"] = ".m4a" mimeOverride["audio/aac"] = ".aac" mimeOverride["audio/ogg"] = ".ogg" mimeOverride["audio/flac"] = ".flac" } func GetSubmission(client *http.Client, submissionJsonUrl string) (*Submission, error) { request, err := http.NewRequest("GET", submissionJsonUrl, nil) if err != nil { return nil, fmt.Errorf("Failed to create request: %s", err) } request.Header.Add("User-Agent", USER_AGENT) response, err := client.Do(request) 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 submission []SubmissionResponseItem err = json.Unmarshal(contents, &submission) if err != nil { return nil, fmt.Errorf("Failed to parse response: %s", err) } return submission[0].Data.Children[0].Data, nil } func InteractivelyAskIndex(stdin *bufio.Reader, items []string) (int, error) { if len(items) == 1 { return 0, nil } fmt.Printf("Select an item (from 1 to %d): ", len(items)) str, err := stdin.ReadString('\n') if err != nil { return 0, fmt.Errorf("Failed to read stdin: %s", err) } i, err := strconv.Atoi(strings.TrimSpace(str)) if err != nil { return 0, fmt.Errorf("Failed to parse stdin: %s", err) } i-- if i < 0 { return i, errors.New("Index is under or equal to 0") } if i >= len(items) { return i, errors.New("Index is bigger than items available") } 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) } ext, exists := mimeOverride[mediaType] if exists { return ext, nil } 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 } func PrintStatus(bytesDownloaded, contentLength float64, lastOutputLength int) int { output := fmt.Sprintf("%s downloaded", FormatBytes(bytesDownloaded)) if contentLength >= 0 { contentLengthString := FormatBytes(contentLength) output = fmt.Sprintf("%s out of %s downloaded (%.2f%%)", FormatBytes(bytesDownloaded), contentLengthString, bytesDownloaded/contentLength*100.0) } fmt.Print(output) for i := 0; i < lastOutputLength-len(output); i++ { fmt.Print(" ") } fmt.Print("\r") return len(output) }