func (g *gweet) tweet(api *anaconda.TwitterApi, text string, files []string, lewd bool) (tweetUrl string, err error) { log.Printf(`Tweeting {"%s", %v, lewd=%v}.`+"\n", text, files, lewd) var ids string var data []byte for _, filePath := range files { log.Println("Uploading", filePath) // TODO: refuse files larger than 15mb for vids and 5mb for images data, err = ioutil.ReadFile(filePath) if err != nil { return } /*mime*/ meme := http.DetectContentType(data) log.Println(meme) if !strings.HasPrefix( /*mime*/ meme, "image") { var media anaconda.ChunkedMedia var videoMedia anaconda.VideoMedia // TODO: do not read entire file to memory media, err = api.UploadVideoInit(len(data), "video/mp4") if err != nil { return } chunkIndex := 0 for i := 0; i < len(data); i += 5242879 { log.Println("Chunk", chunkIndex) err = api.UploadVideoAppend(media.MediaIDString, chunkIndex, base64.StdEncoding.EncodeToString( data[i:int(math.Min(5242879.0, float64(len(data))))], ), ) if err != nil { return } chunkIndex++ } videoMedia, err = api.UploadVideoFinalize(media.MediaIDString) if err != nil { return } ids += videoMedia.MediaIDString ids += "," } else { var media anaconda.Media media, err = api.UploadMedia( base64.StdEncoding.EncodeToString(data)) ids += media.MediaIDString ids += "," } if err != nil { return } } ids = ids[:len(ids)-1] log.Println("media_ids:", ids) v := url.Values{} v.Set("media_ids", ids) v.Set("possibly_sensitive", strconv.FormatBool(lewd)) tweet, err := api.PostTweet(text, v) if err != nil { return } tweetUrl = fmt.Sprintf("https://twitter.com/%s/status/%s", tweet.User.ScreenName, tweet.IdStr) return }