Skip to content
This repository was archived by the owner on Aug 25, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions const.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package goinsta

const (
goInstaBaseUrl = "https://i.instagram.com/"
goInstaAPIUrl = "https://i.instagram.com/api/v1/"
goInstaAPIUrlv2 = "https://i.instagram.com/api/v2/"
goInstaUserAgent = "Instagram 107.0.0.27.121 Android (24/7.0; 380dpi; 1080x1920; OnePlus; ONEPLUS A3010; OnePlus3T; qcom; en_US)"
Expand Down
41 changes: 41 additions & 0 deletions examples/upload-photo/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"log"
"net/http"
"os"

"github.com/manslaughter03/goinsta"
)

func main() {
insta := goinsta.New(
os.Getenv("INSTAGRAM_USERNAME"),
os.Getenv("INSTAGRAM_PASSWORD"),
)
if err := insta.Login(); err != nil {
log.Fatal(err)
}

defer insta.Logout()

log.Println("Download random photo")
client := http.Client{}
request, err := http.NewRequest("GET", "https://picsum.photos/800/800", nil)
if err != nil {
log.Fatal(err)
}
resp, err := client.Do(request)
if err != nil {
log.Fatal(err)
}

defer resp.Body.Close()

postedPhoto, err := insta.UploadPhoto(resp.Body, "awesome! :)", 1, 1)
if err != nil {
log.Fatal(err)
}

log.Printf("Success upload photo %s", postedPhoto.ID)
}
2 changes: 1 addition & 1 deletion goinsta.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func ImportReader(r io.Reader) (*Instagram, error) {
//
// This function does not set proxy automatically. Use SetProxy after this call.
func ImportConfig(config ConfigFile) (*Instagram, error) {
url, err := neturl.Parse(goInstaAPIUrl)
url, err := neturl.Parse(goInstaBaseUrl)
if err != nil {
return nil, err
}
Expand Down
65 changes: 35 additions & 30 deletions media.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"math/rand"
"net/http"
neturl "net/url"
"os"
Expand Down Expand Up @@ -949,46 +949,40 @@ func (insta *Instagram) UploadPhoto(photo io.Reader, photoCaption string, qualit

func (insta *Instagram) postPhoto(photo io.Reader, photoCaption string, quality int, filterType int, isSidecar bool) (map[string]interface{}, error) {
uploadID := time.Now().Unix()
photoName := fmt.Sprintf("pending_media_%d.jpg", uploadID)
var b bytes.Buffer
w := multipart.NewWriter(&b)
w.WriteField("upload_id", strconv.FormatInt(uploadID, 10))
w.WriteField("_uuid", insta.uuid)
w.WriteField("_csrftoken", insta.token)
var compression = map[string]interface{}{
"lib_name": "jt",
"lib_version": "1.3.0",
"quality": quality,
}
cBytes, _ := json.Marshal(compression)
w.WriteField("image_compression", toString(cBytes))
if isSidecar {
w.WriteField("is_sidecar", toString(1))
}
fw, err := w.CreateFormFile("photo", photoName)
rndNumber := rand.Intn(9999999999-1000000000) + 1000000000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this is needed?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add this random number to generate name of the upload (part of url) and then use as value of 'X-Entity-Name' header. I use the same range used by https://github.com/dilame/instagram-private-api/blob/master/src/repositories/upload.repository.ts#L20. When i listen instagram api call from app, the requested url for upload fit this generate string.

name := strconv.FormatInt(uploadID, 10) + "_0_" + strconv.Itoa(rndNumber)
buf := new(bytes.Buffer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick:
var buf bytes.Buffer

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems buf need to be initialize to be use as a reader
./media.go:960:71: cannot use buf (type bytes.Buffer) as type io.Reader in argument to http.NewRequest

_, err := buf.ReadFrom(photo)
if err != nil {
return nil, err
}
var buf bytes.Buffer
rdr := io.TeeReader(photo, &buf)
if _, err = io.Copy(fw, rdr); err != nil {
return nil, err
}
if err := w.Close(); err != nil {
return nil, err
}
req, err := http.NewRequest("POST", goInstaAPIUrl+"upload/photo/", &b)
bs := buf.Bytes()
req, err := http.NewRequest("POST", goInstaBaseUrl+"rupload_igphoto/"+name, buf)
if err != nil {
return nil, err
}
req.Header.Set("X-IG-Capabilities", "3Q4=")
req.Header.Set("X-IG-Connection-Type", "WIFI")
req.Header.Set("Cookie2", "$Version=1")
req.Header.Set("Accept-Language", "en-US")
req.Header.Set("Accept-Encoding", "gzip, deflate")
req.Header.Set("Content-type", w.FormDataContentType())
req.Header.Set("Content-type", "application/octet-stream")
req.Header.Set("Connection", "close")
req.Header.Set("User-Agent", goInstaUserAgent)
req.Header.Set("X-Entity-Name", name)
ruploadParams := map[string]string{
"retry_context": `{"num_step_auto_retry": 0, "num_reupload": 0, "num_step_manual_retry": 0}`,
"media_type": "1",
"upload_id": strconv.FormatInt(uploadID, 10),
"xsharing_user_ids": "[]",
"image_compression": `{"lib_name": "moz", "lib_version": "3.1.m", "quality": "80"}`,
}
params, err := json.Marshal(ruploadParams)
if err != nil {
return nil, err
}
req.Header.Set("X-Instagram-Rupload-Params", string(params))
req.Header.Set("Offset", "0")
req.Header.Set("X-Entity-Length", strconv.FormatInt(req.ContentLength, 10))

resp, err := insta.c.Do(req)
if err != nil {
Expand All @@ -1014,15 +1008,18 @@ func (insta *Instagram) postPhoto(photo io.Reader, photoCaption string, quality
if result.Status != "ok" {
return nil, fmt.Errorf("unknown error, status: %s", result.Status)
}
width, height, err := getImageDimensionFromReader(&buf)
width, height, err := getImageDimensionFromReader(bytes.NewReader(bs))
if err != nil {
return nil, err
}
now := time.Now()

config := map[string]interface{}{
"media_folder": "Instagram",
"source_type": 4,
"caption": photoCaption,
"upload_id": strconv.FormatInt(uploadID, 10),
"device_id": insta.dID,
"device": goInstaDeviceSettings,
"edits": map[string]interface{}{
"crop_original_size": []int{width * 1.0, height * 1.0},
Expand All @@ -1034,6 +1031,14 @@ func (insta *Instagram) postPhoto(photo io.Reader, photoCaption string, quality
"source_width": width,
"source_height": height,
},
"height": height,
"width": width,
"camera_model": goInstaDeviceSettings["model"],
"scene_capture_type": "standard",
"timezone_offset": "3600",
"date_time_original": now.Format("2020:51:21 22:51:37"),
"date_time_digitalized": now.Format("2020:51:21 22:51:37"),
"software": "1",
}
return config, nil
}
Expand Down