rmm5t-rwebthumb 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,51 @@
1
+ == rwebthumb
2
+
3
+ = what is it
4
+ A Ruby wrapper for the webthumb API from http://webthumb.bluga.net and a generator
5
+ for the easythumb API
6
+
7
+ = Installation
8
+ sudo gem update --system (in case you are not yet on version 1.2.0 or higher)
9
+ sudo gem sources -a http://gems.github.com (only once)
10
+ sudo gem install simplificator-rwebthumb
11
+
12
+
13
+ = Usage
14
+ # require the libs
15
+ require 'rubygems'
16
+ require 'rwebthumb'
17
+ include Simplificator::Webthumb
18
+
19
+ # Creating a Webthumb Object. This is used as your main access point.
20
+ wt = Webthumb.new('YOUR API KEY')
21
+
22
+ # Create a new thumbnail job
23
+ job = wt.thumbnail(:url => 'http://simplificator.com')
24
+
25
+ # fetch the thumbnail. this might throw an exception from server side
26
+ # if thumb is not ready yet
27
+ job.fetch(:large)
28
+
29
+ # you can check the status of a job
30
+ job.check_status()
31
+
32
+ # or fetch the thumbnail when it is complete
33
+ job.fetch_when_complete(:large)
34
+
35
+ # once thumbnails are fetched they are cached within the job. so a new fetch will not go to the server again
36
+
37
+ # there is a helper method to write the images to disk
38
+ job.write_file(job.fetch(:custom), '/tmp/test.jpg')
39
+
40
+ # if you have a job ID then you can use this to get a Job object and then use the fetch_xyz methods
41
+ wt.job_status(JOB_ID)
42
+
43
+ # check the status of your account
44
+ wt.status
45
+
46
+
47
+ # generate a Easythumb URL
48
+ et = Easythumb.new('YOUR_API_KEY', 'YOUR_USER_ID')
49
+ # This returns an URL which you can directly use in your webpage
50
+ et.build_url(:url => 'http://simplificator.com', :size => :large, :cache => 1)
51
+
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'rwebthumb'
@@ -0,0 +1,78 @@
1
+ module Simplificator
2
+ module Webthumb
3
+ #
4
+ #
5
+ #
6
+ #
7
+ class Base
8
+ # Valid output_types for thumbnail requests
9
+ VALID_OUTPUT_TYPES = [:jpg, :png]
10
+ # Valid values for size element in fetch requests
11
+ VALID_SIZES = [:small, :medium, :medium2, :large, :full, :excerpt, :effect, :custom, :zip]
12
+
13
+ attr_reader :api_key
14
+ # Constructor
15
+ # api_key: the Webthumb api key, not nil and not blank
16
+ #
17
+ def initialize(api_key, api_endpoint = 'http://webthumb.bluga.net/api.php')
18
+ raise WebthumbException.new('Need an not nil and not blank api_key') if api_key == nil || api_key == ''
19
+ @api_key = api_key
20
+ @api_endpoint = api_endpoint
21
+ @api_uri = URI.parse(@api_endpoint)
22
+ end
23
+
24
+ # Parse the datetime string and returns a DateTime object in UTC time
25
+ # Webthumb returns the time in MST (Mountain Standard Time) which is some 7 hours
26
+ # behind UTC
27
+ def self.parse_webthumb_datetime(s)
28
+ Time.parse("#{s} MST").getutc
29
+ end
30
+
31
+ def do_request(xml)
32
+ request = Net::HTTP::Post.new(@api_uri.path)
33
+ request.body = xml.to_s
34
+ response = Net::HTTP.new(@api_uri.host, @api_uri.port).start {|p| p.request(request) }
35
+ case response
36
+ when Net::HTTPOK :
37
+ case response.content_type.downcase
38
+ when 'text/xml' : REXML::Document.new(response.body)
39
+ when 'image/jpg', 'image/jpeg', 'image/png'
40
+ raise WebthumbException.new("No data returned though content type is #{response.content_type}") if response.body.length == 0
41
+ response.body
42
+ else
43
+ raise WebthumbException.new("usupported content type #{response.content_type}. Body was: \n#{response.body}")
44
+ end
45
+ else
46
+ raise CommunicationException('Response code was not HTTP OK')
47
+ end
48
+ end
49
+
50
+ # builds the root node for webthumb requtes
51
+ def build_root_node()
52
+ root = REXML::Element.new('webthumb')
53
+ api = root.add_element('apikey')
54
+ api.text = @api_key
55
+ root
56
+ end
57
+
58
+ protected
59
+ #
60
+ # add a XML element if value is present.
61
+ # can be used to create XML for webthumb requests from ruby options hash.
62
+ #
63
+ # root: the root XML element where element is added to
64
+ # options: the hash where value is taken from
65
+ # key: the key to lookup the value in options
66
+ # name: the name of the XML element. defaults to key
67
+ #
68
+ def add_element(root, options, key, name = key.to_s)
69
+ root.add_element(name).add_text(options[key].to_s) if options.has_key?(key)
70
+ end
71
+
72
+ end
73
+ class WebthumbException < RuntimeError
74
+ end
75
+ class CommunicationException < RuntimeError
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,27 @@
1
+ require 'cgi'
2
+ require 'digest/md5'
3
+ module Simplificator
4
+ module Webthumb
5
+ class Easythumb
6
+ VALID_SIZES = [:small, :medium, :medium2, :large]
7
+ def initialize(api_key, user_id, api_endpoint = 'http://webthumb.bluga.net/easythumb.php')
8
+ @api_key = api_key
9
+ @user_id = user_id
10
+ @api_endpoint = api_endpoint
11
+ end
12
+
13
+ # Build an Easythumb URL
14
+ # options are
15
+ # url: the url to take a snapshot from. required.
16
+ # size: the size of the thumbnail to take (VALID_SIZES). Defaults to :medium
17
+ # cache: the maximum allowed age in the cache (1-30). Defaults to 15
18
+ def build_url(options = {})
19
+ raise WebthumbException.new(':url is required') if (options[:url] == nil || options[:url] == '')
20
+ options[:size] ||= :medium
21
+ options[:cache] ||= 15
22
+ hash_out = Digest::MD5.hexdigest("#{Time.now.strftime('%Y%m%d')}#{options[:url]}#{@api_key}")
23
+ "#{@api_endpoint}?user=#{@user_id}&cache=#{options[:cache]}&size=#{options[:size]}&url=#{CGI.escape(options[:url])}&hash=#{hash_out}"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,121 @@
1
+ module Simplificator
2
+ module Webthumb
3
+ class Job < Base
4
+
5
+ attr_reader :duration_estimate, :submission_datetime, :cost, :job_id, :url
6
+
7
+ # Constant for the status attribute when job is beeing processed
8
+ STATUS_PROCESSING = 100
9
+ # Constant for the status attribute when job is done
10
+ STATUS_PICKUP = 200
11
+
12
+ # Factory method to build a Job object from a REXML xml element
13
+ def self.from_thumbnail_xml(api_key, xml)
14
+ job_element = REXML::XPath.first(xml, '/webthumb/jobs/job')
15
+ submission_datetime = self.parse_webthumb_datetime(job_element.attributes['time'])
16
+ Job.new(api_key, job_element.text, job_element.attributes['url'], submission_datetime, job_element.attributes['estimate'].to_i, job_element.attributes['cost'].to_i)
17
+ end
18
+ # Factory method to create a Job object from a status XML.
19
+ # this does not set all attributes of the Job (url, duration_estimate, cost) since the API of webthumb does not
20
+ # return the same information on job creation and status requests.
21
+ def self.from_status_xml(api_key, xml)
22
+ status_element = REXML::XPath.first(xml, '/webthumb/jobStatus/status')
23
+ submission_datetime = self.parse_webthumb_datetime(status_element.attributes['submissionTime'])
24
+ job = Job.new(api_key, status_element.attributes['id'], nil, submission_datetime, 5, nil,
25
+ status_element.text == 'Complete' ? STATUS_PICKUP : STATUS_PROCESSING)
26
+ end
27
+ # Constructor.
28
+ # *api_key: webthumb API key. Required by all the operations which query the server
29
+ # *job_id: id of the job. Required.
30
+ # *url: the url of the site to snapshot. Optional
31
+ # *submission_datetime: UTC Datetime of job submission
32
+ # *duration_estimate: integer value indicating estimated job duration in seconds
33
+ # *cost: integer value indicating how many credit this request costet. Optional
34
+ # *status: one of the STATUS_XXX constants defined in Base. Defaults to STATUS_PROCESSING
35
+ def initialize(api_key, job_id, url, submission_datetime, duration_estimate, cost, status = STATUS_PROCESSING)
36
+ super(api_key)
37
+ @job_id = job_id
38
+ @url = url
39
+ @submission_datetime = submission_datetime
40
+ @duration_estimate = duration_estimate
41
+ @cost = cost
42
+ @status = status
43
+ @cache = {}
44
+ end
45
+
46
+ # Checks the status of the job on webthumb server.
47
+ # Returns one of the STATUS_XXX constants from Base.
48
+ # A call to this method updates the @status attribute.
49
+ def check_status
50
+ response = do_request(build_status_xml())
51
+ @status = REXML::XPath.first(response, '/webthumb/jobStatus/status').text == 'Complete' ? STATUS_PICKUP : STATUS_PROCESSING
52
+ if pickup?
53
+ @completion_time = response.attributes['completionTime']
54
+ end
55
+ @status
56
+ end
57
+
58
+ def fetch_when_complete(size = :small)
59
+ while not pickup?
60
+ sleep @duration_estimate
61
+ check_status
62
+ end
63
+ fetch(size)
64
+ end
65
+
66
+ # Fetch an image from the webthumb server.
67
+ # If the job has not yet finished then the server will return an error so check status first or use fetch_when_complete()
68
+ # Images are cached in the context of this Job so consequent calls are not requested from server again.
69
+ # Cache is experimental, dont know if it is a good idea.
70
+ def fetch(size = :small)
71
+ unless @cache.has_key?(size)
72
+ response = do_request(build_fetch_xml(size))
73
+ @cache[size] = response
74
+ end
75
+ @cache[size]
76
+ end
77
+
78
+ # Write the data to disk.
79
+ # *data: the bytes of the image as returned by fetch/fetch_when_complete
80
+ # *name: a filename
81
+ # Will return a File object
82
+ def write_file(data, name)
83
+ raise WebthumbException.new('NO data given') if data == nil || data.size == 0
84
+ File.open(name, 'wb+') do |file|
85
+ file.write(data)
86
+ file.close
87
+ file
88
+ end
89
+ end
90
+
91
+ # Is the status attribute set to STATUS_PICKUP ?
92
+ def pickup?
93
+ @status == STATUS_PICKUP
94
+ end
95
+ # Is the status attribute set to STATUS_PROCESSING ?
96
+ def processing?
97
+ @status == STATUS_PROCESSING
98
+ end
99
+
100
+ private
101
+ def build_fetch_xml(size = :small)
102
+ raise WebthumbException.new("size parameter must be one of #{VALID_SIZES.join(', ')} but was #{size}") unless Base::VALID_SIZES.include?(size)
103
+ root = build_root_node()
104
+ fetch = root.add_element('fetch')
105
+ fetch.add_element('job').add_text(@job_id)
106
+ fetch.add_element('size').add_text(size.to_s)
107
+ root
108
+ end
109
+ def build_status_xml()
110
+ root = build_root_node()
111
+ status = root.add_element('status')
112
+ status.add_element('job').add_text(@job_id)
113
+ root
114
+ end
115
+
116
+ def to_s
117
+ "Job: #{@job_id} / Status: #{@status} / Submission Time #{@submission_time} / Duration Estimate #{@duration_estimate}"
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,111 @@
1
+ require 'net/http'
2
+ require 'rexml/document'
3
+ require 'date'
4
+ module Simplificator
5
+ module Webthumb
6
+
7
+ #
8
+ # Main access point for the webthumb API.
9
+ # All methods calling the Server need the api key beeing set.
10
+ #
11
+ class Webthumb < Base
12
+ # Request thumbnail creation from webthumb server. A Job object holding
13
+ # request information is returned (most important the job_id)
14
+ # Some keys have been ruby-ized (i.e. outputType -> :output_type). All keys are
15
+ # Symbols. Check out the webthumb API description for detailed explanation of the options
16
+ # http://webthumb.bluga.net/apidoc
17
+ # Options:
18
+ # * url: the url to take the snapshot from
19
+ # * output_type: chose output format (jpg or png)
20
+ # * width: width of the browser
21
+ # * height: height of the browser
22
+ # * fullthumb: full sized snapshot (true or false)
23
+ # * custom_thumbnail: create a custom sized thumbnail. A hash with width and height entries
24
+ # * effect: specify a visual effect (mirror, dropshadow or border)
25
+ # * delay: wait until the snapshot is taken
26
+ # * notify: callback url which is called after snapshot is taken
27
+ # * excerpt: taking an excerpt snapshot. A hash with for entries. width, height, x, y
28
+ # * videothumb: experimental option, check Joshs blog (http://blog.joshuaeichorn.com/archives/2008/07/08/videothumb-addon-to-webthumb-is-alpha/)
29
+ # (true or false)
30
+ # Only the url option is required. Check webthumb API for default values. Check also the different constants
31
+ # defined in Base.rb for valid values
32
+ #
33
+ def thumbnail(options = {})
34
+ Job.from_thumbnail_xml(@api_key, do_request(build_thumbnail_xml(options)))
35
+ end
36
+
37
+ # Request the job status from server.
38
+ # This can be used to look up job status from server when you just have the job ID, e.g. when you want to retrieve
39
+ # the thumbs later or when you use callbacks.
40
+ # The Job object returned from this method does not have all attributes set since. Webthumbs API does not return
41
+ # the requested URL, the duration estimation and the cost values when checking the status. I hope this will change someday.
42
+ def job_status(job_id)
43
+ raise WebthumbException.new('Job id is required') if job_id == nil || job_id == ''
44
+ Job.from_status_xml(@api_key, do_request(build_job_status_xml(job_id)))
45
+ end
46
+
47
+ # Check your credit status on the webthumbs server
48
+ # Returns a hash with two keys. See webthumb API for detailed information.
49
+ # * reserve: an integer
50
+ # * subscription: an integer
51
+ def credits()
52
+ response = do_request(build_credits_xml())
53
+ credit_element = REXML::XPath.first(response, '/webthumb/credits')
54
+ {:reserve => credit_element['reserve'].text.to_i, :subscription => credit_element['subscription'].text.to_i}
55
+ end
56
+
57
+ private
58
+ def build_thumbnail_xml(options)
59
+ validate_thumbnail_options(options)
60
+
61
+
62
+ root = build_root_node()
63
+ request = root.add_element('request')
64
+ request.add_element('url').add_text(options[:url])
65
+ add_element(request, options, :output_type, 'outputType')
66
+ # these elements have the same name as the key in options hash
67
+ [:width, :height, :effect, :delay, :notify].each {|item| add_element(request, options, item)}
68
+ # these options need conversion from true/false to 0/1
69
+ if options[:fullthumb] == true
70
+ request.add_element('fullthumb').add_text('1')
71
+ end
72
+ if options[:videothumb] == true
73
+ request.add_element('videothumb').add_text('1')
74
+ end
75
+ if options.has_key?(:custom_thumbnail)
76
+ request.add_element('customThumbnail',
77
+ 'width' => options[:custom_thumbnail][:width].to_s,
78
+ 'height' => options[:custom_thumbnail][:height].to_s)
79
+
80
+ end
81
+ if options.has_key?(:excerpt)
82
+ excerpt = request.add_element('excerpt')
83
+ [:x, :y, :width, :height].each {|item| add_element(excerpt, options[:excerpt], item)}
84
+ end
85
+ root
86
+ end
87
+
88
+ def build_job_status_xml(job_id)
89
+ root = build_root_node()
90
+ root.add_element('status').add_element('job').add_text(job_id)
91
+ root
92
+ end
93
+
94
+ def build_credits_xml()
95
+ root = build_root_node()
96
+ root.add_element('credits')
97
+ root
98
+ end
99
+
100
+ def validate_thumbnail_options(options)
101
+ raise WebthumbException.new('Need an URL') if options[:url] == nil || options[:url] == ''
102
+ #raise WebthumbException.new("output_type is invalid: #{options[:output_type]}") if options.has_key?(:output_type) and (not Base::VALID_OUTPUT_TYPES.include?(options[:output_type]))
103
+ end
104
+ end
105
+
106
+ end
107
+ end
108
+
109
+
110
+
111
+
data/lib/rwebthumb.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'time'
2
+ require 'rwebthumb/base'
3
+ require 'rwebthumb/job'
4
+ require 'rwebthumb/webthumb'
5
+ require 'rwebthumb/easythumb'
data/test/base_test.rb ADDED
@@ -0,0 +1,23 @@
1
+ require File.join(File.dirname(__FILE__), 'helper')
2
+ class BaseTest < Test::Unit::TestCase
3
+ def test_api_key_required
4
+ assert_raises(WebthumbException) { Base.new('') }
5
+ assert_raises(WebthumbException) { Base.new(nil) }
6
+ end
7
+
8
+ def test_parse_webthumb_date
9
+ [['2000-1-1 14:00:00', '2000-1-1 07:00:00'], ['2000-1-1 07:00:00', '2000-1-1 00:00:00'], ['2000-8-1 07:44:2', '2000-8-1 00:44:02']].each do |item|
10
+ utc = Time.parse("#{item[0]} UTC")
11
+ mst = Base.parse_webthumb_datetime(item[1])
12
+ assert_equal(utc, mst)
13
+ end
14
+ end
15
+
16
+ def test_build_root_node()
17
+ root = Base.new('1234').build_root_node()
18
+ assert_not_nil(root)
19
+ assert_not_nil(REXML::XPath.first(root, '/'))
20
+ assert_not_nil(REXML::XPath.first(root, '/apikey'))
21
+ assert_equal('1234', REXML::XPath.first(root, '/apikey').text)
22
+ end
23
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'rwebthumb'
4
+ include Simplificator::Webthumb
data/test/job_test.rb ADDED
@@ -0,0 +1,35 @@
1
+ require File.join(File.dirname(__FILE__), 'helper')
2
+ class JobTest < Test::Unit::TestCase
3
+ def setup()
4
+ xml = <<-EOF
5
+ <webthumb>
6
+ <jobs>
7
+ <job estimate='20' time='2008-02-27 12:49:48' url='http://blog.joshuaeichorn.com' cost='1'>wt47c5f71c37c3a</job>
8
+ </jobs>
9
+ </webthumb>
10
+ EOF
11
+ job_xml = REXML::Document.new(xml)
12
+ @job = Job.from_thumbnail_xml('1234', job_xml)
13
+ end
14
+ def test_from_thumbnail_xml
15
+
16
+ assert_equal('1234', @job.api_key)
17
+ assert_equal(20, @job.duration_estimate)
18
+ assert_equal(Time.parse('2008-02-27 19:49:48 UTC'), @job.submission_datetime)
19
+ assert_equal('http://blog.joshuaeichorn.com', @job.url)
20
+ assert_equal(1, @job.cost)
21
+ assert_equal('wt47c5f71c37c3a', @job.job_id)
22
+ end
23
+
24
+
25
+ def test_build_fetch()
26
+ xml = @job.send(:build_fetch_xml)
27
+ assert_equal('small', REXML::XPath.first(xml, 'fetch/size').text)
28
+ assert_equal('wt47c5f71c37c3a', REXML::XPath.first(xml, 'fetch/job').text)
29
+ end
30
+
31
+ def test_build_status_xml()
32
+ xml = @job.send(:build_status_xml)
33
+ assert_equal('wt47c5f71c37c3a', REXML::XPath.first(xml, 'status/job').text)
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ require File.join(File.dirname(__FILE__), 'helper')
2
+ class WebthumbTest < Test::Unit::TestCase
3
+
4
+
5
+
6
+ def test_build_fetch()
7
+ xml = Webthumb.new('1234').send(:build_thumbnail_xml,
8
+ :url => 'http://simplificator.com',
9
+ :videothumb => true, :fullthumb => true, :effect => 'dropshadow', :output_type => :jpg,
10
+ :width => 1024, :height => 2048, :custom_thumbnail => {:width => 300, :height => 400},
11
+ :excerpt => {:x => 30, :y => 40, :width => 600, :height => 345}, :delay => 20, :notify => 'http://foo.bar.com')
12
+ assert_equal('http://simplificator.com', REXML::XPath.first(xml, 'request/url').text)
13
+ assert_equal('1', REXML::XPath.first(xml, 'request/videothumb').text)
14
+ assert_equal('1', REXML::XPath.first(xml, 'request/fullthumb').text)
15
+ assert_equal('dropshadow', REXML::XPath.first(xml, 'request/effect').text)
16
+ assert_equal('jpg', REXML::XPath.first(xml, 'request/outputType').text)
17
+ assert_equal('1024', REXML::XPath.first(xml, 'request/width').text)
18
+ assert_equal('2048', REXML::XPath.first(xml, 'request/height').text)
19
+ assert_equal('300', REXML::XPath.first(xml, 'request/customThumbnail').attributes['width'])
20
+ assert_equal('400', REXML::XPath.first(xml, 'request/customThumbnail').attributes['height'])
21
+ assert_equal('30', REXML::XPath.first(xml, 'request/excerpt/x').text)
22
+ assert_equal('40', REXML::XPath.first(xml, 'request/excerpt/y').text)
23
+ assert_equal('600', REXML::XPath.first(xml, 'request/excerpt/width').text)
24
+ assert_equal('345', REXML::XPath.first(xml, 'request/excerpt/height').text)
25
+ assert_equal('20', REXML::XPath.first(xml, 'request/delay').text)
26
+ assert_equal('http://foo.bar.com', REXML::XPath.first(xml, 'request/notify').text)
27
+
28
+
29
+ end
30
+
31
+ def test_build_job_status_xml()
32
+ xml = Webthumb.new('1234').send(:build_job_status_xml, 'abcd')
33
+ assert_equal('abcd', REXML::XPath.first(xml, 'status/job').text)
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rmm5t-rwebthumb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.6
5
+ platform: ruby
6
+ authors:
7
+ - Simplificator GmbH
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-09-03 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: rwebthumb provides a ruby interface for the webthumb.bluga.net
17
+ email: info@simplificator.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/rwebthumb.rb
26
+ - lib/rwebthumb/base.rb
27
+ - lib/rwebthumb/job.rb
28
+ - lib/rwebthumb/webthumb.rb
29
+ - test/base_test.rb
30
+ - test/helper.rb
31
+ - test/job_test.rb
32
+ - test/webthumb_test.rb
33
+ - lib/rwebthumb/easythumb.rb
34
+ - README
35
+ - init.rb
36
+ has_rdoc: false
37
+ homepage: http://simplificator.com/
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ requirements: []
56
+
57
+ rubyforge_project:
58
+ rubygems_version: 1.2.0
59
+ signing_key:
60
+ specification_version: 2
61
+ summary: rwebthumb provides a ruby interface for the webthumb.bluga.net
62
+ test_files: []
63
+