yoomee-rwebthumb 0.2.13

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.
data/README ADDED
@@ -0,0 +1,47 @@
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
+ # generate a Easythumb URL
44
+ et = Easythumb.new('YOUR_API_KEY', 'YOUR_USER_ID')
45
+ # This returns an URL which you can directly use in your webpage
46
+ et.build_url(:url => 'http://simplificator.com', :size => :large, :cache => 1)
47
+
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'rwebthumb'
@@ -0,0 +1,5 @@
1
+ require 'time'
2
+ require 'rwebthumb/base'
3
+ require 'rwebthumb/job'
4
+ require 'rwebthumb/webthumb'
5
+ require 'rwebthumb/easythumb'
@@ -0,0 +1,82 @@
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'
39
+ REXML::Document.new(response.body)
40
+ when 'text/plain'
41
+ raise WebthumbException.new("Unsupported content type #{response.content_type}: Body was: #{response.body}")
42
+ when 'image/jpg', 'image/jpeg', 'image/png', 'archive/zip'
43
+ raise WebthumbException.new("No data returned though content type is #{response.content_type}") if response.body.length == 0
44
+ response.body
45
+ else
46
+ raise WebthumbException.new("Unsupported content type #{response.content_type}")
47
+ end
48
+ else
49
+ raise CommunicationException('Response code was not HTTP OK')
50
+ end
51
+ end
52
+
53
+
54
+ # builds the root node for webthumb requtes
55
+ def build_root_node()
56
+ root = REXML::Element.new('webthumb')
57
+ api = root.add_element('apikey')
58
+ api.text = @api_key
59
+ root
60
+ end
61
+
62
+ protected
63
+ #
64
+ # add a XML element if value is present.
65
+ # can be used to create XML for webthumb requests from ruby options hash.
66
+ #
67
+ # root: the root XML element where element is added to
68
+ # options: the hash where value is taken from
69
+ # key: the key to lookup the value in options
70
+ # name: the name of the XML element. defaults to key
71
+ #
72
+ def add_element(root, options, key, name = key.to_s)
73
+ root.add_element(name).add_text(options[key].to_s) if options.has_key?(key)
74
+ end
75
+
76
+ end
77
+ class WebthumbException < RuntimeError
78
+ end
79
+ class CommunicationException < RuntimeError
80
+ end
81
+ end
82
+ 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,123 @@
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
+ return nil if job_element.nil?
16
+
17
+ submission_datetime = self.parse_webthumb_datetime(job_element.attributes['time'])
18
+ 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)
19
+ end
20
+ # Factory method to create a Job object from a status XML.
21
+ # this does not set all attributes of the Job (url, duration_estimate, cost) since the API of webthumb does not
22
+ # return the same information on job creation and status requests.
23
+ def self.from_status_xml(api_key, xml)
24
+ status_element = REXML::XPath.first(xml, '/webthumb/jobStatus/status')
25
+ submission_datetime = self.parse_webthumb_datetime(status_element.attributes['submissionTime'])
26
+ job = Job.new(api_key, status_element.attributes['id'], nil, submission_datetime, 5, nil,
27
+ status_element.text == 'Complete' ? STATUS_PICKUP : STATUS_PROCESSING)
28
+ end
29
+ # Constructor.
30
+ # *api_key: webthumb API key. Required by all the operations which query the server
31
+ # *job_id: id of the job. Required.
32
+ # *url: the url of the site to snapshot. Optional
33
+ # *submission_datetime: UTC Datetime of job submission
34
+ # *duration_estimate: integer value indicating estimated job duration in seconds
35
+ # *cost: integer value indicating how many credit this request costet. Optional
36
+ # *status: one of the STATUS_XXX constants defined in Base. Defaults to STATUS_PROCESSING
37
+ def initialize(api_key, job_id, url, submission_datetime, duration_estimate, cost, status = STATUS_PROCESSING)
38
+ super(api_key)
39
+ @job_id = job_id
40
+ @url = url
41
+ @submission_datetime = submission_datetime
42
+ @duration_estimate = duration_estimate
43
+ @cost = cost
44
+ @status = status
45
+ @cache = {}
46
+ end
47
+
48
+ # Checks the status of the job on webthumb server.
49
+ # Returns one of the STATUS_XXX constants from Base.
50
+ # A call to this method updates the @status attribute.
51
+ def check_status
52
+ response = do_request(build_status_xml())
53
+ @status = REXML::XPath.first(response, '/webthumb/jobStatus/status').text == 'Complete' ? STATUS_PICKUP : STATUS_PROCESSING
54
+ if pickup?
55
+ @completion_time = response.attributes['completionTime']
56
+ end
57
+ @status
58
+ end
59
+
60
+ def fetch_when_complete(size = :small)
61
+ while not pickup?
62
+ sleep @duration_estimate
63
+ check_status
64
+ end
65
+ fetch(size)
66
+ end
67
+
68
+ # Fetch an image from the webthumb server.
69
+ # If the job has not yet finished then the server will return an error so check status first or use fetch_when_complete()
70
+ # Images are cached in the context of this Job so consequent calls are not requested from server again.
71
+ # Cache is experimental, dont know if it is a good idea.
72
+ def fetch(size = :small)
73
+ unless @cache.has_key?(size)
74
+ response = do_request(build_fetch_xml(size))
75
+ @cache[size] = response
76
+ end
77
+ @cache[size]
78
+ end
79
+
80
+ # Write the data to disk.
81
+ # *data: the bytes of the image as returned by fetch/fetch_when_complete
82
+ # *name: a filename
83
+ # Will return a File object
84
+ def write_file(data, name)
85
+ raise WebthumbException.new('No data given') if data == nil || data.size == 0
86
+ File.open(name, 'wb+') do |file|
87
+ file.write(data)
88
+ file.close
89
+ file
90
+ end
91
+ end
92
+
93
+ # Is the status attribute set to STATUS_PICKUP ?
94
+ def pickup?
95
+ @status == STATUS_PICKUP
96
+ end
97
+ # Is the status attribute set to STATUS_PROCESSING ?
98
+ def processing?
99
+ @status == STATUS_PROCESSING
100
+ end
101
+
102
+ private
103
+ def build_fetch_xml(size = :small)
104
+ raise WebthumbException.new("size parameter must be one of #{VALID_SIZES.join(', ')} but was #{size}") unless Base::VALID_SIZES.include?(size)
105
+ root = build_root_node()
106
+ fetch = root.add_element('fetch')
107
+ fetch.add_element('job').add_text(@job_id)
108
+ fetch.add_element('size').add_text(size.to_s)
109
+ root
110
+ end
111
+ def build_status_xml()
112
+ root = build_root_node()
113
+ status = root.add_element('status')
114
+ status.add_element('job').add_text(@job_id)
115
+ root
116
+ end
117
+
118
+ def to_s
119
+ "Job: #{@job_id} / Status: #{@status} / Submission Time #{@submission_time} / Duration Estimate #{@duration_estimate}"
120
+ end
121
+ end
122
+ end
123
+ 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_elements = REXML::XPath.first(response, '/webthumb/credits').elements
54
+ {:reserve => credit_elements['reserve'].text.to_i, :subscription => credit_elements['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
+
@@ -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
@@ -0,0 +1,4 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'rwebthumb'
4
+ include Simplificator::Webthumb
@@ -0,0 +1,48 @@
1
+ require File.join(File.dirname(__FILE__), 'helper')
2
+ class JobTest < Test::Unit::TestCase
3
+ JOB_XML = <<-EOF
4
+ <webthumb>
5
+ <jobs>
6
+ <job estimate='20' time='2008-02-27 12:49:48' url='http://blog.joshuaeichorn.com' cost='1'>wt47c5f71c37c3a</job>
7
+ </jobs>
8
+ </webthumb>
9
+ EOF
10
+
11
+ JOBLESS_XML = <<-EOF
12
+ <webthumb>
13
+ </webthumb>
14
+ EOF
15
+
16
+ def setup_job_from_xml(xml)
17
+ job_xml = REXML::Document.new(xml)
18
+ @job = Job.from_thumbnail_xml('1234', job_xml)
19
+ end
20
+
21
+ def test_from_thumbnail_xml
22
+ setup_job_from_xml(JOB_XML)
23
+ assert_equal('1234', @job.api_key)
24
+ assert_equal(20, @job.duration_estimate)
25
+ assert_equal(Time.parse('2008-02-27 19:49:48 UTC'), @job.submission_datetime)
26
+ assert_equal('http://blog.joshuaeichorn.com', @job.url)
27
+ assert_equal(1, @job.cost)
28
+ assert_equal('wt47c5f71c37c3a', @job.job_id)
29
+ end
30
+
31
+ def test_build_fetch()
32
+ setup_job_from_xml(JOB_XML)
33
+ xml = @job.send(:build_fetch_xml)
34
+ assert_equal('small', REXML::XPath.first(xml, 'fetch/size').text)
35
+ assert_equal('wt47c5f71c37c3a', REXML::XPath.first(xml, 'fetch/job').text)
36
+ end
37
+
38
+ def test_build_status_xml()
39
+ setup_job_from_xml(JOB_XML)
40
+ xml = @job.send(:build_status_xml)
41
+ assert_equal('wt47c5f71c37c3a', REXML::XPath.first(xml, 'status/job').text)
42
+ end
43
+
44
+ def test_from_thumbnail_xml_without_any_jobs()
45
+ setup_job_from_xml(JOBLESS_XML)
46
+ assert_nil @job
47
+ end
48
+ 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,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yoomee-rwebthumb
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 13
9
+ version: 0.2.13
10
+ platform: ruby
11
+ authors:
12
+ - Simplificator GmbH
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-16 00:00:00 +00:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: "rwebthumb provides a ruby interface for the webthumb.bluga.net. "
22
+ email: info@simplificator.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - lib/rwebthumb.rb
31
+ - lib/rwebthumb/base.rb
32
+ - lib/rwebthumb/job.rb
33
+ - lib/rwebthumb/webthumb.rb
34
+ - test/base_test.rb
35
+ - test/helper.rb
36
+ - test/job_test.rb
37
+ - test/webthumb_test.rb
38
+ - lib/rwebthumb/easythumb.rb
39
+ - README
40
+ - init.rb
41
+ has_rdoc: true
42
+ homepage: http://simplificator.com/
43
+ licenses: []
44
+
45
+ post_install_message:
46
+ rdoc_options: []
47
+
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.7
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: rwebthumb provides a ruby interface for the webthumb.bluga.net
73
+ test_files: []
74
+