gruubY 0.2.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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +6 -0
- data/Rakefile +51 -0
- data/config/config.rb +5 -0
- data/example/bot.rb +160 -0
- data/example/generate_user_session.rb +81 -0
- data/example/ntgcalls.rb +80 -0
- data/example/tdlib.rb +77 -0
- data/example/userbot.rb +133 -0
- data/lib/grubY/api.rb +363 -0
- data/lib/grubY/async.rb +13 -0
- data/lib/grubY/bot.rb +90 -0
- data/lib/grubY/bound.rb +14 -0
- data/lib/grubY/client.rb +296 -0
- data/lib/grubY/context.rb +242 -0
- data/lib/grubY/dispatcher.rb +60 -0
- data/lib/grubY/enums.rb +62 -0
- data/lib/grubY/exception.rb +5 -0
- data/lib/grubY/file_stream.rb +17 -0
- data/lib/grubY/filters.rb +292 -0
- data/lib/grubY/group_manager.rb +213 -0
- data/lib/grubY/handlers.rb +170 -0
- data/lib/grubY/keyboard.rb +49 -0
- data/lib/grubY/media.rb +38 -0
- data/lib/grubY/middleware.rb +18 -0
- data/lib/grubY/ntgcalls/native.rb +100 -0
- data/lib/grubY/ntgcalls.rb +478 -0
- data/lib/grubY/plugin.rb +14 -0
- data/lib/grubY/raw.rb +25 -0
- data/lib/grubY/raw_types.rb +57 -0
- data/lib/grubY/retry.rb +14 -0
- data/lib/grubY/server.rb +18 -0
- data/lib/grubY/session.rb +30 -0
- data/lib/grubY/tdlib/client.rb +565 -0
- data/lib/grubY/tdlib/client_manager.rb +37 -0
- data/lib/grubY/tdlib/decorators.rb +17 -0
- data/lib/grubY/tdlib/errors.rb +6 -0
- data/lib/grubY/tdlib/group_manager.rb +58 -0
- data/lib/grubY/tdlib/native.rb +72 -0
- data/lib/grubY/tdlib/schema_builder.rb +237 -0
- data/lib/grubY/tdlib/tdjson.rb +49 -0
- data/lib/grubY/tdlib/user_session.rb +69 -0
- data/lib/grubY/types/base_object.rb +72 -0
- data/lib/grubY/types/bound_entities.rb +245 -0
- data/lib/grubY/types/chat.rb +93 -0
- data/lib/grubY/types/chat_info.rb +31 -0
- data/lib/grubY/types/extra.rb +251 -0
- data/lib/grubY/types/message.rb +295 -0
- data/lib/grubY/types/message_entity.rb +14 -0
- data/lib/grubY/types/registry.rb +67 -0
- data/lib/grubY/types/user.rb +31 -0
- data/lib/grubY/webapp.rb +22 -0
- data/lib/grubY.rb +41 -0
- data/plugins/logger.rb +7 -0
- data/plugins/media_tools.rb +13 -0
- metadata +110 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
require "set"
|
|
2
|
+
|
|
3
|
+
module GrubY
|
|
4
|
+
module Filters
|
|
5
|
+
class Filter
|
|
6
|
+
attr_reader :name
|
|
7
|
+
|
|
8
|
+
def initialize(name = "Filter", &block)
|
|
9
|
+
@name = name
|
|
10
|
+
@block = block || proc { true }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def call(*args)
|
|
14
|
+
@block.call(*args)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def &(other)
|
|
18
|
+
Filter.new("(#{name}&#{other.name})") { |*args| call(*args) && other.call(*args) }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def |(other)
|
|
22
|
+
Filter.new("(#{name}|#{other.name})") { |*args| call(*args) || other.call(*args) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ~@
|
|
26
|
+
Filter.new("~#{name}") { |*args| !call(*args) }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class EntityFilter < Filter
|
|
31
|
+
attr_reader :values
|
|
32
|
+
|
|
33
|
+
def initialize(name, values = nil, &matcher)
|
|
34
|
+
@values = normalize(values)
|
|
35
|
+
@matcher = matcher
|
|
36
|
+
super(name) do |_filter, _client, update|
|
|
37
|
+
@matcher.call(update, @values)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def add(value)
|
|
42
|
+
@values.merge(normalize(value))
|
|
43
|
+
self
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def delete(value)
|
|
47
|
+
normalize(value).each { |v| @values.delete(v) }
|
|
48
|
+
self
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def clear
|
|
52
|
+
@values.clear
|
|
53
|
+
self
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def normalize(v)
|
|
59
|
+
Array(v).flatten.compact.map(&:to_s).to_set
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
module_function
|
|
64
|
+
|
|
65
|
+
def create(func:, name: "CustomFilter", **kwargs)
|
|
66
|
+
Filter.new(name) do |filter, client, update|
|
|
67
|
+
func.call(filter, client, update, **kwargs)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def all
|
|
72
|
+
Filter.new("all") { true }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def me
|
|
76
|
+
Filter.new("me") do |_f, _c, u|
|
|
77
|
+
msg = message_from(u)
|
|
78
|
+
msg&.from&.is_bot == false && (msg&.from&.is_self == true || %w[me self].include?(msg&.from&.username.to_s.downcase))
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def bot
|
|
83
|
+
Filter.new("bot") { |_f, _c, u| message_from(u)&.from&.is_bot == true }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def sender_chat
|
|
87
|
+
Filter.new("sender_chat") { |_f, _c, u| !message_from(u)&.sender_chat.nil? }
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def incoming
|
|
91
|
+
Filter.new("incoming") { |_f, _c, u| message_from(u)&.from&.is_bot != true }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def outgoing
|
|
95
|
+
Filter.new("outgoing") do |_f, _c, u|
|
|
96
|
+
msg = message_from(u)
|
|
97
|
+
msg && msg.from && (msg.from.is_self == true || msg.from.id == msg.chat&.id)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def text = has_key_filter("text")
|
|
102
|
+
def reply = Filter.new("reply") { |_f, _c, u| !!(message_from(u)&.reply_to_message || message_from(u)&.reply_to_story) }
|
|
103
|
+
def forwarded = Filter.new("forwarded") { |_f, _c, u| !!message_from(u)&.forward_origin }
|
|
104
|
+
def caption = has_key_filter("caption")
|
|
105
|
+
def self_destruction = has_key_filter("self_destruction")
|
|
106
|
+
def audio = has_key_filter("audio")
|
|
107
|
+
def document = has_key_filter("document")
|
|
108
|
+
def photo = has_key_filter("photo")
|
|
109
|
+
def sticker = has_key_filter("sticker")
|
|
110
|
+
def animation = has_key_filter("animation")
|
|
111
|
+
def game = has_key_filter("game")
|
|
112
|
+
def giveaway = has_key_filter("giveaway")
|
|
113
|
+
def giveaway_winners = has_key_filter("giveaway_winners")
|
|
114
|
+
def gift_code = has_key_filter("gift_code")
|
|
115
|
+
def gift = has_key_filter("gift")
|
|
116
|
+
def users_shared = has_key_filter("users_shared")
|
|
117
|
+
def chat_shared = has_key_filter("chat_shared")
|
|
118
|
+
def video = has_key_filter("video")
|
|
119
|
+
def media_group = has_key_filter("media_group_id")
|
|
120
|
+
def voice = has_key_filter("voice")
|
|
121
|
+
def video_note = has_key_filter("video_note")
|
|
122
|
+
def contact = has_key_filter("contact")
|
|
123
|
+
def location = has_key_filter("location")
|
|
124
|
+
def live_location = Filter.new("live_location") { |_f, _c, u| !!message_from(u)&.location&.dig("live_period") }
|
|
125
|
+
def venue = has_key_filter("venue")
|
|
126
|
+
def web_page = Filter.new("web_page") { |_f, _c, u| !!message_from(u)&.link_preview_options }
|
|
127
|
+
def poll = has_key_filter("poll")
|
|
128
|
+
def dice = has_key_filter("dice")
|
|
129
|
+
def quote = has_key_filter("quote")
|
|
130
|
+
def media_spoiler = has_key_filter("has_media_spoiler")
|
|
131
|
+
def story = has_key_filter("story")
|
|
132
|
+
def new_chat_members = has_key_filter("new_chat_members")
|
|
133
|
+
def left_chat_member = has_key_filter("left_chat_member")
|
|
134
|
+
def new_chat_title = has_key_filter("new_chat_title")
|
|
135
|
+
def new_chat_photo = has_key_filter("new_chat_photo")
|
|
136
|
+
def delete_chat_photo = has_key_filter("delete_chat_photo")
|
|
137
|
+
def group_chat_created = has_key_filter("group_chat_created")
|
|
138
|
+
def supergroup_chat_created = has_key_filter("supergroup_chat_created")
|
|
139
|
+
def channel_chat_created = has_key_filter("channel_chat_created")
|
|
140
|
+
def migrate_to_chat_id = has_key_filter("migrate_to_chat_id")
|
|
141
|
+
def migrate_from_chat_id = has_key_filter("migrate_from_chat_id")
|
|
142
|
+
def pinned_message = has_key_filter("pinned_message")
|
|
143
|
+
def game_high_score = has_key_filter("game_high_score")
|
|
144
|
+
def reply_keyboard = has_key_filter("reply_markup")
|
|
145
|
+
def inline_keyboard = has_key_filter("reply_markup")
|
|
146
|
+
def mentioned = Filter.new("mentioned") { |_f, _c, u| message_from(u)&.entities&.any? { |e| e["type"] == "mention" } }
|
|
147
|
+
def via_bot = has_key_filter("via_bot")
|
|
148
|
+
def admin = Filter.new("admin") { |_f, _c, u| %w[administrator creator].include?(message_from(u)&.chat_member_status.to_s) }
|
|
149
|
+
def video_chat_started = has_key_filter("video_chat_started")
|
|
150
|
+
def video_chat_ended = has_key_filter("video_chat_ended")
|
|
151
|
+
def business = has_key_filter("business_connection_id")
|
|
152
|
+
def video_chat_members_invited = has_key_filter("video_chat_members_invited")
|
|
153
|
+
def successful_payment = has_key_filter("successful_payment")
|
|
154
|
+
def scheduled = has_key_filter("is_scheduled")
|
|
155
|
+
def from_scheduled = has_key_filter("from_scheduled")
|
|
156
|
+
def paid_message = has_key_filter("is_paid_post")
|
|
157
|
+
def linked_channel = has_key_filter("is_automatic_forward")
|
|
158
|
+
def gift_offer = has_key_filter("gift_offer")
|
|
159
|
+
def gift_offer_accepted = has_key_filter("gift_offer_accepted")
|
|
160
|
+
def gift_offer_rejected = has_key_filter("gift_offer_rejected")
|
|
161
|
+
|
|
162
|
+
def service
|
|
163
|
+
Filter.new("service") do |_f, _c, u|
|
|
164
|
+
msg = message_from(u)
|
|
165
|
+
next false unless msg
|
|
166
|
+
|
|
167
|
+
%w[left_chat_member new_chat_title new_chat_photo delete_chat_photo group_chat_created
|
|
168
|
+
supergroup_chat_created channel_chat_created migrate_to_chat_id migrate_from_chat_id
|
|
169
|
+
pinned_message video_chat_started video_chat_ended video_chat_members_invited successful_payment].any? do |k|
|
|
170
|
+
present_key?(msg, k)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def media
|
|
176
|
+
Filter.new("media") do |_f, _c, u|
|
|
177
|
+
msg = message_from(u)
|
|
178
|
+
next false unless msg
|
|
179
|
+
|
|
180
|
+
%w[audio document photo sticker video animation voice video_note contact location venue poll].any? { |k| present_key?(msg, k) }
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def private
|
|
185
|
+
Filter.new("private") { |_f, _c, u| message_from(u)&.chat&.type == "private" }
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def group
|
|
189
|
+
Filter.new("group") { |_f, _c, u| %w[group supergroup].include?(message_from(u)&.chat&.type) }
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def channel
|
|
193
|
+
Filter.new("channel") { |_f, _c, u| message_from(u)&.chat&.type == "channel" }
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def direct
|
|
197
|
+
Filter.new("direct") { |_f, _c, u| message_from(u)&.chat&.is_direct_messages == true }
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def forum
|
|
201
|
+
Filter.new("forum") { |_f, _c, u| message_from(u)&.chat&.is_forum == true }
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def command(commands, prefixes: "/", case_sensitive: false)
|
|
205
|
+
list = Array(commands).map(&:to_s)
|
|
206
|
+
prefix_list = prefixes.nil? ? [""] : Array(prefixes).map(&:to_s)
|
|
207
|
+
Filter.new("command") do |_f, _c, u|
|
|
208
|
+
msg = message_from(u)
|
|
209
|
+
text = msg&.text.to_s
|
|
210
|
+
next false if text.empty?
|
|
211
|
+
next false unless prefix_list.any? { |p| p.empty? || text.start_with?(p) }
|
|
212
|
+
|
|
213
|
+
cmd = text.split(/\s+/, 2).first.to_s
|
|
214
|
+
cmd = cmd.sub(/\A[#{Regexp.escape(prefix_list.join)}]/, "") unless prefix_list.include?("")
|
|
215
|
+
cmd = cmd.split("@", 2).first
|
|
216
|
+
cmd = cmd.downcase unless case_sensitive
|
|
217
|
+
expected = case_sensitive ? list : list.map(&:downcase)
|
|
218
|
+
expected.include?(cmd)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def regex(pattern, flags: 0)
|
|
223
|
+
reg = pattern.is_a?(Regexp) ? pattern : Regexp.new(pattern.to_s, flags)
|
|
224
|
+
Filter.new("regex") do |_f, _c, u|
|
|
225
|
+
target = if u.respond_to?(:data) && !u.data.to_s.empty?
|
|
226
|
+
u.data.to_s
|
|
227
|
+
elsif u.respond_to?(:query)
|
|
228
|
+
u.query.to_s
|
|
229
|
+
else
|
|
230
|
+
msg = message_from(u)
|
|
231
|
+
msg&.text.to_s.empty? ? msg&.caption.to_s : msg&.text.to_s
|
|
232
|
+
end
|
|
233
|
+
!!(target =~ reg)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def user(users = nil)
|
|
238
|
+
require "set"
|
|
239
|
+
EntityFilter.new("user", users) do |u, values|
|
|
240
|
+
msg = message_from(u)
|
|
241
|
+
uid = msg&.from&.id || u&.from&.id
|
|
242
|
+
uname = msg&.from&.username || u&.from&.username
|
|
243
|
+
values.empty? || values.include?(uid.to_s) || values.include?(uname.to_s) || values.include?("me")
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def chat(chats = nil)
|
|
248
|
+
require "set"
|
|
249
|
+
EntityFilter.new("chat", chats) do |u, values|
|
|
250
|
+
msg = message_from(u)
|
|
251
|
+
cid = msg&.chat&.id || u&.chat&.id
|
|
252
|
+
uname = msg&.chat&.username || u&.chat&.username
|
|
253
|
+
values.empty? || values.include?(cid.to_s) || values.include?(uname.to_s) || values.include?("me")
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def topic(topics = nil)
|
|
258
|
+
require "set"
|
|
259
|
+
EntityFilter.new("topic", topics) do |u, values|
|
|
260
|
+
msg = message_from(u)
|
|
261
|
+
tid = msg&.message_thread_id || msg&.direct_messages_topic&.dig("topic_id")
|
|
262
|
+
values.empty? || values.include?(tid.to_s)
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
private_class_method
|
|
267
|
+
|
|
268
|
+
def has_key_filter(key)
|
|
269
|
+
Filter.new(key) { |_f, _c, u| present_key?(message_from(u), key) }
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def present_key?(obj, key)
|
|
273
|
+
return false unless obj
|
|
274
|
+
value = if obj.respond_to?(:[])
|
|
275
|
+
obj[key]
|
|
276
|
+
elsif obj.respond_to?(key)
|
|
277
|
+
obj.public_send(key)
|
|
278
|
+
end
|
|
279
|
+
!(value.nil? || (value.respond_to?(:empty?) && value.empty?))
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def message_from(update)
|
|
283
|
+
return update if update.is_a?(GrubY::Message)
|
|
284
|
+
return update.message if update.respond_to?(:message)
|
|
285
|
+
return update.edited_message if update.respond_to?(:edited_message)
|
|
286
|
+
return update.business_message if update.respond_to?(:business_message)
|
|
287
|
+
return update.edited_business_message if update.respond_to?(:edited_business_message)
|
|
288
|
+
|
|
289
|
+
nil
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
module GrubY
|
|
2
|
+
class GroupManager
|
|
3
|
+
DEFAULT_WARN_LIMIT = 3
|
|
4
|
+
|
|
5
|
+
def initialize(api, session: nil, warn_limit: DEFAULT_WARN_LIMIT)
|
|
6
|
+
@api = api
|
|
7
|
+
@session = session
|
|
8
|
+
@warn_limit = warn_limit
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def ban(chat_id, user_id, **opts)
|
|
12
|
+
@api.ban_chat_member(chat_id: chat_id, user_id: user_id, **opts)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def unban(chat_id, user_id, **opts)
|
|
16
|
+
@api.unban_chat_member(chat_id: chat_id, user_id: user_id, **opts)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def kick(chat_id, user_id, **opts)
|
|
20
|
+
ban(chat_id, user_id, **opts)
|
|
21
|
+
unban(chat_id, user_id)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def restrict(chat_id, user_id, permissions:, **opts)
|
|
25
|
+
@api.restrict_chat_member(
|
|
26
|
+
chat_id: chat_id,
|
|
27
|
+
user_id: user_id,
|
|
28
|
+
permissions: permissions,
|
|
29
|
+
**opts
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def mute(chat_id, user_id, until_date: nil)
|
|
34
|
+
restrict(
|
|
35
|
+
chat_id,
|
|
36
|
+
user_id,
|
|
37
|
+
permissions: { can_send_messages: false },
|
|
38
|
+
until_date: until_date
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def unmute(chat_id, user_id)
|
|
43
|
+
permissions = {
|
|
44
|
+
can_send_messages: true,
|
|
45
|
+
can_send_audios: true,
|
|
46
|
+
can_send_documents: true,
|
|
47
|
+
can_send_photos: true,
|
|
48
|
+
can_send_videos: true,
|
|
49
|
+
can_send_video_notes: true,
|
|
50
|
+
can_send_voice_notes: true,
|
|
51
|
+
can_send_polls: true,
|
|
52
|
+
can_send_other_messages: true,
|
|
53
|
+
can_add_web_page_previews: true
|
|
54
|
+
}
|
|
55
|
+
restrict(chat_id, user_id, permissions: permissions)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def promote(chat_id, user_id, **opts)
|
|
59
|
+
@api.promote_chat_member(chat_id: chat_id, user_id: user_id, **opts)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def demote(chat_id, user_id)
|
|
63
|
+
promote(
|
|
64
|
+
chat_id,
|
|
65
|
+
user_id,
|
|
66
|
+
can_manage_chat: false,
|
|
67
|
+
can_delete_messages: false,
|
|
68
|
+
can_manage_video_chats: false,
|
|
69
|
+
can_restrict_members: false,
|
|
70
|
+
can_promote_members: false,
|
|
71
|
+
can_change_info: false,
|
|
72
|
+
can_invite_users: false,
|
|
73
|
+
can_post_stories: false,
|
|
74
|
+
can_edit_stories: false,
|
|
75
|
+
can_delete_stories: false,
|
|
76
|
+
can_post_messages: false,
|
|
77
|
+
can_edit_messages: false,
|
|
78
|
+
can_pin_messages: false,
|
|
79
|
+
can_manage_topics: false
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def set_member_tag(chat_id, user_id, tag = nil)
|
|
84
|
+
@api.set_chat_member_tag(chat_id: chat_id, user_id: user_id, tag: tag)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def set_admin_title(chat_id, user_id, title)
|
|
88
|
+
@api.set_chat_administrator_custom_title(
|
|
89
|
+
chat_id: chat_id,
|
|
90
|
+
user_id: user_id,
|
|
91
|
+
custom_title: title
|
|
92
|
+
)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def set_administrator_title(chat_id, user_id, title)
|
|
96
|
+
set_admin_title(chat_id, user_id, title)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def set_chat_title(chat_id, title)
|
|
100
|
+
@api.set_chat_title(chat_id: chat_id, title: title)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def set_chat_description(chat_id, description)
|
|
104
|
+
@api.set_chat_description(chat_id: chat_id, description: description)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def set_chat_photo(chat_id, photo)
|
|
108
|
+
@api.set_chat_photo(chat_id: chat_id, photo: photo)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def delete_chat_photo(chat_id)
|
|
112
|
+
@api.delete_chat_photo(chat_id: chat_id)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def leave_chat(chat_id)
|
|
116
|
+
@api.leave_chat(chat_id: chat_id)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def set_permissions(chat_id, permissions, **opts)
|
|
120
|
+
@api.set_chat_permissions(chat_id: chat_id, permissions: permissions, **opts)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def lock(chat_id)
|
|
124
|
+
set_permissions(chat_id, { can_send_messages: false })
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def unlock(chat_id)
|
|
128
|
+
set_permissions(chat_id, { can_send_messages: true })
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def set_slow_mode(chat_id, seconds)
|
|
132
|
+
@api.set_slow_mode(chat_id: chat_id, seconds: seconds)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def pin(chat_id, message_id, **opts)
|
|
136
|
+
@api.pin_chat_message(chat_id: chat_id, message_id: message_id, **opts)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def unpin(chat_id, message_id = nil, **opts)
|
|
140
|
+
params = { chat_id: chat_id }.merge(opts)
|
|
141
|
+
params[:message_id] = message_id if message_id
|
|
142
|
+
@api.unpin_chat_message(**params)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def unpin_all(chat_id)
|
|
146
|
+
@api.unpin_all_chat_messages(chat_id: chat_id)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def approve_join_request(chat_id, user_id)
|
|
150
|
+
@api.approve_chat_join_request(chat_id: chat_id, user_id: user_id)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def decline_join_request(chat_id, user_id)
|
|
154
|
+
@api.decline_chat_join_request(chat_id: chat_id, user_id: user_id)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def get_chat(chat_id)
|
|
158
|
+
@api.get_chat(chat_id: chat_id)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def get_member(chat_id, user_id)
|
|
162
|
+
@api.get_chat_member(chat_id: chat_id, user_id: user_id)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def warn(chat_id, user_id, reason: nil)
|
|
166
|
+
key = warn_key(chat_id, user_id)
|
|
167
|
+
current = load_warns(key)
|
|
168
|
+
current += 1
|
|
169
|
+
store_warns(key, current)
|
|
170
|
+
|
|
171
|
+
{
|
|
172
|
+
user_id: user_id,
|
|
173
|
+
warns: current,
|
|
174
|
+
limit: @warn_limit,
|
|
175
|
+
reason: reason,
|
|
176
|
+
action: (current >= @warn_limit ? :kick : :none)
|
|
177
|
+
}
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def reset_warns(chat_id, user_id)
|
|
181
|
+
key = warn_key(chat_id, user_id)
|
|
182
|
+
store_warns(key, 0)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def enforce_warns(chat_id, user_id, reason: nil)
|
|
186
|
+
result = warn(chat_id, user_id, reason: reason)
|
|
187
|
+
return result unless result[:action] == :kick
|
|
188
|
+
|
|
189
|
+
kick(chat_id, user_id)
|
|
190
|
+
reset_warns(chat_id, user_id)
|
|
191
|
+
result
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
private
|
|
195
|
+
|
|
196
|
+
def warn_key(chat_id, user_id)
|
|
197
|
+
"warns:#{chat_id}:#{user_id}"
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def load_warns(key)
|
|
201
|
+
return 0 unless @session
|
|
202
|
+
|
|
203
|
+
value = @session.get(key)
|
|
204
|
+
value.is_a?(Hash) ? value["count"].to_i : value.to_i
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def store_warns(key, count)
|
|
208
|
+
return unless @session
|
|
209
|
+
|
|
210
|
+
@session.set(key, { "count" => count })
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
module GrubY
|
|
2
|
+
module Handlers
|
|
3
|
+
class BaseHandler
|
|
4
|
+
attr_reader :callback, :filters, :group, :exceptions
|
|
5
|
+
|
|
6
|
+
def initialize(callback = nil, filters: nil, group: 0, exceptions: nil, &block)
|
|
7
|
+
@callback = callback || block
|
|
8
|
+
@filters = filters
|
|
9
|
+
@group = group.to_i
|
|
10
|
+
@exceptions = exceptions
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def event
|
|
14
|
+
raise NotImplementedError
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def extract(ctx)
|
|
18
|
+
ctx
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def client_only?
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class MessageHandler < BaseHandler
|
|
27
|
+
def event = :message
|
|
28
|
+
def extract(ctx) = ctx.message
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
class EditedMessageHandler < BaseHandler
|
|
32
|
+
def event = :edited_message
|
|
33
|
+
def extract(ctx) = ctx.edited_message
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class DeletedMessagesHandler < BaseHandler
|
|
37
|
+
def event = :deleted_messages
|
|
38
|
+
def extract(ctx) = ctx.deleted_messages
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class BusinessMessageHandler < BaseHandler
|
|
42
|
+
def event = :business_message
|
|
43
|
+
def extract(ctx) = ctx.business_message
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class EditedBusinessMessageHandler < BaseHandler
|
|
47
|
+
def event = :edited_business_message
|
|
48
|
+
def extract(ctx) = ctx.edited_business_message
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class DeletedBusinessMessagesHandler < BaseHandler
|
|
52
|
+
def event = :deleted_business_messages
|
|
53
|
+
def extract(ctx) = ctx.deleted_business_messages
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class BusinessConnectionHandler < BaseHandler
|
|
57
|
+
def event = :business_connection
|
|
58
|
+
def extract(ctx) = ctx.business_connection
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class CallbackQueryHandler < BaseHandler
|
|
62
|
+
def event = :callback_query
|
|
63
|
+
def extract(ctx) = ctx.callback_query
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class ChatBoostHandler < BaseHandler
|
|
67
|
+
def event = :chat_boost
|
|
68
|
+
def extract(ctx) = ctx.chat_boost
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class ChatJoinRequestHandler < BaseHandler
|
|
72
|
+
def event = :chat_join_request
|
|
73
|
+
def extract(ctx) = ctx.chat_join_request
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class ChatMemberUpdatedHandler < BaseHandler
|
|
77
|
+
def event = :chat_member_updated
|
|
78
|
+
def extract(ctx) = ctx.chat_member_updated
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
class ChosenInlineResultHandler < BaseHandler
|
|
82
|
+
def event = :chosen_inline_result
|
|
83
|
+
def extract(ctx) = ctx.chosen_inline_result
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class InlineQueryHandler < BaseHandler
|
|
87
|
+
def event = :inline_query
|
|
88
|
+
def extract(ctx) = ctx.inline_query
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
class MessageReactionCountHandler < BaseHandler
|
|
92
|
+
def event = :message_reaction_count
|
|
93
|
+
def extract(ctx) = ctx.message_reaction_count
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
class MessageReactionHandler < BaseHandler
|
|
97
|
+
def event = :message_reaction
|
|
98
|
+
def extract(ctx) = ctx.message_reaction
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
class PollHandler < BaseHandler
|
|
102
|
+
def event = :poll
|
|
103
|
+
def extract(ctx) = ctx.poll_update
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
class PreCheckoutQueryHandler < BaseHandler
|
|
107
|
+
def event = :pre_checkout_query
|
|
108
|
+
def extract(ctx) = ctx.pre_checkout_query
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
class PurchasedPaidMediaHandler < BaseHandler
|
|
112
|
+
def event = :purchased_paid_media
|
|
113
|
+
def extract(ctx) = ctx.purchased_paid_media
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
class ShippingQueryHandler < BaseHandler
|
|
117
|
+
def event = :shipping_query
|
|
118
|
+
def extract(ctx) = ctx.shipping_query
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
class StoryHandler < BaseHandler
|
|
122
|
+
def event = :story
|
|
123
|
+
def extract(ctx) = ctx.story_update
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
class UserStatusHandler < BaseHandler
|
|
127
|
+
def event = :user_status
|
|
128
|
+
def extract(ctx) = ctx.user_status
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
class StartHandler < BaseHandler
|
|
132
|
+
def event = :start
|
|
133
|
+
def extract(_ctx) = nil
|
|
134
|
+
def client_only? = true
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
class StopHandler < BaseHandler
|
|
138
|
+
def event = :stop
|
|
139
|
+
def extract(_ctx) = nil
|
|
140
|
+
def client_only? = true
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
class ConnectHandler < BaseHandler
|
|
144
|
+
def event = :connect
|
|
145
|
+
def extract(_ctx) = nil
|
|
146
|
+
def client_only? = true
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
class DisconnectHandler < BaseHandler
|
|
150
|
+
def event = :disconnect
|
|
151
|
+
def extract(_ctx) = nil
|
|
152
|
+
def client_only? = true
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
class ErrorHandler < BaseHandler
|
|
156
|
+
def event = :error
|
|
157
|
+
def extract(ctx) = ctx.error_payload
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
class ManagedBotUpdatedHandler < BaseHandler
|
|
161
|
+
def event = :managed_bot
|
|
162
|
+
def extract(ctx) = ctx.managed_bot_updated
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
class RawUpdateHandler < BaseHandler
|
|
166
|
+
def event = :raw_update
|
|
167
|
+
def extract(ctx) = ctx.update
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|