-
-
Save afilhodaniel/09a1df8eafeabe1584c6 to your computer and use it in GitHub Desktop.
| class InstagramPrivateController < ApplicationController | |
| def initialize(username, password, photo, caption) | |
| @username = username | |
| @password = password | |
| @photo = photo | |
| @caption = caption | |
| @cookiepath = Tempfile.new('cookies').path | |
| @user_agent = generate_user_agent() | |
| @guid = generate_guid() | |
| @device_id = generate_device_id(@guid) | |
| end | |
| def send | |
| login = login() | |
| if login['status'] == 'ok' | |
| media = upload() | |
| if media['status'] == 'ok' | |
| configure = configure(media['media_id']) | |
| return configure | |
| end | |
| return media | |
| end | |
| return login | |
| end | |
| def generate_user_agent | |
| resolution = ['720x1280', '320x480', '480x800', '1024x768', '1280x720', '768x1024', '480x320'].sample | |
| version = ['GT-N7000', 'SM-N9000', 'GT-I9220', 'GT-I9100'].sample | |
| dpi = ['120', '160', '320', '240'].sample | |
| return 'Instagram 4.' + rand(1..2).to_s + '.' + rand(0..2).to_s + ' Android (' + rand(10..11).to_s + '/' + rand(1..3).to_s + '.' + rand(3..5).to_s + '.' + rand(0..5).to_s + '; #{dpi}; #{resolution}; samsung; #{version }; #{version}; smdkc210; en_US)' | |
| end | |
| def generate_guid | |
| guid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', | |
| rand(0..65535), | |
| rand(0..65535), | |
| rand(0..65535), | |
| rand(16384..20479), | |
| rand(32768..49151), | |
| rand(0..65535), | |
| rand(0..65535), | |
| rand(0..65535)) | |
| return guid | |
| end | |
| def generate_device_id(guid) | |
| return 'android-#{guid}' | |
| end | |
| def generate_signature(data) | |
| return OpenSSL::HMAC.hexdigest('sha256', 'b4a23f5e39b5929e0666ac5de94c89d1618a2916', data) | |
| end | |
| def request(url, data, upload, cookies) | |
| http = Curl::Easy.new(url) | |
| http.headers["User-Agent"] = @user_agent | |
| http.multipart_form_post = upload | |
| http.verbose = true | |
| http.follow_location = true | |
| http.enable_cookies = true | |
| if cookies | |
| http.cookiefile = @cookiepath | |
| else | |
| http.cookiejar = @cookiepath | |
| end | |
| if data.kind_of?(Array) | |
| http.send('post', *data) | |
| else | |
| http.send('post', data) | |
| end | |
| response = JSON.parse(http.body) | |
| http.close | |
| return response | |
| end | |
| def login | |
| url = 'https://instagram.com/api/v1/accounts/login/' | |
| data = "{'username':'#{@username}','password':'#{@password}','guid':'#{@guid}','device_id':'#{@device_id}','Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'}".gsub("'", '"') | |
| signature = generate_signature(data) | |
| body = 'ig_sig_key_version=4&signed_body=' + signature + '.' + URI::encode(data, /\W/) | |
| response = request(url, body, false, false) | |
| return response | |
| end | |
| def upload | |
| url = 'https://instagram.com/api/v1/media/upload/' | |
| device_timestamp = Time.now.to_i.to_s | |
| data = [ | |
| Curl::PostField.file('photo', @photo), | |
| Curl::PostField.content('device_timestamp', device_timestamp) | |
| ] | |
| response = request(url, data, true, true) | |
| return response | |
| end | |
| def configure(media_id) | |
| url = 'https://instagram.com/api/v1/media/configure/' | |
| device_timestamp = Time.now.to_i.to_s | |
| data = "{'guid':'#{@guid}','device_id':'#{@device_id}','device_timestamp':'#{device_timestamp}','media_id':'#{media_id}','caption':'#{@caption}','source_type':'5','filter_type':'0','extra':'{}','Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'}".gsub("'", '"') | |
| signature = generate_signature(data) | |
| body = 'ig_sig_key_version=4&signed_body=' + signature + '.' + URI::encode(data, /\W/) | |
| response = request(url, body, false, true) | |
| return response | |
| end | |
| end | |
| Fonts: | |
| http://lancenewman.me/posting-a-photo-to-instagram-without-a-phone/ | |
| http://mokhdzanifaeq.github.io/reverse-engineering-instagram-private-api/ |
And if you ask me this shouldn't be a model or a controller. Instead it should be a separate service that you can inject into your controller.
@aclemmensen I would like to see your C# version. I wonder how you worked with the http requests.
// Your version of Instagram is out of date. Please upgrade your app to log in to Instagram.
@newstler How do you fix this?
Hi. Nice code! Thanks! But i have one problem with uploading video to instagram. Tell me pls, how i can fix this error:
configure response: {"status"=>"ok", "media"=>{"upload_id"=>"1453635345"}, "message"=>"media_needs_reupload", "error_title"=>"staged_position_not_found"}
success but SUCCESS: {
"error_title" = "staged_position_not_found";
media = {
"upload_id" = 1453825279;
};
message = "media_needs_reupload";
status = ok;
}
I want the script to video, can anyone?
mgp25 has a similar script that I use yet I also encounter the same media_needs_reupload / staged_position_not_found when I upload videos. I been posting on mgp25's GitHub trying to find a solution yet to find a solution. Some people suggest downgrade to 5.5.3 but that did not fix fyi.
mgp25/Instagram-API#191
mgp25/Instagram-API#185
Nada ainda né? :( 12/12/2018 e ainda nenhuma resolução do problema.
@lastbench I made my C# implementation based on the original PHP implementation by Lance Newman. I was suspecting that this was a flaw in my implementation, but I just tested the original code and it shows the same behavior. I've been spending quite a few hours in Fiddler trying to figure out why my phone can post images just fine and my application can't.
I haven't tested this particular Ruby implementation. I was just wondering if the author had experienced the same issue.