├── .gitignore ├── LICENSE ├── README.md ├── lib ├── lighthouse-api.rb ├── lighthouse.rb └── lighthouse │ ├── base.rb │ ├── bin.rb │ ├── changeset.rb │ ├── console.rb │ ├── core_ext │ └── uri.rb │ ├── membership.rb │ ├── message.rb │ ├── milestone.rb │ ├── project.rb │ ├── project_membership.rb │ ├── tag.rb │ ├── tag_resource.rb │ ├── ticket.rb │ ├── token.rb │ └── user.rb └── lighthouse-api.gemspec /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | pkg 3 | doc 4 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008 Active Reload, LLC 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Lighthouse API 2 | -------------- 3 | 4 | The official Ruby library for interacting with the [Lighthouse REST API](http://lighthouseapp.com/api). 5 | 6 | ### Documentation & Requirements 7 | * ActiveResource 8 | * ActiveSupport 9 | 10 | Check out lib/lighthouse.rb for examples and documentation. 11 | 12 | 13 | ### Using The Lighthouse Console 14 | 15 | The Lighthouse library comes with a convenient console for testing and quick commands 16 | (or whatever else you want to use it for). 17 | 18 | From /lib: 19 | 20 | # For ruby 1.9 21 | # irb -I. -r lighthouse/console.rb 22 | 23 | irb -r lighthouse/console 24 | 25 | Lighthouse.account = "activereload" 26 | 27 | #### You can use `authenticate` OR `token` 28 | Lighthouse.authenticate('username', 'password') 29 | #Lighthouse.token = 'YOUR_TOKEN' 30 | 31 | Project.find(:all) 32 | 33 | ### Contributions 34 | * technoweenie (rick) 35 | * caged (Justin Palmer) 36 | * granth (Grant Hollingworth) 37 | * kneath (Kyle Neath) 38 | * djanowski (Damian Janowski) 39 | * drnic (Dr Nic Williams) 40 | * texel (Leigh Caplan) 41 | * trptcolin (Colin Jones) 42 | * cyberfox (Morgan Schweers) 43 | * krekoten (Крекотень Мар'ян) 44 | 45 | 46 | -------------------------------------------------------------------------------- /lib/lighthouse-api.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), "lighthouse") -------------------------------------------------------------------------------- /lib/lighthouse.rb: -------------------------------------------------------------------------------- 1 | $: << File.dirname(__FILE__) unless $:.include?(File.dirname(__FILE__)) 2 | 3 | require 'rubygems' 4 | require 'lighthouse/core_ext/uri' 5 | require 'active_support' 6 | require 'active_resource' 7 | 8 | # required for ruby < 1.9. constants(false) emaulation in active_support is buggy. 9 | require 'lighthouse/base' 10 | 11 | # Ruby lib for working with the Lighthouse API's XML interface. 12 | # The first thing you need to set is the account name. This is the same 13 | # as the web address for your account. 14 | # 15 | # Lighthouse.account = 'activereload' 16 | # 17 | # Then, you should set the authentication. You can either use your login 18 | # credentials with HTTP Basic Authentication or with an API Tokens. You can 19 | # find more info on tokens at http://lighthouseapp.com/help/using-beacons. 20 | # 21 | # # with basic authentication 22 | # Lighthouse.authenticate('rick@techno-weenie.net', 'spacemonkey') 23 | # 24 | # # or, use a token 25 | # Lighthouse.token = 'abcdefg' 26 | # 27 | # If no token or authentication info is given, you'll only be granted public access. 28 | # 29 | # This library is a small wrapper around the REST interface. You should read the docs at 30 | # http://lighthouseapp.com/api. 31 | # 32 | module Lighthouse 33 | 34 | extend ActiveSupport::Autoload 35 | 36 | autoload :Bin 37 | autoload :Changeset 38 | autoload :Membership 39 | autoload :Message 40 | autoload :Milestone 41 | autoload :Project 42 | autoload :ProjectMembership 43 | autoload :Tag 44 | autoload :TagResource 45 | autoload :Ticket 46 | autoload :Token 47 | autoload :User 48 | 49 | class Error < StandardError; end 50 | 51 | class Change < Array; end 52 | 53 | class << self 54 | attr_accessor :account, :email, :password, :host_format, :domain_format, :protocol, :port 55 | attr_reader :token 56 | 57 | # Sets up basic authentication credentials for all the resources. 58 | def authenticate(email, password) 59 | self.email = email 60 | self.password = password 61 | 62 | resources.each do |klass| 63 | update_auth(klass) 64 | end 65 | end 66 | 67 | # Sets the API token for all the resources. 68 | def token=(value) 69 | @token = value 70 | resources.each do |klass| 71 | update_token_header(klass) 72 | end 73 | end 74 | 75 | def resources 76 | @resources ||= [] 77 | end 78 | 79 | def update_site(resource) 80 | resource.site = resource.site_format % (host_format % [protocol, domain_format % account, ":#{port}"]) 81 | end 82 | 83 | def update_token_header(resource) 84 | resource.headers['X-LighthouseToken'] = token if token 85 | end 86 | 87 | def update_auth(resource) 88 | return unless email && password 89 | resource.user = email 90 | resource.password = password 91 | end 92 | end 93 | 94 | self.host_format = '%s://%s%s' 95 | self.domain_format = '%s.lighthouseapp.com' 96 | self.protocol = 'http' 97 | self.port = '' 98 | end 99 | -------------------------------------------------------------------------------- /lib/lighthouse/base.rb: -------------------------------------------------------------------------------- 1 | module Lighthouse 2 | class Base < ActiveResource::Base 3 | def self.inherited(base) 4 | Lighthouse.resources << base 5 | class << base 6 | attr_accessor :site_format 7 | 8 | def site_with_update 9 | Lighthouse.update_site(self) 10 | site_without_update 11 | end 12 | alias_method_chain :site, :update 13 | end 14 | base.site_format = '%s' 15 | super 16 | Lighthouse.update_token_header(base) 17 | Lighthouse.update_auth(base) 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/lighthouse/bin.rb: -------------------------------------------------------------------------------- 1 | module Lighthouse 2 | class Bin < Base 3 | site_format << '/projects/:project_id' 4 | 5 | def tickets(options = {}) 6 | Ticket.find(:all, :params => options.merge(prefix_options).update(:q => query)) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/lighthouse/changeset.rb: -------------------------------------------------------------------------------- 1 | module Lighthouse 2 | class Changeset < Base 3 | site_format << '/projects/:project_id' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/lighthouse/console.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lighthouse')) 2 | puts <<-TXT 3 | Ruby lib for working with the Lighthouse API's XML interface. 4 | The first thing you need to set is the account name. This is the same 5 | as the web address for your account. 6 | 7 | Lighthouse.account = 'activereload' 8 | 9 | Then, you should set the authentication. You can either use your login 10 | credentials with HTTP Basic Authentication or with an API Tokens. You can 11 | find more info on tokens at http://lighthouseapp.com/help/using-beacons. 12 | 13 | # with basic authentication 14 | Lighthouse.authenticate('rick@techno-weenie.net', 'spacemonkey') 15 | 16 | # or, use a token 17 | Lighthouse.token = 'abcdefg' 18 | 19 | If no token or authentication info is given, you'll only be granted public access. 20 | 21 | This library is a small wrapper around the REST interface. You should read the docs at 22 | http://lighthouseapp.com/api. 23 | TXT 24 | 25 | include Lighthouse -------------------------------------------------------------------------------- /lib/lighthouse/core_ext/uri.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require 'uri' 3 | require 'addressable/uri' 4 | 5 | module URI 6 | def decode(*args) 7 | Addressable::URI.decode(*args) 8 | end 9 | 10 | def escape(*args) 11 | Addressable::URI.escape(*args) 12 | end 13 | 14 | def parse(*args) 15 | Addressable::URI.parse(*args) 16 | end 17 | end 18 | rescue LoadError => e 19 | puts "Install the Addressable gem (with dependencies) to support accounts with subdomains." 20 | puts "# sudo gem install addressable --development" 21 | puts e.message 22 | end -------------------------------------------------------------------------------- /lib/lighthouse/membership.rb: -------------------------------------------------------------------------------- 1 | module Lighthouse 2 | class Membership < Base 3 | site_format << '/users/:user_id' 4 | def save 5 | raise Error, "Cannot modify memberships from the API" 6 | end 7 | end 8 | end -------------------------------------------------------------------------------- /lib/lighthouse/message.rb: -------------------------------------------------------------------------------- 1 | module Lighthouse 2 | class Message < Base 3 | site_format << '/projects/:project_id' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/lighthouse/milestone.rb: -------------------------------------------------------------------------------- 1 | module Lighthouse 2 | class Milestone < Base 3 | site_format << '/projects/:project_id' 4 | 5 | def tickets(options = {}) 6 | Ticket.find(:all, :params => options.merge(prefix_options).update(:q => %{milestone:"#{title}"})) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/lighthouse/project.rb: -------------------------------------------------------------------------------- 1 | module Lighthouse 2 | # Find projects 3 | # 4 | # Lighthouse::Project.find(:all) # find all projects for the current account. 5 | # Lighthouse::Project.find(44) # find individual project by ID 6 | # 7 | # Creating a Project 8 | # 9 | # project = Lighthouse::Project.new(:name => 'Ninja Whammy Jammy') 10 | # project.save 11 | # # => true 12 | # 13 | # Creating an OSS project 14 | # 15 | # project = Lighthouse::Project.new(:name => 'OSS Project') 16 | # project.access = 'oss' 17 | # project.license = 'mit' 18 | # project.save 19 | # 20 | # OSS License Mappings 21 | # 22 | # 'mit' => "MIT License", 23 | # 'apache-2-0' => "Apache License 2.0", 24 | # 'artistic-gpl-2' => "Artistic License/GPLv2", 25 | # 'gpl-2' => "GNU General Public License v2", 26 | # 'gpl-3' => "GNU General Public License v3", 27 | # 'lgpl' => "GNU Lesser General Public License" 28 | # 'mozilla-1-1' => "Mozilla Public License 1.1" 29 | # 'new-bsd' => "New BSD License", 30 | # 'afl-3' => "Academic Free License v. 3.0" 31 | 32 | # 33 | # Updating a Project 34 | # 35 | # project = Lighthouse::Project.find(44) 36 | # project.name = "Lighthouse Issues" 37 | # project.public = false 38 | # project.save 39 | # 40 | # Finding tickets 41 | # 42 | # project = Lighthouse::Project.find(44) 43 | # project.tickets 44 | # 45 | class Project < Base 46 | def tickets(options = {}) 47 | Ticket.find(:all, :params => options.update(:project_id => id)) 48 | end 49 | 50 | def messages(options = {}) 51 | Message.find(:all, :params => options.update(:project_id => id)) 52 | end 53 | 54 | def milestones(options = {}) 55 | Milestone.find(:all, :params => options.update(:project_id => id)) 56 | end 57 | 58 | def bins(options = {}) 59 | Bin.find(:all, :params => options.update(:project_id => id)) 60 | end 61 | 62 | def changesets(options = {}) 63 | Changeset.find(:all, :params => options.update(:project_id => id)) 64 | end 65 | 66 | def memberships(options = {}) 67 | ProjectMembership.find(:all, :params => options.update(:project_id => id)) 68 | end 69 | 70 | def tags(options = {}) 71 | TagResource.find(:all, :params => options.update(:project_id => id)) 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /lib/lighthouse/project_membership.rb: -------------------------------------------------------------------------------- 1 | module Lighthouse 2 | class ProjectMembership < Base 3 | self.element_name = 'membership' 4 | self.site_format << "/projects/:project_id" 5 | 6 | def save 7 | raise Error, "Cannot modify memberships from the API" 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/lighthouse/tag.rb: -------------------------------------------------------------------------------- 1 | require 'active_support/core_ext/module/attr_accessor_with_default' 2 | 3 | module Lighthouse 4 | class Tag < String 5 | attr_accessor_with_default :prefix_options, {} 6 | attr_accessor :project_id 7 | 8 | def initialize(s, project_id) 9 | self.project_id = project_id 10 | super(s) 11 | end 12 | 13 | def tickets(options = {}) 14 | options[:project_id] ||= project_id 15 | Ticket.find(:all, :params => options.merge(prefix_options).update(:q => %{tagged:"#{self}"})) 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/lighthouse/tag_resource.rb: -------------------------------------------------------------------------------- 1 | module Lighthouse 2 | class TagResource < Base 3 | self.element_name = 'tag' 4 | site_format << '/projects/:project_id' 5 | 6 | def name 7 | @name ||= Tag.new(attributes['name'], prefix_options[:project_id]) 8 | end 9 | 10 | def tickets(options = {}) 11 | name.tickets(options) 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/lighthouse/ticket.rb: -------------------------------------------------------------------------------- 1 | module Lighthouse 2 | # Find tickets 3 | # 4 | # Lighthouse::Ticket.find(:all, :params => { :project_id => 44 }) 5 | # Lighthouse::Ticket.find(:all, :params => { :project_id => 44, :q => "state:closed tagged:committed" }) 6 | # 7 | # project = Lighthouse::Project.find(44) 8 | # project.tickets 9 | # project.tickets(:q => "state:closed tagged:committed") 10 | # 11 | # Creating a Ticket 12 | # 13 | # ticket = Lighthouse::Ticket.new(:project_id => 44) 14 | # ticket.title = 'asdf' 15 | # ... 16 | # ticket.tags << 'ruby' << 'rails' << '@high' 17 | # ticket.save 18 | # 19 | # Updating a Ticket 20 | # 21 | # ticket = Lighthouse::Ticket.find(20, :params => { :project_id => 44 }) 22 | # ticket.state = 'resolved' 23 | # ticket.tags.delete '@high' 24 | # ticket.save 25 | # 26 | class Ticket < Base 27 | 28 | attr_writer :tags 29 | site_format << '/projects/:project_id' 30 | 31 | def id 32 | attributes['number'] ||= nil 33 | number 34 | end 35 | 36 | def tags 37 | attributes['tag'] ||= nil 38 | @tags ||= tag.blank? ? [] : parse_with_spaces(tag) 39 | end 40 | 41 | def body 42 | attributes['body'] ||= '' 43 | end 44 | 45 | def body=(value) 46 | attributes['body'] = value 47 | end 48 | 49 | def body_html 50 | attributes['body_html'] ||= '' 51 | end 52 | 53 | def body_html=(value) 54 | attributes['body_html'] = value 55 | end 56 | 57 | def save_with_tags 58 | self.tag = self.tags.collect do |tag| 59 | tag.include?(' ') ? tag.inspect : tag 60 | end.join(" ") if self.tags.is_a?(Array) 61 | 62 | self.tags = nil 63 | 64 | save_without_tags 65 | end 66 | 67 | alias_method_chain :save, :tags 68 | 69 | private 70 | # taken from Lighthouse Tag code 71 | def parse_with_spaces(list) 72 | tags = [] 73 | 74 | # first, pull out the quoted tags 75 | list.gsub!(/\"(.*?)\"\s*/ ) { tags << $1; "" } 76 | 77 | # then, get whatever's left 78 | tags.concat list.split(/\s/) 79 | 80 | cleanup_tags(tags) 81 | end 82 | 83 | def cleanup_tags(tags) 84 | tags.tap do |tag| 85 | tag.collect! do |t| 86 | unless tag.blank? 87 | t = Tag.new(t,prefix_options[:project_id]) 88 | t.downcase! 89 | t.gsub! /(^')|('$)/, '' 90 | t.gsub! /[^a-z0-9 \-_@\!']/, '' 91 | t.strip! 92 | t.prefix_options = prefix_options 93 | t 94 | end 95 | end 96 | tag.compact! 97 | tag.uniq! 98 | end 99 | end 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /lib/lighthouse/token.rb: -------------------------------------------------------------------------------- 1 | module Lighthouse 2 | class Token < Base 3 | def save 4 | raise Error, "Cannot modify Tokens from the API" 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/lighthouse/user.rb: -------------------------------------------------------------------------------- 1 | module Lighthouse 2 | class User < Base 3 | def memberships(options = {}) 4 | Membership.find(:all, :params => {:user_id => id}) 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lighthouse-api.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = %q{lighthouse-api} 3 | s.version = "2.0" 4 | 5 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= 6 | s.authors = ["Rick Olson", "Justin Palmer"] 7 | s.email = ["justin@entp.com"] 8 | s.extra_rdoc_files = ["LICENSE"] 9 | s.files = Dir.glob("lib/**/*") + %w(LICENSE README.md) 10 | s.has_rdoc = true 11 | s.homepage = 'http://lighthouseapp.com/api' 12 | s.rdoc_options = ["--main", "README.md"] 13 | s.require_paths = ["lib"] 14 | s.rubyforge_project = 'lighthouse' 15 | s.rubygems_version = '1.2.0' 16 | s.summary = %q{Ruby API wrapper for Lighthouse - http://lighthouseapp.com} 17 | s.description = %q{Ruby API wrapper for Lighthouse - http://lighthouseapp.com} 18 | s.test_files = [] 19 | 20 | s.add_dependency(%q, [">= 3.0.0"]) 21 | s.add_dependency(%q, [">= 3.0.0"]) 22 | end 23 | --------------------------------------------------------------------------------