smugmug 0.0.1
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/HISTORY +2 -0
- data/LICENSE +19 -0
- data/MANIFEST +48 -0
- data/README +30 -0
- data/Rakefile +100 -0
- data/bin/smcli +225 -0
- data/bin/smugmug2sql +158 -0
- data/doc/API +310 -0
- data/doc/TODO +32 -0
- data/lib/net/httpz.rb +31 -0
- data/lib/smugmug.rb +179 -0
- data/lib/smugmug/album/info.rb +131 -0
- data/lib/smugmug/album/stats.rb +31 -0
- data/lib/smugmug/albums.rb +39 -0
- data/lib/smugmug/base.rb +104 -0
- data/lib/smugmug/cache.rb +33 -0
- data/lib/smugmug/config.rb +48 -0
- data/lib/smugmug/image/exif.rb +72 -0
- data/lib/smugmug/image/info.rb +88 -0
- data/lib/smugmug/image/stats.rb +32 -0
- data/lib/smugmug/images.rb +52 -0
- data/lib/smugmug/table.rb +133 -0
- data/lib/smugmug/util.rb +12 -0
- data/test/album.rb +359 -0
- data/test/config.rb +39 -0
- data/test/httpz.rb +120 -0
- data/test/image.rb +540 -0
- data/test/login.rb +24 -0
- data/test/runner.rb +83 -0
- data/test/servlet.rb +257 -0
- data/test/table.rb +113 -0
- data/xml/canned +212 -0
- data/xml/fail/empty.set.xml +4 -0
- data/xml/fail/invalid.apikey.xml +4 -0
- data/xml/fail/invalid.login.xml +4 -0
- data/xml/fail/invalid.method.xml +4 -0
- data/xml/fail/invalid.user.xml +4 -0
- data/xml/fail/system.error.xml +4 -0
- data/xml/standard/albums.get.xml +24 -0
- data/xml/standard/albums.getInfo.xml +38 -0
- data/xml/standard/albums.getStats.xml +43 -0
- data/xml/standard/categories.get.xml +213 -0
- data/xml/standard/images.get.xml +9 -0
- data/xml/standard/images.getEXIF.xml +34 -0
- data/xml/standard/images.getInfo.xml +29 -0
- data/xml/standard/images.getStats.xml +15 -0
- data/xml/standard/login.withHash.xml +7 -0
- data/xml/standard/login.withPassword.xml +10 -0
- metadata +103 -0
data/xml/canned
ADDED
@@ -0,0 +1,212 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# $Hg$
|
3
|
+
|
4
|
+
require 'net/https'
|
5
|
+
require 'rexml/document'
|
6
|
+
require 'optparse'
|
7
|
+
require 'uri'
|
8
|
+
|
9
|
+
API_KEY='dydlCYDzmykqoLkVGgECEIP5WEuwWFzc'
|
10
|
+
USERAGENT='$HgRev$'
|
11
|
+
|
12
|
+
class File
|
13
|
+
def File.write(filename, data, offset=0)
|
14
|
+
File.open(filename, 'w') do |fh|
|
15
|
+
fh.seek(offset)
|
16
|
+
fh.write(data)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Tuna
|
22
|
+
BASE='://api.smugmug.com/hack/rest/1.1.1/'
|
23
|
+
|
24
|
+
attr_reader :album_id, :image_id, :session_id
|
25
|
+
attr_accessor :headers, :password, :username
|
26
|
+
|
27
|
+
def initialize()
|
28
|
+
@headers = {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def album_id=(val) headers[:AlbumID] = val ; end
|
32
|
+
def image_id=(val) headers[:ImageID] = val ; end
|
33
|
+
def session_id=(val) headers[:SessionID] = val ; end
|
34
|
+
|
35
|
+
def get(method, params={})
|
36
|
+
params['method'] = method
|
37
|
+
params.merge!(headers)
|
38
|
+
|
39
|
+
url = (method =~ /login/) ? 'https' : 'http'
|
40
|
+
url += BASE + '?'
|
41
|
+
params.each { |k,v| url += "#{k}=" + URI.encode(v.to_s) + '&' }
|
42
|
+
|
43
|
+
uri = URI.parse(url)
|
44
|
+
|
45
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
46
|
+
if uri.scheme == 'https'
|
47
|
+
http.use_ssl = true
|
48
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
49
|
+
end
|
50
|
+
|
51
|
+
http.start {
|
52
|
+
response = http.get(uri.path + '?' + uri.query, {'User-Agent' => USERAGENT})
|
53
|
+
raise "fetch of #{uri} failed, code #{response.code}" unless response.code.to_i == 200
|
54
|
+
|
55
|
+
@doc = response.body
|
56
|
+
}
|
57
|
+
|
58
|
+
return @doc
|
59
|
+
end
|
60
|
+
|
61
|
+
def walk
|
62
|
+
data = {}
|
63
|
+
methods = %w{login_withPassword login_withHash
|
64
|
+
albums_get albums_get_heavy albums_getInfo albums_getStats
|
65
|
+
images_get images_get_heavy images_getInfo images_getStats images_getEXIF images_getURLs
|
66
|
+
categories_get
|
67
|
+
}
|
68
|
+
|
69
|
+
methods.each do |method|
|
70
|
+
puts "Processing #{method} ..."
|
71
|
+
data[method] = self.send(method.to_sym)
|
72
|
+
end
|
73
|
+
|
74
|
+
return data
|
75
|
+
end
|
76
|
+
|
77
|
+
## login ###########################################################
|
78
|
+
|
79
|
+
def login_withPassword
|
80
|
+
return unless session_id.nil?
|
81
|
+
resp = get('smugmug.login.withPassword',
|
82
|
+
{:EmailAddress => username, :Password => password, :APIKey => API_KEY})
|
83
|
+
|
84
|
+
doc = REXML::Document.new(resp)
|
85
|
+
|
86
|
+
@account_type = doc.root.elements['Login/AccountType'].text
|
87
|
+
@user_id = doc.root.elements['Login/UserID'].text
|
88
|
+
@password_hash = doc.root.elements['Login/PasswordHash'].text
|
89
|
+
|
90
|
+
return resp
|
91
|
+
end
|
92
|
+
def login_withHash
|
93
|
+
return unless session_id.nil?
|
94
|
+
resp = get('smugmug.login.withHash',
|
95
|
+
{:UserID => @user_id, :PasswordHash => @password_hash, :APIKey => API_KEY})
|
96
|
+
|
97
|
+
doc = REXML::Document.new(resp)
|
98
|
+
@session_id = doc.root.elements['Login/SessionID'].text
|
99
|
+
|
100
|
+
headers['SessionID'] = @session_id
|
101
|
+
return resp
|
102
|
+
end
|
103
|
+
|
104
|
+
## albums ##########################################################
|
105
|
+
|
106
|
+
def albums_get
|
107
|
+
resp = get('smugmug.albums.get')
|
108
|
+
|
109
|
+
if album_id.nil?
|
110
|
+
doc = REXML::Document.new(resp)
|
111
|
+
@album_id = REXML::XPath.first(doc, '//Album/attribute::id')
|
112
|
+
headers['AlbumID'] = @album_id
|
113
|
+
end
|
114
|
+
|
115
|
+
return resp
|
116
|
+
end
|
117
|
+
def albums_get_heavy
|
118
|
+
return get('smugmug.albums.get', {:Heavy => 1})
|
119
|
+
end
|
120
|
+
def albums_getInfo
|
121
|
+
return get('smugmug.albums.getInfo', {:AlbumID => album_id})
|
122
|
+
end
|
123
|
+
def albums_getStats
|
124
|
+
return get('smugmug.albums.getStats',
|
125
|
+
{:AlbumID => album_id, :Month => Time.now.month, :Year => Time.now.year})
|
126
|
+
end
|
127
|
+
|
128
|
+
## images ##########################################################
|
129
|
+
|
130
|
+
def images_get
|
131
|
+
resp = get('smugmug.images.get', {:AlbumID => album_id})
|
132
|
+
|
133
|
+
if image_id.nil?
|
134
|
+
doc = REXML::Document.new(resp)
|
135
|
+
@image_id = REXML::XPath.first(doc, '//Image/attribute::id')
|
136
|
+
headers[:ImageID] = @image_id
|
137
|
+
end
|
138
|
+
|
139
|
+
return resp
|
140
|
+
end
|
141
|
+
def images_get_heavy
|
142
|
+
return get('smugmug.images.get', {:AlbumID => album_id, :Heavy => 1})
|
143
|
+
end
|
144
|
+
def images_getInfo
|
145
|
+
return get('smugmug.images.getInfo', {:ImageID => image_id})
|
146
|
+
end
|
147
|
+
def images_getStats
|
148
|
+
return get('smugmug.images.getStats', {:ImageID => image_id})
|
149
|
+
end
|
150
|
+
def images_getEXIF
|
151
|
+
return get('smugmug.images.getEXIF', {:ImageID => image_id})
|
152
|
+
end
|
153
|
+
def images_getURLs
|
154
|
+
return get('smugmug.images.getURLs', {:ImageID => image_id})
|
155
|
+
end
|
156
|
+
|
157
|
+
## categories ######################################################
|
158
|
+
|
159
|
+
def categories_get
|
160
|
+
return get('smugmug.categories.get')
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
def main()
|
166
|
+
options = {}
|
167
|
+
|
168
|
+
OptionParser.new do |opts|
|
169
|
+
opts.banner = "Usage: canned [options]"
|
170
|
+
|
171
|
+
opts.on("-p", "--password PASSWORD", "SmugMug password") do |v|
|
172
|
+
options[:password] = v
|
173
|
+
end
|
174
|
+
opts.on("-u", "--username USERNAME", "SmugMug email address") do |v|
|
175
|
+
options[:username] = v
|
176
|
+
end
|
177
|
+
opts.on("-s", "--session-id SessionID", "Use a specific SessionID") do |v|
|
178
|
+
options[:session_id] = v
|
179
|
+
end
|
180
|
+
opts.on("-i", "--image-id ImageID", "Use a specific ImageID") do |v|
|
181
|
+
options[:image_id] = v
|
182
|
+
end
|
183
|
+
opts.on("-a", "--album-id AlbumID", "Use a specific AlbumID") do |v|
|
184
|
+
options[:album_id] = v
|
185
|
+
end
|
186
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
187
|
+
puts opts
|
188
|
+
Kernel.exit
|
189
|
+
end
|
190
|
+
end.parse!
|
191
|
+
|
192
|
+
unless options.has_key?(:username) or options.has_key?(:password) or options.has_key?(:session_id)
|
193
|
+
puts "%Error: Must specify --username and --password, or --session-id!"
|
194
|
+
raise SystemExit
|
195
|
+
end
|
196
|
+
|
197
|
+
if options.has_key?(:username) ^ options.has_key?(:password)
|
198
|
+
puts "%Error: Must specify both --username and --password"
|
199
|
+
raise SystemExit
|
200
|
+
end
|
201
|
+
|
202
|
+
tuna = Tuna.new
|
203
|
+
options.each do |k,v|
|
204
|
+
tuna.send("#{k.to_s.gsub('-', '_')}=".to_sym, v)
|
205
|
+
end
|
206
|
+
|
207
|
+
tuna.walk.each { |k,v| File.write("#{k.sub('smugmug.', '').gsub('_', '.')}.xml", v) }
|
208
|
+
end
|
209
|
+
|
210
|
+
if __FILE__ == $0
|
211
|
+
main()
|
212
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<method>smugmug.albums.get</method>
|
4
|
+
<Albums>
|
5
|
+
<Album id="1001">
|
6
|
+
<Title>Gallery One</Title>
|
7
|
+
<Category id="47">
|
8
|
+
<Title>Children</Title>
|
9
|
+
</Category>
|
10
|
+
</Album>
|
11
|
+
<Album id="1002">
|
12
|
+
<Title>Gallery Two</Title>
|
13
|
+
<Category id="47">
|
14
|
+
<Title>Children</Title>
|
15
|
+
</Category>
|
16
|
+
</Album>
|
17
|
+
<Album id="1003">
|
18
|
+
<Title>Gallery Three</Title>
|
19
|
+
<Category id="44">
|
20
|
+
<Title>Parties</Title>
|
21
|
+
</Category>
|
22
|
+
</Album>
|
23
|
+
</Albums>
|
24
|
+
</rsp>
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<method>smugmug.albums.getInfo</method>
|
4
|
+
<Albums>
|
5
|
+
<Album id="1001">
|
6
|
+
<Highlight id="0" />
|
7
|
+
<Category id="47" />
|
8
|
+
<SubCategory id="0" />
|
9
|
+
<Community id="0" />
|
10
|
+
<Position>1</Position>
|
11
|
+
<ImageCount>3</ImageCount>
|
12
|
+
<Title>Gallery One</Title>
|
13
|
+
<Description>description</Description>
|
14
|
+
<Keywords>keywords</Keywords>
|
15
|
+
<Public>1</Public>
|
16
|
+
<Password />
|
17
|
+
<PasswordHint />
|
18
|
+
<Printable>1</Printable>
|
19
|
+
<Filenames>0</Filenames>
|
20
|
+
<Comments>1</Comments>
|
21
|
+
<External>0</External>
|
22
|
+
<Originals>1</Originals>
|
23
|
+
<EXIF>1</EXIF>
|
24
|
+
<Share>1</Share>
|
25
|
+
<SortMethod>Position</SortMethod>
|
26
|
+
<SortDirection>0</SortDirection>
|
27
|
+
<LastUpdated>1970-01-01 00:00:00</LastUpdated>
|
28
|
+
<FamilyEdit>0</FamilyEdit>
|
29
|
+
<FriendEdit>0</FriendEdit>
|
30
|
+
<HideOwner>0</HideOwner>
|
31
|
+
<CanRank>1</CanRank>
|
32
|
+
<Clean>0</Clean>
|
33
|
+
<Geography>1</Geography>
|
34
|
+
<SmugSearchable>0</SmugSearchable>
|
35
|
+
<WorldSearchable>0</WorldSearchable>
|
36
|
+
</Album>
|
37
|
+
</Albums>
|
38
|
+
</rsp>
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<method>smugmug.albums.getStats</method>
|
4
|
+
<Album id="1001">
|
5
|
+
<Status>Open</Status>
|
6
|
+
<Bytes>234659</Bytes>
|
7
|
+
<Tiny>20</Tiny>
|
8
|
+
<Thumb>2</Thumb>
|
9
|
+
<Small>0</Small>
|
10
|
+
<Medium>2</Medium>
|
11
|
+
<Large>0</Large>
|
12
|
+
<Original>0</Original>
|
13
|
+
<Images>
|
14
|
+
<Image id="1001">
|
15
|
+
<Bytes>0</Bytes>
|
16
|
+
<Tiny>0</Tiny>
|
17
|
+
<Thumb>0</Thumb>
|
18
|
+
<Small>0</Small>
|
19
|
+
<Medium>0</Medium>
|
20
|
+
<Large>0</Large>
|
21
|
+
<Original>0</Original>
|
22
|
+
</Image>
|
23
|
+
<Image id="1002">
|
24
|
+
<Bytes>0</Bytes>
|
25
|
+
<Tiny>0</Tiny>
|
26
|
+
<Thumb>0</Thumb>
|
27
|
+
<Small>0</Small>
|
28
|
+
<Medium>0</Medium>
|
29
|
+
<Large>0</Large>
|
30
|
+
<Original>0</Original>
|
31
|
+
</Image>
|
32
|
+
<Image id="1003">
|
33
|
+
<Bytes>0</Bytes>
|
34
|
+
<Tiny>0</Tiny>
|
35
|
+
<Thumb>0</Thumb>
|
36
|
+
<Small>0</Small>
|
37
|
+
<Medium>0</Medium>
|
38
|
+
<Large>0</Large>
|
39
|
+
<Original>0</Original>
|
40
|
+
</Image>
|
41
|
+
</Images>
|
42
|
+
</Album>
|
43
|
+
</rsp>
|
@@ -0,0 +1,213 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<method>smugmug.categories.get</method>
|
4
|
+
<Categories>
|
5
|
+
<Category id="0">
|
6
|
+
<Title>Other</Title>
|
7
|
+
</Category>
|
8
|
+
<Category id="41">
|
9
|
+
<Title>Airplanes</Title>
|
10
|
+
</Category>
|
11
|
+
<Category id="1">
|
12
|
+
<Title>Animals</Title>
|
13
|
+
</Category>
|
14
|
+
<Category id="25">
|
15
|
+
<Title>Aquariums</Title>
|
16
|
+
</Category>
|
17
|
+
<Category id="2">
|
18
|
+
<Title>Architecture</Title>
|
19
|
+
</Category>
|
20
|
+
<Category id="3">
|
21
|
+
<Title>Art</Title>
|
22
|
+
</Category>
|
23
|
+
<Category id="43">
|
24
|
+
<Title>Arts and Crafts</Title>
|
25
|
+
</Category>
|
26
|
+
<Category id="39">
|
27
|
+
<Title>Births</Title>
|
28
|
+
</Category>
|
29
|
+
<Category id="4">
|
30
|
+
<Title>Boats</Title>
|
31
|
+
</Category>
|
32
|
+
<Category id="5">
|
33
|
+
<Title>Business</Title>
|
34
|
+
</Category>
|
35
|
+
<Category id="6">
|
36
|
+
<Title>Cars</Title>
|
37
|
+
</Category>
|
38
|
+
<Category id="47">
|
39
|
+
<Title>Children</Title>
|
40
|
+
</Category>
|
41
|
+
<Category id="7">
|
42
|
+
<Title>Competitions</Title>
|
43
|
+
</Category>
|
44
|
+
<Category id="26">
|
45
|
+
<Title>Computers</Title>
|
46
|
+
</Category>
|
47
|
+
<Category id="158734">
|
48
|
+
<Title>Construction</Title>
|
49
|
+
</Category>
|
50
|
+
<Category id="48">
|
51
|
+
<Title>Dance</Title>
|
52
|
+
</Category>
|
53
|
+
<Category id="40">
|
54
|
+
<Title>Electronics</Title>
|
55
|
+
</Category>
|
56
|
+
<Category id="8">
|
57
|
+
<Title>Events</Title>
|
58
|
+
</Category>
|
59
|
+
<Category id="9">
|
60
|
+
<Title>Family</Title>
|
61
|
+
</Category>
|
62
|
+
<Category id="10">
|
63
|
+
<Title>Fashion</Title>
|
64
|
+
</Category>
|
65
|
+
<Category id="51">
|
66
|
+
<Title>Flowers</Title>
|
67
|
+
</Category>
|
68
|
+
<Category id="57">
|
69
|
+
<Title>Food</Title>
|
70
|
+
</Category>
|
71
|
+
<Category id="45">
|
72
|
+
<Title>Friends</Title>
|
73
|
+
</Category>
|
74
|
+
<Category id="56">
|
75
|
+
<Title>Funerals</Title>
|
76
|
+
</Category>
|
77
|
+
<Category id="32">
|
78
|
+
<Title>Genealogy</Title>
|
79
|
+
</Category>
|
80
|
+
<Category id="63">
|
81
|
+
<Title>Grandchildren</Title>
|
82
|
+
</Category>
|
83
|
+
<Category id="11">
|
84
|
+
<Title>Groups</Title>
|
85
|
+
</Category>
|
86
|
+
<Category id="59">
|
87
|
+
<Title>History</Title>
|
88
|
+
</Category>
|
89
|
+
<Category id="12">
|
90
|
+
<Title>Hobbies</Title>
|
91
|
+
</Category>
|
92
|
+
<Category id="31">
|
93
|
+
<Title>Holidays</Title>
|
94
|
+
</Category>
|
95
|
+
<Category id="30">
|
96
|
+
<Title>Humor</Title>
|
97
|
+
</Category>
|
98
|
+
<Category id="53">
|
99
|
+
<Title>Jewelry</Title>
|
100
|
+
</Category>
|
101
|
+
<Category id="62">
|
102
|
+
<Title>Journalism</Title>
|
103
|
+
</Category>
|
104
|
+
<Category id="13">
|
105
|
+
<Title>Landscapes</Title>
|
106
|
+
</Category>
|
107
|
+
<Category id="54">
|
108
|
+
<Title>Machines</Title>
|
109
|
+
</Category>
|
110
|
+
<Category id="67520">
|
111
|
+
<Title>Military</Title>
|
112
|
+
</Category>
|
113
|
+
<Category id="14">
|
114
|
+
<Title>Motorcycles</Title>
|
115
|
+
</Category>
|
116
|
+
<Category id="29">
|
117
|
+
<Title>Movies</Title>
|
118
|
+
</Category>
|
119
|
+
<Category id="34">
|
120
|
+
<Title>Music</Title>
|
121
|
+
</Category>
|
122
|
+
<Category id="15">
|
123
|
+
<Title>Nature</Title>
|
124
|
+
</Category>
|
125
|
+
<Category id="44">
|
126
|
+
<Title>Parties</Title>
|
127
|
+
</Category>
|
128
|
+
<Category id="16">
|
129
|
+
<Title>People</Title>
|
130
|
+
</Category>
|
131
|
+
<Category id="167961">
|
132
|
+
<Title>Performance</Title>
|
133
|
+
</Category>
|
134
|
+
<Category id="37">
|
135
|
+
<Title>Pets</Title>
|
136
|
+
</Category>
|
137
|
+
<Category id="27">
|
138
|
+
<Title>Photography</Title>
|
139
|
+
</Category>
|
140
|
+
<Category id="55">
|
141
|
+
<Title>Politics</Title>
|
142
|
+
</Category>
|
143
|
+
<Category id="28">
|
144
|
+
<Title>Portfolio</Title>
|
145
|
+
</Category>
|
146
|
+
<Category id="52">
|
147
|
+
<Title>Portraits</Title>
|
148
|
+
</Category>
|
149
|
+
<Category id="159296">
|
150
|
+
<Title>Pregnancy</Title>
|
151
|
+
</Category>
|
152
|
+
<Category id="17">
|
153
|
+
<Title>Professional</Title>
|
154
|
+
</Category>
|
155
|
+
<Category id="36">
|
156
|
+
<Title>Religion</Title>
|
157
|
+
</Category>
|
158
|
+
<Category id="46">
|
159
|
+
<Title>School</Title>
|
160
|
+
</Category>
|
161
|
+
<Category id="160095">
|
162
|
+
<Title>Shower</Title>
|
163
|
+
</Category>
|
164
|
+
<Category id="35">
|
165
|
+
<Title>Spirituality</Title>
|
166
|
+
</Category>
|
167
|
+
<Category id="18">
|
168
|
+
<Title>Sports</Title>
|
169
|
+
</Category>
|
170
|
+
<Category id="19">
|
171
|
+
<Title>Still Life</Title>
|
172
|
+
</Category>
|
173
|
+
<Category id="50">
|
174
|
+
<Title>Street Scenes</Title>
|
175
|
+
</Category>
|
176
|
+
<Category id="159294">
|
177
|
+
<Title>Swimming</Title>
|
178
|
+
</Category>
|
179
|
+
<Category id="49">
|
180
|
+
<Title>Theater</Title>
|
181
|
+
</Category>
|
182
|
+
<Category id="42">
|
183
|
+
<Title>Trains</Title>
|
184
|
+
</Category>
|
185
|
+
<Category id="20">
|
186
|
+
<Title>Travel</Title>
|
187
|
+
</Category>
|
188
|
+
<Category id="21">
|
189
|
+
<Title>Trucks</Title>
|
190
|
+
</Category>
|
191
|
+
<Category id="58">
|
192
|
+
<Title>Underwater</Title>
|
193
|
+
</Category>
|
194
|
+
<Category id="33">
|
195
|
+
<Title>Vacation</Title>
|
196
|
+
</Category>
|
197
|
+
<Category id="24">
|
198
|
+
<Title>Video Games</Title>
|
199
|
+
</Category>
|
200
|
+
<Category id="61">
|
201
|
+
<Title>Weather</Title>
|
202
|
+
</Category>
|
203
|
+
<Category id="23">
|
204
|
+
<Title>Weddings</Title>
|
205
|
+
</Category>
|
206
|
+
<Category id="38">
|
207
|
+
<Title>Woodworking</Title>
|
208
|
+
</Category>
|
209
|
+
<Category id="60">
|
210
|
+
<Title>Zoos</Title>
|
211
|
+
</Category>
|
212
|
+
</Categories>
|
213
|
+
</rsp>
|