vk_longpoll_bot 0.0.1
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.
- 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: []
|