Compare commits

...

34 Commits

Author SHA1 Message Date
Aaron Johnson 8e7c5517ff Merge pull request 'Status aliases' (#16) from dev into master
2 years ago
Aaron Johnon 75c79750d4 Added check to /srvstop to make sure server is up before sending stop command
2 years ago
Aaron Johnson 8d0d765fd7 Merge branch 'master' into dev
5 years ago
Aaron Johnson 33cf62044c Added aliases for /status
5 years ago
Aaron Johnson 9e0464d9a6 refined the specification of custom static text files to ignore
6 years ago
Aaron Johnson 38d0c327dd Merge branch 'dev' of skyfall/empyrion-bot into master
6 years ago
Aaron Johnson 8db94101c1 Re-implemented two-part sent message logging.
6 years ago
Aaron Johnson 08f0a1fcf8 Merge branch 'dev' of skyfall/empyrion-bot into master
6 years ago
Aaron Johnson f9a1bce1f6 Added message handling from Heatbot; Added voicechat info feature
6 years ago
Aaron Johnson 66d9e9c416 Change notes
6 years ago
Aaron Johnson 049d7041f2 Fixed case where message fails to send, but log suggests otherwise
6 years ago
Aaron Johnson ac47bcf4f3 Added color and style consistency to /status log messages
6 years ago
Aaron Johnson 8a9fcdc562 Merge branch 'dev' of skyfall/empyrion-bot into master
6 years ago
Aaron Johnson 69381daf66 Added configurable tmp directory; rewrote srvstatus
6 years ago
Aaron Johnson 6ec095e3f6 updated patch notes
6 years ago
Aaron Johnson aa777ba4e1 Fixed srvstatus bug
6 years ago
Aaron Johnson a9ba662fe1 updated patch notes
6 years ago
Aaron Johnson 84c8c757cf updated patch notes
6 years ago
Aaron Johnson c279985f2d Server logging and minor code efficiency improvements
6 years ago
Aaron Johnson a299ba7c53 commented out redundant output
6 years ago
Aaron Johnson 56630ad5b0 Improved and colorized logging
6 years ago
Aaron Johnson 36ffd9e4e5 Improved sanity check; addition of colors.rb
6 years ago
Aaron Johnson e8873c0808 More descriptive failure message
6 years ago
Aaron Johnson 808b22ecc1 improved sanity check
6 years ago
Aaron Johnson a609084384 Added git repo link to /start
6 years ago
Aaron Johnson afddd6c130 Merge branch 'dev' of skyfall/empyrion-bot into master
6 years ago
Aaron Johnson 568e3babd0 Fixed patchnotes crashing on some servers (non-ASCII characters)
6 years ago
Aaron Johnson a014f6b26d Updated patchnotes.txt
6 years ago
Aaron Johnson 8346216498 Removed extra space in output
6 years ago
Aaron Johnson 12fdbf70e3 updated /start message
6 years ago
Aaron Johnson d9d231eab8 Fixed broken Contegix myip information
6 years ago
Aaron Johnson 658c3df819 Fixed 'server is up oops nevermind' condition
6 years ago
Aaron Johnson 61f587a85e Added .ignore directory
6 years ago
Aaron Johnson d2206651be Updated /start output
6 years ago

2
.gitignore vendored

@ -1,2 +1,4 @@
/bot_config.yaml /bot_config.yaml
/.ignore
/static_text/custom/*

@ -1,4 +1,5 @@
botname: 'Bob' botname: 'Bob'
tmpdir: '/tmp/.skyfall/egs-bot'
token: '<your-bot-token>' token: '<your-bot-token>'
telnet: telnet:
host: '<your empyrion host address>' host: '<your empyrion host address>'
@ -12,4 +13,11 @@ allowed_sources:
- 'private' - 'private'
- 'group' - 'group'
- 'supergroup' - 'supergroup'
#gif_url_prefix: "<URL to web directory containing GIFs>"
voice_chat_enabled: 'true'
voice_chat_info:
type: 'Mumble'
address: 'chat.example.com'
port: 64738
password: 'ilikebirds'

@ -0,0 +1,28 @@
class String
def black; "\e[30m#{self}\e[0m" end
def red; "\e[31m#{self}\e[0m" end
def green; "\e[32m#{self}\e[0m" end
def yellow; "\e[33m#{self}\e[0m" end
def brown; "\e[33m#{self}\e[0m" end
def blue; "\e[34m#{self}\e[0m" end
def magenta; "\e[35m#{self}\e[0m" end
def cyan; "\e[36m#{self}\e[0m" end
def gray; "\e[37m#{self}\e[0m" end
def bg_black; "\e[40m#{self}\e[0m" end
def bg_red; "\e[41m#{self}\e[0m" end
def bg_green; "\e[42m#{self}\e[0m" end
def bg_yellow; "\e[43m#{self}\e[0m" end
def bg_brown; "\e[43m#{self}\e[0m" end
def bg_blue; "\e[44m#{self}\e[0m" end
def bg_magenta; "\e[45m#{self}\e[0m" end
def bg_cyan; "\e[46m#{self}\e[0m" end
def bg_gray; "\e[47m#{self}\e[0m" end
def bold; "\e[1m#{self}\e[22m" end
def italic; "\e[3m#{self}\e[23m" end
def underline; "\e[4m#{self}\e[24m" end
def blink; "\e[5m#{self}\e[25m" end
def reverse_color; "\e[7m#{self}\e[27m" end
end

@ -13,26 +13,88 @@ def message_from_admin?(message, adm)
#puts message.from.id #puts message.from.id
#puts adm #puts adm
if adm.include?(message.from.id) if adm.include?(message.from.id)
puts "Command is from an admin. [#{message.from.username}]" puts "Command is from an admin. [" + "#{message.from.username}".green.bold + "]"
return true return true
else else
puts "Command is NOT from an admin! [#{message.from.username}]" puts "Command is NOT from an admin! [" + "#{message.from.username}".yellow.bold + "]"
return false return false
end end
end end
def is_chat_authorized?(message, auth_chat) def is_chat_authorized?(message, auth_chat)
if auth_chat.include?(message.chat.id) if auth_chat.include?(message.chat.id)
puts "Group [#{message.chat.id}][#{message.chat.title}] is authorized" puts "Group [" + "#{message.chat.id}".green.bold + "][" + "#{message.chat.title}".green + "] is authorized"
return true return true
else else
puts "Group [#{message.chat.id}][#{message.chat.title}] is NOT authorized!" puts "Group [" + "#{message.chat.id}".red.bold + "][" + "#{message.chat.title}".red + "] is NOT authorized!"
return false return false
end end
end end
#def send_gif(chat, cmd)
# bot.api.sendVideo(chat_id: chat, video: "#{@gif_url_prefix}#{cmd}.gif")
#end
def process_command_start(message, command, adm)
reply = "Introduction: I am #{@botname}, and I am here to make life easier for meatbag admins like you. Currently I can retrieve information " +
"from an Empyrion server as well as kill the server process. I also have some pretty sweet dance moves.\n\n" +
"Commands available:\n/start or /help (Shows this message)\n/voice or /chat (Shows voice chat info)\n/srvstart (Currently non-functional)\n/srvstop\n" +
"/status (show version and online players)\n/whoami or /chatinfo\n/whereareyou or /location\n\n" +
"Check again later to see if any new functions have been added, or use /patchnotes to learn about recent updates.\n" +
"You can also view the source code at the following location:\nhttps://git.skyfall.tech/skyfall/empyrion-bot"
if message_from_admin?(message, adm)
msg_from_admin = true
end
if is_chat_authorized?(message, @auth_chat)
chat_authorized = true
end
if ! msg_from_admin && ! chat_authorized
if message.from.id == message.chat.id
reply = reply + "\n\nWARNING: I am not authorized to work with you directly. My functionality is limited."
else
reply = reply + "\n\nWARNING: I am not authorized to participate with this group. My functionality is limited."
end
elsif msg_from_admin && ! chat_authorized
reply = reply + "\n\nWARNING: Although you are my master, I have not been authorized to participate in this group. My functionality is limited."
end
send_message(message.chat.id, reply)
end
def process_command_voicechat(message, command, adm, vchat_info = @vchat_info)
if is_chat_authorized?(message, @auth_chat) || message_from_admin?(message, adm)
print "Checking connectivity to #{vchat_info['type']} service... "
STDOUT.flush
if vchat_info['type'].downcase != 'discord'
if system("nc -zvw3 #{vchat_info['address']} #{vchat_info['port']} >/dev/null 2>&1")
print "OK\n".green.bold
STDOUT.flush
reply = "#{vchat_info['type']} service is online.\n\n"
else
print "FAIL\n".red.bold
STDOUT.flush
reply = "#{vchat_info['type']} service is not responding!\n\n"
end
else
reply = ""
end
reply = reply + "Voice Chat Connection Information\n" +
"-------------------------------------------------\n" +
"Application: #{vchat_info['type']}\n" +
"Address: #{vchat_info['address']}\n" +
"Port: #{vchat_info['port']}\n" +
"Password: #{vchat_info['password']}\n"
if system("test -f static_text/custom/voicechat.txt")
reply = reply + File.read("static_text/custom/voicechat.txt") #Add custom info
end
STDOUT.flush
else
reply = "Refusal: I am not authorized to provide this information here."
end
send_message(message.chat.id, reply)
end
def process_command_srvstart(message, command, adm) def process_command_srvstart(message, command, adm)
puts "Received command: srvstart" #puts "Received command: " + "srvstart".green
#pp message #pp message
from_admin = message_from_admin?(message, adm) from_admin = message_from_admin?(message, adm)
auth_grp = is_chat_authorized?(message, @auth_chat) auth_grp = is_chat_authorized?(message, @auth_chat)
@ -52,7 +114,7 @@ def process_command_srvstart(message, command, adm)
end end
def process_command_srvstop(message, command, adm) def process_command_srvstop(message, command, adm)
puts "Received command: srvstop" #puts "Received command: " + "srvstop".red
from_admin = message_from_admin?(message, adm) from_admin = message_from_admin?(message, adm)
auth_grp = is_chat_authorized?(message, @auth_chat) auth_grp = is_chat_authorized?(message, @auth_chat)
if ! auth_grp && ! from_admin if ! auth_grp && ! from_admin
@ -63,8 +125,18 @@ def process_command_srvstop(message, command, adm)
return "Refusal: Although I respect your wishes, master, I am not authorized to perform this function for this group." return "Refusal: Although I respect your wishes, master, I am not authorized to perform this function for this group."
else else
telnet = @conf['telnet'] telnet = @conf['telnet']
`./scripts/srvstop #{telnet['host']} #{telnet['port']} #{telnet['pass']}` print 'Checking connectivity to Empyrion service... '
return "Affirmation: I am shutting down the Empyrion service." STDOUT.flush
if system("nc -zvw3 #{telnet['host']} #{telnet['port']} >/dev/null 2>&1")
print "OK\n".green.bold + "Sending shutdown message:\n"
STDOUT.flush
reply = "Affirmation: I am shutting down the Empyrion service."
`./scripts/srvstop #{telnet['host']} #{telnet['port']} #{telnet['pass']}`
else
print "Server did not respond!\nSending failure message...\n".red.bold
reply = "Exclamation: Server is not responding!"
end
return reply
end end
end end
@ -73,19 +145,20 @@ def process_command_srvstatus(message, command, adm)
telnet = @conf['telnet'] telnet = @conf['telnet']
print 'Checking connectivity to Empyrion service... ' print 'Checking connectivity to Empyrion service... '
STDOUT.flush STDOUT.flush
if `nc -zvw3 #{telnet['host']} #{telnet['port']} >/dev/null 2>&1` if system("nc -zvw3 #{telnet['host']} #{telnet['port']} >/dev/null 2>&1")
print "Server responded!\nSending message receipt... " print "OK\n".green.bold + "Sending message receipt... "
STDOUT.flush STDOUT.flush
if `./scripts/srvstatus.receipt #{@conf['token']} #{message.chat.id}` if `./scripts/srvstatus.receipt #{@conf['token']} #{message.chat.id}`
print "Receipt sent!\nFetching details...\n" print "OK\n".green.bold + "Fetching details...\n"
else else
print "Receipt FAILED to send (non-zero exit code on scripts/srvstatus.receipt) !!!\nContinuing to fetch details anyway...\n" print "Receipt FAILED to send (non-zero exit code on scripts/srvstatus.receipt) !!!\nContinuing to fetch details anyway...\n".red.bold
end end
reply = `./scripts/srvstatus #{telnet['host']} #{telnet['port']} #{telnet['pass']} #{@tmpdir}`
else else
print "Server did not respond! Passing to scripts/srvstatus for sending the failure message (revisit this for code efficiency review\n)" print "Server did not respond!\nSending failure message...\n".red.bold
reply = "Exclamation: Server is not responding!"
end end
STDOUT.flush STDOUT.flush
reply = `./scripts/srvstatus #{telnet['host']} #{telnet['port']} #{telnet['pass']}`
else else
reply = "Refusal: I am not authorized to provide this information here." reply = "Refusal: I am not authorized to provide this information here."
end end
@ -94,11 +167,10 @@ end
def process_command_patchnotes(message, command, adm) def process_command_patchnotes(message, command, adm)
if is_chat_authorized?(message, @auth_chat) || message_from_admin?(message, adm) if is_chat_authorized?(message, @auth_chat) || message_from_admin?(message, adm)
telnet = @conf['telnet'] #telnet = @conf['telnet']
reply = `cat patchnotes.txt` reply = File.read("static_text/patchnotes.txt")
else else
reply = "Refusal: I am not authorized to provide this information here." reply = "Refusal: I am not authorized to provide this information here."
end end
return reply return reply
end end

@ -1,16 +0,0 @@
SkyfallTech EGS Telebot
Patch Notes:
v0.3.02
+ Better server logs, round 2
+ Less ambiguous patchnotes listing
(These are for the bot, not for Empyrion)
v0.3.01
+ Better server logs, round 1.
v0.3.00
+ Auto self-resurrection after random bot-suicide.
+ This `/patchnotes` command.
+ Instant message confirmation for `/status` command.

396
run.rb

@ -4,54 +4,173 @@ require 'rubygems'
require 'yaml' require 'yaml'
require 'telegram/bot' require 'telegram/bot'
require 'pp' require 'pp'
require 'time'
require_relative 'commands.rb' require_relative 'commands.rb'
#require_relative 'callbacks.rb'
require_relative 'colors.rb'
def timestamp
Time.now.strftime("%F %H:%M:%S").yellow
end
#conf = YAML.load(File.read("bot_config.yaml")) #conf = YAML.load(File.read("bot_config.yaml"))
@conf = YAML.load_file("bot_config.yaml") @conf = YAML.load_file("bot_config.yaml")
@botname = @conf['botname'] @botname = @conf['botname']
token = @conf['token'] @tmpdir = @conf['tmpdir']
@token = @conf['token']
telnet = @conf['telnet'] telnet = @conf['telnet']
admin = @conf['admin'] admin = @conf['admin']
@auth_chat = @conf['authorized_chats'] @auth_chat = @conf['authorized_chats']
@allowed_sources = @conf['allowed_sources'] @allowed_sources = @conf['allowed_sources']
@ip_provider = "ip.skyfall.tech"
#@gif_url_prefix = "https://img.skyfalltech.net/togra/"
@gif_url_prefix = @conf['gif_url_prefix']
@voice_chat_enabled = @conf['voice_chat_enabled']
@vchat_info = @conf['voice_chat_info']
# Sanity check ### Begin sanity check ###
STDOUT.sync = true
errcount = 0 errcount = 0
puts "Checking if environment is sane...\n\n" puts "Checking if environment is sane...\n\n"
if token.nil? print "Checking system utilities ............... "
puts "No bot token defined in bot_config.yaml!\nTHIS IS REQUIRED! Bot initialization failed; exiting..." ### if !system("which nmap 2>&1 >/dev/null")
### print "FAIL!\n\n".red.bold
### puts "nmap".yellow.bold + " not found. This utility requires the 'nmap' command (for testing connectivity to temperature probes)"
### puts "THIS IS REQUIRED!".red.bold + " Bot initialization failed; exiting..."
### exit(1)
### elsif !system("which curl 2>&1 >/dev/null")
if !system("which curl 2>&1 >/dev/null")
print "FAIL!\n\n".red.bold
puts "curl".yellow.bold + " not found. This utility requires the 'curl' command (for providing IP information to users upon request)"
puts "THIS IS REQUIRED!".red.bold + " Bot initialization failed; exiting..."
exit(1) exit(1)
else
print "OK\n".green.bold
end end
print "Checking bot token ...................... "
if @token.nil?
print "FAIL!\n\n".red.bold
puts "No bot token defined in bot_config.yaml!\n" + "THIS IS REQUIRED!".red.bold + " Bot initialization failed; exiting..."
exit(1)
else
print "OK\n".green.bold
end
print "Checking configured bot name ............ "
if @botname.nil? if @botname.nil?
errcount += 1 errcount += 1
print "FAIL!\n\n".red.bold
puts "Error(#{errcount.to_s}): No bot name defined. This is superficial. We'll call him Bob.\n\n" puts "Error(#{errcount.to_s}): No bot name defined. This is superficial. We'll call him Bob.\n\n"
@botname = "Bob" @botname = "Bob"
else
print "OK\n".green.bold
end end
### Temporary directory check
print "Checking configured tmp directory ....... "
def is_tmp_writable?
system("mkdir -p #{@tmpdir} >/dev/null 2>&1")
if system("touch #{@tmpdir}/test.file >/dev/null 2>&1")
system("rm #{@tmpdir}/test.file >/dev/null 2>&1")
return true
else
system("rm #{@tmpdir}/test.file >/dev/null 2>&1") #Attempt to clean up anyway
return false
end
end
if @tmpdir.nil?
errcount += 1
print "FAIL!\n\n".red.bold
puts "Error(#{errcount.to_s}): No temporary directory defined. Using '/tmp/.skyfall/egs-bot'.\n"
@tmpdir = "/tmp/.skyfall/egs-bot"
if is_tmp_writable?
puts "Default temporary directory is writable. Continuing...\n\n"
else
errcount += 1
puts "Error(#{errcount.to_s}): Temporary directory [" + @tmpdir.red.bold + "] is not writable!\n" + "THIS IS REQUIRED!".red.bold + " Bot initialization failed; exiting..."
exit(1)
end
else
if is_tmp_writable?
print "OK\n".green.bold
else
errcount += 1
print "FAIL!\n\n".red.bold
puts "Error(#{errcount.to_s}): Temporary directory [" + @tmpdir.red.bold + "] is not writable!\n" + "THIS IS REQUIRED!".red.bold + " Bot initialization failed; exiting..."
exit(1)
end
end
### End tmpdir check
print "Checking telnet configuration ........... "
if telnet.nil? if telnet.nil?
errcount += 1 errcount += 1
print "FAIL!\n\n".red.bold
puts "Error(#{errcount.to_s}): No telnet information provided in bot_config.yaml.\nThis is required for nearly all Empyrion-related " + puts "Error(#{errcount.to_s}): No telnet information provided in bot_config.yaml.\nThis is required for nearly all Empyrion-related " +
"functions.\nTHIS SHOULD BE ADDRESSED. Continuing. (some commands will return broken messages)\n\n" "functions.\nTHIS SHOULD BE ADDRESSED. Continuing. (some commands will return broken messages)\n\n"
else
print "OK\n".green.bold
end end
print "Checking administrators ................. "
if admin.nil? if admin.nil?
errcount += 1 errcount += 1
print "FAIL!\n\n".red.bold
puts "Error(#{errcount.to_s}): No admin Telegram IDs provided in bot_config.yaml.\nThis is required for many functions.\n" + puts "Error(#{errcount.to_s}): No admin Telegram IDs provided in bot_config.yaml.\nThis is required for many functions.\n" +
"THIS SHOULD BE ADDRESSED. Continuing. (some commands will not be available)\n\n" "THIS SHOULD BE ADDRESSED. Continuing. (some commands will not be available)\n\n"
admin = ["0"] admin = ["0"]
else
print "OK\n".green.bold
end end
print "Checking authorized chats ............... "
if @auth_chat.nil? if @auth_chat.nil?
errcount += 1 errcount += 1
print "FAIL!\n\n".red.bold
puts "Error(#{errcount.to_s}): No authorized Telegram group IDs provided in bot_config.yaml.\nThis is required for most Empyrion-related " + puts "Error(#{errcount.to_s}): No authorized Telegram group IDs provided in bot_config.yaml.\nThis is required for most Empyrion-related " +
"functions.\nTHIS SHOULD BE ADDRESSED. Continuing. (some commands will not be available)\n\n" "functions.\nTHIS SHOULD BE ADDRESSED. Continuing. (some commands will not be available)\n\n"
@auth_chat = ["0"] @auth_chat = ["0"]
else
print "OK\n".green.bold
end
print "Checking GIF URL prefix ................. "
if @gif_url_prefix.nil?
errcount += 1
print "FAIL!\n\n".red.bold
puts "Error(#{errcount.to_s}): No GIF URL prefix provided in bot_config.yaml.\nThis is required only for a couple of Easter egg features. " +
"Using the Skyfall/Togra GIF prefix instead. Continuing.\n\n"
@gif_url_prefix = "https://img.skyfalltech.net/togra/"
else
print "OK\n".green.bold
end
if @voice_chat_enabled == "true"
print "Checking voice chat info ................ "
if @vchat_info.nil?
errcount += 1
print "FAIL!\n\n".red.bold
puts "Error(#{errcount.to_s}): Voice chat features are enabled, but no voice chat application info is configured in bot_config.yaml!\n" +
"THIS SHOULD BE ADDRESSED. Some functions may fail, but the core functionality should be unaffected. Continuing.\n\n"
else
print "OK\n".green.bold
end
end end
puts "Errors found: #{errcount.to_s}\n\n"
puts "Errors found: #{errcount.to_s}\n\n"
if errcount > 0
print "Environment is grinning and holding a spatula. Please review your configuration.\n\n".red.bold
else
print "Environment appears sane.\n\n".green.bold
end
STDOUT.sync = false
### End sanity check ###
puts "Starting [#{@botname}]...\n\n" puts "Starting [#{@botname}]...\n\n"
puts "Empyrion Host: #{telnet['host']}" puts "Empyrion Host: #{telnet['host']}"
puts "Empyrion Telnet Port: #{telnet['port']}" puts "Empyrion Telnet Port: #{telnet['port']}"
puts "Authorized administrator IDs: #{admin}" puts "Authorized administrator IDs: #{admin}"
puts "Authorized chat IDs: #{@auth_chat}" puts "Authorized chat IDs: #{@auth_chat}"
puts "Bot token: #{token}\n\n\n\n" puts "Bot token: #{@token}"
puts "Temporary direcotry: #{@tmpdir}"
puts "IP Provider: #{@ip_provider}"
puts "GIF URL Prefix: #{@gif_url_prefix}"
puts "Start time: " + timestamp + "\n\n\n\n"
STDOUT.flush
#def process_command_srvstart(message) #def process_command_srvstart(message)
# puts "Received command: srvstart" # puts "Received command: srvstart"
@ -63,10 +182,109 @@ puts "Bot token: #{token}\n\n\n\n"
# reply = `./srvstop` # reply = `./srvstop`
#end #end
def ack_callback(message, display_message = true)
#Delete message and notify user that we got the request
begin
Telegram::Bot::Client.run(@token) do |bot|
if display_message == true
bot.api.editMessageText(chat_id: message.message.chat.id, message_id: message.message.message_id, text: "Request received. Please wait...", reply_markup: "") #Removes buttons. Changes text
bot.api.answerCallbackQuery(callback_query_id: message.id, show_alert: false, text: "Request received. Please wait...") #Sends a pop-up notification
else
bot.api.deleteMessage(chat_id: message.message.chat.id, message_id: message.message.message_id) #Deletes message and buttons
end
end
rescue
puts "Error handling callback query. Error: " + $!.message
end
STDOUT.flush
end
def delete_message(message)
#Deletes a message referred to by message_id
begin
Telegram::Bot::Client.run(@token) do |bot|
bot.api.deleteMessage(chat_id: message.message.chat.id, message_id: message.message.message_id) #Deletes message and buttons
end
rescue
puts "Error deleting message. Error: " + $!.message
end
STDOUT.flush
end
def delete_confirmation(message)
#Deletes a message referred to by message_id
begin
Telegram::Bot::Client.run(@token) do |bot|
bot.api.deleteMessage(chat_id: message.chat.id, message_id: message.message_id)
end
rescue
puts "Error deleting message. Error: " + $!.message
end
STDOUT.flush
end
def send_message(chatid, message_text, imageurl = nil)
if imageurl != nil
#Send message with text as html link to image
print timestamp + ": Sending ............ "
STDOUT.flush
message = Telegram::Bot::Client.run(@token) {|bot| message = bot.api.send_message(chat_id: chatid, text: "#{message_text}<a href=\"#{imageurl}\">.</a>", parse_mode: "HTML") }
print "OK\n".green.bold
STDOUT.flush
puts "Sent: #{message_text.inspect}\n\n"
STDOUT.flush
#puts timestamp + ": Sent: #{message_text.inspect}\n\n"
return message
else
#Send a plain-text message
print timestamp + ": Sending ............ "
STDOUT.flush
message = Telegram::Bot::Client.run(@token) {|bot| bot.api.send_message(chat_id: chatid, text: message_text) }
print "OK\n".green.bold
puts "Sent: #{message_text.inspect}\n\n"
STDOUT.flush
#puts message
#message = message["results"]
#puts message
return message
end
end
def send_gif(chatid, cmd)
#message = Telegram::Bot::Client.run(@token) {|bot| message = bot.api.send_message(chat_id: chatid, text: "#{message_text}<a href=\"#{imageurl}\">.</a>", parse_mode: "HTML") }
gif_url = "#{@gif_url_prefix}#{cmd}.gif"
print timestamp + ": Sending ............ "
message = Telegram::Bot::Client.run(@token) {|bot| message = bot.api.sendVideo(chat_id: chatid, video: gif_url) }
print "OK\n".green.bold
puts "Sent GIF: #{gif_url}\n\n"
STDOUT.flush
return message
end
def send_message_markdown(chatid, message_text)
#Send a plain-text message
Telegram::Bot::Client.run(@token) {|bot| bot.api.send_message(chat_id: chatid, text: "```#{message_text}```", parse_mode: 'Markdown') }
puts timestamp + ": Sent: #{message_text.inspect}\n\n"
STDOUT.flush
end
def send_question(chatid, question_text, answers = [ ])
if ! answers.empty? then
begin
keyboard = Telegram::Bot::Types::InlineKeyboardMarkup.new(inline_keyboard: answers)
Telegram::Bot::Client.run(@token) {|bot| bot.api.send_message(chat_id: chatid, text: question_text, reply_markup: keyboard) }
rescue
puts timestamp + ": " + "ERROR".red.bold + ": " + $!.message
end
else
puts timestamp + "send_question called without any possible answers provided"
end
STDOUT.flush
end
def handle_message(message) def handle_message(message)
if ! message.reply_to_message.nil? then if ! message.reply_to_message.nil? then
#drop message. Someone's replying to a message #drop message. Someone's replying to a message sent by our bot
#sent by our bot
message.text = nil message.text = nil
return return
end end
@ -81,97 +299,173 @@ def handle_message(message)
return #so that we don't try to process this as a command (below) return #so that we don't try to process this as a command (below)
end end
#Format sender name ### #Format sender name
if ! message.from.username.nil? ### if ! message.from.username.nil?
message.from.username = "@" + message.from.username ### #message.from.username = "@" + message.from.username
elsif ! message.from.first_name.nil? ### elsif ! message.from.first_name.nil?
message.from.username = message.from.first_name ### message.from.username = message.from.first_name
end ### end
#Format command #Format command
command = message.text.split(" ")[0].split("@")[0].downcase #Strip command from arguments and @tags command = message.text.split(" ")[0].split("@")[0].downcase #Strip command from arguments and @tags
#command = message.text
reply = 'Empty String' reply = 'Empty String'
#conf = YAML.load_file("bot_config.yaml")
telnet = @conf['telnet'] telnet = @conf['telnet']
adm = @conf['admin'] adm = @conf['admin']
puts "Received command from #{message.from.username}: #{command}" puts Time.now.strftime("%F %H:%M:%S").yellow + ": Received command from " + "#{message.from.username}".cyan.bold + " [" + "#{message.from.id}".cyan + "]: " + "#{command}".magenta.bold
case command case command
when '/start' when '/start', '/help'
reply = "Introduction: I am #{@botname}, and I am here to make life easier for meatbag admins like you. Currently I can retrieve information " + process_command_start(message, command, adm)
"from an Empyrion server as well as kill the server process.\n\n" + when '/chat', '/voice', '/mumble', '/teamspeak', '/discord', '/vox', '/voicechat'
"Commands available:\n/start (Shows this message)\n/srvstart (Probably won't work)\n/srvstop\n/status\n/whoami\n\n" + if @voice_chat_enabled == "true"
"Check again later to see if any new functions have been added." process_command_voicechat(message, command, adm)
if ! message_from_admin?(message, adm) && ! is_chat_authorized?(message, @auth_chat) else
if message.from.id == message.chat.id send_message(message.chat.id, "Refusal: My master has disabled this feature. Perhaps voice chat service does not exist for this group?")
reply = reply + "\n\nWARNING: I am not authorized to work you directly. My functionality is limited."
else
reply = reply + "\n\nWARNING: I am not authorized to participate with this group. My functionality is limited."
end
elsif message_from_admin?(message, adm) && ! is_chat_authorized?(message, @auth_chat)
reply = reply + "\n\nWARNING: Although you are my master, I have not been authorized to participate in this group. My functionality is limited."
end end
when '/srvstart' when '/srvstart'
reply = process_command_srvstart(message, command, adm) reply = process_command_srvstart(message, command, adm)
send_message(message.chat.id, reply)
when '/srvstop' when '/srvstop'
reply = process_command_srvstop(message, command, adm) reply = process_command_srvstop(message, command, adm)
when '/status' send_message(message.chat.id, reply)
when '/status', '/stat', '/stats', '/list', '/check'
reply = process_command_srvstatus(message, command, adm) reply = process_command_srvstatus(message, command, adm)
#if is_chat_authorized?(message, @auth_chat) || message_from_admin?(message, adm) if command == '/check'
# reply = `./scripts/srvstatus #{telnet['host']} #{telnet['port']} #{telnet['pass']}` reply = "Hi Matt, here's the /status.\n\n" + reply
#else end
# reply = "Refusal: I am not authorized to provide this information here." send_message(message.chat.id, reply)
#end
when '/patch', '/patchnotes' when '/patch', '/patchnotes'
reply = process_command_patchnotes(message, command, adm) reply = process_command_patchnotes(message, command, adm)
send_message(message.chat.id, reply)
when '/location', '/whereareyou' when '/location', '/whereareyou'
if message_from_admin?(message, adm) || is_chat_authorized?(message, @auth_chat) if message_from_admin?(message, adm) || is_chat_authorized?(message, @auth_chat)
reply = "I am currently located at:\n\nHost: #{`head -n1 /etc/hostname`}ExtIP: #{`curl myip.contegix.com 2>/dev/null`}" reply = "I am currently located at:\n\nHost: #{`head -n1 /etc/hostname`}ExtIP: #{`curl #{@ip_provider} 2>/dev/null`}"
else else
reply = "Refusal: I am not authorized to provide this information here." reply = "Refusal: I am not authorized to provide this information here."
end end
send_message(message.chat.id, reply)
when '/whoami', '/chatinfo' when '/whoami', '/chatinfo'
#reply = "Answer: You are a meatbag named #{message.from.username}\n\nUser ID: #{message.from.id}\n\nChat ID: #{message.chat.id}" #reply = "Answer: You are a meatbag named #{message.from.username}\n\nUser ID: #{message.from.id}\n\nChat ID: #{message.chat.id}"
reply = "User ID: #{message.from.id}\nChat ID: #{message.chat.id}" reply = "User ID: #{message.from.id}\nChat ID: #{message.chat.id}"
if command == '/whoami' if command == '/whoami'
reply = "Answer: You are a meatbag named #{message.from.username}\n\n" + reply reply = "Answer: You are a meatbag named #{message.from.username}\n\n" + reply
end end
if command == '/chatinfo'
reply = reply + "\n\nInterjection: If you were intending to find information about how to connect to voice chat, try using the /voice command instead."
end
send_message(message.chat.id, reply)
when '/pp', '/debug' when '/pp', '/debug'
pp message pp message
reply = "Confirmation: Message debug information sent to console." send_message(message.chat.id,"Confirmation: Message debug information sent to console.")
when '/dance' when '/dance'
if is_chat_authorized?(message, @auth_chat) || message_from_admin?(message, adm) if is_chat_authorized?(message, @auth_chat) || message_from_admin?(message, adm)
reply = "dance" send_gif(message.chat.id, 'dance')
else else
reply = "Refusal: I am not authorized to bust a move in this location." send_message(message.chat.id,"Refusal: I am not authorized to bust a move in this location.")
end end
when '/flex', '/unclemike' when '/flex', '/unclemike'
if is_chat_authorized?(message, @auth_chat) || message_from_admin?(message, adm) if is_chat_authorized?(message, @auth_chat) || message_from_admin?(message, adm)
reply = "flex" send_gif(message.chat.id, 'flex')
else else
reply = "Refusal: I am not authorized to bring the gun show to this location." send_message(message.chat.id,"Refusal: I am not authorized to bring the gun show to this location.")
end end
else else
reply = "Mockery: My name is #{message.from.username}, I am a meatbag, and I think #{command} is a valid command." send_message(message.chat.id,"Mockery: My name is #{message.from.username}, I am a meatbag, and I think #{command} is a valid command.")
end end
rescue => e
handle_exception(e, message, true)
# Verbose output: # Verbose output:
puts "Sending #{reply.inspect}\n\n" #print timestamp + ": Sending #{reply.inspect} ..... "
STDOUT.flush
#puts "End of case" #puts "End of case"
return reply return reply
end end
Telegram::Bot::Client.run(token) do |bot| ### def handle_callback_query(message)
### #callbacks that start with a "!" ("!DMS|tt123456") can ONLY be submitted
### #by an admin. Ignore if normal user presses
###
### #Get "DLM" from "DLM|abc123"
### command = message.data.split("|")[0].upcase
###
### if command.start_with?('!') then
### #verify an admin pressed this button
### if ! message_from_admin?(message)
### Telegram::Bot::Client.run(@token) {|bot| bot.api.answerCallbackQuery(callback_query_id: message.id, show_alert: false, text: "Requires admin approval")}
### return
### end
### command = command.split("!")[1]
### elsif command.start_with?('#') then
### #is this an ignored command
### return
### end
###
### ack_callback(message) #Change the selection message to "Request received..."
###
### case command
### when "ZONE" #Get temp info from location
### process_callback_zone(message)
### end
###
### delete_message(message) #Delete the "Request received..." message
### rescue => e
### handle_exception(e, message, true)
### end
def handle_exception(e, message, notify_users)
puts "=" * 60
puts "EXCEPTION OCCURRED!".red.bold
puts "=" * 60
puts "PRINTING INSPECT...".yellow.bold
puts e.inspect
puts "=" * 60
puts "PRINTING BACKTRACE...".yellow.bold
puts e.backtrace
puts "=" * 60
STDOUT.flush
if notify_users == true then
#is this a callback query or a message
case message
when Telegram::Bot::Types::Message
send_message(message.chat.id, "I have run into an issue while processing a command.\n\nPlease notify an administrator.")
when Telegram::Bot::Types::CallbackQuery
send_message(message.message.chat.id, "I have run into an issue while processing a request.\n\nPlease notify an administrator.")
end
end
end
Telegram::Bot::Client.run(@token) do |bot|
bot.listen do |message| bot.listen do |message|
#pp message #pp message
validation = validate_incoming_data(message) validation = validate_incoming_data(message)
#puts "DEBUG: #{validation}" #puts "DEBUG: #{validation}"
if validation if validation
reply = handle_message(message) #Change message.from.username to something we can call the user. This makes referring to the user in replies much easier.
if reply == "dance" || reply == "flex" if ! message.from.username.nil? #Username -> @Username
bot.api.sendVideo(chat_id: message.chat.id, video: "https://img.skyfalltech.net/togra/#{reply}.gif") message.from.username = "@" + message.from.username
elsif ! message.text.nil? elsif ! message.from.first_name.nil? #Username -> John
bot.api.send_message(chat_id: message.chat.id, text: "#{reply}") message.from.username = message.from.first_name
end
#reply = handle_message(message)
#print timestamp + ": Sending ............ "
if ! message.text.nil?
#if reply == "dance" || reply == "flex"
# bot.api.sendVideo(chat_id: message.chat.id, video: "https://img.skyfalltech.net/togra/#{reply}.gif")
#else
## bot.api.send_message(chat_id: message.chat.id, text: "#{reply}")
## print "OK\n".green.bold
## puts "Sent: #{reply.inspect}\n\n"
case message
when Telegram::Bot::Types::Message
handle_message(message) #entrypoint for all messages
when Telegram::Bot::Types::CallbackQuery
handle_callback_query(message) #entrypoint for all callback queries
end
else
print 'FAIL'.red.bold
print " (Message is NULL)\n\n"
end end
STDOUT.flush STDOUT.flush
else else

@ -3,16 +3,17 @@
host=$1 host=$1
port=$2 port=$2
pass=$3 pass=$3
tmpfile=$4/.egsbot-stat
if nc -zvw3 $host $port 2>/dev/null; then if nc -zvw3 $host $port 2>/dev/null; then
./scripts/srvstatus.expect $host $port $pass > /tmp/.stat ./scripts/srvstatus.expect $host $port $pass > $tmpfile
grep -B1 -A8 Empyrion\ dedicated\ server /tmp/.stat | egrep -v Playfield\|Game\ seed grep -a -B1 -A8 Empyrion\ dedicated\ server $tmpfile | egrep -v Playfield\|Game\ seed
printf "\nOnline players:\n- - - - - - - - - - - - -" printf "\nOnline players:\n- - - - - - - - - - - - -"
sed -n '/Global\ online/,/Global\ players/p' /tmp/.stat | awk -F\= '{print $3}' | sed 's/....$//' sed -n '/Global\ online/,/Global\ players/p' $tmpfile | awk -F\= '{print $3}' | sed 's/....$//'
rm /tmp/.stat rm $tmpfile
exit 0 exit 0
else else
printf "Server is DOWN!" printf "Server is not responding to telnet requests!"
exit 1 exit 1
fi fi

@ -0,0 +1,45 @@
SkyfallTech EGS Telebot
Patch Notes:
v0.5.01
+ Added check to /srvstop to see if the server is even running first
* (Previously reported a successful shutdown even if the there was nothing running)
+ Added common aliases for /status command
+ Added an Easter egg command
v0.5.00
+ Added Voicechat information feature (/voice).
+ Rewrite of message handling based on Skyfall Heatbot.
v0.4.01
+ Better logging in cases where sending message fails.
v0.4.00
+ Better server logs, round 3.
* Vastly improved sanity check
* Timestamps, colours, user IDs
* Better STDOUT synchronization
+ Code efficiency improvements.
+ Fixed a few typos in responses.
+ Fixed possible "binary file" bug for /status command.
+ Added configurable tmp directory.
v0.3.03
+ Fixed 'server is up oops nevermind' condition in /status.
+ Fixed /whoami output formatting.
+ Fixed /whereareyou command.
* (previously relied on a now-broken Contegix service)
v0.3.02
+ Better server logs, round 2.
+ Less ambiguous patchnotes listing
* (These are for the bot, not for Empyrion)
v0.3.01
+ Better server logs, round 1.
v0.3.00
+ Auto self-resurrection after random bot-suicide.
+ This `/patchnotes` command.
+ Instant message confirmation for `/status` command.
Loading…
Cancel
Save