vkontakte_client 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +33 -0
- data/LICENSE +21 -0
- data/README.md +90 -0
- data/README.ru.md +79 -0
- data/examples/accept_all_requests.rb +37 -0
- data/examples/add_suggestions.rb +40 -0
- data/examples/ban_news_from_all_friends.rb +72 -0
- data/examples/friends_of_friends.rb +125 -0
- data/examples/get_online_friends.rb +30 -0
- data/examples/last_seen.rb +32 -0
- data/examples/long_poll.rb +105 -0
- data/examples/mechanize.rb +55 -0
- data/examples/remove_out_requests.rb +44 -0
- data/examples/remove_suspended_friends.rb +30 -0
- data/examples/users_get_offline.rb +17 -0
- data/examples/users_info.rb +25 -0
- data/gems.rb +5 -0
- data/lib/socksify_mechanize.rb +24 -0
- data/lib/vkontakte/api.rb +86 -0
- data/lib/vkontakte/api_error.rb +22 -0
- data/lib/vkontakte/ask_for_credentials.rb +57 -0
- data/lib/vkontakte/client.rb +129 -0
- data/lib/vkontakte/proxy.rb +23 -0
- data/lib/vkontakte/version.rb +5 -0
- data/lib/vkontakte_client.rb +18 -0
- data/vkontakte_client.gemspec +25 -0
- metadata +150 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.setup :default
|
5
|
+
|
6
|
+
require 'vkontakte_client'
|
7
|
+
|
8
|
+
puts Vkontakte::VERSION
|
9
|
+
|
10
|
+
if $PROGRAM_NAME == __FILE__
|
11
|
+
CLIENT_ID = '5987497'
|
12
|
+
email = ARGV[0]
|
13
|
+
pass = ARGV[1]
|
14
|
+
vk = Vkontakte::Client.new(CLIENT_ID)
|
15
|
+
vk.login!(email, pass, open_captcha: true)
|
16
|
+
|
17
|
+
puts "access_token: #{vk.access_token}"
|
18
|
+
puts "api_version: #{vk.api_version}"
|
19
|
+
|
20
|
+
vk.api.lang = 'en'
|
21
|
+
friends = vk.api.friends_get(fields: 'online')
|
22
|
+
|
23
|
+
friends_online = friends['items'].select { |item| item['online'] == 1 }
|
24
|
+
|
25
|
+
puts "Online friends [#{friends_online.size}]:"
|
26
|
+
friends_online.each do |f|
|
27
|
+
mobile = f['online_mobile'] == 1 ? '[mobile]' : ''
|
28
|
+
puts "[#{f['id']}] #{f['first_name']} #{f['last_name']} #{mobile}"
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.setup :default
|
5
|
+
|
6
|
+
require 'vkontakte_client'
|
7
|
+
|
8
|
+
puts Vkontakte::VERSION
|
9
|
+
|
10
|
+
if $PROGRAM_NAME == __FILE__
|
11
|
+
CLIENT_ID = '5987497'
|
12
|
+
|
13
|
+
email = ARGV[0]
|
14
|
+
pass = ARGV[1]
|
15
|
+
|
16
|
+
vk = Vkontakte::Client.new(CLIENT_ID)
|
17
|
+
vk.login!(email, pass)
|
18
|
+
|
19
|
+
# http://vkontakte.ru/developers.php?o=-1&p=friends.get
|
20
|
+
iam = vk.api.users_get(user_ids: vk.user_id, fields: 'online,last_seen').first
|
21
|
+
friends = vk.api.friends_get(fields: 'online,last_seen')['items']
|
22
|
+
friends << iam
|
23
|
+
|
24
|
+
# sort an array of hashes by a value in the hash
|
25
|
+
sorted_friends = friends.sort_by { |k| k['last_seen'] ? k['last_seen']['time'] : 0 }
|
26
|
+
|
27
|
+
sorted_friends.each do |f|
|
28
|
+
last_seen = f['last_seen'] ? Time.at(f['last_seen']['time']) : 'Temporarily suspended'
|
29
|
+
puts "#{last_seen}: [#{f['id']}] #{f['first_name']} #{f['last_name']}"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# https://vk.com/dev/messages_api
|
4
|
+
#
|
5
|
+
# From February 15, 2019 methods of the messages section
|
6
|
+
# by default, will be available to call only with the community access key.
|
7
|
+
|
8
|
+
require 'bundler'
|
9
|
+
Bundler.setup :default
|
10
|
+
|
11
|
+
require 'vkontakte_client'
|
12
|
+
|
13
|
+
require 'pp'
|
14
|
+
require 'date'
|
15
|
+
require 'net/http'
|
16
|
+
require 'uri'
|
17
|
+
require 'json'
|
18
|
+
|
19
|
+
CLIENT_ID = '5987497'
|
20
|
+
|
21
|
+
offline = "\033[31;3mофлайн\033[0m"
|
22
|
+
online = "\033[32;3mонлайн\033[0m"
|
23
|
+
|
24
|
+
credentials = Vkontakte::AskForCredentials.new
|
25
|
+
email = credentials.email
|
26
|
+
pass = credentials.password
|
27
|
+
|
28
|
+
vk = Vkontakte::Client.new(CLIENT_ID)
|
29
|
+
vk.login!(email, pass, permissions: 'messages')
|
30
|
+
|
31
|
+
# https://vk.com/dev/using_longpoll
|
32
|
+
|
33
|
+
resp = vk.api.messages_getLongPollServer
|
34
|
+
puts resp
|
35
|
+
key = resp['key']
|
36
|
+
server = resp['server']
|
37
|
+
ts = resp['ts']
|
38
|
+
|
39
|
+
loop do
|
40
|
+
url = "https://#{server}?act=a_check&key=#{key}&ts=#{ts}&wait=25&mode=10&version=1"
|
41
|
+
uri = URI.parse(url)
|
42
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
43
|
+
http.use_ssl = true
|
44
|
+
|
45
|
+
begin
|
46
|
+
res = http.request(Net::HTTP::Get.new(uri.request_uri))
|
47
|
+
rescue StandardError => e
|
48
|
+
puts "[ERROR] #{e}"
|
49
|
+
sleep 5
|
50
|
+
retry
|
51
|
+
end
|
52
|
+
|
53
|
+
begin
|
54
|
+
params = JSON.parse(res.body)
|
55
|
+
rescue JSON::ParserError
|
56
|
+
puts '[ERROR] JSON Parse Error'
|
57
|
+
end
|
58
|
+
|
59
|
+
if params['failed'] == 2
|
60
|
+
puts '[INFO] Re-initilize Long Pool Server'
|
61
|
+
|
62
|
+
begin
|
63
|
+
resp = vk.api.messages_getLongPollServer
|
64
|
+
key = resp['key']
|
65
|
+
server = resp['server']
|
66
|
+
ts = resp['ts']
|
67
|
+
rescue Vkontakte::API::Error => e
|
68
|
+
if e.error_code == 5
|
69
|
+
puts '[ERROR] User authorization failed: access_token have heen expired'
|
70
|
+
puts '[INFO] Getting a new access_token'
|
71
|
+
vk.login!(email, pass, permissions: 'messages')
|
72
|
+
retry
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
next
|
77
|
+
end
|
78
|
+
|
79
|
+
params['updates']&.each do |param|
|
80
|
+
uid = e[1].abs
|
81
|
+
begin
|
82
|
+
user = vk.api.users_get(user_ids: uid, fields: 'sex').first
|
83
|
+
rescue Vkontakte::API::Error => e
|
84
|
+
if e.error_code == 5
|
85
|
+
puts "[ERROR] #{e.message}"
|
86
|
+
puts '[INFO] Getting a new access_token'
|
87
|
+
vk.login!(email, pass, permissions: 'messages')
|
88
|
+
retry
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
puts param if user.nil?
|
93
|
+
first_name = user['first_name']
|
94
|
+
last_name = user['last_name']
|
95
|
+
state = %w[стало стала став][user['sex'].to_i]
|
96
|
+
case param[0]
|
97
|
+
when 8
|
98
|
+
puts "#{Time.now.strftime('%d/%m/%y %H:%M:%S')}: #{first_name} #{last_name} #{state} #{online}"
|
99
|
+
when 9
|
100
|
+
puts "#{Time.now.strftime('%d/%m/%y %H:%M:%S')}: #{first_name} #{last_name} #{state} #{offline}"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
ts = params['ts']
|
105
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Bundler.setup :default
|
4
|
+
|
5
|
+
require 'mechanize'
|
6
|
+
require 'logger'
|
7
|
+
|
8
|
+
email = ARGV[0]
|
9
|
+
pass = ARGV[1]
|
10
|
+
|
11
|
+
client_id = '5135875'
|
12
|
+
redirect_uri = 'https://oauth.vk.com/blank.html'
|
13
|
+
display = 'mobile'
|
14
|
+
scope = 'friends,audio,video'
|
15
|
+
response_type = 'token'
|
16
|
+
v = '5.101'
|
17
|
+
|
18
|
+
# https://vk.com/dev/auth_mobile
|
19
|
+
puts 'Открытие диалога авторизации'
|
20
|
+
url = "https://oauth.vk.com/oauth/authorize?client_id=#{client_id}&display=#{display}&redirect_uri=#{redirect_uri}&scope=#{scope}&response_type=#{response_type}&v=#{v}"
|
21
|
+
puts url
|
22
|
+
|
23
|
+
# puts Mechanize::VERSION
|
24
|
+
# log = Logger.new($stderr)
|
25
|
+
# log.level = Logger::DEBUG
|
26
|
+
|
27
|
+
agent = Mechanize.new do |a|
|
28
|
+
a.user_agent_alias = 'Linux Firefox'
|
29
|
+
a.follow_meta_refresh
|
30
|
+
# a.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
31
|
+
# a.log = log
|
32
|
+
end
|
33
|
+
|
34
|
+
# agent.agent.http.debug_output = $stderr
|
35
|
+
|
36
|
+
page = agent.get(url)
|
37
|
+
|
38
|
+
login_form = page.forms.first
|
39
|
+
login_form.email = email
|
40
|
+
login_form.pass = pass
|
41
|
+
page = login_form.submit
|
42
|
+
|
43
|
+
raise('Invalid login or password.') unless page.search('.service_msg_warning').empty?
|
44
|
+
|
45
|
+
if page.uri.path == '/authorize'
|
46
|
+
puts 'Разрешение доступа'
|
47
|
+
gain_access_form = page.forms.first
|
48
|
+
page = gain_access_form.submit
|
49
|
+
end
|
50
|
+
|
51
|
+
# https://oauth.vk.com/blank.html#access_token=398ef517c9552129ec0f4df40ac483f9a29dd8f309f72323846deb40ee8799b38138cff939762c979c093&expires_in=86400&user_id=83380724
|
52
|
+
gragment_regexp = /\Aaccess_token=(?<access_token>.*)&expires_in=(?<expires_in>\d+)&user_id=(?<user_id>\d*)\z/
|
53
|
+
auth_params = page.uri.fragment.match(gragment_regexp)
|
54
|
+
|
55
|
+
puts "access_token = #{auth_params[:access_token]}" if auth_params
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.setup :default
|
5
|
+
|
6
|
+
require 'vkontakte_client'
|
7
|
+
|
8
|
+
puts Vkontakte::VERSION
|
9
|
+
|
10
|
+
if $PROGRAM_NAME == __FILE__
|
11
|
+
CLIENT_ID = '5987497'
|
12
|
+
|
13
|
+
email = ARGV[0]
|
14
|
+
pass = ARGV[1]
|
15
|
+
|
16
|
+
vk = Vkontakte::Client.new(CLIENT_ID)
|
17
|
+
vk.login!(email, pass, permissions: 'friends', open_captcha: true)
|
18
|
+
|
19
|
+
out_requests = []
|
20
|
+
count = 1000
|
21
|
+
offset = 0
|
22
|
+
|
23
|
+
loop do
|
24
|
+
fr = vk.api.friends_getRequests(count: count, offset: offset * count, out: 1)['items']
|
25
|
+
break if fr.empty?
|
26
|
+
|
27
|
+
out_requests << fr
|
28
|
+
offset += 1
|
29
|
+
end
|
30
|
+
out_requests.flatten!
|
31
|
+
|
32
|
+
out_requests_size = out_requests.size
|
33
|
+
|
34
|
+
puts "You have #{out_requests_size} out requests."
|
35
|
+
|
36
|
+
out_requests.each_with_index do |id, i|
|
37
|
+
resp = vk.api.friends_delete(user_id: id)
|
38
|
+
if resp['out_request_deleted'] == 1
|
39
|
+
puts "[#{i + 1}/#{out_requests_size}] Succeess delete request to `#{id}`"
|
40
|
+
else
|
41
|
+
resp
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.setup :default
|
5
|
+
|
6
|
+
require 'vkontakte_client'
|
7
|
+
|
8
|
+
puts Vkontakte::VERSION
|
9
|
+
|
10
|
+
if $PROGRAM_NAME == __FILE__
|
11
|
+
CLIENT_ID = '5987497'
|
12
|
+
|
13
|
+
email = ARGV[0]
|
14
|
+
pass = ARGV[1]
|
15
|
+
|
16
|
+
vk = Vkontakte::Client.new(CLIENT_ID)
|
17
|
+
vk.login!(email, pass, permissions: 'friends', open_captcha: true)
|
18
|
+
|
19
|
+
vk.api.account_getInfo
|
20
|
+
|
21
|
+
# https://vk.com/dev/friends.get
|
22
|
+
friends = vk.api.friends_get(fields: 'online,last_seen')['items']
|
23
|
+
friends.each do |f|
|
24
|
+
deactivated = f['deactivated'] == 'banned'
|
25
|
+
if deactivated
|
26
|
+
puts "Delete user with id `#{f['id']}`"
|
27
|
+
vk.api.friends_delete(user_id: f['id'])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.setup :default
|
5
|
+
|
6
|
+
require 'vkontakte_client'
|
7
|
+
|
8
|
+
puts Vkontakte::VERSION
|
9
|
+
|
10
|
+
uids = %w[strutynska amaminov]
|
11
|
+
|
12
|
+
# vk = Vkontakte::Client.new
|
13
|
+
# puts vk.authorized?
|
14
|
+
# puts vk.api.users_get(uids: uids.join(','), fields: 'online,last_seen')
|
15
|
+
|
16
|
+
api = Vkontakte::API.new
|
17
|
+
puts api.users_get(uids: uids.join(','), fields: 'online,last_seen')
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'vkontakte_client'
|
4
|
+
|
5
|
+
if $PROGRAM_NAME == __FILE__
|
6
|
+
CLIENT_ID = '5987497'
|
7
|
+
|
8
|
+
email = ARGV[0]
|
9
|
+
pass = ARGV[1]
|
10
|
+
|
11
|
+
vk = Vkontakte::Client.new(CLIENT_ID)
|
12
|
+
|
13
|
+
vk.login!(email, pass, open_captcha: true, permissions: 'friends')
|
14
|
+
vk_api = vk.api
|
15
|
+
|
16
|
+
friends_requests_ids = vk_api.friends_getRequests(need_viewed: 1, out: 0)['items']
|
17
|
+
|
18
|
+
current_user = vk_api.users_get(fields: 'counters').first
|
19
|
+
|
20
|
+
puts "User: #{current_user['first_name']} #{current_user['last_name']}"
|
21
|
+
puts "Friends: #{current_user['counters']['friends']}"
|
22
|
+
puts "Online Friends: #{current_user['counters']['online_friends']}"
|
23
|
+
puts "Friends requests: #{friends_requests_ids.size}"
|
24
|
+
puts "Subscriptions: #{current_user['counters']['subscriptions']}"
|
25
|
+
end
|
data/gems.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'socksify'
|
4
|
+
require 'socksify/http'
|
5
|
+
|
6
|
+
# agent = Mechanize.new
|
7
|
+
# agent.agent.set_socks('localhost', 9050) #Use Tor as proxy
|
8
|
+
#
|
9
|
+
class Mechanize::HTTP::Agent
|
10
|
+
def set_socks(addr, port)
|
11
|
+
set_http unless @http
|
12
|
+
|
13
|
+
class << @http
|
14
|
+
attr_accessor :socks_addr, :socks_port
|
15
|
+
|
16
|
+
def http_class
|
17
|
+
Net::HTTP.SOCKSProxy(socks_addr, socks_port)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
@http.socks_addr = addr
|
22
|
+
@http.socks_port = port
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Vkontakte
|
4
|
+
# Make Vkontakte API requests
|
5
|
+
#
|
6
|
+
class API
|
7
|
+
attr_reader :access_token, :proxy, :api_version, :timeout
|
8
|
+
attr_accessor :lang
|
9
|
+
|
10
|
+
def initialize(
|
11
|
+
access_token = nil,
|
12
|
+
proxy: nil,
|
13
|
+
api_version: Vkontakte::API_VERSION,
|
14
|
+
lang: 'ru',
|
15
|
+
timeout: 60
|
16
|
+
)
|
17
|
+
@access_token = access_token
|
18
|
+
@proxy = proxy
|
19
|
+
@api_version = api_version
|
20
|
+
@lang = lang
|
21
|
+
@timeout = timeout
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(method, *params)
|
25
|
+
method_name = method.to_s.split('_').join('.')
|
26
|
+
response = execute(method_name, *params)
|
27
|
+
if response['error']
|
28
|
+
error_code = response['error']['error_code']
|
29
|
+
error_msg = response['error']['error_msg']
|
30
|
+
raise Vkontakte::API::Error.new(method_name, error_code, error_msg, params)
|
31
|
+
end
|
32
|
+
|
33
|
+
response['response']
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def execute(method_name, params = {})
|
39
|
+
params.merge!(access_token: @access_token, lang: @lang, v: @api_version, https: '1')
|
40
|
+
|
41
|
+
url = "https://api.vk.com/method/#{method_name}"
|
42
|
+
|
43
|
+
response = make_request(url, params)
|
44
|
+
|
45
|
+
JSON.parse(response.body)
|
46
|
+
end
|
47
|
+
|
48
|
+
def make_request(url, params)
|
49
|
+
uri = URI(url)
|
50
|
+
use_ssl = uri.scheme == 'https'
|
51
|
+
|
52
|
+
request = Net::HTTP::Post.new(uri)
|
53
|
+
request.form_data = params
|
54
|
+
|
55
|
+
if @proxy
|
56
|
+
if @proxy.http?
|
57
|
+
Net::HTTP.start(
|
58
|
+
uri.hostname,
|
59
|
+
uri.port,
|
60
|
+
@proxy.addr,
|
61
|
+
@proxy.port,
|
62
|
+
use_ssl: use_ssl,
|
63
|
+
read_timeout: timeout,
|
64
|
+
open_timeout: timeout
|
65
|
+
) do |http|
|
66
|
+
http.request(request)
|
67
|
+
end
|
68
|
+
elsif @proxy.socks?
|
69
|
+
Net::HTTP.SOCKSProxy(@proxy.addr, @proxy.port).start(uri.hostname, uri.port, use_ssl: use_ssl) do |http|
|
70
|
+
http.request(request)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
else
|
74
|
+
Net::HTTP.start(
|
75
|
+
uri.hostname,
|
76
|
+
uri.port,
|
77
|
+
use_ssl: use_ssl,
|
78
|
+
read_timeout: timeout,
|
79
|
+
open_timeout: timeout
|
80
|
+
) do |http|
|
81
|
+
http.request(request)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|