vk_longpoll_bot 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +8 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +25 -0
- data/README.md +37 -5
- data/Rakefile +10 -24
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/examples/audio_bot/main.rb +42 -0
- data/examples/chat_bot/main.rb +29 -0
- data/examples/command_bot/main.rb +37 -0
- data/lib/vk_longpoll_bot.rb +11 -6
- data/lib/vk_longpoll_bot/bot.rb +88 -52
- data/lib/vk_longpoll_bot/constants.rb +4 -1
- data/lib/vk_longpoll_bot/events.rb +65 -14
- data/lib/vk_longpoll_bot/exceptions.rb +16 -1
- data/lib/vk_longpoll_bot/request.rb +27 -5
- data/lib/vk_longpoll_bot/utility.rb +12 -3
- data/lib/vk_longpoll_bot/version.rb +7 -0
- data/vk_longpoll_bot.gemspec +36 -16
- metadata +56 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6b0cfc136c4a32241d516da8a4a93ddca2233cfbe78110585191c891d7f7f37
|
4
|
+
data.tar.gz: ea9f81876c642fd066bfce3eb548b28979812f5296cfa52106db311f519db628
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7338044936b97bceb6f0d293f9d81b4f39634a268ae336177eb4c44c2bb43defcbf976e0b467edee2f12f12be5df1a662789737e7b1a1750e0ff124e1201209
|
7
|
+
data.tar.gz: 1943ef424b8aa3c9c0836aa1f3a56f663f89bd5b026cd38a816a3db6154175c7ebec82da48a360eb819bff702c0def6582822f6b753eb6306f18eaa801c08282
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
vk_longpoll_bot (0.1.0)
|
5
|
+
json (~> 2.2.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
json (2.2.0)
|
11
|
+
minitest (5.12.0)
|
12
|
+
rake (10.5.0)
|
13
|
+
|
14
|
+
PLATFORMS
|
15
|
+
x64-mingw32
|
16
|
+
|
17
|
+
DEPENDENCIES
|
18
|
+
bundler (~> 2.0)
|
19
|
+
json (~> 2.2)
|
20
|
+
minitest (~> 5.0)
|
21
|
+
rake (~> 10.0)
|
22
|
+
vk_longpoll_bot!
|
23
|
+
|
24
|
+
BUNDLED WITH
|
25
|
+
2.0.2
|
data/README.md
CHANGED
@@ -1,5 +1,37 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
# VkLongpollBot
|
2
|
+
|
3
|
+
This small gem provides interface to work with VK API and create simple longpoll bot for group.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'vk_longpoll_bot'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install vk_longpoll_bot
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
You can find usage examples in `example` folder.
|
24
|
+
|
25
|
+
## Development
|
26
|
+
|
27
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
28
|
+
|
29
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
30
|
+
|
31
|
+
## Contributing
|
32
|
+
|
33
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/fizvlad/vk-longpoll-bot-rb.
|
34
|
+
|
35
|
+
## License
|
36
|
+
|
37
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,24 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
desc "Build and install gem"
|
14
|
-
task :install_local => :build do
|
15
|
-
puts `gem install ./#{GEM_NAME}-*.gem`
|
16
|
-
end
|
17
|
-
|
18
|
-
desc "Setup SSL certificate"
|
19
|
-
task :setup_ssl do
|
20
|
-
print "Path to SSL certificate (leave empty if there is no troubles with SSL):"
|
21
|
-
ssl_cert_path = STDIN.gets.chomp
|
22
|
-
puts
|
23
|
-
ENV["SSL_CERT_FILE"] = ssl_cert_path
|
24
|
-
end
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
4
|
+
Rake::TestTask.new(:test) do |t|
|
5
|
+
t.libs << "test"
|
6
|
+
t.libs << "lib"
|
7
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => :test
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "vk_longpoll_bot"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
2
|
+
|
3
|
+
require "vk_music" # See https://rubygems.org/gems/vk_music
|
4
|
+
|
5
|
+
require "vk_longpoll_bot"
|
6
|
+
include VkLongpollBot
|
7
|
+
|
8
|
+
bot = Bot.new(ARGV[0], ARGV[1])
|
9
|
+
|
10
|
+
bot.on_start { puts "Starting bot." }
|
11
|
+
bot.on_finish { puts "Finishing bot." }
|
12
|
+
|
13
|
+
bot.on(subtype: "message_new") do |event|
|
14
|
+
next unless event["attachments"] && event["body"].chomp == "id"
|
15
|
+
reply = []
|
16
|
+
event["attachments"].each do |att|
|
17
|
+
if att["type"] == "audio"
|
18
|
+
audio = VkMusic::Audio.new(
|
19
|
+
artist: att["audio"]["artist"],
|
20
|
+
id: att["audio"]["id"],
|
21
|
+
owner_id: att["audio"]["owner_id"],
|
22
|
+
title: att["audio"]["title"],
|
23
|
+
url: att["audio"]["url"],
|
24
|
+
duration: att["audio"]["duration"]
|
25
|
+
)
|
26
|
+
|
27
|
+
puts audio
|
28
|
+
reply << "#{audio.owner_id}_#{audio.id}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
bot.send_message(event["user_id"], reply.join("\n")) unless reply.empty?
|
33
|
+
end
|
34
|
+
|
35
|
+
bot.on(subtype: "message_new") do |event|
|
36
|
+
if event["body"].chomp == "stop"
|
37
|
+
bot.send_message(event["user_id"], "Shutting down")
|
38
|
+
bot.stop
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
bot.run
|
@@ -0,0 +1,29 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
2
|
+
|
3
|
+
require "vk_longpoll_bot"
|
4
|
+
include VkLongpollBot
|
5
|
+
|
6
|
+
bot = Bot.new(ARGV[0], ARGV[1])
|
7
|
+
|
8
|
+
bot.on_start { puts "Starting bot." }
|
9
|
+
bot.on_finish { puts "Finishing bot." }
|
10
|
+
|
11
|
+
bot.on(subtype: "message_typing_state") do |event|
|
12
|
+
puts "#{event["from_id"]} is typing message"
|
13
|
+
end
|
14
|
+
|
15
|
+
bot.on(subtype: "message_new") do |event|
|
16
|
+
puts "Got message from #{event["user_id"]}: #{event["body"]}"
|
17
|
+
bot.send_message(event["user_id"], "I got your message")
|
18
|
+
|
19
|
+
if event["attachments"]
|
20
|
+
puts "And it got attachments! #{event["attachments"]}"
|
21
|
+
end
|
22
|
+
|
23
|
+
if event["body"].chomp == "stop"
|
24
|
+
bot.send_message(event["user_id"], "Shutting down")
|
25
|
+
bot.stop
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
bot.run
|
@@ -0,0 +1,37 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
2
|
+
|
3
|
+
require "vk_longpoll_bot"
|
4
|
+
include VkLongpollBot
|
5
|
+
|
6
|
+
PREFIX = ">"
|
7
|
+
|
8
|
+
bot = Bot.new(ARGV[0], ARGV[1], api_version: "5.74")
|
9
|
+
|
10
|
+
bot.on_start do
|
11
|
+
puts "Starting bot."
|
12
|
+
bot.enable_online
|
13
|
+
end
|
14
|
+
bot.on_finish do
|
15
|
+
puts "Finishing bot."
|
16
|
+
bot.disable_online
|
17
|
+
end
|
18
|
+
|
19
|
+
bot.on(subtype: "message_new") do |event|
|
20
|
+
puts "Got message from #{event["user_id"]}: #{event["body"].chomp}"
|
21
|
+
next unless event["body"].start_with?(PREFIX)
|
22
|
+
command = event["body"].chomp.sub(PREFIX, "")
|
23
|
+
|
24
|
+
case command
|
25
|
+
when "help"
|
26
|
+
bot.send_message(event["user_id"], "Available commands: \n* help - show this message\n* answer - answer message\n* exit, stop - shut down")
|
27
|
+
when "answer"
|
28
|
+
bot.send_message(event["user_id"], "Answering")
|
29
|
+
when "exit", "stop"
|
30
|
+
bot.send_message(event["user_id"], "Shutting down")
|
31
|
+
bot.stop
|
32
|
+
else
|
33
|
+
bot.send_message(event["user_id"], "Unknwon command")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
bot.run
|
data/lib/vk_longpoll_bot.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
require "vk_longpoll_bot/utility"
|
2
|
+
require "vk_longpoll_bot/constants"
|
3
|
+
require "vk_longpoll_bot/exceptions"
|
4
|
+
require "vk_longpoll_bot/request"
|
5
|
+
require "vk_longpoll_bot/bot"
|
6
|
+
require "vk_longpoll_bot/events"
|
7
|
+
require "vk_longpoll_bot/version"
|
8
|
+
|
9
|
+
##
|
10
|
+
# Main module.
|
11
|
+
module VkLongpollBot; end
|
data/lib/vk_longpoll_bot/bot.rb
CHANGED
@@ -1,96 +1,139 @@
|
|
1
1
|
module VkLongpollBot
|
2
2
|
|
3
|
+
##
|
3
4
|
# Main class, which contains all the methods of bot.
|
4
5
|
class Bot
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
##
|
8
|
+
# @return [Integer] group ID.
|
9
|
+
attr_reader :id
|
10
|
+
|
11
|
+
##
|
12
|
+
# @return [Hash<Symbol, Array<EventListener>>] hash with listeners for each of event type.
|
13
|
+
attr_reader :event_listeners
|
8
14
|
|
9
|
-
|
15
|
+
##
|
16
|
+
# Initialize bot. This method don't start longpoll session.
|
17
|
+
#
|
18
|
+
# @param access_token [String] group access token.
|
19
|
+
# @param group_id [Integer] group of associated ID.
|
20
|
+
# @param options [Hash]
|
10
21
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
def initialize(access_token, id, options = {})
|
22
|
+
# @option options [Gem::Version, String] api_version (VK_API_URL_BASE) version of VK API.
|
23
|
+
# @option options [Integer] longpoll_wait longpoll (LONGPOLL_STANDART_WAIT) requests timeout.
|
24
|
+
def initialize(access_token, group_id, options = {})
|
15
25
|
@event_listeners = Hash.new { |hash, key| hash[key] = Array.new }
|
16
26
|
@on_start = []
|
17
27
|
@on_finish = []
|
18
28
|
|
19
|
-
@access_token = access_token
|
20
|
-
@id =
|
29
|
+
@access_token = access_token.to_s
|
30
|
+
@id = group_id.to_i
|
21
31
|
|
22
32
|
@api_version = options[:api_version] || VK_API_CURRENT_VERSION
|
23
33
|
@longpoll_wait = options[:longpoll_wait] || LONGPOLL_STANDART_WAIT
|
24
34
|
|
25
35
|
@longpoll = {}
|
26
|
-
|
27
|
-
# TODO
|
28
36
|
end
|
29
37
|
|
30
|
-
|
31
|
-
#
|
32
|
-
# =========================================================================
|
38
|
+
##
|
39
|
+
# @! group API methods
|
33
40
|
|
34
|
-
|
41
|
+
##
|
42
|
+
# Call for API method.
|
43
|
+
#
|
44
|
+
# @param method_name ["String"] name of requested method. See https://vk.com/dev/methods
|
45
|
+
#
|
46
|
+
# @return [Hash]
|
35
47
|
def api(method_name, parameters = {})
|
36
48
|
Request.api(method_name, parameters, @access_token, @api_version)
|
37
49
|
end
|
38
50
|
|
39
|
-
|
40
|
-
|
51
|
+
##
|
52
|
+
# Send text message.
|
53
|
+
#
|
54
|
+
# @param target [Integer] ID of receiver.
|
55
|
+
# @param content [String] text of message.
|
56
|
+
# @param options [Hash] additional options which must be sent with request.
|
57
|
+
# Options +user_id+, +message+ and +random_id+ will be overwritten
|
58
|
+
#
|
59
|
+
# @return [Hash]
|
60
|
+
def send_message(target, content, options = {})
|
41
61
|
target_id = target.to_i
|
42
|
-
|
43
|
-
|
62
|
+
forced_options = {
|
63
|
+
user_id: target_id,
|
64
|
+
message: content,
|
65
|
+
random_id: Utility.random_id(target_id)
|
66
|
+
}
|
67
|
+
api("messages.send", options.merge(forced_options))
|
44
68
|
end
|
45
69
|
|
70
|
+
##
|
46
71
|
# Enable group online status
|
47
|
-
|
72
|
+
#
|
73
|
+
# @return [nil]
|
74
|
+
def enable_online
|
48
75
|
begin
|
49
|
-
api("groups.enableOnline", group_id:
|
76
|
+
api("groups.enableOnline", group_id: @id)
|
50
77
|
rescue
|
51
78
|
# Online is already enabled
|
52
79
|
end
|
80
|
+
nil
|
53
81
|
end
|
54
82
|
|
83
|
+
##
|
55
84
|
# Disable group online status
|
56
|
-
|
85
|
+
#
|
86
|
+
# @return [nil]
|
87
|
+
def disable_online
|
57
88
|
begin
|
58
|
-
api("groups.disableOnline", group_id:
|
89
|
+
api("groups.disableOnline", group_id: @id)
|
59
90
|
rescue
|
60
91
|
# Online is already disabled
|
61
92
|
end
|
93
|
+
nil
|
62
94
|
end
|
63
95
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
#
|
96
|
+
##
|
97
|
+
# @!endgroup
|
98
|
+
|
99
|
+
##
|
100
|
+
# @!group Events
|
69
101
|
|
70
|
-
|
102
|
+
##
|
103
|
+
# Add new event listener.
|
104
|
+
#
|
105
|
+
# @param options [Hash]
|
106
|
+
#
|
107
|
+
# @option options [String] subtype
|
108
|
+
#
|
109
|
+
# @yieldparam event [Event]
|
71
110
|
#
|
72
|
-
#
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
111
|
+
# @return [nil]
|
112
|
+
def on(options, &block)
|
113
|
+
raise ArgumentError.new("Got subtype #{options[:subtype]} of class #{options[:subtype].class}") unless String === options[:subtype] && Events.valid_subtype?(options[:subtype])
|
114
|
+
@event_listeners[options[:subtype]] << Events::EventListener.new(options, &block)
|
115
|
+
nil
|
77
116
|
end
|
78
117
|
|
118
|
+
##
|
79
119
|
# Add code to be executed right after bot starts.
|
80
120
|
def on_start(&block)
|
81
121
|
@on_start << block
|
82
122
|
end
|
83
123
|
|
124
|
+
##
|
84
125
|
# Add code to be executed right after bot finishes.
|
85
126
|
def on_finish(&block)
|
86
127
|
@on_finish << block
|
87
128
|
end
|
129
|
+
|
130
|
+
##
|
131
|
+
# @!endgroup
|
88
132
|
|
89
|
-
|
90
|
-
#
|
91
|
-
#
|
92
|
-
|
93
|
-
# Start bot. This methods freeze current thread until <tt>stop</tt> called.
|
133
|
+
##
|
134
|
+
# Start bot. This methods freeze current thread until {Bot#stop} method is called.
|
135
|
+
#
|
136
|
+
# @return [void]
|
94
137
|
def run
|
95
138
|
@on_start.each(&:call)
|
96
139
|
|
@@ -100,18 +143,16 @@ module VkLongpollBot
|
|
100
143
|
@on_finish.each(&:call)
|
101
144
|
end
|
102
145
|
|
146
|
+
##
|
103
147
|
# Stop bot.
|
148
|
+
#
|
149
|
+
# @return [void]
|
104
150
|
def stop
|
105
151
|
@finish_flag = true
|
106
152
|
end
|
107
153
|
|
108
|
-
# =========================================================================
|
109
|
-
private
|
110
|
-
# =========================================================================
|
111
154
|
|
112
|
-
|
113
|
-
# LONGPOLL
|
114
|
-
# =========================================================================
|
155
|
+
private
|
115
156
|
|
116
157
|
# Request longpoll data.
|
117
158
|
def init_longpoll
|
@@ -121,14 +162,13 @@ module VkLongpollBot
|
|
121
162
|
@longpoll[:ts] = lp["ts"]
|
122
163
|
end
|
123
164
|
|
124
|
-
# Start longpoll. Requires
|
165
|
+
# Start longpoll. Requires +init_longpoll+ to be run first.
|
125
166
|
def run_longpoll
|
126
167
|
@finish_flag = false # Setting up flag for loop
|
127
168
|
|
128
169
|
until @finish_flag
|
129
|
-
response = Request.longpoll(@longpoll[:server], @longpoll[:key], @longpoll[:ts], @longpoll_wait)
|
170
|
+
response = Request.longpoll(@longpoll[:server], @longpoll[:key], @longpoll[:ts], @longpoll_wait)
|
130
171
|
if response["failed"]
|
131
|
-
# Error happened
|
132
172
|
Utility.warn "Longpoll failed with code #{response["failed"]}. This must be solvable. Keep running..."
|
133
173
|
case response["failed"]
|
134
174
|
when 1
|
@@ -150,10 +190,6 @@ module VkLongpollBot
|
|
150
190
|
end
|
151
191
|
end
|
152
192
|
end
|
153
|
-
|
154
|
-
# =========================================================================
|
155
|
-
# EVENTS
|
156
|
-
# =========================================================================
|
157
193
|
|
158
194
|
# Handle update from longpoll.
|
159
195
|
def update_handler(update)
|
@@ -1,12 +1,15 @@
|
|
1
1
|
module VkLongpollBot
|
2
2
|
|
3
|
+
##
|
3
4
|
# Base of URL to API.
|
4
5
|
VK_API_URL_BASE = "https://api.vk.com"
|
5
6
|
|
7
|
+
##
|
6
8
|
# It's recommended to use last version of VK API.
|
7
9
|
VK_API_CURRENT_VERSION = Gem::Version.new("5.101")
|
8
10
|
|
11
|
+
##
|
9
12
|
# Longpoll requests timeout.
|
10
13
|
LONGPOLL_STANDART_WAIT = 25
|
11
14
|
|
12
|
-
end
|
15
|
+
end
|
@@ -1,14 +1,16 @@
|
|
1
1
|
module VkLongpollBot
|
2
2
|
|
3
|
+
##
|
3
4
|
# Everything related to longpoll events.
|
4
5
|
module Events
|
5
6
|
|
6
|
-
|
7
|
+
##
|
8
|
+
# All the types and subtypes of events.
|
7
9
|
TYPES = {
|
8
10
|
message: %w{message_new message_reply message_edit message_typing_state message_allow message_deny},
|
9
11
|
photo: %w{photo_new photo_comment_new photo_comment_edit photo_comment_restore photo_comment_delete},
|
10
12
|
audio: %w{audio_new},
|
11
|
-
video: %w{video_new video_comment_new video_comment_restore video_comment_delete},
|
13
|
+
video: %w{video_new video_comment_new video_comment_edit video_comment_restore video_comment_delete},
|
12
14
|
wall: %w{wall_post_new wall_repost wall_reply_new wall_reply_edit wall_reply_restore wall_reply_delete},
|
13
15
|
board: %w{board_post_new board_post_edit board_post_restore board_post_delete},
|
14
16
|
market: %w{market_comment_new market_comment_edit market_comment_restore market_comment_delete},
|
@@ -19,16 +21,41 @@ module VkLongpollBot
|
|
19
21
|
app: %w{app_payload}
|
20
22
|
}
|
21
23
|
|
24
|
+
##
|
25
|
+
# Check whether subtype is correct.
|
26
|
+
#
|
27
|
+
# @param subtype [String]
|
22
28
|
def self.valid_subtype?(subtype)
|
23
29
|
TYPES.values.any? { |arr| arr.include?(subtype) }
|
24
30
|
end
|
25
31
|
|
26
|
-
|
32
|
+
##
|
33
|
+
# Class containing data received from longpoll. Provides easy access to it's data.
|
27
34
|
class Event
|
28
35
|
|
29
|
-
|
36
|
+
##
|
37
|
+
# @return [String] subtype of event.
|
38
|
+
attr_reader :subtype
|
39
|
+
|
40
|
+
##
|
41
|
+
# @return [Integer] ID of group which received event.
|
42
|
+
attr_reader :group_id
|
43
|
+
|
44
|
+
##
|
45
|
+
# @return [Hash] hash with updates data.
|
46
|
+
attr_reader :data
|
47
|
+
|
48
|
+
##
|
49
|
+
# @return [Bot] longpoll bot which received event.
|
50
|
+
attr_reader :bot
|
30
51
|
|
31
|
-
|
52
|
+
##
|
53
|
+
# New event. Initialize from fields of update json and bot which got this event.
|
54
|
+
#
|
55
|
+
# @param subtype [String]
|
56
|
+
# @param data [Hash] +update+ array entry.
|
57
|
+
# @param group_id [Integer]
|
58
|
+
# @param bot [Bot]
|
32
59
|
def initialize(subtype, data, group_id, bot)
|
33
60
|
@subtype = subtype.to_s
|
34
61
|
@data = data
|
@@ -36,37 +63,61 @@ module VkLongpollBot
|
|
36
63
|
@bot = bot
|
37
64
|
end
|
38
65
|
|
66
|
+
##
|
39
67
|
# Provides access to fields of update data.
|
68
|
+
#
|
69
|
+
# @param arg [String] hash key.
|
70
|
+
#
|
71
|
+
# @return [Object]
|
40
72
|
def [](arg)
|
41
73
|
@data[arg.to_s]
|
42
74
|
end
|
43
|
-
|
44
|
-
# TODO
|
45
75
|
|
46
76
|
end
|
47
77
|
|
48
78
|
# NOTE: It might be better to create separate class for each event but there's lot of them and they don't have good hierarchy.
|
49
79
|
|
80
|
+
##
|
50
81
|
# Class containing block to run on some event.
|
51
82
|
class EventListener
|
52
83
|
|
84
|
+
##
|
85
|
+
# @return [String] subtype of this listener.
|
53
86
|
attr_reader :subtype
|
54
87
|
|
55
|
-
|
56
|
-
|
88
|
+
##
|
89
|
+
# Initialize new listener
|
90
|
+
#
|
91
|
+
# @param options[Hash]
|
92
|
+
#
|
93
|
+
# @option options [String] subtype
|
94
|
+
#
|
95
|
+
# @yieldparam event [Event]
|
96
|
+
def initialize(options, &block)
|
97
|
+
@subtype = options[:subtype]
|
57
98
|
@block = block
|
58
|
-
|
59
|
-
# TODO
|
60
99
|
end
|
61
100
|
|
101
|
+
##
|
102
|
+
# Calls block with given event as argument.
|
103
|
+
#
|
104
|
+
# @param event [Event]
|
105
|
+
#
|
106
|
+
# @return [void]
|
62
107
|
def call(event)
|
63
108
|
@block.call(event)
|
64
109
|
end
|
65
110
|
|
66
|
-
# TODO
|
67
|
-
|
68
111
|
end
|
69
112
|
|
70
113
|
end
|
71
114
|
|
72
|
-
|
115
|
+
##
|
116
|
+
# Alias for {Events::Event} class
|
117
|
+
Event = Events::Event
|
118
|
+
|
119
|
+
##
|
120
|
+
# Alias for {Events::EventListener} class
|
121
|
+
EventListener = Events::EventListener
|
122
|
+
|
123
|
+
end
|
@@ -1,8 +1,10 @@
|
|
1
1
|
module VkLongpollBot
|
2
2
|
|
3
|
+
##
|
3
4
|
# Custom exceptions.
|
4
5
|
module Exceptions
|
5
6
|
|
7
|
+
##
|
6
8
|
# All of the error codes descriptions. Source: https://vk.com/dev/errors
|
7
9
|
CODES = {
|
8
10
|
1 => "Произошла неизвестная ошибка.",
|
@@ -54,35 +56,48 @@ module VkLongpollBot
|
|
54
56
|
940 => "Слишком много постов в сообщении."
|
55
57
|
}
|
56
58
|
|
59
|
+
##
|
57
60
|
# Something wrong with response from vk.com.
|
58
61
|
class ResponseError < RuntimeError
|
59
62
|
end
|
60
63
|
|
64
|
+
##
|
61
65
|
# API error. Must have some code and description.
|
62
66
|
class APIError < ResponseError
|
63
67
|
|
64
68
|
attr_reader :error
|
65
69
|
|
70
|
+
##
|
71
|
+
# Create new instance.
|
72
|
+
#
|
73
|
+
# @param error [Hash] response hash which contains "error" key.
|
66
74
|
def initialize(error)
|
67
75
|
@error = error["error"]
|
68
76
|
super("#{code}: #{included_message}")
|
69
77
|
end
|
70
78
|
|
79
|
+
##
|
80
|
+
# @return [Integer]
|
71
81
|
def code
|
72
82
|
@error["error_code"]
|
73
83
|
end
|
74
84
|
|
85
|
+
##
|
86
|
+
# @return [String] attached error description.
|
75
87
|
def included_message
|
76
88
|
@error["error_msg"]
|
77
89
|
end
|
78
90
|
|
91
|
+
##
|
92
|
+
# @return [String] error description from API documentation.
|
79
93
|
def description
|
80
94
|
CODES[code]
|
81
95
|
end
|
82
96
|
|
83
97
|
end
|
84
98
|
|
85
|
-
|
99
|
+
##
|
100
|
+
# Something wrong with longpoll response.
|
86
101
|
class LongpollError < ResponseError
|
87
102
|
end
|
88
103
|
|
@@ -3,16 +3,30 @@ require "json"
|
|
3
3
|
|
4
4
|
module VkLongpollBot
|
5
5
|
|
6
|
-
|
6
|
+
##
|
7
|
+
# Some functions to send HTTP requests.
|
7
8
|
module Request
|
8
9
|
|
9
|
-
|
10
|
+
##
|
11
|
+
# Regular GET HTTP request to given URI.
|
12
|
+
#
|
13
|
+
# @param url [String]
|
14
|
+
#
|
15
|
+
# @return [String]
|
10
16
|
def self.to(url)
|
11
17
|
uri = URI(url.to_s)
|
12
18
|
Net::HTTP.get(uri)
|
13
19
|
end
|
14
20
|
|
15
|
-
|
21
|
+
##
|
22
|
+
# GET request to VK API.
|
23
|
+
#
|
24
|
+
# @param method_name [String, Symbol]
|
25
|
+
# @param parameters [Hash]
|
26
|
+
# @param access_token [String]
|
27
|
+
# @param v [Gem::Version, String] VK API version.
|
28
|
+
#
|
29
|
+
# @return [Hash]
|
16
30
|
def self.api(method_name, parameters, access_token, v = VK_API_CURRENT_VERSION)
|
17
31
|
response = JSON.parse self.to("#{VK_API_URL_BASE}/method/#{method_name}?access_token=#{access_token}&v=#{v.to_s}&#{URI.encode_www_form(parameters)}")
|
18
32
|
if response["response"]
|
@@ -24,11 +38,19 @@ module VkLongpollBot
|
|
24
38
|
end
|
25
39
|
end
|
26
40
|
|
27
|
-
|
41
|
+
##
|
42
|
+
# GET request to longpoll server.
|
43
|
+
#
|
44
|
+
# @param server [String] server address.
|
45
|
+
# @param key [String] secret session key.
|
46
|
+
# @param ts [Integer] index of last event.
|
47
|
+
# @param wait [Integer] size of request timeout in seconds.
|
48
|
+
#
|
49
|
+
# @return [Hash] hash with timestamp of last event and array of updates.
|
28
50
|
def self.longpoll(server, key, ts, wait = LONGPOLL_STANDART_WAIT)
|
29
51
|
JSON.parse self.to("#{server}?act=a_check&key=#{key}&ts=#{ts}&wait=#{wait}")
|
30
52
|
end
|
31
53
|
|
32
54
|
end
|
33
55
|
|
34
|
-
end
|
56
|
+
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module VkLongpollBot
|
2
2
|
|
3
|
-
|
3
|
+
##
|
4
|
+
# Some utility methods.
|
4
5
|
module Utility
|
5
6
|
|
6
|
-
|
7
|
+
##
|
8
|
+
# Log warning message.
|
7
9
|
def self.warn(msg)
|
8
10
|
if defined?(Warning.warn)
|
9
11
|
Warning.warn msg
|
@@ -12,7 +14,14 @@ module VkLongpollBot
|
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
15
|
-
|
17
|
+
##
|
18
|
+
# Generate +random_id+ for message.
|
19
|
+
#
|
20
|
+
# This method generates random numerical ID based on current time, receiver ID and random salt.
|
21
|
+
#
|
22
|
+
# @param target_id [Integer] ID of message receiver.
|
23
|
+
#
|
24
|
+
# @return [Integer]
|
16
25
|
def self.random_id(target_id)
|
17
26
|
(rand(1000) * target_id * Time.now.to_f * 1000).to_i % 2**32
|
18
27
|
end
|
data/vk_longpoll_bot.gemspec
CHANGED
@@ -1,16 +1,36 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "vk_longpoll_bot/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "vk_longpoll_bot"
|
7
|
+
spec.version = VkLongpollBot::VERSION
|
8
|
+
spec.authors = ["Fizvlad"]
|
9
|
+
spec.email = ["fizvlad@mail.ru"]
|
10
|
+
|
11
|
+
spec.summary = "Provides interface to create simple VK longpoll bot"
|
12
|
+
spec.description = "Library to work with VK API and create simple longpoll bot for group."
|
13
|
+
spec.homepage = "https://github.com/fizvlad/vk-longpoll-bot-rb"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.required_ruby_version = ">=2.3.1"
|
17
|
+
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
spec.metadata["source_code_uri"] = "https://github.com/fizvlad/vk-longpoll-bot-rb"
|
20
|
+
spec.metadata["changelog_uri"] = "https://github.com/fizvlad/vk-longpoll-bot-rb/releases"
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
end
|
27
|
+
spec.bindir = "exe"
|
28
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
29
|
+
spec.require_paths = ["lib"]
|
30
|
+
|
31
|
+
spec.add_runtime_dependency "json", "~> 2.2.0"
|
32
|
+
|
33
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
34
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
35
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
36
|
+
end
|
metadata
CHANGED
@@ -1,52 +1,90 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vk_longpoll_bot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Fizvlad
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: json
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 2.2.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 2.2.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '2.
|
34
|
-
type: :
|
33
|
+
version: '2.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.0'
|
62
|
+
type: :development
|
35
63
|
prerelease: false
|
36
64
|
version_requirements: !ruby/object:Gem::Requirement
|
37
65
|
requirements:
|
38
66
|
- - "~>"
|
39
67
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
68
|
+
version: '5.0'
|
41
69
|
description: Library to work with VK API and create simple longpoll bot for group.
|
42
|
-
email:
|
70
|
+
email:
|
71
|
+
- fizvlad@mail.ru
|
43
72
|
executables: []
|
44
73
|
extensions: []
|
45
74
|
extra_rdoc_files: []
|
46
75
|
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".travis.yml"
|
78
|
+
- Gemfile
|
79
|
+
- Gemfile.lock
|
47
80
|
- LICENSE
|
48
81
|
- README.md
|
49
82
|
- Rakefile
|
83
|
+
- bin/console
|
84
|
+
- bin/setup
|
85
|
+
- examples/audio_bot/main.rb
|
86
|
+
- examples/chat_bot/main.rb
|
87
|
+
- examples/command_bot/main.rb
|
50
88
|
- lib/vk_longpoll_bot.rb
|
51
89
|
- lib/vk_longpoll_bot/bot.rb
|
52
90
|
- lib/vk_longpoll_bot/constants.rb
|
@@ -54,11 +92,15 @@ files:
|
|
54
92
|
- lib/vk_longpoll_bot/exceptions.rb
|
55
93
|
- lib/vk_longpoll_bot/request.rb
|
56
94
|
- lib/vk_longpoll_bot/utility.rb
|
95
|
+
- lib/vk_longpoll_bot/version.rb
|
57
96
|
- vk_longpoll_bot.gemspec
|
58
97
|
homepage: https://github.com/fizvlad/vk-longpoll-bot-rb
|
59
98
|
licenses:
|
60
99
|
- MIT
|
61
|
-
metadata:
|
100
|
+
metadata:
|
101
|
+
homepage_uri: https://github.com/fizvlad/vk-longpoll-bot-rb
|
102
|
+
source_code_uri: https://github.com/fizvlad/vk-longpoll-bot-rb
|
103
|
+
changelog_uri: https://github.com/fizvlad/vk-longpoll-bot-rb/releases
|
62
104
|
post_install_message:
|
63
105
|
rdoc_options: []
|
64
106
|
require_paths:
|
@@ -74,8 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
116
|
- !ruby/object:Gem::Version
|
75
117
|
version: '0'
|
76
118
|
requirements: []
|
77
|
-
|
78
|
-
rubygems_version: 2.7.6.2
|
119
|
+
rubygems_version: 3.0.4
|
79
120
|
signing_key:
|
80
121
|
specification_version: 4
|
81
122
|
summary: Provides interface to create simple VK longpoll bot
|