arunthampi-injour 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,48 @@
1
+ = Injour
2
+
3
+ An evolution of the In/Out app which 37Signals uses. A distributed In/Out, if you will.
4
+
5
+ == Installation
6
+
7
+ sudo gem install dnssd
8
+ sudo gem install arunthampi-injour --source=http://gems.github.com
9
+
10
+ == Usage
11
+
12
+ alice$ injour serve # Starts up publishing your statuses
13
+ alice$ injour status Testing out injour # Sets your status as injour ['st' is an alias for 'status']
14
+ bob$ injour list # Finds alice ['ls' is an alias for 'list']
15
+ bob$ injour show alice # Shows alice's last 3 updates
16
+
17
+ Prefix the cmds with "sudo" as necessary.
18
+
19
+ == Inspiration
20
+
21
+ 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' ;)
22
+
23
+ The author would also like to thank Dr. Nic for his inspirational blog-post which set the wheels in motion.
24
+
25
+ http://drnicwilliams.com/2008/06/18/what-is-gitjour-gemjour-starjour/
26
+
27
+ == License
28
+
29
+ Copyright (c) 2008 Arun Thampi
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining
32
+ a copy of this software and associated documentation files (the
33
+ "Software"), to deal in the Software without restriction, including
34
+ without limitation the rights to use, copy, modify, merge, publish,
35
+ distribute, sublicense, and/or sell copies of the Software, and to
36
+ permit persons to whom the Software is furnished to do so, subject to
37
+ the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be
40
+ included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
43
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
45
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
46
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
47
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
48
+ 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,26 @@
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"
11
+ Injour.set_status(ARGV.join(' '))
12
+ when "st"
13
+ Injour.set_status(ARGV.join(' '))
14
+ when "serve"
15
+ Injour.serve(*ARGV)
16
+ when "list"
17
+ Injour.list(*ARGV)
18
+ when "ls"
19
+ Injour.list(*ARGV)
20
+ when "show"
21
+ Injour.get(*ARGV)
22
+ end
23
+ rescue => e
24
+ puts "ERROR: running '#{cmd}': #{e.message} (#{e.class})\n"
25
+ Injour.usage
26
+ end
@@ -0,0 +1,133 @@
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
+
9
+ require "injour/version"
10
+
11
+ Thread.abort_on_exception = true
12
+
13
+ module Injour
14
+ Server = Struct.new(:name, :host, :port)
15
+ PORT = 43215
16
+ SERVICE = "_injour._tcp"
17
+ INJOUR_STATUS = File.join(ENV['HOME'], '.injour')
18
+
19
+ def self.usage
20
+ puts <<-HELP
21
+ Usage:
22
+
23
+ serve [<name>] [<port>]
24
+ Start up your injour server as <name> on <port>. <name> is your username
25
+ by default, and <port> is 43215. If you want to use the default <name>,
26
+ pass it as "".
27
+
28
+ status/st [<message>]
29
+ Publishes your [<message>] on Injour.
30
+
31
+ list/ls
32
+ List all people who are publishing statuses on Injour
33
+
34
+ show user
35
+ Lists the last three updates from the 'user'
36
+
37
+ HELP
38
+ end
39
+
40
+ def self.get(name)
41
+ hosts = find(name)
42
+
43
+ if hosts.empty?
44
+ STDERR.puts "ERROR: Unable to find #{name}"
45
+ elsif hosts.size > 1
46
+ STDERR.puts "ERROR: Multiple possibles found:"
47
+ hosts.each do |host|
48
+ STDERR.puts " #{host.name} (#{host.host}:#{host.port})"
49
+ end
50
+ else
51
+ # Set is weird. There is no #[] or #at
52
+ hosts.each do |host|
53
+ sock = TCPSocket.open host.host, host.port
54
+ puts sock.read
55
+ end
56
+ end
57
+ end
58
+
59
+ def self.list(name = nil)
60
+ return show(name) if name
61
+ hosts = []
62
+
63
+ waiting = Thread.current
64
+
65
+ service = DNSSD.browse(SERVICE) do |reply|
66
+ DNSSD.resolve(reply.name, reply.type, reply.domain) do |rr|
67
+ host = Server.new(reply.name, rr.target, rr.port)
68
+ unless hosts.include? host
69
+ puts "#{host.name} (#{host.host}:#{host.port})"
70
+ hosts << host
71
+ end
72
+ end
73
+ end
74
+
75
+ sleep 5
76
+ service.stop
77
+ end
78
+
79
+ def self.set_status(message)
80
+ File.open(INJOUR_STATUS, 'a') { |file| file.puts("[#{Time.now.strftime("%d-%b-%Y %I:%M %p")}] #{message}") }
81
+ end
82
+
83
+ def self.find(name, first=true)
84
+ hosts = Set.new
85
+
86
+ waiting = Thread.current
87
+
88
+ service = DNSSD.browse(SERVICE) do |reply|
89
+ if name === reply.name
90
+ DNSSD.resolve(reply.name, reply.type, reply.domain) do |rr|
91
+ hosts << Server.new(reply.name, rr.target, rr.port)
92
+ waiting.run if first
93
+ end
94
+ end
95
+ end
96
+
97
+ sleep 5
98
+ service.stop
99
+
100
+ hosts
101
+ end
102
+
103
+ def self.get_status(limit = 3)
104
+ File.read(INJOUR_STATUS).split("\n").reverse.slice(0, limit).join("\n")
105
+ end
106
+
107
+ def self.serve(name="", port=PORT)
108
+ name = ENV['USER'] if name.empty?
109
+
110
+ tr = DNSSD::TextRecord.new
111
+ tr['description'] = "#{name}'s In/Out"
112
+
113
+ DNSSD.register(name, SERVICE, "local", port.to_i, tr.encode) do |reply|
114
+ puts "#{name}'s In/Out Records..."
115
+ end
116
+
117
+ log = WEBrick::Log.new(true) # true fools it
118
+ def log.log(*anything); end # send it to the abyss
119
+
120
+ # Open webrick babeh
121
+ server = WEBrick::GenericServer.new(:Port => port.to_i, :Logger => log)
122
+ # Get the latest status
123
+ %w(INT TERM).each do |signal|
124
+ trap signal do
125
+ server.shutdown
126
+ exit!
127
+ end
128
+ end
129
+ # Get the latest status
130
+ server.start { |socket| socket.print(get_status) }
131
+ end
132
+
133
+ end
@@ -0,0 +1,3 @@
1
+ module Injour
2
+ VERSION = "0.1.1".freeze
3
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: arunthampi-injour
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Arun Thampi
8
+ autorequire: injour
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-18 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
+