arunthampi-injour 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+