instagram-private-api 0.1.5.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,18 +1,78 @@
1
- module Instagram
2
- module Feed
3
- def self.user_media(user, data)
4
- user_id = (!data[:id].nil? ? data[:id] : user.data[:id])
5
- rank_token = Instagram::API.generate_rank_token user.session.scan(/ds_user_id=([\d]+);/)[0][0]
6
- endpoint = "https://i.instagram.com/api/v1/feed/user/#{user_id}/"
7
- param = "?rank_token=#{rank_token}" +
8
- (!data[:max_id].nil? ? '&max_id=' + data[:max_id] : '')
9
- result = Instagram::API.http(
10
- url: endpoint + param,
11
- method: 'GET',
12
- user: user
13
- )
14
-
15
- JSON.parse result.body
16
- end
17
- end
18
- end
1
+ module Instagram
2
+ class Feed
3
+ def initialize
4
+ @api = V1.singleton
5
+ end
6
+
7
+ def using user
8
+ @user = {
9
+ id: user.data[:id],
10
+ session: user.session,
11
+ ua: user.useragent
12
+ }
13
+ self
14
+ end
15
+
16
+ def timeline_media
17
+ user_id = @user[:id]
18
+
19
+ rank_token = Instagram::V1.generate_rank_token @user[:id]
20
+ endpoint = "https://i.instagram.com/api/v1/feed/user/#{user_id}/"
21
+ param = "?rank_token=#{rank_token}"
22
+ result = @api.get(endpoint + param)
23
+ .with(session: @user[:session], ua: @user[:ua]).exec
24
+
25
+ JSON.parse result.body
26
+ end
27
+
28
+ def self.user_followers(user, data, limit)
29
+ has_next_page = true
30
+ followers = []
31
+ user_id = (!data[:id].nil? ? data[:id] : user.data[:id])
32
+ data[:rank_token] = Instagram::API.generate_rank_token user.session.scan(/ds_user_id=([\d]+);/)[0][0]
33
+ while has_next_page && limit > followers.size
34
+ response = user_followers_next_page(user, user_id, data)
35
+ has_next_page = !response['next_max_id'].nil?
36
+ data[:max_id] = response['next_max_id']
37
+ followers += response['users']
38
+ end
39
+ limit.infinite? ? followers : followers[0...limit]
40
+ end
41
+
42
+ def self.user_followers_graphql(user, data, limit)
43
+ has_next_page = true
44
+ followers = []
45
+ user_id = (!data[:id].nil? ? data[:id] : user.data[:id])
46
+ while has_next_page && limit > followers.size
47
+ response = user_followers_graphql_next_page(user, user_id, data)
48
+ has_next_page = response['data']['user']['edge_followed_by']['page_info']['has_next_page']
49
+ data[:end_cursor] = response['data']['user']['edge_followed_by']['page_info']['end_cursor']
50
+ followers += response['data']['user']['edge_followed_by']['edges']
51
+ end
52
+ limit.infinite? ? followers : followers[0...limit]
53
+ end
54
+
55
+ def self.user_followers_graphql_next_page(user, user_id, data)
56
+ endpoint = "https://www.instagram.com/graphql/query/?query_id=17851374694183129&id=#{user_id}&first=5000"
57
+ param = (!data[:end_cursor].nil? ? "&after=#{data[:end_cursor]}" : '')
58
+ result = Instagram::API.http(
59
+ url: endpoint + param,
60
+ method: 'GET',
61
+ user: user
62
+ )
63
+ JSON.parse result.body
64
+ end
65
+
66
+ def self.user_followers_next_page(user, user_id, data)
67
+ endpoint = "https://i.instagram.com/api/v1/friendships/#{user_id}/followers/"
68
+ param = "?rank_token=#{data[:rank_token]}" +
69
+ (!data[:max_id].nil? ? '&max_id=' + data[:max_id] : '')
70
+ result = Instagram::API.http(
71
+ url: endpoint + param,
72
+ method: 'GET',
73
+ user: user
74
+ )
75
+ JSON.parse result.body
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Instagram
4
+ class Relationship
5
+ def initialize user
6
+ @user = user
7
+ @api = nil
8
+ end
9
+
10
+ def create(id)
11
+ api.post("https://i.instagram.com/api/v1/friendships/create/#{id}/",
12
+ format(
13
+ 'ig_sig_key_version=4&signed_body=%s',
14
+ V1.generate_signature(
15
+ user_id: id
16
+ )
17
+ )).with(session: @user.session, ua: @user.useragent).exec
18
+ end
19
+
20
+ def api
21
+ @api = V1.new if @api.nil?
22
+
23
+ @api
24
+ end
25
+ end
26
+ end
@@ -1,84 +1,118 @@
1
- require 'digest/md5'
2
- require 'Instagram/Device'
3
- require 'Instagram/CONSTANTS'
4
-
5
- module Instagram
6
- class User
7
- attr_reader :username
8
- attr_reader :password
9
- attr_reader :language
10
- attr_reader :data
11
- attr_writer :data
12
- attr_reader :session
13
- attr_writer :session
14
-
15
- def initialize(username, password, session = nil, data = nil)
16
- @username = username
17
- @password = password
18
- @language = 'en_US'
19
- @session = session
20
- @data = data
21
- end
22
-
23
- def search_for_user (username)
24
- Instagram::Account.search_for_user(self, username)
25
- end
26
-
27
- def user_media(data = {})
28
- Instagram::Feed.user_media(self, data)
29
- end
30
-
31
- def md5
32
- Digest::MD5.hexdigest @username
33
- end
34
-
35
- def md5int
36
- (md5.to_i(32) / 10e32).round
37
- end
38
-
39
- def api
40
- (18 + (md5int % 5)).to_s
41
- end
42
-
43
- # @return [string]
44
- def release
45
- %w[4.0.4 4.3.1 4.4.4 5.1.1 6.0.1][md5int % 5]
46
- end
47
-
48
- def dpi
49
- %w[801 577 576 538 515 424 401 373][md5int % 8]
50
- end
51
-
52
- def resolution
53
- %w[3840x2160 1440x2560 2560x1440 1440x2560
54
- 2560x1440 1080x1920 1080x1920 1080x1920][md5int % 8]
55
- end
56
-
57
- def info
58
- line = Device.devices[md5int % Device.devices.count]
59
- {
60
- manufacturer: line[0],
61
- device: line[1],
62
- model: line[2]
63
- }
64
- end
65
-
66
- def useragent_hash
67
- agent = [api + '/' + release, dpi + 'dpi',
68
- resolution, info[:manufacturer], info[:model], info[:device], @language]
69
-
70
- {
71
- agent: agent.join('; '),
72
- version: CONSTANTS::PRIVATE_KEY[:APP_VERSION]
73
- }
74
- end
75
-
76
- def useragent
77
- format('Instagram %s Android(%s)', useragent_hash[:version], useragent_hash[:agent].rstrip)
78
- end
79
-
80
- def device_id
81
- 'android-' + md5[0..15]
82
- end
83
- end
84
- end
1
+ require 'digest/md5'
2
+ require 'Instagram/Device'
3
+ require 'Instagram/CONSTANTS'
4
+
5
+ module Instagram
6
+ class User
7
+ attr_reader :username
8
+ attr_reader :password
9
+ attr_reader :language
10
+ attr_reader :data
11
+ attr_writer :data
12
+ attr_reader :session
13
+ attr_writer :session
14
+ attr_reader :config
15
+ attr_writer :config
16
+
17
+ def initialize(username, password, session = nil, data = nil, config = nil)
18
+ @username = username
19
+ @password = password
20
+ @language = 'en_US'
21
+ @session = session
22
+ @data = data
23
+ @config = config
24
+ @account = nil
25
+ @feed = nil
26
+ end
27
+
28
+ def search_for_user(username)
29
+ account.search_for_user(self, username)
30
+ end
31
+
32
+ def search_for_user_graphql(username)
33
+ account.search_for_graphql(self, username)
34
+ end
35
+
36
+ def followers(limit = Float::INFINITY, data = {})
37
+ Instagram::Feed.user_followers(self, data, limit)
38
+ end
39
+
40
+ def user_followers_graphql(limit = Float::INFINITY, data = {})
41
+ Instagram::Feed.user_followers_graphql(self, data, limit)
42
+ end
43
+
44
+ def relationship
45
+ unless instance_variable_defined? :@relationship
46
+ @relationship = Relationship.new self
47
+ end
48
+
49
+ @relationship
50
+ end
51
+
52
+ def account
53
+ @account = Instagram::Account.new if @account.nil?
54
+
55
+ @account
56
+ end
57
+
58
+ def feed
59
+ @feed = Instagram::Feed.new if @feed.nil?
60
+
61
+ @feed.using(self)
62
+ end
63
+
64
+ def md5
65
+ Digest::MD5.hexdigest @username
66
+ end
67
+
68
+ def md5int
69
+ (md5.to_i(32) / 10e32).round
70
+ end
71
+
72
+ def api
73
+ (18 + (md5int % 5)).to_s
74
+ end
75
+
76
+ # @return [string]
77
+ def release
78
+ %w[4.0.4 4.3.1 4.4.4 5.1.1 6.0.1][md5int % 5]
79
+ end
80
+
81
+ def dpi
82
+ %w[801 577 576 538 515 424 401 373][md5int % 8]
83
+ end
84
+
85
+ def resolution
86
+ %w[3840x2160 1440x2560 2560x1440 1440x2560
87
+ 2560x1440 1080x1920 1080x1920 1080x1920][md5int % 8]
88
+ end
89
+
90
+ def info
91
+ line = Device.devices[md5int % Device.devices.count]
92
+ {
93
+ manufacturer: line[0],
94
+ device: line[1],
95
+ model: line[2]
96
+ }
97
+ end
98
+
99
+ def useragent_hash
100
+ agent = [api + '/' + release, dpi + 'dpi',
101
+ resolution, info[:manufacturer],
102
+ info[:model], info[:device], @language]
103
+
104
+ {
105
+ agent: agent.join('; '),
106
+ version: CONSTANTS::PRIVATE_KEY[:APP_VERSION]
107
+ }
108
+ end
109
+
110
+ def useragent
111
+ format('Instagram %s Android(%s)', useragent_hash[:version], useragent_hash[:agent].rstrip)
112
+ end
113
+
114
+ def device_id
115
+ 'android-' + md5[0..15]
116
+ end
117
+ end
118
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: instagram-private-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - vicoerv
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-11-10 00:00:00.000000000 Z
11
+ date: 2018-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -60,10 +60,13 @@ executables: []
60
60
  extensions: []
61
61
  extra_rdoc_files: []
62
62
  files:
63
+ - ".gitignore"
63
64
  - ".rspec"
65
+ - ".rubocop.yml"
64
66
  - ".travis.yml"
65
67
  - CODE_OF_CONDUCT.md
66
68
  - Gemfile
69
+ - Gemfile.lock
67
70
  - Instagram-API.gemspec
68
71
  - LICENSE.txt
69
72
  - README.md
@@ -74,9 +77,11 @@ files:
74
77
  - lib/Instagram/API/version.rb
75
78
  - lib/Instagram/account.rb
76
79
  - lib/Instagram/api.rb
80
+ - lib/Instagram/configuration.rb
77
81
  - lib/Instagram/constants.rb
78
82
  - lib/Instagram/device.rb
79
83
  - lib/Instagram/feed.rb
84
+ - lib/Instagram/relationship.rb
80
85
  - lib/Instagram/user.rb
81
86
  homepage: http://www.vicoervanda.com
82
87
  licenses:
@@ -99,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
104
  version: '0'
100
105
  requirements: []
101
106
  rubyforge_project:
102
- rubygems_version: 2.5.2
107
+ rubygems_version: 2.7.6
103
108
  signing_key:
104
109
  specification_version: 4
105
110
  summary: Instagram private api, implemented from huttarichard/instagram-private-api