benevolent_gaze 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +112 -0
  6. data/Rakefile +2 -0
  7. data/benevolent_gaze.gemspec +35 -0
  8. data/bin/benevolent_gaze +5 -0
  9. data/frontend/.gitignore +15 -0
  10. data/frontend/Gemfile +21 -0
  11. data/frontend/Gemfile.lock +162 -0
  12. data/frontend/config.rb +56 -0
  13. data/frontend/data/site.yml +4 -0
  14. data/frontend/source/images/.gitkeep +0 -0
  15. data/frontend/source/images/board@1x.png +0 -0
  16. data/frontend/source/images/city@1x.png +0 -0
  17. data/frontend/source/images/complete_left_panel@1x.png +0 -0
  18. data/frontend/source/images/icon_password@1x.png +0 -0
  19. data/frontend/source/images/icon_wifi@1x.png +0 -0
  20. data/frontend/source/images/logo@1x.png +0 -0
  21. data/frontend/source/images/pin_rope@1x.png +0 -0
  22. data/frontend/source/images/register@2x.png +0 -0
  23. data/frontend/source/images/sky@1x.png +0 -0
  24. data/frontend/source/images/sky_register@1x.png +0 -0
  25. data/frontend/source/images/sun@1x.png +0 -0
  26. data/frontend/source/images/tape_left@1x.png +0 -0
  27. data/frontend/source/images/tape_right@1x.png +0 -0
  28. data/frontend/source/images/thanks@2x.png +0 -0
  29. data/frontend/source/images/uploads/info.txt +1 -0
  30. data/frontend/source/images/visitor_art@1x.png +0 -0
  31. data/frontend/source/images/welcome@1x.png +0 -0
  32. data/frontend/source/index.html.haml +33 -0
  33. data/frontend/source/javascripts/all.js +161 -0
  34. data/frontend/source/layouts/layout.haml +23 -0
  35. data/frontend/source/register.html.haml +21 -0
  36. data/frontend/source/stylesheets/animate.css.scss +3176 -0
  37. data/frontend/source/stylesheets/application.css.scss +291 -0
  38. data/frontend/source/thanks.html.haml +8 -0
  39. data/kiosk/.env +7 -0
  40. data/kiosk/Procfile +2 -0
  41. data/kiosk/public/fonts/bootstrap/glyphicons-halflings-regular-22037a34.woff +0 -0
  42. data/kiosk/public/fonts/bootstrap/glyphicons-halflings-regular-66b1fc67.svg +229 -0
  43. data/kiosk/public/fonts/bootstrap/glyphicons-halflings-regular-aafafdc0.ttf +0 -0
  44. data/kiosk/public/fonts/bootstrap/glyphicons-halflings-regular-f3a9a3b6.eot +0 -0
  45. data/kiosk/public/images/board@1x-b5fb87e5.png +0 -0
  46. data/kiosk/public/images/city@1x-22396032.png +0 -0
  47. data/kiosk/public/images/complete_left_panel@1x-7dec25da.png +0 -0
  48. data/kiosk/public/images/icon_password@1x-fb34b974.png +0 -0
  49. data/kiosk/public/images/icon_wifi@1x-e92e9c20.png +0 -0
  50. data/kiosk/public/images/logo@1x-927932fa.png +0 -0
  51. data/kiosk/public/images/pin_rope@1x-f5912856.png +0 -0
  52. data/kiosk/public/images/register@2x-328082c6.png +0 -0
  53. data/kiosk/public/images/sky@1x-47babe39.png +0 -0
  54. data/kiosk/public/images/sky_register@1x-cd96f779.png +0 -0
  55. data/kiosk/public/images/sun@1x-4f644bff.png +0 -0
  56. data/kiosk/public/images/tape_left@1x-9f3af6c1.png +0 -0
  57. data/kiosk/public/images/tape_right@1x-646752c4.png +0 -0
  58. data/kiosk/public/images/thanks@2x-694b424f.png +0 -0
  59. data/kiosk/public/images/uploads/info.txt +1 -0
  60. data/kiosk/public/images/visitor_art@1x-21d82dcb.png +0 -0
  61. data/kiosk/public/images/welcome@1x-7d17fbb9.png +0 -0
  62. data/kiosk/public/index.html +74 -0
  63. data/kiosk/public/javascripts/all-eb365891.js +12256 -0
  64. data/kiosk/public/register.html +52 -0
  65. data/kiosk/public/stylesheets/animate-31203878.css +6 -0
  66. data/kiosk/public/stylesheets/application-70841e1d.css +1 -0
  67. data/kiosk/public/thanks.html +36 -0
  68. data/lib/benevolent_gaze/bgapp.rb +39 -0
  69. data/lib/benevolent_gaze/cli.rb +153 -0
  70. data/lib/benevolent_gaze/kiosk.rb +164 -0
  71. data/lib/benevolent_gaze/kiosk_bak.rb +164 -0
  72. data/lib/benevolent_gaze/tracker.rb +87 -0
  73. data/lib/benevolent_gaze/version.rb +3 -0
  74. data/lib/benevolent_gaze.rb +5 -0
  75. data/website/.gitignore +18 -0
  76. data/website/Gemfile +20 -0
  77. data/website/Gemfile.lock +151 -0
  78. data/website/config.rb +58 -0
  79. data/website/data/site.yml +4 -0
  80. data/website/source/CNAME +1 -0
  81. data/website/source/fonts/OpenSans-Regular-webfont.eot +0 -0
  82. data/website/source/fonts/OpenSans-Regular-webfont.svg +1831 -0
  83. data/website/source/fonts/OpenSans-Regular-webfont.ttf +0 -0
  84. data/website/source/fonts/OpenSans-Regular-webfont.woff +0 -0
  85. data/website/source/fonts/Oswald-Bold.eot +0 -0
  86. data/website/source/fonts/Oswald-Bold.svg +0 -0
  87. data/website/source/fonts/Oswald-Bold.ttf +0 -0
  88. data/website/source/fonts/Oswald-Bold.woff +0 -0
  89. data/website/source/fonts/Oswald-Light.eot +0 -0
  90. data/website/source/fonts/Oswald-Light.svg +0 -0
  91. data/website/source/fonts/Oswald-Light.ttf +0 -0
  92. data/website/source/fonts/Oswald-Light.woff +0 -0
  93. data/website/source/fonts/Oswald-Regular.eot +0 -0
  94. data/website/source/fonts/Oswald-Regular.svg +0 -0
  95. data/website/source/fonts/Oswald-Regular.ttf +0 -0
  96. data/website/source/fonts/Oswald-Regular.woff +0 -0
  97. data/website/source/fonts/TradeGothic-BoldCondTwenty.eot +0 -0
  98. data/website/source/fonts/TradeGothic-BoldCondTwenty.svg +0 -0
  99. data/website/source/fonts/TradeGothic-BoldCondTwenty.ttf +0 -0
  100. data/website/source/fonts/TradeGothic-BoldCondTwenty.woff +0 -0
  101. data/website/source/fonts/TradeGothic-CondEighteen.eot +0 -0
  102. data/website/source/fonts/TradeGothic-CondEighteen.svg +0 -0
  103. data/website/source/fonts/TradeGothic-CondEighteen.ttf +0 -0
  104. data/website/source/fonts/TradeGothic-CondEighteen.woff +0 -0
  105. data/website/source/fonts/telegrafico_by_ficod-webfont.eot +0 -0
  106. data/website/source/fonts/telegrafico_by_ficod-webfont.svg +95 -0
  107. data/website/source/fonts/telegrafico_by_ficod-webfont.ttf +0 -0
  108. data/website/source/fonts/telegrafico_by_ficod-webfont.woff +0 -0
  109. data/website/source/images/.gitkeep +0 -0
  110. data/website/source/images/gaze.png +0 -0
  111. data/website/source/images/splash/accessorized_badge@2x.png +0 -0
  112. data/website/source/images/splash/benevolent_gaze_icon@2x.png +0 -0
  113. data/website/source/images/splash/benevolent_gaze_logo@2x.png +0 -0
  114. data/website/source/images/splash/benevolent_gaze_logo_color@2x.png +0 -0
  115. data/website/source/images/splash/benevolent_gaze_text@2x.png +0 -0
  116. data/website/source/images/splash/brackets.png +0 -0
  117. data/website/source/images/splash/checkmark.png +0 -0
  118. data/website/source/images/splash/circle_for_logo@2x.png +0 -0
  119. data/website/source/images/splash/cloud_cover@2x.png +0 -0
  120. data/website/source/images/splash/clouds.png +0 -0
  121. data/website/source/images/splash/complete_badge@2x.png +0 -0
  122. data/website/source/images/splash/down_arrow.png +0 -0
  123. data/website/source/images/splash/easy_badge@2x.png +0 -0
  124. data/website/source/images/splash/faded-clouds.png +0 -0
  125. data/website/source/images/splash/github_banner@2x.png +0 -0
  126. data/website/source/images/splash/hero_bkg.png +0 -0
  127. data/website/source/images/splash/left-bracket.png +0 -0
  128. data/website/source/images/splash/more-awesome-stuff.png +0 -0
  129. data/website/source/images/splash/overbracket.png +0 -0
  130. data/website/source/images/splash/rainbow@2x.png +0 -0
  131. data/website/source/images/splash/rainbow_banner@2x.png +0 -0
  132. data/website/source/images/splash/right-bracket.png +0 -0
  133. data/website/source/images/splash/seed-logo-color.png +0 -0
  134. data/website/source/images/splash/seed-logo.png +0 -0
  135. data/website/source/images/splash/sensible-defaults.png +0 -0
  136. data/website/source/images/splash/single_check@2x.png +0 -0
  137. data/website/source/images/splash/sky_background.png +0 -0
  138. data/website/source/images/splash/solid-gems.png +0 -0
  139. data/website/source/images/splash/ted.png +0 -0
  140. data/website/source/images/splash/ted_on_unicorn@2x.png +0 -0
  141. data/website/source/images/splash/view-me-on-github.png +0 -0
  142. data/website/source/index.html.haml +181 -0
  143. data/website/source/javascripts/all.js +3 -0
  144. data/website/source/javascripts/modernizr.js +1406 -0
  145. data/website/source/javascripts/scrollReveal.js +398 -0
  146. data/website/source/layouts/_footer.html.haml +34 -0
  147. data/website/source/layouts/_javascripts.erb +9 -0
  148. data/website/source/layouts/docs_layout.haml +23 -0
  149. data/website/source/layouts/layout.haml +87 -0
  150. data/website/source/stylesheets/animate.css +3158 -0
  151. data/website/source/stylesheets/application.css.scss +534 -0
  152. data/website/source/stylesheets/fonts/socicon-webfont.eot +0 -0
  153. data/website/source/stylesheets/fonts/socicon-webfont.svg +90 -0
  154. data/website/source/stylesheets/fonts/socicon-webfont.ttf +0 -0
  155. data/website/source/stylesheets/fonts/socicon-webfont.woff +0 -0
  156. data/website/source/stylesheets/socicons.css +124 -0
  157. metadata +382 -0
@@ -0,0 +1,153 @@
1
+ require 'thor'
2
+ require 'thor/actions'
3
+ require 'csv'
4
+ require 'benevolent_gaze/kiosk'
5
+ require 'benevolent_gaze/tracker'
6
+
7
+ include FileUtils
8
+
9
+ module BenevolentGaze
10
+ class Cli < Thor
11
+ include Thor::Actions
12
+ source_root File.expand_path("../../../kiosk", __FILE__)
13
+
14
+ desc "kiosk", "Start up the sinatra app that displays the users"
15
+ def kiosk
16
+ BenevolentGaze::Kiosk.run!
17
+ end
18
+
19
+ desc "tracker", "Start up the tracking daemon that looks at the network"
20
+ def tracker
21
+ BenevolentGaze::Tracker.run!
22
+ end
23
+
24
+ desc "add_user device name image", "Add single user's device name, name and image"
25
+ long_desc <<-LONGDESC
26
+ This command takes a user's device name, real name and image url and maps them
27
+ so that Benevolent Gaze can use the information when they log onto your network.
28
+ LONGDESC
29
+
30
+ def add_user(device_name, name, image_url)
31
+ `redis-cli set "name:#{device_name}" "#{name}"`
32
+ `redis-cli set "image:#{name}" "#{image_url}"`
33
+ end
34
+
35
+ desc "assign_users", "This will prompt you for each current user without an associated name so that you can assign one."
36
+ def assign_users
37
+ # users = `redis-cli hgetall "current_devices"`.split("\n")
38
+ require 'redis'
39
+ redis = Redis.new
40
+ users = redis.hgetall "current_devices"
41
+
42
+ puts "Right now, these are the devices on your network"
43
+ users.each { |u,v| puts " #{u}" }
44
+
45
+ users.each do |u, val|
46
+ val = redis.get "name:#{u}"
47
+ if val.nil? || val.empty?
48
+ puts "Do you know whose device this is #{u}? ( y/n )"
49
+ response = $stdin.gets.chomp.strip
50
+ if response == "y"
51
+ puts "Please enter their name."
52
+ name_response = $stdin.gets.chomp.strip
53
+ redis.set "name:#{u}", "#{name_response}"
54
+ # `redis-cli set "name:#{u}" "#{name_response}"`
55
+
56
+ puts "Do you have an image for this user? ( y/n )"
57
+ image_response = $stdin.gets.chomp.strip
58
+ if image_response == "y"
59
+ puts "Please enter the image url."
60
+ image_url_response = $stdin.gets.chomp.strip
61
+ redis.set "image:#{name_response}", image_url_response
62
+ end
63
+ end
64
+ else
65
+ puts "#{Thor::Shell::Color::MAGENTA}#{u} looks like it has a name already associated with them.#{Thor::Shell::Color::CLEAR}"
66
+ end
67
+ end
68
+ self.bg_flair
69
+ end
70
+
71
+ desc "dump_csv [FILENAME]", "This dumps the current_devices"
72
+ def dump_csv( filename )
73
+ require 'redis'
74
+ redis = Redis.new
75
+ users = redis.hgetall "current_devices"
76
+ CSV.open( filename, "wb" ) do |out|
77
+ users.each do |device, name|
78
+ name = redis.get "name:#{device}"
79
+ image = redis.get "image:#{name}"
80
+ out << [device,name,image]
81
+ end
82
+ end
83
+ self.bg_flair
84
+ puts "#{filename} created"
85
+ end
86
+
87
+ desc "bulk_assign yourcsv.csv", "This takes a csv file as an argument formated in the following way. device_name, real_name, image_url"
88
+ def bulk_assign(csv_path)
89
+ CSV.foreach(csv_path) do |row|
90
+ puts "Loading device info for #{row[0]} -> #{row[1]}"
91
+ device_name = row[0]
92
+ real_name = row[1]
93
+ image_url = row[2]
94
+
95
+ unless real_name.nil? || real_name.empty?
96
+ `redis-cli set "name:#{device_name}" "#{real_name}"`
97
+ end
98
+
99
+ unless image_url.nil? || image_url.empty?
100
+ `redis-cli set "image:#{real_name}" "#{image_url}"`
101
+ end
102
+ end
103
+ # puts `redis-cli keys "*"`
104
+ puts "#{Thor::Shell::Color::MAGENTA}The CSV has now been added.#{Thor::Shell::Color::CLEAR}"
105
+ self.bg_flair
106
+ end
107
+
108
+ desc "install wifi_username, wifi_password", "This commands installs the necessary components in the gem and pulls the assets into a local folder so that you can save to your local file system if you do not want to use s3 and also enables you to customize your kiosk."
109
+ def install(uname, pass)
110
+ directory ".", "bg_public"
111
+ env_file = "bg_public/.env"
112
+ new_path = File.expand_path("./bg_public")
113
+ gsub_file(env_file, /.*PUBLIC_FOLDER.*/, "PUBLIC_FOLDER=\"#{new_path}/public\"")
114
+ gsub_file("bg_public/public/index.html", "happyfuncorp3", uname)
115
+ gsub_file("bg_public/public/index.html", "happiness4u", pass)
116
+ puts <<-CUSTOMIZE
117
+
118
+ #{Thor::Shell::Color::MAGENTA}**************************************************#{Thor::Shell::Color::CLEAR}
119
+
120
+ Generated the bg_public folder where you should go to customize images and to run
121
+
122
+ ```foreman start```
123
+
124
+ Please modify the .env file with the relevant information mentioned in the README.
125
+
126
+ You can now customize your kiosk, by switching out the graphics in the images folder.
127
+ Please replace the images with the images of the same size.
128
+
129
+ Uploaded images will save to your local filesystem if you do not supply AWS creds.
130
+
131
+ #{Thor::Shell::Color::MAGENTA}**************************************************#{Thor::Shell::Color::CLEAR}
132
+ CUSTOMIZE
133
+
134
+ self.bg_flair
135
+ end
136
+
137
+ desc "bg_flair prints Benevolent Gaze in ascii art letters, because awesome.", "This command prints Benevolent Gaze in ascii art letters, because...um...well...it's cool looking!"
138
+ def bg_flair
139
+ @bg = <<-BG
140
+ #{Thor::Shell::Color::CYAN}
141
+ ____ _ _ _____
142
+ | _ \\ | | | | / ____|
143
+ | |_) | ___ _ __ _____ _____ | | ___ _ __ | |_ | | __ __ _ _______
144
+ | _ < / _ \\ '_ \\ / _ \\ \\ / / _ \\| |/ _ \\ '_ \\| __| | | |_ |/ _` |_ / _ \\
145
+ | |_) | __/ | | | __/\\ V / (_) | | __/ | | | |_ | |__| | (_| |/ / __/
146
+ |____/ \\___|_| |_|\\___| \\_/ \\___/|_|\\___|_| |_|\\__| \\_____|\\__,_/___\\___|
147
+
148
+ #{Thor::Shell::Color::CLEAR}
149
+ BG
150
+ puts @bg
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,164 @@
1
+ require 'json'
2
+ require 'sinatra/base'
3
+ require 'sinatra/support'
4
+ require 'sinatra/json'
5
+ require 'redis'
6
+ require 'resolv'
7
+ require 'sinatra/cross_origin'
8
+ require 'aws/s3'
9
+ require 'SecureRandom'
10
+ require 'mini_magick'
11
+
12
+ Encoding.default_external = 'utf-8' if defined?(::Encoding)
13
+
14
+ module BenevolentGaze
15
+ class Kiosk < Sinatra::Base
16
+ set server: 'thin', connections: []
17
+ set :bind, '0.0.0.0'
18
+ set :app_file, __FILE__
19
+ set :port, ENV['IPORT']
20
+ set :static, true
21
+ set :public_folder, ENV['PUBLIC_FOLDER'] || "public"
22
+ @@local_file_system = ENV['PUBLIC_FOLDER']
23
+
24
+ register Sinatra::CrossOrigin
25
+
26
+ configure do
27
+ unless ENV['AWS_ACCESS_KEY_ID'].nil? || ENV['AWS_ACCESS_KEY_ID'].empty? || ENV['AWS_SECRET_ACCESS_KEY'].empty? || ENV['AWS_CDN_BUCKET'].empty?
28
+ USE_AWS = true
29
+ else
30
+ USE_AWS = false
31
+ end
32
+ end
33
+
34
+ helpers do
35
+ def upload(filename, file, device_name)
36
+ doomsday = Time.mktime(2038, 1, 18).to_i
37
+ if (filename)
38
+ new_file_name = device_name.to_s + SecureRandom.uuid.to_s + filename
39
+ bucket = ENV['AWS_CDN_BUCKET']
40
+ image = MiniMagick::Image.open(file.path)
41
+
42
+ animated_gif = `identify -format "%n" "#{file.path}"`.to_i > 1
43
+ if animated_gif
44
+ image.repage "0x0"
45
+ if image.height > image.width
46
+ image.resize "300"
47
+ offset = (image.height/2) - 150
48
+ image.crop("300x300+0+#{offset}")
49
+ else
50
+ image.resize "x300"
51
+ offset = (image.width/2) - 150
52
+ image.crop("300x300+#{offset}+0")
53
+ end
54
+ image << "+repage"
55
+ else
56
+ image.auto_orient
57
+ if image.height > image.width
58
+ image.resize "300"
59
+ offset = (image.height/2) - 150
60
+ image.crop("300x300+0+#{offset}")
61
+ else
62
+ image.resize "x300"
63
+ offset = (image.width/2) - 150
64
+ image.crop("300x300+#{offset}+0")
65
+ end
66
+ image.format "png"
67
+ end
68
+
69
+ if USE_AWS
70
+ AWS::S3::Base.establish_connection!(
71
+ :access_key_id => ENV['AWS_ACCESS_KEY_ID'],
72
+ :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
73
+ )
74
+ AWS::S3::S3Object.store(
75
+ new_file_name,
76
+ image.to_blob,
77
+ bucket,
78
+ :access => :public_read
79
+ )
80
+ image_url = AWS::S3::S3Object.url_for( new_file_name, bucket, :expires => doomsday )
81
+ else
82
+ upload_path = @@local_file_system + '/images/uploads/'
83
+ file_on_disk = upload_path + new_file_name
84
+ File.open(File.expand_path(file_on_disk), "w") do |f|
85
+ f.write(image.to_blob)
86
+ end
87
+ image_url = "images/uploads/" + new_file_name
88
+ end
89
+
90
+ return image_url
91
+
92
+ else
93
+ return nil
94
+ end
95
+ end
96
+ end
97
+
98
+ get "/" do
99
+ redirect "index.html"
100
+ end
101
+
102
+ post "/register" do
103
+ dns = Resolv.new
104
+ device_name = dns.getname(request.ip)
105
+ r = Redis.new
106
+
107
+ compound_name = nil
108
+
109
+ if !params[:real_first_name].empty? || !params[:real_last_name].empty?
110
+ compound_name = "#{params[:real_first_name].to_s.strip} #{params[:real_last_name].to_s.strip}"
111
+ r.set("name:#{device_name}", compound_name)
112
+ end
113
+ if params[:fileToUpload]
114
+ image_url_returned_from_upload_function = upload(params[:fileToUpload][:filename], params[:fileToUpload][:tempfile], device_name)
115
+ name_key = "image:" + (compound_name || r.get("name:#{device_name}") || device_name)
116
+ r.set(name_key, image_url_returned_from_upload_function)
117
+ end
118
+ redirect "thanks.html"
119
+ end
120
+
121
+ get "/register" do
122
+ redirect "register.html"
123
+ end
124
+
125
+ get "/feed", provides: 'text/event-stream' do
126
+ cross_origin
127
+ r = Redis.new
128
+
129
+ stream :keep_open do |out|
130
+ loop do
131
+ if out.closed?
132
+ break
133
+ end
134
+ data = []
135
+ r.hgetall("current_devices").each do |k,v|
136
+ name_or_device_name = r.get("name:#{k}") || k
137
+ data << { device_name: k, name: v, last_seen: (Time.now.to_f * 1000).to_i, avatar: r.get("image:#{name_or_device_name}") }
138
+ end
139
+
140
+ out << "data: #{data.to_json}\n\n"
141
+ sleep 1
142
+ end
143
+ end
144
+ end
145
+
146
+ post "/information" do
147
+ #grab current devices on network. Save them to the devices on network key after we make sure that we grab the names that have been added already to the whole list and then save them to the updated hash for redis.
148
+ devices_on_network = JSON.parse(params[:devices])
149
+ r = Redis.new
150
+ old_set = r.hkeys("current_devices")
151
+ new_set = devices_on_network.keys
152
+ diff_set = old_set - new_set
153
+
154
+ diff_set.each do |d|
155
+ r.hdel("current_devices", d)
156
+ end
157
+
158
+ devices_on_network.each do |k,v|
159
+ r.hmset("current_devices", k, r.get("name:#{k}"))
160
+ end
161
+
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,164 @@
1
+ require 'json'
2
+ require 'sinatra/base'
3
+ require 'sinatra/support'
4
+ require 'sinatra/json'
5
+ require 'redis'
6
+ require 'resolv'
7
+ require 'sinatra/cross_origin'
8
+ require 'aws/s3'
9
+ require 'SecureRandom'
10
+ require 'mini_magick'
11
+
12
+ Encoding.default_external = 'utf-8' if defined?(::Encoding)
13
+
14
+ module BenevolentGaze
15
+ class Kiosk < Sinatra::Base
16
+ set server: 'thin', connections: []
17
+ set :bind, '0.0.0.0'
18
+ set :app_file, __FILE__
19
+ set :port, ENV['PORT']
20
+ set :static, true
21
+ set :public_folder, 'public'
22
+ @@local_file_system = "insert_local_file_system"
23
+
24
+ register Sinatra::CrossOrigin
25
+
26
+ configure do
27
+ unless ENV['AWS_ACCESS_KEY_ID'].empty? || ENV['AWS_SECRET_ACCESS_KEY'].empty? || ENV['AWS_CDN_BUCKET'].empty?
28
+ USE_AWS = true
29
+ else
30
+ USE_AWS = false
31
+ end
32
+ end
33
+
34
+ helpers do
35
+ def upload(filename, file, device_name)
36
+ doomsday = Time.mktime(2038, 1, 18).to_i
37
+ if (filename)
38
+ new_file_name = device_name.to_s + SecureRandom.uuid.to_s + filename
39
+ bucket = ENV['AWS_CDN_BUCKET']
40
+ image = MiniMagick::Image.open(file.path)
41
+
42
+ animated_gif = `identify -format "%n" "#{file.path}"`.to_i > 1
43
+ if animated_gif
44
+ image.repage "0x0"
45
+ if image.height > image.width
46
+ image.resize "300"
47
+ offset = (image.height/2) - 150
48
+ image.crop("300x300+0+#{offset}")
49
+ else
50
+ image.resize "x300"
51
+ offset = (image.width/2) - 150
52
+ image.crop("300x300+#{offset}+0")
53
+ end
54
+ image << "+repage"
55
+ else
56
+ image.auto_orient
57
+ if image.height > image.width
58
+ image.resize "300"
59
+ offset = (image.height/2) - 150
60
+ image.crop("300x300+0+#{offset}")
61
+ else
62
+ image.resize "x300"
63
+ offset = (image.width/2) - 150
64
+ image.crop("300x300+#{offset}+0")
65
+ end
66
+ image.format "png"
67
+ end
68
+
69
+ if USE_AWS
70
+ AWS::S3::Base.establish_connection!(
71
+ :access_key_id => ENV['AWS_ACCESS_KEY_ID'],
72
+ :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
73
+ )
74
+ AWS::S3::S3Object.store(
75
+ new_file_name,
76
+ image.to_blob,
77
+ bucket,
78
+ :access => :public_read
79
+ )
80
+ image_url = AWS::S3::S3Object.url_for( new_file_name, bucket, :expires => doomsday )
81
+ else
82
+ upload_path = @@local_file_system
83
+ file_on_disk = upload_path + new_file_name
84
+ File.open(File.expand_path(file_on_disk), "w") do |f|
85
+ f.write(image.to_blob)
86
+ end
87
+ image_url = "images/uploads/" + new_file_name
88
+ end
89
+
90
+ return image_url
91
+
92
+ else
93
+ return nil
94
+ end
95
+ end
96
+ end
97
+
98
+ get "/" do
99
+ redirect "index.html"
100
+ end
101
+
102
+ post "/register" do
103
+ dns = Resolv.new
104
+ device_name = dns.getname(request.ip)
105
+ r = Redis.new
106
+
107
+ compound_name = nil
108
+
109
+ if !params[:real_first_name].empty? || !params[:real_last_name].empty?
110
+ compound_name = "#{params[:real_first_name].to_s.strip} #{params[:real_last_name].to_s.strip}"
111
+ r.set("name:#{device_name}", compound_name)
112
+ end
113
+ if params[:fileToUpload]
114
+ image_url_returned_from_upload_function = upload(params[:fileToUpload][:filename], params[:fileToUpload][:tempfile], device_name)
115
+ name_key = "image:" + (compound_name || r.get("name:#{device_name}") || device_name)
116
+ r.set(name_key, image_url_returned_from_upload_function)
117
+ end
118
+ redirect "thanks.html"
119
+ end
120
+
121
+ get "/register" do
122
+ redirect "register.html"
123
+ end
124
+
125
+ get "/feed", provides: 'text/event-stream' do
126
+ cross_origin
127
+ r = Redis.new
128
+
129
+ stream :keep_open do |out|
130
+ loop do
131
+ if out.closed?
132
+ break
133
+ end
134
+ data = []
135
+ r.hgetall("current_devices").each do |k,v|
136
+ name_or_device_name = r.get("name:#{k}") || k
137
+ data << { device_name: k, name: v, last_seen: (Time.now.to_f * 1000).to_i, avatar: r.get("image:#{name_or_device_name}") }
138
+ end
139
+
140
+ out << "data: #{data.to_json}\n\n"
141
+ sleep 1
142
+ end
143
+ end
144
+ end
145
+
146
+ post "/information" do
147
+ #grab current devices on network. Save them to the devices on network key after we make sure that we grab the names that have been added already to the whole list and then save them to the updated hash for redis.
148
+ devices_on_network = JSON.parse(params[:devices])
149
+ r = Redis.new
150
+ old_set = r.hkeys("current_devices")
151
+ new_set = devices_on_network.keys
152
+ diff_set = old_set - new_set
153
+
154
+ diff_set.each do |d|
155
+ r.hdel("current_devices", d)
156
+ end
157
+
158
+ devices_on_network.each do |k,v|
159
+ r.hmset("current_devices", k, r.get("name:#{k}"))
160
+ end
161
+
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,87 @@
1
+ require 'resolv'
2
+ require 'httparty'
3
+
4
+ module BenevolentGaze
5
+ class Tracker
6
+ @@old_time = Time.now.to_i
7
+
8
+ def self.run!
9
+ # Run forever
10
+ while true
11
+ scan
12
+ check_time
13
+ sleep 10
14
+ end
15
+ end
16
+
17
+ class << self
18
+ private
19
+
20
+ def check_time
21
+ #if ((@@old_time + (30*60)) <= Time.now.to_i)
22
+ if (@@old_time <= Time.now.to_i)
23
+ begin
24
+ #TODO make sure to change the url to read from an environment variable for the correct company url.
25
+ HTTParty.post( (ENV['BG_COMPANY_URL'] || 'http://localhost:3000/register'), query: { ip: `ifconfig | awk '/inet/ {print $2}' | grep -E '[[:digit:]]{1,3}\\.' | tail -1`.strip + ":#{ENV['IPORT']}/register"})
26
+ puts "Just sent localhost address to server."
27
+ rescue
28
+ puts "Looks like there is something wrong with the endpoint to identify the localhost."
29
+ end
30
+ @old_time = Time.now.to_i
31
+ end
32
+ end
33
+
34
+ def scan
35
+ =begin
36
+ # Look for the network broadcast address
37
+ broadcast = `ifconfig -a | grep broadcast`.split[-1]
38
+
39
+ # puts "Broadcast Address #{broadcast}"
40
+ unless broadcast =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
41
+ puts "#{broadcast} doesn't look correct"
42
+ exit 1
43
+ end
44
+
45
+ # Ping the broadcast address 4 times and wait for responses
46
+ ips = `ping -t 4 #{broadcast}`.split(/\n/).collect do |x|
47
+ if x =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):/
48
+ $1
49
+ else
50
+ nil
51
+ end
52
+ end.select { |x| x && x != broadcast}.sort.uniq
53
+
54
+ dns = Resolv.new
55
+ device_names_and_ip_addresses = {}
56
+
57
+ ips.each do |ip|
58
+ name = dns.getname ip
59
+ device_names_and_ip_addresses[name] = nil
60
+ end
61
+ puts "****************************"
62
+ =end
63
+
64
+ #reintroduction of arp usage for mac addresses - will reintegrate soon.
65
+ device_name_and_mac_address_hash = {}
66
+ `arp -a | grep -v "?" | awk '{print $1 "\t" $4}'`.split("\n").each do |a|
67
+ a = a.split("\t")
68
+ device_name_and_mac_address_hash[a[0]] = a[1]
69
+ end
70
+
71
+ device_names_hash = {}
72
+ device_names_arr = `for i in {1..254}; do echo ping -t 4 192.168.1.${i} ; done | parallel -j 0 --no-notice 2> /dev/null | awk '/ttl/ { print $4 }' | sort | uniq | sed 's/://' | xargs -n 1 host | awk '{ print $5 }' | sed 's/\.$//'`.split(/\n/)
73
+ device_names_arr.each do |d|
74
+ unless d.match(/Wireless|EPSON/)
75
+ device_names_hash[d] = nil
76
+ end
77
+ end
78
+ puts device_names_hash
79
+ begin
80
+ HTTParty.post("http://localhost:#{ENV['IPORT']}/information", query: {devices: device_names_hash.to_json } )
81
+ rescue
82
+ puts "Looks like you might not have the Benevolent Gaze gem running"
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module BenevolentGaze
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,5 @@
1
+ require "benevolent_gaze/version"
2
+
3
+ module BenevolentGaze
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,18 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Ignore bundler config
8
+ /.bundle
9
+
10
+ # Ignore the build directory
11
+ /build
12
+
13
+ # Ignore cache
14
+ /.sass-cache
15
+ /.cache
16
+
17
+ # Ignore .DS_store file
18
+ .DS_Store
data/website/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ # If you do not have OpenSSL installed, update
2
+ # the following line to use "http://" instead
3
+ source 'https://rubygems.org'
4
+
5
+ gem "middleman", "~>3.3.7"
6
+ gem "middleman-deploy"
7
+ gem "middleman-autometatags"
8
+ gem "middleman-livereload", "~> 3.1.0"
9
+ gem "bootstrap-sass"
10
+ gem "jquery-middleman"
11
+
12
+ # For faster file watcher updates on Windows:
13
+ gem "wdm", "~> 0.1.0", :platforms => [:mswin, :mingw]
14
+
15
+ # Windows does not come with time zone data
16
+ gem "tzinfo-data", platforms: [:mswin, :mingw]
17
+
18
+ gem "builder", "~> 3.0"
19
+
20
+ gem "redcarpet"