piwigo-api 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.vscode/launch.json +1 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +1 -1
- data/README.md +29 -4
- data/lib/piwigo/albums.rb +187 -0
- data/lib/piwigo/session.rb +79 -37
- data/lib/piwigo/version.rb +1 -1
- data/piwigo-api.gemspec +2 -2
- metadata +7 -5
- data/main.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5051a29ebbe23995bb4c2d6436d6534b197f1b3794f7f857e0678e612d544501
|
4
|
+
data.tar.gz: f0c5dc53eede301abf914eb04fecb42e3c607281786939ef51db3dc50a6c8e98
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0fa2225cd04231a474299be116ff723a7ecbc70f44ada895041adfa2e47131663d08f60b399dd2ca98eb5e8f24ebf403195f2ff8aaf929d2e17e63bb7345c7cb
|
7
|
+
data.tar.gz: 4dfb369883eadfe868eaa6853a9c3c70661fef1ad9fd01b57011cf6e30454c5c56caf559f855465939ec9a2c9ab11f7c21a01eb99d6c0c063129441cdef340c1
|
data/.gitignore
CHANGED
data/.vscode/launch.json
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
0.2.0 - 2019-11-17
|
10
|
+
- Refactored the Session to make iteasier to use
|
11
|
+
- Support adding/deleting & listing albums
|
9
12
|
|
10
13
|
0.1.1 - 2019-11-16
|
11
14
|
- Initial Version, supports login/logout against a piwigo server
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Piwigo-API
|
2
2
|
|
3
|
-
|
3
|
+
Piwigo is open source web application to manage your collection of photos, and other medias. Piwigo provides an API for interacting with it.
|
4
4
|
|
5
|
-
|
5
|
+
This is a ruby-based client for interacting with a Piwigo instance using the Piwigo API.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -22,7 +22,32 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
|
25
|
+
Just include 'piwigo/session' and the related classes, then querying Piwigo is fairly quick and straightforward.
|
26
|
+
|
27
|
+
# Get the second album and all of it's children
|
28
|
+
|
29
|
+
|
30
|
+
```
|
31
|
+
require 'piwigo/session'
|
32
|
+
require 'piwigo/albums'
|
33
|
+
|
34
|
+
session = Piwigo::Session.login('mypiwigo.fqdn', 'Adrian', 'mypassword', https: false)
|
35
|
+
unless session.nil?
|
36
|
+
albums = Piwigo::Albums.list(session, album_id: 2, recursive: true)
|
37
|
+
albums.each { |album| p "#{album.id}, #{album.name} - # of photos: #{album.total_nb_images}" }
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
# Add a new album
|
42
|
+
```
|
43
|
+
session = Piwigo::Session.login('10.100.230.78', 'Adrian', 'secret', https: false)
|
44
|
+
unless session.nil?
|
45
|
+
album = Piwigo::Albums::Album.new
|
46
|
+
album.name = "My First Album"
|
47
|
+
album = Piwigo::Albums.add(session, album)
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
26
51
|
|
27
52
|
## Development
|
28
53
|
|
@@ -32,7 +57,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
57
|
|
33
58
|
## Contributing
|
34
59
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/kkdad/piwigo.
|
60
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/kkdad/piwigo-ruby.
|
36
61
|
|
37
62
|
## License
|
38
63
|
|
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require 'json'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
# Piwigo organizes images by albums. The album tree has unlimted depth and each photo can belong to multiple albums. The Piwigo API
|
7
|
+
# refers to a Album as a Category.
|
8
|
+
module Piwigo
|
9
|
+
class Albums
|
10
|
+
class Album
|
11
|
+
# @return [Number] Album ID
|
12
|
+
attr_accessor :id
|
13
|
+
|
14
|
+
# @return [String] Name of the Album
|
15
|
+
attr_accessor :name
|
16
|
+
|
17
|
+
# @return [String] Album Description
|
18
|
+
attr_accessor :comment
|
19
|
+
|
20
|
+
# ???
|
21
|
+
attr_accessor :permalink
|
22
|
+
|
23
|
+
# @return [String] public or private
|
24
|
+
attr_accessor :status
|
25
|
+
|
26
|
+
# ???
|
27
|
+
attr_accessor :uppercats
|
28
|
+
|
29
|
+
# The rank of an album
|
30
|
+
attr_accessor :global_rank
|
31
|
+
|
32
|
+
# @return [Number] ID of the parent album, nil of this is a top-level album (Aka ParentID)
|
33
|
+
attr_accessor :id_uppercat
|
34
|
+
|
35
|
+
# @return [Number] Number of the Newest photos, excluding child albums
|
36
|
+
attr_accessor :nb_images
|
37
|
+
|
38
|
+
# @return [Number] Number of the Newest photos, including child albums
|
39
|
+
attr_accessor :total_nb_images
|
40
|
+
|
41
|
+
# ID of the representative photo for an album. This photo doesn't have to belong to the album.
|
42
|
+
attr_accessor :representative_picture_id
|
43
|
+
|
44
|
+
# @return [DateTime] Date of the Newest photos, excluding child albums
|
45
|
+
attr_accessor :date_last
|
46
|
+
|
47
|
+
# @return [DateTime] Date of the Newest photos, including child albums
|
48
|
+
attr_accessor :max_date_last
|
49
|
+
|
50
|
+
# @return [Number] Number of child albums inside this album
|
51
|
+
attr_accessor :nb_categories
|
52
|
+
|
53
|
+
# @return [Atring] Album URL
|
54
|
+
attr_accessor :url
|
55
|
+
|
56
|
+
# @return [String] Thumbnail URL
|
57
|
+
attr_accessor :tn_url
|
58
|
+
|
59
|
+
def initialize(hash: nil)
|
60
|
+
hash.each { |key, value| send("#{key}=", value) } unless hash.nil?
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Returns a list of albums
|
66
|
+
#
|
67
|
+
# @param [Session] session - Session
|
68
|
+
# @param [Number] album_id - Album to fetch, Optional
|
69
|
+
# @param [Boolean] recursive - Include subalbums, Optional
|
70
|
+
# @param [Boolean] public - Only include public albums, Optional
|
71
|
+
# @param [Boolean] fullname - ???, Optional
|
72
|
+
# @param [String] thumbnail_size - Size of thumbname to return, One of: square, thumb, 2small, xsmall, small, medium, large, xlarge, xxlarge. Optional
|
73
|
+
# @param [Logger] logger logger to output debug messages to (Optional)
|
74
|
+
#
|
75
|
+
# @return [Array<Album>] All albums that match the criteria, or nil there were no matches
|
76
|
+
#
|
77
|
+
def self.list(session, album_id: nil, recursive: false, public: false, fullname: false, thumbnail_size: 'thumb', logger: nil)
|
78
|
+
raise "Invalid session" if session.uri.nil?
|
79
|
+
logger = logger || Logger.new(STDOUT)
|
80
|
+
|
81
|
+
|
82
|
+
begin
|
83
|
+
http = Net::HTTP.new(session.uri.host, session.uri.port)
|
84
|
+
request = Net::HTTP::Post.new(session.uri.request_uri)
|
85
|
+
request.body = "method=pwg.categories.getList&cat_id=#{album_id}&recursive=#{recursive}&public=#{public}&fullname=#{fullname}&thumbnail_size=#{thumbnail_size}"
|
86
|
+
request['Cookie'] = [session.id]
|
87
|
+
|
88
|
+
# Send the request
|
89
|
+
response = http.request(request)
|
90
|
+
if response.code == '200'
|
91
|
+
data = JSON.parse(response.body)
|
92
|
+
albums = data['result']['categories'].map{ |hash| Album.new(hash: hash) }
|
93
|
+
logger.info "Album List succeeded: #{albums.size} albums retrieved."
|
94
|
+
albums
|
95
|
+
else
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
99
|
+
logger.error "Album List failed: #{e.messages}"
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
# Adds an album.
|
106
|
+
#
|
107
|
+
# @param [Session] session to interact with Piwigo
|
108
|
+
# @param [Album] album album to create
|
109
|
+
# @param [Logger] logger logger to output debug messages to (Optional)
|
110
|
+
#
|
111
|
+
# @return [Album] newly created album
|
112
|
+
def self.add(session, album, logger: nil)
|
113
|
+
raise "Invalid session" if session.uri.nil?
|
114
|
+
raise "Invalid album" if album.nil?
|
115
|
+
|
116
|
+
logger = logger || Logger.new(STDOUT)
|
117
|
+
|
118
|
+
begin
|
119
|
+
http = Net::HTTP.new(session.uri.host, session.uri.port)
|
120
|
+
request = Net::HTTP::Post.new(session.uri.request_uri)
|
121
|
+
request.body = "method=pwg.categories.add&name=#{album.name}"
|
122
|
+
request.body.concat "&parent=#{album.id_uppercat}" unless album.id_uppercat.nil?
|
123
|
+
request.body.concat "&comment=#{album.comment}" unless album.comment.nil?
|
124
|
+
request.body.concat "&status=#{album.status}" unless album.status.nil?
|
125
|
+
request['Cookie'] = [session.id]
|
126
|
+
|
127
|
+
# Send the request
|
128
|
+
response = http.request(request)
|
129
|
+
if response.code == '200'
|
130
|
+
data = JSON.parse(response.body)
|
131
|
+
album.id = albums = data['result']['id']
|
132
|
+
logger.info "Album Add succeeded: #{album.id} created."
|
133
|
+
album
|
134
|
+
else
|
135
|
+
nil
|
136
|
+
|
137
|
+
end
|
138
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
139
|
+
logger.error "Album Add failed: #{e.messages}"
|
140
|
+
nil
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
# Deletes album(s).
|
146
|
+
#
|
147
|
+
# @param [Session] piwigo session
|
148
|
+
# @param [Number] id of the album to remove
|
149
|
+
# @param [String] photo_deletion_mode can be "no_delete" (may create orphan photos), "delete_orphans" (default mode, only deletes photos linked to no other album)
|
150
|
+
# or "force_delete" (delete all photos, even those linked to other albums)
|
151
|
+
# @param [Logger] logger logger to output debug messages to (Optional)
|
152
|
+
#
|
153
|
+
# @return [Boolean] true if album was deleted
|
154
|
+
def self.delete(session, id, photo_deletion_mode: nil, logger: nil)
|
155
|
+
raise "Invalid session" if session.uri.nil?
|
156
|
+
|
157
|
+
logger = logger || Logger.new(STDOUT)
|
158
|
+
|
159
|
+
begin
|
160
|
+
http = Net::HTTP.new(session.uri.host, session.uri.port)
|
161
|
+
request = Net::HTTP::Post.new(session.uri.request_uri)
|
162
|
+
request.body = "method=pwg.categories.delete&category_id=#{id}"
|
163
|
+
request.body.concat "&photo_deletion_mode=#{photo_deletion_mode}" unless photo_deletion_mode.nil?
|
164
|
+
request.body.concat "&pwg_token=#{session.pwg_token}"
|
165
|
+
request['Cookie'] = [session.id]
|
166
|
+
|
167
|
+
# Send the request
|
168
|
+
response = http.request(request)
|
169
|
+
if response.code == '200'
|
170
|
+
data = JSON.parse(response.body)
|
171
|
+
logger.info "Album Delete succeeded."
|
172
|
+
true
|
173
|
+
else
|
174
|
+
p response.code
|
175
|
+
p response.body
|
176
|
+
false
|
177
|
+
|
178
|
+
end
|
179
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
180
|
+
logger.error "Album delete: #{e.messages}"
|
181
|
+
false
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
end
|
187
|
+
end
|
data/lib/piwigo/session.rb
CHANGED
@@ -7,70 +7,112 @@ module Piwigo
|
|
7
7
|
# Class to hold the Piwigo session the rest of the API needs to pass in order to access the API
|
8
8
|
class Session
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
# @return [String] Piwigo session cookie
|
11
|
+
attr_accessor :id
|
12
|
+
|
13
|
+
# @return [URI::HTTP] Piwigo host associated with this session
|
14
|
+
attr_accessor :uri
|
15
|
+
|
16
|
+
# @return [String] token required for admin methods
|
17
|
+
attr_accessor :pwg_token
|
18
|
+
|
19
|
+
# @return [String] token required for admin methods
|
20
|
+
attr_accessor :username
|
21
|
+
|
22
|
+
|
23
|
+
def initialize(id, uri)
|
24
|
+
self.id = id
|
25
|
+
self.uri = uri
|
26
|
+
|
27
|
+
status
|
12
28
|
end
|
29
|
+
|
30
|
+
# Gets information about the current session. Also provides a token useable with admin methods.
|
31
|
+
# {"stat":"ok","result":{"username":"Adrian","status":"webmaster","theme":"modus","language":"en_GB","pwg_token":"9edde6a1ae535934cca6a2423f9bcbe7","charset":"utf-8","current_datetime":"2019-11-17 21:57:58","version":"2.10.1","available_sizes":["square","thumb","2small","xsmall","small","medium","large","xlarge","xxlarge"],"upload_file_types":"jpg,jpeg,png,gif","upload_form_chunk_size":500}}
|
32
|
+
# @return [<Type>] <description>
|
33
|
+
def status
|
34
|
+
logger = logger || Logger.new(STDOUT)
|
35
|
+
|
36
|
+
begin
|
37
|
+
# Create the HTTP objects
|
38
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
39
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
40
|
+
request.body = "method=pwg.session.getStatus"
|
41
|
+
request['Cookie'] = self.id
|
42
|
+
|
43
|
+
# Send the request
|
44
|
+
response = http.request(request)
|
45
|
+
|
46
|
+
if response.code == '200'
|
47
|
+
logger.info "Status succeeded"
|
48
|
+
data = JSON.parse(response.body)
|
49
|
+
self.pwg_token = data['result']['pwg_token']
|
50
|
+
self.username = data['result']['username']
|
51
|
+
end
|
52
|
+
|
53
|
+
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
54
|
+
logger.error "Unexpected failed: #{e.messages}"
|
55
|
+
end
|
56
|
+
nil
|
13
57
|
|
14
|
-
# Instantion a new Session object
|
15
|
-
# @param [Logger] logger logger to output debug messages to (Optional)
|
16
|
-
def initialize(logger: nil)
|
17
|
-
@session_id=nil
|
18
|
-
@uri=nil
|
19
|
-
@logger = logger || Logger.new(STDOUT)
|
20
58
|
end
|
59
|
+
|
60
|
+
# Logout of the current session
|
61
|
+
# @param [Logger] logger logger to output debug messages to (Optional)
|
62
|
+
def logout(logger: nil)
|
63
|
+
raise "This session has already been logged out" if uri.nil?
|
64
|
+
logger = logger || Logger.new(STDOUT)
|
21
65
|
|
66
|
+
# Create the HTTP objects
|
67
|
+
http = Net::HTTP.new(self.uri.host, self.uri.port)
|
68
|
+
request = Net::HTTP::Get.new(self.uri.request_uri + "&method=pwg.session.logout")
|
69
|
+
request['Cookie'] = self.id
|
70
|
+
|
71
|
+
# Send the request
|
72
|
+
response = http.request(request)
|
73
|
+
logger.info "Logout succeeded: #{response.body}" if response.code == '200'
|
74
|
+
self.id = nil
|
75
|
+
self.uri = nil
|
76
|
+
end
|
77
|
+
|
78
|
+
|
22
79
|
# Log into the piwigo API and grab the session id for subsequent calls.
|
23
80
|
# @param [string] piwigo - host to connect to. Can be fqdn or ip.
|
24
81
|
# @param [string] username - user to connect as
|
25
82
|
# @param [string] password - password for user
|
26
83
|
# @param [boolean] https - Use HTTPS?
|
27
|
-
|
84
|
+
# @param [Logger] logger logger to output debug messages to (Optional)
|
85
|
+
def self.login(host, username, password, https: true, logger: nil)
|
28
86
|
|
29
87
|
raise "host should not be nil" if host.nil?
|
30
88
|
raise "username should not be nil" if username.nil?
|
89
|
+
logger = logger || Logger.new(STDOUT)
|
31
90
|
|
32
91
|
begin
|
33
92
|
|
34
|
-
|
35
|
-
|
93
|
+
uri = https ? URI::HTTPS.build(host: host, path: "/ws.php", query: "format=json") :
|
94
|
+
URI::HTTP.build(host: host, path: "/ws.php", query: "format=json")
|
36
95
|
|
37
96
|
# Create the HTTP objects
|
38
|
-
http = Net::HTTP.new(
|
39
|
-
request = Net::HTTP::Post.new(
|
97
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
98
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
40
99
|
request.body = "method=pwg.session.login&username=#{username}&password=#{password}"
|
41
100
|
|
42
101
|
# Send the request
|
43
102
|
response = http.request(request)
|
44
103
|
|
45
104
|
if response.code == '200'
|
46
|
-
|
47
|
-
|
48
|
-
return
|
105
|
+
logger.info "Login succeeded: #{response.body}"
|
106
|
+
pwg_id = response.response['set-cookie'].split(';').select { |i| i.strip.start_with? "pwg_id" }.first
|
107
|
+
return Session.new(pwg_id, uri)
|
49
108
|
else
|
50
|
-
|
51
|
-
@session_id = nil
|
52
|
-
@uri = nil
|
109
|
+
logger.error "Login failed: #{response.body}"
|
53
110
|
end
|
54
111
|
|
55
112
|
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError => e
|
56
|
-
|
113
|
+
logger.error "Login failed: #{e.messages}"
|
57
114
|
end
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
def logout
|
62
|
-
raise "login must be successfully called before logout" if @uri.nil?
|
63
|
-
|
64
|
-
# Create the HTTP objects
|
65
|
-
http = Net::HTTP.new(@uri.host, @uri.port)
|
66
|
-
request = Net::HTTP::Get.new(@uri.request_uri + "&method=pwg.session.logout")
|
67
|
-
request['Cookie'] = @session_id
|
68
|
-
|
69
|
-
# Send the request
|
70
|
-
response = http.request(request)
|
71
|
-
@logger.info "Logout succeeded: #{response.body}" if response.code == '200'
|
72
|
-
@session_id = nil
|
73
|
-
@uri = nil
|
74
|
-
end
|
115
|
+
nil
|
116
|
+
end
|
75
117
|
end
|
76
118
|
end
|
data/lib/piwigo/version.rb
CHANGED
data/piwigo-api.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.authors = ["Adrian Gilbert"]
|
9
9
|
spec.email = ["adrian@gilbert.ca"]
|
10
10
|
|
11
|
-
spec.summary = %q{
|
12
|
-
spec.description = %q{
|
11
|
+
spec.summary = %q{Gem to interact with the Piwigo API}
|
12
|
+
spec.description = %q{Piwigo is open source web application to manage your collection of photos, and other medias. Piwigo provides an API for interacting with it. This is a ruby-based client for interacting with a Piwigo instance using the Piwigo API.}
|
13
13
|
spec.homepage = "https://github.com/kkdad/piwigo-api"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: piwigo-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adrian Gilbert
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-11-
|
11
|
+
date: 2019-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,7 +80,9 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '4.2'
|
83
|
-
description:
|
83
|
+
description: Piwigo is open source web application to manage your collection of photos,
|
84
|
+
and other medias. Piwigo provides an API for interacting with it. This is a ruby-based
|
85
|
+
client for interacting with a Piwigo instance using the Piwigo API.
|
84
86
|
email:
|
85
87
|
- adrian@gilbert.ca
|
86
88
|
executables: []
|
@@ -100,9 +102,9 @@ files:
|
|
100
102
|
- bin/console
|
101
103
|
- bin/setup
|
102
104
|
- lib/piwigo.rb
|
105
|
+
- lib/piwigo/albums.rb
|
103
106
|
- lib/piwigo/session.rb
|
104
107
|
- lib/piwigo/version.rb
|
105
|
-
- main.rb
|
106
108
|
- piwigo-api.gemspec
|
107
109
|
homepage: https://github.com/kkdad/piwigo-api
|
108
110
|
licenses:
|
@@ -129,5 +131,5 @@ requirements: []
|
|
129
131
|
rubygems_version: 3.0.3
|
130
132
|
signing_key:
|
131
133
|
specification_version: 4
|
132
|
-
summary:
|
134
|
+
summary: Gem to interact with the Piwigo API
|
133
135
|
test_files: []
|