#!/usr/bin/env ruby require 'rubygems' require 'yaml' require 'telegram/bot' require 'pp' require 'time' require_relative 'commands.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("bot_config.yaml") @botname = @conf['botname'] @tmpdir = @conf['tmpdir'] token = @conf['token'] admin = @conf['admin'] @auth_chat = @conf['authorized_chats'] @allowed_sources = @conf['allowed_sources'] ### Begin sanity check ### STDOUT.sync = true errcount = 0 puts "Checking if environment is sane...\n\n" 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? 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" @botname = "Bob" else print "OK\n".green.bold 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 administrators ................. " if admin.nil? 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" + "THIS SHOULD BE ADDRESSED. Continuing. (some commands will not be available)\n\n" admin = ["0"] else print "OK\n".green.bold end print "Checking authorized chats ............... " if @auth_chat.nil? 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 " + "functions.\nTHIS SHOULD BE ADDRESSED. Continuing. (some commands will not be available)\n\n" @auth_chat = ["0"] else print "OK\n".green.bold end 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 "Authorized administrator IDs: #{admin}" puts "Authorized chat IDs: #{@auth_chat}" puts "Bot token: #{token}" puts "Temporary direcotry: #{@tmpdir}" puts "Start time: " + timestamp + "\n\n\n\n" STDOUT.flush def handle_message(message) if ! message.reply_to_message.nil? then #drop message. Someone's replying to a message #sent by our bot message.text = nil return end if message.text.nil? # Find out if user(s) joined the group. If so, welcome them #if ! message.new_chat_members.nil? # handle_user_join(message) #else # #Handle non-messages and non-joins here #end return #so that we don't try to process this as a command (below) end #Format sender name if ! message.from.username.nil? message.from.username = "@" + message.from.username elsif ! message.from.first_name.nil? message.from.username = message.from.first_name end #Format command command = message.text.split(" ")[0].split("@")[0].downcase #Strip command from arguments and @tags reply = 'Empty String' adm = @conf['admin'] 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 when '/start' reply = "I am #{@botname}, and I am here to provide temperature information from various sensors. Currently I can retrieve information " + "from temperature sensors as well as report when temperatures are out of a specified range.\n\n" + "Commands available:\n/start (Shows this message)\n/check (Show temperatures, currently non-functional)\n/whoami or /chatinfo (Provides IDs for internal use)\n/whereareyou or /location (Provides hostname for bot server)\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/heatbot" 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 an administrator, I have not been authorized to participate in this group. My functionality is limited." end when '/patch', '/patchnotes' reply = process_command_patchnotes(message, command, adm) when '/location', '/whereareyou' 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 icanhazip.com 2>/dev/null`}" else reply = "I am not authorized to provide this information here." end when '/whoami', '/chatinfo' reply = "User ID: #{message.from.id}\nChat ID: #{message.chat.id}" when '/check' reply = process_command_check(message, command, adm) when '/pp', '/debug' pp message reply = "Confirmation: Message debug information sent to console." else reply = "Sorry, #{command} is not a valid command." end # Verbose output: puts timestamp + ": Sending #{reply.inspect}\n\n" STDOUT.flush return reply end Telegram::Bot::Client.run(token) do |bot| bot.listen do |message| #pp message validation = validate_incoming_data(message) #puts "DEBUG: #{validation}" if validation reply = handle_message(message) if ! message.text.nil? bot.api.send_message(chat_id: message.chat.id, text: "#{reply}") end STDOUT.flush else puts "Received bad data! [#{message.chat.type}]" puts validation STDOUT.flush end end end