tgbot 0.1.6 → 0.2.2
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 +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +108 -3
- data/Rakefile +0 -9
- data/lib/api.yaml +4052 -0
- data/lib/tgbot.rb +290 -4
- data/lib/tgbot/version.rb +2 -2
- data/tgbot.gemspec +3 -3
- data/tool/gen.rb +32 -0
- metadata +8 -23
- data/example.rb +0 -110
- data/lib/methods.json +0 -1
- data/lib/tgbot/core.rb +0 -145
- data/lib/tgbot/dsl.rb +0 -59
- data/lib/tgbot/runner.rb +0 -46
- data/lib/tgbot/update.rb +0 -83
- data/lib/types.json +0 -1
- data/tools/gen_methods_json.rb +0 -19
- data/tools/gen_methods_txt.rb +0 -15
- data/tools/gen_types_json.rb +0 -15
- data/tools/gen_types_txt.rb +0 -21
- data/tools/methods.json +0 -1
- data/tools/methods.txt +0 -372
- data/tools/types.json +0 -1
- data/tools/types.txt +0 -605
- data/usage.md +0 -97
data/lib/tgbot.rb
CHANGED
@@ -1,5 +1,291 @@
|
|
1
1
|
require 'tgbot/version'
|
2
|
-
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
2
|
+
|
3
|
+
require 'http'
|
4
|
+
require 'mimemagic'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'json'
|
7
|
+
require 'psych'
|
8
|
+
|
9
|
+
class Tgbot
|
10
|
+
APIDOC = Psych.load_file File.join __dir__, 'api.yaml'
|
11
|
+
|
12
|
+
def self.run(*args, &blk)
|
13
|
+
bot = new(*args)
|
14
|
+
bot.instance_exec(bot, &blk) if blk
|
15
|
+
bot.run
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_accessor :debug
|
19
|
+
|
20
|
+
def initialize(token, proxy: nil, debug: false)
|
21
|
+
@prefix = "/bot#{token}"
|
22
|
+
@client = HTTP.persistent "https://api.telegram.org"
|
23
|
+
if proxy
|
24
|
+
addr, port = *proxy.split(':')
|
25
|
+
@client = @client.via(addr, port.to_i)
|
26
|
+
end
|
27
|
+
@debug = debug
|
28
|
+
@commands = []
|
29
|
+
@start = @finish = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def start &blk
|
33
|
+
@start = blk
|
34
|
+
end
|
35
|
+
|
36
|
+
def finish &blk
|
37
|
+
@finish = blk
|
38
|
+
end
|
39
|
+
|
40
|
+
def on pattern=nil, name: nil, before_all: false, after_all: false, &blk
|
41
|
+
if before_all && after_all
|
42
|
+
raise ArgumentError, 'before_all and after_all can\'t both be true'
|
43
|
+
end
|
44
|
+
@commands << [pattern, name, before_all, after_all, blk]
|
45
|
+
end
|
46
|
+
|
47
|
+
def debug msg
|
48
|
+
STDERR.puts "#{Time.now.strftime "%FT%T"} #{msg}" if @debug
|
49
|
+
end
|
50
|
+
|
51
|
+
class Update
|
52
|
+
attr_reader :bot, :data
|
53
|
+
|
54
|
+
def initialize bot, data
|
55
|
+
@bot = bot
|
56
|
+
@data = data
|
57
|
+
end
|
58
|
+
|
59
|
+
def interrupt!
|
60
|
+
@bot.instance_variable_get(:@tasks).clear
|
61
|
+
end
|
62
|
+
|
63
|
+
alias done! interrupt!
|
64
|
+
|
65
|
+
def retry! n=1
|
66
|
+
@retried ||= n
|
67
|
+
return if @retried <= 0
|
68
|
+
@bot.instance_variable_get(:@updates) << self
|
69
|
+
@retried -= 1
|
70
|
+
end
|
71
|
+
|
72
|
+
def match? pattern
|
73
|
+
return true if pattern.nil?
|
74
|
+
return false if text.nil?
|
75
|
+
!!match(pattern)
|
76
|
+
end
|
77
|
+
|
78
|
+
def match pattern
|
79
|
+
return nil if pattern.nil? || text.nil?
|
80
|
+
text.match(pattern)
|
81
|
+
end
|
82
|
+
|
83
|
+
def message
|
84
|
+
@data.to_h.find { |k, v| k.match? /message|post/ }&.last
|
85
|
+
end
|
86
|
+
|
87
|
+
def text
|
88
|
+
message&.text&.gsub(/(\/\w+)(@\w+)/, '\1')
|
89
|
+
end
|
90
|
+
|
91
|
+
def reply *things, media: true, style: nil, **options
|
92
|
+
meth = :send_message
|
93
|
+
payload = { chat_id: message&.chat.id }
|
94
|
+
things.each do |x|
|
95
|
+
if IO === x
|
96
|
+
magic = MimeMagic.by_magic(x)
|
97
|
+
case
|
98
|
+
when magic.audio?
|
99
|
+
meth = :send_audio
|
100
|
+
payload[:audio] = x
|
101
|
+
when magic.image?
|
102
|
+
meth = :send_photo
|
103
|
+
payload[:photo] = x
|
104
|
+
when magic.video?
|
105
|
+
meth = :send_video
|
106
|
+
payload[:video] = x
|
107
|
+
else
|
108
|
+
meth = :send_document
|
109
|
+
payload[:document] = x
|
110
|
+
end
|
111
|
+
else
|
112
|
+
payload[:text] = x.to_s
|
113
|
+
payload[:parse_mode] = 'Markdown'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
payload = payload.merge options
|
117
|
+
case style
|
118
|
+
when :at
|
119
|
+
if payload[:text] && message.from
|
120
|
+
from = message.from
|
121
|
+
if payload[:parse_mode].match? /Markdown/i
|
122
|
+
prefix = "[#{from.first_name}](tg://user?id=#{from.id}) "
|
123
|
+
elsif payload[:parse_mode].match? /HTML/i
|
124
|
+
prefix = "<a href=\"tg://user?id=#{from.id}\">#{from.first_name}</a> "
|
125
|
+
else
|
126
|
+
prefix = ''
|
127
|
+
end
|
128
|
+
payload[:text] = prefix + payload[:text]
|
129
|
+
end
|
130
|
+
when nil
|
131
|
+
if !payload[:reply_to_message_id]
|
132
|
+
payload[:reply_to_message_id] = message_id
|
133
|
+
end
|
134
|
+
end
|
135
|
+
@bot.send meth, payload
|
136
|
+
end
|
137
|
+
|
138
|
+
def message_id
|
139
|
+
message&.message_id
|
140
|
+
end
|
141
|
+
|
142
|
+
def method_missing meth, *args, &blk
|
143
|
+
return @data[meth] if args.empty? && @data[meth]
|
144
|
+
@bot.send(meth, *args, &blk)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def run &blk
|
149
|
+
@offset = 0
|
150
|
+
@timeout = 2
|
151
|
+
@updates = []
|
152
|
+
instance_exec(self, &@start) if @start
|
153
|
+
loop do
|
154
|
+
while x = @updates.shift
|
155
|
+
u = Update === x ? x : Update.new(self, x)
|
156
|
+
@offset = u.update_id if u.update_id && @offset < u.update_id
|
157
|
+
@tasks = @commands.select { |pattern, *| u.match? pattern }
|
158
|
+
.group_by { |e| e[2] ? :before : e[3] ? :after : nil }
|
159
|
+
.values_at(:before, nil, :after).compact.flatten(1)
|
160
|
+
while t = @tasks.shift
|
161
|
+
debug ">> #{t[1] || t[0]}"
|
162
|
+
u.instance_exec(u.match(t[0]), u, t, &t[4])
|
163
|
+
end
|
164
|
+
end
|
165
|
+
res = get_updates offset: @offset + 1, limit: 7, timeout: 15
|
166
|
+
if res.ok
|
167
|
+
@updates.push *res.result
|
168
|
+
else
|
169
|
+
debug "#{res.error_code}: #{res.description}"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
rescue HTTP::ConnectionError
|
173
|
+
debug "connect failed, check proxy?"
|
174
|
+
retry
|
175
|
+
rescue Interrupt
|
176
|
+
instance_exec(self, &@finish) if @finish
|
177
|
+
ensure
|
178
|
+
@client.close
|
179
|
+
end
|
180
|
+
|
181
|
+
def api_version
|
182
|
+
search_in_doc(/changes/i, '')[0].desc[0].content[/\d+\.\d+/]
|
183
|
+
end
|
184
|
+
|
185
|
+
private
|
186
|
+
|
187
|
+
def method_missing meth, *args, &blk
|
188
|
+
meth = meth.to_s.split('_').map.
|
189
|
+
with_index { |x, i| i.zero? ? x : (x[0].upcase + x[1..-1]) }.join
|
190
|
+
payload = make_payload meth, *args
|
191
|
+
debug "/#{meth} #{payload}"
|
192
|
+
result = @client.post("#@prefix/#{meth}", form: payload).to_s
|
193
|
+
result = json_to_ostruct(result)
|
194
|
+
debug "=> #{result}"
|
195
|
+
blk ? blk.call(result) : result
|
196
|
+
end
|
197
|
+
|
198
|
+
def json_to_ostruct json
|
199
|
+
JSON.parse(json, object_class: OpenStruct)
|
200
|
+
end
|
201
|
+
|
202
|
+
def make_payload meth, *args
|
203
|
+
defaults, schema = meth_info meth
|
204
|
+
payload = {}
|
205
|
+
args.each do |arg|
|
206
|
+
if field = defaults.find { |k, _| k.any? { |l| check_match l, arg } }&.last
|
207
|
+
defaults.delete_if { |_, v| v == field }
|
208
|
+
payload[field] = arg
|
209
|
+
end
|
210
|
+
if Hash === arg
|
211
|
+
defaults.delete_if { |_, v| arg.keys.include?(v) || arg.keys.include?(v.to_sym) }
|
212
|
+
payload = payload.merge arg
|
213
|
+
end
|
214
|
+
end
|
215
|
+
if !defaults.empty?
|
216
|
+
debug "should 400: #{defaults.values.join(', ')} not specified"
|
217
|
+
end
|
218
|
+
check_type payload, schema
|
219
|
+
end
|
220
|
+
|
221
|
+
def meth_info meth
|
222
|
+
unless table = (search_in_doc '', /^#{meth}$/)[0]&.table
|
223
|
+
debug "don't find type of #{meth}"
|
224
|
+
return {}, {}
|
225
|
+
end
|
226
|
+
defaults = table.select { |e| e.Required.match? /Yes/i }
|
227
|
+
.map { |e|
|
228
|
+
[e.Type.split(/\s+or\s+/).flat_map { |s|
|
229
|
+
string_to_native_types s, false
|
230
|
+
}.compact, e.Parameter]
|
231
|
+
}.reject { |(ts, _para)| ts.empty? }.to_h
|
232
|
+
schema = table
|
233
|
+
.map { |e|
|
234
|
+
[e.Parameter, e.Type.split(/\s+or\s+/).map { |s|
|
235
|
+
string_to_native_types s
|
236
|
+
}]
|
237
|
+
}.to_h
|
238
|
+
return defaults, schema
|
239
|
+
end
|
240
|
+
|
241
|
+
def string_to_native_types s, keep_unknown=true
|
242
|
+
if s['Array of ']
|
243
|
+
return [string_to_native_types(s[9..-1], keep_unknown)]
|
244
|
+
end
|
245
|
+
case s
|
246
|
+
when 'String' then String
|
247
|
+
when 'Integer' then Integer
|
248
|
+
when 'Boolean' then [true, false]
|
249
|
+
else
|
250
|
+
keep_unknown ? s : nil
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def check_match k, arg
|
255
|
+
if Array === k
|
256
|
+
if k.size > 1
|
257
|
+
k.any? { |t| t === arg }
|
258
|
+
else
|
259
|
+
Array === arg && arg.all? { |a| check_match k[0], a }
|
260
|
+
end
|
261
|
+
else
|
262
|
+
return true if String === k # unknown types, like "User"
|
263
|
+
k === arg
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def check_type payload, schema
|
268
|
+
filtered = {}
|
269
|
+
payload.each do |field, value|
|
270
|
+
row = schema[field.to_s]
|
271
|
+
if row&.any? { |k| check_match k, value }
|
272
|
+
filtered[field] = value
|
273
|
+
else
|
274
|
+
debug "check_type failed at #{field} :: #{row&.join(' | ')} = #{value.inspect}"
|
275
|
+
end
|
276
|
+
end
|
277
|
+
filtered
|
278
|
+
end
|
279
|
+
|
280
|
+
def search_in_doc *hints
|
281
|
+
doc = [APIDOC]
|
282
|
+
hints.each do |hint|
|
283
|
+
if nxt = doc.flat_map { |x| x['children'] }.select { |x| x['name'][hint] }
|
284
|
+
doc = nxt
|
285
|
+
else
|
286
|
+
return nil
|
287
|
+
end
|
288
|
+
end
|
289
|
+
json_to_ostruct JSON.generate doc
|
290
|
+
end
|
291
|
+
end
|
data/lib/tgbot/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = '0.
|
1
|
+
class Tgbot
|
2
|
+
VERSION = '0.2.2'.freeze
|
3
3
|
end
|
data/tgbot.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["hyrious@outlook.com"]
|
11
11
|
|
12
12
|
spec.summary = 'Telegram Bot API'
|
13
|
-
spec.description = 'Telegram Bot API
|
13
|
+
spec.description = 'A deadly simple Telegram Bot API wrapper.'
|
14
14
|
spec.homepage = 'https://github.com/hyrious/tgbot'
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency "bundler"
|
25
25
|
spec.add_development_dependency "rake"
|
26
26
|
|
27
|
-
spec.add_dependency '
|
27
|
+
spec.add_dependency 'http'
|
28
28
|
spec.add_dependency 'mimemagic'
|
29
|
-
spec.required_ruby_version = '>= 2.
|
29
|
+
spec.required_ruby_version = '>= 2.6.0'
|
30
30
|
end
|
data/tool/gen.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'http'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
raw = HTTP.via('127.0.0.1', 1080).get('https://core.telegram.org/bots/api').to_s
|
5
|
+
nodes = Nokogiri::HTML(raw).at('#dev_page_content').children
|
6
|
+
ret = [{ name: 'Telegram Bot API', children: [] }]
|
7
|
+
uplevels = [2]
|
8
|
+
nodes.each do |node|
|
9
|
+
case node.name
|
10
|
+
when 'h3', 'h4'
|
11
|
+
n = node.name[/\d/].to_i
|
12
|
+
while uplevels[-1] >= n
|
13
|
+
ret.pop
|
14
|
+
uplevels.pop
|
15
|
+
end
|
16
|
+
ret[-1][:children] << (x = { name: node.content, children: [] })
|
17
|
+
ret << x
|
18
|
+
uplevels << n
|
19
|
+
when 'h6', 'p', 'blockquote', 'pre'
|
20
|
+
(ret[-1]['desc'] ||= []) << { name: node.name, content: node.content.strip }
|
21
|
+
when 'ul', 'ol'
|
22
|
+
(ret[-1]['desc'] ||= []) << { name: node.name, content: node.css('li').map(&:content).map(&:strip) }
|
23
|
+
when 'table'
|
24
|
+
keys = node.css('th').map(&:content)
|
25
|
+
ret[-1]['table'] = node.css('tbody > tr').map do |tr|
|
26
|
+
keys.zip(tr.css('td').map(&:content)).to_h
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
ret = JSON.parse JSON.generate ret[0]
|
31
|
+
require 'psych'
|
32
|
+
open(File.expand_path('../lib/api.yaml', __dir__), 'wb') { |f| Psych.dump ret, f, line_width: 1<<30 }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tgbot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- hyrious
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-03-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: http
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
-
description: Telegram Bot API
|
69
|
+
description: A deadly simple Telegram Bot API wrapper.
|
70
70
|
email:
|
71
71
|
- hyrious@outlook.com
|
72
72
|
executables: []
|
@@ -80,25 +80,11 @@ files:
|
|
80
80
|
- Rakefile
|
81
81
|
- bin/console
|
82
82
|
- bin/setup
|
83
|
-
-
|
84
|
-
- lib/methods.json
|
83
|
+
- lib/api.yaml
|
85
84
|
- lib/tgbot.rb
|
86
|
-
- lib/tgbot/core.rb
|
87
|
-
- lib/tgbot/dsl.rb
|
88
|
-
- lib/tgbot/runner.rb
|
89
|
-
- lib/tgbot/update.rb
|
90
85
|
- lib/tgbot/version.rb
|
91
|
-
- lib/types.json
|
92
86
|
- tgbot.gemspec
|
93
|
-
-
|
94
|
-
- tools/gen_methods_txt.rb
|
95
|
-
- tools/gen_types_json.rb
|
96
|
-
- tools/gen_types_txt.rb
|
97
|
-
- tools/methods.json
|
98
|
-
- tools/methods.txt
|
99
|
-
- tools/types.json
|
100
|
-
- tools/types.txt
|
101
|
-
- usage.md
|
87
|
+
- tool/gen.rb
|
102
88
|
homepage: https://github.com/hyrious/tgbot
|
103
89
|
licenses:
|
104
90
|
- MIT
|
@@ -111,15 +97,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
111
97
|
requirements:
|
112
98
|
- - ">="
|
113
99
|
- !ruby/object:Gem::Version
|
114
|
-
version: 2.
|
100
|
+
version: 2.6.0
|
115
101
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
102
|
requirements:
|
117
103
|
- - ">="
|
118
104
|
- !ruby/object:Gem::Version
|
119
105
|
version: '0'
|
120
106
|
requirements: []
|
121
|
-
|
122
|
-
rubygems_version: 2.7.3
|
107
|
+
rubygems_version: 3.0.1
|
123
108
|
signing_key:
|
124
109
|
specification_version: 4
|
125
110
|
summary: Telegram Bot API
|
data/example.rb
DELETED
@@ -1,110 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'faraday'
|
3
|
-
require './helper'
|
4
|
-
save_pid
|
5
|
-
require 'tgbot'
|
6
|
-
Garage = load_data.shuffle
|
7
|
-
Cache = {}
|
8
|
-
TOKEN =
|
9
|
-
Tgbot.run TOKEN, proxy: 'http://127.0.0.1:1080' do |bot|
|
10
|
-
|
11
|
-
bot.start do
|
12
|
-
log "\e[33m#{bot.name}\e[32m, at your service.", 2
|
13
|
-
end
|
14
|
-
bot.finish do
|
15
|
-
log "byebye.", 2
|
16
|
-
end
|
17
|
-
|
18
|
-
bot.get 'start' do
|
19
|
-
send_message(<<~EOF, parse_mode: 'Markdown')
|
20
|
-
```
|
21
|
-
start : 显示此帮助信息
|
22
|
-
drive : 随机返回一张车库里的图
|
23
|
-
对该图回复 “原图” : 返回原图
|
24
|
-
exchange 100 CNY to JPY : 汇率转换
|
25
|
-
register : 添加自定义功能(会先提交给作者)
|
26
|
-
```
|
27
|
-
EOF
|
28
|
-
end
|
29
|
-
|
30
|
-
bot.get 'drive' do
|
31
|
-
pic = Garage.pop
|
32
|
-
log ">> Sending #{File.basename(pic)} to @#{message.from.username} ##{id}", 6
|
33
|
-
bytes = File.size pic
|
34
|
-
size = hsize bytes
|
35
|
-
reply "正在发车 (#{size} #{htime(bytes / 30720)})"
|
36
|
-
x = reply_photo pic, caption: File.basename(pic, '.*')
|
37
|
-
if self.done = x['ok']
|
38
|
-
Cache["drive_#{x['result']['message_id']}"] = pic
|
39
|
-
end
|
40
|
-
self.done! if self.count > 1
|
41
|
-
end
|
42
|
-
bot.get '原图' do
|
43
|
-
x = message&.reply_to_message&.message_id
|
44
|
-
pic = Cache["drive_#{x}"]
|
45
|
-
unless pic
|
46
|
-
reply '没找到原图,重开'
|
47
|
-
next
|
48
|
-
end
|
49
|
-
log ">> Sending original #{File.basename(pic)} to @#{message.from.username} ##{id}", 6
|
50
|
-
reply_document pic
|
51
|
-
end
|
52
|
-
|
53
|
-
bot.get 'exchange' do
|
54
|
-
x = text&.match /([-+]?[1-9]\d*(\.\d+)?)\s*([A-Z]+)\s*to\s*([A-Z]+)/
|
55
|
-
unless x
|
56
|
-
reply 'Usage: exchange 100 CNY to JPY'
|
57
|
-
next
|
58
|
-
end
|
59
|
-
n, f, t = x.values_at 1, 3, 4
|
60
|
-
n = Float(n) rescue next
|
61
|
-
Cache["exchange_#{f}"] ||= JSON.parse Faraday.get("http://api.fixer.io/latest?base=#{f}").body
|
62
|
-
next unless Cache["exchange_#{f}"] && !Cache["exchange_#{f}"]['error']
|
63
|
-
next unless Cache["exchange_#{f}"]['rates'][t]
|
64
|
-
n *= Cache["exchange_#{f}"]['rates'][t]
|
65
|
-
t = Cache["exchange_#{f}"]['date']
|
66
|
-
reply "#{'%.2f' % n} (#{t})"
|
67
|
-
end
|
68
|
-
|
69
|
-
bot.before do |update|
|
70
|
-
log ">> Processing ##{update.id}"
|
71
|
-
log "@#{update.message&.from&.first_name}: #{update.text}", 3
|
72
|
-
end
|
73
|
-
bot.after do |update|
|
74
|
-
if update.done?
|
75
|
-
log "=> Success ##{update.id}", 2
|
76
|
-
else
|
77
|
-
log "?> Retry ##{update.id}", 3
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
bot.get 'register' do
|
82
|
-
e = message&.entities&.find { |e| e.type == 'pre' }
|
83
|
-
if e.nil?
|
84
|
-
send_message(<<~EOF)
|
85
|
-
register <功能名>
|
86
|
-
```
|
87
|
-
get /command/ do |matched|
|
88
|
-
# your code here
|
89
|
-
end
|
90
|
-
```
|
91
|
-
EOF
|
92
|
-
next
|
93
|
-
end
|
94
|
-
open 'register.rb', 'a' do |f|
|
95
|
-
f.puts text[e.offset, e.length]
|
96
|
-
end
|
97
|
-
reply '脚本已备分'
|
98
|
-
end
|
99
|
-
|
100
|
-
bot.get 'coin' do
|
101
|
-
send_message Array.new(text&.match(/\d+/)&.to_s.to_i || 1){ ['🌞', '🌚'].sample }.join
|
102
|
-
end
|
103
|
-
bot.get 'roll' do
|
104
|
-
send_message rand(text&.match(/\d+/)&.to_s.to_i.nonzero? || 100).to_s
|
105
|
-
end
|
106
|
-
|
107
|
-
end
|
108
|
-
|
109
|
-
save_data Garage
|
110
|
-
delete_pid
|