amazon-hacks 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/Manifest.txt +6 -0
- data/README.txt +105 -0
- data/Rakefile +17 -0
- data/lib/amazon-hacks.rb +411 -0
- data/test/test_amazon-hacks.rb +238 -0
- metadata +59 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
AmazonHacks
|
2
|
+
by Jacob Harris
|
3
|
+
harrisj@schizopolis.net
|
4
|
+
http://www.nimblecode.com/
|
5
|
+
|
6
|
+
NYC.rb
|
7
|
+
http://www.nycruby.org/
|
8
|
+
|
9
|
+
== DESCRIPTION:
|
10
|
+
|
11
|
+
Mainly the product of messing around, this gem comprises Ruby code for a few
|
12
|
+
useful "Amazon Hacks" -- common techniques for manipulating Amazon product URLs
|
13
|
+
and Images. This is mainly useful if you find yourself creating a site where you
|
14
|
+
might link to Amazon product pages and display images for them. Examples of this
|
15
|
+
might include:
|
16
|
+
|
17
|
+
* Social consumption sites like http://www.allconsuming.net/
|
18
|
+
* Blogs or tumbleblogs with book/music/etc. reviews
|
19
|
+
* Normalizing Amazon links or create associate IDs
|
20
|
+
|
21
|
+
This GEM is NOT related to using the Amazon Web Services and there is already an
|
22
|
+
excellent gem for that if you need more heavy-duty use of the Amazon website
|
23
|
+
(this gem does not even communicate with Amazon at all). Also, note this gem is
|
24
|
+
meant in the spirit of fun hackery. You can use it to create interesting images
|
25
|
+
from Amazon on demand, but if you are going to use it on a serious website,
|
26
|
+
please consider caching and attributing that image to Amazon (I also have no
|
27
|
+
idea what the official legal policy for using Amazon's book images is).
|
28
|
+
|
29
|
+
And of course, do not even consider using this for fraud. It is possible to
|
30
|
+
generate "20% off" or "Look Inside!" badges on Amazon images, but this gem does
|
31
|
+
not support that since I can not think of any reason why outside sites would use
|
32
|
+
that.
|
33
|
+
|
34
|
+
== FEATURES/PROBLEMS:
|
35
|
+
|
36
|
+
There are two main classes within the Amazon::Hacks namespace with the following
|
37
|
+
functionality:
|
38
|
+
|
39
|
+
=== Link (product URL)
|
40
|
+
|
41
|
+
* Extract country of site
|
42
|
+
* Extract ASIN (Amazon identifier)
|
43
|
+
* Normalize (reduce to most basic URL for matching)
|
44
|
+
* Associate URL (create a normalized URL with your Amazon Associate ID)
|
45
|
+
|
46
|
+
=== Image
|
47
|
+
|
48
|
+
- Derive a corresponding image URL from a product URL
|
49
|
+
- Sizes (small, medium, large)
|
50
|
+
- Shadow
|
51
|
+
- Border
|
52
|
+
- Crop
|
53
|
+
- Scale
|
54
|
+
- Tilt
|
55
|
+
- Blur
|
56
|
+
- Sharpen
|
57
|
+
- Highlight
|
58
|
+
- Text overlay
|
59
|
+
|
60
|
+
This is still a work in development, and while I have tested against some
|
61
|
+
generic Amazon rules, it is possible that certain countries might deviate from
|
62
|
+
Amazon's practices (for instance, China seems to not use the image generation
|
63
|
+
code and instead just links to static URLs). Let me know if you find any issues
|
64
|
+
for a given product link/image. Thank you.
|
65
|
+
|
66
|
+
== SYNOPSIS:
|
67
|
+
|
68
|
+
To use, simply +require 'amazon_hacks'+
|
69
|
+
|
70
|
+
=== LINKS
|
71
|
+
|
72
|
+
This gem is inspired by the {Abusing Amazon Images}[http://aaugh.com/imageabuse.html] page.
|
73
|
+
|
74
|
+
== REQUIREMENTS:
|
75
|
+
|
76
|
+
* Requires the 'color-tools' gem
|
77
|
+
|
78
|
+
== INSTALL:
|
79
|
+
|
80
|
+
* sudo gem install amazon-hacks
|
81
|
+
|
82
|
+
== LICENSE:
|
83
|
+
|
84
|
+
(The MIT License)
|
85
|
+
|
86
|
+
Copyright (c) 2006 FIX
|
87
|
+
|
88
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
89
|
+
a copy of this software and associated documentation files (the
|
90
|
+
'Software'), to deal in the Software without restriction, including
|
91
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
92
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
93
|
+
permit persons to whom the Software is furnished to do so, subject to
|
94
|
+
the following conditions:
|
95
|
+
|
96
|
+
The above copyright notice and this permission notice shall be
|
97
|
+
included in all copies or substantial portions of the Software.
|
98
|
+
|
99
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
100
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
101
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
102
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
103
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
104
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
105
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/amazon-hacks'
|
6
|
+
|
7
|
+
Hoe.new('amazon-hacks', AmazonHacks::VERSION) do |p|
|
8
|
+
p.rubyforge_name = 'amazon-hacks'
|
9
|
+
p.summary = 'A collection of useful snippets against the Amazon website'
|
10
|
+
p.author = 'Jacob Harris'
|
11
|
+
p.email = 'harrisj@schizopolis.net'
|
12
|
+
p.url = 'http://www.nimblecode.com/code/AmazonHacks'
|
13
|
+
p.description = p.paragraphs_of('README.txt', 2..6).join("\n\n")
|
14
|
+
# p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
|
15
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
16
|
+
p.extra_deps = "color-tools"
|
17
|
+
end
|
data/lib/amazon-hacks.rb
ADDED
@@ -0,0 +1,411 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'uri'
|
3
|
+
require 'color'
|
4
|
+
|
5
|
+
class AmazonHacks
|
6
|
+
VERSION = '0.1.0'
|
7
|
+
end
|
8
|
+
|
9
|
+
module Amazon
|
10
|
+
module Hacks
|
11
|
+
Country = Struct.new("Country", :country, :host, :img_code, :img_host)
|
12
|
+
|
13
|
+
##
|
14
|
+
# COUNTRIES is nice generic structure for storing information specific to
|
15
|
+
# each country Amazon has a store for (China seems special though, so I have
|
16
|
+
# deferred supporting it for now)
|
17
|
+
COUNTRIES = {
|
18
|
+
:ca => Country.new(:ca, "www.amazon.ca", "01", "images.amazon.ca"),
|
19
|
+
# :cn => new Location("www.amazon.cn", )
|
20
|
+
:de => Country.new(:de, "www.amazon.de", "03", "images.amazon.de"),
|
21
|
+
:fr => Country.new(:fr, "www.amazon.fr", "08", "images.amazon.fr"),
|
22
|
+
:jp => Country.new(:jp, "www.amazon.co.jp", "09", "images.amazon.co.jp"),
|
23
|
+
:uk => Country.new(:uk, "www.amazon.co.uk", "02", "images.amazon.co.uk"),
|
24
|
+
:us => Country.new(:us, "www.amazon.com", "01", "images.amazon.com")
|
25
|
+
}
|
26
|
+
|
27
|
+
##
|
28
|
+
# The countries module is a convenience mixin to retrieve the correct
|
29
|
+
# server, etc. for an Image or Link. This module requires the class to
|
30
|
+
# include a +@country+ instance variable.
|
31
|
+
module Countries
|
32
|
+
|
33
|
+
##
|
34
|
+
# Returns a hostname for the Amazon store for that country
|
35
|
+
def country_host
|
36
|
+
COUNTRIES[@country].host
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Each country in Amazon seems to use a different image code number in its
|
41
|
+
# images (eg, "01" for the US, "08" for France). This method returns the
|
42
|
+
# image code for the country
|
43
|
+
def country_imgcode
|
44
|
+
COUNTRIES[@country].img_code
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Each country also has a different server for its images. This returns
|
49
|
+
# the correct server.
|
50
|
+
def country_imghost
|
51
|
+
COUNTRIES[@country].img_host
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Link
|
56
|
+
include Countries
|
57
|
+
attr_reader :asin, :country
|
58
|
+
|
59
|
+
def initialize(url=nil, country=nil, asin=nil)
|
60
|
+
if url.nil?
|
61
|
+
@url = @country = @asin = nil
|
62
|
+
else
|
63
|
+
@url = URI.parse(url)
|
64
|
+
@country = country ? country : Amazon::Hacks::Link.extract_country(url)
|
65
|
+
@asin = asin ? asin : Amazon::Hacks::Link.extract_asin(url)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Sets the internal url of the link to be +url+. Also parses the values of
|
71
|
+
# the +asin+ and +country+ from the URL
|
72
|
+
def url=(url)
|
73
|
+
@url = URI.parse(url)
|
74
|
+
@country = Amazon::Hacks::Link.extract_country(url)
|
75
|
+
@asin = Amazon::Hacks::Link.extract_asin(url)
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Returns a normalized form of the Link's URL. This is the shortest valid
|
80
|
+
# URL that links to the product on Amazon
|
81
|
+
#
|
82
|
+
# For example, the normalized form of a URL like:
|
83
|
+
#
|
84
|
+
# http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672/sr=8-1/qid=1165273301/ref=pd_bbs_sr_1/002-2410048-1716806?ie=UTF8&s=books
|
85
|
+
#
|
86
|
+
# would be:
|
87
|
+
#
|
88
|
+
# http://www.amazon.com/o/asin/0201485672
|
89
|
+
#
|
90
|
+
# Since it removes the session and other variables from the URL,
|
91
|
+
# normalization is very useful for comparing two Amazon links directly.
|
92
|
+
# The Link== method does NOT normalize, but you might want to consider
|
93
|
+
# that if you need it.
|
94
|
+
def normalize
|
95
|
+
"http://#{country_host}/o/asin/#{asin}"
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Extracts the Amazon Standard Identification Number (ASIN) from a string +url+.
|
100
|
+
# Each product on an Amazon store has a unique ASIN used to identify it.
|
101
|
+
# As Amazon's help documents describe it:
|
102
|
+
#
|
103
|
+
# "For books, the ASIN is the same as the ISBN number, but for all other
|
104
|
+
# products a new ASIN is created when the item is uploaded to our catalog"
|
105
|
+
#
|
106
|
+
# ASIN values are specific to the store they're applied to and can not be
|
107
|
+
# used against another store nor are they guaranteed to be globally unique.
|
108
|
+
# Put another way, the ASIN for the US edition of a book will not return
|
109
|
+
# the UK edition when used with the UK store and might return nothing or
|
110
|
+
# something completely different. Also, ASINs are alphanumeric strings, not
|
111
|
+
# numbers.
|
112
|
+
#
|
113
|
+
# Amazon has used several different major URL formats interchangeably and
|
114
|
+
# this function extracts the ASIN from the following URL paths:
|
115
|
+
#
|
116
|
+
# /o/asin/<ASIN VALUE>[/...]
|
117
|
+
#
|
118
|
+
# /exec/obidos/ASIN/<ASIN VALUE>[/...]
|
119
|
+
#
|
120
|
+
# /exec/obidos/tg/detail/-/<ASIN VALUE>[/...]
|
121
|
+
#
|
122
|
+
# /long-title-goes-here/dp/<ASIN VALUE>[/...]
|
123
|
+
#
|
124
|
+
# This is only an informally gathered list. If you find a case where
|
125
|
+
# +extract_asin+ fails, please send me the URL. If the ASIN is not matched,
|
126
|
+
# returns +nil+
|
127
|
+
def Link.extract_asin(url)
|
128
|
+
u = URI.parse(url)
|
129
|
+
asin = nil
|
130
|
+
|
131
|
+
asin_regexps = [ /^\/o\/asin\/([^\/]+)/,
|
132
|
+
/^\/exec\/obidos\/ASIN\/([^\/]+)/,
|
133
|
+
/^\/exec\/obidos\/tg\/detail\/-\/([^\/]+)/,
|
134
|
+
/^\/[^\/]+\/dp\/([^\/]+)/
|
135
|
+
]
|
136
|
+
|
137
|
+
asin_regexps.each do |re|
|
138
|
+
md = re.match(u.path)
|
139
|
+
if md
|
140
|
+
then
|
141
|
+
asin = md[1]
|
142
|
+
break
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
asin
|
147
|
+
end
|
148
|
+
|
149
|
+
##
|
150
|
+
# This method analyzes the +url+ string and returns a symbol representing
|
151
|
+
# the country (eg, +:us+). If the host is not recognized, returns +nil+
|
152
|
+
def Link.extract_country(url)
|
153
|
+
u = URI.parse(url)
|
154
|
+
c = COUNTRIES.find { |key, value| value.host == u.host }
|
155
|
+
c[0] unless c.nil? #.country unless c.nil?
|
156
|
+
end
|
157
|
+
|
158
|
+
def associate_url(assoc_id)
|
159
|
+
normalize + "/#{assoc_id}"
|
160
|
+
end
|
161
|
+
|
162
|
+
def normalize!
|
163
|
+
u = normalize
|
164
|
+
@url = URI.parse(u)
|
165
|
+
self
|
166
|
+
end
|
167
|
+
|
168
|
+
def url
|
169
|
+
@url.to_s
|
170
|
+
end
|
171
|
+
|
172
|
+
alias :to_s :url
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
module Amazon
|
178
|
+
module Hacks
|
179
|
+
|
180
|
+
##
|
181
|
+
# Class for manipulating Amazon's image URLs. These images are generated
|
182
|
+
# on demand at Amazon, so please don't abuse this feature against their
|
183
|
+
# site (save the image locally or link to them so they can get some sales
|
184
|
+
# out of it). I also do not have transformations that apply Amazon-specific
|
185
|
+
# decorations like "20% off" badges or "Look Inside" to hinder spoofing an
|
186
|
+
# Amazon site somewhat.
|
187
|
+
#
|
188
|
+
# Amazon images require an ASIN and country. These can either be specified
|
189
|
+
# manually or imported from a URL. In addition, each image can be modified
|
190
|
+
# with zero or more transformations (all specified in the URL), although the
|
191
|
+
# using more than two transformations is not necessarily guaranteed to be
|
192
|
+
# honored by Amazon's rendering engine (only the first will generally be
|
193
|
+
# applied, but [size + transform] seems to work usually).
|
194
|
+
#
|
195
|
+
# {Abusing Amazon Images}[http://aaugh.com/imageabuse.html], a site to whom
|
196
|
+
# I am most indebted here, notes the following about transform chaining:
|
197
|
+
#
|
198
|
+
# "The cool thing (if you want to generate unlikely Amazon images) is that
|
199
|
+
# you're not limited to one use of any of these commands. You can have
|
200
|
+
# multiple discounts, multiple shadows, multiple bullets, generating images
|
201
|
+
# that Amazon would never have on its site. However, every additional command
|
202
|
+
# you add generates another 10% to the image dimensions, adding white space
|
203
|
+
# around the image. And that 10% compounds; add a lot of bullets, and you'll
|
204
|
+
# find that you have a small image in a large blank space. (You can use the
|
205
|
+
# #crop! command to cut away the excess, however.) Note also that the commands
|
206
|
+
# are interpreted in order, which can have an impact on what overlaps what."
|
207
|
+
class Image
|
208
|
+
include Countries
|
209
|
+
attr :asin, :country
|
210
|
+
|
211
|
+
SIZES = { :small => "SCTZZZZZZZ",
|
212
|
+
:medium => "SCMZZZZZZZ",
|
213
|
+
:large => "SCLZZZZZZZ" }
|
214
|
+
|
215
|
+
SHADOW_POSITIONS = [ :left, :right, :custom ]
|
216
|
+
|
217
|
+
SCALE_TYPES = { :proportion => "AA",
|
218
|
+
:square => "SS",
|
219
|
+
:width => "SX",
|
220
|
+
:height => "SY" }
|
221
|
+
|
222
|
+
TEXT_FONTS = [ :times, :arial, :arialbi, :verdanab, :advc128d ]
|
223
|
+
TEXT_ALIGNS = [ :left, :center ]
|
224
|
+
|
225
|
+
##
|
226
|
+
# Creates an Image object from a +url+
|
227
|
+
def Image.build_from_url(url)
|
228
|
+
u = Amazon::Hacks::Link.new(url)
|
229
|
+
i = Image.new(u.asin, u.country)
|
230
|
+
end
|
231
|
+
|
232
|
+
##
|
233
|
+
# Initializes an Image object, requires both a valid asin as well as
|
234
|
+
# a country symbol (eg, +:us+ or +:uk+)
|
235
|
+
def initialize(asin, country)
|
236
|
+
@asin = asin
|
237
|
+
@country = country
|
238
|
+
reset_transforms!
|
239
|
+
end
|
240
|
+
|
241
|
+
##
|
242
|
+
# Add a size transform to the image. The following sizes are allowed:
|
243
|
+
# * small
|
244
|
+
# * medium
|
245
|
+
# * large
|
246
|
+
#
|
247
|
+
# These sizes are not guaranteed to particular dimensions. If you need
|
248
|
+
# exact sizing, use the #scale! transformation. These sizes are a lot
|
249
|
+
# friendlier to Amazon's image servers though, so I would recommend them
|
250
|
+
# if you can handle some variation.
|
251
|
+
def set_size!(size)
|
252
|
+
@transforms << SIZES[size]
|
253
|
+
end
|
254
|
+
|
255
|
+
##
|
256
|
+
# Add a simple shadow to the left or right; takes arguments +:left+ or
|
257
|
+
# +:right+.
|
258
|
+
def add_shadow! (side)
|
259
|
+
case
|
260
|
+
when side == :left then @transforms << "PB"
|
261
|
+
when side == :right then @transforms << "PC"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
##
|
266
|
+
# Add a custom shadow to the image. Takes 4 parameters:
|
267
|
+
#
|
268
|
+
# * +size+ - padding around the image (pixels)
|
269
|
+
# * +xoff+ - distance from the shadow's edge to the item's edge horizontally.
|
270
|
+
# Positive values go to the right, negative to the left (pixels)
|
271
|
+
# * +yoff+ - like xoff but vertically.
|
272
|
+
# * +fuzz+ - fuzziness of shadow; 0 is perfectly square while higher values
|
273
|
+
# blur the sharpness of the shadow's edge
|
274
|
+
def add_custom_shadow! (size, xoff, yoff, fuzz)
|
275
|
+
@transforms << "PA#{size},#{xoff},#{yoff},#{fuzz}"
|
276
|
+
end
|
277
|
+
|
278
|
+
##
|
279
|
+
# Add a border around the image. Takes the following arguments
|
280
|
+
#
|
281
|
+
# * +width+ - size of the border (pixels)
|
282
|
+
# * +color+ - color of the border in HTML format (eg, "#CCCCCC") [defaults
|
283
|
+
# black if not specified]
|
284
|
+
def add_border! (width, html_color="\#000000")
|
285
|
+
color = Color::RGB.from_html(html_color)
|
286
|
+
cmd = "BO#{width},"
|
287
|
+
cmd << [color.r, color.g, color.b].map {|c| (c*255).to_i }.join(",")
|
288
|
+
@transforms << cmd
|
289
|
+
end
|
290
|
+
|
291
|
+
##
|
292
|
+
# Rotate the image. Takes a single argument of degrees to rotate. Positive
|
293
|
+
# values rotate to the right, negative to the left.
|
294
|
+
#
|
295
|
+
# According to auugh: "The values seem to range as high as 135. Positive
|
296
|
+
# values rotate to the right, negative numbers rotate to the left. Negative
|
297
|
+
# numbers go... well, I stopped testing in the hundreds of millions, but
|
298
|
+
# there's not much need to go beyond -360, which takes it full circle.
|
299
|
+
# Positive rotations in some values seem to cause severe image shrinkage,
|
300
|
+
# so you should consider using a size adjustment after rotation."
|
301
|
+
def tilt! (degrees)
|
302
|
+
@transforms << "PT#{degrees}"
|
303
|
+
end
|
304
|
+
|
305
|
+
##
|
306
|
+
# Blur the image. The input argument seems to represent a radius, but the
|
307
|
+
# essential thing to know is the higher the value, the blurrier it gets.
|
308
|
+
def blur! (radius)
|
309
|
+
@transforms << "BL#{radius}"
|
310
|
+
end
|
311
|
+
|
312
|
+
##
|
313
|
+
# Sharpen the image. The value can range from 0 - 99. Larger values may
|
314
|
+
# affect color and increase noise significantly.
|
315
|
+
def sharpen! (percent)
|
316
|
+
@transforms << "SH#{percent}"
|
317
|
+
end
|
318
|
+
|
319
|
+
##
|
320
|
+
# Scale the image to exact dimensions. Takes a scaling type and dimension
|
321
|
+
# in pixels. There are four types of scaling possible:
|
322
|
+
#
|
323
|
+
# * +:proportion+ - preserve the image's proportions
|
324
|
+
# * +:square+ - make the image square
|
325
|
+
# * +:width+ - the size represents the width of image. Height is
|
326
|
+
# proportionally scaled.
|
327
|
+
# * +:height+ - the size represents the height of the image. Width is
|
328
|
+
# proportionally scaled.
|
329
|
+
def scale!(type, size)
|
330
|
+
@transforms << "#{SCALE_TYPES[type]}#{size}"
|
331
|
+
end
|
332
|
+
|
333
|
+
##
|
334
|
+
# Crops the image. This can be used to generate Flickr-like square windows
|
335
|
+
# into the image (although there is no method to figure out programmatically
|
336
|
+
# the dimensions of a particular size, so this might be hard [maybe scale
|
337
|
+
# then crop?]). Takes four arguments to set the crop square:
|
338
|
+
#
|
339
|
+
# * +xoff+ - x offset from top left corner of image to tlc of box (pixels)
|
340
|
+
# * +yoff+ - y offset from top left corner of image to tlc of (pixels)
|
341
|
+
# * +width+ - width of crop square
|
342
|
+
# * +height+ - height of crop square
|
343
|
+
def crop! (xoff, yoff, width, height)
|
344
|
+
@transforms << "CR#{xoff},#{yoff},#{width},#{height}"
|
345
|
+
end
|
346
|
+
|
347
|
+
##
|
348
|
+
# Overlay text on the image. This is easily the most complicated transformation
|
349
|
+
# you can apply in terms of sheer argument heft. The text is placed in a square
|
350
|
+
# area you must set the dimensions of first. Takes the following options:
|
351
|
+
#
|
352
|
+
# * +text+ - the text you want to overlay
|
353
|
+
# * +xoff+ - x offset from the top left corner to tlc of box (pixels)
|
354
|
+
# * +yoff+ - y offset from the top left corner to tlc of box (pixels)
|
355
|
+
# * +width+ - width of the text box
|
356
|
+
# * +height+ - height of the text box in pixels
|
357
|
+
# * +font+ - four options are allowed:
|
358
|
+
# * +:times+ - Times Roman
|
359
|
+
# * +:arial+ - Arial
|
360
|
+
# * +:arialbi+ - Arial Bold Italic
|
361
|
+
# * +:verdanab+ - Verdana Bold
|
362
|
+
# * +:advc128d+ - barcode font
|
363
|
+
# * +size+ - font size (points?)
|
364
|
+
# * +color+ - a color specified in HTML style (eg, "#CCEECC")
|
365
|
+
# * +align+ - may be +:left+ or +:center+ only, defaults to +:left+
|
366
|
+
def add_text! (text, xoff, yoff, width, height, font, size, html_color, align=:left)
|
367
|
+
color = Color::RGB.from_html(html_color)
|
368
|
+
cmd = (align == :center) ? "ZC" : "ZA"
|
369
|
+
parts = [URI.escape(text), xoff, yoff, width, height, font, size].map {|x| x.to_s} +
|
370
|
+
[color.r, color.g, color.b].map {|c| (c*255).to_i }
|
371
|
+
cmd << parts.join(",")
|
372
|
+
@transforms << cmd
|
373
|
+
end
|
374
|
+
|
375
|
+
##
|
376
|
+
# Highlight the image. I'm still not sure what this means, but here it is.
|
377
|
+
# You specify an square highlight area of the image with the following
|
378
|
+
# parameters:
|
379
|
+
#
|
380
|
+
# * +xoff+ - x offset from the top left corner to tlc of box (pixels)
|
381
|
+
# * +yoff+ - y offset from the top left corner to tlc of box (pixels)
|
382
|
+
# * +width+ - width of the text box
|
383
|
+
# * +height+ - height of the text box in pixels
|
384
|
+
# * +intensity+ - I really don't know what this means, but more is bigger
|
385
|
+
def highlight!(xoff, yoff, width, height, intensity)
|
386
|
+
@transforms << "HL#{xoff},#{yoff},#{width},#{height},#{intensity}"
|
387
|
+
end
|
388
|
+
|
389
|
+
##
|
390
|
+
# Transformations like #crop! and #add_shadow!, etc. can be chained and
|
391
|
+
# are potentially applied in the order specified. Should you need to clear
|
392
|
+
# the transforms and revert to the original image, this command does that.
|
393
|
+
def reset_transforms!
|
394
|
+
@transforms = []
|
395
|
+
end
|
396
|
+
|
397
|
+
##
|
398
|
+
# Returns a URL for the image from Amazon's servers.
|
399
|
+
def url
|
400
|
+
url = "http://#{country_imghost}/images/P/#{asin}"
|
401
|
+
url << "." << country_imgcode << "."
|
402
|
+
|
403
|
+
url << "_" << @transforms.join(",") << "_" << ".jpg"
|
404
|
+
end
|
405
|
+
|
406
|
+
##
|
407
|
+
# This method is an alias for #url
|
408
|
+
alias :to_s :url
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
@@ -0,0 +1,238 @@
|
|
1
|
+
# Code Generated by ZenTest v. 3.4.2
|
2
|
+
# classname: asrt / meth = ratio%
|
3
|
+
# Amazon::Hacks::Image: 0 / 15 = 0.00%
|
4
|
+
# Amazon::Hacks::Link: 0 / 8 = 0.00%
|
5
|
+
# Countries: 0 / 3 = 0.00%
|
6
|
+
|
7
|
+
require 'test/unit' unless defined? $ZENTEST and $ZENTEST
|
8
|
+
require './lib/amazon-hacks'
|
9
|
+
|
10
|
+
module TestAmazon
|
11
|
+
module TestHacks
|
12
|
+
class TestCountries
|
13
|
+
include Amazon::Hacks::Countries
|
14
|
+
|
15
|
+
def setup
|
16
|
+
@country = :uk
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_country_host
|
20
|
+
assert_equal("www.amazon.co.uk", country_host)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_country_imgcode
|
24
|
+
assert_equal("02", country_imgcode)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_country_imghost
|
28
|
+
assert_equal("images.amazon.co.uk", country_imghost)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module TestAmazon
|
35
|
+
module TestHacks
|
36
|
+
class TestImage < Test::Unit::TestCase
|
37
|
+
URL_PREFIX = "http://images.amazon.com/images/P/0201485672.01."
|
38
|
+
|
39
|
+
def setup
|
40
|
+
@img = Amazon::Hacks::Image.new("0201485672", :us)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_build_from_url
|
44
|
+
i = Amazon::Hacks::Image.build_from_url("http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672/sr=8-1/qid=1165273301/ref=pd_bbs_sr_1/002-2410048-1716806?ie=UTF8&s=books")
|
45
|
+
assert_equal("#{URL_PREFIX}__.jpg", i.url)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_add_border_bang
|
49
|
+
@img.add_border! 12, "\#CC2244"
|
50
|
+
assert_equal("#{URL_PREFIX}_BO12,204,34,68_.jpg", @img.url)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_add_custom_shadow_bang
|
54
|
+
@img.add_custom_shadow! 2, 23, 45, 30
|
55
|
+
assert_equal("#{URL_PREFIX}_PA2,23,45,30_.jpg", @img.url)
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_add_shadow_bang_left
|
59
|
+
@img.add_shadow! :left
|
60
|
+
assert_equal("#{URL_PREFIX}_PB_.jpg", @img.url)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_add_shadow_bang_right
|
64
|
+
@img.add_shadow! :right
|
65
|
+
assert_equal("#{URL_PREFIX}_PC_.jpg", @img.url)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_blur_bang
|
69
|
+
@img.blur! 23
|
70
|
+
assert_equal("#{URL_PREFIX}_BL23_.jpg", @img.url)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_crop_bang
|
74
|
+
@img.crop! 0, 10, 20, 20
|
75
|
+
assert_equal("#{URL_PREFIX}_CR0,10,20,20_.jpg", @img.url)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_highlight_bang
|
79
|
+
@img.highlight! 0, 10, 20, 15, 75
|
80
|
+
assert_equal("#{URL_PREFIX}_HL0,10,20,15,75_.jpg", @img.url)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_reset_transforms_bang
|
84
|
+
@img.add_border! 33, "\#CCCCCC"
|
85
|
+
@img.blur! 23
|
86
|
+
@img.add_shadow! :right
|
87
|
+
@img.reset_transforms!
|
88
|
+
|
89
|
+
assert_equal("#{URL_PREFIX}__.jpg", @img.url)
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_scale_bang_proportion
|
93
|
+
@img.scale! :proportion, 23
|
94
|
+
assert_equal("#{URL_PREFIX}_AA23_.jpg", @img.url)
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_scale_bang_square
|
98
|
+
@img.scale! :square, 23
|
99
|
+
assert_equal("#{URL_PREFIX}_SS23_.jpg", @img.url)
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_scale_bang_width
|
103
|
+
@img.scale! :width, 23
|
104
|
+
assert_equal("#{URL_PREFIX}_SX23_.jpg", @img.url)
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_scale_bang_height
|
108
|
+
@img.scale! :height, 23
|
109
|
+
assert_equal("#{URL_PREFIX}_SY23_.jpg", @img.url)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_set_size_bang_small
|
113
|
+
@img.set_size! :small
|
114
|
+
assert_equal("#{URL_PREFIX}_SCTZZZZZZZ_.jpg", @img.url)
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_set_size_bang_medium
|
118
|
+
@img.set_size! :medium
|
119
|
+
assert_equal("#{URL_PREFIX}_SCMZZZZZZZ_.jpg", @img.url)
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_set_size_bang_large
|
123
|
+
@img.set_size! :large
|
124
|
+
assert_equal("#{URL_PREFIX}_SCLZZZZZZZ_.jpg", @img.url)
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_sharpen_bang
|
128
|
+
@img.sharpen! 83
|
129
|
+
assert_equal("#{URL_PREFIX}_SH83_.jpg", @img.url)
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_add_text_bang
|
133
|
+
@img.add_text! "hello world", 5, 15, 100, 100, :times, 20, "\#CC2244", :left
|
134
|
+
assert_equal("#{URL_PREFIX}_ZAhello%20world,5,15,100,100,times,20,204,34,68_.jpg", @img.url)
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_text_bang_center
|
138
|
+
@img.add_text! "hello world", 5, 15, 100, 100, :times, 20, "\#CC2244", :center
|
139
|
+
assert_equal("#{URL_PREFIX}_ZChello%20world,5,15,100,100,times,20,204,34,68_.jpg", @img.url)
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_tilt_bang
|
143
|
+
@img.tilt! 45
|
144
|
+
assert_equal("#{URL_PREFIX}_PT45_.jpg", @img.url)
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_url
|
148
|
+
assert_equal("#{URL_PREFIX}__.jpg", @img.url)
|
149
|
+
assert_equal("#{URL_PREFIX}__.jpg", @img.to_s)
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_chain_transforms
|
153
|
+
@img.set_size! :small
|
154
|
+
@img.blur! 87
|
155
|
+
assert_equal("#{URL_PREFIX}_SCTZZZZZZZ,BL87_.jpg", @img.url)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
module TestAmazon
|
162
|
+
module TestHacks
|
163
|
+
class TestLink < Test::Unit::TestCase
|
164
|
+
def setup
|
165
|
+
@us_link = Amazon::Hacks::Link.new("http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672/sr=8-1/qid=1165273301/ref=pd_bbs_sr_1/002-2410048-1716806?ie=UTF8&s=books")
|
166
|
+
@uk_link = Amazon::Hacks::Link.new("http://www.amazon.co.uk/The-IT-Crowd/dp/B000EU1OYC/sr=8-1/qid=1165274239/ref=pd_ka_1/026-4633332-4150855?ie=UTF8&s=dvd")
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_class_extract_asin_1
|
170
|
+
asin = Amazon::Hacks::Link.extract_asin("http://www.amazon.com/o/asin/0201485672")
|
171
|
+
assert_equal("0201485672", asin)
|
172
|
+
|
173
|
+
asin = Amazon::Hacks::Link.extract_asin("http://www.amazon.co.uk/o/asin/B000EU1OYC")
|
174
|
+
assert_equal("B000EU1OYC", asin)
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_class_extract_asin_2
|
178
|
+
asin = Amazon::Hacks::Link.extract_asin("http://www.amazon.com/exec/obidos/ASIN/0201485672")
|
179
|
+
assert_equal("0201485672", asin)
|
180
|
+
|
181
|
+
asin = Amazon::Hacks::Link.extract_asin("http://www.amazon.co.uk/exec/obidos/ASIN/B000EU1OYC")
|
182
|
+
assert_equal("B000EU1OYC", asin)
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_class_extract_asin_3
|
186
|
+
asin = Amazon::Hacks::Link.extract_asin("http://www.amazon.com/exec/obidos/tg/detail/-/0201485672")
|
187
|
+
assert_equal("0201485672", asin)
|
188
|
+
|
189
|
+
asin = Amazon::Hacks::Link.extract_asin("http://www.amazon.co.uk/exec/obidos/tg/detail/-/B000EU1OYC")
|
190
|
+
assert_equal("B000EU1OYC", asin)
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_class_extract_asin_4
|
194
|
+
asin = Amazon::Hacks::Link.extract_asin("http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672/sr=8-1/qid=1165273301/ref=pd_bbs_sr_1/002-2410048-1716806?ie=UTF8&s=books")
|
195
|
+
assert_equal("0201485672", asin)
|
196
|
+
|
197
|
+
asin = Amazon::Hacks::Link.extract_asin("http://www.amazon.co.uk/The-IT-Crowd/dp/B000EU1OYC/sr=8-1/qid=1165274239/ref=pd_ka_1/026-4633332-4150855?ie=UTF8&s=dvd")
|
198
|
+
assert_equal("B000EU1OYC", asin)
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_class_extract_country
|
202
|
+
assert_equal(:us, Amazon::Hacks::Link.extract_country("http://www.amazon.com/foo"))
|
203
|
+
assert_equal(:uk, Amazon::Hacks::Link.extract_country("http://www.amazon.co.uk/foo"))
|
204
|
+
assert_equal(:de, Amazon::Hacks::Link.extract_country("http://www.amazon.de/foo"))
|
205
|
+
assert_equal(:fr, Amazon::Hacks::Link.extract_country("http://www.amazon.fr/foo"))
|
206
|
+
assert_equal(:jp, Amazon::Hacks::Link.extract_country("http://www.amazon.co.jp/foo"))
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_asin
|
210
|
+
assert_equal("0201485672", @us_link.asin)
|
211
|
+
assert_equal("B000EU1OYC", @uk_link.asin)
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_associate_url
|
215
|
+
assert_equal("http://www.amazon.com/o/asin/0201485672/testassoc", @us_link.associate_url("testassoc"))
|
216
|
+
assert_equal("http://www.amazon.co.uk/o/asin/B000EU1OYC/testassoc", @uk_link.associate_url("testassoc"))
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_normalize
|
220
|
+
assert_equal("http://www.amazon.com/o/asin/0201485672", @us_link.normalize)
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_normalize_bang
|
224
|
+
@us_link.normalize!
|
225
|
+
assert_equal("http://www.amazon.com/o/asin/0201485672", @us_link.to_s)
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_url_equals
|
229
|
+
link = Amazon::Hacks::Link.new
|
230
|
+
link.url = "http://www.amazon.co.uk/The-IT-Crowd/dp/B000EU1OYC/sr=8-1/qid=1165274239/ref=pd_ka_1/026-4633332-4150855?ie=UTF8&s=dvd"
|
231
|
+
assert_equal("http://www.amazon.co.uk/The-IT-Crowd/dp/B000EU1OYC/sr=8-1/qid=1165274239/ref=pd_ka_1/026-4633332-4150855?ie=UTF8&s=dvd", link.to_s)
|
232
|
+
assert_equal(:uk, link.country)
|
233
|
+
assert_equal("B000EU1OYC", link.asin)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: amazon-hacks
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.1.0
|
7
|
+
date: 2006-12-12 00:00:00 -05:00
|
8
|
+
summary: A collection of useful snippets against the Amazon website
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: harrisj@schizopolis.net
|
12
|
+
homepage: http://www.nimblecode.com/code/AmazonHacks
|
13
|
+
rubyforge_project: amazon-hacks
|
14
|
+
description: "== DESCRIPTION: Mainly the product of messing around, this gem comprises Ruby code for a few useful \"Amazon Hacks\" -- common techniques for manipulating Amazon product URLs and Images. This is mainly useful if you find yourself creating a site where you might link to Amazon product pages and display images for them. Examples of this might include: * Social consumption sites like http://www.allconsuming.net/ * Blogs or tumbleblogs with book/music/etc. reviews * Normalizing Amazon links or create associate IDs This GEM is NOT related to using the Amazon Web Services and there is already an excellent gem for that if you need more heavy-duty use of the Amazon website (this gem does not even communicate with Amazon at all). Also, note this gem is meant in the spirit of fun hackery. You can use it to create interesting images from Amazon on demand, but if you are going to use it on a serious website, please consider caching and attributing that image to Amazon (I also have no idea what the official legal policy for using Amazon's book images is). And of course, do not even consider using this for fraud. It is possible to generate \"20% off\" or \"Look Inside!\" badges on Amazon images, but this gem does not support that since I can not think of any reason why outside sites would use that."
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Jacob Harris
|
31
|
+
files:
|
32
|
+
- History.txt
|
33
|
+
- Manifest.txt
|
34
|
+
- README.txt
|
35
|
+
- Rakefile
|
36
|
+
- lib/amazon-hacks.rb
|
37
|
+
- test/test_amazon-hacks.rb
|
38
|
+
test_files:
|
39
|
+
- test/test_amazon-hacks.rb
|
40
|
+
rdoc_options: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
executables: []
|
45
|
+
|
46
|
+
extensions: []
|
47
|
+
|
48
|
+
requirements: []
|
49
|
+
|
50
|
+
dependencies:
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: color-tools
|
53
|
+
version_requirement:
|
54
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">"
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: 0.0.0
|
59
|
+
version:
|