Merge branch 'dev' of skyfall/heatbot into master

dev^2 v1.0.00
Aaron Johnson 6 years ago committed by Gitea
commit e90740bee6

@ -1,2 +1,108 @@
#HeatBot
A Ruby application to provide remote temperature probe data over Telegram, to groups or to individuals
-------------------------------------------------------------------------------
##Prerequisites
You will need the following packages on your **primary bot server**:
- nmap
- curl
- ruby
As well as these Ruby gems:
- telegram-bot-ruby
- yaml
- time
For each **remote temperature probe**:
- bc
- w1-gpio (kernel module)
- w1-therm (kernel module)
##Configuration
####bot_config.yaml
After cloning this git repo, the first thing you will want to do is copy `bot_config.yaml`.example to `bot_config.yaml` and edit the values. Below are the values with a description:
**botname:** The name of your bot. This is cosmetic, and does not alter any functions.
**tmpdir:** Temporary directory the bot will use when needed.
**token:** Private Bot token. Can be obtained from @botfather on Telegram.
**admin:** This is an array of admin users. Currently, there are no admin-only functions built into the bot at this time.
**authorized_chats:** These are the chat IDs (or user IDs for individual, non-group interaction) in which the bot is allowed to respond with any temperature or self-identifying information. User information will still be provided publicly by design, so you can use /chatinfo to find your own information you need to add to be authorized.
**allowed_sources:** These are the types of messages to allow. By default, all message types are allowed. It is recommended to leave this alone, but the option is there to restrict it further.
**units:** The default temperature unit. Heatbot supports Fahrenheit (F), Celsius (C), Rankine (R or Ra), and Kelvin (K).
**probes:** This is a "hash of hashes" that will identify each remote temperature probe, first by hostname to be used for the SSH connection (shq-example01), then `loc:` is the human-readable location (Server Room), and `port:` is the SSH port, default 22, which can be altered in case a non-standard SSH port is used for a particular probe.
####HeatBot systemd Service
In the repository, you will find `eample/services/heatbot.service`. Copy this into `/etc/systemd/system/` and edit the copy. Primarily, you will want to edit the username to the desired user to run the service (default is `ivo`, user must already exist), and be sure the working directory is pointing to your repository location. Please not that symlinks are perfectly valid for this purpose. Once in place, as with any other service, run:
```
systemctl daemon-reload
systemctl enable heatbot.service #Optional
```
At this time, the bot has not yet been started. By default, the bot will log to journald when run as a service. The bot's output is colour-coded, and by normal `journalctl` usage does not show up as intended. You can still read the logs this way, but it will be much easier if you use the `--output cat` flag with it. To be sure the bot is configured correctly, let's watch the log output during the first start:
```
systemctl start heatbot.service & journalctl --output cat -fu heatbot
```
Pay careful attention to the sanity check portion, and if anything comes up with a red FAIL instead of a green OK, address the issue and restart the service and check again.
####SSH Confgiuration (Recommendations)
There are many ways you can configure your SSH connections that will work. The bare minimum to function is that the following command must be valid to be run from the primary bot server, and return in Celsius the probe temperature:
```
ssh -p [port] [host] heatbot_gettemp
```
The way in which we have achieved this conveniently is by use of the bot server's `/etc/hosts` file and the bot service user's `~/.ssh/config` file. Let's take a look at an example set up. Let's say we are using a `bot_config.yaml` with the following `probes:` hash:
```
probes:
probe01:
loc: 'Server Room'
port: 22
probe02:
loc: 'Garage'
port: 22
```
Let's also say that these hosts, probe01 and probe02, use the respective IP addresses 10.0.0.1 and 10.0.0.2 and both probes have SSH set up for the user `heatbot`. The user that is running the service in our example is `ivo`. Under this topology, we would configure the bot server as such:
######/etc/hosts
```
10.0.0.1 probe01
10.0.0.2 probe02
```
######~ivo/.ssh/config
```
Host probe01
User heatbot
PasswordAuthentication no
PubKeyAuthentication yes
Host probe02
User heatbot
PasswordAuthentication no
PubKeyAuthentication yes
```
Next, you will want to be check your configuration by making sure your bot user can run the following commands, and succesffully retrieves the expected Celsius temperature value. **Please note:** __You will not be able to retrieve this info until the below__ Probe Configuration __section is completed.__
```
ssh -p 22 probe01 heatbot_gettemp
ssh -p 22 probe02 heatbot_gettemp
```
If all is set up well, you will simply receive a decimal number and nothing else.
####Probe Configuration
There are a large number of ways a remote probe can be configured, even outside of the intended operation. The included probe script is based on obtaining temperature readings from a DS18B20 probe connected to a Raspberry Pi. Let's assume this is the setup, and that you have basic working knowledge of setting up SSH keys and users. The following checklist should be sufficient to complete the setup:
- Add the following line to `/boot/config.txt`:
```
dtoverlay=w1-gpio,gpiopin=4
```
- Clone the git repo to each temperature probe host.
- Copy `probe_scripts/heatbot_gettemp` to a `$PATH` that is readable by the `heatbot` user, or whichever user you decide to use to interact with the probe. `/usr/bin/` is a good default location that is sure to be readily read and executed.
- Edit the copy, changing the configurable line to show the address of your temperature probe. This address will look like `28-[somehexnumbers]` as a symlink under `/sys/bus/w1/devices/` on the probe.
- Setup `~heatbot/.ssh/authorized_keys` to allow passwordless SSH from the primary bot server's service user.
If all is in order, you should be abel to run locally on the probe the `heatbot_gettemp` command from the heatbot user, which will return a decimal number.
A secondary test would be to attempt the test from the above section, and test running the script remotely from the primary bot server, using, for example:
```
ssh -p 22 probe01 heatbot_gettemp
```
## Setup Complete
If anything appears to be missing or needs further clarification, drop us a note and we can get the documentation updated.

@ -9,4 +9,14 @@ allowed_sources:
- 'private'
- 'group'
- 'supergroup'
units: 'F'
probes:
srv1:
loc: 'Office'
port: 22
srv2:
loc: 'Area 50.1'
port: 22
srv3:
loc: 'Dungeon'
port: 22

@ -0,0 +1,14 @@
def process_callback_zone(message)
host = message.data.split("|")[1]
#zone = @probes[host].values.first
zone = @probes[host].select { |k,v| k == 'loc' }
zone = zone["loc"]
puts "Selected: #{zone}"
port = @probes[host].select { |k,v| k == 'port' }
port = port["port"]
#print " Port: #{port}\n"
tdata = process_tdata(host, port)
#puts "Selected: #{zone} [#{tdata}]"
send_message(message.message.chat.id, "#{zone}: #{tdata}")
STDOUT.flush
end

@ -25,21 +25,94 @@ def is_chat_authorized?(message, auth_chat)
end
end
def process_command_start(message, command, adm)
reply = "I am #{@botname}, and I am here to provide temperature information from various sensors. Currently I can retrieve information " +
"from temperature sensors. In a future version, I will also report when temperatures are out of a specified range through regular checks.\n\n" +
"Commands available:\n/start (Shows this message)\n/check or /c (Show a specific temperature interactively)\n/report or /r (Show all temperatures)\n" +
"/simple or /s (Show a simplified report)\n\nExtra functions:\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
send_message(message.chat.id, reply)
end
def process_command_patchnotes(message, command, adm)
if is_chat_authorized?(message, @auth_chat) || message_from_admin?(message, adm)
reply = `cat patchnotes.txt`
reply = File.read("static_text/patchnotes.txt")
else
reply = "I am not authorized to provide this information here."
end
return reply
send_message(message.chat.id, reply)
end
def process_command_check(message, command, adm)
def process_command_location(message, command, adm)
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 #{@ip_provider} 2>/dev/null`}"
else
reply = "I am not authorized to provide this information here."
end
#send_message_markdown(message.chat.id, reply)
send_message(message.chat.id, reply)
end
def process_command_chatinfo(message)
reply = "User ID: #{message.from.id}\nChat ID: #{message.chat.id}"
send_message(message.chat.id, reply)
end
def process_command_check(message, command, adm, simple=false)
if is_chat_authorized?(message, @auth_chat) || message_from_admin?(message, adm)
reply = `cat fakeoutput.txt`
else
reply = "I am not authorized to provide this information here."
end
return reply
#begin interactive code
options = [ ]
@probes.each do |k,v|
puts " Option: #{k} is #{v["loc"].to_s}"
button_text = v["loc"].to_s
options.insert(-1, Telegram::Bot::Types::InlineKeyboardButton.new(text: button_text, callback_data: "ZONE|#{k}"))
end
message_text = "Which area would you like to check?\n"
send_question(message.chat.id, message_text, options)
#end interactive code
else
send_message(message.chat.id,"I am not authorized to provide this information here.")
end
end
def process_command_report(message, command, adm, simple=false)
if is_chat_authorized?(message, @auth_chat) || message_from_admin?(message, adm)
if !simple
confirmation = send_message(message.chat.id,"Generating full report... Please wait.")
report = "Full Report:\n\n"
else
confirmation = send_message(message.chat.id,"Generating simple report... Please wait.")
report = "Simple Report:\n\n"
end
@probes.each do |k,v|
zone = v["loc"].to_s
port = v["port"].to_s
host = k
tdata = process_tdata(host, port, simple)
report = report + "#{zone}: #{tdata}\n"
STDOUT.flush
end
send_message(message.chat.id,report)
#delete_message(confirmation)
#delete_confirmation(confirmation)
else
send_message(message.chat.id,"I am not authorized to provide this information here.")
end
end

@ -1,5 +0,0 @@
SkyfallTech HeatBot
Patch Notes:
v0.1.00
+ Starting from a fork of the Skyfall EGS-Bot v0.4.00

@ -0,0 +1,14 @@
#!/usr/bin/env sh
#Modify this to point to your temperature probe
dir=/sys/bus/w1/devices/[some-hexadecimals]
# DO NOT MODIFY
# Sanity check
which bc 2>&1 >/dev/null || { echo "PROBE ERROR: 'bc' not found. Please install bc." >&2; exit 1; }
# Retrieve temperature in Celsius
raw=$(grep 't=' $dir/w1_slave | awk -F'=' '{print $2}')
echo "scale=3; ${raw}/1000" | bc -l && exit 0
exit 1

@ -0,0 +1,8 @@
#/usr/bin/env sh
# Symlink this script to heatbot_gettemp if you need to test a probe's connection
# without retrieving real temperature numbers. This is useful in setup such as before
# the sensor hardware is available to use.
echo $((-20 + $RANDOM % 60)).$((10 + $RANDOM % 89)) || exit 1
exit 0

356
run.rb

@ -6,6 +6,7 @@ require 'telegram/bot'
require 'pp'
require 'time'
require_relative 'commands.rb'
require_relative 'callbacks.rb'
require_relative 'colors.rb'
def timestamp
@ -16,19 +17,40 @@ end
@conf = YAML.load_file("bot_config.yaml")
@botname = @conf['botname']
@tmpdir = @conf['tmpdir']
token = @conf['token']
@token = @conf['token']
admin = @conf['admin']
@auth_chat = @conf['authorized_chats']
@allowed_sources = @conf['allowed_sources']
@probes = @conf['probes']
@tunit = @conf['units']
## Non-configurable
@simplehot = 24
@simplecold = 10
@ip_provider = "ip.skyfall.tech"
### Begin sanity check ###
STDOUT.sync = true
errcount = 0
puts "Checking if environment is sane...\n\n"
print "Checking bot token ...................... "
if token.nil?
print "Checking system utilities ............... "
if !system("which nmap 2>&1 >/dev/null")
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..."
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")
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)
else
print "OK\n".green.bold
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
@ -98,37 +120,222 @@ if @auth_chat.nil?
else
print "OK\n".green.bold
end
print "Checking temperature units .............. "
if @tunit.nil?
errcount += 1
print "FAIL!\n\n".red.bold
puts "Error(#{errcount.to_s}): Temperature units not configured! Defaulting to Rankine. Continuing...\n\n"
@tunit = 'R'
else
case @tunit.upcase
when "C", "F", "K", "R", "RA"
@tunit = @tunit.capitalize
print "OK\n".green.bold
else
errcount += 1
print "FAIL!\n\n".red.bold
puts "Error(#{errcount.to_s}): Temperature unit '#{@tunit}' not recognized! Defaulting to Rankine. Continuing...\n\n"
@tunit = 'R'
end
end
print "Checking probes list .................... "
if @probes.nil?
errcount += 1
print "FAIL!\n\n".red.bold
puts "Error(#{errcount.to_s}): No temperature probes configured! Bot will serve no purpose. Continuing anyway...\n\n"
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 "Bot token: #{@token}"
puts "Temporary direcotry: #{@tmpdir}"
puts "Temperature unit: #{@tunit}"
puts "Probes loaded:"
@probes.each do |k,v|
#puts " [#{k}] #{v["loc"].to_s}"
puts " [" + "#{k}: ".bold + v['port'].to_s.green.bold + "] #{v['loc'].to_s}"
end
puts "Start time: " + timestamp + "\n\n\n\n"
STDOUT.flush
## Constant collection model (may be scrapped)
#last_collection = 0
#loop do
# collection_time = Time.now
# if collection_time - last_collection >= 10
# puts timestamp + ": [#{collection_time}] Updating records //Not really"
# last_collection = collection_time
# STDOUT.flush
# end
#end
def host_lookup(select_loc)
return @probes.select { |k,v| v['loc'] == select_loc }
end
class String
def is_integer?
/\A[-+]?\d+\z/ === self
end
def is_float?
/^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/ === self
end
end
def process_tdata(host, port, simple=false)
print "Processing #{host}: "
STDOUT.flush
if system("nmap #{host} -p #{port} 2>&1 | grep #{port} | grep open >/dev/null")
tdata = `ssh -p #{port} -oBatchMode=yes #{host} heatbot_gettemp`.chomp
#if tdata.is_integer?
if tdata.is_float?
tdf = tdata.to_f
case @tunit.upcase
when "C"
#Do nothing; expected input is Celsius
when "F"
tdf = (tdf * 1.8) + 32
when "K"
tdf = tdf + 273.15
when "R", "RA"
tdf = (tdf * 1.8) + 491.67
else
puts "#{@tunit} not valid temperature unit! Submitting unmodified output!"
end
ctdata = tdf.round.to_s
print ctdata + "°#{@tunit}" + " (" + "Raw: ".bold + "#{tdata})"
if simple #This is mostly just an Easter egg
if tdata.to_i > @simplehot
sdata = "Hot"
elsif tdata.to_i < @simplecold
sdata = "Cold"
else
sdata = "Fair"
end
print " [#{sdata}]\n"
STDOUT.flush
return sdata
else
print "\n"
STDOUT.flush
return ctdata + "°#{@tunit}"
end
else
puts "Unexpected output from [".red.bold + host.bold + "]: ".red.bold + tdata
STDOUT.flush
return "CHECK PROBE"
end
else
print "OFFLINE\n"
STDOUT.flush
return "OFFLINE"
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
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") }
#puts timestamp + ": Sent: #{message_text.inspect}\n\n"
return message
else
#Send a plain-text message
message = Telegram::Bot::Client.run(@token) {|bot| bot.api.send_message(chat_id: chatid, text: message_text) }
puts timestamp + ": Sent: #{message_text.inspect}\n\n"
#puts message
#message = message["results"]
#puts message
return message
end
STDOUT.flush
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)
if ! message.reply_to_message.nil? then
#drop message. Someone's replying to a message
#sent by our bot
#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
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
@ -144,64 +351,111 @@ def handle_message(message)
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
puts timestamp + ": 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)
process_command_start(message, command, adm)
when '/patch', '/patchnotes', '/version', '/versioninfo'
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
process_command_location(message, command, adm)
when '/whoami', '/chatinfo'
reply = "User ID: #{message.from.id}\nChat ID: #{message.chat.id}"
when '/check'
reply = process_command_check(message, command, adm)
process_command_chatinfo(message)
when '/check', '/c'
process_command_check(message, command, adm)
when '/report', '/r'
process_command_report(message, command, adm)
#when '/simple', '/s', '/sc'
# process_command_check(message, command, adm, true)
#when '/sreport', '/simpler', '/simplereport', '/sr'
when '/simple', '/s', '/sreport', '/simpler', '/simplereport', '/sr'
process_command_report(message, command, adm, true)
when '/pp', '/debug'
pp message
reply = "Confirmation: Message debug information sent to console."
send_message(message.chat.id"Confirmation: Message debug information sent to console.")
else
reply = "Sorry, #{command} is not a valid command."
send_message(message.chat.id,"Sorry, #{command} is not a valid command.")
end
rescue => e
handle_exception(e, message, true)
# Verbose output:
puts timestamp + ": Sending #{reply.inspect}\n\n"
#print timestamp + ": Sending #{reply.inspect} ..... "
STDOUT.flush
return reply
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
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|
#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}")
#Change message.from.username to something we can call the user. This makes referring to the user in replies much easier.
if ! message.from.username.nil? #Username -> @Username
#message.from.username = "@" + message.from.username
elsif ! message.from.first_name.nil? #Username -> John
message.from.username = message.from.first_name
end
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
STDOUT.flush
else
puts "Received bad data! [#{message.chat.type}]"
puts validation

@ -0,0 +1,5 @@
SkyfallTech HeatBot
Patch Notes:
v0.1.00
+ Initial Release
Loading…
Cancel
Save