vkontakte_client 2.0.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.
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Vkontakte
4
+ class API
5
+ # An exception raised by `Vkontakte::API` when given a response with an error
6
+ class Error < StandardError
7
+ attr_reader :method_name, :error_code, :error_msg, :params
8
+
9
+ def initialize(method_name, error_code, error_msg, params)
10
+ @method_name = method_name
11
+ @error_code = error_code.to_i
12
+ @error_msg = error_msg
13
+ @params = params
14
+ end
15
+
16
+ # A full description of the error
17
+ def message
18
+ "VKontakte returned an error #{@error_code}: '#{@error_msg}' after calling method '#{@method_name}' with parameters #{@params.inspect}"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Vkontakte
4
+ # Ask Email and Password for user
5
+ class AskForCredentials
6
+ attr_reader :email, :password
7
+
8
+ def initialize
9
+ ask_for_credentials
10
+ end
11
+
12
+ private
13
+
14
+ def ask_for_credentials
15
+ puts 'Enter your credentials.'
16
+
17
+ print 'Email: '
18
+ @email = ask
19
+
20
+ print 'Password (typing will be hidden): '
21
+ @password = ask_for_password
22
+
23
+ nil
24
+ end
25
+
26
+ def ask
27
+ $stdin.gets.to_s.strip
28
+ end
29
+
30
+ def ask_for_password
31
+ echo_off
32
+ password = ask
33
+ puts
34
+ echo_on
35
+
36
+ password
37
+ end
38
+
39
+ def echo_off
40
+ with_tty do
41
+ system 'stty -echo'
42
+ end
43
+ end
44
+
45
+ def echo_on
46
+ with_tty do
47
+ system 'stty echo'
48
+ end
49
+ end
50
+
51
+ def with_tty
52
+ return unless $stdin.isatty
53
+
54
+ yield
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Vkontakte
4
+ # :nodoc:
5
+ class Client
6
+ attr_reader :api, :access_token, :user_id, :expires_in, :api_version
7
+
8
+ def initialize(
9
+ client_id = nil,
10
+ api_version: Vkontakte::API_VERSION,
11
+ proxy: nil,
12
+ timeout: 60
13
+ )
14
+ @client_id = client_id
15
+ @api_version = api_version
16
+ @proxy = proxy
17
+ @timeout = timeout
18
+ @authorize = false
19
+
20
+ @api = Vkontakte::API.new
21
+ end
22
+
23
+ def login!(email, pass, open_captcha: false, permissions: '')
24
+ @email = email
25
+ @pass = pass
26
+
27
+ redirect_uri = 'https://oauth.vk.com/blank.html'
28
+ display = 'mobile'
29
+ response_type = 'token'
30
+
31
+ query = {
32
+ client_id: @client_id,
33
+ redirect_uri: redirect_uri,
34
+ display: display,
35
+ scope: permissions,
36
+ response_type: response_type,
37
+ v: api_version
38
+ }
39
+
40
+ agent = Mechanize.new do |a|
41
+ a.user_agent_alias = 'Linux Firefox'
42
+ a.follow_meta_refresh
43
+
44
+ a.agent.set_socks(@proxy.addr, @proxy.port) if @proxy&.socks?
45
+ a.agent.set_proxy(@proxy.addr, @proxy.port) if @proxy&.http?
46
+ end
47
+
48
+ # https://vk.com/dev/implicit_flow_user
49
+ #
50
+ # Открытие диалога авторизации OAuth
51
+ #
52
+ query_string = query.map { |k, v| "#{k}=#{v}" }.join('&')
53
+ url = "https://oauth.vk.com/authorize?#{query_string}"
54
+
55
+ page = agent.get(url)
56
+
57
+ login_form = page.forms.first
58
+ login_form.email = @email
59
+ login_form.pass = @pass
60
+ page = login_form.submit
61
+
62
+ raise('Invalid login or password.') unless page.search('.service_msg_warning').empty?
63
+
64
+ page = submit_gain_access_form(page, open_captcha) if page.uri.path == '/authorize'
65
+
66
+ get_token(page)
67
+ end
68
+
69
+ def authorized?
70
+ @authorize ? true : false
71
+ end
72
+
73
+ private
74
+
75
+ def get_token(page)
76
+ auth_regexp = /access_token=(?<access_token>.*)&expires_in=(?<expires_in>\d+)&user_id=(?<user_id>\d*)\z/
77
+
78
+ return false unless page.uri.path == '/auth_redirect'
79
+
80
+ query_params = URI.decode_www_form(page.uri.query).to_h
81
+ authorize_url = CGI.unescape(query_params['authorize_url'])
82
+
83
+ auth_params = authorize_url.match(auth_regexp)
84
+
85
+ return false unless auth_params
86
+
87
+ @access_token = auth_params[:access_token]
88
+ @user_id = auth_params[:user_id]
89
+ @expires_in = auth_params[:expires_in]
90
+
91
+ @api = Vkontakte::API.new(
92
+ @access_token,
93
+ proxy: @proxy,
94
+ api_version: @api_version,
95
+ timeout: @timeout
96
+ )
97
+
98
+ @authorize = true
99
+
100
+ @access_token
101
+ end
102
+
103
+ def submit_gain_access_form(page, open_captcha)
104
+ form = page.forms.first
105
+
106
+ return form.submit unless form.has_key?('captcha_key')
107
+
108
+ raise('Captcha needed.') unless open_captcha
109
+
110
+ captcha_img = page.search('img[id=captcha]').first
111
+
112
+ puts 'Captcha needed.'
113
+ puts "Open url: #{captcha_img['src']}"
114
+ print 'Enter captch: '
115
+ captcha = $stdin.gets.chomp
116
+
117
+ form.pass = @pass
118
+ form.captcha_key = captcha
119
+ allow_page = form.submit
120
+
121
+ allow_form = allow_page.forms.first
122
+ allow_page = allow_form.submit if allow_form&.buttons&.detect { |btn| btn.value == 'Allow' }
123
+
124
+ raise('Invalid captcha.') unless allow_page.uri.path == '/blank.html'
125
+
126
+ allow_page
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Vkontakte
4
+ class Proxy # :nodoc:
5
+ attr_reader :type, :addr, :port
6
+
7
+ VALID_PROXY_TYPES = %i[http socks].freeze
8
+
9
+ def initialize(type, addr, port)
10
+ raise(StandartError, "#{`type`} is an invalid proxy type. Available values: #{VALID_PROXY_TYPES.join(',')}") unless VALID_PROXY_TYPES.include?(type)
11
+
12
+ @type = type
13
+ @addr = addr
14
+ @port = port
15
+ end
16
+
17
+ VALID_PROXY_TYPES.each do |type|
18
+ define_method(:"#{type}?") do
19
+ @type == type
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Vkontakte
4
+ VERSION = '2.0.0'
5
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'mechanize'
6
+ require 'socksify'
7
+ require 'socksify_mechanize'
8
+
9
+ require 'vkontakte/version'
10
+ require 'vkontakte/client'
11
+ require 'vkontakte/api'
12
+ require 'vkontakte/api_error'
13
+ require 'vkontakte/proxy'
14
+ require 'vkontakte/ask_for_credentials'
15
+
16
+ module Vkontakte
17
+ API_VERSION = '5.101'
18
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.push File.expand_path('lib', __dir__)
4
+ require 'vkontakte/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.authors = ['Anton Maminov']
8
+ gem.email = ['anton.maminov@gmail.com']
9
+ gem.description = 'VKontakte API Client for Ruby'
10
+ gem.summary = 'Unofficial VKontakte API Client for Ruby'
11
+ gem.homepage = 'https://github.com/mamantoha/vkontakte_client'
12
+ gem.licenses = ['MIT']
13
+
14
+ gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
15
+ gem.files = `git ls-files`.split("\n")
16
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ gem.name = 'vkontakte_client'
18
+ gem.require_paths = ['lib']
19
+ gem.version = Vkontakte::VERSION
20
+ gem.required_ruby_version = '>= 2.7.0'
21
+ gem.add_runtime_dependency 'mechanize', '~> 2.8', '>= 2.8.0'
22
+ gem.add_runtime_dependency 'socksify', '~> 1.7', '>= 1.7.0'
23
+ gem.add_development_dependency 'pry', '~> 0.14', '>= 0.14.0'
24
+ gem.add_development_dependency 'rubocop', '~> 1.18', '>= 1.18.0'
25
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vkontakte_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Anton Maminov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-08-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mechanize
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.8'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.8.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.8'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.8.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: socksify
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.7'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.7.0
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.7'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.7.0
53
+ - !ruby/object:Gem::Dependency
54
+ name: pry
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '0.14'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 0.14.0
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '0.14'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 0.14.0
73
+ - !ruby/object:Gem::Dependency
74
+ name: rubocop
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '1.18'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 1.18.0
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.18'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 1.18.0
93
+ description: VKontakte API Client for Ruby
94
+ email:
95
+ - anton.maminov@gmail.com
96
+ executables: []
97
+ extensions: []
98
+ extra_rdoc_files: []
99
+ files:
100
+ - ".gitignore"
101
+ - ".rubocop.yml"
102
+ - LICENSE
103
+ - README.md
104
+ - README.ru.md
105
+ - examples/accept_all_requests.rb
106
+ - examples/add_suggestions.rb
107
+ - examples/ban_news_from_all_friends.rb
108
+ - examples/friends_of_friends.rb
109
+ - examples/get_online_friends.rb
110
+ - examples/last_seen.rb
111
+ - examples/long_poll.rb
112
+ - examples/mechanize.rb
113
+ - examples/remove_out_requests.rb
114
+ - examples/remove_suspended_friends.rb
115
+ - examples/users_get_offline.rb
116
+ - examples/users_info.rb
117
+ - gems.rb
118
+ - lib/socksify_mechanize.rb
119
+ - lib/vkontakte/api.rb
120
+ - lib/vkontakte/api_error.rb
121
+ - lib/vkontakte/ask_for_credentials.rb
122
+ - lib/vkontakte/client.rb
123
+ - lib/vkontakte/proxy.rb
124
+ - lib/vkontakte/version.rb
125
+ - lib/vkontakte_client.rb
126
+ - vkontakte_client.gemspec
127
+ homepage: https://github.com/mamantoha/vkontakte_client
128
+ licenses:
129
+ - MIT
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: 2.7.0
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubygems_version: 3.2.22
147
+ signing_key:
148
+ specification_version: 4
149
+ summary: Unofficial VKontakte API Client for Ruby
150
+ test_files: []