Skip to content

Commit

Permalink
Initial project commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jsgoecke committed Jan 26, 2011
0 parents commit a336a26
Show file tree
Hide file tree
Showing 18 changed files with 1,669 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .bundle/config
@@ -0,0 +1,2 @@
---
BUNDLE_DISABLE_SHARED_GEMS: "1"
5 changes: 5 additions & 0 deletions .document
@@ -0,0 +1,5 @@
README.rdoc
lib/**/*.rb
bin/*
features/**/*.feature
LICENSE
21 changes: 21 additions & 0 deletions .gitignore
@@ -0,0 +1,21 @@
## MAC OS
.DS_Store

## TEXTMATE
*.tmproj
tmtags

## EMACS
*~
\#*
.\#*

## VIM
*.swp

## PROJECT::GENERAL
coverage
rdoc
pkg

## PROJECT::SPECIFIC
11 changes: 11 additions & 0 deletions Gemfile
@@ -0,0 +1,11 @@
source 'http://rubygems.org'

gem 'mime-types'
gem 'json'

group :development do
gem "rspec", "~> 2.3.0"
gem "bundler", "~> 1.0.0"
gem "jeweler", "~> 1.5.2"
gem "rcov", ">= 0"
end
32 changes: 32 additions & 0 deletions Gemfile.lock
@@ -0,0 +1,32 @@
GEM
remote: http://rubygems.org/
specs:
diff-lcs (1.1.2)
git (1.2.5)
jeweler (1.5.2)
bundler (~> 1.0.0)
git (>= 1.2.5)
rake
json (1.5.1)
mime-types (1.16)
rake (0.8.7)
rcov (0.9.9)
rspec (2.3.0)
rspec-core (~> 2.3.0)
rspec-expectations (~> 2.3.0)
rspec-mocks (~> 2.3.0)
rspec-core (2.3.1)
rspec-expectations (2.3.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.3.0)

PLATFORMS
ruby

DEPENDENCIES
bundler (~> 1.0.0)
jeweler (~> 1.5.2)
json
mime-types
rcov
rspec (~> 2.3.0)
21 changes: 21 additions & 0 deletions LICENSE
@@ -0,0 +1,21 @@
The MIT License

Copyright (c) 2010 Voxeo Corporation

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
45 changes: 45 additions & 0 deletions README.md
@@ -0,0 +1,45 @@
PamFaxr
=======

Ruby library for sending faxes via the [PamFax](http://pamfax.com) Simple API.

Overview
--------

You may send faxes using the PamFax API. See the [PamFax Developer](http://www.pamfax.biz/en/extensions/developers/) page for more details and how to get your developer key.

Requirements
------------

Requires these gems, also in the Gemfile:

* json
* mime-types

Example
-------

# Create a new PamFaxr object
pamfaxr = PamFaxr.new :base_uri => 'https://sandbox-api.pamfax.biz',
:key => 'your_api_key',
:secret => 'your_api_secret',
:username => 'your_username',
:password => 'your_password'
# Create a new FaxJob
pamfaxr.create_fax_job
# Add the cover sheet
covers = pamfaxr.list_available_covers
pamfaxr.set_cover(covers['Covers']['content'][1]['id'], 'Foobar is here!')
# Add files
pamfaxr.add_remote_file('https://s3.amazonaws.com/pamfax-test/R-intro.pdf')
pamfaxr.add_file('examples/R-intro.pdf')
# Add a recipient
pamfaxr.add_recipient('+14155551212')
# Loop until the fax is ready to send
loop do
fax_state = pamfaxr.get_state
break if fax_state['FaxContainer']['state'] == 'ready_to_send'
sleep 5
end
# Send the fax
pamfaxr.send_fax
46 changes: 46 additions & 0 deletions Rakefile
@@ -0,0 +1,46 @@
require 'rubygems'
require 'bundler'
begin
Bundler.setup(:default, :development)
rescue Bundler::BundlerError => e
$stderr.puts e.message
$stderr.puts "Run `bundle install` to install missing gems"
exit e.status_code
end
require 'rake'

require 'jeweler'
Jeweler::Tasks.new do |gem|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
gem.name = "pamfaxr"
gem.homepage = "http://github.com/tropo/pamfaxr"
gem.license = "MIT"
gem.summary = "Ruby library for the PamFax API."
gem.description = "Ruby library for the FaxJob portion of the PamFax API."
gem.email = "jsgoecke@voxeo.com"
gem.authors = ["Jason Goecke"]
end
Jeweler::RubygemsDotOrgTasks.new

require 'rspec/core'
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec) do |spec|
spec.pattern = FileList['spec/**/*_spec.rb']
end

RSpec::Core::RakeTask.new(:rcov) do |spec|
spec.pattern = 'spec/**/*_spec.rb'
spec.rcov = true
end

task :default => :spec

require 'rake/rdoctask'
Rake::RDocTask.new do |rdoc|
version = File.exist?('VERSION') ? File.read('VERSION') : ""

rdoc.rdoc_dir = 'rdoc'
rdoc.title = "foobar #{version}"
rdoc.rdoc_files.include('README*')
rdoc.rdoc_files.include('lib/**/*.rb')
end
1 change: 1 addition & 0 deletions VERSION
@@ -0,0 +1 @@
0.0.1
Binary file added examples/R-intro.pdf
Binary file not shown.
93 changes: 93 additions & 0 deletions examples/example.rb
@@ -0,0 +1,93 @@
require 'rubygems'
require 'lib/pamfaxr'
require 'awesome_print'

PAMFAX_URI = 'https://sandbox-api.pamfax.biz'
PAMFAX_KEY = 'your_key'
PAMFAX_SECRET = 'your_secret'
PAMFAX_USERNAME = 'your_username'
PAMFAX_PASSWORD = 'your_password'

pamfaxr = PamFaxr.new :base_uri => PAMFAX_URI,
:key => PAMFAX_KEY,
:secret => PAMFAX_SECRET,
:username => PAMFAX_USERNAME,
:password => PAMFAX_PASSWORD

# Create a faxjob
faxjob = pamfaxr.create_fax_job
ap 'Creating a fax job'
ap '*'*10
ap faxjob

# Add a cover
covers = pamfaxr.list_available_covers
ap 'Listing available covers'
ap '*'*10
ap covers
ap 'Adding a cover'
ap '*'*10
ap pamfaxr.set_cover(covers['Covers']['content'][1]['id'], 'Foobar is here!')

ap 'Adding a remote file'
ap '*'*10
ap pamfaxr.add_remote_file('https://s3.amazonaws.com/pamfax-test/R-intro.pdf')

ap 'Adding a local file'
ap '*'*10
file = pamfaxr.add_file('examples/R-intro.pdf')
ap file

ap 'Removing a file'
ap '*'*10
ap pamfaxr.remove_file(file['FaxContainerFile']['file_uuid'])

ap 'Adding a recipient'
ap '*'*10
ap pamfaxr.add_recipient('+14155551212')

ap 'Adding a second recipient'
ap '*'*10
recipient = pamfaxr.add_recipient('+13035551212')
ap recipient

ap 'Removing a recipient'
ap '*'*10
ap pamfaxr.remove_file(recipient['FaxRecipient']['number'])

ap 'Listing a recipient'
ap '*'*10
ap pamfaxr.list_recipients

ap 'Listing associated fax files'
ap '*'*10
ap pamfaxr.list_fax_files

ap 'Checking state'
ap '*'*10
time = 0
loop do
fax_state = pamfaxr.get_state
ap fax_state
converting = true
break if fax_state['FaxContainer']['state'] == 'ready_to_send'
sleep 2
time += 2
ap "#{time.to_s} seconds elapsed..."
end

ap 'Preview the fax'
ap '*'*10
ap pamfaxr.get_preview(faxjob['FaxContainer']['uuid'])

ap 'Sent the fax'
ap '*'*10
ap pamfaxr.send_fax

ap 'Sent the fax later'
ap '*'*10
ap pamfaxr.send_fax_later

ap 'Cloning the fax'
ap '*'*10
ap pamfaxr.clone_fax(faxjob['FaxContainer']['uuid'])
2 changes: 2 additions & 0 deletions lib/pamfaxr.rb
@@ -0,0 +1,2 @@
$: << File.expand_path(File.dirname(__FILE__))
%w(json net/http net/https uri socket cgi mime/types base64 pamfaxr/pamfaxr pamfaxr/multipart).each { |lib| require lib }
75 changes: 75 additions & 0 deletions lib/pamfaxr/multipart.rb
@@ -0,0 +1,75 @@
# Takes a hash of string and file parameters and returns a string of text
# formatted to be sent as a multipart form post.
#
# Author:: Cody Brimhall <mailto:cbrimhall@ucdavis.edu>
# Created:: 22 Feb 2008

module Multipart
VERSION = "1.0.0" unless const_defined?(:VERSION)

# Formats a given hash as a multipart form post
# If a hash value responds to :string or :read messages, then it is
# interpreted as a file and processed accordingly; otherwise, it is assumed
# to be a string
class Post
# We have to pretend like we're a web browser...
USERAGENT = "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/523.10.6 (KHTML, like Gecko) Version/3.0.4 Safari/523.10.6" unless const_defined?(:USERAGENT)
BOUNDARY = "0123456789ABLEWASIEREISAWELBA9876543210" unless const_defined?(:BOUNDARY)
CONTENT_TYPE = "multipart/form-data; boundary=#{ BOUNDARY }" unless const_defined?(:CONTENT_TYPE)
HEADER = { "Content-Type" => CONTENT_TYPE, "User-Agent" => USERAGENT } unless const_defined?(:HEADER)

def self.prepare_query(params)
fp = []

params.each do |k, v|
# Are we trying to make a file parameter?
if v.respond_to?(:path) and v.respond_to?(:read) then
fp.push(FileParam.new(k, v.path, v.read))
# We must be trying to make a regular parameter
else
fp.push(StringParam.new(k, v))
end
end

# Assemble the request body using the special multipart format
query = fp.collect {|p| "--" + BOUNDARY + "\r\n" + p.to_multipart }.join("") + "--" + BOUNDARY + "--"
return query, HEADER
end
end

private

# Formats a basic string key/value pair for inclusion with a multipart post
class StringParam
attr_accessor :k, :v

def initialize(k, v)
@k = k
@v = v
end

def to_multipart
return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"\r\n\r\n#{v}\r\n"
end
end

# Formats the contents of a file or string for inclusion with a multipart
# form post
class FileParam
attr_accessor :k, :filename, :content

def initialize(k, filename, content)
@k = k
@filename = filename
@content = content
end

def to_multipart
# If we can tell the possible mime-type from the filename, use the
# first in the list; otherwise, use "application/octet-stream"
mime_type = MIME::Types.type_for(filename)[0] || MIME::Types["application/octet-stream"][0]
return "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"; filename=\"#{ filename }\"\r\n" +
"Content-Type: #{ mime_type.simplified }\r\n\r\n#{ content }\r\n"
end
end
end

0 comments on commit a336a26

Please sign in to comment.