Skip to content

Instantly share code, notes, and snippets.

@jvanbaarsen
Created September 21, 2016 07:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jvanbaarsen/d60eb18fd27cbfb74ae0030759aedbad to your computer and use it in GitHub Desktop.
Save jvanbaarsen/d60eb18fd27cbfb74ae0030759aedbad to your computer and use it in GitHub Desktop.
Auto office joiner
#!/usr/bin/env ruby
# encoding: utf-8
require 'net/http'
require 'socket'
LAST_SEEN_TIME_OUT = 60 * 60 * 2 # 2 hours
ACCESS_TOKEN = "YOUR_ACCESS_TOKEN"
CHANNEL_ID = "YOUR_CHANNEL_ID"
CHANNEL_NAME="YOUR_CHANNEL_NAME"
TOKEN_OWNER = "SLACK_ID_OF_USER_THAT_OWNS_THE_TOKEN"
def current_ips
ips = []
raw_data = `nmap -sn #{ip_address}/24 | grep "scan report for" | awk '{print $5}'`
raw_data.each_line do |line|
ips << line.chomp
end
ips
end
def ip_address
ip = Socket.ip_address_list.detect{|intf| intf.ipv4_private?}
return if ip.nil?
ip.ip_address
end
def find_mac_for_ip(ip)
`arp -a | grep "(#{ip})" | awk '{print $4}'`.chomp.downcase
end
def known_devices
{
"e1:e5:c0:97:3d:0c" => "Jeroen",
"5d:2c:b1:62:d9:45" => "Bob",
"8f:70:a9:32:01:49" => "Michiel",
}
end
def users
{
"jeroen" => "xxx",
"bob" => "yyy",
"michiel" => "zzz",
}
end
def still_in_office?(last_seen)
return false if last_seen.nil?
# Is last seen within 4 hours
last_seen.to_i + (LAST_SEEN_TIME_OUT) > Time.now.to_i
end
def device_to_name(device_mac)
known_devices[device_mac] || "Unknown device: #{device_mac}"
end
def join_channel(user_token)
if user_token == TOKEN_OWNER
Net::HTTP.get(URI("https://slack.com/api/channels.join?token=#{ACCESS_TOKEN}&name=#{CHANNEL_NAME}"))
else
Net::HTTP.get(URI("https://slack.com/api/channels.invite?token=#{ACCESS_TOKEN}&channel=#{CHANNEL_ID}&user=#{user_token}"))
end
end
def leave_channel(user_token)
if user_token == TOKEN_OWNER
Net::HTTP.get(URI("https://slack.com/api/channels.leave?token=#{ACCESS_TOKEN}&channel=#{CHANNEL_ID}"))
else
Net::HTTP.get(URI("https://slack.com/api/channels.kick?token=#{ACCESS_TOKEN}&channel=#{CHANNEL_ID}&user=#{user_token}"))
end
end
@first_run ||= true
loop do
puts "=" * 20
@last_devices ||= {}
current_ips.each do |ip|
@last_devices[find_mac_for_ip(ip)] = Time.now
end
begin
if @first_run
p "Running on IP: #{ip_address}"
offline_devices = known_devices.reject { |device| @last_devices.include?(device) }
offline_devices.each do |device, name|
user_token = users[name.downcase]
leave_channel(user_token)
puts "#{name} was not in the office when the script started"
end
@first_run = false
end
@last_devices.each do |device, time|
unless known_devices.include?(device)
puts "Unknown device: #{device}"
next
end
user_token = users[device_to_name(device).downcase]
if user_token.nil?
puts "Unknown user: #{device_to_name(device).downcase} with device #{device}"
next
end
if still_in_office?(@last_devices[device])
join_channel(user_token)
puts "#{device_to_name(device)} is in the office"
else
@last_devices.delete(device)
leave_channel(user_token)
puts "#{device_to_name(device)} is not in the office"
end
end
rescue SocketError
puts "No network connection, retrying in 10 seconds"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment