chuyeow-injour 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,60 @@
1
+ = Injour
2
+
3
+ An evolution of the In/Out app which 37Signals uses. A distributed In/Out, if you will.
4
+
5
+ == Installation from GitHub Gems
6
+
7
+ sudo gem install dnssd
8
+ sudo gem install arunthampi-injour --source=http://gems.github.com
9
+
10
+ == Installation from Source (More reliable)
11
+ sudo gem install dnssd
12
+ git clone git://github.com/arunthampi/injour.git
13
+ cd injour
14
+ rake install
15
+
16
+ == Useful bash aliases the author recommends
17
+ # To be put in your ~/.bash_profile
18
+ alias ise='injour serve &'
19
+ alias ist='injour st'
20
+ alias ils='injour ls'
21
+
22
+ == Usage
23
+
24
+ alice$ injour serve # Starts up publishing your statuses
25
+ alice$ injour status Testing out injour # Sets your status as injour ['st' is an alias for 'status']
26
+ bob$ injour list # Finds alice ['ls' is an alias for 'list']
27
+ bob$ injour show alice # Shows alice's last 3 updates
28
+
29
+ Prefix the cmds with "sudo" as necessary.
30
+
31
+ == Inspiration
32
+
33
+ Inspiration is a polite word for copy. This lib has copied vast amounts of code from the insanely awesome gemjour and pastejour projects. In any case, I conveniently believe in the quote 'Good artists copy, great artists steal, real artists ship' ;)
34
+
35
+ The author would also like to thank Dr. Nic for his inspirational blog-post which set the wheels in motion.
36
+
37
+ http://drnicwilliams.com/2008/06/18/what-is-gitjour-gemjour-starjour/
38
+
39
+ == License
40
+
41
+ Copyright (c) 2008 Arun Thampi
42
+
43
+ Permission is hereby granted, free of charge, to any person obtaining
44
+ a copy of this software and associated documentation files (the
45
+ "Software"), to deal in the Software without restriction, including
46
+ without limitation the rights to use, copy, modify, merge, publish,
47
+ distribute, sublicense, and/or sell copies of the Software, and to
48
+ permit persons to whom the Software is furnished to do so, subject to
49
+ the following conditions:
50
+
51
+ The above copyright notice and this permission notice shall be
52
+ included in all copies or substantial portions of the Software.
53
+
54
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
55
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
56
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
57
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
58
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
59
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
60
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,47 @@
1
+ require "date"
2
+ require "fileutils"
3
+ require "rubygems"
4
+ require "rake/gempackagetask"
5
+
6
+ require "./lib/injour/version.rb"
7
+
8
+ injour_gemspec = Gem::Specification.new do |s|
9
+ s.name = "injour"
10
+ s.version = Injour::VERSION
11
+ s.platform = Gem::Platform::RUBY
12
+ s.has_rdoc = true
13
+ s.extra_rdoc_files = ["README.rdoc"]
14
+ s.summary = "Publish your statuses over Bonjour. A distributed approach to the In/Out app created by 37Signals."
15
+ s.description = s.summary
16
+ s.authors = ["Arun Thampi"]
17
+ s.email = "arun.thampi@gmail.com"
18
+ s.homepage = "http://github.com/arunthampi/injour"
19
+ s.require_path = "lib"
20
+ s.autorequire = "injour"
21
+ s.files = %w(README.rdoc Rakefile) + Dir.glob("{bin,lib}/**/*")
22
+ s.executables = %w(injour)
23
+
24
+ s.add_dependency "dnssd", ">= 0.6.0"
25
+ end
26
+
27
+ Rake::GemPackageTask.new(injour_gemspec) do |pkg|
28
+ pkg.gem_spec = injour_gemspec
29
+ end
30
+
31
+ namespace :gem do
32
+ namespace :spec do
33
+ desc "Update injour.gemspec"
34
+ task :generate do
35
+ File.open("injour.gemspec", "w") do |f|
36
+ f.puts(injour_gemspec.to_ruby)
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ task :install => :package do
43
+ sh %{sudo gem install pkg/injour-#{Injour::VERSION}}
44
+ end
45
+
46
+ desc "Remove all generated artifacts"
47
+ task :clean => :clobber_package
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require File.dirname(__FILE__) + '/../lib/injour'
5
+
6
+ begin
7
+ cmd = ARGV.shift
8
+
9
+ case cmd
10
+ when 'status', 'st'
11
+ Injour.set_status(ARGV.join(' '))
12
+ when 'serve'
13
+ Injour.serve(*ARGV)
14
+ when 'list', 'ls'
15
+ Injour.list(*ARGV)
16
+ when 'show'
17
+ Injour.get(*ARGV)
18
+ else
19
+ Injour.usage
20
+ end
21
+ rescue => e
22
+ puts "ERROR: running '#{cmd}': #{e.message} (#{e.class})\n"
23
+ Injour.usage
24
+ end
@@ -0,0 +1,153 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require "dnssd"
5
+ require "set"
6
+ require "socket"
7
+ require "webrick"
8
+ require 'net/http'
9
+ require 'uri'
10
+
11
+ require "injour/version"
12
+
13
+ Thread.abort_on_exception = true
14
+
15
+ module Injour
16
+ Server = Struct.new(:name, :host, :port)
17
+ PORT = 43215
18
+ SERVICE = "_injour._tcp"
19
+ INJOUR_STATUS = File.join(ENV['HOME'], '.injour')
20
+
21
+ def self.usage
22
+ puts <<-HELP
23
+ Usage:
24
+
25
+ serve [<name>] [<port>]
26
+ Start up your injour server as <name> on <port>. <name> is your username
27
+ by default, and <port> is 43215. If you want to use the default <name>,
28
+ pass it as "".
29
+
30
+ status/st [<message>]
31
+ Publishes your [<message>] on Injour.
32
+
33
+ list/ls
34
+ List all people who are publishing statuses on Injour
35
+
36
+ show user
37
+ Lists the last three updates from the 'user'
38
+
39
+ HELP
40
+ end
41
+
42
+ def self.retrieve_status_using_http(host, port, limit)
43
+ Net::HTTP.get_response(URI.parse("http://#{host}:#{port}/?number=#{limit}")).body
44
+ end
45
+
46
+ def self.get(name, limit = 10)
47
+ hosts = find(name)
48
+
49
+ if hosts.empty?
50
+ STDERR.puts "ERROR: Unable to find #{name}"
51
+ elsif hosts.size > 1
52
+ STDERR.puts "ERROR: Multiple possibles found:"
53
+ hosts.each do |host|
54
+ STDERR.puts " #{host.name} (#{host.host}:#{host.port})"
55
+ end
56
+ else
57
+ # Set is weird. There is no #[] or #at
58
+ hosts.each do |host|
59
+ puts retrieve_status_using_http(host.host, host.port, limit)
60
+ end
61
+ end
62
+ end
63
+
64
+ def self.list(name = nil)
65
+ return get(name) if name
66
+ hosts = []
67
+
68
+ service = DNSSD.browse(SERVICE) do |reply|
69
+ DNSSD.resolve(reply.name, reply.type, reply.domain) do |rr|
70
+ host = Server.new(reply.name, rr.target, rr.port)
71
+ unless hosts.include? host
72
+ puts "#{host.name} (#{host.host}:#{host.port}) -> #{retrieve_status_using_http(host.host, host.port, 1)}"
73
+ hosts << host
74
+ end
75
+ end
76
+ end
77
+
78
+ sleep 5
79
+ service.stop
80
+ end
81
+
82
+ def self.set_status(message)
83
+ File.open(INJOUR_STATUS, 'a') { |file| file.puts("[#{Time.now.strftime("%d-%b-%Y %I:%M %p")}] #{message}") }
84
+ if message !~ /\S/
85
+ puts 'Your status has been cleared.'
86
+ else
87
+ puts "Your status has been set to '#{message}'."
88
+ end
89
+ end
90
+
91
+ def self.find(name, first=true)
92
+ hosts = Set.new
93
+
94
+ waiting = Thread.current
95
+
96
+ service = DNSSD.browse(SERVICE) do |reply|
97
+ if name === reply.name
98
+ DNSSD.resolve(reply.name, reply.type, reply.domain) do |rr|
99
+ hosts << Server.new(reply.name, rr.target, rr.port)
100
+ waiting.run if first
101
+ end
102
+ end
103
+ end
104
+
105
+ sleep 5
106
+ service.stop
107
+ hosts
108
+ end
109
+
110
+ def self.get_status(limit = 5)
111
+ File.read(INJOUR_STATUS).split("\n").reverse.slice(0, limit).join("\n")
112
+ end
113
+
114
+ def self.get_limit(query_string)
115
+ (query_string.match(/number=(\d+)/)[1]).to_i || 5
116
+ rescue
117
+ 5
118
+ end
119
+
120
+ def self.serve(name="", port=PORT)
121
+ name = ENV['USER'] if name.empty?
122
+
123
+ tr = DNSSD::TextRecord.new
124
+ tr['description'] = "#{name}'s In/Out"
125
+
126
+ DNSSD.register(name, SERVICE, "local", port.to_i, tr.encode) do |reply|
127
+ puts "#{name}'s In/Out Records..."
128
+ end
129
+
130
+ # Don't log anything, everything goes in an abyss
131
+ log = WEBrick::Log.new(true)
132
+ def log.log(*anything); end
133
+ server = WEBrick::HTTPServer.new(:Port => port.to_i, :Logger => log)
134
+
135
+ # Open up a servlet, so that status can be viewed in a browser
136
+ server.mount_proc("/") do |req, res|
137
+ @logger = log
138
+ limit = get_limit(req.query_string)
139
+ res.body = get_status(limit)
140
+ res['Content-Type'] = "text/plain"
141
+ end
142
+ # Ctrl+C must quit it
143
+ %w(INT TERM).each do |signal|
144
+ trap signal do
145
+ server.shutdown
146
+ exit!
147
+ end
148
+ end
149
+ # Start the server
150
+ server.start
151
+ end
152
+
153
+ end
@@ -0,0 +1,3 @@
1
+ module Injour
2
+ VERSION = "0.2.0".freeze
3
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chuyeow-injour
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Arun Thampi
8
+ autorequire: injour
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-20 00:00:00 -07:00
13
+ default_executable: injour
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: dnssd
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.6.0
23
+ version:
24
+ description: Publish your statuses over Bonjour. A distributed approach to the In/Out app created by 37Signals.
25
+ email: arun.thampi@gmail.com
26
+ executables:
27
+ - injour
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - README.rdoc
32
+ files:
33
+ - README.rdoc
34
+ - Rakefile
35
+ - bin/injour
36
+ - lib/injour
37
+ - lib/injour/version.rb
38
+ - lib/injour.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/arunthampi/injour
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.0.1
62
+ signing_key:
63
+ specification_version: 2
64
+ summary: Publish your statuses over Bonjour. A distributed approach to the In/Out app created by 37Signals.
65
+ test_files: []
66
+