chuyeow-injour 0.2.0

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,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
+