Рубиновый камень мешает мне спасти
Я пытаюсь создать бота Discord, выполнив вход в систему непосредственно на сервере Discord, на котором он находится, однако само гем discordrb отказывается позволить мне спасти сам блок.
begin
require 'discordrb'
phoenix = Discordrb::Bot.new token: 'TOKEN'
crashpass = rand(0..9999999)
puts "Crash password: #{crashpass}" #Prints to the terminal screen, not to the server
phoenix.message(with_text: "CP!crash #{crashpass}") do
raise "Admin initiated crash."
end
rescue Exception #I know, bad practice, but I wish for this to always execute on error.
ensure
phoenix.run :async #allows code to keep running after bot initialization
phoenix.dnd
phoenix.send_message(454137675944034314, "Something terrible has happened, and I can't recover!\n#{e}")
phoenix.send_message(454137675944034314, "Currently running in emergency mode!")
phoenix.sync
end
Это приводит к этому:
Using WSCS version: 0.3.0
libsodium not available! You can continue to use discordrb as normal but voice support won't work.
Read https://github.com/meew0/discordrb/wiki/Installing-libsodium for more details.
Crash password: 6736731
[INFO : websocket @ 2018-06-07 19:04:57.517] Discord using gateway protocol version: 6, requested: 6
[ERROR : et-1 @ 2018-06-07 19:05:33.326] Exception: #<RuntimeError: Admin initiated crash.>
[ERROR : et-1 @ 2018-06-07 19:05:33.330] C:/Users/nathan/Desktop/Cyan_Phoenix local/bot.rb:19:in `block in <main>'
[ERROR : et-1 @ 2018-06-07 19:05:33.330] C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/discordrb-3.2.1/lib/discordrb/events/generic.rb:98:in `call'
[ERROR : et-1 @ 2018-06-07 19:05:33.330] C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/discordrb-3.2.1/lib/discordrb/bot.rb:1227:in `block in call_event'
Бот не останавливает и не сообщает об ошибке на сервер, игнорируя все спасение, включая обеспечение (которое, я считаю, гарантированно, по крайней мере, начнет работать).
Есть ли способ заставить скрипт обрабатывать мои ошибки вместо встроенных в гемы?
1 ответ
Это только помешает вам спасать исключения внутри phoenix
,
require 'discordrb'
phoenix = Discordrb::Bot.new token: 'TOKEN'
phoenix.run :async
begin
raise "Error here!"
rescue Exception
puts "Got exception!"
end
Нечто подобное будет работать нормально, но когда вы делаете что-то вроде:
phoenix.message(with_text: "CP!crash #{crashpass}") do
raise "Admin initiated crash."
end
Исключение будет возникать внутри асинхронно работающего phoenix
DiscorrRb::Bot
экземпляр, который имеет свою собственную обработку ошибок, так что исключения, возникающие при работе в фоновом режиме, такие как переподключение после любых ошибок подключения, будут обрабатываться там, а не сбой остальной части приложения.
Если вы хотите отправить сообщения об исключении на дискорд, вам нужно будет изменить Discordrb::Logger
, Тем не менее, я не думаю, что это очень полезно, так как, скорее всего, исключения, поднятые внутри Discordrb::Bot
Асинхронный код будет связан с ситуацией, когда соединение перестало работать, и он не сможет отправить сообщение об исключении в Discord, вызывая бесконечное переполнение цикла / стека, когда отправка сообщения об исключении в Discord вызывает исключение, потому что дискорд соединение было отключено.
Однако, если вы хотите какие-либо исключения в вашем коде (не Discordrb::Bot
код) ничто не мешает вам написать что-то вроде:
phoenix.run :async
loop do
begin
score = calculate_score
phoenix.send_message(channel_id, "Score : #{score}")
rescue => ex
phoenix.send_message(
channel_id,
"crash while calulcating score! #{ex.class} : #{ex.message}"
)
sleep 10
retry
end
sleep 10
end
И если вы хотите спасти внутри обработчика событий:
phoenix.message(with_text: "score?") do |event|
begin
score = ScoreCalc.calculate_score
event.respond("Score : #{score}")
rescue => ex
send_message(454137675944034314, "CRASHED! #{ex.class}: #{ex.message}")
send_message(454137675944034314, ex.backtrace.join("\n"))
event.respond "Sorry, there was a problem and it has been reported"
end
end
Обработка исключений в поточном / асинхронном коде - распространенная проблема в Ruby.