pyre 0.1.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,4 @@
1
+ == 0.1.0 / 2008-02-15
2
+
3
+ * 1 major enhancement
4
+ * Existence
@@ -0,0 +1,19 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/pyre.rb
6
+ lib/pyre/campfire.rb
7
+ lib/pyre/room.rb
8
+ spec/pyre_spec.rb
9
+ spec/spec_helper.rb
10
+ tasks/annotations.rake
11
+ tasks/doc.rake
12
+ tasks/gem.rake
13
+ tasks/manifest.rake
14
+ tasks/post_load.rake
15
+ tasks/rubyforge.rake
16
+ tasks/setup.rb
17
+ tasks/spec.rake
18
+ tasks/svn.rake
19
+ tasks/test.rake
@@ -0,0 +1,67 @@
1
+ = pyre
2
+ by Christopher Shea
3
+ http://pyre.rubyforge.org/
4
+
5
+ == DESCRIPTION:
6
+
7
+ Pyre is a library for interacting with Campfire, the web-based group chat site from 37signals.
8
+
9
+ Pyre owes a great deal of debt to Tinder (http://tinder.rubyforge.org)
10
+
11
+ == FEATURES/PROBLEMS:
12
+
13
+ Features:
14
+ * Speak in a Campfire room!
15
+ * Paste in a Campfire room!
16
+ * More reliable determination of whether your login was successful than Tinder!
17
+
18
+ Problems:
19
+ * No public tests (I have them on my box, but you can't see them (passwords!))
20
+ * No listening (yet)
21
+
22
+ Patches awfully welcome.
23
+
24
+ == SYNOPSIS:
25
+
26
+ require 'rubygems'
27
+ require 'pyre'
28
+
29
+ campfire = Pyre::Campfire.new('pyre')
30
+ campfire.login('mycoolemail@example.com', 'anactualpassword')
31
+ room = campfire.find_room_by_name('Pyre Test')
32
+ room.speak('ZOMG! It works!') # automatically joins the room
33
+ room.leave
34
+ campfire.logout
35
+
36
+ == REQUIREMENTS:
37
+
38
+ * mechanize (WWW::Mechanize)
39
+
40
+ == INSTALL:
41
+
42
+ * sudo gem install pyre
43
+
44
+ == LICENSE:
45
+
46
+ (The MIT License)
47
+
48
+ Copyright (c) 2008
49
+
50
+ Permission is hereby granted, free of charge, to any person obtaining
51
+ a copy of this software and associated documentation files (the
52
+ 'Software'), to deal in the Software without restriction, including
53
+ without limitation the rights to use, copy, modify, merge, publish,
54
+ distribute, sublicense, and/or sell copies of the Software, and to
55
+ permit persons to whom the Software is furnished to do so, subject to
56
+ the following conditions:
57
+
58
+ The above copyright notice and this permission notice shall be
59
+ included in all copies or substantial portions of the Software.
60
+
61
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
62
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
63
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
64
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
65
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
66
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
67
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,20 @@
1
+ # Look in the tasks/setup.rb file for the various options that can be
2
+ # configured in this Rakefile. The .rake files in the tasks directory
3
+ # are where the options are used.
4
+
5
+ load 'tasks/setup.rb'
6
+
7
+ ensure_in_path 'lib'
8
+ require 'pyre'
9
+
10
+ task :default => 'spec:run'
11
+
12
+ PROJ.name = 'pyre'
13
+ PROJ.authors = 'Christopher Shea'
14
+ PROJ.email = 'chris@ruby.tie-rack.org'
15
+ PROJ.url = 'http://pyre.rubyforge.org'
16
+ PROJ.rubyforge_name = 'pyre'
17
+
18
+ PROJ.spec_opts << '--color'
19
+
20
+ depend_on('mechanize')
@@ -0,0 +1,24 @@
1
+ # Pyre: Because there isn't a real API for Campfire.
2
+ module Pyre
3
+ # :stopdoc:
4
+ VERSION = '0.1.0'
5
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
6
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
7
+ # :startdoc:
8
+
9
+ # Returns the version string for the library.
10
+ #
11
+ def self.version
12
+ VERSION
13
+ end
14
+ end
15
+
16
+ require 'uri'
17
+ begin
18
+ require 'mechanize'
19
+ rescue LoadError
20
+ require 'rubygems'
21
+ require 'mechanize'
22
+ end
23
+ require 'pyre/campfire'
24
+ require 'pyre/room'
@@ -0,0 +1,60 @@
1
+ module Pyre
2
+ # Pyre::Campfire is for general Campfire tasks. Logging in, logging out, and finding rooms.
3
+ class Campfire
4
+ attr_reader :subdomain, :uri, :agent
5
+
6
+ # Create a new Pyre::Campfire object.
7
+ # Pass in your subdomain and maybe some options.
8
+ # Of course, the only option is whether or not to use ssl.
9
+ # Pass along <tt>:ssl => true</tt> if you need it.
10
+ def initialize(subdomain, options={})
11
+ @subdomain = subdomain
12
+ protocol = 'http'
13
+ protocol << 's' if options[:ssl]
14
+ @uri = "#{protocol}://#{subdomain}.campfirenow.com"
15
+ @agent = WWW::Mechanize.new
16
+ end
17
+
18
+ # Login with the supplied credentials. Returns true on success.
19
+ def login(email, password)
20
+ page = @agent.get(@uri + '/login')
21
+ login_form = page.forms.first
22
+ login_form.fields.name('email_address').value = email
23
+ login_form.fields.name('password').value = password
24
+ @agent.submit(login_form)
25
+ logged_in?
26
+ end
27
+
28
+ # Log out. Returns true on success.
29
+ def logout
30
+ page = @agent.get(@uri + '/logout')
31
+ not logged_in?
32
+ end
33
+
34
+ def logged_in?
35
+ @agent.current_page.links.any? {|link| link.text == 'Logout'} rescue false
36
+ end
37
+
38
+ # Get a list of all the rooms as Pyre::Room objects.
39
+ def rooms
40
+ if logged_in?
41
+ @agent.get(@uri)
42
+ @rooms = @agent.current_page.parser.search('div[@id="rooms"]//h2').map do |h2|
43
+ name = h2.inner_text.strip
44
+ url = h2.at('a')[:href]
45
+ Pyre::Room.new(name, url, self)
46
+ end
47
+ end
48
+ end
49
+
50
+ # Know the name of the room you're looking for? Try it here.
51
+ def find_room_by_name(name)
52
+ @rooms ||= rooms
53
+ @rooms.detect {|room| room.name == name}
54
+ end
55
+
56
+ def inspect #:nodoc:
57
+ "#<#{self.class} \"#{@subdomain}\" \"#{uri}\">"
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,60 @@
1
+ module Pyre
2
+ # Pyre::Room is for interacting with a room!
3
+ class Room
4
+ attr_reader :name
5
+
6
+ def initialize(name, url, campfire) #:nodoc:
7
+ @name = name
8
+ @url = url
9
+ @campfire = campfire
10
+ end
11
+
12
+ # Enter the room. Returns true on success.
13
+ def join
14
+ @campfire.agent.get(@url)
15
+ joined?
16
+ end
17
+
18
+ # Leave the room. Returns true on success.
19
+ def leave
20
+ if joined?
21
+ leave = @campfire.agent.current_page.links.detect {|link| link.text == 'Leave'}
22
+ @campfire.agent.post(leave.uri)
23
+ not joined?
24
+ end
25
+ end
26
+
27
+ # If you're in the room right now.
28
+ def joined?
29
+ @campfire.agent.current_page.at('h1[@id="room_name"]').inner_text == @name rescue false
30
+ end
31
+
32
+ # Send +message+ to the room. Joins the room if necessary.
33
+ def speak(message)
34
+ result = submit_chat_form(message)
35
+ success = (result.uri.to_s == "#{@url}/speak")
36
+ join
37
+ success
38
+ end
39
+
40
+ # Paste +message+ to the room. Joins the room if necessary.
41
+ def paste(message)
42
+ result = submit_chat_form(message, 'paste' => 'true')
43
+ success = (result.links.detect {|link| link.text == 'View paste'} and result.uri.to_s == "#{@url}/speak")
44
+ join
45
+ success
46
+ end
47
+
48
+ def inspect #:nodoc:
49
+ "#<#{self.class} \"#{@name}\" \"#{@url}\">"
50
+ end
51
+
52
+ protected
53
+
54
+ def submit_chat_form(message, options={}) #:nodoc:
55
+ join unless joined?
56
+ speak_form = @campfire.agent.current_page.forms.detect {|form| form.form_node[:id] == 'chat_form'}
57
+ @campfire.agent.post(@url + '/speak', {'message' => message, 't' => Time.now.to_i.to_s}.merge(options))
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,8 @@
1
+ # $Id$
2
+
3
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
4
+
5
+ describe Pyre do
6
+ end
7
+
8
+ # EOF
@@ -0,0 +1,17 @@
1
+ # $Id$
2
+
3
+ require File.expand_path(
4
+ File.join(File.dirname(__FILE__), %w[.. lib pyre]))
5
+
6
+ Spec::Runner.configure do |config|
7
+ # == Mock Framework
8
+ #
9
+ # RSpec uses it's own mocking framework by default. If you prefer to
10
+ # use mocha, flexmock or RR, uncomment the appropriate line:
11
+ #
12
+ # config.mock_with :mocha
13
+ # config.mock_with :flexmock
14
+ # config.mock_with :rr
15
+ end
16
+
17
+ # EOF
@@ -0,0 +1,30 @@
1
+ # $Id$
2
+
3
+ if HAVE_BONES
4
+
5
+ desc "Enumerate all annotations"
6
+ task :notes do
7
+ Bones::AnnotationExtractor.enumerate(
8
+ PROJ, "OPTIMIZE|FIXME|TODO", :tag => true)
9
+ end
10
+
11
+ namespace :notes do
12
+ desc "Enumerate all OPTIMIZE annotations"
13
+ task :optimize do
14
+ Bones::AnnotationExtractor.enumerate(PROJ, "OPTIMIZE")
15
+ end
16
+
17
+ desc "Enumerate all FIXME annotations"
18
+ task :fixme do
19
+ Bones::AnnotationExtractor.enumerate(PROJ, "FIXME")
20
+ end
21
+
22
+ desc "Enumerate all TODO annotations"
23
+ task :todo do
24
+ Bones::AnnotationExtractor.enumerate(PROJ, "TODO")
25
+ end
26
+ end
27
+
28
+ end # if HAVE_BONES
29
+
30
+ # EOF
@@ -0,0 +1,49 @@
1
+ # $Id$
2
+
3
+ require 'rake/rdoctask'
4
+
5
+ namespace :doc do
6
+
7
+ desc 'Generate RDoc documentation'
8
+ Rake::RDocTask.new do |rd|
9
+ rd.main = PROJ.rdoc_main
10
+ rd.rdoc_dir = PROJ.rdoc_dir
11
+
12
+ incl = Regexp.new(PROJ.rdoc_include.join('|'))
13
+ excl = Regexp.new(PROJ.rdoc_exclude.join('|'))
14
+ files = PROJ.files.find_all do |fn|
15
+ case fn
16
+ when excl; false
17
+ when incl; true
18
+ else false end
19
+ end
20
+ rd.rdoc_files.push(*files)
21
+
22
+ title = "#{PROJ.name}-#{PROJ.version} Documentation"
23
+ title = "#{PROJ.rubyforge_name}'s " + title if PROJ.rubyforge_name != title
24
+
25
+ rd.options << "-t #{title}"
26
+ rd.options.concat(PROJ.rdoc_opts)
27
+ end
28
+
29
+ desc 'Generate ri locally for testing'
30
+ task :ri => :clobber_ri do
31
+ sh "#{RDOC} --ri -o ri ."
32
+ end
33
+
34
+ desc 'Remove ri products'
35
+ task :clobber_ri do
36
+ rm_r 'ri' rescue nil
37
+ end
38
+
39
+ end # namespace :doc
40
+
41
+ desc 'Alias to doc:rdoc'
42
+ task :doc => 'doc:rdoc'
43
+
44
+ desc 'Remove all build products'
45
+ task :clobber => %w(doc:clobber_rdoc doc:clobber_ri)
46
+
47
+ remove_desc_for_task %w(doc:clobber_rdoc doc:clobber_ri)
48
+
49
+ # EOF
@@ -0,0 +1,89 @@
1
+ # $Id$
2
+
3
+ require 'rake/gempackagetask'
4
+
5
+ namespace :gem do
6
+
7
+ PROJ.spec = Gem::Specification.new do |s|
8
+ s.name = PROJ.name
9
+ s.version = PROJ.version
10
+ s.summary = PROJ.summary
11
+ s.authors = Array(PROJ.authors)
12
+ s.email = PROJ.email
13
+ s.homepage = Array(PROJ.url).first
14
+ s.rubyforge_project = PROJ.rubyforge_name
15
+
16
+ s.description = PROJ.description
17
+
18
+ PROJ.dependencies.each do |dep|
19
+ s.add_dependency(*dep)
20
+ end
21
+
22
+ s.files = PROJ.files
23
+ s.executables = PROJ.executables.map {|fn| File.basename(fn)}
24
+ s.extensions = PROJ.files.grep %r/extconf\.rb$/
25
+
26
+ s.bindir = 'bin'
27
+ dirs = Dir["{#{PROJ.libs.join(',')}}"]
28
+ s.require_paths = dirs unless dirs.empty?
29
+
30
+ incl = Regexp.new(PROJ.rdoc_include.join('|'))
31
+ excl = PROJ.rdoc_exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext]
32
+ excl = Regexp.new(excl.join('|'))
33
+ rdoc_files = PROJ.files.find_all do |fn|
34
+ case fn
35
+ when excl; false
36
+ when incl; true
37
+ else false end
38
+ end
39
+ s.rdoc_options = PROJ.rdoc_opts + ['--main', PROJ.rdoc_main]
40
+ s.extra_rdoc_files = rdoc_files
41
+ s.has_rdoc = true
42
+
43
+ if test ?f, PROJ.test_file
44
+ s.test_file = PROJ.test_file
45
+ else
46
+ s.test_files = PROJ.tests.to_a
47
+ end
48
+
49
+ # Do any extra stuff the user wants
50
+ # spec_extras.each do |msg, val|
51
+ # case val
52
+ # when Proc
53
+ # val.call(s.send(msg))
54
+ # else
55
+ # s.send "#{msg}=", val
56
+ # end
57
+ # end
58
+ end
59
+
60
+ desc 'Show information about the gem'
61
+ task :debug do
62
+ puts PROJ.spec.to_ruby
63
+ end
64
+
65
+ Rake::GemPackageTask.new(PROJ.spec) do |pkg|
66
+ pkg.need_tar = PROJ.need_tar
67
+ pkg.need_zip = PROJ.need_zip
68
+ end
69
+
70
+ desc 'Install the gem'
71
+ task :install => [:clobber, :package] do
72
+ sh "#{SUDO} #{GEM} install pkg/#{PROJ.spec.full_name}"
73
+ end
74
+
75
+ desc 'Uninstall the gem'
76
+ task :uninstall do
77
+ sh "#{SUDO} #{GEM} uninstall -v '#{PROJ.version}' -x #{PROJ.name}"
78
+ end
79
+
80
+ end # namespace :gem
81
+
82
+ desc 'Alias to gem:package'
83
+ task :gem => 'gem:package'
84
+
85
+ task :clobber => 'gem:clobber_package'
86
+
87
+ remove_desc_for_task %w(gem:clobber_package)
88
+
89
+ # EOF
@@ -0,0 +1,55 @@
1
+ # $Id$
2
+
3
+ require 'find'
4
+
5
+ namespace :manifest do
6
+
7
+ desc 'Verify the manifest'
8
+ task :check do
9
+ fn = 'Manifest.tmp'
10
+ files = []
11
+ exclude = Regexp.new(PROJ.exclude.join('|'))
12
+ Find.find '.' do |path|
13
+ path.sub! %r/^(\.\/|\/)/o, ''
14
+ next unless test ?f, path
15
+ next if path =~ exclude
16
+ files << path
17
+ end
18
+
19
+ File.open(fn, 'w') {|fp| fp.puts files.sort}
20
+ lines = %x(#{DIFF} -du Manifest.txt #{fn}).split("\n")
21
+ if HAVE_FACETS_ANSICODE and ENV.has_key?('TERM')
22
+ lines.map! do |line|
23
+ case line
24
+ when %r/^(-{3}|\+{3})/; nil
25
+ when %r/^@/; Console::ANSICode.blue line
26
+ when %r/^\+/; Console::ANSICode.green line
27
+ when %r/^\-/; Console::ANSICode.red line
28
+ else line end
29
+ end
30
+ end
31
+ puts lines.compact
32
+ rm fn rescue nil
33
+ end
34
+
35
+ desc 'Create a new manifest'
36
+ task :create do
37
+ fn = 'Manifest.txt'
38
+ files = []
39
+ exclude = Regexp.new(PROJ.exclude.join('|'))
40
+ Find.find '.' do |path|
41
+ path.sub! %r/^(\.\/|\/)/o, ''
42
+ next unless test ?f, path
43
+ next if path =~ exclude
44
+ files << path
45
+ end
46
+
47
+ files << fn unless test ?f, fn
48
+ File.open(fn, 'w') {|fp| fp.puts files.sort}
49
+ end
50
+ end # namespace :manifest
51
+
52
+ desc 'Alias to manifest:check'
53
+ task :manifest => 'manifest:check'
54
+
55
+ # EOF
@@ -0,0 +1,18 @@
1
+ # $Id$
2
+
3
+ # This file does not define any rake tasks. It is used to load some project
4
+ # settings if they are not defined by the user.
5
+
6
+ unless PROJ.changes
7
+ PROJ.changes = paragraphs_of('History.txt', 0..1).join("\n\n")
8
+ end
9
+
10
+ unless PROJ.description
11
+ PROJ.description = paragraphs_of('README.txt', 'description').join("\n\n")
12
+ end
13
+
14
+ unless PROJ.summary
15
+ PROJ.summary = PROJ.description.split('.').first
16
+ end
17
+
18
+ # EOF
@@ -0,0 +1,57 @@
1
+ # $Id$
2
+
3
+ if PROJ.rubyforge_name && HAVE_RUBYFORGE
4
+
5
+ require 'rubyforge'
6
+ require 'rake/contrib/sshpublisher'
7
+
8
+ namespace :gem do
9
+ desc 'Package and upload to RubyForge'
10
+ task :release => [:clobber, :package] do |t|
11
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
12
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
13
+ pkg = "pkg/#{PROJ.spec.full_name}"
14
+
15
+ if $DEBUG then
16
+ puts "release_id = rf.add_release #{PROJ.rubyforge_name.inspect}, #{PROJ.name.inspect}, #{PROJ.version.inspect}, \"#{pkg}.tgz\""
17
+ puts "rf.add_file #{PROJ.rubyforge_name.inspect}, #{PROJ.name.inspect}, release_id, \"#{pkg}.gem\""
18
+ end
19
+
20
+ rf = RubyForge.new
21
+ puts 'Logging in'
22
+ rf.login
23
+
24
+ c = rf.userconfig
25
+ c['release_notes'] = PROJ.description if PROJ.description
26
+ c['release_changes'] = PROJ.changes if PROJ.changes
27
+ c['preformatted'] = true
28
+
29
+ files = [(PROJ.need_tar ? "#{pkg}.tgz" : nil),
30
+ (PROJ.need_zip ? "#{pkg}.zip" : nil),
31
+ "#{pkg}.gem"].compact
32
+
33
+ puts "Releasing #{PROJ.name} v. #{PROJ.version}"
34
+ rf.add_release PROJ.rubyforge_name, PROJ.name, PROJ.version, *files
35
+ end
36
+ end # namespace :gem
37
+
38
+
39
+ namespace :doc do
40
+ desc "Publish RDoc to RubyForge"
41
+ task :release => %w(doc:clobber_rdoc doc:rdoc) do
42
+ config = YAML.load(
43
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
44
+ )
45
+
46
+ host = "#{config['username']}@rubyforge.org"
47
+ remote_dir = "/var/www/gforge-projects/#{PROJ.rubyforge_name}/"
48
+ remote_dir << PROJ.rdoc_remote_dir if PROJ.rdoc_remote_dir
49
+ local_dir = PROJ.rdoc_dir
50
+
51
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
52
+ end
53
+ end # namespace :doc
54
+
55
+ end # if HAVE_RUBYFORGE
56
+
57
+ # EOF
@@ -0,0 +1,189 @@
1
+ # $Id$
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'fileutils'
6
+ require 'ostruct'
7
+
8
+ PROJ = OpenStruct.new
9
+
10
+ PROJ.name = nil
11
+ PROJ.summary = nil
12
+ PROJ.description = nil
13
+ PROJ.changes = nil
14
+ PROJ.authors = nil
15
+ PROJ.email = nil
16
+ PROJ.url = nil
17
+ PROJ.version = ENV['VERSION'] || '0.0.0'
18
+ PROJ.rubyforge_name = nil
19
+ PROJ.exclude = %w(tmp$ bak$ ~$ CVS .svn/ ^pkg/ ^doc/)
20
+
21
+ # Rspec
22
+ PROJ.specs = FileList['spec/**/*_spec.rb']
23
+ PROJ.spec_opts = []
24
+
25
+ # Test::Unit
26
+ PROJ.tests = FileList['test/**/test_*.rb']
27
+ PROJ.test_file = 'test/all.rb'
28
+ PROJ.test_opts = []
29
+
30
+ # Rcov
31
+ PROJ.rcov_opts = ['--sort', 'coverage', '-T']
32
+
33
+ # Rdoc
34
+ PROJ.rdoc_opts = []
35
+ PROJ.rdoc_include = %w(^lib/ ^bin/ ^ext/ .txt$)
36
+ PROJ.rdoc_exclude = %w(extconf.rb$ ^Manifest.txt$)
37
+ PROJ.rdoc_main = 'README.txt'
38
+ PROJ.rdoc_dir = 'doc'
39
+ PROJ.rdoc_remote_dir = nil
40
+
41
+ # Extensions
42
+ PROJ.extensions = FileList['ext/**/extconf.rb']
43
+ PROJ.ruby_opts = %w(-w)
44
+ PROJ.libs = []
45
+ %w(lib ext).each {|dir| PROJ.libs << dir if test ?d, dir}
46
+
47
+ # Gem Packaging
48
+ PROJ.files =
49
+ if test ?f, 'Manifest.txt'
50
+ files = File.readlines('Manifest.txt').map {|fn| fn.chomp.strip}
51
+ files.delete ''
52
+ files
53
+ else [] end
54
+ PROJ.executables = PROJ.files.find_all {|fn| fn =~ %r/^bin/}
55
+ PROJ.dependencies = []
56
+ PROJ.need_tar = true
57
+ PROJ.need_zip = false
58
+
59
+ # File Annotations
60
+ PROJ.annotation_exclude = []
61
+ PROJ.annotation_extensions = %w(.txt .rb .erb) << ''
62
+
63
+ # Subversion Repository
64
+ PROJ.svn = false
65
+ PROJ.svn_root = nil
66
+ PROJ.svn_trunk = 'trunk'
67
+ PROJ.svn_tags = 'tags'
68
+ PROJ.svn_branches = 'branches'
69
+
70
+ # Load the other rake files in the tasks folder
71
+ rakefiles = Dir.glob('tasks/*.rake').sort
72
+ rakefiles.unshift(rakefiles.delete('tasks/post_load.rake')).compact!
73
+ import(*rakefiles)
74
+
75
+ # Setup some constants
76
+ WIN32 = %r/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM unless defined? WIN32
77
+
78
+ DEV_NULL = WIN32 ? 'NUL:' : '/dev/null'
79
+
80
+ def quiet( &block )
81
+ io = [STDOUT.dup, STDERR.dup]
82
+ STDOUT.reopen DEV_NULL
83
+ STDERR.reopen DEV_NULL
84
+ block.call
85
+ ensure
86
+ STDOUT.reopen io.first
87
+ STDERR.reopen io.last
88
+ end
89
+
90
+ DIFF = if WIN32 then 'diff.exe'
91
+ else
92
+ if quiet {system "gdiff", __FILE__, __FILE__} then 'gdiff'
93
+ else 'diff' end
94
+ end unless defined? DIFF
95
+
96
+ SUDO = if WIN32 then ''
97
+ else
98
+ if quiet {system 'which sudo'} then 'sudo'
99
+ else '' end
100
+ end
101
+
102
+ RCOV = WIN32 ? 'rcov.cmd' : 'rcov'
103
+ GEM = WIN32 ? 'gem.cmd' : 'gem'
104
+
105
+ %w(rcov spec/rake/spectask rubyforge bones facets/ansicode).each do |lib|
106
+ begin
107
+ require lib
108
+ Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", true}
109
+ rescue LoadError
110
+ Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", false}
111
+ end
112
+ end
113
+
114
+ # Reads a file at +path+ and spits out an array of the +paragraphs+
115
+ # specified.
116
+ #
117
+ # changes = paragraphs_of('History.txt', 0..1).join("\n\n")
118
+ # summary, *description = paragraphs_of('README.txt', 3, 3..8)
119
+ #
120
+ def paragraphs_of( path, *paragraphs )
121
+ title = String === paragraphs.first ? paragraphs.shift : nil
122
+ ary = File.read(path).delete("\r").split(/\n\n+/)
123
+
124
+ result = if title
125
+ tmp, matching = [], false
126
+ rgxp = %r/^=+\s*#{Regexp.escape(title)}/i
127
+ paragraphs << (0..-1) if paragraphs.empty?
128
+
129
+ ary.each do |val|
130
+ if val =~ rgxp
131
+ break if matching
132
+ matching = true
133
+ rgxp = %r/^=+/i
134
+ elsif matching
135
+ tmp << val
136
+ end
137
+ end
138
+ tmp
139
+ else ary end
140
+
141
+ result.values_at(*paragraphs)
142
+ end
143
+
144
+ # Adds the given gem _name_ to the current project's dependency list. An
145
+ # optional gem _version_ can be given. If omitted, the newest gem version
146
+ # will be used.
147
+ #
148
+ def depend_on( name, version = nil )
149
+ spec = Gem.source_index.find_name(name).last
150
+ version = spec.version.to_s if version.nil? and !spec.nil?
151
+
152
+ PROJ.dependencies << (version.nil? ? [name] : [name, ">= #{version}"])
153
+ end
154
+
155
+ # Adds the given arguments to the include path if they are not already there
156
+ #
157
+ def ensure_in_path( *args )
158
+ args.each do |path|
159
+ path = File.expand_path(path)
160
+ $:.unshift(path) if test(?d, path) and not $:.include?(path)
161
+ end
162
+ end
163
+
164
+ # Find a rake task using the task name and remove any description text. This
165
+ # will prevent the task from being displayed in the list of available tasks.
166
+ #
167
+ def remove_desc_for_task( names )
168
+ Array(names).each do |task_name|
169
+ task = Rake.application.tasks.find {|t| t.name == task_name}
170
+ next if task.nil?
171
+ task.instance_variable_set :@comment, nil
172
+ end
173
+ end
174
+
175
+ # Change working directories to _dir_, call the _block_ of code, and then
176
+ # change back to the original working directory (the current directory when
177
+ # this method was called).
178
+ #
179
+ def in_directory( dir, &block )
180
+ curdir = pwd
181
+ begin
182
+ cd dir
183
+ return block.call
184
+ ensure
185
+ cd curdir
186
+ end
187
+ end
188
+
189
+ # EOF
@@ -0,0 +1,43 @@
1
+ # $Id$
2
+
3
+ if HAVE_SPEC_RAKE_SPECTASK
4
+
5
+ namespace :spec do
6
+
7
+ desc 'Run all specs with basic output'
8
+ Spec::Rake::SpecTask.new(:run) do |t|
9
+ t.spec_opts = PROJ.spec_opts
10
+ t.spec_files = PROJ.specs
11
+ t.libs += PROJ.libs
12
+ end
13
+
14
+ desc 'Run all specs with text output'
15
+ Spec::Rake::SpecTask.new(:specdoc) do |t|
16
+ t.spec_opts = PROJ.spec_opts + ['--format', 'specdoc']
17
+ t.spec_files = PROJ.specs
18
+ t.libs += PROJ.libs
19
+ end
20
+
21
+ if HAVE_RCOV
22
+ desc 'Run all specs with RCov'
23
+ Spec::Rake::SpecTask.new(:rcov) do |t|
24
+ t.spec_opts = PROJ.spec_opts
25
+ t.spec_files = PROJ.specs
26
+ t.libs += PROJ.libs
27
+ t.rcov = true
28
+ t.rcov_opts = PROJ.rcov_opts + ['--exclude', 'spec']
29
+ end
30
+ end
31
+
32
+ end # namespace :spec
33
+
34
+ desc 'Alias to spec:run'
35
+ task :spec => 'spec:run'
36
+
37
+ task :clobber => 'spec:clobber_rcov' if HAVE_RCOV
38
+
39
+ remove_desc_for_task %w(spec:clobber_rcov)
40
+
41
+ end # if HAVE_SPEC_RAKE_SPECTASK
42
+
43
+ # EOF
@@ -0,0 +1,44 @@
1
+ # $Id$
2
+
3
+
4
+ if PROJ.svn and system("svn --version 2>&1 > #{DEV_NULL}")
5
+
6
+ unless PROJ.svn_root
7
+ info = %x/svn info ./
8
+ m = %r/^Repository Root:\s+(.*)$/.match(info)
9
+ PROJ.svn_root = (m.nil? ? '' : m[1])
10
+ end
11
+ PROJ.svn_root = File.join(PROJ.svn_root, PROJ.svn) if String === PROJ.svn
12
+
13
+ namespace :svn do
14
+
15
+ desc 'Show tags from the SVN repository'
16
+ task :show_tags do |t|
17
+ tags = %x/svn list #{File.join(PROJ.svn_root, PROJ.svn_tags)}/
18
+ tags.gsub!(%r/\/$/, '')
19
+ puts tags
20
+ end
21
+
22
+ desc 'Create a new tag in the SVN repository'
23
+ task :create_tag do |t|
24
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
25
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
26
+
27
+ trunk = File.join(PROJ.svn_root, PROJ.svn_trunk)
28
+ tag = "%s-%s" % [PROJ.name, PROJ.version]
29
+ tag = File.join(PROJ.svn_root, PROJ.svn_tags, tag)
30
+ msg = "Creating tag for #{PROJ.name} version #{PROJ.version}"
31
+
32
+ puts "Creating SVN tag '#{tag}'"
33
+ unless system "svn cp -m '#{msg}' #{trunk} #{tag}"
34
+ abort "Tag creation failed"
35
+ end
36
+ end
37
+
38
+ end # namespace :svn
39
+
40
+ task 'gem:release' => 'svn:create_tag'
41
+
42
+ end # if PROJ.svn
43
+
44
+ # EOF
@@ -0,0 +1,40 @@
1
+ # $Id$
2
+
3
+ require 'rake/testtask'
4
+
5
+ namespace :test do
6
+
7
+ Rake::TestTask.new(:run) do |t|
8
+ t.libs = PROJ.libs
9
+ t.test_files = if test ?f, PROJ.test_file then [PROJ.test_file]
10
+ else PROJ.tests end
11
+ t.ruby_opts += PROJ.ruby_opts
12
+ t.ruby_opts += PROJ.test_opts
13
+ end
14
+
15
+ if HAVE_RCOV
16
+ desc 'Run rcov on the unit tests'
17
+ task :rcov => :clobber_rcov do
18
+ opts = PROJ.rcov_opts.join(' ')
19
+ files = if test ?f, PROJ.test_file then [PROJ.test_file]
20
+ else PROJ.tests end
21
+ files = files.join(' ')
22
+ sh "#{RCOV} #{files} #{opts}"
23
+ end
24
+
25
+ desc 'Remove rcov products'
26
+ task :clobber_rcov do
27
+ rm_r 'coverage' rescue nil
28
+ end
29
+ end
30
+
31
+ end # namespace :test
32
+
33
+ desc 'Alias to test:run'
34
+ task :test => 'test:run'
35
+
36
+ task :clobber => 'test:clobber_rcov' if HAVE_RCOV
37
+
38
+ remove_desc_for_task %w(test:clobber_rcov)
39
+
40
+ # EOF
@@ -0,0 +1,53 @@
1
+ require 'test/unit'
2
+
3
+ require 'pyre'
4
+
5
+ class TestPyre < Test::Unit::TestCase
6
+ def setup
7
+ @pyre_campfire = Pyre::Campfire.new('pyre')
8
+ @pyre_email = 'bot@tie-rack.org'
9
+ @pyre_password = 'pyre99bts'
10
+ end
11
+
12
+ def login
13
+ @pyre_campfire.login(@pyre_email, @pyre_password)
14
+ end
15
+
16
+ def test_001_subdomain
17
+ assert_equal('pyre', @pyre_campfire.subdomain)
18
+ end
19
+
20
+ def test_002_uri
21
+ assert_equal('http://pyre.campfirenow.com', @pyre_campfire.uri)
22
+ end
23
+
24
+ def test_003_agent
25
+ assert_kind_of(WWW::Mechanize, @pyre_campfire.instance_variable_get('@agent'))
26
+ end
27
+
28
+ def test_004_login
29
+ assert_equal(false, @pyre_campfire.logged_in?)
30
+ login
31
+ assert(@pyre_campfire.logged_in?, 'Campfire#login failed.')
32
+ end
33
+
34
+ def test_005_login_fails_with_bad_credentials
35
+ assert_equal(false, @pyre_campfire.logged_in?)
36
+ @pyre_campfire.login('not an email', 'not a password')
37
+ assert_equal(false, @pyre_campfire.logged_in?, 'Campfire#login succeeded with bad credentials!')
38
+ end
39
+
40
+ def test_006_rooms
41
+ login
42
+ rooms = @pyre_campfire.rooms
43
+ assert_kind_of(Array, rooms)
44
+ assert_equal(false, rooms.empty?, 'Rooms returns an empty array.')
45
+ end
46
+
47
+ def test_007_logout
48
+ login
49
+ assert(@pyre_campfire.logged_in?, 'Campfire#login failed.')
50
+ @pyre_campfire.logout
51
+ assert_equal(false, @pyre_campfire.logged_in?, 'Campfire#logout failed!')
52
+ end
53
+ end
@@ -0,0 +1,42 @@
1
+ require 'test/unit'
2
+
3
+ require 'pyre'
4
+
5
+ class TestPyreRooms < Test::Unit::TestCase
6
+ def setup
7
+ @pyre_campfire = Pyre::Campfire.new('pyre')
8
+ @pyre_email = 'bot@tie-rack.org'
9
+ @pyre_password = 'pyre99bts'
10
+
11
+ @pyre_campfire.login(@pyre_email, @pyre_password)
12
+
13
+ @pyre_test = @pyre_campfire.find_room_by_name('Pyre Test')
14
+ end
15
+
16
+ def teardown
17
+ @pyre_campfire.logout
18
+ end
19
+
20
+ def test_001_find_room_by_name
21
+ assert_kind_of(Pyre::Room, @pyre_test)
22
+ end
23
+
24
+ def test_002_enter_and_leave_room
25
+ assert_equal(false, @pyre_test.joined?, 'Somehow in the room before joining!')
26
+ @pyre_test.join
27
+ assert(@pyre_test.joined?, 'Room#join failed')
28
+ @pyre_test.leave
29
+ assert_equal(false, @pyre_test.joined?, 'Room#leave failed!')
30
+ assert(@pyre_campfire.logged_in?, 'Room#leave did\'t redirect.')
31
+ end
32
+
33
+ def test_003_interact_with_room
34
+ @pyre_test.join
35
+ assert(@pyre_test.speak("I am speaking at #{Time.now}"))
36
+ assert(@pyre_test.joined?, 'Didn\'t return to room after speaking!')
37
+ assert(@pyre_test.paste("I am pasting\n at #{Time.now}"))
38
+ assert(@pyre_test.joined?, 'Didn\'t return to room after pasting!')
39
+ @pyre_test.leave
40
+ assert_equal(false, @pyre_test.joined?, 'Room#leave failed!')
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ require 'test/unit'
2
+
3
+ require 'pyre'
4
+
5
+ class TestPyreSSL < Test::Unit::TestCase
6
+ def setup
7
+ @qval_campfire = Pyre::Campfire.new('qval', :ssl => true)
8
+ @qval_email = 'chris@myqval.com'
9
+ @qval_password = 'd0rkc0ntr0l'
10
+
11
+ @qval_campfire.login(@qval_email, @qval_password)
12
+ end
13
+
14
+ def teardown
15
+ @qval_campfire.logout
16
+ end
17
+
18
+ def test_001_uri
19
+ assert_equal('https://qval.campfirenow.com', @qval_campfire.uri)
20
+ end
21
+
22
+ def test_002_rooms
23
+ rooms = @qval_campfire.rooms
24
+ assert_kind_of(Array, rooms)
25
+ assert_equal(false, rooms.empty?)
26
+ assert_kind_of(Pyre::Room, rooms.first)
27
+ end
28
+
29
+ def test_004_find_room_by_name
30
+ assert_not_nil(@qval_campfire.find_room_by_name('Qval Development'))
31
+ assert_nil(@qval_campfire.find_room_by_name('Chris is the new owner of Qval'))
32
+ end
33
+
34
+ def test_005_interact_with_room
35
+ tinder_test = @qval_campfire.find_room_by_name('Tinder Test')
36
+ assert_equal(true, tinder_test.join)
37
+ assert_equal(true, tinder_test.speak('Hello from the test suite!'))
38
+ tinder_test.leave
39
+ end
40
+
41
+ def test_006_paste
42
+ tinder_test = @qval_campfire.find_room_by_name('Tinder Test')
43
+ assert_equal(true, tinder_test.join)
44
+ assert_equal(true, tinder_test.paste("Two Liner\nat #{Time.now}"))
45
+ tinder_test.leave
46
+ end
47
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pyre
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Christopher Shea
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-02-16 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mechanize
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.7.0
23
+ version:
24
+ description: Pyre is a library for interacting with Campfire, the web-based group chat site from 37signals. Pyre owes a great deal of debt to Tinder (http://tinder.rubyforge.org)
25
+ email: chris@ruby.tie-rack.org
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - History.txt
32
+ - README.txt
33
+ files:
34
+ - History.txt
35
+ - Manifest.txt
36
+ - README.txt
37
+ - Rakefile
38
+ - lib/pyre.rb
39
+ - lib/pyre/campfire.rb
40
+ - lib/pyre/room.rb
41
+ - spec/pyre_spec.rb
42
+ - spec/spec_helper.rb
43
+ - tasks/annotations.rake
44
+ - tasks/doc.rake
45
+ - tasks/gem.rake
46
+ - tasks/manifest.rake
47
+ - tasks/post_load.rake
48
+ - tasks/rubyforge.rake
49
+ - tasks/setup.rb
50
+ - tasks/spec.rake
51
+ - tasks/svn.rake
52
+ - tasks/test.rake
53
+ has_rdoc: true
54
+ homepage: http://pyre.rubyforge.org
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --main
58
+ - README.txt
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project: pyre
76
+ rubygems_version: 1.0.1
77
+ signing_key:
78
+ specification_version: 2
79
+ summary: Pyre is a library for interacting with Campfire, the web-based group chat site from 37signals
80
+ test_files:
81
+ - test/test_pyre_private.rb
82
+ - test/test_pyre_rooms_private.rb
83
+ - test/test_ssl_private.rb