vk_longpoll_bot 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +2 -0
- data/Rakefile +24 -0
- data/lib/vk_longpoll_bot/bot.rb +134 -0
- data/lib/vk_longpoll_bot/constants.rb +12 -0
- data/lib/vk_longpoll_bot/events.rb +72 -0
- data/lib/vk_longpoll_bot/exceptions.rb +84 -0
- data/lib/vk_longpoll_bot/request.rb +34 -0
- data/lib/vk_longpoll_bot/utility.rb +22 -0
- data/lib/vk_longpoll_bot.rb +6 -0
- data/vk_longpoll_bot.gemspec +16 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f28f217393130c2c06d14a05e785bde07781ed164da0032689e15cf02526fae5
|
4
|
+
data.tar.gz: e3c750777c8347751b940fdc27366cb90b30c2de932894c4456cfd2c05e1f81d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4ecb287c910584456bbbba055d7af012dba65fffad2657336766c78560f1165c5184d2d45b892232ab228bfc556935d1815def1b9ba3b90a6c17badbff791aa6
|
7
|
+
data.tar.gz: 143c4c9964f20b9750619820bde70c66c2f8142e48e7396df9443021ef5c90fc10ca648b5c11c7cccf80aa550a7c90d157d9979e224228bc0a14c459278ed330
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019 Fizvlad
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
GEM_NAME = "vk_longpoll_bot"
|
2
|
+
|
3
|
+
desc "Build gem file"
|
4
|
+
task :build do
|
5
|
+
puts `gem build #{GEM_NAME}.gemspec`
|
6
|
+
end
|
7
|
+
|
8
|
+
desc "Uninstall gem"
|
9
|
+
task :uninstall do
|
10
|
+
puts `gem uninstall #{GEM_NAME}`
|
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
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module VkLongpollBot
|
2
|
+
|
3
|
+
# Main class, which contains all the methods of bot.
|
4
|
+
class Bot
|
5
|
+
|
6
|
+
# Every bot stores id of group it operates.
|
7
|
+
attr_reader :id, :event_listeners
|
8
|
+
|
9
|
+
# Initialize bot. This method don't run longpoll.
|
10
|
+
#
|
11
|
+
# <tt>options</tt> hash can contain following keys:
|
12
|
+
# * <tt>:api_version</tt> - version of api to use
|
13
|
+
# * <tt>:longpoll_wait</tt> - longpoll requests timeout
|
14
|
+
def initialize(access_token, id, options = {})
|
15
|
+
@event_listeners = Hash.new { |hash, key| hash[key] = Array.new }
|
16
|
+
@on_start = []
|
17
|
+
@on_finish = []
|
18
|
+
|
19
|
+
@access_token = access_token
|
20
|
+
@id = id
|
21
|
+
|
22
|
+
@api_version = options[:api_version] || VK_API_CURRENT_VERSION
|
23
|
+
@longpoll_wait = options[:longpoll_wait] || LONGPOLL_STANDART_WAIT
|
24
|
+
|
25
|
+
@longpoll = {}
|
26
|
+
|
27
|
+
# TODO
|
28
|
+
end
|
29
|
+
|
30
|
+
# Call for api method with given parameters.
|
31
|
+
def api(method_name, parameters = {})
|
32
|
+
Request.api(method_name, parameters, @access_token, @api_version)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Messaging
|
36
|
+
|
37
|
+
# Send message to <tt>target</tt> with provided <tt>content</tt>.
|
38
|
+
def send_message(target, content)
|
39
|
+
target_id = target.to_i
|
40
|
+
api("messages.send", user_id: target_id, message: content, random_id: Utility.random_id(target_id))
|
41
|
+
end
|
42
|
+
|
43
|
+
# TODO: Which methods are also addable here?
|
44
|
+
|
45
|
+
# Events
|
46
|
+
|
47
|
+
# Add event listener.
|
48
|
+
#
|
49
|
+
# <tt>attributes</tt> hash can contain following keys:
|
50
|
+
# * <tt>:subtype</tt> - event subtype. All of event types and subtypes are stated in Events::TYPES
|
51
|
+
def on(attributes, &block)
|
52
|
+
raise ArgumentError.new("Got subtype #{attributes[:subtype]} of class #{attributes[:subtype].class}") unless String === attributes[:subtype] && Events.valid_subtype?(attributes[:subtype])
|
53
|
+
@event_listeners[attributes[:subtype]] << Events::EventListener.new(attributes, &block)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Add code to be executed right after bot starts.
|
57
|
+
def on_start(&block)
|
58
|
+
@on_start << block
|
59
|
+
end
|
60
|
+
|
61
|
+
# Add code to be executed right after bot finishes.
|
62
|
+
def on_finish(&block)
|
63
|
+
@on_finish << block
|
64
|
+
end
|
65
|
+
|
66
|
+
# Running bot
|
67
|
+
|
68
|
+
# Start bot. This methods freeze current thread until <tt>stop</tt> called.
|
69
|
+
def run
|
70
|
+
@on_start.each(&:call)
|
71
|
+
|
72
|
+
init_longpoll
|
73
|
+
run_longpoll
|
74
|
+
|
75
|
+
@on_finish.each(&:call)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Stop bot.
|
79
|
+
def stop
|
80
|
+
@finish_flag = true
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# Request longpoll data.
|
86
|
+
def init_longpoll
|
87
|
+
lp = api("groups.getLongPollServer", group_id: @id)
|
88
|
+
@longpoll[:server] = lp["server"]
|
89
|
+
@longpoll[:key] = lp["key"]
|
90
|
+
@longpoll[:ts] = lp["ts"]
|
91
|
+
end
|
92
|
+
|
93
|
+
# Start longpoll. Requires <tt>init_longpoll</tt> to be run first.
|
94
|
+
def run_longpoll
|
95
|
+
@finish_flag = false # Setting up flag for loop
|
96
|
+
|
97
|
+
until @finish_flag
|
98
|
+
response = Request.longpoll(@longpoll[:server], @longpoll[:key], @longpoll[:ts], @longpoll_wait) # TODO
|
99
|
+
if response["failed"]
|
100
|
+
# Error happened
|
101
|
+
Utility.warn "Longpoll failed with code #{response["failed"]}. This must be solvable. Keep running..."
|
102
|
+
case response["failed"]
|
103
|
+
when 1
|
104
|
+
# Just update ts
|
105
|
+
@longpoll[:ts] = response["ts"]
|
106
|
+
when 2, 3
|
107
|
+
# Need to reconnect
|
108
|
+
init_longpoll
|
109
|
+
else
|
110
|
+
raise Exceptions::LongpollError("Unknown 'failed' value: #{response["failed"]}. Full response: #{response.to_s}")
|
111
|
+
end
|
112
|
+
elsif response["ts"] && response["updates"]
|
113
|
+
# Everything is fine. Handling update
|
114
|
+
@longpoll[:ts] = response["ts"]
|
115
|
+
updates = response["updates"]
|
116
|
+
response["updates"].each { |update| update_handler(update) }
|
117
|
+
else
|
118
|
+
raise Exceptions::LongpollError("Strange longpoll response: #{response.to_s}")
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Handle update from longpoll.
|
124
|
+
def update_handler(update)
|
125
|
+
event = Events::Event.new(update["type"], update["object"], update["group_id"], self)
|
126
|
+
@event_listeners[event.subtype].each do |listener|
|
127
|
+
# NOTE: If we had any attributes, we would check whether matching here.
|
128
|
+
listener.call(event)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module VkLongpollBot
|
2
|
+
|
3
|
+
# Base of URL to API.
|
4
|
+
VK_API_URL_BASE = "https://api.vk.com"
|
5
|
+
|
6
|
+
# It's recommended to use last version of VK API.
|
7
|
+
VK_API_CURRENT_VERSION = Gem::Version.new("5.101")
|
8
|
+
|
9
|
+
# Longpoll requests timeout.
|
10
|
+
LONGPOLL_STANDART_WAIT = 25
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module VkLongpollBot
|
2
|
+
|
3
|
+
# Everything related to longpoll events.
|
4
|
+
module Events
|
5
|
+
|
6
|
+
# All the types and subtypes of events
|
7
|
+
TYPES = {
|
8
|
+
message: %w{message_new message_reply message_edit message_typing_state message_allow message_deny},
|
9
|
+
photo: %w{photo_new photo_comment_new photo_comment_edit photo_comment_restore photo_comment_delete},
|
10
|
+
audio: %w{audio_new},
|
11
|
+
video: %w{video_new video_comment_new video_comment_restore video_comment_delete},
|
12
|
+
wall: %w{wall_post_new wall_repost wall_reply_new wall_reply_edit wall_reply_restore wall_reply_delete},
|
13
|
+
board: %w{board_post_new board_post_edit board_post_restore board_post_delete},
|
14
|
+
market: %w{market_comment_new market_comment_edit market_comment_restore market_comment_delete},
|
15
|
+
group: %w{group_leave group_join group_officers_edit group_change_settings group_change_photo},
|
16
|
+
user: %w{user_block user_unblock},
|
17
|
+
poll: %w{poll_vote_new},
|
18
|
+
vkpay: %w{vkpay_transaction},
|
19
|
+
app: %w{app_payload}
|
20
|
+
}
|
21
|
+
|
22
|
+
def self.valid_subtype?(subtype)
|
23
|
+
TYPES.values.any? { |arr| arr.include?(subtype) }
|
24
|
+
end
|
25
|
+
|
26
|
+
# Class containing data recieved from longpoll. Provides easy update to it's data.
|
27
|
+
class Event
|
28
|
+
|
29
|
+
attr_reader :subtype, :group_id, :data, :bot
|
30
|
+
|
31
|
+
# Initialize from fields of update json and bot which got this event.
|
32
|
+
def initialize(subtype, data, group_id, bot)
|
33
|
+
@subtype = subtype.to_s
|
34
|
+
@data = data
|
35
|
+
@group_id = group_id.to_i
|
36
|
+
@bot = bot
|
37
|
+
end
|
38
|
+
|
39
|
+
# Provides access to fields of update data.
|
40
|
+
def [](arg)
|
41
|
+
@data[arg.to_s]
|
42
|
+
end
|
43
|
+
|
44
|
+
# TODO
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
# 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
|
+
|
50
|
+
# Class containing block to run on some event.
|
51
|
+
class EventListener
|
52
|
+
|
53
|
+
attr_reader :subtype
|
54
|
+
|
55
|
+
def initialize(attributes, &block)
|
56
|
+
@subtype = attributes[:subtype]
|
57
|
+
@block = block
|
58
|
+
|
59
|
+
# TODO
|
60
|
+
end
|
61
|
+
|
62
|
+
def call(event)
|
63
|
+
@block.call(event)
|
64
|
+
end
|
65
|
+
|
66
|
+
# TODO
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module VkLongpollBot
|
2
|
+
|
3
|
+
# Custom exceptions.
|
4
|
+
module Exceptions
|
5
|
+
|
6
|
+
# All of the error codes descriptions. Source: https://vk.com/dev/errors
|
7
|
+
CODES = {
|
8
|
+
1 => "Произошла неизвестная ошибка.",
|
9
|
+
2 => "Приложение выключено.",
|
10
|
+
3 => "Передан неизвестный метод.",
|
11
|
+
4 => "Неверная подпись.",
|
12
|
+
5 => "Авторизация пользователя не удалась.",
|
13
|
+
6 => "Слишком много запросов в секунду.",
|
14
|
+
7 => "Нет прав для выполнения этого действия.",
|
15
|
+
8 => "Неверный запрос.",
|
16
|
+
9 => "Слишком много однотипных действий.",
|
17
|
+
10 => "Произошла внутренняя ошибка сервера.",
|
18
|
+
11 => "В тестовом режиме приложение должно быть выключено или пользователь должен быть залогинен.",
|
19
|
+
14 => "Требуется ввод кода с картинки (Captcha).",
|
20
|
+
15 => "Доступ запрещён.",
|
21
|
+
16 => "Требуется выполнение запросов по протоколу HTTPS, т.к. пользователь включил настройку, требующую работу через безопасное соединение.",
|
22
|
+
17 => "Требуется валидация пользователя.",
|
23
|
+
18 => "Страница удалена или заблокирована.",
|
24
|
+
20 => "Данное действие запрещено для не Standalone приложений.",
|
25
|
+
21 => "Данное действие разрешено только для Standalone и Open API приложений.",
|
26
|
+
23 => "Метод был выключен.",
|
27
|
+
24 => "Требуется подтверждение со стороны пользователя.",
|
28
|
+
27 => "Ключ доступа сообщества недействителен.",
|
29
|
+
28 => "Ключ доступа приложения недействителен.",
|
30
|
+
29 => "Достигнут количественный лимит на вызов метода.",
|
31
|
+
30 => "Профиль является приватным.",
|
32
|
+
33 => "Метод ещё не реализован.",
|
33
|
+
100 => "Один из необходимых параметров был не передан или неверен.",
|
34
|
+
101 => "Неверный API ID приложения.",
|
35
|
+
113 => "Неверный идентификатор пользователя.",
|
36
|
+
150 => "Неверный timestamp.",
|
37
|
+
200 => "Доступ к альбому запрещён.",
|
38
|
+
201 => "Доступ к аудио запрещён.",
|
39
|
+
203 => "Доступ к группе запрещён.",
|
40
|
+
300 => "Альбом переполнен.",
|
41
|
+
500 => "Действие запрещено. Вы должны включить переводы голосов в настройках приложения. ",
|
42
|
+
600 => "Нет прав на выполнение данных операций с рекламным кабинетом.",
|
43
|
+
603 => "Произошла ошибка при работе с рекламным кабинетом.",
|
44
|
+
900 => "Нельзя отправлять сообщение пользователю из черного списка.",
|
45
|
+
901 => "Пользователь запретил отправку сообщений от имени сообщества.",
|
46
|
+
902 => "Нельзя отправлять сообщения этому пользователю в связи с настройками приватности.",
|
47
|
+
911 => "Формат клавиатуры некорректен.",
|
48
|
+
912 => "Это функция чат-бота, измените данный статус в настройках.",
|
49
|
+
913 => "Слишком много пересланных сообщений.",
|
50
|
+
914 => "Сообщение слишком длинное.",
|
51
|
+
917 => "У вас нет доступа к этому чату.",
|
52
|
+
921 => "Невозможно переслать выбранные сообщения.",
|
53
|
+
936 => "Контакт не найден.",
|
54
|
+
940 => "Слишком много постов в сообщении."
|
55
|
+
}
|
56
|
+
|
57
|
+
# Something wrong with response from vk.com.
|
58
|
+
class ResponseError < RuntimeError
|
59
|
+
end
|
60
|
+
|
61
|
+
# API error. Must have some code and description.
|
62
|
+
class APIError < ResponseError
|
63
|
+
|
64
|
+
attr_reader :code, :error
|
65
|
+
|
66
|
+
def initialize(error)
|
67
|
+
@error = error["error"]
|
68
|
+
@code = @error["error_code"]
|
69
|
+
super(@error["error_msg"])
|
70
|
+
end
|
71
|
+
|
72
|
+
def description
|
73
|
+
CODES[@code]
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
# Something wrong in longpoll response.
|
79
|
+
class LongpollError < ResponseError
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module VkLongpollBot
|
5
|
+
|
6
|
+
# Some functions to send HTTP requests
|
7
|
+
module Request
|
8
|
+
|
9
|
+
# Regular HTTP request to given URI.
|
10
|
+
def self.to(url)
|
11
|
+
uri = URI(url.to_s)
|
12
|
+
Net::HTTP.get(uri)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Request to api.
|
16
|
+
def self.api(method_name, parameters, access_token, v = VK_API_CURRENT_VERSION)
|
17
|
+
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
|
+
if response["response"]
|
19
|
+
response["response"]
|
20
|
+
elsif response["error"]
|
21
|
+
raise Exceptions::APIError.new(response)
|
22
|
+
else
|
23
|
+
raise Exceptions::ResponseError.new(response)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Request to longpoll server.
|
28
|
+
def self.longpoll(server, key, ts, wait = LONGPOLL_STANDART_WAIT)
|
29
|
+
JSON.parse self.to("#{server}?act=a_check&key=#{key}&ts=#{ts}&wait=#{wait}")
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module VkLongpollBot
|
2
|
+
|
3
|
+
# Module with some utility methods.
|
4
|
+
module Utility
|
5
|
+
|
6
|
+
# Log warning.
|
7
|
+
def self.warn(msg)
|
8
|
+
if defined?(Warning.warn)
|
9
|
+
Warning.warn msg
|
10
|
+
else
|
11
|
+
STDERR.puts "Warning: #{msg}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Generate <tt>random_id</tt> for message.
|
16
|
+
def self.random_id(target_id)
|
17
|
+
(rand(100) * target_id) % 2**32
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require_relative "vk_longpoll_bot/utility.rb"
|
2
|
+
require_relative "vk_longpoll_bot/constants.rb"
|
3
|
+
require_relative "vk_longpoll_bot/exceptions.rb"
|
4
|
+
require_relative "vk_longpoll_bot/request.rb"
|
5
|
+
require_relative "vk_longpoll_bot/bot.rb"
|
6
|
+
require_relative "vk_longpoll_bot/events.rb"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "vk_longpoll_bot"
|
3
|
+
s.summary = "Provides interface to create simple VK longpoll bot"
|
4
|
+
s.description = "Library to work with VK API and create simple longpoll bot for group."
|
5
|
+
s.version = "0.0.1"
|
6
|
+
s.author = "Kuznetsov Vladislav"
|
7
|
+
s.email = "fizvlad@mail.ru"
|
8
|
+
s.homepage = "https://github.com/fizvlad/vk-longpoll-bot-rb"
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.required_ruby_version = ">=2.3.1"
|
11
|
+
s.files = Dir[ "lib/**/**", "example/**/**", "LICENSE", "Rakefile", "README.md", "vk_longpoll_bot.gemspec" ]
|
12
|
+
s.license = "MIT"
|
13
|
+
|
14
|
+
s.add_runtime_dependency "rake", "~>12.3"
|
15
|
+
s.add_runtime_dependency "json", "~>2.2"
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vk_longpoll_bot
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kuznetsov Vladislav
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-07-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '12.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '12.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.2'
|
41
|
+
description: Library to work with VK API and create simple longpoll bot for group.
|
42
|
+
email: fizvlad@mail.ru
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- LICENSE
|
48
|
+
- README.md
|
49
|
+
- Rakefile
|
50
|
+
- lib/vk_longpoll_bot.rb
|
51
|
+
- lib/vk_longpoll_bot/bot.rb
|
52
|
+
- lib/vk_longpoll_bot/constants.rb
|
53
|
+
- lib/vk_longpoll_bot/events.rb
|
54
|
+
- lib/vk_longpoll_bot/exceptions.rb
|
55
|
+
- lib/vk_longpoll_bot/request.rb
|
56
|
+
- lib/vk_longpoll_bot/utility.rb
|
57
|
+
- vk_longpoll_bot.gemspec
|
58
|
+
homepage: https://github.com/fizvlad/vk-longpoll-bot-rb
|
59
|
+
licenses:
|
60
|
+
- MIT
|
61
|
+
metadata: {}
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 2.3.1
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 2.7.6.2
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: Provides interface to create simple VK longpoll bot
|
82
|
+
test_files: []
|